From 37b80711238506c6de995cbc6de8d829d90c407e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 29 Jan 2021 20:15:41 +0100 Subject: [PATCH] :rotating_light: fix warnings --- .../nlohmann/detail/conversions/to_chars.hpp | 2 +- .../nlohmann/detail/input/binary_reader.hpp | 2 +- .../nlohmann/detail/input/input_adapters.hpp | 2 +- include/nlohmann/detail/input/json_sax.hpp | 5 ++ include/nlohmann/detail/input/lexer.hpp | 2 +- .../nlohmann/detail/iterators/iter_impl.hpp | 4 +- .../detail/output/output_adapters.hpp | 6 ++ single_include/nlohmann/json.hpp | 23 +++-- test/src/unit-constructor2.cpp | 12 +-- test/src/unit-conversions.cpp | 2 + test/src/unit-deserialization.cpp | 4 +- test/src/unit-regression1.cpp | 4 +- test/src/unit-udt.cpp | 6 +- test/thirdparty/doctest/doctest.h | 86 +++++++++++++++---- 14 files changed, 121 insertions(+), 39 deletions(-) diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp index 5b098eb8d..e904d10fa 100644 --- a/include/nlohmann/detail/conversions/to_chars.hpp +++ b/include/nlohmann/detail/conversions/to_chars.hpp @@ -200,7 +200,7 @@ boundaries compute_boundaries(FloatType value) using bits_type = typename std::conditional::type; - const std::uint64_t bits = reinterpret_bits(value); + const auto bits = static_cast(reinterpret_bits(value)); const std::uint64_t E = bits >> (kPrecision - 1); const std::uint64_t F = bits & (kHiddenBit - 1); diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 265c0bf79..09b611485 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -1854,7 +1854,7 @@ class binary_reader { return false; } - result = static_cast(number); + result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char return true; } diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index 3edca57c8..5d0b59b57 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -437,7 +437,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b) } template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) +auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { return input_adapter(array, array + N); } diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index c41493d6d..851c1b855 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -126,6 +126,11 @@ struct json_sax const std::string& last_token, const detail::exception& ex) = 0; + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; virtual ~json_sax() = default; }; diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index 8a8403a06..f822a2097 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -1236,7 +1236,7 @@ scan_number_done: // we are done scanning a number) unget(); - char* endptr = nullptr; + char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) errno = 0; // try to parse integers first and fall back to floats diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 5054c1507..69abab75f 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -75,8 +75,10 @@ class iter_impl typename BasicJsonType::const_reference, typename BasicJsonType::reference>::type; - /// default constructor iter_impl() = default; + ~iter_impl() = default; + iter_impl(iter_impl&&) noexcept = default; + iter_impl& operator=(iter_impl&&) noexcept = default; /*! @brief constructor for a given JSON instance diff --git a/include/nlohmann/detail/output/output_adapters.hpp b/include/nlohmann/detail/output/output_adapters.hpp index 71ca65b92..25886ad1a 100644 --- a/include/nlohmann/detail/output/output_adapters.hpp +++ b/include/nlohmann/detail/output/output_adapters.hpp @@ -20,6 +20,12 @@ template struct output_adapter_protocol virtual void write_character(CharType c) = 0; virtual void write_characters(const CharType* s, std::size_t length) = 0; virtual ~output_adapter_protocol() = default; + + output_adapter_protocol() = default; + output_adapter_protocol(const output_adapter_protocol&) = default; + output_adapter_protocol(output_adapter_protocol&&) noexcept = default; + output_adapter_protocol& operator=(const output_adapter_protocol&) = default; + output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; }; /// a type to simplify interfaces diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index c3a21fd2f..849f43d73 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5244,7 +5244,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b) } template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) +auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { return input_adapter(array, array + N); } @@ -5413,6 +5413,11 @@ struct json_sax const std::string& last_token, const detail::exception& ex) = 0; + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; virtual ~json_sax() = default; }; @@ -7223,7 +7228,7 @@ scan_number_done: // we are done scanning a number) unget(); - char* endptr = nullptr; + char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) errno = 0; // try to parse integers first and fall back to floats @@ -9600,7 +9605,7 @@ class binary_reader { return false; } - result = static_cast(number); + result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char return true; } @@ -10958,8 +10963,10 @@ class iter_impl typename BasicJsonType::const_reference, typename BasicJsonType::reference>::type; - /// default constructor iter_impl() = default; + ~iter_impl() = default; + iter_impl(iter_impl&&) noexcept = default; + iter_impl& operator=(iter_impl&&) noexcept = default; /*! @brief constructor for a given JSON instance @@ -12752,6 +12759,12 @@ template struct output_adapter_protocol virtual void write_character(CharType c) = 0; virtual void write_characters(const CharType* s, std::size_t length) = 0; virtual ~output_adapter_protocol() = default; + + output_adapter_protocol() = default; + output_adapter_protocol(const output_adapter_protocol&) = default; + output_adapter_protocol(output_adapter_protocol&&) noexcept = default; + output_adapter_protocol& operator=(const output_adapter_protocol&) = default; + output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; }; /// a type to simplify interfaces @@ -14657,7 +14670,7 @@ boundaries compute_boundaries(FloatType value) using bits_type = typename std::conditional::type; - const std::uint64_t bits = reinterpret_bits(value); + const auto bits = static_cast(reinterpret_bits(value)); const std::uint64_t E = bits >> (kPrecision - 1); const std::uint64_t F = bits & (kHiddenBit - 1); diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp index eb3ab9207..4ffa96aad 100644 --- a/test/src/unit-constructor2.cpp +++ b/test/src/unit-constructor2.cpp @@ -188,20 +188,20 @@ TEST_CASE("other constructors and destructor") { SECTION("object") { - auto* j = new json {{"foo", 1}, {"bar", false}}; - delete j; + auto* j = new json {{"foo", 1}, {"bar", false}}; // NOLINT(cppcoreguidelines-owning-memory) + delete j; // NOLINT(cppcoreguidelines-owning-memory) } SECTION("array") { - auto* j = new json {"foo", 1, 1u, false, 23.42}; - delete j; + auto* j = new json {"foo", 1, 1u, false, 23.42}; // NOLINT(cppcoreguidelines-owning-memory) + delete j; // NOLINT(cppcoreguidelines-owning-memory) } SECTION("string") { - auto* j = new json("Hello world"); - delete j; + auto* j = new json("Hello world"); // NOLINT(cppcoreguidelines-owning-memory) + delete j; // NOLINT(cppcoreguidelines-owning-memory) } } } diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 6117226e2..4a544ea3f 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1639,6 +1639,7 @@ TEST_CASE("value conversion") enum class cards {kreuz, pik, herz, karo}; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive NLOHMANN_JSON_SERIALIZE_ENUM(cards, { {cards::kreuz, "kreuz"}, @@ -1656,6 +1657,7 @@ enum TaskState TS_INVALID = -1, }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, { {TS_INVALID, nullptr}, diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 5ccc0d9e7..293d2418f 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -412,7 +412,7 @@ TEST_CASE("deserialization") SECTION("from chars") { - auto* v = new uint8_t[5]; + auto* v = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory) v[0] = 't'; v[1] = 'r'; v[2] = 'u'; @@ -426,7 +426,7 @@ TEST_CASE("deserialization") CHECK(l.events.size() == 1); CHECK(l.events == std::vector({"boolean(true)"})); - delete[] v; + delete[] v; // NOLINT(cppcoreguidelines-owning-memory) } SECTION("from std::string") diff --git a/test/src/unit-regression1.cpp b/test/src/unit-regression1.cpp index ffbd184d0..449d9fd91 100644 --- a/test/src/unit-regression1.cpp +++ b/test/src/unit-regression1.cpp @@ -422,7 +422,7 @@ TEST_CASE("regression tests 1") // Non-const access with key as "char *" char _ptr_key[] = "Key3"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - char* ptr_key = &_ptr_key[0]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + char* ptr_key = &_ptr_key[0]; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) CHECK_NOTHROW(j[ptr_key] = 3); CHECK(j[ptr_key] == json(3)); @@ -735,7 +735,7 @@ TEST_CASE("regression tests 1") check_roundtrip(83623297654460.33); check_roundtrip(701466573254773.6); check_roundtrip(1369013370304513); - check_roundtrip(96963648023094720); + check_roundtrip(96963648023094720); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) check_roundtrip(3.478237409280108e+17); } diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 96398dbea..0983b371f 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -376,7 +376,7 @@ struct adl_serializer> } else { - opt.reset(new T(j.get())); + opt.reset(new T(j.get())); // NOLINT(cppcoreguidelines-owning-memory) } } }; @@ -407,7 +407,7 @@ TEST_CASE("adl_serializer specialization" * doctest::test_suite("udt")) json j = optPerson; CHECK(j.is_null()); - optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); + optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory) j = optPerson; CHECK_FALSE(j.is_null()); @@ -520,7 +520,7 @@ TEST_CASE("Non-copyable types" * doctest::test_suite("udt")) json j = optPerson; CHECK(j.is_null()); - optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); + optPerson.reset(new udt::person{{42}, {"John Doe"}, udt::country::russia}); // NOLINT(cppcoreguidelines-owning-memory,modernize-make-unique) j = optPerson; CHECK_FALSE(j.is_null()); diff --git a/test/thirdparty/doctest/doctest.h b/test/thirdparty/doctest/doctest.h index ae9c4d410..7712dd6b6 100644 --- a/test/thirdparty/doctest/doctest.h +++ b/test/thirdparty/doctest/doctest.h @@ -48,8 +48,8 @@ #define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 3 -#define DOCTEST_VERSION_STR "2.4.3" +#define DOCTEST_VERSION_PATCH 4 +#define DOCTEST_VERSION_STR "2.4.4" #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -3718,6 +3718,7 @@ namespace detail { } bool TestCase::operator<(const TestCase& other) const { + // this will be used only to differentiate between test cases - not relevant for sorting if(m_line != other.m_line) return m_line < other.m_line; const int file_cmp = m_file.compare(other.m_file); @@ -4043,15 +4044,29 @@ namespace { struct FatalConditionHandler { static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { - for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - break; + // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the + // console just once no matter how many threads have crashed. + static std::mutex mutex; + static bool execute = true; + { + std::lock_guard lock(mutex); + if(execute) { + bool reported = false; + for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } + } + if(reported == false) + reportFatal("Unhandled SEH exception caught"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); } + execute = false; } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; + std::exit(EXIT_FAILURE); } FatalConditionHandler() { @@ -4073,6 +4088,8 @@ namespace { original_terminate_handler = std::get_terminate(); std::set_terminate([]() noexcept { reportFatal("Terminate handler called"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well }); @@ -4083,8 +4100,29 @@ namespace { prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) noexcept { if(signal == SIGABRT) { reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); } }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); } static void reset() { @@ -4092,16 +4130,25 @@ namespace { // Unregister handler and restore the old guarantee SetUnhandledExceptionFilter(previousTop); SetThreadStackGuarantee(&guaranteeSize); - previousTop = nullptr; - isSet = false; std::set_terminate(original_terminate_handler); std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + _CrtSetReportMode(_CRT_ASSERT, prev_report_mode); + _CrtSetReportFile(_CRT_ASSERT, prev_report_file); + isSet = false; } } ~FatalConditionHandler() { reset(); } private: + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; static void (*prev_sigabrt_handler)(int); static std::terminate_handler original_terminate_handler; static bool isSet; @@ -4109,6 +4156,11 @@ namespace { static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; }; + UINT FatalConditionHandler::prev_error_mode_1; + int FatalConditionHandler::prev_error_mode_2; + unsigned int FatalConditionHandler::prev_abort_behavior; + int FatalConditionHandler::prev_report_mode; + _HFILE FatalConditionHandler::prev_report_file; void (*FatalConditionHandler::prev_sigabrt_handler)(int); std::terminate_handler FatalConditionHandler::original_terminate_handler; bool FatalConditionHandler::isSet = false; @@ -5046,7 +5098,6 @@ namespace { struct JUnitTestCaseData { -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime static std::string getCurrentTimestamp() { // Beware, this is not reentrant because of backward compatibility issues // Also, UTC only, again because of backward compatibility (%z is C++11) @@ -5054,16 +5105,19 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime std::time(&rawtime); auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); + std::tm timeInfo; +#ifdef DOCTEST_PLATFORM_WINDOWS + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); +#endif // DOCTEST_PLATFORM_WINDOWS char timeStamp[timeStampSize]; const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); return std::string(timeStamp); } -DOCTEST_CLANG_SUPPRESS_WARNING_POP struct JUnitTestMessage {