diff --git a/CMakeLists.txt b/CMakeLists.txt index 045004a2..3f65a6a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,33 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} include(cxx14) -if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wshadow -pedantic) +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic + -Wold-style-cast -Wfloat-equal -Wlogical-op -Wundef + -Wredundant-decls -Wshadow -Wwrite-strings -Wpointer-arith + -Wcast-qual -Wformat=2 -Wmissing-include-dirs + -Wcast-align -Wnon-virtual-dtor + -Wctor-dtor-privacy -Wdisabled-optimization + -Winvalid-pch -Wmissing-declarations -Woverloaded-virtual) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept) + endif () + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion + -Wtrampolines -Wzero-as-null-pointer-constant -Wuseless-cast + -Wvector-operation-performance -Wsized-deallocation) + endif () + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2 + -Wnull-dereference -Wduplicated-cond) + endif () +endif () + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(PEDANTIC_COMPILE_FLAGS -Weverything -Wpedantic + -Wno-weak-vtables -Wno-padded -Wno-gnu-statement-expression + -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-reserved-id-macro + -Wno-global-constructors -Wno-disabled-macro-expansion) endif () if (MASTER_PROJECT AND CMAKE_GENERATOR MATCHES "Visual Studio") diff --git a/include/fmt/core.h b/include/fmt/core.h index 66597eed..d0f63feb 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -30,10 +30,10 @@ # define FMT_HAS_INCLUDE(x) 0 #endif -#if defined(__GNUC__) && !defined(__clang__) -# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#ifdef __has_cpp_attribute +# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else -# define FMT_GCC_VERSION 0 +# define FMT_HAS_CPP_ATTRIBUTE(x) 0 #endif #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) @@ -42,12 +42,6 @@ # define FMT_HAS_GXX_CXX11 0 #endif -#ifdef _MSC_VER -# define FMT_MSC_VER _MSC_VER -#else -# define FMT_MSC_VER 0 -#endif - // Check if relaxed c++14 constexpr is supported. // GCC doesn't allow throw in constexpr until version 6 (bug 67371). #ifndef FMT_USE_CONSTEXPR @@ -94,6 +88,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 @@ -557,6 +557,11 @@ struct typed_value : value { template FMT_CONSTEXPR basic_format_arg make_arg(const T &value); +#if FMT_GCC_VERSION +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuseless-cast" +#endif + #define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \ template \ FMT_CONSTEXPR typed_value make_value(ArgType val) { \ @@ -624,6 +629,11 @@ FMT_MAKE_VALUE(pointer_type, const void*, const void*) FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*) #endif +#if FMT_GCC_VERSION +// -Wuseless-cast +#pragma GCC diagnostic pop +#endif + // Formatting of arbitrary pointers is disallowed. If you want to output a // pointer cast it to "void *" or "const void *". In particular, this forbids // formatting of "[const] volatile char *" which is printed as bool by diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index f5c26d2f..fad31909 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -74,8 +74,6 @@ FMT_BEGIN_NAMESPACE FMT_FUNC format_error::~format_error() throw() {} FMT_FUNC system_error::~system_error() FMT_DTOR_NOEXCEPT {} -namespace { - #ifndef _MSC_VER # define FMT_SNPRINTF snprintf #else // _MSC_VER @@ -122,6 +120,11 @@ int safe_strerror( // A noop assignment operator to avoid bogus warnings. void operator=(const StrError &) {} +#if FMT_CLANG_VERSION +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-member-function" +#endif + // Handle the result of XSI-compliant version of strerror_r. int handle(int result) { // glibc versions before 2.13 return result in errno. @@ -156,6 +159,10 @@ int safe_strerror( return errno; } +#if FMT_CLANG_VERSION +#pragma clang diagnostic pop +#endif + public: StrError(int err_code, char *&buf, std::size_t buf_size) : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} @@ -221,6 +228,11 @@ FMT_FUNC void system_error::init( } namespace internal { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + template int char_traits::format_float( char *buffer, std::size_t size, const char *format, @@ -249,6 +261,10 @@ int char_traits::format_float( FMT_SWPRINTF(buffer, size, format, width, precision, value); } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + template const char basic_data::DIGITS[] = "0001020304050607080910111213141516171819" @@ -468,9 +484,16 @@ void basic_fixed_buffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); } +#if FMT_CLANG_VERSION +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-noreturn" +#endif FMT_FUNC void internal::error_handler::on_error(const char *message) { FMT_THROW(format_error(message)); } +#if FMT_CLANG_VERSION +#pragma clang diagnostic pop +#endif FMT_FUNC void report_system_error( int error_code, fmt::string_view message) FMT_NOEXCEPT { diff --git a/include/fmt/format.h b/include/fmt/format.h index 07c644aa..215510ac 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -37,6 +37,49 @@ #include #include +#if defined(__GNUC__) && !defined(__clang__) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif + +#ifdef __clang__ +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#else +# define FMT_CLANG_VERSION 0 +#endif + +#if defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#elif defined(__ICL) +# define FMT_ICC_VERSION __ICL +#endif + +#ifdef _MSC_VER +# define FMT_MSC_VER _MSC_VER +#else +# define FMT_MSC_VER 0 +#endif + +#if FMT_GCC_VERSION >= 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 + +#if FMT_CLANG_VERSION && !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 "-Wswitch-enum" +#endif + #include "core.h" #ifdef _SECURE_SCL @@ -55,47 +98,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 # define FMT_THROW(x) throw x @@ -115,9 +121,8 @@ # endif #endif -#if FMT_USE_USER_DEFINED_LITERALS && \ - ((FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L) || \ - (defined(FMT_CLANG_VERSION) && FMT_CLANG_VERSION >= 304)) +#if FMT_USE_USER_DEFINED_LITERALS && __cplusplus >= 201402L && \ + (FMT_GCC_VERSION >= 600 || FMT_CLANG_VERSION >= 304) # define FMT_UDL_TEMPLATE 1 #else # define FMT_UDL_TEMPLATE 0 @@ -126,7 +131,8 @@ #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 @@ -134,6 +140,14 @@ #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 // __builtin_clz is broken in clang with Microsoft CodeGen: @@ -380,8 +394,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 { @@ -2306,8 +2318,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_; } }; @@ -2542,11 +2552,18 @@ class basic_writer { }; void on_num() { + #if FMT_CLANG_VERSION + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wundefined-func-template" + #endif unsigned num_digits = internal::count_digits(abs_value); char_type sep = internal::thousands_sep(writer.locale_.get()); unsigned size = num_digits + SEP_SIZE * ((num_digits - 1) / 3); writer.write_int(size, get_prefix(), spec, num_writer{abs_value, size, sep}); + #if FMT_CLANG_VERSION + #pragma clang diagnostic pop + #endif } void on_error() { @@ -3647,11 +3664,11 @@ 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) +#if FMT_CLANG_VERSION && !defined(FMT_ICC_VERSION) # pragma clang diagnostic pop #endif diff --git a/src/posix.cc b/src/posix.cc index bcdab324..452d49f5 100644 --- a/src/posix.cc +++ b/src/posix.cc @@ -6,7 +6,7 @@ // For the license information refer to format.h. // Disable bogus MSVC warnings. -#ifndef _CRT_SECURE_NO_WARNINGS +#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER) # define _CRT_SECURE_NO_WARNINGS #endif diff --git a/test/gtest-extra-test.cc b/test/gtest-extra-test.cc index 2043f549..53f0a0d6 100644 --- a/test/gtest-extra-test.cc +++ b/test/gtest-extra-test.cc @@ -195,33 +195,39 @@ TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) { } TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) { - if (::testing::internal::AlwaysFalse()) + if (::testing::internal::AlwaysFalse()) { EXPECT_THROW_MSG(do_nothing(), std::exception, ""); + } - if (::testing::internal::AlwaysTrue()) + if (::testing::internal::AlwaysTrue()) { EXPECT_THROW_MSG(throw_exception(), std::exception, "test"); - else + } else { do_nothing(); + } } TEST(AssertionSyntaxTest, SystemErrorAssertionBehavesLikeSingleStatement) { - if (::testing::internal::AlwaysFalse()) + if (::testing::internal::AlwaysFalse()) { EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, ""); + } - if (::testing::internal::AlwaysTrue()) + if (::testing::internal::AlwaysTrue()) { EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test"); - else + } else { do_nothing(); + } } TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) { - if (::testing::internal::AlwaysFalse()) + if (::testing::internal::AlwaysFalse()) { EXPECT_WRITE(stdout, std::printf("x"), "x"); + } - if (::testing::internal::AlwaysTrue()) + if (::testing::internal::AlwaysTrue()) { EXPECT_WRITE(stdout, std::printf("x"), "x"); - else + } else { do_nothing(); + } } // Tests EXPECT_THROW_MSG. diff --git a/test/posix-test.cc b/test/posix-test.cc index d6b1953c..6e0d08c6 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -153,7 +153,7 @@ TEST(BufferedFileTest, Fileno) { EXPECT_DEATH_IF_SUPPORTED({ try { f.fileno(); - } catch (fmt::system_error) { + } catch (const fmt::system_error&) { std::exit(1); } }, ""); diff --git a/test/util-test.cc b/test/util-test.cc index 544d933d..a9329a38 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -402,7 +402,7 @@ TEST(UtilTest, BitCast) { uint32_t u[2]; }; auto s = fmt::internal::bit_cast(uint64_t(42)); - EXPECT_EQ(fmt::internal::bit_cast(s), 42); + EXPECT_EQ(fmt::internal::bit_cast(s), 42ull); s = fmt::internal::bit_cast(uint64_t(~0ull)); EXPECT_EQ(fmt::internal::bit_cast(s), ~0ull); } @@ -765,7 +765,7 @@ TEST(UtilTest, FormatSystemError) { try { std::allocator alloc; alloc.deallocate(alloc.allocate(max_size), max_size); - } catch (std::bad_alloc) { + } catch (const std::bad_alloc&) { throws_on_alloc = true; } if (!throws_on_alloc) {