aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2025-01-24 10:51:10 +0800
committerGitHub <noreply@github.com>2025-01-24 10:51:10 +0800
commit378dcf61014b787b3542b917f6296c9fb5ec490c (patch)
tree9d6d0227abee0f139c8371dbf445bc5187ec137d /clang/lib/Sema/SemaLookup.cpp
parent0ef39a882bb342982929d2c856d7865de147a3c7 (diff)
downloadllvm-378dcf61014b787b3542b917f6296c9fb5ec490c.zip
llvm-378dcf61014b787b3542b917f6296c9fb5ec490c.tar.gz
llvm-378dcf61014b787b3542b917f6296c9fb5ec490c.tar.bz2
[C++20] [Modules] Fix may-be incorrect ADL for module local entities (#123931)
Close https://github.com/llvm/llvm-project/issues/123815 See the comments for details. We can't get primary context arbitrarily since the redecl may have different context and information. There is a TODO for modules specific case, I'd like to make it after this PR.
Diffstat (limited to 'clang/lib/Sema/SemaLookup.cpp')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp52
1 files changed, 51 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 2ed8d36..5f8ffa7 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2914,7 +2914,57 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
while (!Ctx->isFileContext() || Ctx->isInlineNamespace())
Ctx = Ctx->getParent();
- Namespaces.insert(Ctx->getPrimaryContext());
+ // Actually it is fine to always do `Namespaces.insert(Ctx);` simply. But it
+ // may cause more allocations in Namespaces and more unnecessary lookups. So
+ // we'd like to insert the representative namespace only.
+ DeclContext *PrimaryCtx = Ctx->getPrimaryContext();
+ Decl *PrimaryD = cast<Decl>(PrimaryCtx);
+ Decl *D = cast<Decl>(Ctx);
+ ASTContext &AST = D->getASTContext();
+
+ // TODO: Technically it is better to insert one namespace per module. e.g.,
+ //
+ // ```
+ // //--- first.cppm
+ // export module first;
+ // namespace ns { ... } // first namespace
+ //
+ // //--- m-partA.cppm
+ // export module m:partA;
+ // import first;
+ //
+ // namespace ns { ... }
+ // namespace ns { ... }
+ //
+ // //--- m-partB.cppm
+ // export module m:partB;
+ // import first;
+ // import :partA;
+ //
+ // namespace ns { ... }
+ // namespace ns { ... }
+ //
+ // ...
+ //
+ // //--- m-partN.cppm
+ // export module m:partN;
+ // import first;
+ // import :partA;
+ // ...
+ // import :part$(N-1);
+ //
+ // namespace ns { ... }
+ // namespace ns { ... }
+ //
+ // consume(ns::any_decl); // the lookup
+ // ```
+ //
+ // We should only insert once for all namespaces in module m.
+ if (D->isInNamedModule() &&
+ !AST.isInSameModule(D->getOwningModule(), PrimaryD->getOwningModule()))
+ Namespaces.insert(Ctx);
+ else
+ Namespaces.insert(PrimaryCtx);
}
// Add the associated classes and namespaces for argument-dependent