https://github.com/hongtaihu updated https://github.com/llvm/llvm-project/pull/225099
>From 5a4219be1ea7c1c79df6e26b0cd65eaad25b9d73 Mon Sep 17 00:00:00 2001 From: hongtaihu <[email protected]> Date: Mon, 21 Sep 2026 22:33:17 +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. Fixes #203167 --- clang/lib/Sema/SemaModule.cpp | 11 +++++++---- clang/test/Modules/GH203167-header.cpp | 8 ++++++++ clang/test/Modules/GH203167.cpp | 12 ++++++++++++ clang/test/Modules/Inputs/GH203167.h | 5 +++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 clang/test/Modules/GH203167-header.cpp create mode 100644 clang/test/Modules/GH203167.cpp create mode 100644 clang/test/Modules/Inputs/GH203167.h 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-header.cpp b/clang/test/Modules/GH203167-header.cpp new file mode 100644 index 0000000000000..de6f2066ad01a --- /dev/null +++ b/clang/test/Modules/GH203167-header.cpp @@ -0,0 +1,8 @@ +// RUN: not %clang_cc1 -std=c++20 -fmodules -fsyntax-only -I %S/Inputs %s 2> %t +// RUN: FileCheck %s < %t + +#include "GH203167.h" + +// CHECK: error: no matching '#pragma clang module endbuild' +// CHECK: error: no matching '#pragma clang module end' +// CHECK-NOT: Assertion diff --git a/clang/test/Modules/GH203167.cpp b/clang/test/Modules/GH203167.cpp new file mode 100644 index 0000000000000..ff69a19a84d58 --- /dev/null +++ b/clang/test/Modules/GH203167.cpp @@ -0,0 +1,12 @@ +// RUN: not %clang_cc1 -std=c++20 -fmodules -fsyntax-only %s 2> %t +// RUN: FileCheck %s < %t + +#pragma clang module build N +module N {} +#pragma clang module contents +#pragma clang module begin N +int x; + +// CHECK: error: no matching '#pragma clang module endbuild' +// CHECK: error: no matching '#pragma clang module end' +// CHECK-NOT: Assertion diff --git a/clang/test/Modules/Inputs/GH203167.h b/clang/test/Modules/Inputs/GH203167.h new file mode 100644 index 0000000000000..d48f6d1c5aa7f --- /dev/null +++ b/clang/test/Modules/Inputs/GH203167.h @@ -0,0 +1,5 @@ +#pragma clang module build N +module N {} +#pragma clang module contents +#pragma clang module begin N +int x; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
