https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107795
Bug ID: 107795 Summary: <limits.h> recursion through <syslimits.h> breaks non-GNU implementations of the C++ stdlib Product: gcc Version: 12.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- The <limits.h> header currently includes "syslimits.h", which then recursively includes <limits.h> after defining the _GCC_NEXT_LIMITS_H macro. The <limits.h> header seems to be generated from a bunch of stuff, including `gcc/limitx.h`, which seems to be responsible for that recursive inclusion. Incidentally, this seems to not have been modified in the last 30 years. This recursive inclusion with a macro is hostile to implementations that want to build on top of GCC's <limits.h> header, since they need to know about that recursive inclusion trick and the _GCC_NEXT_LIMITS_H macro. For example, libc++ currently needs to know about this wrinkle and implement its own <limits.h> header differently depending on whether it's built with GCC or another compiler. System headers should work such that they can be layered on top of each other without needing this sort of trick. To reproduce the issue we're seeing with a minimal example: #!/usr/bin/env bash rm -rf __fake_cxx_include && mkdir -p __fake_cxx_include cat <<EOF > __fake_cxx_include/limits.h #ifndef __MY_LIMITS_H #define __MY_LIMITS_H # include_next <limits.h> #endif EOF cat <<EOF | g++-12 -isystem $PWD/__fake_cxx_include -nostdinc++ -v -fsyntax-only -xc++ - -O2 -H #include <limits.h> #include <wchar.h> EOF When running this script, the output is (on our Docker image): . /llvm/__fake_cxx_include/limits.h .. /usr/lib/gcc/x86_64-linux-gnu/12/include/limits.h ... /usr/lib/gcc/x86_64-linux-gnu/12/include/syslimits.h .... /llvm/__fake_cxx_include/limits.h . /usr/include/wchar.h [...] .. /usr/include/x86_64-linux-gnu/bits/wchar.h [...] .. /usr/include/x86_64-linux-gnu/bits/wchar2.h In file included from /usr/include/wchar.h:867, from <stdin>:2: /usr/include/x86_64-linux-gnu/bits/wchar2.h:398:3: error: #error "Assumed value of MB_LEN_MAX wrong" 398 | # error "Assumed value of MB_LEN_MAX wrong" | ^~~~~ Because this <limits.h> header does not know about the GCC-internal macro _GCC_NEXT_LIMITS_H, we fail to recursively re-include <limits.h> and then including <wchar.h> fails in a rather obscure way. Also note that this only fails if we're using -O2 to compile, since -O2 seems to turn on some __fortify stuff which leads to including <wchar2.h>. Long story short, it would be great if GCC's <limits.h> header could be simplified to avoid recursively including itself through <syslimits.h>.