Author: Victor Chernyakin
Date: 2026-03-26T21:59:25-07:00
New Revision: 9c98207e16ad9135abd732caf55cdbf215717210

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

LOG: [clang][Modules] Reject export declarations in implementation partitions 
(#188698)

[module.interface]/1 says:

> An export-declaration shall [...] appear in the purview of
   a module interface unit.

But clang currently fails to enforce this rule in implementation
partitions.

Partially addresses #107602.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Sema/Sema.h
    clang/test/CXX/module/module.interface/p1.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 80913393e69c5..0f1190510f0f8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -46,6 +46,9 @@ C++ Specific Potentially Breaking Changes
 - Clang now more aggressively optimizes away stores to objects after they are
   dead. This behavior can be disabled with ``-fno-lifetime-dse``.
 
+- Clang now correctly rejects ``export`` declarations in module implementation
+  partitions. (#GH107602)
+
 ABI Changes in This Version
 ---------------------------
 

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9c4af2e2f986c..4e6058b8e5f79 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9931,9 +9931,10 @@ class Sema final : public SemaBase {
 
   /// Is the module scope we are an implementation unit?
   bool currentModuleIsImplementation() const {
-    return ModuleScopes.empty()
-               ? false
-               : ModuleScopes.back().Module->isModuleImplementation();
+    if (ModuleScopes.empty())
+      return false;
+    const Module *M = ModuleScopes.back().Module;
+    return M->isModuleImplementation() || M->isModulePartitionImplementation();
   }
 
   // When loading a non-modular PCH files, this is used to restore module

diff  --git a/clang/test/CXX/module/module.interface/p1.cpp 
b/clang/test/CXX/module/module.interface/p1.cpp
index 1754d9ea14618..d3e4f756452db 100644
--- a/clang/test/CXX/module/module.interface/p1.cpp
+++ b/clang/test/CXX/module/module.interface/p1.cpp
@@ -4,6 +4,8 @@
 // RUN: %clang_cc1 -std=c++2a %t/errors.cpp -verify
 // RUN: %clang_cc1 -std=c++2a %t/M.cppm -emit-module-interface -o %t/M.pcm
 // RUN: %clang_cc1 -std=c++2a %t/impl.cpp -fmodule-file=M=%t/M.pcm -verify
+// RUN: %clang_cc1 -std=c++2a %t/interface-partition.cppm 
-emit-module-interface -o %t/L-P1.pcm
+// RUN: %clang_cc1 -std=c++2a %t/implementation-partition.cpp 
-fmodule-file=L:P1=%t/L-P1.pcm -verify
 
 //--- errors.cpp
 module;
@@ -42,3 +44,19 @@ namespace N {
   export int c2; // expected-error {{export declaration can only be used 
within a module interface}}
 }
 // expected-note@#M 2+{{add 'export'}}
+
+//--- interface-partition.cppm
+
+export module L:P1;
+
+//--- implementation-partition.cpp
+
+module L:P2; // #M
+
+export import :P1; // expected-error {{export declaration can only be used 
within a module interface}}
+
+export int b3; // expected-error {{export declaration can only be used within 
a module interface}}
+namespace N {
+  export int c3; // expected-error {{export declaration can only be used 
within a module interface}}
+}
+// expected-note@#M 2+{{add 'export'}}


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

Reply via email to