llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.51k stars 11.3k forks source link

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

Open llvmbot opened 6 years ago

llvmbot commented 6 years ago
Bugzilla Link 38216
Version unspecified
OS Linux
Reporter LLVM Bugzilla Contributor
CC @DougGregor,@mclow,@zygoloid,@jwakely

Extended Description

clang++ rejects the following code:

include

::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.

mclow commented 3 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.

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.

3a17e7c4-fca4-4827-b2a7-11a54d73d746 commented 3 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.

Maybe it's not too late, there seems to be support for removing it. https://wg21.link/lwg3484

ec04fc15-fa35-46f2-80e1-5d271f2ef708 commented 6 years ago

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).

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.

3a17e7c4-fca4-4827-b2a7-11a54d73d746 commented 6 years ago

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

3a17e7c4-fca4-4827-b2a7-11a54d73d746 commented 6 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 .

I think that would be conforming, since any std::lib header is allowed to include 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 defines ::nullptr_t but Clang uses a different +// 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

3a17e7c4-fca4-4827-b2a7-11a54d73d746 commented 6 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).

ec04fc15-fa35-46f2-80e1-5d271f2ef708 commented 6 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.)

jwakely commented 2 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.

This is supposed to say "should only have been required by \ and not \" but the imported plain text comments from bugzilla are now treated as markdown (which is quite annoying).

ldionne commented 2 years ago

@jwakely I read the original bug report and I'm wondering what's expected from Clang/libc++ here. It seems like the simplest fix would be for libstdc++ to declare nullptr_t inside <stddef.h>. Is there something actionable for LLVM here?