Skip to content

Commit e956b0d

Browse files
[clang][headers] Including stddef.h always redefines NULL
stddef.h always includes __stddef_null.h. This is fine in modules because it's not possible to re-include the pcm, and it's necessary to export the _Builtin_stddef.null submodule. However, without modules it causes NULL to always get redefined which disrupts some C++ code. Rework the inclusion of __stddef_null.h so that with not building with modules it's only included if __need_NULL is set by the includer, or it's the first time stddef.h is being included.
1 parent a96c906 commit e956b0d

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

clang/lib/Headers/stdarg.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,18 @@
2020
* modules.
2121
*/
2222
#if defined(__MVS__) && __has_include_next(<stdarg.h>)
23-
#include <__stdarg_header_macro.h>
2423
#undef __need___va_list
2524
#undef __need_va_list
2625
#undef __need_va_arg
2726
#undef __need___va_copy
2827
#undef __need_va_copy
28+
#include <__stdarg_header_macro.h>
2929
#include_next <stdarg.h>
3030

3131
#else
3232
#if !defined(__need___va_list) && !defined(__need_va_list) && \
3333
!defined(__need_va_arg) && !defined(__need___va_copy) && \
3434
!defined(__need_va_copy)
35-
#include <__stdarg_header_macro.h>
3635
#define __need___va_list
3736
#define __need_va_list
3837
#define __need_va_arg
@@ -45,6 +44,7 @@
4544
!defined(__STRICT_ANSI__)
4645
#define __need_va_copy
4746
#endif
47+
#include <__stdarg_header_macro.h>
4848
#endif
4949

5050
#ifdef __need___va_list

clang/lib/Headers/stddef.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
* modules.
2121
*/
2222
#if defined(__MVS__) && __has_include_next(<stddef.h>)
23-
#include <__stddef_header_macro.h>
2423
#undef __need_ptrdiff_t
2524
#undef __need_size_t
2625
#undef __need_rsize_t
@@ -31,6 +30,7 @@
3130
#undef __need_max_align_t
3231
#undef __need_offsetof
3332
#undef __need_wint_t
33+
#include <__stddef_header_macro.h>
3434
#include_next <stddef.h>
3535

3636
#else
@@ -40,7 +40,6 @@
4040
!defined(__need_NULL) && !defined(__need_nullptr_t) && \
4141
!defined(__need_unreachable) && !defined(__need_max_align_t) && \
4242
!defined(__need_offsetof) && !defined(__need_wint_t)
43-
#include <__stddef_header_macro.h>
4443
#define __need_ptrdiff_t
4544
#define __need_size_t
4645
/* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is
@@ -49,7 +48,24 @@
4948
#define __need_rsize_t
5049
#endif
5150
#define __need_wchar_t
51+
#if !defined(__STDDEF_H) || __has_feature(modules)
52+
/*
53+
* __stddef_null.h is special when building without modules: if __need_NULL is
54+
* set, then it will unconditionally redefine NULL. To avoid stepping on client
55+
* definitions of NULL, __need_NULL should only be set the first time this
56+
* header is included, that is when __STDDEF_H is not defined. However, when
57+
* building with modules, this header is a textual header and needs to
58+
* unconditionally include __stdef_null.h to support multiple submodules
59+
* exporting _Builtin_stddef.null. Take module SM with submodules A and B, whose
60+
* headers both include stddef.h When SM.A builds, __STDDEF_H will be defined.
61+
* When SM.B builds, the definition from SM.A will leak when building without
62+
* local submodule visibility. stddef.h wouldn't include __stddef_null.h, and
63+
* SM.B wouldn't import _Builtin_stddef.null, and SM.B's `export *` wouldn't
64+
* export NULL as expected. When building with modules, always include
65+
* __stddef_null.h so that everything works as expected.
66+
*/
5267
#define __need_NULL
68+
#endif
5369
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
5470
defined(__cplusplus)
5571
#define __need_nullptr_t
@@ -65,6 +81,7 @@
6581
/* wint_t is provided by <wchar.h> and not <stddef.h>. It's here
6682
* for compatibility, but must be explicitly requested. Therefore
6783
* __need_wint_t is intentionally not defined here. */
84+
#include <__stddef_header_macro.h>
6885
#endif
6986

7087
#if defined(__need_ptrdiff_t)

clang/test/Headers/stddefneeds.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,21 @@ max_align_t m5;
5656
#undef NULL
5757
#define NULL 0
5858

59-
// glibc (and other) headers then define __need_NULL and rely on stddef.h
60-
// to redefine NULL to the correct value again.
61-
#define __need_NULL
59+
// Including stddef.h again shouldn't redefine NULL
6260
#include <stddef.h>
6361

6462
// gtk headers then use __attribute__((sentinel)), which doesn't work if NULL
6563
// is 0.
66-
void f(const char* c, ...) __attribute__((sentinel));
64+
void f(const char* c, ...) __attribute__((sentinel)); // expected-note{{function has been explicitly marked sentinel here}}
6765
void g() {
66+
f("", NULL); // expected-warning{{missing sentinel in function call}}
67+
}
68+
69+
// glibc (and other) headers then define __need_NULL and rely on stddef.h
70+
// to redefine NULL to the correct value again.
71+
#define __need_NULL
72+
#include <stddef.h>
73+
74+
void h() {
6875
f("", NULL); // Shouldn't warn.
6976
}

0 commit comments

Comments
 (0)