Author: Chuanqi Xu
Date: 2026-08-10T11:37:28Z
New Revision: 878be2fadd3a1695eec2018e7f2001859ff87e4f

URL: 
https://github.com/llvm/llvm-project/commit/878be2fadd3a1695eec2018e7f2001859ff87e4f
DIFF: 
https://github.com/llvm/llvm-project/commit/878be2fadd3a1695eec2018e7f2001859ff87e4f.diff

LOG: [C++20] [Modules] Don't treat non-named-module as interface unit for 
implementation unit (#215241)

Close https://github.com/llvm/llvm-project/issues/204633

Added: 
    clang/test/Modules/GH204633.cppm

Modified: 
    clang/lib/Sema/SemaModule.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 667f36ab737ed..42c67cf89ed88 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -424,6 +424,11 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
                                              /*IsInclusionDirective=*/false);
     const_cast<LangOptions &>(getLangOpts()).CurrentModule = ModuleName;
 
+    // A Clang module or a header unit cannot serve as the primary module
+    // interface while recovering from an implementation unit declaration.
+    if (Interface && !Interface->isNamedModule())
+      return nullptr;
+
     if (!Interface) {
       Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
       // Create an empty module interface unit for error recovery.

diff  --git a/clang/test/Modules/GH204633.cppm 
b/clang/test/Modules/GH204633.cppm
new file mode 100644
index 0000000000000..4bcd1200a5568
--- /dev/null
+++ b/clang/test/Modules/GH204633.cppm
@@ -0,0 +1,23 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -std=c++26 -triple x86_64-pc-win32 -fsyntax-only -fmodules \
+// RUN:   -fimplicit-module-maps -fmodules-cache-path=%t \
+// RUN:   -fmodule-map-file=%t/original.cppm -verify %t/original.cppm
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fmodules -verify %t/inline.cppm
+
+// Use the same file as both the source input and the module map. The module 
map
+// parser accepts this as a Clang module definition, while the C++ parser
+// diagnoses it as a malformed module declaration.
+//--- original.cppm
+// expected-error@+2 {{unexpected preprocessing token '{' after module name}}
+// expected-error@+1 {{module directive must end with a ';'}}
+module M {}
+
+// Build the conflicting Clang module inline.
+//--- inline.cppm
+// expected-no-diagnostics
+#pragma clang module build Foo
+module Foo {}
+#pragma clang module endbuild
+
+module Foo;


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

Reply via email to