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 {}; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits