Skip to content

Commit f09050f

Browse files
committed
[C++20] [Modules] Fix module local lookup ambiguousity
Close #61360 Close #129525 Close #143734 We shouldn't identify different module local decls in different modules as the same entity.
1 parent 5f231db commit f09050f

File tree

6 files changed

+76
-4
lines changed

6 files changed

+76
-4
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
488488
/// if possible.
489489
///
490490
/// Not serialized intentionally.
491-
llvm::StringMap<const Module *> PrimaryModuleNameMap;
492-
llvm::DenseMap<const Module *, const Module *> SameModuleLookupSet;
491+
mutable llvm::StringMap<const Module *> PrimaryModuleNameMap;
492+
mutable llvm::DenseMap<const Module *, const Module *> SameModuleLookupSet;
493493

494494
static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
495495
static constexpr unsigned GeneralTypesLog2InitSize = 9;
@@ -1151,7 +1151,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
11511151
///
11521152
/// FIXME: The signature may be confusing since `clang::Module` means to
11531153
/// a module fragment or a module unit but not a C++20 module.
1154-
bool isInSameModule(const Module *M1, const Module *M2);
1154+
bool isInSameModule(const Module *M1, const Module *M2) const;
11551155

11561156
TranslationUnitDecl *getTranslationUnitDecl() const {
11571157
return TUDecl->getMostRecentDecl();

clang/include/clang/AST/DeclBase.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,10 @@ class alignas(8) Decl {
646646
return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
647647
}
648648

649+
/// Whether this declaration was a local declaration to a C++20
650+
/// named module.
651+
bool isModuleLocal() const;
652+
649653
/// Whether this declaration was exported in a lexical context.
650654
/// e.g.:
651655
///

clang/lib/AST/ASTContext.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,7 @@ void ASTContext::setCurrentNamedModule(Module *M) {
11751175
CurrentCXXNamedModule = M;
11761176
}
11771177

1178-
bool ASTContext::isInSameModule(const Module *M1, const Module *M2) {
1178+
bool ASTContext::isInSameModule(const Module *M1, const Module *M2) const {
11791179
if (!M1 != !M2)
11801180
return false;
11811181

@@ -7429,6 +7429,12 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
74297429
cast<Decl>(Y->getDeclContext()->getRedeclContext())))
74307430
return false;
74317431

7432+
// If either X or Y are local to the owning module, they are only possible to
7433+
// be the same entity if they are in the same module.
7434+
if (X->isModuleLocal() || Y->isModuleLocal())
7435+
if (!isInSameModule(X->getOwningModule(), Y->getOwningModule()))
7436+
return false;
7437+
74327438
// Two typedefs refer to the same entity if they have the same underlying
74337439
// type.
74347440
if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X))

clang/lib/AST/DeclBase.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,12 @@ bool Decl::isInExportDeclContext() const {
11321132
return isa_and_nonnull<ExportDecl>(DC);
11331133
}
11341134

1135+
bool Decl::isModuleLocal() const {
1136+
auto *M = getOwningModule();
1137+
return M && M->isNamedModule() &&
1138+
getModuleOwnershipKind() == ModuleOwnershipKind::ReachableWhenImported;
1139+
}
1140+
11351141
bool Decl::isInAnotherModuleUnit() const {
11361142
auto *M = getOwningModule();
11371143

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fprebuilt-module-path=%t -emit-llvm -o %t/B.ll
7+
8+
//--- A.cppm
9+
export module A;
10+
11+
export template<typename>
12+
struct holder {
13+
};
14+
15+
struct foo {};
16+
17+
export struct a {
18+
holder<foo> m;
19+
};
20+
21+
//--- B.cppm
22+
// expected-no-diagnostics
23+
export module B;
24+
25+
import A;
26+
27+
struct foo {};
28+
29+
struct b {
30+
holder<foo> m;
31+
};

clang/test/Modules/pr61360.cppm

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fprebuilt-module-path=%t -emit-llvm -o %t/B.ll
7+
8+
//--- A.cppm
9+
export module A;
10+
export template<typename>
11+
struct holder {
12+
};
13+
14+
struct a {
15+
holder<struct foo> m;
16+
};
17+
18+
//--- B.cppm
19+
// expected-no-diagnostics
20+
export module B;
21+
import A;
22+
23+
struct b {
24+
holder<struct foo> m;
25+
};

0 commit comments

Comments
 (0)