https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109732
Bug ID: 109732 Summary: [14 regression] gcc miscompiles iterator comparison on nlohmann_json Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: slyfox at gcc dot gnu.org Target Milestone: --- Initially I observed the failure as a test failure on nlohmann_json-3.11.2 against gcc-14 master (r14-395-g1adb1a653d6739): 33 - test-items_cpp11 (Failed) 34 - test-items_cpp17 (Failed) I extracted smaller but not yet self-contained example that seems to illustrate the problem: // $ cat unit-t.cpp #include <cstdio> #include <nlohmann/json.hpp> namespace { int seen_failures = 0; __attribute__((noinline)) static void sne(nlohmann::json::const_reverse_iterator lhs, nlohmann::json::const_reverse_iterator rhs) { bool res = !(lhs == rhs); if (!res) seen_failures++; } struct TestCase { void (*m_test)(); TestCase(void (*test)()) { // not used anywhere, but triggers the failure m_test = test; } }; static void _DOCTEST_ANON_FUNC_8() { const nlohmann::json js = "hello world"; const nlohmann::json js_const(js); nlohmann::json::const_reverse_iterator sit = js_const.crbegin(); sne(sit, js_const.crend()); } } int main() { // below 3 lines look like a no-op, but afects the result: TestCase ltc(&_DOCTEST_ANON_FUNC_8); std::vector<const TestCase*> testArray; testArray.push_back(<c); _DOCTEST_ANON_FUNC_8(); puts((seen_failures > 0) ? "FAILURE!" : "SUCCESS!"); return EXIT_SUCCESS; } To trigger it we will need json headers-only library: $ git clone --depth 1 https://github.com/nlohmann/json.git # commit 6af826d0bdb55e4b69e3ad817576745335f243ca $ g++-14 unit-t.cpp -O2 -Ijson/include -o a && ./a FAILURE! For comparison unoptimized and older gcc does work as expcted: $ g++-14 unit-t.cpp -O0 -Ijson/include -o a && ./a SUCCESS! $ g++ unit-t.cpp -O2 -Ijson/include -o a && ./a SUCCESS! I'm not sure if `nlohmann::json::const_reverse_iterator` is implemented correctly according to c++ requirements. The inheritance looks fishy. At least I would expect consistent behaviour for -O0/O2. -fsanitize={address,undefined} does not uncover anything obvious. Can you help me understand if it's a gcc or json deficiency? Thank you!