From 9f7fa05f1110f93c139ce56c39ce94e6e97878c7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 8 Oct 2026 16:21:45 +0200 Subject: [PATCH] Fix MSVC C4127 and Infer finding in the view serializer Test the template options through enabled() so that conditions combined with them are not constant, and mark the nav::value() null dereference as a false positive like materialize.hpp does. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/view/serializer.hpp | 16 +++++++++++++--- single_include/nlohmann/json_view.hpp | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/include/nlohmann/detail/view/serializer.hpp b/include/nlohmann/detail/view/serializer.hpp index 8059f29da..8ed9fc9ac 100644 --- a/include/nlohmann/detail/view/serializer.hpp +++ b/include/nlohmann/detail/view/serializer.hpp @@ -396,6 +396,14 @@ class view_serializer std::memcpy(to, from, n); } + /// a compile-time option as a runtime condition: testing the template + /// argument directly makes a condition like `Editable && c` constant when + /// the option is off, which MSVC reports as C4127 + static NLOHMANN_VIEW_ALWAYS_INLINE bool enabled(bool option) noexcept + { + return option; + } + template void dump_compact(const node* root) { @@ -472,6 +480,8 @@ class view_serializer { // write the value at n (read-only documents: and advance n) bool opened = false; + // false positive: n comes from nav::value(), which never returns null for a valid index + // @infer-ignore NULLPTR_DEREFERENCE switch (static_cast(n->kind)) { case value_t::string: @@ -492,14 +502,14 @@ class view_serializer { const std::uint32_t len = number_length(*n); room(len); - if (Editable && (n->flags & node_flags::storage) != 0) + if (enabled(Editable) && (n->flags & node_flags::storage) != 0) { copy_long(w, m_doc.str(*n), len); // a canonical token written by an edit w += len; break; } const char* const token = src + n->off; - if (!SourceNumbers && NLOHMANN_VIEW_UNLIKELY(len == 2 && token[0] == '-' && token[1] == '0')) + if (!enabled(SourceNumbers) && NLOHMANN_VIEW_UNLIKELY(len == 2 && token[0] == '-' && token[1] == '0')) { *w++ = '0'; // parse() reads -0 as the integer 0 } @@ -510,7 +520,7 @@ class view_serializer break; } case value_t::number_float: - if (SourceNumbers && (n->flags & node_flags::storage) != node_flags::edited) + if (enabled(SourceNumbers) && (n->flags & node_flags::storage) != node_flags::edited) { room(n->len); copy(src + n->off, n->len); diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index 00b0450f2..e402ef6b2 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -5772,6 +5772,14 @@ class view_serializer std::memcpy(to, from, n); } + /// a compile-time option as a runtime condition: testing the template + /// argument directly makes a condition like `Editable && c` constant when + /// the option is off, which MSVC reports as C4127 + static NLOHMANN_VIEW_ALWAYS_INLINE bool enabled(bool option) noexcept + { + return option; + } + template void dump_compact(const node* root) { @@ -5848,6 +5856,8 @@ class view_serializer { // write the value at n (read-only documents: and advance n) bool opened = false; + // false positive: n comes from nav::value(), which never returns null for a valid index + // @infer-ignore NULLPTR_DEREFERENCE switch (static_cast(n->kind)) { case value_t::string: @@ -5868,14 +5878,14 @@ class view_serializer { const std::uint32_t len = number_length(*n); room(len); - if (Editable && (n->flags & node_flags::storage) != 0) + if (enabled(Editable) && (n->flags & node_flags::storage) != 0) { copy_long(w, m_doc.str(*n), len); // a canonical token written by an edit w += len; break; } const char* const token = src + n->off; - if (!SourceNumbers && NLOHMANN_VIEW_UNLIKELY(len == 2 && token[0] == '-' && token[1] == '0')) + if (!enabled(SourceNumbers) && NLOHMANN_VIEW_UNLIKELY(len == 2 && token[0] == '-' && token[1] == '0')) { *w++ = '0'; // parse() reads -0 as the integer 0 } @@ -5886,7 +5896,7 @@ class view_serializer break; } case value_t::number_float: - if (SourceNumbers && (n->flags & node_flags::storage) != node_flags::edited) + if (enabled(SourceNumbers) && (n->flags & node_flags::storage) != node_flags::edited) { room(n->len); copy(src + n->off, n->len);