Bug#798955: [PATCH] libstdc++: don't use #include_next in c_global headers
The <cmath> and <cstdlib> headers need their counter parts <math.h> and
<stdlib.h> from the libc respectively, but libstdc++ wraps these
headers. Now <cmath> and <cstdlib> include these headers using
$ echo '#include <cstdlib>' | g++ -x c++ -E - -isystem /usr/include >/dev/null
In file included from <stdin>:1:
/usr/include/c++/9/cstdlib:75:15: fatal error: stdlib.h: No such file or directory
75 | #include_next <stdlib.h>
| ^~~~~~~~~~
compilation terminated.
$
What happens here is that g++ includes
libstdc++-v3/include/c_global/cstdlib. That header temporarily #defines
_GLIBCXX_INCLUDE_NEXT_C_HEADERS and then does #include_next <stdlib.h>.
libstdc++-v3's replacement libstdc++-v3/include/c_comaptibility/stdlib.h
happens to come earlier and is not considered. Unfortunately, the
-isystem above inserted glibc's header before the location containing
<cstdlib>, so the #include_next continues searching and fails to find
<stdlib.h>.
Now you are probably going to say that "-isystem /usr/include" is a bad
idea and that you shouldn't do that. I'm inclined to agree. This isn't a
problem just yet. Debian wants to move /usr/include/stdlib.h to
/usr/include/<multiarch>/stdlib.h. After that move, the problematic flag
becomes "-isystem /usr/include/<multiarch>". Unfortunately, around 30
Debian packages[1] do pass exactly that flag. Regardless whether doing
so is a bad idea, I guess we will have to support that.
I am proposing to replace those two #include_next with plain #include.
That'll solve the problem described above, but it is not entirely
obvious that doing so doesn't break something else.
After switching those #include_next to #include,
libstdc++-v3/include/c_global/cstdlib will continue to temporarily
will #include <stdlib.h>. Now, it'll search all include directories. It
may find libstdc++-v3/include/c_comaptibility/stdlib.h or the libc's
version. We cannot tell which. If it finds the one from libstdc++-v3,
the header will notice the _GLIBCXX_INCLUDE_NEXT_C_HEADERS macro and
immediately #include_next <stdlib.h> skipping the rest of the header.
That in turn will find the libc version. So in both cases, it ends up
using the right one. Precisely what we wanted. #include_next is simply
not useful here.
The #include_next was originally added via PRs libstdc++/14608 and
libstdc++/60401. At that time, the _GLIBCXX_INCLUDE_NEXT_C_HEADERS guard
macro was also added. It seems like the #include_next was a meant as an
extra safe-guard, but actually breaks a practical use case.
For these reasons, I think that using #include_next here is harmful and
that replacing it with plain #include solves the problem without
introducing regressions.
[1] Including but not limited chromium-browser, inkscape, various kde
packages, opencv, and vtk.
libstdc++-v3/ChangeLog:
* include/c_global/cmath: Don't use #include_next.
* include/c_global/cstdlib: Likewise.
---
libstdc++-v3/include/c_global/cmath | 2 +-
libstdc++-v3/include/c_global/cstdlib | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
Given the patch's size, I think that the copyright dance is not
necessary. The issue affects at least gcc-8 to gcc-10. Please Cc me in
replies.
Helmut
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index b99aaf8df40..8b2bb7c0785 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -42,7 +42,7 @@
#include <bits/cpp_type_traits.h>
#include <ext/type_traits.h>
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
-#include_next <math.h>
+#include <math.h>
#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
#include <bits/std_abs.h>
diff --git a/libstdc++-v3/include/c_global/cstdlib b/libstdc++-v3/include/c_global/cstdlib
index f42db41fc51..80b39f6144f 100644
--- a/libstdc++-v3/include/c_global/cstdlib
+++ b/libstdc++-v3/include/c_global/cstdlib
@@ -72,7 +72,7 @@ namespace std
// Need to ensure this finds the C library's <stdlib.h> not a libstdc++
// wrapper that might already be installed later in the include search path.
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
-#include_next <stdlib.h>
+#include <stdlib.h>
#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
#include <bits/std_abs.h>
--
2.26.0
Reply to: