Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

No ::nullptr_t in header <stddef.h> #37189

Open Quuxplusone opened 5 years ago

Quuxplusone commented 5 years ago
Bugzilla Link PR38216
Status NEW
Importance P enhancement
Reported by Hao Zhong (zhonghao@pku.org.cn)
Reported on 2018-07-18 17:54:50 -0700
Last modified on 2020-09-29 13:02:37 -0700
Version unspecified
Hardware PC Linux
CC dgregor@apple.com, llvm-bugs@lists.llvm.org, mclow.lists@gmail.com, richard-llvm@metafoo.co.uk, zilla@kayari.org
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
clang++ rejects the following code:

#include <stddef.h>

::nullptr_t n;

"3|error: 'nullptr_t' in namespace '::' does not name a type"

This code is supposed to be accepted, because [depr.c.headers] p2 says:

"Every C header, each of which has a name of the form name.h, behaves as if
each name placed in the standard library namespace by the corresponding cname
header is placed within the global namespace scope."

Paolo Carlini has suggested to perform this change near to existing C++11-aware
code in stddef.h:

#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \
  || (defined(__cplusplus) && __cplusplus >= 201103L)
#ifndef _GCC_MAX_ALIGN_T
#define _GCC_MAX_ALIGN_T
/* Type whose alignment is supported in every context and is at least
   as great as that of any standard type not using alignment
   specifiers.  */
typedef struct {
  long long __max_align_ll __attribute__((__aligned__(__alignof__(long long))));
  long double __max_align_ld __attribute__((__aligned__(__alignof__(long double))));
} max_align_t;
#endif
#endif /* C11 or C++11.  */

BTW, I tried g++. It accepts the above code sample.
Quuxplusone commented 5 years ago

Clang++ accepts when using libc++.

The problem is that we added this in libc++, whereas GCC added it in their compiler-specific stddef.h wrapper.

Question is, who should change? Should libstdc++ change, in that it's not providing a correct C++ standard library implementation when used with a C standard library ? Or should Clang change, to provide this little piece of the C++ standard library itself rather than relying on the C++ stdlib to do it?

(We already make the latter choice on Windows platforms, where the native apparently also lacks ::nullptr_t.)

Quuxplusone commented 5 years ago

IMHO nullptr_t should only have been required by and not . That's what we did for std::byte. Too late now though.

Libstdc++ could provide its own which uses #include_next (which would either find GCC's one, or the C library one) but I'd really prefer not to.

We do that for and and it causes problems too often (when somebody does -I /usr/include the include order changes and #include_next no longer works).

Quuxplusone commented 5 years ago
A simpler libstdc++ change would be to just add it to the global namespace
unconditionally in <bits/c++config.h>, which is where we add it to namespace
std, not in <cstddef>.

I think that would be conforming, since any std::lib header is allowed to
include <cstddef> and it's unspecified whether that adds its names to just
namespace std or also the global namespace.

I don't much like that, but would be less unhappy if it was conditional:

--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -251,6 +251,12 @@ namespace std
 #endif
 }

+#if __clang__
+// GCC's <stddef.h> defines ::nullptr_t but Clang uses a different <stddef.h>
+// that might not define it. Ensure it's present in the global namespace:
+using std::nullptr_t;
+#endif
+
 #define _GLIBCXX_USE_DUAL_ABI

 #if ! _GLIBCXX_USE_DUAL_ABI
Quuxplusone commented 5 years ago

ICC has the same problem, but that's not your concern.

Quuxplusone commented 5 years ago
(In reply to Jonathan Wakely from comment #2)
> We do that for <math.h> and <stdlib.h> and it causes problems too often
> (when somebody does -I /usr/include the include order changes and
> #include_next no longer works).

libc++ does this for 18 of the C headers; doing so seemed necessary to get the
right results for the headers where C and C++ have somewhat different
requirements (for instance, we are required to #undef macros that the C headers
"helpfully" define that shadow libc functions). We don't consider ourselves
responsible for problems caused by people misconfiguring their own include
paths.
Quuxplusone commented 3 years ago
(In reply to Jonathan Wakely from comment #2)
> IMHO nullptr_t should only have been required by <cstddef> and not
> <stddef.h>. That's what we did for std::byte. Too late now though.

Maybe it's not too late, there seems to be support for removing it.
https://wg21.link/lwg3484
Quuxplusone commented 3 years ago
(In reply to Jonathan Wakely from comment #6)
> (In reply to Jonathan Wakely from comment #2)
> > IMHO nullptr_t should only have been required by <cstddef> and not
> > <stddef.h>. That's what we did for std::byte. Too late now though.
>
> Maybe it's not too late, there seems to be support for removing it.
> https://wg21.link/lwg3484

There's usually support for removing things from people who won't get the bug
reports when code using it breaks ;-)

That being said, we have implementation divergence, and we should resolve that.