https://github.com/hongtaihu updated 
https://github.com/llvm/llvm-project/pull/225099

>From a1bb39e574e352e16c5eed8fbce08dddd9f9dd76 Mon Sep 17 00:00:00 2001
From: hongtaihu <[email protected]>
Date: Mon, 21 Sep 2026 22:56:49 +0800
Subject: [PATCH] [clang][Modules] Don't treat recovered module-end at EOF as
 an included header

When a #pragma clang module begin is left unclosed, the parser
synthesizes an annot_module_end at EOF. ActOnAnnotModuleEnd treated any
EOM at EOF as the end of a #included module header and asserted that
this could not happen in the main file.

That is not true for this recovery path: the main file has no include
location. Only use the include location when getIncludeLoc() is valid;
otherwise keep the annotation location. The original assertion is kept
on the included-header path, where that invariant still holds.

Fixes #203167
---
 clang/lib/Sema/SemaModule.cpp   | 11 +++++++----
 clang/test/Modules/GH203167.cpp |  7 +++++++
 2 files changed, 14 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/Modules/GH203167.cpp

diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 7dbb38bbe078e..da056230fd51c 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -815,13 +815,16 @@ void Sema::ActOnAnnotModuleEnd(SourceLocation EomLoc, 
Module *Mod) {
   // ImportDecl as we would for an imported module.
   FileID File = getSourceManager().getFileID(EomLoc);
   SourceLocation DirectiveLoc;
-  if (EomLoc == getSourceManager().getLocForEndOfFile(File)) {
+  SourceLocation IncludeLoc = getSourceManager().getIncludeLoc(File);
+  if (EomLoc == getSourceManager().getLocForEndOfFile(File) &&
+      IncludeLoc.isValid()) {
     // We reached the end of a #included module header. Use the #include loc.
     assert(File != getSourceManager().getMainFileID() &&
-           "end of submodule in main source file");
-    DirectiveLoc = getSourceManager().getIncludeLoc(File);
+           "included module header should not be the main source file");
+    DirectiveLoc = IncludeLoc;
   } else {
-    // We reached an EOM pragma. Use the pragma location.
+    // We reached an EOM pragma, possibly synthesized at EOF for recovery. Use
+    // the annotation location.
     DirectiveLoc = EomLoc;
   }
   BuildModuleInclude(DirectiveLoc, Mod);
diff --git a/clang/test/Modules/GH203167.cpp b/clang/test/Modules/GH203167.cpp
new file mode 100644
index 0000000000000..d8105cb0978d9
--- /dev/null
+++ b/clang/test/Modules/GH203167.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++20 -fmodules -fsyntax-only -verify %s
+
+#pragma clang module build N // expected-error {{no matching '#pragma clang 
module endbuild'}}
+module N {}
+#pragma clang module contents
+#pragma clang module begin N // expected-error {{no matching '#pragma clang 
module end'}}
+int x;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to