diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Lookup.h | 38 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 49 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 11 |
4 files changed, 87 insertions, 16 deletions
diff --git a/clang/lib/Sema/Lookup.h b/clang/lib/Sema/Lookup.h index 0c0f363cbd7..fa6f0370264 100644 --- a/clang/lib/Sema/Lookup.h +++ b/clang/lib/Sema/Lookup.h @@ -587,6 +587,44 @@ private: virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) = 0; }; + +/// \brief A class for storing results from argument-dependent lookup. +class ADLResult { +private: + /// A map from canonical decls to the 'most recent' decl. + llvm::DenseMap<NamedDecl*, NamedDecl*> Decls; + +public: + /// Adds a new ADL candidate to this map. + void insert(NamedDecl *D); + + /// Removes any data associated with a given decl. + void erase(NamedDecl *D) { + Decls.erase(cast<NamedDecl>(D->getCanonicalDecl())); + } + + class iterator { + typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator; + inner_iterator iter; + + friend class ADLResult; + iterator(const inner_iterator &iter) : iter(iter) {} + public: + iterator() {} + + iterator &operator++() { ++iter; return *this; } + iterator operator++(int) { return iterator(iter++); } + + NamedDecl *operator*() const { return iter->second; } + + bool operator==(const iterator &other) const { return iter == other.iter; } + bool operator!=(const iterator &other) const { return iter != other.iter; } + }; + + iterator begin() { return iterator(Decls.begin()); } + iterator end() { return iterator(Decls.end()); } +}; + } #endif diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 42dac8fafc1..d041f54a023 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -103,6 +103,7 @@ namespace clang { class InitializationSequence; class VisibleDeclConsumer; class TargetAttributesSema; + class ADLResult; /// BlockSemaInfo - When a block is being parsed, this contains information /// about the block. It is pointed to from Sema::CurBlock. @@ -950,8 +951,6 @@ public: // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet; - // Members have to be a function or function template. - typedef llvm::SmallPtrSet<NamedDecl*, 16> ADLFunctionSet; typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; void AddOverloadCandidate(NamedDecl *Function, @@ -1240,7 +1239,7 @@ public: void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - ADLFunctionSet &Functions); + ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index c61d666c4b0..9b91e227392 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/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); } } } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index a4c11b077a2..0fba0c62281 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -4131,7 +4131,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, const TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading) { - ADLFunctionSet Functions; + ADLResult Fns; // FIXME: This approach for uniquing ADL results (and removing // redundant candidates from the set) relies on pointer-equality, @@ -4141,22 +4141,21 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Operator, Args, NumArgs, Functions); + ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns); // Erase all of the candidates we already knew about. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); Cand != CandEnd; ++Cand) if (Cand->Function) { - Functions.erase(Cand->Function); + Fns.erase(Cand->Function); if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) - Functions.erase(FunTmpl); + Fns.erase(FunTmpl); } // For each of the ADL candidates we found, add it to the overload // set. - for (ADLFunctionSet::iterator I = Functions.begin(), - E = Functions.end(); I != E; ++I) { + for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { if (ExplicitTemplateArgs) continue; |