[clang] 1d1f9af - [C++20] [Modules] Treat directly imported internal partition unit as reachable
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 12 02:46:52 PDT 2025
Author: Chuanqi Xu
Date: 2025-06-12T17:46:33+08:00
New Revision: 1d1f9afe911c360b9505b5fd2c712cb112c8aa5f
URL: https://github.com/llvm/llvm-project/commit/1d1f9afe911c360b9505b5fd2c712cb112c8aa5f
DIFF: https://github.com/llvm/llvm-project/commit/1d1f9afe911c360b9505b5fd2c712cb112c8aa5f.diff
LOG: [C++20] [Modules] Treat directly imported internal partition unit as reachable
Close https://github.com/llvm/llvm-project/issues/143788
See the discussion for details.
Added:
clang/test/Modules/pr143788.cppm
Modified:
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaModule.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index eef134b158438..91822909f1fd3 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1978,6 +1978,8 @@ bool LookupResult::isReachableSlow(Sema &SemaRef, NamedDecl *D) {
if (D->isModulePrivate())
return false;
+ Module *DeclTopModule = DeclModule->getTopLevelModule();
+
// [module.reach]/p1
// A translation unit U is necessarily reachable from a point P if U is a
// module interface unit on which the translation unit containing P has an
@@ -1996,17 +1998,28 @@ bool LookupResult::isReachableSlow(Sema &SemaRef, NamedDecl *D) {
//
// Here we only check for the first condition. Since we couldn't see
// DeclModule if it isn't (transitively) imported.
- if (DeclModule->getTopLevelModule()->isModuleInterfaceUnit())
+ if (DeclTopModule->isModuleInterfaceUnit())
return true;
- // [module.reach]/p2
+ // [module.reach]/p1,2
+ // A translation unit U is necessarily reachable from a point P if U is a
+ // module interface unit on which the translation unit containing P has an
+ // interface dependency, or the translation unit containing P imports U, in
+ // either case prior to P
+ //
// Additional translation units on
// which the point within the program has an interface dependency may be
// considered reachable, but it is unspecified which are and under what
// circumstances.
- //
- // The decision here is to treat all additional tranditional units as
- // unreachable.
+ Module *CurrentM = SemaRef.getCurrentModule();
+
+ // Directly imported module are necessarily reachable.
+ // Since we can't export import a module implementation partition unit, we
+ // don't need to count for Exports here.
+ if (CurrentM && CurrentM->getTopLevelModule()->Imports.count(DeclTopModule))
+ return true;
+
+ // Then we treat all module implementation partition unit as unreachable.
return false;
}
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 6c4df0aa35af5..9fcaad48d3058 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -712,7 +712,13 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
Diag(ExportLoc, diag::err_export_partition_impl)
<< SourceRange(ExportLoc, Path.back().getLoc());
- } else if (!ModuleScopes.empty() && !currentModuleIsImplementation()) {
+ } else if (ExportLoc.isValid() &&
+ (ModuleScopes.empty() || currentModuleIsImplementation())) {
+ // [module.interface]p1:
+ // An export-declaration shall inhabit a namespace scope and appear in the
+ // purview of a module interface unit.
+ Diag(ExportLoc, diag::err_export_not_in_module_interface);
+ } else if (!ModuleScopes.empty()) {
// Re-export the module if the imported module is exported.
// Note that we don't need to add re-exported module to Imports field
// since `Exports` implies the module is imported already.
@@ -720,11 +726,6 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
getCurrentModule()->Exports.emplace_back(Mod, false);
else
getCurrentModule()->Imports.insert(Mod);
- } else if (ExportLoc.isValid()) {
- // [module.interface]p1:
- // An export-declaration shall inhabit a namespace scope and appear in the
- // purview of a module interface unit.
- Diag(ExportLoc, diag::err_export_not_in_module_interface);
}
return Import;
diff --git a/clang/test/Modules/pr143788.cppm b/clang/test/Modules/pr143788.cppm
new file mode 100644
index 0000000000000..5ae36d8d0e85a
--- /dev/null
+++ b/clang/test/Modules/pr143788.cppm
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-module-interface -o %t/M.pcm
+// RUN: %clang_cc1 -std=c++20 %t/P.cppm -emit-module-interface -o %t/P.pcm
+// RUN: %clang_cc1 -std=c++20 %t/I.cpp -fmodule-file=M:P=%t/P.pcm -fmodule-file=M=%t/M.pcm -fsyntax-only -verify
+
+//--- H.hpp
+struct S{};
+
+//--- M.cppm
+export module M;
+
+
+//--- P.cppm
+module;
+#include "H.hpp"
+module M:P;
+
+using T = S;
+
+//--- I.cpp
+// expected-no-diagnostics
+module M;
+import :P;
+
+T f() { return {}; }
More information about the cfe-commits
mailing list