diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e47d0e94f..ef4e1266d 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 -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" + run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Debug' - name: build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 @@ -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 @@ -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 -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" + run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Debug' - name: build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 @@ -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" -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" + run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" - name: build run: cmake --build build --config Release --parallel 10 - name: test diff --git a/README.md b/README.md index b717f9bee..d570af1b2 100644 --- a/README.md +++ b/README.md @@ -1649,7 +1649,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/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 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 \ 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/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/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/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index fc157a904..02f1b40bb 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: // 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 aaa08897d..f1b65ba54 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -120,6 +120,7 @@ class binary_reader result = parse_ubjson_internal(); break; + 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 } @@ -2279,6 +2280,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())); } @@ -2481,6 +2496,7 @@ class binary_reader error_msg += "BSON"; break; + 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/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index a1096c733..99cdd05ec 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..aaff2b64c 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,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; @@ -419,6 +473,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); } @@ -456,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); } @@ -507,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; @@ -575,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; } @@ -599,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/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..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)); } @@ -555,6 +570,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)); } @@ -602,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)); } @@ -644,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)); } @@ -714,6 +753,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 @@ -847,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 cbe6e5617..1fa0cd2f7 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));; @@ -381,6 +390,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -702,6 +712,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -906,6 +917,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -926,6 +938,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; @@ -1157,6 +1170,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; @@ -1203,6 +1217,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; @@ -1493,6 +1508,7 @@ class binary_writer case value_t::object: return '{'; + case value_t::discarded: default: // discarded values return 'N'; } @@ -1542,8 +1558,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)) @@ -1560,7 +1578,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 4ac2e7531..024266f36 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; @@ -1287,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; } @@ -2051,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; } @@ -2107,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)); } @@ -2206,6 +2228,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -4230,6 +4254,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)); } @@ -4346,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)); } @@ -5101,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 @@ -5174,6 +5209,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 +5281,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() @@ -5346,6 +5396,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -6278,8 +6330,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(); @@ -6314,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; } @@ -6344,7 +6399,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } return false; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } /*! @@ -6478,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; } @@ -7102,6 +7160,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"; } @@ -8439,6 +8500,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // if there exists a parent it cannot be primitive + 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 } @@ -8598,6 +8666,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 @@ -8754,6 +8823,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 diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 1e323e0c5..5f810e291 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: // 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 } @@ -3894,6 +3902,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 +4194,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 +4423,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; } @@ -8360,6 +8389,7 @@ class binary_reader result = parse_ubjson_internal(); break; + 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 } @@ -10519,6 +10549,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())); } @@ -10721,6 +10765,7 @@ class binary_reader error_msg += "BSON"; break; + 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 } @@ -11095,6 +11140,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(), @@ -11518,6 +11570,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(); @@ -11614,6 +11674,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(); @@ -11644,6 +11711,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(); @@ -11678,6 +11753,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())) @@ -11712,6 +11794,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())) @@ -11757,6 +11847,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; @@ -11800,6 +11898,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; @@ -11833,6 +11939,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); } @@ -11870,6 +11984,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); } @@ -11921,6 +12043,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; @@ -11989,6 +12119,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; } @@ -12013,6 +12151,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)) @@ -12632,6 +12777,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)); } @@ -12704,6 +12856,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)); } @@ -12746,6 +12906,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)); } @@ -12793,6 +12961,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)); } @@ -12835,6 +13011,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)); } @@ -12905,6 +13089,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 @@ -13038,6 +13230,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 @@ -13403,6 +13603,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));; @@ -13728,6 +13937,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -14049,6 +14259,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -14253,6 +14464,7 @@ class binary_writer break; } + case value_t::discarded: default: break; } @@ -14273,6 +14485,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; @@ -14504,6 +14717,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; @@ -14550,6 +14764,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; @@ -14840,6 +15055,7 @@ class binary_writer case value_t::object: return '{'; + case value_t::discarded: default: // discarded values return 'N'; } @@ -14889,8 +15105,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)) @@ -14907,7 +15125,9 @@ class binary_writer : get_msgpack_float_prefix(n)); write_number(n); } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } public: @@ -16048,8 +16268,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'; @@ -16058,7 +16280,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); @@ -18215,6 +18439,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::discarded: default: { object = nullptr; // silence warning, see #821 @@ -18372,6 +18597,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; @@ -18443,6 +18674,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; } @@ -19207,6 +19446,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; } @@ -19263,6 +19507,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)); } @@ -19362,6 +19608,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -21386,6 +21634,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)); } @@ -21502,6 +21752,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)); } @@ -22257,6 +22509,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 @@ -22330,6 +22589,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 @@ -22395,6 +22661,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() @@ -22502,6 +22776,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } + case value_t::null: + case value_t::discarded: default: break; } @@ -23434,8 +23710,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(); @@ -23470,6 +23748,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; } @@ -23500,7 +23779,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } return false; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } /*! @@ -23634,6 +23915,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; } @@ -24258,6 +24540,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"; } @@ -25595,6 +25880,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // if there exists a parent it cannot be primitive + 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 } @@ -25754,6 +26046,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 @@ -25910,6 +26203,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 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cbbdcace3..d0ae29438 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -90,6 +90,16 @@ 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") + # 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}) target_compile_definitions(json_unit PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS) target_compile_options(json_unit PRIVATE diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 962828d20..7b5a36090 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -108,6 +108,7 @@ struct my_allocator : std::allocator throw std::bad_alloc(); } + static_cast(p); // fix MSVC's C4100 warning p->~T(); } 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)); 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) + } +} diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index e58ae745f..c13513764 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -156,6 +156,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 = 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("regression tests 2") { @@ -621,6 +641,16 @@ 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'"); + delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory) + } + SECTION("issue #2825 - Properly constrain the basic_json conversion operator") { static_assert(std::is_copy_assignable::value, ""); diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 2bebd8f59..12770ce64 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -816,7 +816,10 @@ 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; };