Skip to content

Commit 9a7a6dd

Browse files
[Modules] Make clang modules for the C standard library headers
Make top level modules for all the C standard library headers. The `__stddef` implementation headers need header guards now that they're all modular. stdarg.h and stddef.h will be textual headers in the builtin modules, and so need to be repeatedly included in both the system and builtin module case. Define their header guards for consistency, but ignore them when building with modules. `__stddef_null.h` needs to ignore its header guard when modules aren't being used to fulfill its redefinition obligation. `__stddef_nullptr_t.h` needs to add a guard for C23 so that `_Builtin_stddef` can compile in C17 and earlier modes. `_Builtin_stddef.nullptr_t` can't require C23 because it also needs to be usable from C++. Reviewed By: Bigcheese Differential Revision: https://reviews.llvm.org/D159064
1 parent 8763aa0 commit 9a7a6dd

26 files changed

+598
-163
lines changed

clang/lib/Basic/Module.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,9 @@ bool Module::directlyUses(const Module *Requested) {
299299
if (Requested->isSubModuleOf(Use))
300300
return true;
301301

302-
// Anyone is allowed to use our builtin stddef.h and its accompanying module.
303-
if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
302+
// Anyone is allowed to use our builtin stdarg.h and stddef.h and their
303+
// accompanying modules.
304+
if (!Requested->Parent && (Requested->Name == "_Builtin_stdarg" || Requested->Name == "_Builtin_stddef"))
304305
return true;
305306

306307
if (NoUndeclaredIncludes)

clang/lib/Headers/__stddef_max_align_t.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*===---- __stddef_max_align_t.h - Definition of max_align_t for modules ---===
1+
/*===---- __stddef_max_align_t.h - Definition of max_align_t ---------------===
22
*
33
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
* See https://llvm.org/LICENSE.txt for license information.

clang/lib/Headers/__stddef_null.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10+
#if !defined(NULL) || !__has_feature(modules)
11+
12+
/* linux/stddef.h will define NULL to 0. glibc (and other) headers then define
13+
* __need_NULL and rely on stddef.h to redefine NULL to the correct value again.
14+
* Modules don't support redefining macros like that, but support that pattern
15+
* in the non-modules case.
16+
*/
1017
#undef NULL
18+
1119
#ifdef __cplusplus
1220
#if !defined(__MINGW32__) && !defined(_MSC_VER)
1321
#define NULL __null
@@ -17,3 +25,5 @@
1725
#else
1826
#define NULL ((void*)0)
1927
#endif
28+
29+
#endif

clang/lib/Headers/__stddef_nullptr_t.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(_NULLPTR_T) || __has_feature(modules)
11-
/* Always define nullptr_t when modules are available. */
12-
#if !__has_feature(modules)
10+
#ifndef _NULLPTR_T
1311
#define _NULLPTR_T
14-
#endif
12+
1513
#ifdef __cplusplus
1614
#if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED)
1715
namespace std {
1816
typedef decltype(nullptr) nullptr_t;
1917
}
2018
using ::std::nullptr_t;
2119
#endif
22-
#else
20+
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
2321
typedef typeof(nullptr) nullptr_t;
2422
#endif
23+
2524
#endif

clang/lib/Headers/__stddef_offsetof.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(offsetof) || __has_feature(modules)
11-
/* Always define offsetof when modules are available. */
10+
#ifndef offsetof
1211
#define offsetof(t, d) __builtin_offsetof(t, d)
1312
#endif

clang/lib/Headers/__stddef_ptrdiff_t.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(_PTRDIFF_T) || __has_feature(modules)
11-
/* Always define ptrdiff_t when modules are available. */
12-
#if !__has_feature(modules)
10+
#ifndef _PTRDIFF_T
1311
#define _PTRDIFF_T
14-
#endif
12+
1513
typedef __PTRDIFF_TYPE__ ptrdiff_t;
14+
1615
#endif

clang/lib/Headers/__stddef_rsize_t.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(_RSIZE_T) || __has_feature(modules)
11-
/* Always define rsize_t when modules are available. */
12-
#if !__has_feature(modules)
10+
#ifndef _RSIZE_T
1311
#define _RSIZE_T
14-
#endif
12+
1513
typedef __SIZE_TYPE__ rsize_t;
14+
1615
#endif

clang/lib/Headers/__stddef_size_t.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(_SIZE_T) || __has_feature(modules)
11-
/* Always define size_t when modules are available. */
12-
#if !__has_feature(modules)
10+
#ifndef _SIZE_T
1311
#define _SIZE_T
14-
#endif
12+
1513
typedef __SIZE_TYPE__ size_t;
14+
1615
#endif

clang/lib/Headers/__stddef_unreachable.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(unreachable) || __has_feature(modules)
11-
/* Always define unreachable when modules are available. */
10+
#ifndef unreachable
1211
#define unreachable() __builtin_unreachable()
1312
#endif

clang/lib/Headers/__stddef_wchar_t.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
*/
99

1010
#if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
11-
/* Always define wchar_t when modules are available. */
12-
#if !defined(_WCHAR_T) || __has_feature(modules)
13-
#if !__has_feature(modules)
11+
12+
#ifndef _WCHAR_T
1413
#define _WCHAR_T
15-
#if defined(_MSC_EXTENSIONS)
14+
15+
#ifdef _MSC_EXTENSIONS
1616
#define _WCHAR_T_DEFINED
1717
#endif
18-
#endif
18+
1919
typedef __WCHAR_TYPE__ wchar_t;
20+
2021
#endif
22+
2123
#endif

clang/lib/Headers/__stddef_wint_t.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
/* Always define wint_t when modules are available. */
11-
#if !defined(_WINT_T) || __has_feature(modules)
12-
#if !__has_feature(modules)
10+
#ifndef _WINT_T
1311
#define _WINT_T
14-
#endif
12+
1513
typedef __WINT_TYPE__ wint_t;
14+
1615
#endif

clang/lib/Headers/module.modulemap

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,164 @@ module _Builtin_intrinsics [system] [extern_c] {
153153
}
154154
}
155155

156-
module _Builtin_stddef_max_align_t [system] [extern_c] {
157-
header "__stddef_max_align_t.h"
156+
// Start -fbuiltin-headers-in-system-modules affected modules
157+
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.
161+
162+
// e.g. if -fbuiltin-headers-in-system-modules is passed, then
163+
// float.h will not be in the _Builtin_float module (that module
164+
// will be empty). If there is a system module that declares
165+
// `header "float.h"`, then the builtin float.h will join
166+
// that module. The system float.h (if present) will be treated
167+
// as a textual header in the sytem module.
168+
module _Builtin_float [system] {
169+
header "float.h"
170+
export *
171+
}
172+
173+
module _Builtin_inttypes [system] {
174+
header "inttypes.h"
175+
export *
176+
}
177+
178+
module _Builtin_iso646 [system] {
179+
header "iso646.h"
180+
export *
181+
}
182+
183+
module _Builtin_limits [system] {
184+
header "limits.h"
185+
export *
186+
}
187+
188+
module _Builtin_stdalign [system] {
189+
header "stdalign.h"
190+
export *
191+
}
192+
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.
198+
module _Builtin_stdarg [system] {
199+
textual header "stdarg.h"
200+
201+
explicit module __gnuc_va_list {
202+
header "__stdarg___gnuc_va_list.h"
203+
export *
204+
}
205+
206+
explicit module __va_copy {
207+
header "__stdarg___va_copy.h"
208+
export *
209+
}
210+
211+
explicit module va_arg {
212+
header "__stdarg_va_arg.h"
213+
export *
214+
}
215+
216+
explicit module va_copy {
217+
header "__stdarg_va_copy.h"
218+
export *
219+
}
220+
221+
explicit module va_list {
222+
header "__stdarg_va_list.h"
223+
export *
224+
}
225+
}
226+
227+
module _Builtin_stdatomic [system] {
228+
header "stdatomic.h"
229+
export *
230+
}
231+
232+
module _Builtin_stdbool [system] {
233+
header "stdbool.h"
234+
export *
235+
}
236+
237+
module _Builtin_stddef [system] {
238+
textual header "stddef.h"
239+
240+
explicit module max_align_t {
241+
header "__stddef_max_align_t.h"
242+
export *
243+
}
244+
245+
explicit module null {
246+
header "__stddef_null.h"
247+
export *
248+
}
249+
250+
explicit module nullptr_t {
251+
header "__stddef_nullptr_t.h"
252+
export *
253+
}
254+
255+
explicit module offsetof {
256+
header "__stddef_offsetof.h"
257+
export *
258+
}
259+
260+
explicit module ptrdiff_t {
261+
header "__stddef_ptrdiff_t.h"
262+
export *
263+
}
264+
265+
explicit module rsize_t {
266+
header "__stddef_rsize_t.h"
267+
export *
268+
}
269+
270+
explicit module size_t {
271+
header "__stddef_size_t.h"
272+
export *
273+
}
274+
275+
explicit module unreachable {
276+
header "__stddef_unreachable.h"
277+
export *
278+
}
279+
280+
explicit module wchar_t {
281+
header "__stddef_wchar_t.h"
282+
export *
283+
}
284+
}
285+
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. */
289+
module _Builtin_stddef_wint_t [system] {
290+
header "__stddef_wint_t.h"
291+
export *
292+
}
293+
294+
module _Builtin_stdint [system] {
295+
header "stdint.h"
296+
export *
297+
}
298+
299+
module _Builtin_stdnoreturn [system] {
300+
header "stdnoreturn.h"
301+
export *
302+
}
303+
304+
module _Builtin_tgmath [system] {
305+
header "tgmath.h"
306+
export *
307+
}
308+
309+
module _Builtin_unwind [system] {
310+
header "unwind.h"
311+
export *
158312
}
313+
// End -fbuiltin-headers-in-system-modules affected modules
159314

160315
module opencl_c {
161316
requires opencl

clang/lib/Headers/stdarg.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,31 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#if !defined(__STDARG_H) || defined(__need___va_list) || \
11-
defined(__need_va_list) || defined(__need_va_arg) || \
12-
defined(__need___va_copy) || defined(__need_va_copy)
10+
/*
11+
* This header is designed to be included multiple times. If any of the __need_
12+
* macros are defined, then only that subset of interfaces are provided. This
13+
* can be useful for POSIX headers that need to not expose all of stdarg.h, but
14+
* need to use some of its interfaces. Otherwise this header provides all of
15+
* the expected interfaces.
16+
*
17+
* When clang modules are enabled, this header is a textual header. It ignores
18+
* its header guard so that multiple submodules can export its interfaces.
19+
* Take module SM with submodules A and B, whose headers both include stdarg.h
20+
* When SM.A builds, __STDARG_H will be defined. When SM.B builds, the
21+
* definition from SM.A will leak when building without local submodule
22+
* visibility. stdarg.h wouldn't include any of its implementation headers, and
23+
* SM.B wouldn't import any of the stdarg modules, and SM.B's `export *`
24+
* wouldn't export any stdarg interfaces as expected. However, since stdarg.h
25+
* ignores its header guard when building with modules, it all works as
26+
* expected.
27+
*
28+
* When clang modules are not enabled, the header guards can function in the
29+
* normal simple fashion.
30+
*/
31+
#if !defined(__STDARG_H) || __has_feature(modules) || \
32+
defined(__need___va_list) || defined(__need_va_list) || \
33+
defined(__need_va_arg) || defined(__need___va_copy) || \
34+
defined(__need_va_copy)
1335

1436
#if !defined(__need___va_list) && !defined(__need_va_list) && \
1537
!defined(__need_va_arg) && !defined(__need___va_copy) && \

0 commit comments

Comments
 (0)