json_view: no byte range in exceptions about a removed value #5990 dropped the found flag from diagnostics(), reasoning that a value value_path() does not find leaves no tokens, like the root. But the node of a value that is no longer part of the document still holds the bytes it had in the source, so with JSON_DIAGNOSTICS and JSON_DIAGNOSTIC_POSITIONS its exceptions gained "(bytes 1-4)" for text that is no longer there. The test #5997 added for exactly this case (unit-json_view_positions.cpp, "views of values that are no longer part of the document") has failed on develop since both were merged. Restore the flag: a value that is not found gets no context, the root keeps its byte range. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
diff --git a/include/nlohmann/detail/view/errors.hpp b/include/nlohmann/detail/view/errors.hpp index 3c97cef..1006394 100644 --- a/include/nlohmann/detail/view/errors.hpp +++ b/include/nlohmann/detail/view/errors.hpp
@@ -230,7 +230,8 @@ /// the context basic_json puts in front of the message of an exception about /// a value: "(/path) " with JSON_DIAGNOSTICS (none for the root), then -/// "(bytes a-b) " with JSON_DIAGNOSTIC_POSITIONS (also for the root) +/// "(bytes a-b) " with JSON_DIAGNOSTIC_POSITIONS (also for the root); with +/// JSON_DIAGNOSTICS, nothing for a value that is no longer part of the document /// /// This and the throw helpers that take an error_site are templates, so that /// the path and range code is instantiated only where an exception can be @@ -251,8 +252,14 @@ std::string context; #if JSON_DIAGNOSTICS std::vector<std::string> tokens; - // a value that is not found leaves no tokens, like the root - static_cast<void>(edited ? value_path<true>(d, site.value(), tokens) : value_path<false>(d, site.value(), tokens)); + // a value that is no longer part of the document has no path, and its + // node still holds the bytes it had in the source: no context at all + const bool found = edited ? value_path<true>(d, site.value(), tokens) : value_path<false>(d, site.value(), tokens); + if (!found) + { + // context is still empty; returning it keeps the copy elided (-Wnrvo) + return context; + } if (!tokens.empty()) { // the root value has no path, but still has a byte range
diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index ea04acd..db26ed2 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp
@@ -5059,7 +5059,8 @@ /// the context basic_json puts in front of the message of an exception about /// a value: "(/path) " with JSON_DIAGNOSTICS (none for the root), then -/// "(bytes a-b) " with JSON_DIAGNOSTIC_POSITIONS (also for the root) +/// "(bytes a-b) " with JSON_DIAGNOSTIC_POSITIONS (also for the root); with +/// JSON_DIAGNOSTICS, nothing for a value that is no longer part of the document /// /// This and the throw helpers that take an error_site are templates, so that /// the path and range code is instantiated only where an exception can be @@ -5080,8 +5081,14 @@ std::string context; #if JSON_DIAGNOSTICS std::vector<std::string> tokens; - // a value that is not found leaves no tokens, like the root - static_cast<void>(edited ? value_path<true>(d, site.value(), tokens) : value_path<false>(d, site.value(), tokens)); + // a value that is no longer part of the document has no path, and its + // node still holds the bytes it had in the source: no context at all + const bool found = edited ? value_path<true>(d, site.value(), tokens) : value_path<false>(d, site.value(), tokens); + if (!found) + { + // context is still empty; returning it keeps the copy elided (-Wnrvo) + return context; + } if (!tokens.empty()) { // the root value has no path, but still has a byte range