| 
 | 1 | +// RUN: rm -rf %t  | 
 | 2 | +// RUN: split-file %s %t  | 
 | 3 | +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/no-lsv -I%t %t/stddef.cpp -verify  | 
 | 4 | +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-local-submodule-visibility -fmodules-cache-path=%t/lsv -I%t %t/stddef.cpp -verify  | 
 | 5 | + | 
 | 6 | +//--- stddef.cpp  | 
 | 7 | +#include <b.h>  | 
 | 8 | + | 
 | 9 | +void *pointer = NULL;  | 
 | 10 | +size_t size = 0;  | 
 | 11 | + | 
 | 12 | +// When building with modules, a pcm is never re-imported, so re-including  | 
 | 13 | +// stddef.h will not re-import _Builtin_stddef.null to restore the definition of  | 
 | 14 | +// NULL, even though stddef.h will unconditionally include __stddef_null.h when  | 
 | 15 | +// building with modules.  | 
 | 16 | +#undef NULL  | 
 | 17 | +#include <stddef.h>  | 
 | 18 | + | 
 | 19 | +void *anotherPointer = NULL; // expected-error{{use of undeclared identifier 'NULL'}}  | 
 | 20 | + | 
 | 21 | +// stddef.h needs to be a `textual` header to support clients doing things like  | 
 | 22 | +// this.  | 
 | 23 | +//  | 
 | 24 | +// #define __need_NULL  | 
 | 25 | +// #include <stddef.h>  | 
 | 26 | +//  | 
 | 27 | +// As a textual header designed to be included multiple times, it can't directly  | 
 | 28 | +// declare anything, or those declarations would go into every module that  | 
 | 29 | +// included it. e.g. if stddef.h contained all of its declarations, and modules  | 
 | 30 | +// A and B included stddef.h, they would both have the declaration for size_t.  | 
 | 31 | +// That breaks Swift, which uses the module name as part of the type name, i.e.  | 
 | 32 | +// A.size_t and B.size_t are treated as completely different types in Swift and  | 
 | 33 | +// cannot be interchanged. To fix that, stddef.h (and stdarg.h) are split out  | 
 | 34 | +// into a separate file per __need macro that can be normal headers in explicit  | 
 | 35 | +// submodules. That runs into yet another wrinkle though. When modules build,  | 
 | 36 | +// declarations from previous submodules leak into subsequent ones when not  | 
 | 37 | +// using local submodule visibility. Consider if stddef.h did the normal thing.  | 
 | 38 | +//  | 
 | 39 | +// #ifndef __STDDEF_H  | 
 | 40 | +// #define __STDDEF_H  | 
 | 41 | +// // include all of the sub-headers  | 
 | 42 | +// #endif  | 
 | 43 | +//  | 
 | 44 | +// When SM builds without local submodule visibility, it will precompile a.h  | 
 | 45 | +// first. When it gets to b.h, the __STDDEF_H declaration from precompiling a.h  | 
 | 46 | +// will leak, and so when b.h includes stddef.h, it won't include any of its  | 
 | 47 | +// sub-headers, and SM.B will thus not import _Builtin_stddef or make any of its  | 
 | 48 | +// submodules visible. Precompiling b.h will be fine since it sees all of the  | 
 | 49 | +// declarations from a.h including stddef.h, but clients that only include b.h  | 
 | 50 | +// will not see any of the stddef.h types. stddef.h thus has to make sure to  | 
 | 51 | +// always include the necessary sub-headers, even if they've been included  | 
 | 52 | +// already. They all have their own header guards to allow this.  | 
 | 53 | +// __stddef_null.h is extra special, so this test makes sure to cover NULL plus  | 
 | 54 | +// one of the normal stddef.h types.  | 
 | 55 | + | 
 | 56 | +//--- module.modulemap  | 
 | 57 | +module SM {  | 
 | 58 | +  module A {  | 
 | 59 | +    header "a.h"  | 
 | 60 | +    export *  | 
 | 61 | +  }  | 
 | 62 | + | 
 | 63 | +  module B {  | 
 | 64 | +    header "b.h"  | 
 | 65 | +    export *  | 
 | 66 | +  }  | 
 | 67 | +}  | 
 | 68 | + | 
 | 69 | +//--- a.h  | 
 | 70 | +#include <stddef.h>  | 
 | 71 | + | 
 | 72 | +//--- b.h  | 
 | 73 | +#include <stddef.h>  | 
0 commit comments