Skip to content

Commit 0cc4b77

Browse files
[clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules
On Apple platforms, some of the stddef.h types are also declared in system headers. In particular NULL has a conflicting declaration in <sys/_types/_null.h>. When that's in a different module from <__stddef_null.h>, redeclaration errors can occur. Make the __stddef_ headers be non-modular in -fbuiltin-headers-in-system-modules and restore them back to not respecting their header guards. Still define the header guards though. __stddef_max_align_t.h was in _Builtin_stddef_max_align_t prior to the addition of _Builtin_stddef, and it needs to stay in a module because struct's can't be type merged. __stddef_wint_t.h didn't used to have a module, but leave it in it current module since it doesn't really belong to stddef.h.
1 parent bf631c6 commit 0cc4b77

13 files changed

+73
-41
lines changed

clang/lib/Basic/Module.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,9 @@ bool Module::directlyUses(const Module *Requested) {
301301
if (Requested->isSubModuleOf(Use))
302302
return true;
303303

304-
// Anyone is allowed to use our builtin stdarg.h and stddef.h and their
305-
// accompanying modules.
306-
if (Requested->getTopLevelModuleName() == "_Builtin_stdarg" ||
307-
Requested->getTopLevelModuleName() == "_Builtin_stddef")
304+
// Anyone is allowed to use our builtin stddef.h and its accompanying modules.
305+
if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) ||
306+
Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"}))
308307
return true;
309308

310309
if (NoUndeclaredIncludes)

clang/lib/Headers/__stddef_null.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(NULL) || !__has_feature(modules)
10+
#if !defined(NULL) || !__building_module(_Builtin_stddef)
1111

1212
/* linux/stddef.h will define NULL to 0. glibc (and other) headers then define
1313
* __need_NULL and rely on stddef.h to redefine NULL to the correct value again.

clang/lib/Headers/__stddef_nullptr_t.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef _NULLPTR_T
10+
/*
11+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
12+
* and needs to behave as if it was textual.
13+
*/
14+
#if !defined(_NULLPTR_T) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1115
#define _NULLPTR_T
1216

1317
#ifdef __cplusplus

clang/lib/Headers/__stddef_offsetof.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef offsetof
10+
/*
11+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
12+
* and needs to behave as if it was textual.
13+
*/
14+
#if !defined(offsetof) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1115
#define offsetof(t, d) __builtin_offsetof(t, d)
1216
#endif

clang/lib/Headers/__stddef_ptrdiff_t.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef _PTRDIFF_T
10+
/*
11+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
12+
* and needs to behave as if it was textual.
13+
*/
14+
#if !defined(_PTRDIFF_T) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1115
#define _PTRDIFF_T
1216

1317
typedef __PTRDIFF_TYPE__ ptrdiff_t;

clang/lib/Headers/__stddef_rsize_t.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef _RSIZE_T
10+
/*
11+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
12+
* and needs to behave as if it was textual.
13+
*/
14+
#if !defined(_RSIZE_T) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1115
#define _RSIZE_T
1216

1317
typedef __SIZE_TYPE__ rsize_t;

clang/lib/Headers/__stddef_size_t.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef _SIZE_T
10+
/*
11+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
12+
* and needs to behave as if it was textual.
13+
*/
14+
#if !defined(_SIZE_T) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1115
#define _SIZE_T
1216

1317
typedef __SIZE_TYPE__ size_t;

clang/lib/Headers/__stddef_unreachable.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef unreachable
10+
/*
11+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
12+
* and needs to behave as if it was textual.
13+
*/
14+
#if !defined(unreachable) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1115
#define unreachable() __builtin_unreachable()
1216
#endif

clang/lib/Headers/__stddef_wchar_t.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99

1010
#if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
1111

12-
#ifndef _WCHAR_T
12+
/*
13+
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
14+
* and needs to behave as if it was textual.
15+
*/
16+
#if !defined(_WCHAR_T) || (__has_feature(modules) && !__building_module(_Builtin_stddef))
1317
#define _WCHAR_T
1418

1519
#ifdef _MSC_EXTENSIONS

clang/lib/Headers/module.modulemap

+9-11
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ module _Builtin_intrinsics [system] [extern_c] {
155155

156156
// Start -fbuiltin-headers-in-system-modules affected modules
157157

158-
// The following modules all ignore their top level headers
159-
// when -fbuiltin-headers-in-system-modules is passed, and
160-
// most of those headers join system modules when present.
158+
// The following modules all ignore their headers when
159+
// -fbuiltin-headers-in-system-modules is passed, and many of
160+
// those headers join system modules when present.
161161

162162
// e.g. if -fbuiltin-headers-in-system-modules is passed, then
163163
// float.h will not be in the _Builtin_float module (that module
@@ -190,11 +190,6 @@ module _Builtin_stdalign [system] {
190190
export *
191191
}
192192

193-
// When -fbuiltin-headers-in-system-modules is passed, only
194-
// the top level headers are removed, the implementation headers
195-
// will always be in their submodules. That means when stdarg.h
196-
// is included, it will still import this module and make the
197-
// appropriate submodules visible.
198193
module _Builtin_stdarg [system] {
199194
textual header "stdarg.h"
200195

@@ -237,6 +232,8 @@ module _Builtin_stdbool [system] {
237232
module _Builtin_stddef [system] {
238233
textual header "stddef.h"
239234

235+
// __stddef_max_align_t.h is always in this module, even if
236+
// -fbuiltin-headers-in-system-modules is passed.
240237
explicit module max_align_t {
241238
header "__stddef_max_align_t.h"
242239
export *
@@ -283,9 +280,10 @@ module _Builtin_stddef [system] {
283280
}
284281
}
285282

286-
/* wint_t is provided by <wchar.h> and not <stddef.h>. It's here
287-
* for compatibility, but must be explicitly requested. Therefore
288-
* __stddef_wint_t.h is not part of _Builtin_stddef. */
283+
// wint_t is provided by <wchar.h> and not <stddef.h>. It's here
284+
// for compatibility, but must be explicitly requested. Therefore
285+
// __stddef_wint_t.h is not part of _Builtin_stddef. It is always in
286+
// this module even if -fbuiltin-headers-in-system-modules is passed.
289287
module _Builtin_stddef_wint_t [system] {
290288
header "__stddef_wint_t.h"
291289
export *

clang/lib/Lex/ModuleMap.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -2498,9 +2498,12 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
24982498
}
24992499

25002500
bool NeedsFramework = false;
2501-
// Don't add the top level headers to the builtin modules if the builtin headers
2502-
// belong to the system modules.
2503-
if (!Map.LangOpts.BuiltinHeadersInSystemModules || ActiveModule->isSubModule() || !isBuiltInModuleName(ActiveModule->Name))
2501+
// Don't add headers to the builtin modules if the builtin headers belong to
2502+
// the system modules, with the exception of __stddef_max_align_t.h which
2503+
// always had its own module.
2504+
if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2505+
!isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
2506+
ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
25042507
Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
25052508

25062509
if (NeedsFramework)

clang/test/Modules/no-undeclared-includes-builtins.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// headers.
99

1010
// RUN: rm -rf %t
11-
// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/no-undeclared-includes-builtins/libcxx -I %S/Inputs/no-undeclared-includes-builtins/glibc %s
11+
// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fbuiltin-headers-in-system-modules -fimplicit-module-maps -I %S/Inputs/no-undeclared-includes-builtins/libcxx -I %S/Inputs/no-undeclared-includes-builtins/glibc %s
1212
// expected-no-diagnostics
1313

1414
#include <stddef.h>

clang/test/Modules/stddef.c

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
// RUN: rm -rf %t
2-
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery
2+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify=builtin-headers-in-system-modules -fno-modules-error-recovery
33
// RUN: rm -rf %t
4-
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery
4+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify=no-builtin-headers-in-system-modules -fno-modules-error-recovery
55

66
#include "ptrdiff_t.h"
77

88
ptrdiff_t pdt;
99

10-
// size_t is declared in both size_t.h and __stddef_size_t.h, both of which are
11-
// modular headers. Regardless of whether stddef.h joins the StdDef test module
12-
// or is in its _Builtin_stddef module, __stddef_size_t.h will be in
13-
// _Builtin_stddef.size_t. It's not defined which module will win as the expected
14-
// provider of size_t. For the purposes of this test it doesn't matter which header
15-
// gets reported, just as long as it isn't other.h or include_again.h.
16-
size_t st; // expected-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}}
17-
// expected-note@size_t.h:* 0+ {{here}}
18-
// expected-note@__stddef_size_t.h:* 0+ {{here}}
10+
// size_t is declared in both size_t.h and __stddef_size_t.h. If
11+
// -fbuiltin-headers-in-system-modules is set, then __stddef_size_t.h is a
12+
// non-modular header that will be transitively pulled in the StdDef test module
13+
// by include_again.h. Otherwise it will be in the _Builtin_stddef module. In
14+
// any case it's not defined which module will win as the expected provider of
15+
// size_t. For the purposes of this test it doesn't matter which of the two
16+
// providing headers get reported.
17+
size_t st; // builtin-headers-in-system-modules-error-re {{missing '#include "{{size_t|include_again}}.h"'; 'size_t' must be declared before it is used}} \
18+
no-builtin-headers-in-system-modules-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}}
19+
// builtin-headers-in-system-modules-note@size_t.h:* 0+ {{here}} \
20+
no-builtin-headers-in-system-modules-note@size_t.h:* 0+ {{here}}
21+
// builtin-headers-in-system-modules-note@__stddef_size_t.h:* 0+ {{here}} \
22+
no-builtin-headers-in-system-modules-note@__stddef_size_t.h:* 0+ {{here}}
1923

2024
#include "include_again.h"
21-
// Includes <stddef.h> which includes <__stddef_size_t.h> which imports the
22-
// _Builtin_stddef.size_t module.
25+
// Includes <stddef.h> which includes <__stddef_size_t.h>.
2326

2427
size_t st2;
2528

2629
#include "size_t.h"
27-
// Redeclares size_t, but the type merger should figure it out.
30+
// Redeclares size_t when -fbuiltin-headers-in-system-modules is not passed, but
31+
// the type merger should figure it out.
2832

2933
size_t st3;

0 commit comments

Comments
 (0)