https://github.com/yronglin created 
https://github.com/llvm/llvm-project/pull/144233

This PR is 2nd part of 
[P1857R3](https://github.com/llvm/llvm-project/pull/107168) implementation, and 
mainly implement the restriction `A module directive may only appear as the 
first preprocessing tokens in a file (excluding the global module fragment.)`:
[cpp.pre](https://eel.is/c++draft/cpp.pre):
```
module-file:
    pp-global-module-fragment[opt] pp-module group[opt] 
pp-private-module-fragment[opt]
```

We also refine tests use `split-file` instead of conditional macro.

>From 3346cae130b9fd113f7f7b5a24bc4c84f62c7ae7 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin...@gmail.com>
Date: Sun, 15 Jun 2025 01:16:41 +0800
Subject: [PATCH] [C++][Modules][P1857R3 2]: A module directive may only appear
 as the first preprocessing tokens in a file

Signed-off-by: yronglin <yronglin...@gmail.com>
---
 clang/include/clang/Lex/Lexer.h               |   3 +
 clang/include/clang/Lex/Preprocessor.h        |   5 +
 clang/include/clang/Lex/Token.h               |  12 +-
 clang/include/clang/Sema/Sema.h               |   3 +-
 clang/lib/Lex/Lexer.cpp                       |  10 +
 clang/lib/Parse/Parser.cpp                    |   7 +-
 clang/lib/Sema/SemaModule.cpp                 |  14 +-
 clang/test/CXX/basic/basic.link/p1.cpp        | 143 ++++++++++----
 clang/test/CXX/basic/basic.link/p2.cpp        |  26 +--
 .../basic.scope/basic.scope.namespace/p2.cpp  |  82 ++++++---
 .../CXX/module/basic/basic.def.odr/p6.cppm    | 174 ++++++++++++++----
 .../basic/basic.link/module-declaration.cpp   |  64 ++++---
 .../dcl.module/dcl.module.import/p1.cppm      |  32 +++-
 .../dcl.module/dcl.module.interface/p1.cppm   |  39 ++--
 .../test/CXX/module/dcl.dcl/dcl.module/p1.cpp |  44 +++--
 .../test/CXX/module/dcl.dcl/dcl.module/p5.cpp |  65 +++++--
 clang/test/CXX/module/module.interface/p2.cpp |  26 ++-
 clang/test/CXX/module/module.unit/p8.cpp      |  48 +++--
 clang/test/Driver/modules.cpp                 |  31 ++--
 clang/test/Modules/named-modules-adl-3.cppm   |   1 +
 clang/test/Modules/reserved-names-1.cppm      |  10 +
 .../reserved-names-system-header-1.cpp        |   1 +
 .../reserved-names-system-header-2.cpp        |   1 +
 clang/test/SemaCXX/modules.cppm               |  75 +++++---
 ...-aware-new-delete-transparent-contexts.cpp |  20 +-
 25 files changed, 637 insertions(+), 299 deletions(-)

diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h
index bb65ae010cffa..ca812ba1583fb 100644
--- a/clang/include/clang/Lex/Lexer.h
+++ b/clang/include/clang/Lex/Lexer.h
@@ -143,6 +143,9 @@ class Lexer : public PreprocessorLexer {
   /// True if this is the first time we're lexing the input file.
   bool IsFirstTimeLexingFile;
 
+  /// True if current lexing token is the first pp-token.
+  bool IsFirstPPToken;
+
   // NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
   // it also points to '\n.'
   const char *NewLinePtr;
diff --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index 78be2bd64d61c..436ac783928f4 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -350,6 +350,9 @@ class Preprocessor {
   /// Whether the last token we lexed was an '@'.
   bool LastTokenWasAt = false;
 
+  /// First pp-token in current translation unit.
+  Token FirstPPToken;
+
   /// A position within a C++20 import-seq.
   class StdCXXImportSeq {
   public:
@@ -1766,6 +1769,8 @@ class Preprocessor {
   std::optional<LexEmbedParametersResult> LexEmbedParameters(Token &Current,
                                                              bool ForHasEmbed);
 
+  void setFirstPPToken(const Token &Tok) { FirstPPToken = Tok; }
+  Token getFirstPPToken() const { return FirstPPToken; }
   bool LexAfterModuleImport(Token &Result);
   void CollectPpImportSuffix(SmallVectorImpl<Token> &Toks);
 
diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h
index 4f29fb7d11415..d4dfd7b44d9af 100644
--- a/clang/include/clang/Lex/Token.h
+++ b/clang/include/clang/Lex/Token.h
@@ -86,9 +86,12 @@ class Token {
                                 // macro stringizing or charizing operator.
     CommaAfterElided = 0x200, // The comma following this token was elided 
(MS).
     IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
-    IsReinjected = 0x800, // A phase 4 token that was produced before and
-                          // re-added, e.g. via EnterTokenStream. Annotation
-                          // tokens are *not* reinjected.
+
+    IsReinjected = 0x800,  // A phase 4 token that was produced before and
+                           // re-added, e.g. via EnterTokenStream. Annotation
+                           // tokens are *not* reinjected.
+    FirstPPToken = 0x1000, // This token is the first pp token in the
+                           // translation unit.
   };
 
   tok::TokenKind getKind() const { return Kind; }
@@ -318,6 +321,9 @@ class Token {
   /// represented as characters between '<#' and '#>' in the source code. The
   /// lexer uses identifier tokens to represent placeholders.
   bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
+
+  /// Returns true if this token is the first pp-token.
+  bool isFirstPPToken() const { return getFlag(FirstPPToken); }
 };
 
 /// Information about the conditional stack (\#if directives)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 29452bb37260d..9397546c8fc5d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9822,7 +9822,8 @@ class Sema final : public SemaBase {
   DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
                                  SourceLocation ModuleLoc, ModuleDeclKind MDK,
                                  ModuleIdPath Path, ModuleIdPath Partition,
-                                 ModuleImportState &ImportState);
+                                 ModuleImportState &ImportState,
+                                 bool IntroducerIsFirstPPToken);
 
   /// The parser has processed a global-module-fragment declaration that begins
   /// the definition of the global module fragment of the current module unit.
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 93200458f04b4..06a74fa759794 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -174,6 +174,8 @@ void Lexer::InitLexer(const char *BufStart, const char 
*BufPtr,
   ExtendedTokenMode = 0;
 
   NewLinePtr = nullptr;
+
+  IsFirstPPToken = true;
 }
 
 /// Lexer constructor - Create a new lexer object for the specified buffer
@@ -3725,6 +3727,11 @@ bool Lexer::Lex(Token &Result) {
     HasLeadingEmptyMacro = false;
   }
 
+  if (IsFirstPPToken) {
+    Result.setFlag(Token::FirstPPToken);
+    IsFirstPPToken = false;
+  }
+
   bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
   IsAtPhysicalStartOfLine = false;
   bool isRawLex = isLexingRawMode();
@@ -3732,6 +3739,9 @@ bool Lexer::Lex(Token &Result) {
   bool returnedToken = LexTokenInternal(Result, atPhysicalStartOfLine);
   // (After the LexTokenInternal call, the lexer might be destroyed.)
   assert((returnedToken || !isRawLex) && "Raw lex must succeed");
+
+  if (returnedToken && Result.isFirstPPToken() && PP)
+    PP->setFirstPPToken(Result);
   return returnedToken;
 }
 
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 788ed79e0c1fa..18f399aca59e8 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -2340,7 +2340,8 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
 
 Parser::DeclGroupPtrTy
 Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
-  SourceLocation StartLoc = Tok.getLocation();
+  Token Introducer = Tok;
+  SourceLocation StartLoc = Introducer.getLocation();
 
   Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export)
                                  ? Sema::ModuleDeclKind::Interface
@@ -2359,7 +2360,7 @@ Parser::ParseModuleDecl(Sema::ModuleImportState 
&ImportState) {
   // Parse a global-module-fragment, if present.
   if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) {
     SourceLocation SemiLoc = ConsumeToken();
-    if (ImportState != Sema::ModuleImportState::FirstDecl) {
+    if (!Introducer.isFirstPPToken()) {
       Diag(StartLoc, diag::err_global_module_introducer_not_at_start)
         << SourceRange(StartLoc, SemiLoc);
       return nullptr;
@@ -2416,7 +2417,7 @@ Parser::ParseModuleDecl(Sema::ModuleImportState 
&ImportState) {
   ExpectAndConsumeSemi(diag::err_module_expected_semi);
 
   return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition,
-                                 ImportState);
+                                 ImportState, Introducer.isFirstPPToken());
 }
 
 Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 9fcaad48d3058..486aa3d395134 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -258,11 +258,11 @@ static bool DiagReservedModuleName(Sema &S, const 
IdentifierInfo *II,
 Sema::DeclGroupPtrTy
 Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
                       ModuleDeclKind MDK, ModuleIdPath Path,
-                      ModuleIdPath Partition, ModuleImportState &ImportState) {
+                      ModuleIdPath Partition, ModuleImportState &ImportState,
+                      bool IntroducerIsFirstPPToken) {
   assert(getLangOpts().CPlusPlusModules &&
          "should only have module decl in standard C++ modules");
 
-  bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
   bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
   // If any of the steps here fail, we count that as invalidating C++20
   // module state;
@@ -328,12 +328,14 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
           SeenGMF == (bool)this->TheGlobalModuleFragment) &&
          "mismatched global module state");
 
-  // In C++20, the module-declaration must be the first declaration if there
-  // is no global module fragment.
-  if (getLangOpts().CPlusPlusModules && !IsFirstDecl && !SeenGMF) {
+  // In C++20, A module directive may only appear as the first preprocessing
+  // tokens in a file (excluding the global module fragment.).
+  if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) 
{
     Diag(ModuleLoc, diag::err_module_decl_not_at_start);
     SourceLocation BeginLoc =
-        ModuleScopes.empty()
+        PP.getFirstPPToken().getLocation().isValid()
+            ? PP.getFirstPPToken().getLocation()
+        : ModuleScopes.empty()
             ? SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID())
             : ModuleScopes.back().BeginLoc;
     if (BeginLoc.isValid()) {
diff --git a/clang/test/CXX/basic/basic.link/p1.cpp 
b/clang/test/CXX/basic/basic.link/p1.cpp
index c6a119aa7f47c..26a5f025f42fe 100644
--- a/clang/test/CXX/basic/basic.link/p1.cpp
+++ b/clang/test/CXX/basic/basic.link/p1.cpp
@@ -1,57 +1,128 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_MODULE_DECL %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_PRIVATE_FRAG %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_MODULE_DECL -DNO_PRIVATE_FRAG %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG -DNO_PRIVATE_FRAG %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG -DNO_MODULE_DECL %s
-// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG -DNO_MODULE_DECL 
-DNO_PRIVATE_FRAG %s
-// RUN: %clang_cc1 -std=c++2a -verify -DEXPORT_FRAGS %s
-
-#ifndef NO_GLOBAL_FRAG
-#ifdef EXPORT_FRAGS
-export // expected-error {{global module fragment cannot be exported}}
-#endif
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++2a -verify %t/M.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/NoGlobalFrag.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/NoModuleDecl.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/NoPrivateFrag.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/NoModuleDeclAndNoPrivateFrag.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/NoGlobalFragAndNoPrivateFrag.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/NoGlobalFragAndNoModuleDecl.cppm
+// RUN: %clang_cc1 -std=c++2a -verify 
%t/NoGlobalFragAndNoModuleDeclAndNoPrivateFrag.cppm
+// RUN: %clang_cc1 -std=c++2a -verify %t/ExportFrags.cppm
+
+//--- M.cppm
 module;
-#ifdef NO_MODULE_DECL
-// expected-error@-2 {{missing 'module' declaration at end of global module 
fragment introduced here}}
-#endif
-#endif
+extern int a; // #a1
+export module Foo;
+
+int a; // expected-error {{declaration of 'a' in module Foo follows 
declaration in the global module}}
+       // expected-note@#a1 {{previous decl}}
+extern int b;
+
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
+module :private; // #priv-frag
+int b; // ok
+module :private; // expected-error {{private module fragment redefined}}
+                 // expected-note@#priv-frag {{previous definition is here}}
+
+//--- NoGlobalFrag.cppm
+
+extern int a; // #a1
+export module Foo; // expected-error {{module declaration must occur at the 
start of the translation unit}}
+                   // expected-note@-2 {{add 'module;' to the start of the 
file to introduce a global module fragment}}
+
+// expected-error@#a2 {{declaration of 'a' in module Foo follows declaration 
in the global module}}
+// expected-note@#a1 {{previous decl}}
+
+int a; // #a2
+extern int b;
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
+module :private; // #priv-frag
+int b; // ok
+module :private; // expected-error {{private module fragment redefined}}
+// expected-note@#priv-frag {{previous definition is here}}
 
+//--- NoModuleDecl.cppm
+module; // expected-error {{missing 'module' declaration at end of global 
module fragment introduced here}}
 extern int a; // #a1
+int a; // #a2
+extern int b;
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
+module :private; // expected-error {{private module fragment declaration with 
no preceding module declaration}}
+int b; // ok
 
-#ifndef NO_MODULE_DECL
+//--- NoPrivateFrag.cppm
+module;
+extern int a; // #a1
 export module Foo;
-#ifdef NO_GLOBAL_FRAG
-// expected-error@-2 {{module declaration must occur at the start of the 
translation unit}}
+
+// expected-error@#a2 {{declaration of 'a' in module Foo follows declaration 
in the global module}}
+// expected-note@#a1 {{previous decl}}
+int a; // #a2
+extern int b;
+
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
+int b; // ok
+
+
+//--- NoModuleDeclAndNoPrivateFrag.cppm
+module; // expected-error {{missing 'module' declaration at end of global 
module fragment introduced here}}
+extern int a; // #a1
+int a; // #a2
+extern int b;
+
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
+
+int b; // ok
+
+//--- NoGlobalFragAndNoPrivateFrag.cppm
+extern int a; // #a1
+export module Foo; // expected-error {{module declaration must occur at the 
start of the translation unit}}
 // expected-note@1 {{add 'module;' to the start of the file to introduce a 
global module fragment}}
-#endif
 
 // expected-error@#a2 {{declaration of 'a' in module Foo follows declaration 
in the global module}}
 // expected-note@#a1 {{previous decl}}
-#endif
 
 int a; // #a2
 extern int b;
 
 module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
 
-#ifndef NO_PRIVATE_FRAG
-#ifdef EXPORT_FRAGS
-export // expected-error {{private module fragment cannot be exported}}
-#endif
+int b; // ok
+
+//--- NoGlobalFragAndNoModuleDecl.cppm
+extern int a; // #a1
+int a; // #a2
+extern int b;
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
 module :private; // #priv-frag
-#ifdef NO_MODULE_DECL
-// expected-error@-2 {{private module fragment declaration with no preceding 
module declaration}}
-#endif
-#endif
+// expected-error@-1 {{private module fragment declaration with no preceding 
module declaration}}
+int b; // ok
 
+
+//--- NoGlobalFragAndNoModuleDeclAndNoPrivateFrag.cppm
+extern int a; // #a1
+int a; // #a2
+extern int b;
+
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
 int b; // ok
 
+//--- ExportFrags.cppm
+export module; // expected-error {{global module fragment cannot be exported}}
+extern int a; // #a1
+export module Foo;
+// expected-error@#a2 {{declaration of 'a' in module Foo follows declaration 
in the global module}}
+// expected-note@#a1 {{previous decl}}
 
-#ifndef NO_PRIVATE_FRAG
-#ifndef NO_MODULE_DECL
+int a; // #a2
+extern int b;
+
+module; // expected-error {{'module;' introducing a global module fragment can 
appear only at the start of the translation unit}}
+
+module :private; // #priv-frag
+
+int b; // ok
 module :private; // expected-error {{private module fragment redefined}}
-// expected-note@#priv-frag {{previous definition is here}}
-#endif
-#endif
+                 // expected-note@#priv-frag {{previous definition is here}}
diff --git a/clang/test/CXX/basic/basic.link/p2.cpp 
b/clang/test/CXX/basic/basic.link/p2.cpp
index ccad42022ee80..94cbc62490b2f 100644
--- a/clang/test/CXX/basic/basic.link/p2.cpp
+++ b/clang/test/CXX/basic/basic.link/p2.cpp
@@ -1,16 +1,16 @@
-// RUN: %clang_cc1 -std=c++2a -DEXPORT %s -verify
-// RUN: %clang_cc1 -std=c++2a -DEXPORT %s -emit-module-interface -o %t.pcm
-// RUN: %clang_cc1 -std=c++2a -UEXPORT %s -verify -fmodule-file=M=%t.pcm
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++2a %t/pmf_in_interface.cpp -verify
+// RUN: %clang_cc1 -std=c++2a %t/pmf_in_interface.cpp -emit-module-interface 
-o %t.pcm
+// RUN: %clang_cc1 -std=c++2a %t/pmf_in_implementation.cpp -verify 
-fmodule-file=M=%t.pcm
 
-#ifdef EXPORT
-// expected-no-diagnostics
-export
-#else
-// expected-note@+2 {{add 'export' here}}
-#endif
-module M;
 
-#ifndef EXPORT
-// expected-error@+2 {{private module fragment in module implementation unit}}
-#endif
+//--- pmf_in_interface.cpp
+// expected-no-diagnostics
+export module M;
 module :private;
+
+//--- pmf_in_implementation.cpp
+module M; // expected-note {{add 'export' here}}
+module :private; // expected-error {{private module fragment in module 
implementation unit}}
diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp 
b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
index d70eb7de22c6a..fd0038b3f7745 100644
--- a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
+++ b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
@@ -1,14 +1,16 @@
 // RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: echo '#ifndef FOO_H' > %t/foo.h
-// RUN: echo '#define FOO_H' >> %t/foo.h
-// RUN: echo 'extern int in_header;' >> %t/foo.h
-// RUN: echo '#endif' >> %t/foo.h
-// RUN: %clang_cc1 -std=c++2a -I%t -emit-module-interface -DINTERFACE %s -o 
%t.pcm
-// RUN: %clang_cc1 -std=c++2a -I%t -fmodule-file=A=%t.pcm -DIMPLEMENTATION %s 
-verify -fno-modules-error-recovery
-// RUN: %clang_cc1 -std=c++2a -I%t -fmodule-file=A=%t.pcm %s -verify 
-fno-modules-error-recovery
-
-#ifdef INTERFACE
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -std=c++2a -I%t -emit-module-interface %t/interface.cppm -o 
%t.pcm
+// RUN: %clang_cc1 -std=c++2a -I%t -fmodule-file=A=%t.pcm %t/implA.cppm 
-verify -fno-modules-error-recovery
+// RUN: %clang_cc1 -std=c++2a -I%t -fmodule-file=A=%t.pcm %t/implB.cppm 
-verify -fno-modules-error-recovery
+
+//--- foo.h
+#ifndef FOO_H
+#define FOO_H
+extern int in_header;
+#endif
+
+//--- interface.cppm
 module;
 #include "foo.h"
 // FIXME: The following need to be moved to a header file. The global module
@@ -22,11 +24,9 @@ static int internal;
 module :private;
 int not_exported_private;
 static int internal_private;
-#else
 
-#ifdef IMPLEMENTATION
+//--- implA.cppm
 module;
-#endif
 
 void test_early() {
   in_header = 1; // expected-error {{use of undeclared identifier 'in_header'}}
@@ -46,11 +46,7 @@ void test_early() {
   internal_private = 1; // expected-error {{undeclared identifier}}
 }
 
-#ifdef IMPLEMENTATION
 module A;
-#else
-import A;
-#endif
 
 void test_late() {
   in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' 
must be declared before it is used}}
@@ -61,20 +57,54 @@ void test_late() {
   exported = 1;
 
   not_exported = 1;
-#ifndef IMPLEMENTATION
-  // expected-error@-2 {{use of undeclared identifier 'not_exported'; did you 
mean 'exported'?}}
-  // expected-n...@p2.cpp:18 {{'exported' declared here}}
-#endif
 
   internal = 1; // expected-error {{use of undeclared identifier 'internal'}}
 
   not_exported_private = 1;
-#ifndef IMPLEMENTATION
-  // FIXME: should not be visible here
-  // expected-error@-3 {{undeclared identifier}}
-#endif
 
   internal_private = 1; // expected-error {{use of undeclared identifier 
'internal_private'}}
 }
 
-#endif
+//--- implB.cppm
+module;
+
+void test_early() {
+  in_header = 1; // expected-error {{use of undeclared identifier 'in_header'}}
+  // expected-note@* {{not visible}}
+
+  global_module_fragment = 1; // expected-error {{use of undeclared identifier 
'global_module_fragment'}}
+
+  exported = 1; // expected-error {{use of undeclared identifier 'exported'}}
+
+  not_exported = 1; // expected-error {{use of undeclared identifier 
'not_exported'}}
+
+  // FIXME: We need better diagnostic message for static variable.
+  internal = 1; // expected-error {{use of undeclared identifier 'internal'}}
+
+  not_exported_private = 1; // expected-error {{undeclared identifier}}
+
+  internal_private = 1; // expected-error {{undeclared identifier}}
+}
+
+export module B;
+import A;
+
+void test_late() {
+  in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' 
must be declared before it is used}}
+  // expected-note@* {{not visible}}
+
+  global_module_fragment = 1; // expected-error {{missing '#include'; 
'global_module_fragment' must be declared before it is used}}
+
+  exported = 1;
+
+  not_exported = 1; // expected-error {{use of undeclared identifier 
'not_exported'; did you mean 'exported'?}}
+  // expected-note@* {{'exported' declared here}}
+
+  internal = 1; // expected-error {{use of undeclared identifier 'internal'}}
+
+  not_exported_private = 1;
+  // FIXME: should not be visible here
+  // expected-error@-2 {{undeclared identifier}}
+
+  internal_private = 1; // expected-error {{use of undeclared identifier 
'internal_private'}}
+}
\ No newline at end of file
diff --git a/clang/test/CXX/module/basic/basic.def.odr/p6.cppm 
b/clang/test/CXX/module/basic/basic.def.odr/p6.cppm
index 8e7917dc63ea5..c532e7ad40a10 100644
--- a/clang/test/CXX/module/basic/basic.def.odr/p6.cppm
+++ b/clang/test/CXX/module/basic/basic.def.odr/p6.cppm
@@ -3,29 +3,28 @@
 // RUN: split-file %s %t
 //
 // RUN: %clang_cc1 -std=c++20 -verify %t/global-vs-module.cppm 
-// RUN: %clang_cc1 -std=c++20 -verify %t/global-vs-module.cppm -DEXPORT
-// RUN: %clang_cc1 -std=c++20 -verify %t/global-vs-module.cppm -DUSING
+// RUN: %clang_cc1 -std=c++20 -verify %t/global-vs-module-export.cppm
+// RUN: %clang_cc1 -std=c++20 -verify %t/global-vs-module-using.cppm
 //
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/global-vs-module.cppm 
-o %t/M.pcm -DNO_GLOBAL -DEXPORT
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/M.cppm -o %t/M.pcm
 // RUN: %clang_cc1 -std=c++20 -verify %t/module-vs-global.cpp 
-fmodule-file=M=%t/M.pcm
 //
 // Some of the following tests intentionally have no -verify in their RUN
 // lines; we are testing that those cases do not produce errors.
 //
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-DMODULE_INTERFACE -verify
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-DMODULE_INTERFACE -DNO_IMPORT
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-interface.cpp 
-fmodule-file=M=%t/M.pcm -verify
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-interface.cpp 
-fmodule-file=M=%t/M.pcm -DNO_IMPORT
 //
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-emit-module-interface -o %t/N.pcm -DMODULE_INTERFACE -DNO_ERRORS
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N.pcm -verify
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-interface.cpp 
-fmodule-file=M=%t/M.pcm -emit-module-interface -o %t/N.pcm -DNO_ERRORS
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-impl.cpp 
-fmodule-file=M=%t/M.pcm -fmodule-file=N=%t/N.pcm -verify
 //
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N.pcm -DNO_IMPORT -verify
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-impl.cpp 
-fmodule-file=M=%t/M.pcm -fmodule-file=N=%t/N.pcm -DNO_IMPORT -verify
 //
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-emit-module-interface -o %t/N-no-M.pcm -DMODULE_INTERFACE -DNO_ERRORS 
-DNO_IMPORT
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N-no-M.pcm -verify
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp 
-fmodule-file=N=%t/N-no-M.pcm -DNO_IMPORT
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-interface.cpp 
-fmodule-file=M=%t/M.pcm -emit-module-interface -o %t/N-no-M.pcm -DNO_ERRORS 
-DNO_IMPORT
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-impl.cpp 
-fmodule-file=M=%t/M.pcm -fmodule-file=N=%t/N-no-M.pcm -verify
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module-impl.cpp 
-fmodule-file=N=%t/N-no-M.pcm -DNO_IMPORT
 
 //--- global-vs-module.cppm
-#ifndef NO_GLOBAL
 module;
 extern int var; // expected-note {{previous declaration is here}}
 int func(); // expected-note {{previous declaration is here}}
@@ -40,11 +39,75 @@ template<typename> using type_tpl = int; // expected-note 
{{previous declaration
 typedef int type;
 namespace ns { using ::func; }
 namespace ns_alias = ns;
-#endif
 
 export module M;
 
-#ifdef USING
+extern int var; // expected-error {{declaration of 'var' in module M follows 
declaration in the global module}}
+int func(); // expected-error {{declaration of 'func' in module M follows 
declaration in the global module}}
+struct str; // expected-error {{declaration of 'str' in module M follows 
declaration in the global module}}
+using type = int;
+
+template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in module M follows declaration in the global module}}
+template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in module M follows declaration in the global module}}
+template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in module M follows declaration in the global module}}
+template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in module M follows declaration in the global module}}
+
+typedef int type;
+namespace ns { using ::func; }
+namespace ns_alias = ns;
+
+//--- global-vs-module-export.cppm
+module;
+extern int var; // expected-note {{previous declaration is here}}
+int func(); // expected-note {{previous declaration is here}}
+struct str; // expected-note {{previous declaration is here}}
+using type = int;
+
+template<typename> extern int var_tpl; // expected-note {{previous declaration 
is here}}
+template<typename> int func_tpl(); // expected-note {{previous declaration is 
here}}
+template<typename> struct str_tpl; // expected-note {{previous declaration is 
here}}
+template<typename> using type_tpl = int; // expected-note {{previous 
declaration is here}}
+
+typedef int type;
+namespace ns { using ::func; }
+namespace ns_alias = ns;
+
+export module M;
+
+export {
+extern int var; // expected-error {{declaration of 'var' in module M follows 
declaration in the global module}}
+int func(); // expected-error {{declaration of 'func' in module M follows 
declaration in the global module}}
+struct str; // expected-error {{declaration of 'str' in module M follows 
declaration in the global module}}
+using type = int;
+
+template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in module M follows declaration in the global module}}
+template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in module M follows declaration in the global module}}
+template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in module M follows declaration in the global module}}
+template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in module M follows declaration in the global module}}
+
+typedef int type;
+namespace ns { using ::func; }
+namespace ns_alias = ns;
+}
+
+//--- global-vs-module-using.cppm
+module;
+extern int var; // expected-note {{previous declaration is here}}
+int func(); // expected-note {{previous declaration is here}}
+struct str; // expected-note {{previous declaration is here}}
+using type = int;
+
+template<typename> extern int var_tpl; // expected-note {{previous declaration 
is here}}
+template<typename> int func_tpl(); // expected-note {{previous declaration is 
here}}
+template<typename> struct str_tpl; // expected-note {{previous declaration is 
here}}
+template<typename> using type_tpl = int; // expected-note {{previous 
declaration is here}}
+
+typedef int type;
+namespace ns { using ::func; }
+namespace ns_alias = ns;
+
+export module M;
+
 using ::var;
 using ::func;
 using ::str;
@@ -53,11 +116,6 @@ using ::var_tpl;
 using ::func_tpl;
 using ::str_tpl;
 using ::type_tpl;
-#endif
-
-#ifdef EXPORT
-export {
-#endif
 
 extern int var; // expected-error {{declaration of 'var' in module M follows 
declaration in the global module}}
 int func(); // expected-error {{declaration of 'func' in module M follows 
declaration in the global module}}
@@ -73,51 +131,87 @@ typedef int type;
 namespace ns { using ::func; }
 namespace ns_alias = ns;
 
-#ifdef EXPORT
+//--- M.cppm
+export module M;
+
+export {
+extern int var; // expected-error {{declaration of 'var' in module M follows 
declaration in the global module}}
+int func(); // expected-error {{declaration of 'func' in module M follows 
declaration in the global module}}
+struct str; // expected-error {{declaration of 'str' in module M follows 
declaration in the global module}}
+using type = int;
+
+template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in module M follows declaration in the global module}}
+template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in module M follows declaration in the global module}}
+template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in module M follows declaration in the global module}}
+template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in module M follows declaration in the global module}}
+
+typedef int type;
+namespace ns { using ::func; }
+namespace ns_alias = ns;
 }
-#endif
 
 //--- module-vs-global.cpp
+module;
 import M;
 
-extern int var; // expected-error {{declaration of 'var' in the global module 
follows declaration in module M}} expected-n...@global-vs-module.cppm:35 
{{previous}}
-int func(); // expected-error {{declaration of 'func' in the global module 
follows declaration in module M}} expected-n...@global-vs-module.cppm:36 
{{previous}}
-struct str; // expected-error {{declaration of 'str' in the global module 
follows declaration in module M}} expected-n...@global-vs-module.cppm:37 
{{previous}}
+extern int var; // expected-error {{declaration of 'var' in the global module 
follows declaration in module M}} expected-n...@m.cppm:4 {{previous}}
+int func(); // expected-error {{declaration of 'func' in the global module 
follows declaration in module M}} expected-n...@m.cppm:5 {{previous}}
+struct str; // expected-error {{declaration of 'str' in the global module 
follows declaration in module M}} expected-n...@m.cppm:6 {{previous}}
 using type = int;
 
-template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in the global module follows declaration in module M}} 
expected-n...@global-vs-module.cppm:40 {{previous}}
-template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in the global module follows declaration in module M}} 
expected-n...@global-vs-module.cppm:41 {{previous}}
-template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in the global module follows declaration in module M}} 
expected-n...@global-vs-module.cppm:42 {{previous}}
-template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in the global module follows declaration in module M}} 
expected-n...@global-vs-module.cppm:43 {{previous}}
+template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in the global module follows declaration in module M}} 
expected-n...@m.cppm:9 {{previous}}
+template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in the global module follows declaration in module M}} 
expected-n...@m.cppm:10 {{previous}}
+template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in the global module follows declaration in module M}} 
expected-n...@m.cppm:11 {{previous}}
+template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in the global module follows declaration in module M}} 
expected-n...@m.cppm:12 {{previous}}
 
 typedef int type;
 namespace ns { using ::func; }
 namespace ns_alias = ns;
 
-//--- module-vs-module.cpp
-#ifdef MODULE_INTERFACE
 export module N;
-#else
-module N;
-#endif
+
+//--- module-vs-module-interface.cpp
+export module N;
 
 #ifndef NO_IMPORT
 import M;
 #endif
 
 #ifndef NO_ERRORS
-extern int var; // expected-error {{declaration of 'var' in module N follows 
declaration in module M}} expected-n...@global-vs-module.cppm:35 {{previous}}
-int func(); // expected-error {{declaration of 'func' in module N follows 
declaration in module M}} expected-n...@global-vs-module.cppm:36 {{previous}}
-struct str; // expected-error {{declaration of 'str' in module N follows 
declaration in module M}} expected-n...@global-vs-module.cppm:37 {{previous}}
+extern int var; // expected-error {{declaration of 'var' in module N follows 
declaration in module M}} expected-n...@m.cppm:4 {{previous}}
+int func(); // expected-error {{declaration of 'func' in module N follows 
declaration in module M}} expected-n...@m.cppm:5 {{previous}}
+struct str; // expected-error {{declaration of 'str' in module N follows 
declaration in module M}} expected-n...@m.cppm:6 {{previous}}
 using type = int;
 
-template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in module N follows declaration in module M}} 
expected-n...@global-vs-module.cppm:40 {{previous}}
-template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in module N follows declaration in module M}} 
expected-n...@global-vs-module.cppm:41 {{previous}}
-template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in module N follows declaration in module M}} 
expected-n...@global-vs-module.cppm:42 {{previous}}
-template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in module N follows declaration in module M}} 
expected-n...@global-vs-module.cppm:43 {{previous}}
+template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in module N follows declaration in module M}} expected-n...@m.cppm:9 
{{previous}}
+template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in module N follows declaration in module M}} 
expected-n...@m.cppm:10 {{previous}}
+template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in module N follows declaration in module M}} expected-n...@m.cppm:11 
{{previous}}
+template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in module N follows declaration in module M}} 
expected-n...@m.cppm:12 {{previous}}
 
 typedef int type;
 namespace ns { using ::func; }
 namespace ns_alias = ns;
 #endif
 
+//--- module-vs-module-impl.cpp
+module N;
+
+#ifndef NO_IMPORT
+import M;
+#endif
+
+#ifndef NO_ERRORS
+extern int var; // expected-error {{declaration of 'var' in module N follows 
declaration in module M}} expected-n...@m.cppm:4 {{previous}}
+int func(); // expected-error {{declaration of 'func' in module N follows 
declaration in module M}} expected-n...@m.cppm:5 {{previous}}
+struct str; // expected-error {{declaration of 'str' in module N follows 
declaration in module M}} expected-n...@m.cppm:6 {{previous}}
+using type = int;
+
+template<typename> extern int var_tpl; // expected-error {{declaration of 
'var_tpl' in module N follows declaration in module M}} expected-n...@m.cppm:9 
{{previous}}
+template<typename> int func_tpl(); // expected-error {{declaration of 
'func_tpl' in module N follows declaration in module M}} 
expected-n...@m.cppm:10 {{previous}}
+template<typename> struct str_tpl; // expected-error {{declaration of 
'str_tpl' in module N follows declaration in module M}} expected-n...@m.cppm:11 
{{previous}}
+template<typename> using type_tpl = int; // expected-error {{declaration of 
'type_tpl' in module N follows declaration in module M}} 
expected-n...@m.cppm:12 {{previous}}
+
+typedef int type;
+namespace ns { using ::func; }
+namespace ns_alias = ns;
+#endif
diff --git a/clang/test/CXX/module/basic/basic.link/module-declaration.cpp 
b/clang/test/CXX/module/basic/basic.link/module-declaration.cpp
index d71358cc7a571..4bdcc9e5f278e 100644
--- a/clang/test/CXX/module/basic/basic.link/module-declaration.cpp
+++ b/clang/test/CXX/module/basic/basic.link/module-declaration.cpp
@@ -8,27 +8,19 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fmodule-file=x=%t/x.pcm 
%t/x.y.cppm -o %t/x.y.pcm
 //
 // Module implementation for unknown and known module. (The former is 
ill-formed.)
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify -x c++ 
%t/M.cpp \
-// RUN:            -DTEST=1 -DEXPORT= -DMODULE_NAME=z
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x=%t/x.pcm 
-fmodule-file=x.y=%t/x.y.pcm -verify -x c++ %t/M.cpp \
-// RUN:            -DTEST=2 -DEXPORT= -DMODULE_NAME=x
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify -x c++ 
%t/z_impl.cppm
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x=%t/x.pcm 
-fmodule-file=x.y=%t/x.y.pcm -verify -x c++ %t/x_impl.cppm
 //
 // Module interface for unknown and known module. (The latter is ill-formed 
due to
 // redefinition.)
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/M.cpp \
-// RUN:            -DTEST=3 -DEXPORT=export -DMODULE_NAME=z
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/M.cpp \
-// RUN:            -DTEST=4 -DEXPORT=export -DMODULE_NAME=x
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/z_interface.cppm
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/x_interface.cppm
 //
 // Miscellaneous syntax.
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/M.cpp \
-// RUN:            -DTEST=7 -DEXPORT=export -DMODULE_NAME='z elderberry'
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/M.cpp \
-// RUN:            -DTEST=8 -DEXPORT=export -DMODULE_NAME='z [[]]'
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/M.cpp \
-// RUN:            -DTEST=9 -DEXPORT=export -DMODULE_NAME='z [[fancy]]'
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/M.cpp \
-// RUN:            -DTEST=10 -DEXPORT=export -DMODULE_NAME='z [[maybe_unused]]'
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/invalid_module_name.cppm
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/empty_attribute.cppm
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/fancy_attribute.cppm
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify 
%t/maybe_unused_attribute.cppm
 
 //--- x.cppm
 export module x;
@@ -38,17 +30,31 @@ int a, b;
 export module x.y;
 int c;
 
-//--- M.cpp
-
-EXPORT module MODULE_NAME;
-#if TEST == 7
-// expected-error@-2 {{expected ';'}} expected-error@-2 {{a type specifier is 
required}}
-#elif TEST == 9
-// expected-warning@-4 {{unknown attribute 'fancy' ignored}}
-#elif TEST == 10
-// expected-error-re@-6 {{'maybe_unused' attribute cannot be applied to a 
module{{$}}}}
-#elif TEST == 1
-// expected-error@-8 {{module 'z' not found}}
-#else
+//--- z_impl.cppm
+module z; // expected-error {{module 'z' not found}}
+
+//--- x_impl.cppm
+// expected-no-diagnostics
+module x;
+
+//--- z_interface.cppm
 // expected-no-diagnostics
-#endif
+export module z;
+
+//--- x_interface.cppm
+// expected-no-diagnostics
+export module x;
+
+//--- invalid_module_name.cppm
+export module z elderberry; // expected-error {{expected ';'}} \
+                            // expected-error {{a type specifier is required}}
+
+//--- empty_attribute.cppm
+// expected-no-diagnostics
+export module z [[]];
+
+//--- fancy_attribute.cppm
+export module z [[fancy]]; // expected-warning {{unknown attribute 'fancy' 
ignored}}
+
+//--- maybe_unused_attribute.cppm
+export module z [[maybe_unused]]; // expected-error-re {{'maybe_unused' 
attribute cannot be applied to a module{{$}}}}
diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm 
b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm
index 873e4c0edeac2..f7e4d8da22f60 100644
--- a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm
+++ b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm
@@ -6,10 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fmodule-file=x=%t/x.pcm 
%t/x.y.cppm -o %t/x.y.pcm
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.b.cppm -o %t/a.b.pcm
 //
-// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm 
-fmodule-file=x=%t/x.pcm -verify %t/test.cpp \
-// RUN:            -DMODULE_NAME=z -DINTERFACE
 // RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm 
-fmodule-file=x=%t/x.pcm \
-// RUN:            -fmodule-file=a.b=%t/a.b.pcm -verify %t/test.cpp 
-DMODULE_NAME=a.b
+// RUN:             -verify %t/test.interface.cpp
+// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm 
-fmodule-file=x=%t/x.pcm \
+// RUN:            -fmodule-file=a.b=%t/a.b.pcm -verify 
%t/test.implementation.cpp
 // RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm 
-fmodule-file=x=%t/x.pcm -verify %t/test.x.cpp
 
 //--- x.cppm
@@ -33,12 +33,26 @@ int use_2 = b; // ok
 // There is no relation between module x and module x.y.
 int use_3 = c; // expected-error {{use of undeclared identifier 'c'}}
 
-//--- test.cpp
-#ifdef INTERFACE
-export module MODULE_NAME;
-#else
-module MODULE_NAME;
-#endif
+//--- test.interface.cpp
+export module z;
+
+import x;
+
+import x [[]];
+import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}}
+import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be 
applied to a module import}}
+import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 
'noreturn' ignored}}
+
+import x.y;
+import x.; // expected-error {{expected a module name after 'import'}}
+import .x; // expected-error {{expected a module name after 'import'}}
+
+import blarg; // expected-error {{module 'blarg' not found}}
+
+int use_4 = c; // ok
+
+//--- test.implementation.cpp
+module a.b;
 
 import x;
 
diff --git 
a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm 
b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm
index 84ef85126c369..2158d7fa84b86 100644
--- a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm
+++ b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm
@@ -1,29 +1,26 @@
-// RUN: %clang_cc1 -std=c++20 %s -verify -emit-module-interface -o /dev/null
-// RUN: %clang_cc1 -std=c++20 %s -DINTERFACE -verify -emit-module-interface -o 
%t
-// RUN: %clang_cc1 -std=c++20 %s -DIMPLEMENTATION -verify -fmodule-file=A=%t 
-o /dev/null
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 %t/ExportDeclNotInModulePurview.cppm -verify 
-emit-module-interface -o /dev/null
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -verify -emit-module-interface -o 
%t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/AddExport.cppm -verify 
-fmodule-file=A=%t/A.pcm -o /dev/null
 //
-// RUN: %clang_cc1 -std=c++20 %s -DBUILT_AS_INTERFACE -emit-module-interface 
-verify -o /dev/null
-// RUN: %clang_cc1 -std=c++20 %s -DINTERFACE -DBUILT_AS_INTERFACE 
-emit-module-interface -verify -o /dev/null
-// RUN: %clang_cc1 -std=c++20 %s -DIMPLEMENTATION -DBUILT_AS_INTERFACE 
-emit-module-interface -verify -o /dev/null
+// RUN: %clang_cc1 -std=c++20 %t/AddExport2.cppm -emit-module-interface 
-verify -o /dev/null
 
-#if INTERFACE
+//--- ExportDeclNotInModulePurview.cppm
+// expected-error@* {{missing 'export module' declaration in module interface 
unit}}
+export int b; // expected-error {{export declaration can only be used within a 
module purview}}
+
+//--- A.cppm
 // expected-no-diagnostics
 export module A;
-#elif IMPLEMENTATION
-module A; // #module-decl
- #ifdef BUILT_AS_INTERFACE
-  // expected-error@-2 {{missing 'export' specifier in module declaration 
while building module interface}}
-  #define INTERFACE
- #endif
-#else // Not in a module
-// expected-error@* {{missing 'export module' declaration in module interface 
unit}}
-#endif
+export int a;
 
-#ifndef INTERFACE
+//--- AddExport.cppm
+module A; // #module-decl
 export int b; // expected-error {{export declaration can only be used within a 
module purview}}
-#ifdef IMPLEMENTATION
 // expected-note@#module-decl {{add 'export' here}}
-#endif
-#else
+
+//--- AddExport2.cppm
+module A; // expected-error {{missing 'export' specifier in module declaration 
while building module interface}}
 export int a;
-#endif
diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp 
b/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp
index db86b5dd34c38..95d087e0f6c78 100644
--- a/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp
+++ b/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp
@@ -1,14 +1,30 @@
-// RUN: %clang_cc1 -std=c++20 -verify %s -DFOO=export -DBAR=export
-// RUN: %clang_cc1 -std=c++20 -verify %s -DFOO=export -DBAR=
-// RUN: %clang_cc1 -std=c++20 %s -DFOO=export -emit-module-interface -o %t
-// RUN: %clang_cc1 -std=c++20 %s -fmodule-file=foo=%t -DFOO=
-// RUN: %clang_cc1 -std=c++20 %s -fmodule-file=foo=%t -DBAR=export
-// RUN: %clang_cc1 -std=c++20 -verify %s -fmodule-file=foo=%t -DFOO= 
-DBAR=export
-
-#ifdef FOO
-FOO module foo; // expected-note {{previous module declaration is here}}
-#endif
-
-#ifdef BAR
-BAR module bar; // expected-error {{translation unit contains multiple module 
declarations}}
-#endif
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -verify %t/A.cppm
+// RUN: %clang_cc1 -std=c++20 -verify %t/B.cppm
+// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-module-interface -o %t/C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/D.cppm -fmodule-file=foo=%t/C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/E.cppm -fmodule-file=foo=%t/C.pcm
+// RUN: %clang_cc1 -std=c++20 -verify %t/F.cppm -fmodule-file=foo=%t/C.pcm
+
+//--- A.cppm
+export module foo; // expected-note {{previous module declaration is here}}
+export module bar; // expected-error {{translation unit contains multiple 
module declarations}}
+
+//--- B.cppm
+export module foo; // expected-note {{previous module declaration is here}}
+module bar; // expected-error {{translation unit contains multiple module 
declarations}}
+
+//--- C.cppm
+export module foo;
+
+//--- D.cppm
+module foo;
+
+//--- E.cppm
+export module bar;
+
+//--- F.cppm
+module foo; // expected-note {{previous module declaration is here}}
+export module bar; // expected-error {{translation unit contains multiple 
module declarations}}
diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/p5.cpp 
b/clang/test/CXX/module/dcl.dcl/dcl.module/p5.cpp
index ca100443a4c67..a0d30233809f9 100644
--- a/clang/test/CXX/module/dcl.dcl/dcl.module/p5.cpp
+++ b/clang/test/CXX/module/dcl.dcl/dcl.module/p5.cpp
@@ -1,22 +1,47 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -o %t -DINTERFACE
-// RUN: %clang_cc1 -std=c++20 -fmodule-file=Foo=%t %s -verify -DIMPLEMENTATION
-// RUN: %clang_cc1 -std=c++20 -fmodule-file=Foo=%t %s -verify 
-DEARLY_IMPLEMENTATION
-// RUN: %clang_cc1 -std=c++20 -fmodule-file=Foo=%t %s -verify -DUSER
+// RUN: split-file %s %t
 
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/interface.cppm -o 
%t/interface.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=Foo=%t/interface.pcm 
%t/implementation.cppm -verify -DIMPLEMENTATION
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=Foo=%t/interface.pcm 
%t/early_impl.cppm -verify -DEARLY_IMPLEMENTATION
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=Foo=%t/interface.pcm %t/user.cppm 
-verify -DUSER
+
+//--- interface.cppm
 // expected-no-diagnostics
+module;
 
-#if defined(INTERFACE) || defined(EARLY_IMPLEMENTATION) || 
defined(IMPLEMENTATION)
+template<typename T> struct type_template {
+  typedef T type;
+  void f(type);
+};
+
+template<typename T> void type_template<T>::f(type) {}
+
+template<int = 0, typename = int, template<typename> class = type_template>
+struct default_template_args {};
+
+export module Foo;
+
+//--- implementation.cppm
+// expected-no-diagnostics
 module;
-#endif
 
-#ifdef USER
-import Foo;
-#endif
+template<typename T> struct type_template {
+  typedef T type;
+  void f(type);
+};
+
+template<typename T> void type_template<T>::f(type) {}
+
+template<int = 0, typename = int, template<typename> class = type_template>
+struct default_template_args {};
 
-#ifdef EARLY_IMPLEMENTATION
 module Foo;
-#endif
+
+//--- early_impl.cppm
+// expected-no-diagnostics
+module;
+module Foo;
 
 template<typename T> struct type_template {
   typedef T type;
@@ -28,10 +53,16 @@ template<typename T> void type_template<T>::f(type) {}
 template<int = 0, typename = int, template<typename> class = type_template>
 struct default_template_args {};
 
-#ifdef INTERFACE
-export module Foo;
-#endif
+//--- user.cppm
+// expected-no-diagnostics
+import Foo;
 
-#ifdef IMPLEMENTATION
-module Foo;
-#endif
+template<typename T> struct type_template {
+  typedef T type;
+  void f(type);
+};
+
+template<typename T> void type_template<T>::f(type) {}
+
+template<int = 0, typename = int, template<typename> class = type_template>
+struct default_template_args {};
diff --git a/clang/test/CXX/module/module.interface/p2.cpp 
b/clang/test/CXX/module/module.interface/p2.cpp
index 4f06b9f386869..8221c400ecd62 100644
--- a/clang/test/CXX/module/module.interface/p2.cpp
+++ b/clang/test/CXX/module/module.interface/p2.cpp
@@ -1,24 +1,26 @@
 // RUN: rm -rf %t
 // RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
 // RUN: %clang_cc1 -std=c++20 -x c++-header %S/Inputs/header.h 
-emit-header-unit -o %t/h.pcm
-// RUN: %clang_cc1 -std=c++20 %s -DX_INTERFACE -emit-module-interface -o 
%t/x.pcm
-// RUN: %clang_cc1 -std=c++20 %s -DY_INTERFACE -emit-module-interface -o 
%t/y.pcm
-// RUN: %clang_cc1 -std=c++20 %s -DINTERFACE -fmodule-file=X=%t/x.pcm 
-fmodule-file=Y=%t/y.pcm -emit-module-interface -o %t/m.pcm
-// RUN: %clang_cc1 -std=c++20 %s -DIMPLEMENTATION -I%S/Inputs 
-fmodule-file=%t/h.pcm \
+// RUN: %clang_cc1 -std=c++20 %t/x.cppm -emit-module-interface -o %t/x.pcm
+// RUN: %clang_cc1 -std=c++20 %t/y.cppm -emit-module-interface -o %t/y.pcm
+// RUN: %clang_cc1 -std=c++20 %t/interface.cppm -fmodule-file=X=%t/x.pcm 
-fmodule-file=Y=%t/y.pcm -emit-module-interface -o %t/m.pcm
+// RUN: %clang_cc1 -std=c++20 %t/impl.cppm -I%S/Inputs -fmodule-file=%t/h.pcm \
 // RUN:   -fmodule-file=X=%t/x.pcm -fmodule-file=Y=%t/y.pcm 
-fmodule-file=p2=%t/m.pcm -verify \
 // RUN:   -Wno-experimental-header-units
-// RUN: %clang_cc1 -std=c++20 %s -DUSER -I%S/Inputs -fmodule-file=%t/h.pcm 
-fmodule-file=p2=%t/m.pcm \
+// RUN: %clang_cc1 -std=c++20 %t/user.cppm -I%S/Inputs -fmodule-file=%t/h.pcm 
-fmodule-file=p2=%t/m.pcm \
 // RUN:   -fmodule-file=X=%t/x.pcm -fmodule-file=Y=%t/y.pcm 
-Wno-experimental-header-units -verify
 
-#if defined(X_INTERFACE)
+//--- x.cppm
 export module X;
 export int x;
 
-#elif defined(Y_INTERFACE)
+//--- y.cppm
 export module Y;
 export int y;
 
-#elif defined(INTERFACE)
+//--- interface.cppm
 export module p2;
 export import X;
 import Y; // not exported
@@ -39,7 +41,7 @@ namespace C {}
 namespace D { int f(); }
 export namespace D {}
 
-#elif defined(IMPLEMENTATION)
+//--- impl.cppm
 module p2;
 import "header.h";
 
@@ -66,7 +68,7 @@ void use() {
 
 int use_header() { return foo + bar::baz(); }
 
-#elif defined(USER)
+//--- user.cppm
 import p2;
 import "header.h";
 
@@ -96,7 +98,3 @@ void use() {
 }
 
 int use_header() { return foo + bar::baz(); }
-
-#else
-#error unknown mode
-#endif
diff --git a/clang/test/CXX/module/module.unit/p8.cpp 
b/clang/test/CXX/module/module.unit/p8.cpp
index a5c01c493558e..fb190257d3a23 100644
--- a/clang/test/CXX/module/module.unit/p8.cpp
+++ b/clang/test/CXX/module/module.unit/p8.cpp
@@ -1,37 +1,45 @@
-// RUN: echo 'export module foo; export int n;' > %t.cppm
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+// RUN: echo 'export module foo;' > %t.cppm
+// RUN: echo 'export int n;' >> %t.cppm
 // RUN: %clang_cc1 -std=c++2a %t.cppm -emit-module-interface -o %t.pcm
-// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=0 %s
-// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=1 %s
-// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=2 %s
-// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=3 %s
-// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=4 %s
-// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=5 %s
-
-#if MODE == 0
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=0 
%t/A.cppm
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=1 
%t/B.cppm
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=2 
%t/C.cppm
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=3 
%t/D.cppm
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=4 
%t/E.cppm
+// RUN: %clang_cc1 -std=c++2a -fmodule-file=foo=%t.pcm -verify -DMODE=5 
%t/F.cppm
+
+//--- A.cppm
 // no module declaration
+// expected-no-diagnostics
 
-#elif MODE == 1
+//--- B.cppm
 // expected-no-diagnostics
 module foo; // Implementation, implicitly imports foo.
 #define IMPORTED
 
-#elif MODE == 2
+int k = n;
+
+//--- C.cppm
 export module foo;
 
-#elif MODE == 3
+int k = n; // expected-error {{use of undeclared identifier 'n'}}
+
+//--- D.cppm
 export module bar; // A different module
 
-#elif MODE == 4
+int k = n; // expected-error {{use of undeclared identifier 'n'}}
+
+//--- E.cppm
 module foo:bar; // Partition implementation
 //#define IMPORTED (we don't import foo here)
 
-#elif MODE == 5
+int k = n; // expected-error {{use of undeclared identifier 'n'}}
+
+//--- F.cppm
 export module foo:bar; // Partition interface
 //#define IMPORTED  (we don't import foo here)
 
-#endif
-
-int k = n;
-#ifndef IMPORTED
-// expected-error@-2 {{use of undeclared identifier 'n'}}
-#endif
+int k = n; // expected-error {{use of undeclared identifier 'n'}}
diff --git a/clang/test/Driver/modules.cpp b/clang/test/Driver/modules.cpp
index b0d1f2280d254..088a73230f81e 100644
--- a/clang/test/Driver/modules.cpp
+++ b/clang/test/Driver/modules.cpp
@@ -1,43 +1,48 @@
 // RUN: rm -rf %t
 // RUN: mkdir %t
+// RUN: split-file %s %t
 
 // Check compiling a module interface to a .pcm file.
 //
-// RUN: %clang -std=c++2a -x c++-module --precompile %s -o %t/module.pcm -v 
2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
-// RUN: %clang -std=gnu++2a -x c++-module --precompile %s -o %t/module-gnu.pcm 
-v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+// RUN: %clang -std=c++2a -x c++-module --precompile %t/foo.cpp -o %t/foo.pcm 
-v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+// RUN: %clang -std=gnu++2a -x c++-module --precompile %t/foo.cpp -o 
%t/foo-gnu.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
 //
 // CHECK-PRECOMPILE: -cc1 {{.*}} -emit-module-interface
 // CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm
 // CHECK-PRECOMPILE-SAME: -x c++
-// CHECK-PRECOMPILE-SAME: modules.cpp
+// CHECK-PRECOMPILE-SAME: foo.cpp
 
 // Check compiling a .pcm file to a .o file.
 //
-// RUN: %clang -std=c++2a %t/module.pcm -S -o %t/module.pcm.o -v 2>&1 | 
FileCheck %s --check-prefix=CHECK-COMPILE
+// RUN: %clang -std=c++2a %t/foo.pcm -S -o %t/foo.pcm.o -v 2>&1 | FileCheck %s 
--check-prefix=CHECK-COMPILE
 //
 // CHECK-COMPILE: -cc1 {{.*}} {{-emit-obj|-S}}
-// CHECK-COMPILE-SAME: -o {{.*}}module{{2*}}.pcm.o
+// CHECK-COMPILE-SAME: -o {{.*}}foo{{2*}}.pcm.o
 // CHECK-COMPILE-SAME: -x pcm
 // CHECK-COMPILE-SAME: {{.*}}.pcm
 
 // Check use of a .pcm file in another compilation.
 //
-// RUN: %clang -std=c++2a -fmodule-file=%t/module.pcm -Dexport= %s -S -o 
%t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
-// RUN: %clang -std=c++20 -fmodule-file=%t/module.pcm -Dexport= %s -S -o 
%t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
-// RUN: %clang -std=gnu++20 -fmodule-file=%t/module-gnu.pcm -Dexport= %s -S -o 
%t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
+// RUN: %clang -std=c++2a -fmodule-file=foo=%t/foo.pcm %t/foo_impl.cpp -S -o 
%t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
+// RUN: %clang -std=c++20 -fmodule-file=foo=%t/foo.pcm %t/foo_impl.cpp -S -o 
%t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
+// RUN: %clang -std=gnu++20 -fmodule-file=foo=%t/foo-gnu.pcm %t/foo_impl.cpp 
-S -o %t/module.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
 //
 // CHECK-USE: -cc1 {{.*}} {{-emit-obj|-S}}
-// CHECK-USE-SAME: -fmodule-file={{.*}}.pcm
+// CHECK-USE-SAME: -fmodule-file=foo={{.*}}.pcm
 // CHECK-USE-SAME: -o {{.*}}.{{o|s}}{{"?}} {{.*}}-x c++
-// CHECK-USE-SAME: modules.cpp
+// CHECK-USE-SAME: foo_impl.cpp
 
 // Check combining precompile and compile steps works.
 //
-// RUN: %clang -std=c++2a -x c++-module %s -S -o %t/module2.pcm.o -v 2>&1 | 
FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE
+// RUN: %clang -std=c++2a -x c++-module %t/foo.cpp -S -o %t/foo2.pcm.o -v 2>&1 
| FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE
 
 // Check that .cppm is treated as a module implicitly.
 //
-// RUN: cp %s %t/module.cppm
-// RUN: %clang -std=c++2a --precompile %t/module.cppm -o %t/module.pcm -v 2>&1 
| FileCheck %s --check-prefix=CHECK-PRECOMPILE
+// RUN: cp %t/foo.cpp %t/foo.cppm
+// RUN: %clang -std=c++2a --precompile %t/foo.cppm -o %t/foo.pcm -v 2>&1 | 
FileCheck %s --check-prefix=CHECK-PRECOMPILE
 
+//--- foo.cpp
 export module foo;
+
+//--- foo_impl.cpp
+module foo;
diff --git a/clang/test/Modules/named-modules-adl-3.cppm 
b/clang/test/Modules/named-modules-adl-3.cppm
index d70946fa068b3..a3644b45a5347 100644
--- a/clang/test/Modules/named-modules-adl-3.cppm
+++ b/clang/test/Modules/named-modules-adl-3.cppm
@@ -58,6 +58,7 @@ void b(T x) {
 }
 
 //--- c.cppm
+module;
 #ifdef EXPORT_OPERATOR
 // expected-no-diagnostics
 #endif
diff --git a/clang/test/Modules/reserved-names-1.cppm 
b/clang/test/Modules/reserved-names-1.cppm
index e780f1e35b3b7..35b264bcb573b 100644
--- a/clang/test/Modules/reserved-names-1.cppm
+++ b/clang/test/Modules/reserved-names-1.cppm
@@ -88,12 +88,14 @@ export module module; // expected-error {{'module' is an 
invalid name for a modu
 export module import; // expected-error {{'import' is an invalid name for a 
module}}
 
 //--- _Test.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
 export module _Test;  // loud-warning {{'_Test' is a reserved name for a 
module}}
 
 //--- __test.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
@@ -101,6 +103,7 @@ export module __test; // loud-warning {{'__test' is a 
reserved name for a module
 export int a = 43;
 
 //--- te__st.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
@@ -108,6 +111,7 @@ export module te__st; // loud-warning {{'te__st' is a 
reserved name for a module
 export int a = 43;
 
 //--- std.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
@@ -116,36 +120,42 @@ export module std;    // loud-warning {{'std' is a 
reserved name for a module}}
 export int a = 43;
 
 //--- std.foo.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
 export module std.foo;// loud-warning {{'std' is a reserved name for a module}}
 
 //--- std0.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
 export module std0;   // loud-warning {{'std0' is a reserved name for a 
module}}
 
 //--- std1000000.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
 export module std1000000; // loud-warning {{'std1000000' is a reserved name 
for a module}}
 
 //--- should_diag._Test.cppm
+module;
 #ifdef NODIAGNOSTICS
 // expected-no-diagnostics
 #endif
 export module should_diag._Test; // loud-warning {{'_Test' is a reserved name 
for a module}}
 
 //--- system-module.cppm
+module; // expected-error {{missing 'module' declaration at end of global 
module fragment introduced here}}
 // Show that being in a system header doesn't save you from diagnostics about
 // use of an invalid module-name identifier.
 # 34 "reserved-names-1.cpp" 1 3
 export module module;       // expected-error {{'module' is an invalid name 
for a module}}
 
 //--- system._Test.import.cppm
+module; // expected-error {{missing 'module' declaration at end of global 
module fragment introduced here}}
 # 34 "reserved-names-1.cpp" 1 3
 export module _Test.import; // expected-error {{'import' is an invalid name 
for a module}}
 
diff --git a/clang/test/Modules/reserved-names-system-header-1.cpp 
b/clang/test/Modules/reserved-names-system-header-1.cpp
index 2db4c08add1d9..fa869483980f6 100644
--- a/clang/test/Modules/reserved-names-system-header-1.cpp
+++ b/clang/test/Modules/reserved-names-system-header-1.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
+module;
 // Show that we suppress the reserved identifier diagnostic in a system header.
 # 100 "file.cpp" 1 3  // Enter a system header
 export module std;
diff --git a/clang/test/Modules/reserved-names-system-header-2.cpp 
b/clang/test/Modules/reserved-names-system-header-2.cpp
index 2087f487721cb..d429e58dc1714 100644
--- a/clang/test/Modules/reserved-names-system-header-2.cpp
+++ b/clang/test/Modules/reserved-names-system-header-2.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
+module;
 // Show that we suppress the reserved identifier diagnostic in a system header.
 # 100 "file.cpp" 1 3  // Enter a system header
 export module __test;
diff --git a/clang/test/SemaCXX/modules.cppm b/clang/test/SemaCXX/modules.cppm
index 41204be76eafa..5d0d6da44a2ed 100644
--- a/clang/test/SemaCXX/modules.cppm
+++ b/clang/test/SemaCXX/modules.cppm
@@ -1,19 +1,20 @@
-// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %s -o %t.0.pcm 
-verify -DTEST=0
-// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %s -o %t.1.pcm 
-verify -DTEST=1
-// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %s 
-fmodule-file=foo=%t.0.pcm -o %t.2.pcm -verify -DTEST=2
-// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %s 
-fmodule-file=foo=%t.0.pcm -o %t.3.pcm -verify -Dfoo=bar -DTEST=3
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
 
-#if TEST == 0 || TEST == 2
-// expected-no-diagnostics
-#endif
+// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %t/test0.cpp -o 
%t/test0.pcm -verify
+// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %t/test1.cpp -o 
%t/test1.pcm -verify
+// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %t/test2.cpp 
-fmodule-file=foo=%t/test0.pcm -o %t/test2.pcm -verify
+// RUN:     %clang_cc1 -std=c++20 -emit-module-interface %t/test3.cpp 
-fmodule-file=foo=%t/test0.pcm -o %t/test3.pcm -verify
 
+//--- test0.cpp
+// expected-no-diagnostics
 export module foo;
 
 static int m;
 
 int n;
 
-#if TEST == 0
 export {
   int a;
   int b;
@@ -27,33 +28,18 @@ export void f() {}
 
 export struct T {
 } t;
-#elif TEST == 3
-int use_a = a; // expected-error {{use of undeclared identifier 'a'}}
 
-#undef foo
-import foo; // expected-error {{imports must immediately follow the module 
declaration}}
-
-export {}
-export {
-  ;       // No diagnostic after P2615R1 DR
-}
-export {
-  static_assert(true); // No diagnostic after P2615R1 DR
-}
+//--- test1.cpp
+export module foo;
 
-int use_b = b; // expected-error{{use of undeclared identifier 'b'}}
-int use_n = n; // FIXME: this should not be visible, because it is not exported
+static int m;
 
-extern int n;
-static_assert(&n != p); // expected-error{{use of undeclared identifier 'p'}}
-#endif
+int n;
 
-#if TEST == 1
 struct S {
   export int n;        // expected-error {{expected member name or ';'}}
   export static int n; // expected-error {{expected member name or ';'}}
 };
-#endif
 
 // FIXME: Exports of declarations without external linkage are disallowed.
 // Exports of declarations with non-external-linkage types are disallowed.
@@ -61,7 +47,6 @@ struct S {
 // Cannot export within another export. This isn't precisely covered by the
 // language rules right now, but (per personal correspondence between zygoloid
 // and gdr) is the intent.
-#if TEST == 1
 export { // expected-note {{export block begins here}}
   extern "C++" {
   namespace NestedExport {
@@ -71,4 +56,36 @@ export { // expected-note {{export block begins here}}
   } // namespace NestedExport
   }
 }
-#endif
+
+//--- test2.cpp
+// expected-no-diagnostics
+export module foo;
+
+static int m;
+
+int n;
+
+//--- test3.cpp
+export module bar;
+
+static int m;
+
+int n;
+
+int use_a = a; // expected-error {{use of undeclared identifier 'a'}}
+
+import foo; // expected-error {{imports must immediately follow the module 
declaration}}
+
+export {}
+export {
+  ;       // No diagnostic after P2615R1 DR
+}
+export {
+  static_assert(true); // No diagnostic after P2615R1 DR
+}
+
+int use_b = b; // expected-error{{use of undeclared identifier 'b'}}
+int use_n = n; // FIXME: this should not be visible, because it is not exported
+
+extern int n;
+static_assert(&n != p); // expected-error{{use of undeclared identifier 'p'}}
diff --git a/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp 
b/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp
index 7c0b967a3c03f..30fea464a8dc5 100644
--- a/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp
+++ b/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp
@@ -1,12 +1,22 @@
-// RUN: %clang_cc1  -fsyntax-only -verify %s -std=c++26 -fexceptions 
-DTRANSPARENT_DECL=0
-// RUN: %clang_cc1  -fsyntax-only -verify %s -std=c++26 -fexceptions 
-DTRANSPARENT_DECL=1
-// RUN: %clang_cc1  -fsyntax-only -verify %s -std=c++26 -fexceptions 
-DTRANSPARENT_DECL=2
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
 
+// RUN: %clang_cc1  -fsyntax-only -verify %t/testing.cpp -std=c++26 
-fexceptions -DTRANSPARENT_DECL=0
+// RUN: %clang_cc1  -fsyntax-only -verify %t/testing.cpp -std=c++26 
-fexceptions -DTRANSPARENT_DECL=1
+// RUN: %clang_cc1  -fsyntax-only -verify %t/module_testing.cppm -std=c++26 
-fexceptions -DTRANSPARENT_DECL=2
+
+//--- module_testing.cppm
 // expected-no-diagnostics
-#if TRANSPARENT_DECL==2
 export module Testing;
-#endif
 
+#include "testing.inc"
+
+//--- testing.cpp
+// expected-no-diagnostics
+#include "testing.inc"
+
+//--- testing.inc
 namespace std {
   template <class T> struct type_identity {};
   using size_t = __SIZE_TYPE__;

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to