aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-01-26 07:16:45 +0000
committerJohn McCall <rjmccall@apple.com>2010-01-26 07:16:45 +0000
commit7edb5fdf9703e1abd780417db691b77d5fcbc610 (patch)
tree3a2e028bf7408894a04ae9a10487edf6c67d811a /lib/Sema/SemaLookup.cpp
parentaec7caa3c40891727164167ece11d552422803d2 (diff)
Handle redeclarations found by ADL deterministically and reasonably.
This solution relies on an O(n) scan of redeclarations, which means it might scale poorly in crazy cases with tons of redeclarations brought in by a ton of distinct associated namespaces. I believe that avoiding this is not worth the common-case cost. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94530 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r--lib/Sema/SemaLookup.cpp49
1 files changed, 42 insertions, 7 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index c61d666c4b..9b91e22739 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1731,9 +1731,46 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
}
}
+void ADLResult::insert(NamedDecl *New) {
+ NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
+
+ // If we haven't yet seen a decl for this key, or the last decl
+ // was exactly this one, we're done.
+ if (Old == 0 || Old == New) {
+ Old = New;
+ return;
+ }
+
+ // Otherwise, decide which is a more recent redeclaration.
+ FunctionDecl *OldFD, *NewFD;
+ if (isa<FunctionTemplateDecl>(New)) {
+ OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
+ NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
+ } else {
+ OldFD = cast<FunctionDecl>(Old);
+ NewFD = cast<FunctionDecl>(New);
+ }
+
+ FunctionDecl *Cursor = NewFD;
+ while (true) {
+ Cursor = Cursor->getPreviousDeclaration();
+
+ // If we got to the end without finding OldFD, OldFD is the newer
+ // declaration; leave things as they are.
+ if (!Cursor) return;
+
+ // If we do find OldFD, then NewFD is newer.
+ if (Cursor == OldFD) break;
+
+ // Otherwise, keep looking.
+ }
+
+ Old = New;
+}
+
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
- ADLFunctionSet &Functions) {
+ ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@@ -1788,17 +1825,15 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- // FIXME: canonical decls.
- // See comment in AddArgumentDependentLookupCandidates().
-
if (isa<FunctionDecl>(D)) {
if (Operator &&
!IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
T1, T2, Context))
continue;
- Functions.insert(D);
- } else if (isa<FunctionTemplateDecl>(D))
- Functions.insert(D);
+ } else if (!isa<FunctionTemplateDecl>(D))
+ continue;
+
+ Result.insert(D);
}
}
}