mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 20:20:32 +00:00
Suppress GCC's false -Warray-bounds error in set_parents() with JSON_DIAGNOSTICS
With JSON_DIAGNOSTICS, GCC 13 to 15 report a false -Warray-bounds error at -O3 when set_parents() is inlined right after a non-container value (e.g., a string) was created: the std::map access in the object branch is checked against the string allocation although m_type rules that branch out. GCC 15 fixed the pattern from #4819 but not this one. Suppress -Warray-bounds around set_parents() only, and add a regression test that is compiled with -O3 -Werror=array-bounds on GCC. Fixes #5742 Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -763,6 +763,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
static_cast<void>(check_parents);
|
||||
}
|
||||
|
||||
// GCC 13 to at least 15 report a false -Warray-bounds error when set_parents()
|
||||
// is inlined at -O3 right after a non-container value was created: the analysis
|
||||
// does not use m_type to rule out the object/array branches and checks
|
||||
// the std::map access against the allocation of, e.g., a string.
|
||||
// See https://github.com/nlohmann/json/issues/5742 and #4819.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
void set_parents()
|
||||
{
|
||||
#if JSON_DIAGNOSTICS
|
||||
@@ -799,6 +808,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
iterator set_parents(iterator it, std::ptrdiff_t count_set_parents)
|
||||
{
|
||||
|
||||
@@ -27441,6 +27441,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
static_cast<void>(check_parents);
|
||||
}
|
||||
|
||||
// GCC 13 to at least 15 report a false -Warray-bounds error when set_parents()
|
||||
// is inlined at -O3 right after a non-container value was created: the analysis
|
||||
// does not use m_type to rule out the object/array branches and checks
|
||||
// the std::map access against the allocation of, e.g., a string.
|
||||
// See https://github.com/nlohmann/json/issues/5742 and #4819.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
void set_parents()
|
||||
{
|
||||
#if JSON_DIAGNOSTICS
|
||||
@@ -27477,6 +27486,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
iterator set_parents(iterator it, std::ptrdiff_t count_set_parents)
|
||||
{
|
||||
|
||||
@@ -139,6 +139,11 @@ json_test_set_test_options(test-unicode4 TEST_PROPERTIES TIMEOUT 3000)
|
||||
# only the #972 regression test needs thirdparty/fifo_map on its include path
|
||||
json_test_set_test_options(test-regression1 LINK_LIBRARIES fifo_map_include)
|
||||
|
||||
# GCC's false -Warray-bounds error with JSON_DIAGNOSTICS only shows up when optimizing (#5742)
|
||||
json_test_set_test_options(test-diagnostics-optimized
|
||||
COMPILE_OPTIONS $<$<CXX_COMPILER_ID:GNU>:-O3 -Werror=array-bounds>
|
||||
)
|
||||
|
||||
#############################################################################
|
||||
# add unit tests
|
||||
#############################################################################
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Regression test for https://github.com/nlohmann/json/issues/5742: with
|
||||
// JSON_DIAGNOSTICS, GCC (13 to at least 15) reports a false -Warray-bounds
|
||||
// error in the inlined set_parents() at -O3. The warning depends on GCC's
|
||||
// inlining decisions, so the sections cover patterns that trigger it on
|
||||
// different GCC versions (#4819: GCC 13 and 14; #5742: GCC 14 and 15).
|
||||
// On GCC, this file is compiled with -O3 -Werror=array-bounds (see
|
||||
// tests/CMakeLists.txt), so the test fails to build if the warning returns.
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#ifdef JSON_DIAGNOSTICS
|
||||
#undef JSON_DIAGNOSTICS
|
||||
#endif
|
||||
|
||||
#define JSON_DIAGNOSTICS 1
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class diag_color
|
||||
{
|
||||
red,
|
||||
green,
|
||||
blue
|
||||
};
|
||||
|
||||
void to_json(json& j, const diag_color& c)
|
||||
{
|
||||
static const std::pair<diag_color, json> m[] = // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
{
|
||||
{diag_color::red, "r"},
|
||||
{diag_color::green, "g"},
|
||||
{diag_color::blue, "b"},
|
||||
};
|
||||
const auto* it = std::find_if(std::begin(m), std::end(m), [c](const std::pair<diag_color, json>& p)
|
||||
{
|
||||
return p.first == c;
|
||||
});
|
||||
j = it->second;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("diagnostics with optimization")
|
||||
{
|
||||
SECTION("issue #4819 - object in vector")
|
||||
{
|
||||
std::vector<json> jsons{};
|
||||
jsons.emplace_back(json({{"key", "value"}}));
|
||||
CHECK(jsons.back()["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("issue #5742 - string values from a static table")
|
||||
{
|
||||
json j = json::array();
|
||||
j.push_back(diag_color::red);
|
||||
j.push_back(diag_color::green);
|
||||
j.push_back(diag_color::blue);
|
||||
CHECK(j.dump() == R"(["r","g","b"])");
|
||||
CHECK_THROWS_WITH_AS(j[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user