[C++20] [Modules] Fix module local lookup ambiguousity Close https://github.com/llvm/llvm-project/issues/61360 Close https://github.com/llvm/llvm-project/issues/129525 Close https://github.com/llvm/llvm-project/issues/143734 We shouldn't identify different module local decls in different modules as the same entity.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8d24d393..3abb493 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h
@@ -488,8 +488,8 @@ /// if possible. /// /// Not serialized intentionally. - llvm::StringMap<const Module *> PrimaryModuleNameMap; - llvm::DenseMap<const Module *, const Module *> SameModuleLookupSet; + mutable llvm::StringMap<const Module *> PrimaryModuleNameMap; + mutable llvm::DenseMap<const Module *, const Module *> SameModuleLookupSet; static constexpr unsigned ConstantArrayTypesLog2InitSize = 8; static constexpr unsigned GeneralTypesLog2InitSize = 9; @@ -1151,7 +1151,7 @@ /// /// FIXME: The signature may be confusing since `clang::Module` means to /// a module fragment or a module unit but not a C++20 module. - bool isInSameModule(const Module *M1, const Module *M2); + bool isInSameModule(const Module *M1, const Module *M2) const; TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl->getMostRecentDecl();
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 375e9e2..dd67ebc 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h
@@ -646,6 +646,10 @@ return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate; } + /// Whether this declaration was a local declaration to a C++20 + /// named module. + bool isModuleLocal() const; + /// Whether this declaration was exported in a lexical context. /// e.g.: ///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b51f762..4d44f23c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp
@@ -1175,7 +1175,7 @@ CurrentCXXNamedModule = M; } -bool ASTContext::isInSameModule(const Module *M1, const Module *M2) { +bool ASTContext::isInSameModule(const Module *M1, const Module *M2) const { if (!M1 != !M2) return false; @@ -7429,6 +7429,12 @@ cast<Decl>(Y->getDeclContext()->getRedeclContext()))) return false; + // If either X or Y are local to the owning module, they are only possible to + // be the same entity if they are in the same module. + if (X->isModuleLocal() || Y->isModuleLocal()) + if (!isInSameModule(X->getOwningModule(), Y->getOwningModule())) + return false; + // Two typedefs refer to the same entity if they have the same underlying // type. if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X))
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index a1bb62b..48c60aa 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp
@@ -1132,6 +1132,12 @@ return isa_and_nonnull<ExportDecl>(DC); } +bool Decl::isModuleLocal() const { + auto *M = getOwningModule(); + return M && M->isNamedModule() && + getModuleOwnershipKind() == ModuleOwnershipKind::ReachableWhenImported; +} + bool Decl::isInAnotherModuleUnit() const { auto *M = getOwningModule();
diff --git a/clang/test/Modules/module-local-declarations-02.cppm b/clang/test/Modules/module-local-declarations-02.cppm new file mode 100644 index 0000000..0670c42 --- /dev/null +++ b/clang/test/Modules/module-local-declarations-02.cppm
@@ -0,0 +1,31 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fprebuilt-module-path=%t -emit-llvm -o %t/B.ll + +//--- A.cppm +export module A; + +export template<typename> +struct holder { +}; + +struct foo {}; + +export struct a { + holder<foo> m; +}; + +//--- B.cppm +// expected-no-diagnostics +export module B; + +import A; + +struct foo {}; + +struct b { + holder<foo> m; +}; \ No newline at end of file
diff --git a/clang/test/Modules/pr61360.cppm b/clang/test/Modules/pr61360.cppm new file mode 100644 index 0000000..a16f65d --- /dev/null +++ b/clang/test/Modules/pr61360.cppm
@@ -0,0 +1,25 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fprebuilt-module-path=%t -emit-llvm -o %t/B.ll + +//--- A.cppm +export module A; +export template<typename> +struct holder { +}; + +struct a { + holder<struct foo> m; +}; + +//--- B.cppm +// expected-no-diagnostics +export module B; +import A; + +struct b { + holder<struct foo> m; +};