From 1c030cccf17f4079c06ac5977ce8936a5776f5f4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 29 Jul 2021 15:23:21 +0200 Subject: [PATCH 01/25] :white_check_mark: add regression test #2824 --- test/src/unit-regression2.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index fa5de3179..96bf6c872 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -157,6 +157,26 @@ struct adl_serializer }; } // namespace nlohmann +///////////////////////////////////////////////////////////////////// +// for #2824 +///////////////////////////////////////////////////////////////////// + +class sax_no_exception : public nlohmann::detail::json_sax_dom_parser +{ + public: + explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser(j, false) {} + + static bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) + { + error_string = ex.what(); + return false; + } + + static std::string error_string; +}; + +std::string sax_no_exception::error_string = ""; + TEST_CASE("regression tests 2") { @@ -622,6 +642,15 @@ TEST_CASE("regression tests 2") } } + SECTION("issue #2824 - encoding of json::exception::what()") + { + json j; + sax_no_exception sax(j); + + CHECK (!json::sax_parse("xyz", &sax)); + CHECK(sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); + } + SECTION("issue #2825 - Properly constrain the basic_json conversion operator") { static_assert(std::is_copy_assignable::value, ""); From 2c030bac2cf49cbc5201d39899a4e8f7953b73e0 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 30 Jul 2021 14:41:06 +0200 Subject: [PATCH 02/25] :white_check_mark: add regression test #2824 --- test/src/unit-regression2.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index 96bf6c872..56bb3f398 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -166,16 +166,16 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser public: explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser(j, false) {} - static bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) + static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) { - error_string = ex.what(); + error_string = new std::string(ex.what()); return false; } - static std::string error_string; + static std::string* error_string; }; -std::string sax_no_exception::error_string = ""; +std::string* sax_no_exception::error_string = nullptr; TEST_CASE("regression tests 2") @@ -648,7 +648,8 @@ TEST_CASE("regression tests 2") sax_no_exception sax(j); CHECK (!json::sax_parse("xyz", &sax)); - CHECK(sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); + CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); + delete sax_no_exception::error_string; } SECTION("issue #2825 - Properly constrain the basic_json conversion operator") From c7822840eb57d35a63ddcdec115bc3ea42266567 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 30 Jul 2021 15:00:54 +0200 Subject: [PATCH 03/25] :white_check_mark: add regression test #2824 --- test/src/unit-regression2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index 56bb3f398..c20d72e38 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -168,7 +168,7 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) { - error_string = new std::string(ex.what()); + error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory) return false; } From 8676f6745e84e1f84b3444dd200d71b109b1a090 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 30 Jul 2021 21:18:25 +0200 Subject: [PATCH 04/25] :white_check_mark: add regression test #2824 --- test/src/unit-regression2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index c20d72e38..603963f50 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -649,7 +649,7 @@ TEST_CASE("regression tests 2") CHECK (!json::sax_parse("xyz", &sax)); CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); - delete sax_no_exception::error_string; + delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory) } SECTION("issue #2825 - Properly constrain the basic_json conversion operator") From 5a1bc76f34a01d30eb3b4b0c54f6ec97de28cdb0 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 1 Aug 2021 13:34:55 +0200 Subject: [PATCH 05/25] :alembic: switch off exceptions --- test/CMakeLists.txt | 9 ++++ test/src/unit-disabled_exceptions.cpp | 66 +++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 test/src/unit-disabled_exceptions.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cbbdcace3..271b8c77a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -90,6 +90,15 @@ foreach(file ${files}) endif() endforeach() +# disable exceptions for test-disabled_exceptions +target_compile_definitions(test-disabled_exceptions PUBLIC JSON_NOEXCEPTION) +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(test-disabled_exceptions PUBLIC -fno-exceptions) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_options(test-disabled_exceptions PUBLIC /EH) + target_compile_definitions(test-disabled_exceptions PUBLIC _HAS_EXCEPTIONS=0) +endif() + add_executable(json_unit EXCLUDE_FROM_ALL $ ${files}) target_compile_definitions(json_unit PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS) target_compile_options(json_unit PRIVATE diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp new file mode 100644 index 000000000..6da9dcf1d --- /dev/null +++ b/test/src/unit-disabled_exceptions.cpp @@ -0,0 +1,66 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ (test suite) +| | |__ | | | | | | version 3.9.1 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "doctest_compatibility.h" + +#include +using json = nlohmann::json; + +///////////////////////////////////////////////////////////////////// +// for #2824 +///////////////////////////////////////////////////////////////////// + +class sax_no_exception : public nlohmann::detail::json_sax_dom_parser +{ + public: + explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser(j, false) {} + + static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) + { + error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory) + return false; + } + + static std::string* error_string; +}; + +std::string* sax_no_exception::error_string = nullptr; + +TEST_CASE("Tests with disabled exceptions") +{ + SECTION("issue #2824 - encoding of json::exception::what()") + { + json j; + sax_no_exception sax(j); + + CHECK (!json::sax_parse("xyz", &sax)); + CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); + delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory) + } +} From c3df4ffd5aa4b0b80f2d19a6b7006f89f3efd09d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 1 Aug 2021 14:08:14 +0200 Subject: [PATCH 06/25] :rotating_light: fix warning --- include/nlohmann/detail/output/binary_writer.hpp | 1 + single_include/nlohmann/json.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 24e7c1094..7cd3d804b 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -908,6 +908,7 @@ class binary_writer if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) { JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); + static_cast(j); } return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 28ce55292..681f19495 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -14209,6 +14209,7 @@ class binary_writer if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) { JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); + static_cast(j); } return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; From 83c005f881e6be8095de954030318dad1ea37371 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 9 Aug 2021 21:43:03 +0200 Subject: [PATCH 07/25] :alembic: try minimal example --- test/src/unit-disabled_exceptions.cpp | 88 ++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index 6da9dcf1d..b0d772d89 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -52,6 +52,81 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser std::string* sax_no_exception::error_string = nullptr; +// +#include // size_t +#include // exception +#include // runtime_error +#include // to_string +#include // vector + +// +namespace nlohmann +{ +namespace detail2 +{ + +struct position_t +{ + std::size_t chars_read_total = 0; + std::size_t chars_read_current_line = 0; + std::size_t lines_read = 0; + + constexpr operator size_t() const + { + return chars_read_total; + } +}; + + +class exception : public std::exception +{ + public: + const char* what() const noexcept override + { + return m.what(); + } + + const int id; + + protected: + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + std::runtime_error m; +}; + +class parse_error : public exception +{ + public: + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +} // namespace detail +} // namespace nlohmann +// + TEST_CASE("Tests with disabled exceptions") { SECTION("issue #2824 - encoding of json::exception::what()") @@ -60,7 +135,18 @@ TEST_CASE("Tests with disabled exceptions") sax_no_exception sax(j); CHECK (!json::sax_parse("xyz", &sax)); - CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); + //CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory) } + + SECTION("test") + { + nlohmann::detail2::position_t pos; + pos.chars_read_total = 100; + pos.chars_read_current_line = 50; + pos.lines_read = 1; + + auto error = nlohmann::detail2::parse_error::create(100, pos, "foo"); + CHECK(std::string(error.what()) == "[json.exception.parse_error.100] parse error at line 2, column 50: foo"); + } } From 36394cc262e50b0e2a5a53e11655564ffc2d669b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 9 Aug 2021 21:58:05 +0200 Subject: [PATCH 08/25] :alembic: try minimal example --- test/src/unit-disabled_exceptions.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index b0d772d89..22a85b2c8 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -77,7 +77,6 @@ struct position_t } }; - class exception : public std::exception { public: @@ -86,7 +85,7 @@ class exception : public std::exception return m.what(); } - const int id; + const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) protected: exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} @@ -123,7 +122,7 @@ class parse_error : public exception } }; -} // namespace detail +} // namespace detail2 } // namespace nlohmann // From 0d530c9de83229ced6d25a6a2e8dbd305c07c7ff Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 10 Aug 2021 08:22:21 +0200 Subject: [PATCH 09/25] :alembic: try minimal example --- test/src/unit-disabled_exceptions.cpp | 49 ++++++--------------------- 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index 22a85b2c8..248a2134a 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -65,18 +65,6 @@ namespace nlohmann namespace detail2 { -struct position_t -{ - std::size_t chars_read_total = 0; - std::size_t chars_read_current_line = 0; - std::size_t lines_read = 0; - - constexpr operator size_t() const - { - return chars_read_total; - } -}; - class exception : public std::exception { public: @@ -85,14 +73,12 @@ class exception : public std::exception return m.what(); } - const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) - protected: - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + exception(const char* what_arg) : m(what_arg) {} - static std::string name(const std::string& ename, int id_) + static std::string name(const std::string& ename) { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + return "[json.exception." + ename + "] "; } private: @@ -102,24 +88,16 @@ class exception : public std::exception class parse_error : public exception { public: - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + static parse_error create(const std::string& what_arg) { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); + std::string w = exception::name("parse_error") + what_arg; + return parse_error(w.c_str()); } - const std::size_t byte; - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} - - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } + parse_error(const char* what_arg) + : exception(what_arg) + {} }; } // namespace detail2 @@ -140,12 +118,7 @@ TEST_CASE("Tests with disabled exceptions") SECTION("test") { - nlohmann::detail2::position_t pos; - pos.chars_read_total = 100; - pos.chars_read_current_line = 50; - pos.lines_read = 1; - - auto error = nlohmann::detail2::parse_error::create(100, pos, "foo"); - CHECK(std::string(error.what()) == "[json.exception.parse_error.100] parse error at line 2, column 50: foo"); + auto error = nlohmann::detail2::parse_error::create("foo"); + CHECK(std::string(error.what()) == "[json.exception.parse_error] foo"); } } From edc203a837c79d9fec672134993dfa625b80de4b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 10 Aug 2021 08:35:14 +0200 Subject: [PATCH 10/25] :alembic: try minimal example --- test/src/unit-disabled_exceptions.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index 248a2134a..ed8800f81 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -76,11 +76,6 @@ class exception : public std::exception protected: exception(const char* what_arg) : m(what_arg) {} - static std::string name(const std::string& ename) - { - return "[json.exception." + ename + "] "; - } - private: std::runtime_error m; }; @@ -90,14 +85,12 @@ class parse_error : public exception public: static parse_error create(const std::string& what_arg) { - std::string w = exception::name("parse_error") + what_arg; + std::string w = "[json.exception.parse_error] " + what_arg; return parse_error(w.c_str()); } private: - parse_error(const char* what_arg) - : exception(what_arg) - {} + parse_error(const char* what_arg) : exception(what_arg) {} }; } // namespace detail2 From 26569f8eccf0611938103c0549f1c0465c83f153 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 10 Aug 2021 10:09:31 +0200 Subject: [PATCH 11/25] :alembic: try minimal example --- test/src/unit-disabled_exceptions.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index ed8800f81..31a9873cf 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -83,13 +83,6 @@ class exception : public std::exception class parse_error : public exception { public: - static parse_error create(const std::string& what_arg) - { - std::string w = "[json.exception.parse_error] " + what_arg; - return parse_error(w.c_str()); - } - - private: parse_error(const char* what_arg) : exception(what_arg) {} }; @@ -111,7 +104,8 @@ TEST_CASE("Tests with disabled exceptions") SECTION("test") { - auto error = nlohmann::detail2::parse_error::create("foo"); + std::string w = "[json.exception.parse_error] foo"; + auto error = nlohmann::detail2::parse_error(w.c_str()); CHECK(std::string(error.what()) == "[json.exception.parse_error] foo"); } } From b792bf56601b33737b2abf2d10945d984075643f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 10 Aug 2021 10:29:13 +0200 Subject: [PATCH 12/25] :alembic: try minimal example --- test/src/unit-disabled_exceptions.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index 31a9873cf..5a29958c9 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -53,11 +53,8 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser std::string* sax_no_exception::error_string = nullptr; // -#include // size_t #include // exception #include // runtime_error -#include // to_string -#include // vector // namespace nlohmann @@ -83,6 +80,13 @@ class exception : public std::exception class parse_error : public exception { public: + static parse_error create(const std::string& what_arg) + { + std::string w = "[json.exception.parse_error] " + what_arg; + return parse_error(w.c_str()); + } + + private: parse_error(const char* what_arg) : exception(what_arg) {} }; @@ -104,8 +108,7 @@ TEST_CASE("Tests with disabled exceptions") SECTION("test") { - std::string w = "[json.exception.parse_error] foo"; - auto error = nlohmann::detail2::parse_error(w.c_str()); + auto error = nlohmann::detail2::parse_error::create("foo"); CHECK(std::string(error.what()) == "[json.exception.parse_error] foo"); } } From 68d8661f1b41c078a3871efdae748d313c793b79 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 11 Aug 2021 08:06:25 +0200 Subject: [PATCH 13/25] :memo: update documentation --- README.md | 2 +- doc/mkdocs/docs/features/macros.md | 2 ++ doc/mkdocs/docs/home/exceptions.md | 2 ++ test/CMakeLists.txt | 5 +-- test/src/unit-disabled_exceptions.cpp | 50 +-------------------------- 5 files changed, 9 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 9f972c211..e34afaf4d 100644 --- a/README.md +++ b/README.md @@ -1648,7 +1648,7 @@ Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924). - The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`. - As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. - The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. -- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. +- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). ## Execute unit tests diff --git a/doc/mkdocs/docs/features/macros.md b/doc/mkdocs/docs/features/macros.md index d008393f7..8b10ef1f3 100644 --- a/doc/mkdocs/docs/features/macros.md +++ b/doc/mkdocs/docs/features/macros.md @@ -32,6 +32,8 @@ When defining `JSON_NOEXCEPTION`, `#!cpp try` is replaced by `#!cpp if (true)`, The same effect is achieved by setting the compiler flag `-fno-exceptions`. +Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). + ## `JSON_NO_IO` When defined, headers ``, ``, ``, ``, and `` are not included and parse functions relying on these headers are excluded. This is relevant for environment where these I/O functions are disallowed for security reasons (e.g., Intel Software Guard Extensions (SGX)). diff --git a/doc/mkdocs/docs/home/exceptions.md b/doc/mkdocs/docs/home/exceptions.md index d5d07362f..a04b60f86 100644 --- a/doc/mkdocs/docs/home/exceptions.md +++ b/doc/mkdocs/docs/home/exceptions.md @@ -50,6 +50,8 @@ Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or #include ``` +Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). + ### Extended diagnostic messages Exceptions in the library are thrown in the local context of the JSON value they are detected. This makes detailed diagnostics messages, and hence debugging, difficult. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 271b8c77a..d0ae29438 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -95,8 +95,9 @@ target_compile_definitions(test-disabled_exceptions PUBLIC JSON_NOEXCEPTION) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_compile_options(test-disabled_exceptions PUBLIC -fno-exceptions) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(test-disabled_exceptions PUBLIC /EH) - target_compile_definitions(test-disabled_exceptions PUBLIC _HAS_EXCEPTIONS=0) + # disabled due to https://github.com/nlohmann/json/discussions/2824 + #target_compile_options(test-disabled_exceptions PUBLIC /EH) + #target_compile_definitions(test-disabled_exceptions PUBLIC _HAS_EXCEPTIONS=0) endif() add_executable(json_unit EXCLUDE_FROM_ALL $ ${files}) diff --git a/test/src/unit-disabled_exceptions.cpp b/test/src/unit-disabled_exceptions.cpp index 5a29958c9..6da9dcf1d 100644 --- a/test/src/unit-disabled_exceptions.cpp +++ b/test/src/unit-disabled_exceptions.cpp @@ -52,48 +52,6 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser std::string* sax_no_exception::error_string = nullptr; -// -#include // exception -#include // runtime_error - -// -namespace nlohmann -{ -namespace detail2 -{ - -class exception : public std::exception -{ - public: - const char* what() const noexcept override - { - return m.what(); - } - - protected: - exception(const char* what_arg) : m(what_arg) {} - - private: - std::runtime_error m; -}; - -class parse_error : public exception -{ - public: - static parse_error create(const std::string& what_arg) - { - std::string w = "[json.exception.parse_error] " + what_arg; - return parse_error(w.c_str()); - } - - private: - parse_error(const char* what_arg) : exception(what_arg) {} -}; - -} // namespace detail2 -} // namespace nlohmann -// - TEST_CASE("Tests with disabled exceptions") { SECTION("issue #2824 - encoding of json::exception::what()") @@ -102,13 +60,7 @@ TEST_CASE("Tests with disabled exceptions") sax_no_exception sax(j); CHECK (!json::sax_parse("xyz", &sax)); - //CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); + CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'"); delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory) } - - SECTION("test") - { - auto error = nlohmann::detail2::parse_error::create("foo"); - CHECK(std::string(error.what()) == "[json.exception.parse_error] foo"); - } } From e20f3f95eb1b5485c37e079bbf18d58b1d49f607 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 11 Aug 2021 23:55:46 +0200 Subject: [PATCH 14/25] :rotating_light: guard GCC pragmas #2924 --- include/nlohmann/detail/conversions/to_chars.hpp | 4 ++++ include/nlohmann/detail/output/binary_writer.hpp | 4 ++++ include/nlohmann/json.hpp | 4 ++++ single_include/nlohmann/json.hpp | 12 ++++++++++++ 4 files changed, 24 insertions(+) diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp index e5c1d01f1..17289481d 100644 --- a/include/nlohmann/detail/conversions/to_chars.hpp +++ b/include/nlohmann/detail/conversions/to_chars.hpp @@ -1066,8 +1066,10 @@ char* to_chars(char* first, const char* last, FloatType value) *first++ = '-'; } +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif if (value == 0) // +-0 { *first++ = '0'; @@ -1076,7 +1078,9 @@ char* to_chars(char* first, const char* last, FloatType value) *first++ = '0'; return first; } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 0199b9b59..6c9bbf445 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -1525,8 +1525,10 @@ class binary_writer void write_compact_float(const number_float_t n, detail::input_format_t format) { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && static_cast(n) <= static_cast((std::numeric_limits::max)()) && static_cast(static_cast(n)) == static_cast(n)) @@ -1543,7 +1545,9 @@ class binary_writer : get_msgpack_float_prefix(n)); write_number(n); } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } public: diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index cd8152811..7303ca588 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -6278,8 +6278,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec */ friend bool operator==(const_reference lhs, const_reference rhs) noexcept { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif const auto lhs_type = lhs.type(); const auto rhs_type = rhs.type(); @@ -6344,7 +6346,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } return false; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 84a70cf59..5d6b72b22 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -14826,8 +14826,10 @@ class binary_writer void write_compact_float(const number_float_t n, detail::input_format_t format) { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && static_cast(n) <= static_cast((std::numeric_limits::max)()) && static_cast(static_cast(n)) == static_cast(n)) @@ -14844,7 +14846,9 @@ class binary_writer : get_msgpack_float_prefix(n)); write_number(n); } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } public: @@ -15985,8 +15989,10 @@ char* to_chars(char* first, const char* last, FloatType value) *first++ = '-'; } +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif if (value == 0) // +-0 { *first++ = '0'; @@ -15995,7 +16001,9 @@ char* to_chars(char* first, const char* last, FloatType value) *first++ = '0'; return first; } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); @@ -23370,8 +23378,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec */ friend bool operator==(const_reference lhs, const_reference rhs) noexcept { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif const auto lhs_type = lhs.type(); const auto rhs_type = rhs.type(); @@ -23436,7 +23446,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } return false; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } /*! From 44d60f8d14e317d044955c606077007195d0c8c1 Mon Sep 17 00:00:00 2001 From: Ferry Huberts Date: Thu, 12 Aug 2021 16:33:41 +0200 Subject: [PATCH 15/25] All: fix warnings when compiling with -Wswitch-enum Signed-off-by: Ferry Huberts --- .../nlohmann/detail/conversions/from_json.hpp | 13 ++ include/nlohmann/detail/input/parser.hpp | 7 + .../nlohmann/detail/iterators/iter_impl.hpp | 61 ++++++++ .../detail/iterators/iteration_proxy.hpp | 8 ++ include/nlohmann/detail/json_pointer.hpp | 16 +++ include/nlohmann/json.hpp | 29 ++++ single_include/nlohmann/json.hpp | 134 ++++++++++++++++++ 7 files changed, 268 insertions(+) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 4e4efd0a6..c7bd018e3 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -58,6 +58,13 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) break; } + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: default: JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } @@ -343,6 +350,12 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) break; } + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: default: JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index 90f232765..6ec509f81 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -334,6 +334,13 @@ class parser parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); } + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::end_of_input: + case token_type::literal_or_value: default: // the last token was unexpected { return sax->parse_error(m_lexer.get_position(), diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 1747a88af..cbbb75c59 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -104,6 +104,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator = primitive_iterator_t(); @@ -200,6 +208,13 @@ class iter_impl break; } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator.set_begin(); @@ -230,6 +245,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator.set_end(); @@ -264,6 +287,13 @@ class iter_impl case value_t::null: JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) @@ -298,6 +328,14 @@ class iter_impl return &*m_it.array_iterator; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) @@ -343,6 +381,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { ++m_it.primitive_iterator; @@ -386,6 +432,13 @@ class iter_impl break; } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { --m_it.primitive_iterator; @@ -419,6 +472,14 @@ class iter_impl case value_t::array: return (m_it.array_iterator == other.m_it.array_iterator); + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return (m_it.primitive_iterator == other.m_it.primitive_iterator); } diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index d59098d95..9994b364c 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -97,6 +97,14 @@ template class iteration_proxy_value return anchor.key(); // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return empty_str; } diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 72e14f014..f722d3b4d 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -555,6 +555,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -714,6 +722,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: { // we do not expect primitive values if there is still a diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 7303ca588..92dd2f6ff 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1059,6 +1059,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::discarded: default: { object = nullptr; // silence warning, see #821 @@ -1216,6 +1217,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::discarded: default: { break; @@ -2206,6 +2213,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -4230,6 +4239,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } @@ -5174,6 +5185,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return m_value.object->size(); } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // all other types have size 1 @@ -5239,6 +5257,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return m_value.object->max_size(); } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // all other types have max_size() == size() @@ -7106,6 +7132,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return "binary"; case value_t::discarded: return "discarded"; + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: default: return "number"; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 5d6b72b22..2c10a6d1f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3894,6 +3894,13 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) break; } + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: default: JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } @@ -4179,6 +4186,12 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) break; } + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: default: JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } @@ -4402,6 +4415,14 @@ template class iteration_proxy_value return anchor.key(); // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return empty_str; } @@ -11049,6 +11070,13 @@ class parser parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); } + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::end_of_input: + case token_type::literal_or_value: default: // the last token was unexpected { return sax->parse_error(m_lexer.get_position(), @@ -11472,6 +11500,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator = primitive_iterator_t(); @@ -11568,6 +11604,13 @@ class iter_impl break; } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator.set_begin(); @@ -11598,6 +11641,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator.set_end(); @@ -11632,6 +11683,13 @@ class iter_impl case value_t::null: JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) @@ -11666,6 +11724,14 @@ class iter_impl return &*m_it.array_iterator; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) @@ -11711,6 +11777,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { ++m_it.primitive_iterator; @@ -11754,6 +11828,13 @@ class iter_impl break; } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { --m_it.primitive_iterator; @@ -11787,6 +11868,14 @@ class iter_impl case value_t::array: return (m_it.array_iterator == other.m_it.array_iterator); + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return (m_it.primitive_iterator == other.m_it.primitive_iterator); } @@ -12700,6 +12789,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -12859,6 +12956,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: { // we do not expect primitive values if there is still a @@ -18159,6 +18264,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::discarded: default: { object = nullptr; // silence warning, see #821 @@ -18316,6 +18422,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::discarded: default: { break; @@ -19306,6 +19418,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -21330,6 +21444,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } @@ -22274,6 +22390,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return m_value.object->size(); } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // all other types have size 1 @@ -22339,6 +22462,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return m_value.object->max_size(); } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // all other types have max_size() == size() @@ -24206,6 +24337,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return "binary"; case value_t::discarded: return "discarded"; + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: default: return "number"; } From 832cee5b77013ef8058356f2273f496cd3d9b6f0 Mon Sep 17 00:00:00 2001 From: Ferry Huberts Date: Thu, 12 Aug 2021 19:49:54 +0200 Subject: [PATCH 16/25] Adjust warnings flags, as requested Signed-off-by: Ferry Huberts --- cmake/ci.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/ci.cmake b/cmake/ci.cmake index 7f2a56de6..2bcdd0062 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -99,7 +99,7 @@ set(CLANG_CXXFLAGS "-std=c++11 \ -Wno-extra-semi-stmt \ -Wno-padded \ -Wno-range-loop-analysis \ - -Wno-switch-enum -Wno-covered-switch-default \ + -Wno-covered-switch-default \ -Wno-weak-vtables \ ") @@ -326,7 +326,7 @@ set(GCC_CXXFLAGS "-std=c++11 \ -Wswitch \ -Wswitch-bool \ -Wswitch-default \ - -Wno-switch-enum \ + -Wswitch-enum \ -Wswitch-outside-range \ -Wswitch-unreachable \ -Wsync-nand \ From e65db8344815eb1fbdd05b3d4449ed6f53348952 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 13 Aug 2021 12:42:38 +0200 Subject: [PATCH 17/25] :alembic: add -WX flag to MSVC builds --- .github/workflows/windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index fad51b632..adf663308 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -56,7 +56,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4" + run: cmake -S . -B build -G "Visual Studio 15 2017" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" - name: build run: cmake --build build --config Release --parallel 10 - name: test @@ -88,7 +88,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4" + run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" - name: build run: cmake --build build --config Release --parallel 10 - name: test From 789280fcb2d2176a4e1d393a201e699c9dbb75de Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 13 Aug 2021 13:20:26 +0200 Subject: [PATCH 18/25] :rotating_light: fix C4309 warning --- test/src/unit-deserialization.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 293d2418f..ad96343a0 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -1089,7 +1089,7 @@ TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, char, unsigned char, std::uint8_t) { // a star emoji - std::vector v = {'"', static_cast(0xe2), static_cast(0xad), static_cast(0x90), static_cast(0xef), static_cast(0xb8), static_cast(0x8f), '"'}; + std::vector v = {'"', static_cast(0xe2u), static_cast(0xadu), static_cast(0x90u), static_cast(0xefu), static_cast(0xb8u), static_cast(0x8fu), '"'}; CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\""); CHECK(json::accept(v)); From fecb01858b9ffe9ea7b2fc10bc20ecdef4b201ec Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 13 Aug 2021 13:28:17 +0200 Subject: [PATCH 19/25] :alembic: add -WX flag to MSVC builds --- .github/workflows/windows.yml | 10 +++++----- appveyor.yml | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index adf663308..4978e5d97 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -37,13 +37,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" + run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Release' && matrix.architecture == 'x64' - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On + run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Release' && matrix.architecture != 'x64' - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON + run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Debug' - name: build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 @@ -72,10 +72,10 @@ jobs: steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On + run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Release' - name: cmake - run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON + run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Debug' - name: build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 diff --git a/appveyor.yml b/appveyor.yml index 4dba417c6..0157e2081 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 configuration: Debug platform: x86 - CXX_FLAGS: "" + CXX_FLAGS: "/W4 /WX" LINKER_FLAGS: "" CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 @@ -13,7 +13,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 configuration: Release platform: x86 - CXX_FLAGS: "" + CXX_FLAGS: "/W4 /WX" LINKER_FLAGS: "" CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 @@ -22,7 +22,7 @@ environment: configuration: Release platform: x86 name: with_win_header - CXX_FLAGS: "" + CXX_FLAGS: "/W4 /WX" LINKER_FLAGS: "" CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 @@ -30,7 +30,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 configuration: Release platform: x86 - CXX_FLAGS: "/permissive- /std:c++latest /utf-8" + CXX_FLAGS: "/permissive- /std:c++latest /utf-8 /W4 /WX" LINKER_FLAGS: "" CMAKE_OPTIONS: "" GENERATOR: Visual Studio 15 2017 @@ -38,7 +38,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 configuration: Release platform: x86 - CXX_FLAGS: "" + CXX_FLAGS: "/W4 /WX" LINKER_FLAGS: "" CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF" GENERATOR: Visual Studio 16 2019 @@ -46,7 +46,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 configuration: Release platform: x64 - CXX_FLAGS: "" + CXX_FLAGS: "/W4 /WX" LINKER_FLAGS: "" CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 @@ -54,7 +54,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 configuration: Release platform: x64 - CXX_FLAGS: "/permissive- /std:c++latest /Zc:__cplusplus /utf-8 /F4000000" + CXX_FLAGS: "/permissive- /std:c++latest /Zc:__cplusplus /utf-8 /F4000000 /W4 /WX" LINKER_FLAGS: "/STACK:4000000" CMAKE_OPTIONS: "" GENERATOR: Visual Studio 15 2017 From e7a69b8d316829673ad4e1d98c4a3af13f92a0e0 Mon Sep 17 00:00:00 2001 From: Ferry Huberts Date: Fri, 13 Aug 2021 13:43:51 +0200 Subject: [PATCH 20/25] Adjust more files after actually building like the CI Signed-off-by: Ferry Huberts --- include/nlohmann/detail/exceptions.hpp | 8 ++++ .../nlohmann/detail/input/binary_reader.hpp | 16 +++++++ .../nlohmann/detail/iterators/iter_impl.hpp | 32 ++++++++++++++ include/nlohmann/detail/json_pointer.hpp | 39 ++++++++++++++++ .../nlohmann/detail/output/binary_writer.hpp | 15 +++++++ include/nlohmann/json.hpp | 44 +++++++++++++++++++ 6 files changed, 154 insertions(+) diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index fc157a904..616b089ea 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -102,6 +102,14 @@ class exception : public std::exception break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: // LCOV_EXCL_LINE break; // LCOV_EXCL_LINE } diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 8f55e1959..b9c6d6364 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -119,6 +119,7 @@ class binary_reader result = parse_ubjson_internal(); break; + case input_format_t::json: default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -2236,6 +2237,20 @@ class binary_reader return sax->number_unsigned(number_lexer.get_number_unsigned()); case token_type::value_float: return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: default: return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); } @@ -2438,6 +2453,7 @@ class binary_reader error_msg += "BSON"; break; + case input_format_t::json: default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index cbbb75c59..aaff2b64c 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -432,6 +432,7 @@ class iter_impl break; } + case value_t::null: case value_t::string: case value_t::boolean: case value_t::number_integer: @@ -517,6 +518,14 @@ class iter_impl case value_t::array: return (m_it.array_iterator < other.m_it.array_iterator); + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return (m_it.primitive_iterator < other.m_it.primitive_iterator); } @@ -568,6 +577,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator += i; @@ -636,6 +653,14 @@ class iter_impl case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return m_it.primitive_iterator - other.m_it.primitive_iterator; } @@ -660,6 +685,13 @@ class iter_impl case value_t::null: JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index f722d3b4d..d727ecc50 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -441,6 +441,13 @@ class json_pointer an error situation, because primitive values may only occur as single value; that is, with an empty list of reference tokens. */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); } @@ -513,6 +520,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -610,6 +625,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -652,6 +675,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -863,6 +894,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: { // add primitive value with its reference string diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 6c9bbf445..d89a4a0d9 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -56,6 +56,15 @@ class binary_writer break; } + case value_t::null: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));; @@ -363,6 +372,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -684,6 +694,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -888,6 +899,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -1140,6 +1152,7 @@ class binary_writer return header_size + 0ul; // LCOV_EXCL_START + case value_t::discarded: default: JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) return 0ul; @@ -1186,6 +1199,7 @@ class binary_writer return write_bson_null(name); // LCOV_EXCL_START + case value_t::discarded: default: JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) return; @@ -1476,6 +1490,7 @@ class binary_writer case value_t::object: return '{'; + case value_t::discarded: default: // discarded values return 'N'; } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 92dd2f6ff..f9bb0326e 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1294,6 +1294,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: break; } @@ -2058,6 +2066,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::binary: + case value_t::discarded: default: break; } @@ -2114,6 +2127,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object)); } @@ -4357,6 +4372,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } @@ -5112,6 +5129,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return m_value.object->empty(); } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // all other types are nonempty @@ -5372,6 +5396,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -6342,6 +6368,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::binary: return *lhs.m_value.binary == *rhs.m_value.binary; + case value_t::discarded: default: return false; } @@ -6508,6 +6535,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::binary: return (*lhs.m_value.binary) < (*rhs.m_value.binary); + case value_t::discarded: default: return false; } @@ -8468,6 +8496,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // if there exists a parent it cannot be primitive + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -8627,6 +8662,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case patch_operations::invalid: default: { // op must be "add", "remove", "replace", "move", "copy", or @@ -8783,6 +8819,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // both primitive type: replace value From 288cdf9af7eb1d8f7e93989450942b32e275650c Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 13 Aug 2021 14:07:17 +0200 Subject: [PATCH 21/25] :alembic: add -WX flag to MSVC builds --- test/src/unit-allocator.cpp | 4 ++++ test/src/unit-udt.cpp | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 962828d20..c68e1886b 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -100,6 +100,9 @@ struct my_allocator : std::allocator std::allocator::deallocate(p, n); } + // the code below warns about p in MSVC 2015 - this could be a bug + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH + DOCTEST_MSVC_SUPPRESS_WARNING(4100) void destroy(T* p) { if (next_destroy_fails) @@ -110,6 +113,7 @@ struct my_allocator : std::allocator p->~T(); } + DOCTEST_MSVC_SUPPRESS_WARNING_POP template struct rebind diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 2bebd8f59..7871a7fba 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -809,6 +809,10 @@ TEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated static_assert(!is_constructible_patched::value, ""); } +// the code below warns about t in MSVC 2015 - this could be a bug +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4100) + namespace { class Evil @@ -821,6 +825,8 @@ class Evil int m_i = 0; }; +DOCTEST_MSVC_SUPPRESS_WARNING_POP + void from_json(const json& /*unused*/, Evil& /*unused*/) {} } // namespace From 95b73bcd01762c9832db711ddcacdb204c2d960e Mon Sep 17 00:00:00 2001 From: Ferry Huberts Date: Fri, 13 Aug 2021 14:22:18 +0200 Subject: [PATCH 22/25] Forgot to amalgate Signed-off-by: Ferry Huberts --- single_include/nlohmann/json.hpp | 154 +++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2c10a6d1f..30c2e29ba 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2697,6 +2697,14 @@ class exception : public std::exception break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: // LCOV_EXCL_LINE break; // LCOV_EXCL_LINE } @@ -8377,6 +8385,7 @@ class binary_reader result = parse_ubjson_internal(); break; + case input_format_t::json: default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -10494,6 +10503,20 @@ class binary_reader return sax->number_unsigned(number_lexer.get_number_unsigned()); case token_type::value_float: return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: default: return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); } @@ -10696,6 +10719,7 @@ class binary_reader error_msg += "BSON"; break; + case input_format_t::json: default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -11828,6 +11852,7 @@ class iter_impl break; } + case value_t::null: case value_t::string: case value_t::boolean: case value_t::number_integer: @@ -11913,6 +11938,14 @@ class iter_impl case value_t::array: return (m_it.array_iterator < other.m_it.array_iterator); + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return (m_it.primitive_iterator < other.m_it.primitive_iterator); } @@ -11964,6 +11997,14 @@ class iter_impl break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { m_it.primitive_iterator += i; @@ -12032,6 +12073,14 @@ class iter_impl case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: return m_it.primitive_iterator - other.m_it.primitive_iterator; } @@ -12056,6 +12105,13 @@ class iter_impl case value_t::null: JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) @@ -12675,6 +12731,13 @@ class json_pointer an error situation, because primitive values may only occur as single value; that is, with an empty list of reference tokens. */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); } @@ -12747,6 +12810,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -12844,6 +12915,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -12886,6 +12965,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } @@ -13097,6 +13184,14 @@ class json_pointer break; } + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: default: { // add primitive value with its reference string @@ -13462,6 +13557,15 @@ class binary_writer break; } + case value_t::null: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));; @@ -13769,6 +13873,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -14090,6 +14195,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -14294,6 +14400,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -14546,6 +14653,7 @@ class binary_writer return header_size + 0ul; // LCOV_EXCL_START + case value_t::discarded: default: JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) return 0ul; @@ -14592,6 +14700,7 @@ class binary_writer return write_bson_null(name); // LCOV_EXCL_START + case value_t::discarded: default: JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) return; @@ -14882,6 +14991,7 @@ class binary_writer case value_t::object: return '{'; + case value_t::discarded: default: // discarded values return 'N'; } @@ -18499,6 +18609,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: break; } @@ -19263,6 +19381,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::binary: + case value_t::discarded: default: break; } @@ -19319,6 +19442,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object)); } @@ -21562,6 +21687,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } @@ -22317,6 +22444,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return m_value.object->empty(); } + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // all other types are nonempty @@ -22577,6 +22711,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -23547,6 +23683,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::binary: return *lhs.m_value.binary == *rhs.m_value.binary; + case value_t::discarded: default: return false; } @@ -23713,6 +23850,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::binary: return (*lhs.m_value.binary) < (*rhs.m_value.binary); + case value_t::discarded: default: return false; } @@ -25673,6 +25811,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // if there exists a parent it cannot be primitive + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -25832,6 +25977,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case patch_operations::invalid: default: { // op must be "add", "remove", "replace", "move", "copy", or @@ -25988,6 +26134,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: default: { // both primitive type: replace value From 364a21be6b6bba5d83550f12f40e17608cc3aef7 Mon Sep 17 00:00:00 2001 From: Ferry Huberts Date: Fri, 13 Aug 2021 15:30:55 +0200 Subject: [PATCH 23/25] Add coverage exclusion comments, as requested Signed-off-by: Ferry Huberts --- include/nlohmann/detail/exceptions.hpp | 16 ++++++++-------- include/nlohmann/detail/input/binary_reader.hpp | 4 ++-- include/nlohmann/json.hpp | 14 +++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index 616b089ea..02f1b40bb 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -102,14 +102,14 @@ class exception : public std::exception break; } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE break; // LCOV_EXCL_LINE } diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index b9c6d6364..5e21629ab 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -119,7 +119,7 @@ class binary_reader result = parse_ubjson_internal(); break; - case input_format_t::json: + case input_format_t::json: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -2453,7 +2453,7 @@ class binary_reader error_msg += "BSON"; break; - case input_format_t::json: + case input_format_t::json: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index f9bb0326e..81705ffcb 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -8496,13 +8496,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // if there exists a parent it cannot be primitive - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } From cdbc50b9a856daaff4318458cd8c4c41c4fc71b2 Mon Sep 17 00:00:00 2001 From: Ferry Huberts Date: Fri, 13 Aug 2021 15:33:05 +0200 Subject: [PATCH 24/25] Again forgot to amalgate (sigh) Signed-off-by: Ferry Huberts --- single_include/nlohmann/json.hpp | 34 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 30c2e29ba..761e9ef92 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2697,14 +2697,14 @@ class exception : public std::exception break; } - case value_t::null: - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE break; // LCOV_EXCL_LINE } @@ -8385,7 +8385,7 @@ class binary_reader result = parse_ubjson_internal(); break; - case input_format_t::json: + case input_format_t::json: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -10719,7 +10719,7 @@ class binary_reader error_msg += "BSON"; break; - case input_format_t::json: + case input_format_t::json: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } @@ -25811,13 +25811,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // if there exists a parent it cannot be primitive - case value_t::string: - case value_t::boolean: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::number_float: - case value_t::binary: - case value_t::discarded: + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } From 4b0e04eb685b9ce8cb563177c5aaea9f7002fbf9 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 13 Aug 2021 17:03:55 +0200 Subject: [PATCH 25/25] :rotating_light: fix C4100 warnings --- test/src/unit-allocator.cpp | 5 +---- test/src/unit-udt.cpp | 11 ++++------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index c68e1886b..7b5a36090 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -100,9 +100,6 @@ struct my_allocator : std::allocator std::allocator::deallocate(p, n); } - // the code below warns about p in MSVC 2015 - this could be a bug - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH - DOCTEST_MSVC_SUPPRESS_WARNING(4100) void destroy(T* p) { if (next_destroy_fails) @@ -111,9 +108,9 @@ struct my_allocator : std::allocator throw std::bad_alloc(); } + static_cast(p); // fix MSVC's C4100 warning p->~T(); } - DOCTEST_MSVC_SUPPRESS_WARNING_POP template struct rebind diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 7871a7fba..12770ce64 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -809,10 +809,6 @@ TEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated static_assert(!is_constructible_patched::value, ""); } -// the code below warns about t in MSVC 2015 - this could be a bug -DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING(4100) - namespace { class Evil @@ -820,13 +816,14 @@ class Evil public: Evil() = default; template - Evil(T t) : m_i(sizeof(t)) {} + Evil(T t) : m_i(sizeof(t)) + { + static_cast(t); // fix MSVC's C4100 warning + } int m_i = 0; }; -DOCTEST_MSVC_SUPPRESS_WARNING_POP - void from_json(const json& /*unused*/, Evil& /*unused*/) {} } // namespace