Add more compilers to CI and increase FMT_PEDANTIC warning levels (#736)

* Add a _lot_ more warnings to FMT_PEDANTIC
Fix these warnings

* Add more compilers to CI
Fix (some) of the compiler errors with them

* Enable -Werror on CI
Increase warning level on MSVC when compiling with FMT_PEDANTIC

* Add VS 2013 and 2015 to Appveyor

* Fix Appveyor tests
Formatting

* Implement requested changes
Fix some of the MSVC warnings
Implement C++11 integer_sequence

* Reintroduce appveyor-build.py

* Remove ranges-test from tests

* Remove (some) explicit warning suppressions
Fix C++ standard setting in CI

* Remove (some) explicit warning suppressions
Fix C++ standard setting in CI

* Fix test builds with C++11

* Enable pedantic warnings on tests

* Fix warnings from edits to master

* Cleanups

* Add C++11 support to ranges.h
Re-enable ranges-test
Fix a Visual Studio error about function not returning a value in printf.h
Fix a bug in .travis.yml
This commit is contained in:
Elias Kosunen
2018-06-06 16:57:59 +03:00
committed by Victor Zverovich
parent dd1a5ef7f9
commit 691a7a91a1
36 changed files with 589 additions and 376 deletions
+29 -12
View File
@@ -30,6 +30,12 @@
# define FMT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_cpp_attribute
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#if defined(__GNUC__) && !defined(__clang__)
# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
@@ -95,6 +101,12 @@
# define FMT_USE_NULLPTR 0
#endif
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
# define FMT_NORETURN [[noreturn]]
#else
# define FMT_NORETURN /*noreturn*/
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
@@ -218,7 +230,7 @@ class basic_string_view {
#else
struct type {
const char *data() const { return FMT_NULL; }
size_t size() const { return 0; };
size_t size() const { return 0; }
};
#endif
@@ -550,11 +562,17 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value);
return static_cast<ValueType>(val); \
}
#define FMT_MAKE_VALUE_SAME(TAG, Type) \
template <typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) { \
return val; \
}
FMT_MAKE_VALUE(bool_type, bool, int)
FMT_MAKE_VALUE(int_type, short, int)
FMT_MAKE_VALUE(uint_type, unsigned short, unsigned)
FMT_MAKE_VALUE(int_type, int, int)
FMT_MAKE_VALUE(uint_type, unsigned, unsigned)
FMT_MAKE_VALUE_SAME(int_type, int)
FMT_MAKE_VALUE_SAME(uint_type, unsigned)
// To minimize the number of types we need to deal with, long is translated
// either to int or to long long depending on its size.
@@ -568,8 +586,8 @@ FMT_MAKE_VALUE(
(sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type),
unsigned long, ulong_type)
FMT_MAKE_VALUE(long_long_type, long long, long long)
FMT_MAKE_VALUE(ulong_long_type, unsigned long long, unsigned long long)
FMT_MAKE_VALUE_SAME(long_long_type, long long)
FMT_MAKE_VALUE_SAME(ulong_long_type, unsigned long long)
FMT_MAKE_VALUE(int_type, signed char, int)
FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
FMT_MAKE_VALUE(char_type, char, int)
@@ -583,8 +601,8 @@ inline typed_value<C, char_type> make_value(wchar_t val) {
#endif
FMT_MAKE_VALUE(double_type, float, double)
FMT_MAKE_VALUE(double_type, double, double)
FMT_MAKE_VALUE(long_double_type, long double, long double)
FMT_MAKE_VALUE_SAME(double_type, double)
FMT_MAKE_VALUE_SAME(long_double_type, long double)
// Formatting of wide strings into a narrow buffer and multibyte strings
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
@@ -594,18 +612,17 @@ FMT_MAKE_VALUE(cstring_type, const typename C::char_type*,
const typename C::char_type*)
FMT_MAKE_VALUE(cstring_type, signed char*, const signed char*)
FMT_MAKE_VALUE(cstring_type, const signed char*, const signed char*)
FMT_MAKE_VALUE_SAME(cstring_type, const signed char*)
FMT_MAKE_VALUE(cstring_type, unsigned char*, const unsigned char*)
FMT_MAKE_VALUE(cstring_type, const unsigned char*, const unsigned char*)
FMT_MAKE_VALUE(string_type, basic_string_view<typename C::char_type>,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE_SAME(cstring_type, const unsigned char*)
FMT_MAKE_VALUE_SAME(string_type, basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(string_type,
typename basic_string_view<typename C::char_type>::type,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(string_type, const std::basic_string<typename C::char_type>&,
basic_string_view<typename C::char_type>)
FMT_MAKE_VALUE(pointer_type, void*, const void*)
FMT_MAKE_VALUE(pointer_type, const void*, const void*)
FMT_MAKE_VALUE_SAME(pointer_type, const void*)
#if FMT_USE_NULLPTR
FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*)
-9
View File
@@ -45,12 +45,6 @@
# define FMT_CATCH(x) if (false)
#endif
#ifdef __GNUC__
// Disable the warning about declaration shadowing because it affects too
// many valid cases.
# pragma GCC diagnostic ignored "-Wshadow"
#endif
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
@@ -71,9 +65,6 @@ inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
FMT_BEGIN_NAMESPACE
FMT_FUNC format_error::~format_error() throw() {}
FMT_FUNC system_error::~system_error() FMT_DTOR_NOEXCEPT {}
namespace {
#ifndef _MSC_VER
+63 -61
View File
@@ -37,6 +37,33 @@
#include <stdexcept>
#include <stdint.h>
#ifdef __clang__
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
#else
# define FMT_CLANG_VERSION 0
#endif
#ifdef __INTEL_COMPILER
# define FMT_ICC_VERSION __INTEL_COMPILER
#elif defined(__ICL)
# define FMT_ICC_VERSION __ICL
#else
# define FMT_ICC_VERSION 0
#endif
#if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 406) || \
FMT_CLANG_VERSION
# pragma GCC diagnostic push
// Disable the warning about declaration shadowing because it affects too
// many valid cases.
# pragma GCC diagnostic ignored "-Wshadow"
// Disable the warning about implicit conversions that may change the sign of
// an integer; silencing it otherwise would require many explicit casts.
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include "core.h"
#ifdef _SECURE_SCL
@@ -55,47 +82,10 @@
# define FMT_HAS_BUILTIN(x) 0
#endif
#ifdef __GNUC__
# if FMT_GCC_VERSION >= 406
# pragma GCC diagnostic push
// Disable the warning about declaration shadowing because it affects too
// many valid cases.
# pragma GCC diagnostic ignored "-Wshadow"
// Disable the warning about implicit conversions that may change the sign of
// an integer; silencing it otherwise would require many explicit casts.
# pragma GCC diagnostic ignored "-Wsign-conversion"
# endif
#endif
#ifdef __clang__
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
#endif
#if defined(__INTEL_COMPILER)
# define FMT_ICC_VERSION __INTEL_COMPILER
#elif defined(__ICL)
# define FMT_ICC_VERSION __ICL
#endif
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
# pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
# pragma clang diagnostic ignored "-Wpadded"
#endif
#ifdef __GNUC_LIBSTD__
# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
#endif
#ifdef __has_cpp_attribute
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#ifndef FMT_THROW
# if FMT_EXCEPTIONS
# if FMT_MSC_VER
@@ -116,7 +106,7 @@ FMT_END_NAMESPACE
# define FMT_THROW(x) throw x
# endif
# else
# define FMT_THROW(x) assert(false)
# define FMT_THROW(x) do { static_cast<void>(sizeof(x)); assert(false); } while(false);
# endif
#endif
@@ -124,7 +114,7 @@ FMT_END_NAMESPACE
// For Intel's compiler both it and the system gcc/msc must support UDLs.
# if (FMT_HAS_FEATURE(cxx_user_literals) || \
FMT_GCC_VERSION >= 407 || FMT_MSC_VER >= 1900) && \
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
(!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1500)
# define FMT_USE_USER_DEFINED_LITERALS 1
# else
# define FMT_USE_USER_DEFINED_LITERALS 0
@@ -142,7 +132,8 @@ FMT_END_NAMESPACE
#ifndef FMT_USE_EXTERN_TEMPLATES
# ifndef FMT_HEADER_ONLY
# define FMT_USE_EXTERN_TEMPLATES \
(FMT_CLANG_VERSION >= 209 || (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
((FMT_CLANG_VERSION >= 209 && __cplusplus >= 201103L) || \
(FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
# else
# define FMT_USE_EXTERN_TEMPLATES 0
# endif
@@ -151,6 +142,14 @@ FMT_END_NAMESPACE
#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_trailing_return) || \
FMT_MSC_VER >= 1600
# define FMT_USE_TRAILING_RETURN 1
#else
# define FMT_USE_TRAILING_RETURN 0
#endif
#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_rvalue_references) || FMT_MSC_VER >= 1600
# define FMT_USE_RVALUE_REFERENCES 1
#else
# define FMT_USE_RVALUE_REFERENCES 0
#endif
#ifndef FMT_USE_GRISU
@@ -284,18 +283,18 @@ class fp {
typedef uint64_t significand_type;
// All sizes are in bits.
static constexpr int char_size = std::numeric_limits<unsigned char>::digits;
static FMT_CONSTEXPR_DECL const int char_size = std::numeric_limits<unsigned char>::digits;
// Subtract 1 to account for an implicit most significant bit in the
// normalized form.
static constexpr int double_significand_size =
static FMT_CONSTEXPR_DECL const int double_significand_size =
std::numeric_limits<double>::digits - 1;
static constexpr uint64_t implicit_bit = 1ull << double_significand_size;
static FMT_CONSTEXPR_DECL const uint64_t implicit_bit = 1ull << double_significand_size;
public:
significand_type f;
int e;
static constexpr int significand_size = sizeof(significand_type) * char_size;
static FMT_CONSTEXPR_DECL const int significand_size = sizeof(significand_type) * char_size;
fp(uint64_t f, int e): f(f), e(e) {}
@@ -318,7 +317,7 @@ class fp {
f += implicit_bit;
else
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
e = biased_e - exponent_bias - double_significand_size;
e = static_cast<int>(biased_e - exponent_bias - double_significand_size);
}
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
@@ -455,8 +454,6 @@ class format_error : public std::runtime_error {
explicit format_error(const std::string &message)
: std::runtime_error(message) {}
FMT_API ~format_error() throw();
};
namespace internal {
@@ -1673,6 +1670,13 @@ FMT_CONSTEXPR unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh) {
return value;
}
#if FMT_MSC_VER
// Warns that the compiler cannot generate an assignment operator
// The class has a reference member variable, so this is obviously the case
# pragma warning(push)
# pragma warning(disable: 4512)
#endif
template <typename Char, typename Context>
class custom_formatter: public function<bool> {
private:
@@ -1690,6 +1694,10 @@ class custom_formatter: public function<bool> {
bool operator()(T) const { return false; }
};
#if FMT_MSC_VER
# pragma warning(pop)
#endif
template <typename T>
struct is_integer {
enum {
@@ -2380,8 +2388,6 @@ class system_error : public std::runtime_error {
init(error_code, message, make_format_args(args...));
}
FMT_API ~system_error() FMT_DTOR_NOEXCEPT;
int error_code() const { return error_code_; }
};
@@ -2650,7 +2656,7 @@ class basic_writer {
};
struct double_writer {
unsigned n;
size_t n;
char sign;
basic_memory_buffer<char_type> &buffer;
@@ -2904,12 +2910,12 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
internal::fp product = fp_value * dec_pow;
// Generate output.
internal::fp one(1ull << -product.e, product.e);
uint32_t hi = product.f >> -one.e;
uint64_t hi = product.f >> -one.e;
uint64_t f = product.f & (one.f - 1);
typedef back_insert_range<internal::basic_buffer<char_type>> range;
basic_writer<range> w{range(buffer)};
w.write(hi);
unsigned digits = buffer.size();
size_t digits = buffer.size();
w.write('.');
const unsigned max_digits = 18;
while (digits++ < max_digits) {
@@ -2924,7 +2930,7 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
normalized_spec.type_ = handler.type;
write_double_sprintf(value, normalized_spec, buffer);
}
unsigned n = buffer.size();
size_t n = buffer.size();
align_spec as = spec;
if (spec.align() == ALIGN_NUMERIC) {
if (sign) {
@@ -3215,8 +3221,8 @@ struct formatter<
internal::handle_dynamic_spec<internal::precision_checker>(
specs_.precision_, specs_.precision_ref, ctx);
typedef output_range<typename FormatContext::iterator,
typename FormatContext::char_type> range;
visit(arg_formatter<range>(ctx, specs_),
typename FormatContext::char_type> range_type;
visit(arg_formatter<range_type>(ctx, specs_),
internal::make_arg<FormatContext>(val));
return ctx.out();
}
@@ -3702,7 +3708,7 @@ FMT_END_NAMESPACE
#define FMT_STRING(s) [] { \
struct S : fmt::format_string { \
static FMT_CONSTEXPR auto data() { return s; } \
static FMT_CONSTEXPR decltype(s) data() { return s; } \
static FMT_CONSTEXPR size_t size() { return sizeof(s); } \
}; \
return S{}; \
@@ -3731,12 +3737,8 @@ FMT_END_NAMESPACE
#endif
// Restore warnings.
#if FMT_GCC_VERSION >= 406
#if FMT_GCC_VERSION >= 406 || FMT_CLANG_VERSION
# pragma GCC diagnostic pop
#endif
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
# pragma clang diagnostic pop
#endif
#endif // FMT_FORMAT_H_
+7 -2
View File
@@ -52,7 +52,7 @@ class printf_precision_handler: public function<int> {
typename std::enable_if<!std::is_integral<T>::value, int>::type
operator()(T) {
FMT_THROW(format_error("precision is not integer"));
return 0;
return 0; // Silence visual studio
}
};
@@ -194,7 +194,7 @@ class printf_width_handler: public function<unsigned> {
typename std::enable_if<!std::is_integral<T>::value, unsigned>::type
operator()(T) {
FMT_THROW(format_error("width is not integer"));
return 0;
return 0; // Silence Visual Studio
}
};
} // namespace internal
@@ -635,8 +635,13 @@ inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args)
template <typename... Args>
inline int fprintf(std::FILE *f, wstring_view format_str,
const Args & ... args) {
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 440
return vfprintf<wchar_t>(f, format_str,
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
#else
return vfprintf(f, format_str,
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
#endif
}
inline int vprintf(string_view format, printf_args args) {
+62 -29
View File
@@ -126,18 +126,39 @@ struct is_tuple_like {
static FMT_CONSTEXPR_DECL const bool value =
is_tuple_like_<T>::value && !is_range_<T>::value;
};
} // namespace internal
#if FMT_HAS_FEATURE(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
# define FMT_USE_INTEGER_SEQUENCE 1
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
template <typename T, T... N>
using integer_sequence = std::integer_sequence<T, N...>;
template <std::size_t... N>
using index_sequence = std::index_sequence<N...>;
template <std::size_t N>
using make_index_sequence = std::make_index_sequence<N>;
#else
# define FMT_USE_INTEGER_SEQUENCE 0
template <typename T, T... N>
struct integer_sequence {
typedef T value_type;
static FMT_CONSTEXPR std::size_t size() {
return sizeof...(N);
}
};
template <std::size_t... N>
using index_sequence = integer_sequence<std::size_t, N...>;
template <typename T, std::size_t N, T... Ns>
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
template <typename T, T... Ns>
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
template <std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
#endif
#if FMT_USE_INTEGER_SEQUENCE
namespace internal {
template <size_t... Is, class Tuple, class F>
void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
template <class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
using std::get;
// using free function get<I>(T) now.
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
@@ -145,7 +166,7 @@ void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
}
template <class T>
FMT_CONSTEXPR std::make_index_sequence<std::tuple_size<T>::value>
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value>
get_indexes(T const &) { return {}; }
template <class Tuple, class F>
@@ -157,21 +178,13 @@ void for_each(Tuple &&tup, F &&f) {
template <typename TupleT, typename Char>
struct formatter<TupleT, Char,
typename std::enable_if<fmt::internal::is_tuple_like<TupleT>::value>::type> {
fmt::formatting_tuple<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
}
template <typename FormatContext = format_context>
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) {
auto out = ctx.out();
std::size_t i = 0;
internal::copy(formatting.prefix, out);
internal::for_each(values, [&](const auto &v) {
typename std::enable_if<internal::is_tuple_like<TupleT>::value>::type> {
private:
// C++11 generic lambda for format()
template <typename FormatContext>
struct format_each {
template <typename T>
void operator()(const T& v) {
if (i > 0) {
if (formatting.add_prepostfix_space) {
*out++ = ' ';
@@ -184,7 +197,28 @@ struct formatter<TupleT, Char,
format_to(out, "{}", v);
}
++i;
});
}
formatting_tuple<Char>& formatting;
std::size_t& i;
typename std::add_lvalue_reference<decltype(std::declval<FormatContext>().out())>::type out;
};
public:
formatting_tuple<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
}
template <typename FormatContext = format_context>
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) {
auto out = ctx.out();
std::size_t i = 0;
internal::copy(formatting.prefix, out);
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
if (formatting.add_prepostfix_space) {
*out++ = ' ';
}
@@ -193,13 +227,12 @@ struct formatter<TupleT, Char,
return ctx.out();
}
};
#endif // FMT_USE_INTEGER_SEQUENCE
template <typename RangeT, typename Char>
struct formatter< RangeT, Char,
typename std::enable_if<fmt::internal::is_range<RangeT>::value>::type> {
struct formatter<RangeT, Char,
typename std::enable_if<internal::is_range<RangeT>::value>::type> {
fmt::formatting_range<Char> formatting;
formatting_range<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
-2
View File
@@ -54,7 +54,6 @@ inline std::tm localtime(std::time_t time) {
return lt.tm_;
// Too big time values may be unsupported.
FMT_THROW(format_error("time_t value out of range"));
return std::tm();
}
// Thread-safe replacement for std::gmtime
@@ -90,7 +89,6 @@ inline std::tm gmtime(std::time_t time) {
return gt.tm_;
// Too big time values may be unsupported.
FMT_THROW(format_error("time_t value out of range"));
return std::tm();
}
namespace internal {