[clang] 9a7a6dd - [Modules] Make clang modules for the C standard library headers

Ian Anderson via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 3 12:41:18 PDT 2023


Author: Ian Anderson
Date: 2023-10-03T12:41:11-07:00
New Revision: 9a7a6dd3c358ca7becef75c0a9581dcfa3e6b5f4

URL: https://github.com/llvm/llvm-project/commit/9a7a6dd3c358ca7becef75c0a9581dcfa3e6b5f4
DIFF: https://github.com/llvm/llvm-project/commit/9a7a6dd3c358ca7becef75c0a9581dcfa3e6b5f4.diff

LOG: [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

Added: 
    clang/test/Modules/Inputs/System/usr/include/complex.h
    clang/test/Modules/Inputs/System/usr/include/inttypes.h
    clang/test/Modules/Inputs/System/usr/include/math.h

Modified: 
    clang/lib/Basic/Module.cpp
    clang/lib/Headers/__stddef_max_align_t.h
    clang/lib/Headers/__stddef_null.h
    clang/lib/Headers/__stddef_nullptr_t.h
    clang/lib/Headers/__stddef_offsetof.h
    clang/lib/Headers/__stddef_ptrdiff_t.h
    clang/lib/Headers/__stddef_rsize_t.h
    clang/lib/Headers/__stddef_size_t.h
    clang/lib/Headers/__stddef_unreachable.h
    clang/lib/Headers/__stddef_wchar_t.h
    clang/lib/Headers/__stddef_wint_t.h
    clang/lib/Headers/module.modulemap
    clang/lib/Headers/stdarg.h
    clang/lib/Headers/stddef.h
    clang/test/Headers/stdarg.c
    clang/test/Headers/stdargneeds.c
    clang/test/Headers/stddef.c
    clang/test/Headers/stddefneeds.c
    clang/test/Modules/Inputs/System/usr/include/module.map
    clang/test/Modules/Inputs/System/usr/include/stdint.h
    clang/test/Modules/compiler_builtins.m
    clang/test/Modules/stddef.c
    clang/test/Modules/stddef.m

Removed: 
    


################################################################################
diff  --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 0455304ef7f2b1a..0fd9c1dca39984d 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -299,8 +299,9 @@ bool Module::directlyUses(const Module *Requested) {
     if (Requested->isSubModuleOf(Use))
       return true;
 
-  // Anyone is allowed to use our builtin stddef.h and its accompanying module.
-  if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
+  // Anyone is allowed to use our builtin stdarg.h and stddef.h and their
+  // accompanying modules.
+  if (!Requested->Parent && (Requested->Name == "_Builtin_stdarg" || Requested->Name == "_Builtin_stddef"))
     return true;
 
   if (NoUndeclaredIncludes)

diff  --git a/clang/lib/Headers/__stddef_max_align_t.h b/clang/lib/Headers/__stddef_max_align_t.h
index e3b439285d0fd08..512606a877288bf 100644
--- a/clang/lib/Headers/__stddef_max_align_t.h
+++ b/clang/lib/Headers/__stddef_max_align_t.h
@@ -1,4 +1,4 @@
-/*===---- __stddef_max_align_t.h - Definition of max_align_t for modules ---===
+/*===---- __stddef_max_align_t.h - Definition of max_align_t ---------------===
  *
  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  * See https://llvm.org/LICENSE.txt for license information.

diff  --git a/clang/lib/Headers/__stddef_null.h b/clang/lib/Headers/__stddef_null.h
index 77d7a54025380b6..7336fdab389723d 100644
--- a/clang/lib/Headers/__stddef_null.h
+++ b/clang/lib/Headers/__stddef_null.h
@@ -7,7 +7,15 @@
  *===-----------------------------------------------------------------------===
  */
 
+#if !defined(NULL) || !__has_feature(modules)
+
+/* linux/stddef.h will define NULL to 0. glibc (and other) headers then define
+ * __need_NULL and rely on stddef.h to redefine NULL to the correct value again.
+ * Modules don't support redefining macros like that, but support that pattern
+ * in the non-modules case.
+ */
 #undef NULL
+
 #ifdef __cplusplus
 #if !defined(__MINGW32__) && !defined(_MSC_VER)
 #define NULL __null
@@ -17,3 +25,5 @@
 #else
 #define NULL ((void*)0)
 #endif
+
+#endif

diff  --git a/clang/lib/Headers/__stddef_nullptr_t.h b/clang/lib/Headers/__stddef_nullptr_t.h
index 8d23ed6dc8c697b..183d394d56c1b70 100644
--- a/clang/lib/Headers/__stddef_nullptr_t.h
+++ b/clang/lib/Headers/__stddef_nullptr_t.h
@@ -7,11 +7,9 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(_NULLPTR_T) || __has_feature(modules)
-/* Always define nullptr_t when modules are available. */
-#if !__has_feature(modules)
+#ifndef _NULLPTR_T
 #define _NULLPTR_T
-#endif
+
 #ifdef __cplusplus
 #if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED)
 namespace std {
@@ -19,7 +17,8 @@ typedef decltype(nullptr) nullptr_t;
 }
 using ::std::nullptr_t;
 #endif
-#else
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
 typedef typeof(nullptr) nullptr_t;
 #endif
+
 #endif

diff  --git a/clang/lib/Headers/__stddef_offsetof.h b/clang/lib/Headers/__stddef_offsetof.h
index 84af8357c285b51..3b347b3b92f62ce 100644
--- a/clang/lib/Headers/__stddef_offsetof.h
+++ b/clang/lib/Headers/__stddef_offsetof.h
@@ -7,7 +7,6 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(offsetof) || __has_feature(modules)
-/* Always define offsetof when modules are available. */
+#ifndef offsetof
 #define offsetof(t, d) __builtin_offsetof(t, d)
 #endif

diff  --git a/clang/lib/Headers/__stddef_ptr
diff _t.h b/clang/lib/Headers/__stddef_ptr
diff _t.h
index 853cee5e09799bc..3ea6d7d2852e1cc 100644
--- a/clang/lib/Headers/__stddef_ptr
diff _t.h
+++ b/clang/lib/Headers/__stddef_ptr
diff _t.h
@@ -7,10 +7,9 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(_PTRDIFF_T) || __has_feature(modules)
-/* Always define ptr
diff _t when modules are available. */
-#if !__has_feature(modules)
+#ifndef _PTRDIFF_T
 #define _PTRDIFF_T
-#endif
+
 typedef __PTRDIFF_TYPE__ ptr
diff _t;
+
 #endif

diff  --git a/clang/lib/Headers/__stddef_rsize_t.h b/clang/lib/Headers/__stddef_rsize_t.h
index f9c31cf8f9746a6..b6428d0c12b62ae 100644
--- a/clang/lib/Headers/__stddef_rsize_t.h
+++ b/clang/lib/Headers/__stddef_rsize_t.h
@@ -7,10 +7,9 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(_RSIZE_T) || __has_feature(modules)
-/* Always define rsize_t when modules are available. */
-#if !__has_feature(modules)
+#ifndef _RSIZE_T
 #define _RSIZE_T
-#endif
+
 typedef __SIZE_TYPE__ rsize_t;
+
 #endif

diff  --git a/clang/lib/Headers/__stddef_size_t.h b/clang/lib/Headers/__stddef_size_t.h
index b30e245e0eb5c91..e4a389510bcdbf3 100644
--- a/clang/lib/Headers/__stddef_size_t.h
+++ b/clang/lib/Headers/__stddef_size_t.h
@@ -7,10 +7,9 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(_SIZE_T) || __has_feature(modules)
-/* Always define size_t when modules are available. */
-#if !__has_feature(modules)
+#ifndef _SIZE_T
 #define _SIZE_T
-#endif
+
 typedef __SIZE_TYPE__ size_t;
+
 #endif

diff  --git a/clang/lib/Headers/__stddef_unreachable.h b/clang/lib/Headers/__stddef_unreachable.h
index 5252932cd27698f..3e7fe01979662af 100644
--- a/clang/lib/Headers/__stddef_unreachable.h
+++ b/clang/lib/Headers/__stddef_unreachable.h
@@ -7,7 +7,6 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(unreachable) || __has_feature(modules)
-/* Always define unreachable when modules are available. */
+#ifndef unreachable
 #define unreachable() __builtin_unreachable()
 #endif

diff  --git a/clang/lib/Headers/__stddef_wchar_t.h b/clang/lib/Headers/__stddef_wchar_t.h
index c3f0516a4b1edf5..16a6186512c0c35 100644
--- a/clang/lib/Headers/__stddef_wchar_t.h
+++ b/clang/lib/Headers/__stddef_wchar_t.h
@@ -8,14 +8,16 @@
  */
 
 #if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED)
-/* Always define wchar_t when modules are available. */
-#if !defined(_WCHAR_T) || __has_feature(modules)
-#if !__has_feature(modules)
+
+#ifndef _WCHAR_T
 #define _WCHAR_T
-#if defined(_MSC_EXTENSIONS)
+
+#ifdef _MSC_EXTENSIONS
 #define _WCHAR_T_DEFINED
 #endif
-#endif
+
 typedef __WCHAR_TYPE__ wchar_t;
+
 #endif
+
 #endif

diff  --git a/clang/lib/Headers/__stddef_wint_t.h b/clang/lib/Headers/__stddef_wint_t.h
index d0582ef971efdad..0aa2915079571ac 100644
--- a/clang/lib/Headers/__stddef_wint_t.h
+++ b/clang/lib/Headers/__stddef_wint_t.h
@@ -7,10 +7,9 @@
  *===-----------------------------------------------------------------------===
  */
 
-/* Always define wint_t when modules are available. */
-#if !defined(_WINT_T) || __has_feature(modules)
-#if !__has_feature(modules)
+#ifndef _WINT_T
 #define _WINT_T
-#endif
+
 typedef __WINT_TYPE__ wint_t;
+
 #endif

diff  --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap
index 6894672ef0529b8..a786689d391773c 100644
--- a/clang/lib/Headers/module.modulemap
+++ b/clang/lib/Headers/module.modulemap
@@ -153,9 +153,164 @@ module _Builtin_intrinsics [system] [extern_c] {
   }
 }
 
-module _Builtin_stddef_max_align_t [system] [extern_c] {
-  header "__stddef_max_align_t.h"
+// Start -fbuiltin-headers-in-system-modules affected modules
+
+// The following modules all ignore their top level headers
+// when -fbuiltin-headers-in-system-modules is passed, and
+// most of those headers join system modules when present.
+
+// e.g. if -fbuiltin-headers-in-system-modules is passed, then
+// float.h will not be in the _Builtin_float module (that module
+// will be empty). If there is a system module that declares
+// `header "float.h"`, then the builtin float.h will join
+// that module. The system float.h (if present) will be treated
+// as a textual header in the sytem module.
+module _Builtin_float [system] {
+  header "float.h"
+  export *
+}
+
+module _Builtin_inttypes [system] {
+  header "inttypes.h"
+  export *
+}
+
+module _Builtin_iso646 [system] {
+  header "iso646.h"
+  export *
+}
+
+module _Builtin_limits [system] {
+  header "limits.h"
+  export *
+}
+
+module _Builtin_stdalign [system] {
+  header "stdalign.h"
+  export *
+}
+
+// When -fbuiltin-headers-in-system-modules is passed, only
+// the top level headers are removed, the implementation headers
+// will always be in their submodules. That means when stdarg.h
+// is included, it will still import this module and make the
+// appropriate submodules visible.
+module _Builtin_stdarg [system] {
+  textual header "stdarg.h"
+
+  explicit module __gnuc_va_list {
+    header "__stdarg___gnuc_va_list.h"
+    export *
+  }
+
+  explicit module __va_copy {
+    header "__stdarg___va_copy.h"
+    export *
+  }
+
+  explicit module va_arg {
+    header "__stdarg_va_arg.h"
+    export *
+  }
+
+  explicit module va_copy {
+    header "__stdarg_va_copy.h"
+    export *
+  }
+
+  explicit module va_list {
+    header "__stdarg_va_list.h"
+    export *
+  }
+}
+
+module _Builtin_stdatomic [system] {
+  header "stdatomic.h"
+  export *
+}
+
+module _Builtin_stdbool [system] {
+  header "stdbool.h"
+  export *
+}
+
+module _Builtin_stddef [system] {
+  textual header "stddef.h"
+
+  explicit module max_align_t {
+    header "__stddef_max_align_t.h"
+    export *
+  }
+
+  explicit module null {
+    header "__stddef_null.h"
+    export *
+  }
+
+  explicit module nullptr_t {
+    header "__stddef_nullptr_t.h"
+    export *
+  }
+
+  explicit module offsetof {
+    header "__stddef_offsetof.h"
+    export *
+  }
+
+  explicit module ptr
diff _t {
+    header "__stddef_ptr
diff _t.h"
+    export *
+  }
+
+  explicit module rsize_t {
+    header "__stddef_rsize_t.h"
+    export *
+  }
+
+  explicit module size_t {
+    header "__stddef_size_t.h"
+    export *
+  }
+
+  explicit module unreachable {
+    header "__stddef_unreachable.h"
+    export *
+  }
+
+  explicit module wchar_t {
+    header "__stddef_wchar_t.h"
+    export *
+  }
+}
+
+/* wint_t is provided by <wchar.h> and not <stddef.h>. It's here
+ * for compatibility, but must be explicitly requested. Therefore
+ * __stddef_wint_t.h is not part of _Builtin_stddef. */
+module _Builtin_stddef_wint_t [system] {
+  header "__stddef_wint_t.h"
+  export *
+}
+
+module _Builtin_stdint [system] {
+  header "stdint.h"
+  export *
+}
+
+module _Builtin_stdnoreturn [system] {
+  header "stdnoreturn.h"
+  export *
+}
+
+module _Builtin_tgmath [system] {
+  header "tgmath.h"
+  export *
+}
+
+module _Builtin_unwind [system] {
+  header "unwind.h"
+  export *
 }
+// End -fbuiltin-headers-in-system-modules affected modules
 
 module opencl_c {
   requires opencl

diff  --git a/clang/lib/Headers/stdarg.h b/clang/lib/Headers/stdarg.h
index 085e2bb861ceb5c..94b066566f084e3 100644
--- a/clang/lib/Headers/stdarg.h
+++ b/clang/lib/Headers/stdarg.h
@@ -7,9 +7,31 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(__STDARG_H) || defined(__need___va_list) ||                       \
-    defined(__need_va_list) || defined(__need_va_arg) ||                       \
-    defined(__need___va_copy) || defined(__need_va_copy)
+/*
+ * This header is designed to be included multiple times. If any of the __need_
+ * macros are defined, then only that subset of interfaces are provided. This
+ * can be useful for POSIX headers that need to not expose all of stdarg.h, but
+ * need to use some of its interfaces. Otherwise this header provides all of
+ * the expected interfaces.
+ *
+ * When clang modules are enabled, this header is a textual header. It ignores
+ * its header guard so that multiple submodules can export its interfaces.
+ * Take module SM with submodules A and B, whose headers both include stdarg.h
+ * When SM.A builds, __STDARG_H will be defined. When SM.B builds, the
+ * definition from SM.A will leak when building without local submodule
+ * visibility. stdarg.h wouldn't include any of its implementation headers, and
+ * SM.B wouldn't import any of the stdarg modules, and SM.B's `export *`
+ * wouldn't export any stdarg interfaces as expected. However, since stdarg.h
+ * ignores its header guard when building with modules, it all works as
+ * expected.
+ *
+ * When clang modules are not enabled, the header guards can function in the
+ * normal simple fashion.
+ */
+#if !defined(__STDARG_H) || __has_feature(modules) ||                          \
+    defined(__need___va_list) || defined(__need_va_list) ||                    \
+    defined(__need_va_arg) || defined(__need___va_copy) ||                     \
+    defined(__need_va_copy)
 
 #if !defined(__need___va_list) && !defined(__need_va_list) &&                  \
     !defined(__need_va_arg) && !defined(__need___va_copy) &&                   \

diff  --git a/clang/lib/Headers/stddef.h b/clang/lib/Headers/stddef.h
index 9c6dd0cd62dae1f..e0ad7b8d17aff93 100644
--- a/clang/lib/Headers/stddef.h
+++ b/clang/lib/Headers/stddef.h
@@ -7,23 +7,41 @@
  *===-----------------------------------------------------------------------===
  */
 
-#if !defined(__STDDEF_H) || defined(__need_ptr
diff _t) ||                       \
-    defined(__need_size_t) || defined(__need_rsize_t) ||                       \
-    defined(__need_wchar_t) || defined(__need_NULL) ||                         \
-    defined(__need_nullptr_t) || defined(__need_unreachable) ||                \
-    defined(__need_max_align_t) || defined(__need_offsetof) ||                 \
-    defined(__need_wint_t) ||                                                  \
-    (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1)
+/*
+ * This header is designed to be included multiple times. If any of the __need_
+ * macros are defined, then only that subset of interfaces are provided. This
+ * can be useful for POSIX headers that need to not expose all of stddef.h, but
+ * need to use some of its interfaces. Otherwise this header provides all of
+ * the expected interfaces.
+ *
+ * When clang modules are enabled, this header is a textual header. It ignores
+ * its header guard so that multiple submodules can export its interfaces.
+ * Take module SM with submodules A and B, whose headers both include stddef.h
+ * When SM.A builds, __STDDEF_H will be defined. When SM.B builds, the
+ * definition from SM.A will leak when building without local submodule
+ * visibility. stddef.h wouldn't include any of its implementation headers, and
+ * SM.B wouldn't import any of the stddef modules, and SM.B's `export *`
+ * wouldn't export any stddef interfaces as expected. However, since stddef.h
+ * ignores its header guard when building with modules, it all works as
+ * expected.
+ *
+ * When clang modules are not enabled, the header guards can function in the
+ * normal simple fashion.
+ */
+#if !defined(__STDDEF_H) || __has_feature(modules) ||                          \
+    (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1) ||        \
+    defined(__need_ptr
diff _t) || defined(__need_size_t) ||                     \
+    defined(__need_rsize_t) || defined(__need_wchar_t) ||                      \
+    defined(__need_NULL) || defined(__need_nullptr_t) ||                       \
+    defined(__need_unreachable) || defined(__need_max_align_t) ||              \
+    defined(__need_offsetof) || defined(__need_wint_t)
 
 #if !defined(__need_ptr
diff _t) && !defined(__need_size_t) &&                   \
     !defined(__need_rsize_t) && !defined(__need_wchar_t) &&                    \
     !defined(__need_NULL) && !defined(__need_nullptr_t) &&                     \
     !defined(__need_unreachable) && !defined(__need_max_align_t) &&            \
     !defined(__need_offsetof) && !defined(__need_wint_t)
-/* Always define miscellaneous pieces when modules are available. */
-#if !__has_feature(modules)
 #define __STDDEF_H
-#endif
 #define __need_ptr
diff _t
 #define __need_size_t
 /* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is

diff  --git a/clang/test/Headers/stdarg.c b/clang/test/Headers/stdarg.c
index 49df42caa3300aa..1c403d109bf7c3f 100644
--- a/clang/test/Headers/stdarg.c
+++ b/clang/test/Headers/stdarg.c
@@ -1,29 +1,47 @@
+// RUN: rm -fR %t
 // RUN: split-file %s %t
 // RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg0.c
 // RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg0.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c89-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdarg0.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c99 %t/stdarg0.c
 // RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg1.c
 // RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg1.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c89-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdarg1.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c99 %t/stdarg1.c
 
 // Split the file so that the "implicitly declaring library function" errors get repeated.
 
 //--- stdarg0.c
 static void f(int p, ...) {
-    __gnuc_va_list g; // c89-error{{undeclared identifier '__gnuc_va_list'}} c99-error{{undeclared identifier}}
-    va_list v; // c89-error{{undeclared identifier 'va_list'}} c99-error{{undeclared identifier}}
+    __gnuc_va_list g; // c89-error{{undeclared identifier '__gnuc_va_list'}} c99-error{{undeclared identifier}} \
+                         c89-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}}
+    va_list v; // c89-error{{undeclared identifier 'va_list'}} c99-error{{undeclared identifier}} \
+                  c89-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}}
     va_start(v, p); // c89-error{{implicitly declaring library function 'va_start'}} c89-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_start'}} c89-error{{undeclared identifier 'v'}} \
-                       c99-error{{call to undeclared library function 'va_start'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}}
+                       c99-error{{call to undeclared library function 'va_start'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} \
+                       c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} c89-modules-error{{undeclared identifier}} \
+                       c99-modules-error{{undeclared library function}} c99-modules-note{{provide a declaration}} c99-modules-error{{undeclared identifier}}
     int i = va_arg(v, int); // c89-error{{implicit declaration of function 'va_arg'}} c89-error{{expected expression}} c89-error{{use of undeclared identifier 'v'}} \
-                               c99-error{{call to undeclared function 'va_arg'}} c99-error{{expected expression}} c99-error{{undeclared identifier}}
+                               c99-error{{call to undeclared function 'va_arg'}} c99-error{{expected expression}} c99-error{{undeclared identifier}} \
+                               c89-modules-error{{implicit declaration of function}} c89-modules-error{{expected expression}} c89-modules-error{{undeclared identifier}} \
+                               c99-modules-error{{undeclared function}} c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}}
     va_end(v); // c89-error{{implicitly declaring library function 'va_end'}} c89-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_end'}} c89-error{{undeclared identifier 'v'}} \
-                  c99-error{{call to undeclared library function 'va_end'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}}
+                  c99-error{{call to undeclared library function 'va_end'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} \
+                  c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} c89-modules-error{{undeclared identifier}} \
+                  c99-modules-error{{undeclared library function}} c99-modules-note{{provide a declaration}} c99-modules-error{{undeclared identifier}}
     __va_copy(g, v); // c89-error{{implicit declaration of function '__va_copy'}} c89-error{{use of undeclared identifier 'g'}} c89-error{{use of undeclared identifier 'v'}} \
-                        c99-error{{call to undeclared function '__va_copy'}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}}
+                        c99-error{{call to undeclared function '__va_copy'}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}} \
+                        c89-modules-error{{implicit declaration of function}} c89-modules-error{{undeclared identifier}} c89-modules-error{{undeclared identifier}} \
+                        c99-modules-error{{undeclared function}} c99-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}}
     va_copy(g, v); // c89-error{{implicitly declaring library function 'va_copy'}} c89-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_copy'}} c89-error{{use of undeclared identifier 'g'}} c89-error{{use of undeclared identifier 'v'}} \
-                      c99-error{{call to undeclared library function 'va_copy'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}}
+                      c99-error{{call to undeclared library function 'va_copy'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}} \
+                      c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} c89-modules-error{{undeclared identifier}} c89-modules-error{{undeclared identifier}} \
+                      c99-modules-error{{undeclared library function}} c99-modules-note{{provide a declaration}} c99-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}}
 }
 
 //--- stdarg1.c
 // c99-no-diagnostics
+// c99-modules-no-diagnostics
 
 #include <stdarg.h>
 static void f(int p, ...) {
@@ -33,5 +51,6 @@ static void f(int p, ...) {
     int i = va_arg(v, int);
     va_end(v);
     __va_copy(g, v);
-    va_copy(g, v); // c89-error{{implicitly declaring library function}} c89-note{{provide a declaration}}
+    va_copy(g, v); // c89-error{{implicitly declaring library function}} c89-note{{provide a declaration}} \
+                      c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}}
 }

diff  --git a/clang/test/Headers/stdargneeds.c b/clang/test/Headers/stdargneeds.c
index 7505ff55731f143..8ef76e90deaef0a 100644
--- a/clang/test/Headers/stdargneeds.c
+++ b/clang/test/Headers/stdargneeds.c
@@ -1,23 +1,35 @@
+// RUN: rm -fR %t
 // RUN: split-file %s %t
 // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds0.c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds0.c
 // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds1.c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds1.c
 // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds2.c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds2.c
 // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds3.c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds3.c
 // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds4.c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds4.c
 // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds5.c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds5.c
 
 // Split the file so that the "implicitly declaring library function" errors get repeated.
 // Use C89 to verify that __need_ can be used to get types that wouldn't normally be available.
 
 //--- stdargneeds0.c
 static void f(int p, ...) {
-    __gnuc_va_list g; // expected-error{{undeclared identifier '__gnuc_va_list'}}
-    va_list v; // expected-error{{undeclared identifier 'va_list'}}
-    va_start(v, p); // expected-error{{implicitly declaring library function 'va_start'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_start'}} expected-error{{undeclared identifier 'v'}}
-    int i = va_arg(v, int); // expected-error{{implicit declaration of function 'va_arg'}} expected-error{{expected expression}} expected-error{{use of undeclared identifier 'v'}}
-    va_end(v); // expected-error{{implicitly declaring library function 'va_end'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_end'}} expected-error{{undeclared identifier 'v'}}
-    __va_copy(g, v); // expected-error{{implicit declaration of function '__va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}}
-    va_copy(g, v); // expected-error{{implicitly declaring library function 'va_copy'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}}
+    __gnuc_va_list g; // expected-error{{undeclared identifier '__gnuc_va_list'}} expected-modules-error{{undeclared identifier}}
+    va_list v; // expected-error{{undeclared identifier 'va_list'}} expected-modules-error{{undeclared identifier}}
+    va_start(v, p); // expected-error{{implicitly declaring library function 'va_start'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_start'}} expected-error{{undeclared identifier 'v'}} \
+                       expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} expected-modules-error{{undeclared identifier}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function 'va_arg'}} expected-error{{expected expression}} expected-error{{use of undeclared identifier 'v'}} \
+                               expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}} expected-modules-error{{undeclared identifier}}
+    va_end(v); // expected-error{{implicitly declaring library function 'va_end'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_end'}} expected-error{{undeclared identifier 'v'}} \
+                  expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} expected-modules-error{{undeclared identifier}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function '__va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}} \
+                        expected-modules-error{{implicit declaration of function}} expected-modules-error{{undeclared identifier}} expected-modules-error{{undeclared identifier}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function 'va_copy'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}} \
+                      expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} expected-modules-error{{undeclared identifier}} expected-modules-error{{undeclared identifier}}
 }
 
 //--- stdargneeds1.c
@@ -25,25 +37,37 @@ static void f(int p, ...) {
 #include <stdarg.h>
 static void f(int p, ...) {
     __gnuc_va_list g;
-    va_list v; // expected-error{{undeclared identifier}}
-    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
-    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} expected-error{{undeclared identifier}}
-    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
-    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
-    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+    va_list v; // expected-error{{undeclared identifier}} \
+                  expected-modules-error{{'va_list' must be declared before it is used}} expected-modules-note at __stdarg_va_list.h:*{{declaration here is not visible}}
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \
+                       expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} expected-error{{undeclared identifier}} \
+                               expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \
+                  expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} \
+                        expected-modules-error{{implicit declaration of function}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \
+                      expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
 }
 
 //--- stdargneeds2.c
 #define __need_va_list
 #include <stdarg.h>
 static void f(int p, ...) {
-    __gnuc_va_list g; // expected-error{{undeclared identifier}}
+    __gnuc_va_list g; // expected-error{{undeclared identifier}} \
+                         expected-modules-error{{'__gnuc_va_list' must be declared before it is used}} expected-modules-note at __stdarg___gnuc_va_list.h:*{{declaration here is not visible}}
     va_list v;
-    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
-    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
-    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
-    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
-    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                       expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} \
+                               expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                  expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} \
+                        expected-modules-error{{implicit declaration of function}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \
+                      expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
 }
 
 //--- stdargneeds3.c
@@ -51,13 +75,16 @@ static void f(int p, ...) {
 #define __need_va_arg
 #include <stdarg.h>
 static void f(int p, ...) {
-    __gnuc_va_list g; // expected-error{{undeclared identifier}}
+    __gnuc_va_list g; // expected-error{{undeclared identifier}} \
+                         expected-modules-error{{'__gnuc_va_list' must be declared before it is used}} expected-modules-note at __stdarg___gnuc_va_list.h:*{{declaration here is not visible}}
     va_list v;
     va_start(v, p);
     int i = va_arg(v, int);
     va_end(v);
-    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
-    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} \
+                        expected-modules-error{{implicit declaration of function}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \
+                      expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
 }
 
 //--- stdargneeds4.c
@@ -68,11 +95,15 @@ static void f(int p, ...) {
 static void f(int p, ...) {
     __gnuc_va_list g;
     va_list v;
-    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
-    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
-    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                       expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} \
+                               expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                  expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
     __va_copy(g, v);
-    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                      expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
 }
 
 //--- stdargneeds5.c
@@ -83,9 +114,12 @@ static void f(int p, ...) {
 static void f(int p, ...) {
     __gnuc_va_list g;
     va_list v;
-    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
-    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
-    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
-    __va_copy(g, v); // expected-error{{implicit declaration of function}}
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                       expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} \
+                               expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \
+                  expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-modules-error{{implicit declaration of function}}
     va_copy(g, v);
 }

diff  --git a/clang/test/Headers/stddef.c b/clang/test/Headers/stddef.c
index d2bceb84a0ba0bd..bf564fb15221aee 100644
--- a/clang/test/Headers/stddef.c
+++ b/clang/test/Headers/stddef.c
@@ -1,35 +1,57 @@
+// RUN: rm -fR %t
 // RUN: %clang_cc1 -fsyntax-only -verify=c99 -std=c99 %s
 // RUN: %clang_cc1 -fsyntax-only -verify=c11 -std=c11 %s
 // RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c99 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c11-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c23-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c23 %s
 
 struct astruct { char member; };
 
-ptr
diff _t p0; // c99-error{{unknown type name 'ptr
diff _t'}} c11-error{{unknown type}} c23-error{{unknown type}}
-size_t s0; // c99-error{{unknown type name 'size_t'}} c11-error{{unknown type}} c23-error{{unknown type}}
-rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c11-error{{unknown type}} c23-error{{unknown type}}
-wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c11-error{{unknown type}} c23-error{{unknown type}}
-void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c11-error{{undeclared identifier}} c23-error{{undeclared identifier}}
-nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c11-error{{unknown type}} c23-error{{unknown type}}
-static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c11-error{{undeclared function}} c23-error{{undeclared identifier}}
-max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c11-error{{unknown type}} c23-error{{unknown type}}
+ptr
diff _t p0; // c99-error{{unknown type name 'ptr
diff _t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+size_t s0; // c99-error{{unknown type name 'size_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+              c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+                c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c11-error{{undeclared identifier}} c23-error{{undeclared identifier}} \
+                    c99-modules-error{{undeclared identifier}} c11-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}}
+nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c11-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c11-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
+max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+                   c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 size_t o0 = offsetof(struct astruct, member); // c99-error{{unknown type name 'size_t'}} c99-error{{call to undeclared function 'offsetof'}} c99-error{{expected expression}} c99-error{{use of undeclared identifier 'member'}} \
                                                  c11-error{{unknown type}} c11-error{{undeclared function}} c11-error{{expected expression}} c11-error{{undeclared identifier}} \
-                                                 c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c11-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{unknown type}} c99-modules-error{{undeclared function}} c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c11-modules-error{{unknown type}} c11-modules-error{{undeclared function}} c11-modules-error{{expected expression}} c11-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{unknown type}} c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type name 'wint_t'}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #include <stddef.h>
 
 ptr
diff _t p1;
 size_t s1;
-rsize_t r1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}}
-            // c99-note at __stddef_size_t.h:*{{'size_t' declared here}} c11-note at __stddef_size_t.h:*{{'size_t' declared here}} c23-note at __stddef_size_t.h:*{{'size_t' declared here}}
+rsize_t r1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} \
+               c99-note at __stddef_size_t.h:*{{'size_t' declared here}} c11-note at __stddef_size_t.h:*{{'size_t' declared here}} c23-note at __stddef_size_t.h:*{{'size_t' declared here}} \
+               c99-modules-error{{'rsize_t' must be declared before it is used}} c11-modules-error{{must be declared}} c23-modules-error{{must be declared}} \
+               c99-modules-note at __stddef_rsize_t.h:*{{declaration here is not visible}} c11-modules-note at __stddef_rsize_t.h:*{{declaration here is not visible}} c23-modules-note at __stddef_rsize_t.h:*{{declaration here is not visible}}
 wchar_t wc1;
 void *v1 = NULL;
-nullptr_t n1; // c99-error{{unknown type}} c11-error{{unknown type}}
-static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}}
-max_align_t m1; // c99-error{{unknown type}}
+nullptr_t n1; // c99-error{{unknown type}} c11-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c11-modules-error{{unknown type}}
+static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}} \
+                                           c99-modules-error{{undeclared function}} c11-modules-error{{undeclared function}}
+max_align_t m1; // c99-error{{unknown type}} c99-modules-error{{'max_align_t' must be declared before it is used}} \
+                   c99-modules-note at __stddef_max_align_t.h:*{{declaration here is not visible}}
 size_t o1 = offsetof(struct astruct, member);
-wint_t wi1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}}
+wint_t wi1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 // rsize_t needs to be opted into via __STDC_WANT_LIB_EXT1__ >= 1.
 #define __STDC_WANT_LIB_EXT1__ 1
@@ -39,8 +61,14 @@ size_t s2;
 rsize_t r2;
 wchar_t wc2;
 void *v2 = NULL;
-nullptr_t n2; // c99-error{{unknown type}} c11-error{{unknown type}}
-static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}}
+nullptr_t n2; // c99-error{{unknown type}} c11-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c11-modules-error{{unknown type}}
+static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}} \
+                                           c99-modules-error{{undeclared function}} c11-modules-error{{undeclared function}}
 max_align_t m2; // c99-error{{unknown type}}
 size_t o2 = offsetof(struct astruct, member);
-wint_t wi2; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}}
+wint_t wi2; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+
+// m2 and wi2 don't generate errors in modules, the "must be declared before used"
+// errors are only emitted the first time the known-but-not-visible type is seen.

diff  --git a/clang/test/Headers/stddefneeds.c b/clang/test/Headers/stddefneeds.c
index dd7ecd0e6028da4..fae7d7041d6af5c 100644
--- a/clang/test/Headers/stddefneeds.c
+++ b/clang/test/Headers/stddefneeds.c
@@ -1,36 +1,72 @@
+// RUN: rm -fR %t
 // RUN: %clang_cc1 -fsyntax-only -verify=c99 -std=c99 %s
 // RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c99 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c23-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c23 %s
 
 // Use C99 to verify that __need_ can be used to get types that wouldn't normally be available.
 
 struct astruct { char member; };
 
-ptr
diff _t p0; // c99-error{{unknown type name 'ptr
diff _t'}} c23-error{{unknown type}}
-size_t s0; // c99-error{{unknown type name 'size_t'}} c23-error{{unknown type}}
-rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c23-error{{unknown type}}
-wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c23-error{{unknown type}}
-void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c23-error{{undeclared identifier}}
-nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c23-error{{unknown type}}
-static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c23-error{{undeclared identifier 'unreachable'}}
-max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c23-error{{unknown type}}
+ptr
diff _t p0; // c99-error{{unknown type name 'ptr
diff _t'}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+size_t s0; // c99-error{{unknown type name 'size_t'}} c23-error{{unknown type}} \
+              c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c23-error{{unknown type}} \
+                c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c23-error{{undeclared identifier}} \
+                    c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}}
+nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c23-error{{undeclared identifier 'unreachable'}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
+max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c23-error{{unknown type}} \
+                   c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 size_t o0 = offsetof(struct astruct, member); // c99-error{{unknown type name 'size_t'}} c99-error{{call to undeclared function 'offsetof'}} c99-error{{expected expression}} c99-error{{use of undeclared identifier 'member'}} \
-                                                 c23-error{{unknown type name 'size_t'}} c23-error{{undeclared identifier 'offsetof'}} c23-error{{expected expression}} c23-error{{use of undeclared identifier 'member'}}
-wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c23-error{{unknown type}}
+                                                 c23-error{{unknown type name 'size_t'}} c23-error{{undeclared identifier 'offsetof'}} c23-error{{expected expression}} c23-error{{use of undeclared identifier 'member'}} \
+                                                 c99-modules-error{{unknown type}} c99-modules-error{{undeclared function}} c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{unknown type}} c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_ptr
diff _t
 #include <stddef.h>
 
 ptr
diff _t p1;
-size_t s1; // c99-error{{unknown type}} c23-error{{unknown type}}
-rsize_t r1; // c99-error{{unknown type}} c23-error{{unknown type}}
-wchar_t wc1; // c99-error{{unknown type}} c23-error{{unknown type}}
-void *v1 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}}
-nullptr_t n1; // c99-error{{unknown type}} c23-error{{unknown type}}
-static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}}
-max_align_t m1; // c99-error{{unknown type}} c23-error{{unknown type}}
+size_t s1; // c99-error{{unknown type}} c23-error{{unknown type}} \
+              c99-modules-error{{'size_t' must be declared before it is used}} c23-modules-error{{must be declared}} \
+              c99-modules-note at __stddef_size_t.h:*{{declaration here is not visible}} c23-modules-note at __stddef_size_t.h:*{{declaration here is not visible}}
+rsize_t r1; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{'rsize_t' must be declared before it is used}} c23-modules-error{{must be declared}} \
+               c99-modules-note at __stddef_rsize_t.h:*{{declaration here is not visible}} c23-modules-note at __stddef_rsize_t.h:*{{declaration here is not visible}}
+wchar_t wc1; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                c99-modules-error{{'wchar_t' must be declared before it is used}} c23-modules-error{{must be declared}} \
+                c99-modules-note at __stddef_wchar_t.h:*{{declaration here is not visible}} c23-modules-note at __stddef_wchar_t.h:*{{declaration here is not visible}}
+void *v1 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \
+                    c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}}
+nullptr_t n1; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}} c23-modules-error{{'nullptr_t' must be declared before it is used}} \
+                 c23-modules-note at __stddef_nullptr_t.h:*{{declaration here is not visible}}
+static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
+max_align_t m1; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                   c99-modules-error{{'max_align_t' must be declared before it is used}} c23-modules-error{{must be declared}} \
+                   c99-modules-note at __stddef_max_align_t.h:*{{declaration here is not visible}} c23-modules-note at __stddef_max_align_t.h:*{{declaration here is not visible}}
 size_t o1 = offsetof(struct astruct, member); // c99-error{{unknown type}} c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi1; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi1; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
+
+// The "must be declared before used" 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>
@@ -40,13 +76,19 @@ size_t s2;
 rsize_t r2; // c99-error{{unknown type}} c23-error{{unknown type}}
             // c99-note at __stddef_size_t.h:*{{'size_t' declared here}} c23-note at __stddef_size_t.h:*{{'size_t' declared here}}
 wchar_t wc2; // c99-error{{unknown type}} c23-error{{unknown type}}
-void *v2 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}}
-nullptr_t n2; // c99-error{{unknown type}} c23-error{{unknown type}}
-static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}}
+void *v2 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \
+                    c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}}
+nullptr_t n2; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}}
+static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
 max_align_t m2; // c99-error{{unknown type}} c23-error{{unknown type}}
 size_t o2 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi2; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi2; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_rsize_t
 #include <stddef.h>
@@ -55,13 +97,19 @@ ptr
diff _t p3;
 size_t s3;
 rsize_t r3;
 wchar_t wc3; // c99-error{{unknown type}} c23-error{{unknown type}}
-void *v3 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}}
-nullptr_t n3; // c99-error{{unknown type}} c23-error{{unknown type}}
-static void f3(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}}
+void *v3 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \
+                    c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}}
+nullptr_t n3; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}}
+static void f3(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
 max_align_t m3; // c99-error{{unknown type}} c23-error{{unknown type}}
 size_t o3 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi3; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi3; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_wchar_t
 #include <stddef.h>
@@ -70,13 +118,19 @@ ptr
diff _t p4;
 size_t s4;
 rsize_t r4;
 wchar_t wc4;
-void *v4 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}}
-nullptr_t n4; // c99-error{{unknown type}} c23-error{{unknown type}}
-static void f4(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}}
+void *v4 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \
+                    c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}}
+nullptr_t n4; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}}
+static void f4(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
 max_align_t m4; // c99-error{{unknown type}} c23-error{{unknown type}}
 size_t o4 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi4; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi4; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_NULL
 #include <stddef.h>
@@ -86,29 +140,38 @@ size_t s5;
 rsize_t r5;
 wchar_t wc5;
 void *v5 = NULL;
-nullptr_t n5; // c99-error{{unknown type}} c23-error{{unknown type}}
-static void f5(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}}
+nullptr_t n5; // c99-error{{unknown type}} c23-error{{unknown type}} \
+                 c99-modules-error{{unknown type}}
+static void f5(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
 max_align_t m5; // c99-error{{unknown type}} c23-error{{unknown type}}
 size_t o5 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi5; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi5; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
-// __need_nullptr_t generates an error in <C23 because its definition
+// nullptr_t doesn't get declared before C23 because its definition
 // depends on nullptr.
 #define __need_nullptr_t
-#include <stddef.h> // c99-error at __stddef_nullptr_t.h:*{{expected function body}}
+#include <stddef.h>
 
 ptr
diff _t p6;
 size_t s6;
 rsize_t r6;
 wchar_t wc6;
 void *v6 = NULL;
-nullptr_t n6; // c99-error{{unknown type}}
-static void f6(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}}
+nullptr_t n6; // c99-error{{unknown type}} c99-modules-error{{unknown type}}
+static void f6(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \
+                                           c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}}
 max_align_t m6; // c99-error{{unknown type}} c23-error{{unknown type}}
 size_t o6 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi6; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi6; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_unreachable
 #include <stddef.h>
@@ -118,12 +181,15 @@ size_t s7;
 rsize_t r7;
 wchar_t wc7;
 void *v7 = NULL;
-nullptr_t n7 ; // c99-error{{unknown type}}
+nullptr_t n7 ; // c99-error{{unknown type}} c99-modules-error{{unknown type}}
 static void f7(void) { unreachable(); }
 max_align_t m7; // c99-error{{unknown type}} c23-error{{unknown type}}
 size_t o7 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi7; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi7; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_max_align_t
 #include <stddef.h>
@@ -133,12 +199,15 @@ size_t s8;
 rsize_t r8;
 wchar_t wc8;
 void *v8 = NULL;
-nullptr_t n8; // c99-error{{unknown type}}
+nullptr_t n8; // c99-error{{unknown type}} c99-modules-error{{unknown type}}
 static void f8(void) { unreachable(); }
 max_align_t m8;
 size_t o8 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \
-                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}}
-wint_t wi8; // c99-error{{unknown type}} c23-error{{unknown type}}
+                                                 c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \
+                                                 c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \
+                                                 c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}}
+wint_t wi8; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_offsetof
 #include <stddef.h>
@@ -146,13 +215,14 @@ wint_t wi8; // c99-error{{unknown type}} c23-error{{unknown type}}
 ptr
diff _t p9;
 size_t s9;
 rsize_t r9;
-nullptr_t n9; // c99-error{{unknown type}}
+nullptr_t n9; // c99-error{{unknown type}} c99-modules-error{{unknown type}}
 static void f9(void) { unreachable(); }
 wchar_t wc9;
 void *v9 = NULL;
 max_align_t m9;
 size_t o9 = offsetof(struct astruct, member);
-wint_t wi9; // c99-error{{unknown type}} c23-error{{unknown type}}
+wint_t wi9; // c99-error{{unknown type}} c23-error{{unknown type}} \
+               c99-modules-error{{unknown type}} c23-modules-error{{unknown type}}
 
 #define __need_wint_t
 #include <stddef.h>
@@ -162,7 +232,7 @@ size_t s10;
 rsize_t r10;
 wchar_t wc10;
 void *v10 = NULL;
-nullptr_t n10; // c99-error{{unknown type}}
+nullptr_t n10; // c99-error{{unknown type}} c99-modules-error{{unknown type}}
 static void f10(void) { unreachable(); }
 max_align_t m10;
 size_t o10 = offsetof(struct astruct, member);

diff  --git a/clang/test/Modules/Inputs/System/usr/include/complex.h b/clang/test/Modules/Inputs/System/usr/include/complex.h
new file mode 100644
index 000000000000000..e69de29bb2d1d64

diff  --git a/clang/test/Modules/Inputs/System/usr/include/inttypes.h b/clang/test/Modules/Inputs/System/usr/include/inttypes.h
new file mode 100644
index 000000000000000..e69de29bb2d1d64

diff  --git a/clang/test/Modules/Inputs/System/usr/include/math.h b/clang/test/Modules/Inputs/System/usr/include/math.h
new file mode 100644
index 000000000000000..e69de29bb2d1d64

diff  --git a/clang/test/Modules/Inputs/System/usr/include/module.map b/clang/test/Modules/Inputs/System/usr/include/module.map
index 1d88ca380f49a50..5a15c70a394d2e2 100644
--- a/clang/test/Modules/Inputs/System/usr/include/module.map
+++ b/clang/test/Modules/Inputs/System/usr/include/module.map
@@ -1,9 +1,24 @@
 module cstd [system] {
+  // Only in system headers directory
+  module complex {
+    header "complex.h"
+  }
+
   // Only in compiler support directory
   module float_constants {
     header "float.h"
   }
 
+  // In both directories (compiler support version wins, forwards)
+  module inttypes {
+    header "inttypes.h"
+  }
+
+  // Only in system headers directory
+  module math {
+    header "math.h"
+  }
+
   // Only in system headers directory
   module stdio {
     header "stdio.h"

diff  --git a/clang/test/Modules/Inputs/System/usr/include/stdint.h b/clang/test/Modules/Inputs/System/usr/include/stdint.h
index e8e50f90290ced7..e3592fe359a4a32 100644
--- a/clang/test/Modules/Inputs/System/usr/include/stdint.h
+++ b/clang/test/Modules/Inputs/System/usr/include/stdint.h
@@ -1 +1,35 @@
+#ifndef STDINT_H
+#define STDINT_H
+
 typedef int my_awesome_nonstandard_integer_type;
+
+// types needed by stdatomic.h
+
+typedef char int_least8_t;
+typedef short int_least16_t;
+typedef int int_least32_t;
+typedef long long int int_least64_t;
+typedef unsigned char uint_least8_t;
+typedef unsigned short uint_least16_t;
+typedef unsigned int uint_least32_t;
+typedef unsigned long long uint_least64_t;
+
+typedef char int_fast8_t;
+typedef short int_fast16_t;
+typedef int int_fast32_t;
+typedef long long int int_fast64_t;
+typedef unsigned char uint_fast8_t;
+typedef unsigned short uint_fast16_t;
+typedef unsigned int uint_fast32_t;
+typedef unsigned long long uint_fast64_t;
+
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+typedef int intmax_t;
+typedef unsigned int uintmax_t;
+
+// additional types for unwind.h
+
+typedef unsigned long long uint64_t;
+
+#endif /* STDINT_H */

diff  --git a/clang/test/Modules/compiler_builtins.m b/clang/test/Modules/compiler_builtins.m
index a5e6315cedc8e6e..8eeb65daa9e8878 100644
--- a/clang/test/Modules/compiler_builtins.m
+++ b/clang/test/Modules/compiler_builtins.m
@@ -1,7 +1,7 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -verify
-// RUN: %clang_cc1 -fsyntax-only -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -verify
-// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%resource_dir/module.modulemap -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -verify
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -internal-isystem %S/Inputs/System/usr/include -verify
+// RUN: %clang_cc1 -fsyntax-only -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -internal-isystem %S/Inputs/System/usr/include -verify
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%resource_dir/module.modulemap -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -DNO_SYSTEM_MODULES -verify
 // expected-no-diagnostics
 
 #ifdef __SSE__
@@ -11,3 +11,19 @@
 #ifdef __AVX2__
 @import _Builtin_intrinsics.intel.avx2;
 #endif
+
+#ifndef NO_SYSTEM_MODULES
+ at import _Builtin_float;
+ at import _Builtin_inttypes;
+ at import _Builtin_iso646;
+ at import _Builtin_limits;
+ at import _Builtin_stdalign;
+ at import _Builtin_stdarg;
+ at import _Builtin_stdatomic;
+ at import _Builtin_stdbool;
+ at import _Builtin_stddef;
+ at import _Builtin_stdint;
+ at import _Builtin_stdnoreturn;
+ at import _Builtin_tgmath;
+ at import _Builtin_unwind;
+#endif

diff  --git a/clang/test/Modules/stddef.c b/clang/test/Modules/stddef.c
index 6704abffbf0b7d3..5bc0d1e44c8563f 100644
--- a/clang/test/Modules/stddef.c
+++ b/clang/test/Modules/stddef.c
@@ -1,13 +1,29 @@
 // RUN: rm -rf %t
 // 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
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery
 
 #include "ptr
diff _t.h"
 
 ptr
diff _t pdt;
 
-size_t st; // expected-error {{missing '#include "include_again.h"'; 'size_t' must be declared before it is used}}
-// expected-note at __stddef_size_t.h:* {{here}}
+// size_t is declared in both size_t.h and __stddef_size_t.h, both of which are
+// modular headers. Regardless of whether stddef.h joins the StdDef test module
+// or is in its _Builtin_stddef module, __stddef_size_t.h will be in
+// _Builtin_stddef.size_t. It's not defined which module will win as the expected
+// provider of size_t. For the purposes of this test it doesn't matter which header
+// gets reported, just as long as it isn't other.h or include_again.h.
+size_t st; // expected-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}}
+// expected-note at size_t.h:* 0+ {{here}}
+// expected-note at __stddef_size_t.h:* 0+ {{here}}
 
 #include "include_again.h"
+// Includes <stddef.h> which includes <__stddef_size_t.h> which imports the
+// _Builtin_stddef.size_t module.
 
 size_t st2;
+
+#include "size_t.h"
+// Redeclares size_t, but the type merger should figure it out.
+
+size_t st3;

diff  --git a/clang/test/Modules/stddef.m b/clang/test/Modules/stddef.m
index 1ff6ff73796abe8..855464afe61af19 100644
--- a/clang/test/Modules/stddef.m
+++ b/clang/test/Modules/stddef.m
@@ -4,4 +4,6 @@
 
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I %S/Inputs/StdDef %s -verify
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/StdDef %s -verify
 // expected-no-diagnostics


        


More information about the cfe-commits mailing list