-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[libc++] stddef.h needs to #include_next for the new clang __need_ macros #86252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
.../test/libcxx/language.support/support.c.headers/support.c.headers.other/stddef.verify.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// This is the same test as clang/test/Headers/stddef.c, but to test the | ||
// libc++ version of stddef.h interacts properly with the clang version. | ||
|
||
struct astruct { | ||
char member; | ||
}; | ||
|
||
ptrdiff_t p0; // expected-error{{unknown type name 'ptrdiff_t'}} | ||
size_t s0; // expected-error{{unknown type name 'size_t'}} | ||
rsize_t r0; // expected-error{{unknown type name 'rsize_t'}} | ||
wchar_t wc0; // wchar_t is a keyword in C++ | ||
void* v0 = NULL; // expected-error{{use of undeclared identifier 'NULL'}} | ||
nullptr_t n0; // expected-error{{unknown type name 'nullptr_t'}} | ||
static void f0(void) { unreachable(); } // expected-error{{undeclared identifier 'unreachable'}} | ||
max_align_t m0; // expected-error{{unknown type name 'max_align_t'}} | ||
size_t o0 = offsetof(struct astruct, member); // expected-error{{unknown type name 'size_t'}} | ||
// expected-error@-1{{expected expression}} expected-error@-1{{use of undeclared identifier 'member'}} | ||
wint_t wi0; // expected-error{{unknown type name 'wint_t'}} | ||
|
||
#include <stddef.h> | ||
|
||
ptrdiff_t p1; | ||
size_t s1; | ||
rsize_t r1; | ||
#if __has_feature(modules) && (__cplusplus <= 202302L) | ||
// expected-error-re@-2{{declaration of 'rsize_t' must be imported from module '{{.+}}' before it is required}} | ||
#else | ||
// expected-error@-4{{unknown type}} expected-note@__stddef_size_t.h:*{{'size_t' declared here}} | ||
#endif | ||
wchar_t wc1; | ||
void* v1 = NULL; | ||
nullptr_t n1; | ||
// unreachable() is declared in <utility> in C++ | ||
// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2826.pdf suggests that it maybe should also be | ||
// declared in <stddef.h> too, but it currently isn't. | ||
static void f1(void) { unreachable(); } // expected-error 0+ {{undeclared identifier}} | ||
max_align_t m1; | ||
#if __cplusplus < 201103L | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o1 = offsetof(struct astruct, member); | ||
wint_t wi1; // expected-error{{unknown type}} | ||
|
||
// rsize_t needs to be opted into via __STDC_WANT_LIB_EXT1__ >= 1. | ||
#define __STDC_WANT_LIB_EXT1__ 1 | ||
#include <stddef.h> | ||
ptrdiff_t p2; | ||
size_t s2; | ||
rsize_t r2; | ||
wchar_t wc2; | ||
void* v2 = NULL; | ||
nullptr_t n2; | ||
static void f2(void) { unreachable(); } // expected-error 0+ {{undeclared identifier}} | ||
max_align_t m2; | ||
#if __cplusplus < 201103L | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o2 = offsetof(struct astruct, member); | ||
wint_t wi2; // expected-error{{unknown type}} |
224 changes: 224 additions & 0 deletions
224
...libcxx/language.support/support.c.headers/support.c.headers.other/stddef_needs.verify.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// This is the same test as clang/test/Headers/stddefneeds.c, but to test the | ||
// libc++ version of stddef.h interacts properly with the clang version. | ||
|
||
struct astruct { | ||
char member; | ||
}; | ||
|
||
ptrdiff_t p0; // expected-error{{unknown type name 'ptrdiff_t'}} | ||
size_t s0; // expected-error{{unknown type name 'size_t'}} | ||
rsize_t r0; // expected-error{{unknown type name 'rsize_t'}} | ||
wchar_t wc0; // wchar_t is a keyword in C++ | ||
void* v0 = NULL; // expected-error{{use of undeclared identifier 'NULL'}} | ||
nullptr_t n0; // expected-error{{unknown type name 'nullptr_t'}} | ||
static void f0(void) { unreachable(); } // expected-error{{undeclared identifier 'unreachable'}} | ||
max_align_t m0; // expected-error{{unknown type name 'max_align_t'}} | ||
size_t o0 = offsetof(struct astruct, member); // expected-error{{unknown type name 'size_t'}} | ||
// expected-error@-1{{expected expression}} expected-error@-1{{use of undeclared identifier 'member'}} | ||
wint_t wi0; // expected-error{{unknown type name 'wint_t'}} | ||
|
||
#define __need_ptrdiff_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p1; | ||
size_t s1; | ||
#if __has_feature(modules) && (__cplusplus <= 202302L) | ||
// expected-error-re@-2{{declaration of 'size_t' must be imported from module '{{.+}}' before it is required}} | ||
#else | ||
// expected-error@-4{{unknown type}} | ||
#endif | ||
rsize_t r1; | ||
#if __has_feature(modules) && (__cplusplus <= 202302L) | ||
// expected-error-re@-2{{declaration of 'rsize_t' must be imported from module '{{.+}}' before it is required}} | ||
#else | ||
// expected-error@-4{{unknown type}} | ||
#endif | ||
wchar_t wc1; | ||
void* v1 = NULL; // expected-error{{undeclared identifier}} | ||
nullptr_t n1; // expected-error{{unknown type}} | ||
static void f1(void) { unreachable(); } // expected-error{{undeclared identifier}} | ||
max_align_t m1; | ||
#if __has_feature(modules) && (__cplusplus <= 202302L) | ||
// expected-error-re@-2{{declaration of 'max_align_t' must be imported from module '{{.+}}' before it is required}} | ||
#else | ||
// expected-error@-4{{unknown type}} | ||
#endif | ||
size_t o1 = offsetof(struct astruct, member); | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
// expected-error@-4{{expected expression}} expected-error@-4{{undeclared identifier}} | ||
wint_t wi1; // expected-error{{unknown type}} | ||
|
||
// The "declaration must be imported" errors are only emitted the first time a | ||
// known-but-not-visible type is seen. At this point the _Builtin_stddef module | ||
// has been built and all of the types tried, so most of the errors won't be | ||
// repeated below in modules. The types still aren't available, just the errors | ||
// aren't repeated. e.g. rsize_t still isn't available, if r1 above got deleted, | ||
// its error would move to r2 below. | ||
|
||
#define __need_size_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p2; | ||
size_t s2; | ||
rsize_t r2; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
wchar_t wc2; | ||
void* v2 = NULL; // expected-error{{undeclared identifier}} | ||
nullptr_t n2; // expected-error{{unknown type}} | ||
static void f2(void) { unreachable(); } // expected-error{{undeclared identifier}} | ||
max_align_t m2; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o2 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi2; // expected-error{{unknown type}} | ||
|
||
#define __need_rsize_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p3; | ||
size_t s3; | ||
rsize_t r3; | ||
wchar_t wc3; | ||
void* v3 = NULL; // expected-error{{undeclared identifier}} | ||
nullptr_t n3; // expected-error{{unknown type}} | ||
static void f3(void) { unreachable(); } // expected-error{{undeclared identifier}} | ||
max_align_t m3; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o3 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi3; // expected-error{{unknown type}} | ||
|
||
#define __need_wchar_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p4; | ||
size_t s4; | ||
rsize_t r4; | ||
wchar_t wc4; | ||
void* v4 = NULL; // expected-error{{undeclared identifier}} | ||
nullptr_t n4; // expected-error{{unknown type}} | ||
static void f4(void) { unreachable(); } // expected-error{{undeclared identifier}} | ||
max_align_t m4; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o4 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi4; // expected-error{{unknown type}} | ||
|
||
#define __need_NULL | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p5; | ||
size_t s5; | ||
rsize_t r5; | ||
wchar_t wc5; | ||
void* v5 = NULL; | ||
nullptr_t n5; // expected-error{{unknown type}} | ||
static void f5(void) { unreachable(); } // expected-error{{undeclared identifier}} | ||
max_align_t m5; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o5 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi5; // expected-error{{unknown type}} | ||
|
||
// nullptr_t doesn't get declared before C23 because its definition | ||
// depends on nullptr. | ||
#define __need_nullptr_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p6; | ||
size_t s6; | ||
rsize_t r6; | ||
wchar_t wc6; | ||
void* v6 = NULL; | ||
nullptr_t n6; | ||
static void f6(void) { unreachable(); } // expected-error{{undeclared identifier}} | ||
max_align_t m6; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o6 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi6; // expected-error{{unknown type}} | ||
|
||
#define __need_unreachable | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p7; | ||
size_t s7; | ||
rsize_t r7; | ||
wchar_t wc7; | ||
void* v7 = NULL; | ||
nullptr_t n7; | ||
// __need_unreachable currently declares unreachable(), but the C++23 standard only lists unreachable() in <utility> | ||
// so maybe stddef.h shouldn't declare it even with __need_unreachable. | ||
static void f7(void) { unreachable(); } // expected-error 0+ {{undeclared identifier}} | ||
max_align_t m7; | ||
#if !__has_feature(modules) || (__cplusplus > 202302L) | ||
// expected-error@-2{{unknown type}} | ||
#endif | ||
size_t o7 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi7; // expected-error{{unknown type}} | ||
|
||
#define __need_max_align_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p8; | ||
size_t s8; | ||
rsize_t r8; | ||
wchar_t wc8; | ||
void* v8 = NULL; | ||
nullptr_t n8; | ||
static void f8(void) { unreachable(); } // expected-error 0+ {{undeclared identifier}} | ||
max_align_t m8; | ||
size_t o8 = | ||
offsetof(struct astruct, member); // expected-error{{expected expression}} expected-error{{undeclared identifier}} | ||
wint_t wi8; // expected-error{{unknown type}} | ||
|
||
#define __need_offsetof | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p9; | ||
size_t s9; | ||
rsize_t r9; | ||
nullptr_t n9; | ||
static void f9(void) { unreachable(); } // expected-error 0+ {{undeclared identifier}} | ||
wchar_t wc9; | ||
void* v9 = NULL; | ||
max_align_t m9; | ||
size_t o9 = offsetof(struct astruct, member); | ||
wint_t wi9; // expected-error{{unknown type}} | ||
|
||
#define __need_wint_t | ||
#include <stddef.h> | ||
|
||
ptrdiff_t p10; | ||
size_t s10; | ||
rsize_t r10; | ||
wchar_t wc10; | ||
void* v10 = NULL; | ||
nullptr_t n10; | ||
static void f10(void) { unreachable(); } // expected-error 0+ {{undeclared identifier}} | ||
max_align_t m10; | ||
size_t o10 = offsetof(struct astruct, member); | ||
wint_t wi10; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would actually suggest that we change the whole header to this:
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can unconditionally declare nullptr_t. If e.g.
__need_size_t
is set, thennullptr_t
shouldn't get declared. I'm not sure if that's for POSIX conformance or what, but it seems to be important when I talk to people implementing low level headers.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see what the problem would be though? We'd be defining it at most once due to the header guard, and nobody else anywhere should be defining
nullptr_t
anyways.Either way, I can try doing that in a separate patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I officially don't understand this patch anymore so I would argue we should go for the simpler approach suggested above unless there's a concrete reason why that wouldn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that some headers need to declare just size_t, and it's a problem if anything else gets declared. The way they do that is by setting
__need_size_t
and including stddef.h. I think it's for POSIX reasons but I'm not 100% why it's so important for people to be able to only see pieces of stdarg and stddef.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AaronBallman do you know why the
__need_
macros are so important in the clang stddef.h?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that this is needed for interfacing with other CRTs (primarily Apple's?):
https://opensource.apple.com/source/Libc/Libc-825.26/include/stddef.h.auto.html
https://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20151005/140394.html
and was carried forward with newer functionality more recently:
https://reviews.llvm.org/D157757
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for digging this up. We're checking with some folks internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The answer we're getting from the Darwin folks is that they can't find a historical reason for it. Basically our current understanding is that on Darwin at least, the most naive implementation (without any
__need_FOO
macros) should work. Or at least it would be intended to work.I don't know about Linuxes though. At the very least, as far as libc++ is concerned, I am quite tempted to close this PR and go with #86843 instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No one's really sure why it's important for the
__need_
macros to be perfectly strict. Trying out #86843 internally. We're still talking about if we want to keep this PR for the tests and copy stddef.h from that one, or dump the tests and just do 86843 by itself.