diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Sema/SemaLookup.cpp | |
parent | 5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff) |
Notes
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 1482 |
1 files changed, 709 insertions, 773 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 6f2fc5e0c434b..dd877c16fba79 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -12,18 +12,20 @@ // //===----------------------------------------------------------------------===// #include "Sema.h" -#include "SemaInherit.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/ErrorHandling.h" #include <set> #include <vector> #include <iterator> @@ -34,7 +36,6 @@ using namespace clang; typedef llvm::SmallVector<UsingDirectiveDecl*, 4> UsingDirectivesTy; typedef llvm::DenseSet<NamespaceDecl*> NamespaceSet; -typedef llvm::SmallVector<Sema::LookupResult, 3> LookupResultsTy; /// UsingDirAncestorCompare - Implements strict weak ordering of /// UsingDirectives. It orders them by address of its common ancestor. @@ -59,7 +60,7 @@ struct UsingDirAncestorCompare { /// AddNamespaceUsingDirectives - Adds all UsingDirectiveDecl's to heap UDirs /// (ordered by common ancestors), found in namespace NS, /// including all found (recursively) in their nominated namespaces. -void AddNamespaceUsingDirectives(ASTContext &Context, +void AddNamespaceUsingDirectives(ASTContext &Context, DeclContext *NS, UsingDirectivesTy &UDirs, NamespaceSet &Visited) { @@ -76,7 +77,7 @@ void AddNamespaceUsingDirectives(ASTContext &Context, /// AddScopeUsingDirectives - Adds all UsingDirectiveDecl's found in Scope S, /// including all found in the namespaces they nominate. -static void AddScopeUsingDirectives(ASTContext &Context, Scope *S, +static void AddScopeUsingDirectives(ASTContext &Context, Scope *S, UsingDirectivesTy &UDirs) { NamespaceSet VisitedNS; @@ -99,189 +100,17 @@ static void AddScopeUsingDirectives(ASTContext &Context, Scope *S, NamespaceDecl *Nominated = UD->getNominatedNamespace(); if (!VisitedNS.count(Nominated)) { VisitedNS.insert(Nominated); - AddNamespaceUsingDirectives(Context, Nominated, UDirs, + AddNamespaceUsingDirectives(Context, Nominated, UDirs, /*ref*/ VisitedNS); } } } } -/// MaybeConstructOverloadSet - Name lookup has determined that the -/// elements in [I, IEnd) have the name that we are looking for, and -/// *I is a match for the namespace. This routine returns an -/// appropriate Decl for name lookup, which may either be *I or an -/// OverloadedFunctionDecl that represents the overloaded functions in -/// [I, IEnd). -/// -/// The existance of this routine is temporary; users of LookupResult -/// should be able to handle multiple results, to deal with cases of -/// ambiguity and overloaded functions without needing to create a -/// Decl node. -template<typename DeclIterator> -static NamedDecl * -MaybeConstructOverloadSet(ASTContext &Context, - DeclIterator I, DeclIterator IEnd) { - assert(I != IEnd && "Iterator range cannot be empty"); - assert(!isa<OverloadedFunctionDecl>(*I) && - "Cannot have an overloaded function"); - - if ((*I)->isFunctionOrFunctionTemplate()) { - // If we found a function, there might be more functions. If - // so, collect them into an overload set. - DeclIterator Last = I; - OverloadedFunctionDecl *Ovl = 0; - for (++Last; - Last != IEnd && (*Last)->isFunctionOrFunctionTemplate(); - ++Last) { - if (!Ovl) { - // FIXME: We leak this overload set. Eventually, we want to stop - // building the declarations for these overload sets, so there will be - // nothing to leak. - Ovl = OverloadedFunctionDecl::Create(Context, (*I)->getDeclContext(), - (*I)->getDeclName()); - NamedDecl *ND = (*I)->getUnderlyingDecl(); - if (isa<FunctionDecl>(ND)) - Ovl->addOverload(cast<FunctionDecl>(ND)); - else - Ovl->addOverload(cast<FunctionTemplateDecl>(ND)); - } - - NamedDecl *ND = (*Last)->getUnderlyingDecl(); - if (isa<FunctionDecl>(ND)) - Ovl->addOverload(cast<FunctionDecl>(ND)); - else - Ovl->addOverload(cast<FunctionTemplateDecl>(ND)); - } - - // If we had more than one function, we built an overload - // set. Return it. - if (Ovl) - return Ovl; - } - - return *I; -} - -/// Merges together multiple LookupResults dealing with duplicated Decl's. -static Sema::LookupResult -MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) { - typedef Sema::LookupResult LResult; - typedef llvm::SmallPtrSet<NamedDecl*, 4> DeclsSetTy; - - // Remove duplicated Decl pointing at same Decl, by storing them in - // associative collection. This might be case for code like: - // - // namespace A { int i; } - // namespace B { using namespace A; } - // namespace C { using namespace A; } - // - // void foo() { - // using namespace B; - // using namespace C; - // ++i; // finds A::i, from both namespace B and C at global scope - // } - // - // C++ [namespace.qual].p3: - // The same declaration found more than once is not an ambiguity - // (because it is still a unique declaration). - DeclsSetTy FoundDecls; - - // Counter of tag names, and functions for resolving ambiguity - // and name hiding. - std::size_t TagNames = 0, Functions = 0, OrdinaryNonFunc = 0; - - LookupResultsTy::iterator I = Results.begin(), End = Results.end(); - - // No name lookup results, return early. - if (I == End) return LResult::CreateLookupResult(Context, 0); - - // Keep track of the tag declaration we found. We only use this if - // we find a single tag declaration. - TagDecl *TagFound = 0; - - for (; I != End; ++I) { - switch (I->getKind()) { - case LResult::NotFound: - assert(false && - "Should be always successful name lookup result here."); - break; - - case LResult::AmbiguousReference: - case LResult::AmbiguousBaseSubobjectTypes: - case LResult::AmbiguousBaseSubobjects: - assert(false && "Shouldn't get ambiguous lookup here."); - break; - - case LResult::Found: { - NamedDecl *ND = I->getAsDecl()->getUnderlyingDecl(); - - if (TagDecl *TD = dyn_cast<TagDecl>(ND)) { - TagFound = Context.getCanonicalDecl(TD); - TagNames += FoundDecls.insert(TagFound)? 1 : 0; - } else if (ND->isFunctionOrFunctionTemplate()) - Functions += FoundDecls.insert(ND)? 1 : 0; - else - FoundDecls.insert(ND); - break; - } - - case LResult::FoundOverloaded: - for (LResult::iterator FI = I->begin(), FEnd = I->end(); FI != FEnd; ++FI) - Functions += FoundDecls.insert(*FI)? 1 : 0; - break; - } - } - OrdinaryNonFunc = FoundDecls.size() - TagNames - Functions; - bool Ambiguous = false, NameHidesTags = false; - - if (FoundDecls.size() == 1) { - // 1) Exactly one result. - } else if (TagNames > 1) { - // 2) Multiple tag names (even though they may be hidden by an - // object name). - Ambiguous = true; - } else if (FoundDecls.size() - TagNames == 1) { - // 3) Ordinary name hides (optional) tag. - NameHidesTags = TagFound; - } else if (Functions) { - // C++ [basic.lookup].p1: - // ... Name lookup may associate more than one declaration with - // a name if it finds the name to be a function name; the declarations - // are said to form a set of overloaded functions (13.1). - // Overload resolution (13.3) takes place after name lookup has succeeded. - // - if (!OrdinaryNonFunc) { - // 4) Functions hide tag names. - NameHidesTags = TagFound; - } else { - // 5) Functions + ordinary names. - Ambiguous = true; - } - } else { - // 6) Multiple non-tag names - Ambiguous = true; - } - - if (Ambiguous) - return LResult::CreateLookupResult(Context, - FoundDecls.begin(), FoundDecls.size()); - if (NameHidesTags) { - // There's only one tag, TagFound. Remove it. - assert(TagFound && FoundDecls.count(TagFound) && "No tag name found?"); - FoundDecls.erase(TagFound); - } - - // Return successful name lookup result. - return LResult::CreateLookupResult(Context, - MaybeConstructOverloadSet(Context, - FoundDecls.begin(), - FoundDecls.end())); -} - // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. -inline unsigned -getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, +inline unsigned +getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, bool CPlusPlus) { unsigned IDNS = 0; switch (NameKind) { @@ -300,7 +129,7 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, case Sema::LookupMemberName: IDNS = Decl::IDNS_Member; if (CPlusPlus) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; break; case Sema::LookupNestedNameSpecifierName: @@ -323,97 +152,81 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, return IDNS; } -Sema::LookupResult -Sema::LookupResult::CreateLookupResult(ASTContext &Context, NamedDecl *D) { - if (D) - D = D->getUnderlyingDecl(); - - LookupResult Result; - Result.StoredKind = (D && isa<OverloadedFunctionDecl>(D))? - OverloadedDeclSingleDecl : SingleDecl; - Result.First = reinterpret_cast<uintptr_t>(D); - Result.Last = 0; - Result.Context = &Context; - return Result; +// Necessary because CXXBasePaths is not complete in Sema.h +void Sema::LookupResult::deletePaths(CXXBasePaths *Paths) { + delete Paths; } -/// @brief Moves the name-lookup results from Other to this LookupResult. -Sema::LookupResult -Sema::LookupResult::CreateLookupResult(ASTContext &Context, - IdentifierResolver::iterator F, - IdentifierResolver::iterator L) { - LookupResult Result; - Result.Context = &Context; - - if (F != L && (*F)->isFunctionOrFunctionTemplate()) { - IdentifierResolver::iterator Next = F; - ++Next; - if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) { - Result.StoredKind = OverloadedDeclFromIdResolver; - Result.First = F.getAsOpaqueValue(); - Result.Last = L.getAsOpaqueValue(); - return Result; - } - } - - NamedDecl *D = *F; - if (D) - D = D->getUnderlyingDecl(); - - Result.StoredKind = SingleDecl; - Result.First = reinterpret_cast<uintptr_t>(D); - Result.Last = 0; - return Result; -} - -Sema::LookupResult -Sema::LookupResult::CreateLookupResult(ASTContext &Context, - DeclContext::lookup_iterator F, - DeclContext::lookup_iterator L) { - LookupResult Result; - Result.Context = &Context; - - if (F != L && (*F)->isFunctionOrFunctionTemplate()) { - DeclContext::lookup_iterator Next = F; - ++Next; - if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) { - Result.StoredKind = OverloadedDeclFromDeclContext; - Result.First = reinterpret_cast<uintptr_t>(F); - Result.Last = reinterpret_cast<uintptr_t>(L); - return Result; - } - } +void Sema::LookupResult::resolveKind() { + unsigned N = Decls.size(); - NamedDecl *D = *F; - if (D) - D = D->getUnderlyingDecl(); - - Result.StoredKind = SingleDecl; - Result.First = reinterpret_cast<uintptr_t>(D); - Result.Last = 0; - return Result; -} + // Fast case: no possible ambiguity. + if (N <= 1) return; -/// @brief Determine the result of name lookup. -Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const { - switch (StoredKind) { - case SingleDecl: - return (reinterpret_cast<Decl *>(First) != 0)? Found : NotFound; + // Don't do any extra resolution if we've already resolved as ambiguous. + if (Kind == Ambiguous) return; - case OverloadedDeclSingleDecl: - case OverloadedDeclFromIdResolver: - case OverloadedDeclFromDeclContext: - return FoundOverloaded; + llvm::SmallPtrSet<NamedDecl*, 16> Unique; - case AmbiguousLookupStoresBasePaths: - return Last? AmbiguousBaseSubobjectTypes : AmbiguousBaseSubobjects; + bool Ambiguous = false; + bool HasTag = false, HasFunction = false, HasNonFunction = false; - case AmbiguousLookupStoresDecls: - return AmbiguousReference; + unsigned UniqueTagIndex = 0; + + unsigned I = 0; + while (I < N) { + NamedDecl *D = Decls[I]; + assert(D == D->getUnderlyingDecl()); + + NamedDecl *CanonD = cast<NamedDecl>(D->getCanonicalDecl()); + if (!Unique.insert(CanonD)) { + // If it's not unique, pull something off the back (and + // continue at this index). + Decls[I] = Decls[--N]; + } else if (isa<UnresolvedUsingDecl>(D)) { + // FIXME: proper support for UnresolvedUsingDecls. + Decls[I] = Decls[--N]; + } else { + // Otherwise, do some decl type analysis and then continue. + if (isa<TagDecl>(D)) { + if (HasTag) + Ambiguous = true; + UniqueTagIndex = I; + HasTag = true; + } else if (D->isFunctionOrFunctionTemplate()) { + HasFunction = true; + } else { + if (HasNonFunction) + Ambiguous = true; + HasNonFunction = true; + } + I++; + } } - // We can't ever get here. - return NotFound; + // C++ [basic.scope.hiding]p2: + // A class name or enumeration name can be hidden by the name of + // an object, function, or enumerator declared in the same + // scope. If a class or enumeration name and an object, function, + // or enumerator are declared in the same scope (in any order) + // with the same name, the class or enumeration name is hidden + // wherever the object, function, or enumerator name is visible. + // But it's still an error if there are distinct tag types found, + // even if they're not visible. (ref?) + if (HasTag && !Ambiguous && (HasFunction || HasNonFunction)) + Decls[UniqueTagIndex] = Decls[--N]; + + Decls.set_size(N); + + if (HasFunction && HasNonFunction) + Ambiguous = true; + + if (Ambiguous) + setAmbiguous(LookupResult::AmbiguousReference); + else if (N > 1) + Kind = LookupResult::FoundOverloaded; + else + Kind = LookupResult::Found; } /// @brief Converts the result of name lookup into a single (possible @@ -423,197 +236,99 @@ Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const { /// (if only a single declaration was found), an /// OverloadedFunctionDecl (if an overloaded function was found), or /// NULL (if no declaration was found). This conversion must not be -/// used anywhere where name lookup could result in an ambiguity. +/// used anywhere where name lookup could result in an ambiguity. /// /// The OverloadedFunctionDecl conversion is meant as a stop-gap /// solution, since it causes the OverloadedFunctionDecl to be /// leaked. FIXME: Eventually, there will be a better way to iterate /// over the set of overloaded functions returned by name lookup. -NamedDecl *Sema::LookupResult::getAsDecl() const { - switch (StoredKind) { - case SingleDecl: - return reinterpret_cast<NamedDecl *>(First); - - case OverloadedDeclFromIdResolver: - return MaybeConstructOverloadSet(*Context, - IdentifierResolver::iterator::getFromOpaqueValue(First), - IdentifierResolver::iterator::getFromOpaqueValue(Last)); - - case OverloadedDeclFromDeclContext: - return MaybeConstructOverloadSet(*Context, - reinterpret_cast<DeclContext::lookup_iterator>(First), - reinterpret_cast<DeclContext::lookup_iterator>(Last)); - - case OverloadedDeclSingleDecl: - return reinterpret_cast<OverloadedFunctionDecl*>(First); - - case AmbiguousLookupStoresDecls: - case AmbiguousLookupStoresBasePaths: - assert(false && - "Name lookup returned an ambiguity that could not be handled"); - break; +NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const { + size_t size = Decls.size(); + if (size == 0) return 0; + if (size == 1) return *begin(); + + if (isAmbiguous()) return 0; + + iterator I = begin(), E = end(); + + OverloadedFunctionDecl *Ovl + = OverloadedFunctionDecl::Create(C, (*I)->getDeclContext(), + (*I)->getDeclName()); + for (; I != E; ++I) { + NamedDecl *ND = *I; + assert(ND->getUnderlyingDecl() == ND + && "decls in lookup result should have redirections stripped"); + assert(ND->isFunctionOrFunctionTemplate()); + if (isa<FunctionDecl>(ND)) + Ovl->addOverload(cast<FunctionDecl>(ND)); + else + Ovl->addOverload(cast<FunctionTemplateDecl>(ND)); + // FIXME: UnresolvedUsingDecls. } - - return 0; + + return Ovl; } -/// @brief Retrieves the BasePaths structure describing an ambiguous -/// name lookup, or null. -BasePaths *Sema::LookupResult::getBasePaths() const { - if (StoredKind == AmbiguousLookupStoresBasePaths) - return reinterpret_cast<BasePaths *>(First); - return 0; +void Sema::LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { + CXXBasePaths::paths_iterator I, E; + DeclContext::lookup_iterator DI, DE; + for (I = P.begin(), E = P.end(); I != E; ++I) + for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI) + addDecl(*DI); } -Sema::LookupResult::iterator::reference -Sema::LookupResult::iterator::operator*() const { - switch (Result->StoredKind) { - case SingleDecl: - return reinterpret_cast<NamedDecl*>(Current); - - case OverloadedDeclSingleDecl: - return *reinterpret_cast<NamedDecl**>(Current); - - case OverloadedDeclFromIdResolver: - return *IdentifierResolver::iterator::getFromOpaqueValue(Current); - - case AmbiguousLookupStoresBasePaths: - if (Result->Last) - return *reinterpret_cast<NamedDecl**>(Current); - - // Fall through to handle the DeclContext::lookup_iterator we're - // storing. - - case OverloadedDeclFromDeclContext: - case AmbiguousLookupStoresDecls: - return *reinterpret_cast<DeclContext::lookup_iterator>(Current); - } - - return 0; +void Sema::LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { + Paths = new CXXBasePaths; + Paths->swap(P); + addDeclsFromBasePaths(*Paths); + resolveKind(); + setAmbiguous(AmbiguousBaseSubobjects); } -Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() { - switch (Result->StoredKind) { - case SingleDecl: - Current = reinterpret_cast<uintptr_t>((NamedDecl*)0); - break; - - case OverloadedDeclSingleDecl: { - NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current); - ++I; - Current = reinterpret_cast<uintptr_t>(I); - break; - } - - case OverloadedDeclFromIdResolver: { - IdentifierResolver::iterator I - = IdentifierResolver::iterator::getFromOpaqueValue(Current); - ++I; - Current = I.getAsOpaqueValue(); - break; - } - - case AmbiguousLookupStoresBasePaths: - if (Result->Last) { - NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current); - ++I; - Current = reinterpret_cast<uintptr_t>(I); - break; - } - // Fall through to handle the DeclContext::lookup_iterator we're - // storing. - - case OverloadedDeclFromDeclContext: - case AmbiguousLookupStoresDecls: { - DeclContext::lookup_iterator I - = reinterpret_cast<DeclContext::lookup_iterator>(Current); - ++I; - Current = reinterpret_cast<uintptr_t>(I); - break; - } - } - - return *this; +void Sema::LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { + Paths = new CXXBasePaths; + Paths->swap(P); + addDeclsFromBasePaths(*Paths); + resolveKind(); + setAmbiguous(AmbiguousBaseSubobjectTypes); } -Sema::LookupResult::iterator Sema::LookupResult::begin() { - switch (StoredKind) { - case SingleDecl: - case OverloadedDeclFromIdResolver: - case OverloadedDeclFromDeclContext: - case AmbiguousLookupStoresDecls: - return iterator(this, First); - - case OverloadedDeclSingleDecl: { - OverloadedFunctionDecl * Ovl = - reinterpret_cast<OverloadedFunctionDecl*>(First); - return iterator(this, - reinterpret_cast<uintptr_t>(&(*Ovl->function_begin()))); - } - - case AmbiguousLookupStoresBasePaths: - if (Last) - return iterator(this, - reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_begin())); - else - return iterator(this, - reinterpret_cast<uintptr_t>(getBasePaths()->front().Decls.first)); +void Sema::LookupResult::print(llvm::raw_ostream &Out) { + Out << Decls.size() << " result(s)"; + if (isAmbiguous()) Out << ", ambiguous"; + if (Paths) Out << ", base paths present"; + + for (iterator I = begin(), E = end(); I != E; ++I) { + Out << "\n"; + (*I)->print(Out, 2); } - - // Required to suppress GCC warning. - return iterator(); } -Sema::LookupResult::iterator Sema::LookupResult::end() { - switch (StoredKind) { - case SingleDecl: - case OverloadedDeclFromIdResolver: - case OverloadedDeclFromDeclContext: - case AmbiguousLookupStoresDecls: - return iterator(this, Last); - - case OverloadedDeclSingleDecl: { - OverloadedFunctionDecl * Ovl = - reinterpret_cast<OverloadedFunctionDecl*>(First); - return iterator(this, - reinterpret_cast<uintptr_t>(&(*Ovl->function_end()))); - } - - case AmbiguousLookupStoresBasePaths: - if (Last) - return iterator(this, - reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_end())); - else - return iterator(this, reinterpret_cast<uintptr_t>( - getBasePaths()->front().Decls.second)); - } +// Adds all qualifying matches for a name within a decl context to the +// given lookup result. Returns true if any matches were found. +static bool LookupDirect(Sema::LookupResult &R, DeclContext *DC, + DeclarationName Name, + Sema::LookupNameKind NameKind, + unsigned IDNS) { + bool Found = false; - // Required to suppress GCC warning. - return iterator(); -} + DeclContext::lookup_iterator I, E; + for (llvm::tie(I, E) = DC->lookup(Name); I != E; ++I) + if (Sema::isAcceptableLookupResult(*I, NameKind, IDNS)) + R.addDecl(*I), Found = true; -void Sema::LookupResult::Destroy() { - if (BasePaths *Paths = getBasePaths()) - delete Paths; - else if (getKind() == AmbiguousReference) - delete[] reinterpret_cast<NamedDecl **>(First); + return Found; } -static void -CppNamespaceLookup(ASTContext &Context, DeclContext *NS, +static bool +CppNamespaceLookup(Sema::LookupResult &R, ASTContext &Context, DeclContext *NS, DeclarationName Name, Sema::LookupNameKind NameKind, - unsigned IDNS, LookupResultsTy &Results, - UsingDirectivesTy *UDirs = 0) { + unsigned IDNS, UsingDirectivesTy *UDirs = 0) { assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); // Perform qualified name lookup into the LookupCtx. - DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = NS->lookup(Name); I != E; ++I) - if (Sema::isAcceptableLookupResult(*I, NameKind, IDNS)) { - Results.push_back(Sema::LookupResult::CreateLookupResult(Context, I, E)); - break; - } + bool Found = LookupDirect(R, NS, Name, NameKind, IDNS); if (UDirs) { // For each UsingDirectiveDecl, which common ancestor is equal @@ -622,11 +337,15 @@ CppNamespaceLookup(ASTContext &Context, DeclContext *NS, llvm::tie(UI, UEnd) = std::equal_range(UDirs->begin(), UDirs->end(), NS, UsingDirAncestorCompare()); - + for (; UI != UEnd; ++UI) - CppNamespaceLookup(Context, (*UI)->getNominatedNamespace(), - Name, NameKind, IDNS, Results); + if (LookupDirect(R, (*UI)->getNominatedNamespace(), Name, NameKind, IDNS)) + Found = true; } + + R.resolveKind(); + + return Found; } static bool isNamespaceOrTranslationUnitScope(Scope *S) { @@ -635,16 +354,31 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) { return false; } -std::pair<bool, Sema::LookupResult> -Sema::CppLookupName(Scope *S, DeclarationName Name, +// Find the next outer declaration context corresponding to this scope. +static DeclContext *findOuterContext(Scope *S) { + for (S = S->getParent(); S; S = S->getParent()) + if (S->getEntity()) + return static_cast<DeclContext *>(S->getEntity())->getPrimaryContext(); + + return 0; +} + +bool +Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, LookupNameKind NameKind, bool RedeclarationOnly) { assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); - unsigned IDNS + unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true); + + // If we're testing for redeclarations, also look in the friend namespaces. + if (RedeclarationOnly) { + if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend; + if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend; + } + Scope *Initial = S; - DeclContext *OutOfLineCtx = 0; - IdentifierResolver::iterator + IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); @@ -653,8 +387,8 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // ...During unqualified name lookup (3.4.1), the names appear as if // they were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. - // [Note: in this context, “contains” means “contains directly or - // indirectly”. + // [Note: in this context, "contains" means "contains directly or + // indirectly". // // For example: // namespace A { int i; } @@ -668,47 +402,33 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { // Check whether the IdResolver has anything in this scope. + bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { if (isAcceptableLookupResult(*I, NameKind, IDNS)) { - // We found something. Look for anything else in our scope - // with this same name and in an acceptable identifier - // namespace, so that we can construct an overload set if we - // need to. - IdentifierResolver::iterator LastI = I; - for (++LastI; LastI != IEnd; ++LastI) { - if (!S->isDeclScope(DeclPtrTy::make(*LastI))) - break; - } - LookupResult Result = - LookupResult::CreateLookupResult(Context, I, LastI); - return std::make_pair(true, Result); + Found = true; + R.addDecl(*I); } } + if (Found) { + R.resolveKind(); + return true; + } + if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) { - LookupResult R; - // Perform member lookup into struct. - // FIXME: In some cases, we know that every name that could be found by - // this qualified name lookup will also be on the identifier chain. For - // example, inside a class without any base classes, we never need to - // perform qualified lookup because all of the members are on top of the - // identifier chain. - if (isa<RecordDecl>(Ctx)) { - R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly); - if (R) - return std::make_pair(true, R); - } - if (Ctx->getParent() != Ctx->getLexicalParent() - || isa<CXXMethodDecl>(Ctx)) { - // It is out of line defined C++ method or struct, we continue - // doing name lookup in parent context. Once we will find namespace - // or translation-unit we save it for possible checking - // using-directives later. - for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext(); - OutOfLineCtx = OutOfLineCtx->getParent()) { - R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly); - if (R) - return std::make_pair(true, R); - } + DeclContext *OuterCtx = findOuterContext(S); + for (; Ctx && Ctx->getPrimaryContext() != OuterCtx; + Ctx = Ctx->getLookupParent()) { + if (Ctx->isFunctionOrMethod()) + continue; + + // Perform qualified name lookup into this context. + // FIXME: In some cases, we know that every name that could be found by + // this qualified name lookup will also be on the identifier chain. For + // example, inside a class without any base classes, we never need to + // perform qualified lookup because all of the members are on top of the + // identifier chain. + if (LookupQualifiedName(R, Ctx, Name, NameKind, RedeclarationOnly)) + return true; } } } @@ -731,71 +451,41 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // that aren't strictly lexical, and therefore we walk through the // context as well as walking through the scopes. - LookupResultsTy LookupResults; - assert((!OutOfLineCtx || OutOfLineCtx->isFileContext()) && - "We should have been looking only at file context here already."); - bool LookedInCtx = false; - LookupResult Result; - while (OutOfLineCtx && - OutOfLineCtx != S->getEntity() && - OutOfLineCtx->isNamespace()) { - LookedInCtx = true; - - // Look into context considering using-directives. - CppNamespaceLookup(Context, OutOfLineCtx, Name, NameKind, IDNS, - LookupResults, &UDirs); - - if ((Result = MergeLookupResults(Context, LookupResults)) || - (RedeclarationOnly && !OutOfLineCtx->isTransparentContext())) - return std::make_pair(true, Result); - - OutOfLineCtx = OutOfLineCtx->getParent(); - } - for (; S; S = S->getParent()) { DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); + if (Ctx->isTransparentContext()) + continue; + assert(Ctx && Ctx->isFileContext() && "We should have been looking only at file context here already."); // Check whether the IdResolver has anything in this scope. + bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { if (isAcceptableLookupResult(*I, NameKind, IDNS)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier // namespace, so that we can construct an overload set if we // need to. - IdentifierResolver::iterator LastI = I; - for (++LastI; LastI != IEnd; ++LastI) { - if (!S->isDeclScope(DeclPtrTy::make(*LastI))) - break; - } - - // We store name lookup result, and continue trying to look into - // associated context, and maybe namespaces nominated by - // using-directives. - LookupResults.push_back( - LookupResult::CreateLookupResult(Context, I, LastI)); - break; + Found = true; + R.addDecl(*I); } } - LookedInCtx = true; // Look into context considering using-directives. - CppNamespaceLookup(Context, Ctx, Name, NameKind, IDNS, - LookupResults, &UDirs); + if (CppNamespaceLookup(R, Context, Ctx, Name, NameKind, IDNS, &UDirs)) + Found = true; - if ((Result = MergeLookupResults(Context, LookupResults)) || - (RedeclarationOnly && !Ctx->isTransparentContext())) - return std::make_pair(true, Result); - } + if (Found) { + R.resolveKind(); + return true; + } - if (!(LookedInCtx || LookupResults.empty())) { - // We didn't Performed lookup in Scope entity, so we return - // result form IdentifierResolver. - assert((LookupResults.size() == 1) && "Wrong size!"); - return std::make_pair(true, LookupResults.front()); + if (RedeclarationOnly && !Ctx->isTransparentContext()) + return false; } - return std::make_pair(false, LookupResult()); + + return !R.empty(); } /// @brief Perform unqualified name lookup starting from a given @@ -823,17 +513,16 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, /// @param Name The name of the entity that we are searching for. /// /// @param Loc If provided, the source location where we're performing -/// name lookup. At present, this is only used to produce diagnostics when +/// name lookup. At present, this is only used to produce diagnostics when /// C library functions (like "malloc") are implicitly declared. /// /// @returns The result of name lookup, which includes zero or more /// declarations and possibly additional information used to diagnose /// ambiguities. -Sema::LookupResult -Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, - bool RedeclarationOnly, bool AllowBuiltinCreation, - SourceLocation Loc) { - if (!Name) return LookupResult::CreateLookupResult(Context, 0); +bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name, + LookupNameKind NameKind, bool RedeclarationOnly, + bool AllowBuiltinCreation, SourceLocation Loc) { + if (!Name) return false; if (!getLangOptions().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so @@ -861,7 +550,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, case Sema::LookupRedeclarationWithLinkage: // Find the nearest non-transparent declaration scope. while (!(S->getFlags() & Scope::DeclScope) || - (S->getEntity() && + (S->getEntity() && static_cast<DeclContext *>(S->getEntity()) ->isTransparentContext())) S = S->getParent(); @@ -875,7 +564,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, case Sema::LookupObjCImplementationName: IDNS = Decl::IDNS_ObjCImplementation; break; - + case Sema::LookupObjCCategoryImplName: IDNS = Decl::IDNS_ObjCCategoryImpl; break; @@ -888,7 +577,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, bool LeftStartingScope = false; for (IdentifierResolver::iterator I = IdResolver.begin(Name), - IEnd = IdResolver.end(); + IEnd = IdResolver.end(); I != IEnd; ++I) if ((*I)->isInIdentifierNamespace(IDNS)) { if (NameKind == LookupRedeclarationWithLinkage) { @@ -903,6 +592,8 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, continue; } + R.addDecl(*I); + if ((*I)->getAttr<OverloadableAttr>()) { // If this declaration has the "overloadable" attribute, we // might have a set of overloaded functions. @@ -918,26 +609,24 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, for (++LastI; LastI != IEnd; ++LastI) { if (!S->isDeclScope(DeclPtrTy::make(*LastI))) break; + R.addDecl(*LastI); } - - return LookupResult::CreateLookupResult(Context, I, LastI); } - // We have a single lookup result. - return LookupResult::CreateLookupResult(Context, *I); + R.resolveKind(); + + return true; } } else { // Perform C++ unqualified name lookup. - std::pair<bool, LookupResult> MaybeResult = - CppLookupName(S, Name, NameKind, RedeclarationOnly); - if (MaybeResult.first) - return MaybeResult.second; + if (CppLookupName(R, S, Name, NameKind, RedeclarationOnly)) + return true; } // If we didn't find a use of this identifier, and if the identifier // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. - if (NameKind == LookupOrdinaryName || + if (NameKind == LookupOrdinaryName || NameKind == LookupRedeclarationWithLinkage) { IdentifierInfo *II = Name.getAsIdentifierInfo(); if (II && AllowBuiltinCreation) { @@ -945,17 +634,132 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, if (unsigned BuiltinID = II->getBuiltinID()) { // In C++, we don't have any predefined library functions like // 'malloc'. Instead, we'll just error. - if (getLangOptions().CPlusPlus && + if (getLangOptions().CPlusPlus && Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return LookupResult::CreateLookupResult(Context, 0); + return false; + + NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, + S, RedeclarationOnly, Loc); + if (D) R.addDecl(D); + return (D != NULL); + } + } + } + return false; +} + +/// @brief Perform qualified name lookup in the namespaces nominated by +/// using directives by the given context. +/// +/// C++98 [namespace.qual]p2: +/// Given X::m (where X is a user-declared namespace), or given ::m +/// (where X is the global namespace), let S be the set of all +/// declarations of m in X and in the transitive closure of all +/// namespaces nominated by using-directives in X and its used +/// namespaces, except that using-directives are ignored in any +/// namespace, including X, directly containing one or more +/// declarations of m. No namespace is searched more than once in +/// the lookup of a name. If S is the empty set, the program is +/// ill-formed. Otherwise, if S has exactly one member, or if the +/// context of the reference is a using-declaration +/// (namespace.udecl), S is the required set of declarations of +/// m. Otherwise if the use of m is not one that allows a unique +/// declaration to be chosen from S, the program is ill-formed. +/// C++98 [namespace.qual]p5: +/// During the lookup of a qualified namespace member name, if the +/// lookup finds more than one declaration of the member, and if one +/// declaration introduces a class name or enumeration name and the +/// other declarations either introduce the same object, the same +/// enumerator or a set of functions, the non-type name hides the +/// class or enumeration name if and only if the declarations are +/// from the same namespace; otherwise (the declarations are from +/// different namespaces), the program is ill-formed. +static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R, + DeclContext *StartDC, + DeclarationName Name, + Sema::LookupNameKind NameKind, + unsigned IDNS) { + assert(StartDC->isFileContext() && "start context is not a file context"); + + DeclContext::udir_iterator I = StartDC->using_directives_begin(); + DeclContext::udir_iterator E = StartDC->using_directives_end(); + + if (I == E) return false; + + // We have at least added all these contexts to the queue. + llvm::DenseSet<DeclContext*> Visited; + Visited.insert(StartDC); + + // We have not yet looked into these namespaces, much less added + // their "using-children" to the queue. + llvm::SmallVector<NamespaceDecl*, 8> Queue; + + // We have already looked into the initial namespace; seed the queue + // with its using-children. + for (; I != E; ++I) { + NamespaceDecl *ND = (*I)->getNominatedNamespace(); + if (Visited.insert(ND).second) + Queue.push_back(ND); + } + + // The easiest way to implement the restriction in [namespace.qual]p5 + // is to check whether any of the individual results found a tag + // and, if so, to declare an ambiguity if the final result is not + // a tag. + bool FoundTag = false; + bool FoundNonTag = false; + + Sema::LookupResult LocalR; + + bool Found = false; + while (!Queue.empty()) { + NamespaceDecl *ND = Queue.back(); + Queue.pop_back(); + + // We go through some convolutions here to avoid copying results + // between LookupResults. + bool UseLocal = !R.empty(); + Sema::LookupResult &DirectR = UseLocal ? LocalR : R; + bool FoundDirect = LookupDirect(DirectR, ND, Name, NameKind, IDNS); + + if (FoundDirect) { + // First do any local hiding. + DirectR.resolveKind(); + + // If the local result is a tag, remember that. + if (DirectR.isSingleTagDecl()) + FoundTag = true; + else + FoundNonTag = true; - return LookupResult::CreateLookupResult(Context, - LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, - S, RedeclarationOnly, Loc)); + // Append the local results to the total results if necessary. + if (UseLocal) { + R.addAllDecls(LocalR); + LocalR.clear(); } } + + // If we find names in this namespace, ignore its using directives. + if (FoundDirect) { + Found = true; + continue; + } + + for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) { + NamespaceDecl *Nom = (*I)->getNominatedNamespace(); + if (Visited.insert(Nom).second) + Queue.push_back(Nom); + } } - return LookupResult::CreateLookupResult(Context, 0); + + if (Found) { + if (FoundTag && FoundNonTag) + R.setAmbiguousQualifiedTagHiding(); + else + R.resolveKind(); + } + + return Found; } /// @brief Perform qualified name lookup into a given context. @@ -988,40 +792,91 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, /// @returns The result of name lookup, which includes zero or more /// declarations and possibly additional information used to diagnose /// ambiguities. -Sema::LookupResult -Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, - LookupNameKind NameKind, bool RedeclarationOnly) { +bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + DeclarationName Name, LookupNameKind NameKind, + bool RedeclarationOnly) { assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); - - if (!Name) return LookupResult::CreateLookupResult(Context, 0); + + if (!Name) + return false; // If we're performing qualified name lookup (e.g., lookup into a // struct), find fields as part of ordinary name lookup. unsigned IDNS - = getIdentifierNamespacesFromLookupNameKind(NameKind, + = getIdentifierNamespacesFromLookupNameKind(NameKind, getLangOptions().CPlusPlus); if (NameKind == LookupOrdinaryName) IDNS |= Decl::IDNS_Member; + // Make sure that the declaration context is complete. + assert((!isa<TagDecl>(LookupCtx) || + LookupCtx->isDependentContext() || + cast<TagDecl>(LookupCtx)->isDefinition() || + Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>() + ->isBeingDefined()) && + "Declaration context must already be complete!"); + // Perform qualified name lookup into the LookupCtx. - DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) - if (isAcceptableLookupResult(*I, NameKind, IDNS)) - return LookupResult::CreateLookupResult(Context, I, E); + if (LookupDirect(R, LookupCtx, Name, NameKind, IDNS)) { + R.resolveKind(); + return true; + } + + // Don't descend into implied contexts for redeclarations. + // C++98 [namespace.qual]p6: + // In a declaration for a namespace member in which the + // declarator-id is a qualified-id, given that the qualified-id + // for the namespace member has the form + // nested-name-specifier unqualified-id + // the unqualified-id shall name a member of the namespace + // designated by the nested-name-specifier. + // See also [class.mfct]p5 and [class.static.data]p2. + if (RedeclarationOnly) + return false; - // If this isn't a C++ class or we aren't allowed to look into base + // If this is a namespace, look it up in + if (LookupCtx->isFileContext()) + return LookupQualifiedNameInUsingDirectives(R, LookupCtx, Name, NameKind, + IDNS); + + // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. - if (RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx)) - return LookupResult::CreateLookupResult(Context, 0); + if (!isa<CXXRecordDecl>(LookupCtx)) + return false; // Perform lookup into our base classes. - BasePaths Paths; - Paths.setOrigin(Context.getTypeDeclType(cast<RecordDecl>(LookupCtx))); + CXXRecordDecl *LookupRec = cast<CXXRecordDecl>(LookupCtx); + CXXBasePaths Paths; + Paths.setOrigin(LookupRec); // Look for this member in our base classes - if (!LookupInBases(cast<CXXRecordDecl>(LookupCtx), - MemberLookupCriteria(Name, NameKind, IDNS), Paths)) - return LookupResult::CreateLookupResult(Context, 0); + CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0; + switch (NameKind) { + case LookupOrdinaryName: + case LookupMemberName: + case LookupRedeclarationWithLinkage: + BaseCallback = &CXXRecordDecl::FindOrdinaryMember; + break; + + case LookupTagName: + BaseCallback = &CXXRecordDecl::FindTagMember; + break; + + case LookupOperatorName: + case LookupNamespaceName: + case LookupObjCProtocolName: + case LookupObjCImplementationName: + case LookupObjCCategoryImplName: + // These lookups will never find a member in a C++ class (or base class). + return false; + + case LookupNestedNameSpecifierName: + BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; + break; + } + + if (!LookupRec->lookupInBases(BaseCallback, Name.getAsOpaquePtr(), Paths)) + return false; // C++ [class.member.lookup]p2: // [...] If the resulting set of declarations are not all from @@ -1032,29 +887,28 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // FIXME: support using declarations! QualType SubobjectType; int SubobjectNumber = 0; - for (BasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); + for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); Path != PathEnd; ++Path) { - const BasePathElement &PathElement = Path->back(); + const CXXBasePathElement &PathElement = Path->back(); // Determine whether we're looking at a distinct sub-object or not. if (SubobjectType.isNull()) { - // This is the first subobject we've looked at. Record it's type. + // This is the first subobject we've looked at. Record its type. SubobjectType = Context.getCanonicalType(PathElement.Base->getType()); SubobjectNumber = PathElement.SubobjectNumber; - } else if (SubobjectType + } else if (SubobjectType != Context.getCanonicalType(PathElement.Base->getType())) { // We found members of the given name in two subobjects of // different types. This lookup is ambiguous. - BasePaths *PathsOnHeap = new BasePaths; - PathsOnHeap->swap(Paths); - return LookupResult::CreateLookupResult(Context, PathsOnHeap, true); + R.setAmbiguousBaseSubobjectTypes(Paths); + return true; } else if (SubobjectNumber != PathElement.SubobjectNumber) { // We have a different subobject of the same type. // C++ [class.member.lookup]p5: // A static member, a nested type or an enumerator defined in // a base class T can unambiguously be found even if an object - // has more than one base class subobject of type T. + // has more than one base class subobject of type T. Decl *FirstDecl = *Path->Decls.first; if (isa<VarDecl>(FirstDecl) || isa<TypeDecl>(FirstDecl) || @@ -1083,21 +937,18 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // We have found a nonstatic member name in multiple, distinct // subobjects. Name lookup is ambiguous. - BasePaths *PathsOnHeap = new BasePaths; - PathsOnHeap->swap(Paths); - return LookupResult::CreateLookupResult(Context, PathsOnHeap, false); + R.setAmbiguousBaseSubobjects(Paths); + return true; } } // Lookup in a base class succeeded; return these results. - // If we found a function declaration, return an overload set. - if ((*Paths.front().Decls.first)->isFunctionOrFunctionTemplate()) - return LookupResult::CreateLookupResult(Context, - Paths.front().Decls.first, Paths.front().Decls.second); - - // We found a non-function declaration; return a single declaration. - return LookupResult::CreateLookupResult(Context, *Paths.front().Decls.first); + DeclContext::lookup_iterator I, E; + for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) + R.addDecl(*I); + R.resolveKind(); + return true; } /// @brief Performs name lookup for a name that was parsed in the @@ -1111,59 +962,50 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, /// /// @param S The scope from which unqualified name lookup will /// begin. -/// -/// @param SS An optional C++ scope-specified, e.g., "::N::M". +/// +/// @param SS An optional C++ scope-specifier, e.g., "::N::M". /// /// @param Name The name of the entity that name lookup will /// search for. /// /// @param Loc If provided, the source location where we're performing -/// name lookup. At present, this is only used to produce diagnostics when +/// name lookup. At present, this is only used to produce diagnostics when /// C library functions (like "malloc") are implicitly declared. /// -/// @returns The result of qualified or unqualified name lookup. -Sema::LookupResult -Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, - DeclarationName Name, LookupNameKind NameKind, - bool RedeclarationOnly, bool AllowBuiltinCreation, - SourceLocation Loc) { - if (SS && (SS->isSet() || SS->isInvalid())) { - // If the scope specifier is invalid, don't even look for +/// @param EnteringContext Indicates whether we are going to enter the +/// context of the scope-specifier SS (if present). +/// +/// @returns True if any decls were found (but possibly ambiguous) +bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, + DeclarationName Name, LookupNameKind NameKind, + bool RedeclarationOnly, bool AllowBuiltinCreation, + SourceLocation Loc, + bool EnteringContext) { + if (SS && SS->isInvalid()) { + // When the scope specifier is invalid, don't even look for // anything. - if (SS->isInvalid()) - return LookupResult::CreateLookupResult(Context, 0); - - assert(!isUnknownSpecialization(*SS) && "Can't lookup dependent types"); - - if (isDependentScopeSpecifier(*SS)) { - // Determine whether we are looking into the current - // instantiation. - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); - CXXRecordDecl *Current = getCurrentInstantiationOf(NNS); - assert(Current && "Bad dependent scope specifier"); - - // We nested name specifier refers to the current instantiation, - // so now we will look for a member of the current instantiation - // (C++0x [temp.dep.type]). - unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, true); - DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = Current->lookup(Name); I != E; ++I) - if (isAcceptableLookupResult(*I, NameKind, IDNS)) - return LookupResult::CreateLookupResult(Context, I, E); - } + return false; + } - if (RequireCompleteDeclContext(*SS)) - return LookupResult::CreateLookupResult(Context, 0); + if (SS && SS->isSet()) { + if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { + // We have resolved the scope specifier to a particular declaration + // contex, and will perform name lookup in that context. + if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS)) + return false; - return LookupQualifiedName(computeDeclContext(*SS), - Name, NameKind, RedeclarationOnly); + return LookupQualifiedName(R, DC, Name, NameKind, RedeclarationOnly); + } + + // We could not resolve the scope specified to a specific declaration + // context, which means that SS refers to an unknown specialization. + // Name lookup can't find anything in this case. + return false; } - LookupResult result(LookupName(S, Name, NameKind, RedeclarationOnly, - AllowBuiltinCreation, Loc)); - - return(result); + // Perform unqualified name lookup starting in the given scope. + return LookupName(R, S, Name, NameKind, RedeclarationOnly, + AllowBuiltinCreation, Loc); } @@ -1171,7 +1013,7 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, /// from name lookup. /// /// @param Result The ambiguous name lookup result. -/// +/// /// @param Name The name of the entity that name lookup was /// searching for. /// @@ -1184,79 +1026,164 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, /// /// @returns true bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, - SourceLocation NameLoc, + SourceLocation NameLoc, SourceRange LookupRange) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); - if (BasePaths *Paths = Result.getBasePaths()) { - if (Result.getKind() == LookupResult::AmbiguousBaseSubobjects) { - QualType SubobjectType = Paths->front().back().Base->getType(); - Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects) - << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) - << LookupRange; - - DeclContext::lookup_iterator Found = Paths->front().Decls.first; - while (isa<CXXMethodDecl>(*Found) && - cast<CXXMethodDecl>(*Found)->isStatic()) - ++Found; - - Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); - - Result.Destroy(); - return true; - } - - assert(Result.getKind() == LookupResult::AmbiguousBaseSubobjectTypes && - "Unhandled form of name lookup ambiguity"); + switch (Result.getAmbiguityKind()) { + case LookupResult::AmbiguousBaseSubobjects: { + CXXBasePaths *Paths = Result.getBasePaths(); + QualType SubobjectType = Paths->front().back().Base->getType(); + Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects) + << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) + << LookupRange; + + DeclContext::lookup_iterator Found = Paths->front().Decls.first; + while (isa<CXXMethodDecl>(*Found) && + cast<CXXMethodDecl>(*Found)->isStatic()) + ++Found; + + Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); + + return true; + } + case LookupResult::AmbiguousBaseSubobjectTypes: { Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types) << Name << LookupRange; - + + CXXBasePaths *Paths = Result.getBasePaths(); std::set<Decl *> DeclsPrinted; - for (BasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end(); + for (CXXBasePaths::paths_iterator Path = Paths->begin(), + PathEnd = Paths->end(); Path != PathEnd; ++Path) { Decl *D = *Path->Decls.first; if (DeclsPrinted.insert(D).second) Diag(D->getLocation(), diag::note_ambiguous_member_found); } - Result.Destroy(); return true; - } else if (Result.getKind() == LookupResult::AmbiguousReference) { - Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; + } - NamedDecl **DI = reinterpret_cast<NamedDecl **>(Result.First), - **DEnd = reinterpret_cast<NamedDecl **>(Result.Last); + case LookupResult::AmbiguousTagHiding: { + Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange; - for (; DI != DEnd; ++DI) - Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; + llvm::SmallPtrSet<NamedDecl*,8> TagDecls; + + LookupResult::iterator DI, DE = Result.end(); + for (DI = Result.begin(); DI != DE; ++DI) + if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) { + TagDecls.insert(TD); + Diag(TD->getLocation(), diag::note_hidden_tag); + } + + for (DI = Result.begin(); DI != DE; ++DI) + if (!isa<TagDecl>(*DI)) + Diag((*DI)->getLocation(), diag::note_hiding_object); + + // For recovery purposes, go ahead and implement the hiding. + Result.hideDecls(TagDecls); - Result.Destroy(); return true; } - assert(false && "Unhandled form of name lookup ambiguity"); + case LookupResult::AmbiguousReference: { + Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; + + LookupResult::iterator DI = Result.begin(), DE = Result.end(); + for (; DI != DE; ++DI) + Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; + + return true; + } + } - // We can't reach here. + llvm::llvm_unreachable("unknown ambiguity kind"); return true; } +static void +addAssociatedClassesAndNamespaces(QualType T, + ASTContext &Context, + Sema::AssociatedNamespaceSet &AssociatedNamespaces, + Sema::AssociatedClassSet &AssociatedClasses); + +static void CollectNamespace(Sema::AssociatedNamespaceSet &Namespaces, + DeclContext *Ctx) { + if (Ctx->isFileContext()) + Namespaces.insert(Ctx); +} + +// \brief Add the associated classes and namespaces for argument-dependent +// lookup that involves a template argument (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, + ASTContext &Context, + Sema::AssociatedNamespaceSet &AssociatedNamespaces, + Sema::AssociatedClassSet &AssociatedClasses) { + // C++ [basic.lookup.koenig]p2, last bullet: + // -- [...] ; + switch (Arg.getKind()) { + case TemplateArgument::Null: + break; + + case TemplateArgument::Type: + // [...] the namespaces and classes associated with the types of the + // template arguments provided for template type parameters (excluding + // template template parameters) + addAssociatedClassesAndNamespaces(Arg.getAsType(), Context, + AssociatedNamespaces, + AssociatedClasses); + break; + + case TemplateArgument::Declaration: + // [...] the namespaces in which any template template arguments are + // defined; and the classes in which any member templates used as + // template template arguments are defined. + if (ClassTemplateDecl *ClassTemplate + = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) { + DeclContext *Ctx = ClassTemplate->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + AssociatedClasses.insert(EnclosingClass); + // Add the associated namespace for this class. + while (Ctx->isRecord()) + Ctx = Ctx->getParent(); + CollectNamespace(AssociatedNamespaces, Ctx); + } + break; + + case TemplateArgument::Integral: + case TemplateArgument::Expression: + // [Note: non-type template arguments do not contribute to the set of + // associated namespaces. ] + break; + + case TemplateArgument::Pack: + for (TemplateArgument::pack_iterator P = Arg.pack_begin(), + PEnd = Arg.pack_end(); + P != PEnd; ++P) + addAssociatedClassesAndNamespaces(*P, Context, + AssociatedNamespaces, + AssociatedClasses); + break; + } +} + // \brief Add the associated classes and namespaces for -// argument-dependent lookup with an argument of class type -// (C++ [basic.lookup.koenig]p2). -static void -addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, +// argument-dependent lookup with an argument of class type +// (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, ASTContext &Context, Sema::AssociatedNamespaceSet &AssociatedNamespaces, - Sema::AssociatedClassSet &AssociatedClasses, - bool &GlobalScope) { + Sema::AssociatedClassSet &AssociatedClasses) { // C++ [basic.lookup.koenig]p2: // [...] // -- If T is a class type (including unions), its associated // classes are: the class itself; the class of which it is a // member, if any; and its direct and indirect base // classes. Its associated namespaces are the namespaces in - // which its associated classes are defined. + // which its associated classes are defined. // Add the class of which it is a member, if any. DeclContext *Ctx = Class->getDeclContext(); @@ -1265,17 +1192,38 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, // Add the associated namespace for this class. while (Ctx->isRecord()) Ctx = Ctx->getParent(); - if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx)) - AssociatedNamespaces.insert(EnclosingNamespace); - else if (Ctx->isTranslationUnit()) - GlobalScope = true; - + CollectNamespace(AssociatedNamespaces, Ctx); + // Add the class itself. If we've already seen this class, we don't // need to visit base classes. if (!AssociatedClasses.insert(Class)) return; - // FIXME: Handle class template specializations + // -- If T is a template-id, its associated namespaces and classes are + // the namespace in which the template is defined; for member + // templates, the member template’s class; the namespaces and classes + // associated with the types of the template arguments provided for + // template type parameters (excluding template template parameters); the + // namespaces in which any template template arguments are defined; and + // the classes in which any member templates used as template template + // arguments are defined. [Note: non-type template arguments do not + // contribute to the set of associated namespaces. ] + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Class)) { + DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + AssociatedClasses.insert(EnclosingClass); + // Add the associated namespace for this class. + while (Ctx->isRecord()) + Ctx = Ctx->getParent(); + CollectNamespace(AssociatedNamespaces, Ctx); + + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + addAssociatedClassesAndNamespaces(TemplateArgs[I], Context, + AssociatedNamespaces, + AssociatedClasses); + } // Add direct and indirect base classes along with their associated // namespaces. @@ -1290,17 +1238,14 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(), BaseEnd = Class->bases_end(); Base != BaseEnd; ++Base) { - const RecordType *BaseType = Base->getType()->getAsRecordType(); + const RecordType *BaseType = Base->getType()->getAs<RecordType>(); CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); if (AssociatedClasses.insert(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); while (BaseCtx->isRecord()) BaseCtx = BaseCtx->getParent(); - if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(BaseCtx)) - AssociatedNamespaces.insert(EnclosingNamespace); - else if (BaseCtx->isTranslationUnit()) - GlobalScope = true; + CollectNamespace(AssociatedNamespaces, BaseCtx); // Make sure we visit the bases of this base class. if (BaseDecl->bases_begin() != BaseDecl->bases_end()) @@ -1312,13 +1257,12 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, // \brief Add the associated classes and namespaces for // argument-dependent lookup with an argument of type T -// (C++ [basic.lookup.koenig]p2). -static void -addAssociatedClassesAndNamespaces(QualType T, +// (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(QualType T, ASTContext &Context, Sema::AssociatedNamespaceSet &AssociatedNamespaces, - Sema::AssociatedClassSet &AssociatedClasses, - bool &GlobalScope) { + Sema::AssociatedClassSet &AssociatedClasses) { // C++ [basic.lookup.koenig]p2: // // For each argument type T in the function call, there is a set @@ -1332,44 +1276,43 @@ addAssociatedClassesAndNamespaces(QualType T, T = Context.getCanonicalType(T).getUnqualifiedType(); // -- If T is a pointer to U or an array of U, its associated - // namespaces and classes are those associated with U. + // namespaces and classes are those associated with U. // // We handle this by unwrapping pointer and array types immediately, // to avoid unnecessary recursion. while (true) { - if (const PointerType *Ptr = T->getAsPointerType()) + if (const PointerType *Ptr = T->getAs<PointerType>()) T = Ptr->getPointeeType(); else if (const ArrayType *Ptr = Context.getAsArrayType(T)) T = Ptr->getElementType(); - else + else break; } // -- If T is a fundamental type, its associated sets of // namespaces and classes are both empty. - if (T->getAsBuiltinType()) + if (T->getAs<BuiltinType>()) return; // -- If T is a class type (including unions), its associated // classes are: the class itself; the class of which it is a // member, if any; and its direct and indirect base // classes. Its associated namespaces are the namespaces in - // which its associated classes are defined. - if (const RecordType *ClassType = T->getAsRecordType()) - if (CXXRecordDecl *ClassDecl + // which its associated classes are defined. + if (const RecordType *ClassType = T->getAs<RecordType>()) + if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(ClassType->getDecl())) { - addAssociatedClassesAndNamespaces(ClassDecl, Context, - AssociatedNamespaces, - AssociatedClasses, - GlobalScope); + addAssociatedClassesAndNamespaces(ClassDecl, Context, + AssociatedNamespaces, + AssociatedClasses); return; } // -- If T is an enumeration type, its associated namespace is // the namespace in which it is defined. If it is class // member, its associated class is the member’s class; else - // it has no associated class. - if (const EnumType *EnumT = T->getAsEnumType()) { + // it has no associated class. + if (const EnumType *EnumT = T->getAs<EnumType>()) { EnumDecl *Enum = EnumT->getDecl(); DeclContext *Ctx = Enum->getDeclContext(); @@ -1379,10 +1322,7 @@ addAssociatedClassesAndNamespaces(QualType T, // Add the associated namespace for this class. while (Ctx->isRecord()) Ctx = Ctx->getParent(); - if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx)) - AssociatedNamespaces.insert(EnclosingNamespace); - else if (Ctx->isTranslationUnit()) - GlobalScope = true; + CollectNamespace(AssociatedNamespaces, Ctx); return; } @@ -1390,50 +1330,48 @@ addAssociatedClassesAndNamespaces(QualType T, // -- If T is a function type, its associated namespaces and // classes are those associated with the function parameter // types and those associated with the return type. - if (const FunctionType *FunctionType = T->getAsFunctionType()) { + if (const FunctionType *FnType = T->getAs<FunctionType>()) { // Return type - addAssociatedClassesAndNamespaces(FunctionType->getResultType(), + addAssociatedClassesAndNamespaces(FnType->getResultType(), Context, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); + AssociatedNamespaces, AssociatedClasses); - const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FunctionType); + const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType); if (!Proto) return; // Argument types for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); + ArgEnd = Proto->arg_type_end(); Arg != ArgEnd; ++Arg) addAssociatedClassesAndNamespaces(*Arg, Context, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); - + AssociatedNamespaces, AssociatedClasses); + return; } // -- If T is a pointer to a member function of a class X, its // associated namespaces and classes are those associated // with the function parameter types and return type, - // together with those associated with X. + // together with those associated with X. // // -- If T is a pointer to a data member of class X, its // associated namespaces and classes are those associated // with the member type together with those associated with - // X. - if (const MemberPointerType *MemberPtr = T->getAsMemberPointerType()) { + // X. + if (const MemberPointerType *MemberPtr = T->getAs<MemberPointerType>()) { // Handle the type that the pointer to member points to. addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(), Context, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); + AssociatedNamespaces, + AssociatedClasses); // Handle the class type into which this points. - if (const RecordType *Class = MemberPtr->getClass()->getAsRecordType()) + if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>()) addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()), Context, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); + AssociatedNamespaces, + AssociatedClasses); return; } @@ -1447,13 +1385,12 @@ addAssociatedClassesAndNamespaces(QualType T, /// arguments. /// /// This routine computes the sets of associated classes and associated -/// namespaces searched by argument-dependent lookup +/// namespaces searched by argument-dependent lookup /// (C++ [basic.lookup.argdep]) for a given set of arguments. -void +void Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, AssociatedNamespaceSet &AssociatedNamespaces, - AssociatedClassSet &AssociatedClasses, - bool &GlobalScope) { + AssociatedClassSet &AssociatedClasses) { AssociatedNamespaces.clear(); AssociatedClasses.clear(); @@ -1463,14 +1400,14 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // associated classes to be considered. The sets of namespaces and // classes is determined entirely by the types of the function // arguments (and the namespace of any template template - // argument). + // argument). for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) { Expr *Arg = Args[ArgIdx]; if (Arg->getType() != Context.OverloadTy) { addAssociatedClassesAndNamespaces(Arg->getType(), Context, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); + AssociatedNamespaces, + AssociatedClasses); continue; } @@ -1482,16 +1419,23 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // classes and namespaces associated with its (non-dependent) // parameter types and return type. DeclRefExpr *DRE = 0; + TemplateIdRefExpr *TIRE = 0; + Arg = Arg->IgnoreParens(); if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) { - if (unaryOp->getOpcode() == UnaryOperator::AddrOf) + if (unaryOp->getOpcode() == UnaryOperator::AddrOf) { DRE = dyn_cast<DeclRefExpr>(unaryOp->getSubExpr()); - } else + TIRE = dyn_cast<TemplateIdRefExpr>(unaryOp->getSubExpr()); + } + } else { DRE = dyn_cast<DeclRefExpr>(Arg); - if (!DRE) - continue; + TIRE = dyn_cast<TemplateIdRefExpr>(Arg); + } - OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()); + OverloadedFunctionDecl *Ovl = 0; + if (DRE) + Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()); + else if (TIRE) + Ovl = TIRE->getTemplateName().getAsOverloadedFunctionDecl(); if (!Ovl) continue; @@ -1506,16 +1450,13 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // that, if this is a member function, we do *not* consider the // enclosing namespace of its class. DeclContext *Ctx = FDecl->getDeclContext(); - if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx)) - AssociatedNamespaces.insert(EnclosingNamespace); - else if (Ctx->isTranslationUnit()) - GlobalScope = true; + CollectNamespace(AssociatedNamespaces, Ctx); // Add the classes and namespaces associated with the parameter // types and return type of this function. addAssociatedClassesAndNamespaces(FDecl->getType(), Context, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); + AssociatedNamespaces, + AssociatedClasses); } } } @@ -1525,7 +1466,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, /// arguments have types T1 (and, if non-empty, T2). This routine /// implements the check in C++ [over.match.oper]p3b2 concerning /// enumeration types. -static bool +static bool IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, QualType T1, QualType T2, ASTContext &Context) { @@ -1535,7 +1476,7 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) return true; - const FunctionProtoType *Proto = Fn->getType()->getAsFunctionProtoType(); + const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>(); if (Proto->getNumArgs() < 1) return false; @@ -1561,26 +1502,19 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, /// \brief Find the protocol with the given name, if any. ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) { - Decl *D = LookupName(TUScope, II, LookupObjCProtocolName).getAsDecl(); + Decl *D = LookupSingleName(TUScope, II, LookupObjCProtocolName); return cast_or_null<ObjCProtocolDecl>(D); } -/// \brief Find the Objective-C implementation with the given name, if -/// any. -ObjCImplementationDecl *Sema::LookupObjCImplementation(IdentifierInfo *II) { - Decl *D = LookupName(TUScope, II, LookupObjCImplementationName).getAsDecl(); - return cast_or_null<ObjCImplementationDecl>(D); -} - /// \brief Find the Objective-C category implementation with the given /// name, if any. ObjCCategoryImplDecl *Sema::LookupObjCCategoryImpl(IdentifierInfo *II) { - Decl *D = LookupName(TUScope, II, LookupObjCCategoryImplName).getAsDecl(); + Decl *D = LookupSingleName(TUScope, II, LookupObjCCategoryImplName); return cast_or_null<ObjCCategoryImplDecl>(D); } void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, - QualType T1, QualType T2, + QualType T1, QualType T2, FunctionSet &Functions) { // C++ [over.match.oper]p3: // -- The set of non-member candidates is the result of the @@ -1589,17 +1523,18 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, // unqualified function calls (3.4.2) except that all member // functions are ignored. However, if no operand has a class // type, only those non-member functions in the lookup set - // that have a first parameter of type T1 or “reference to - // (possibly cv-qualified) T1”, when T1 is an enumeration + // that have a first parameter of type T1 or "reference to + // (possibly cv-qualified) T1", when T1 is an enumeration // type, or (if there is a right operand) a second parameter - // of type T2 or “reference to (possibly cv-qualified) T2”, + // of type T2 or "reference to (possibly cv-qualified) T2", // when T2 is an enumeration type, are candidate functions. DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); - LookupResult Operators = LookupName(S, OpName, LookupOperatorName); - + LookupResult Operators; + LookupName(Operators, S, OpName, LookupOperatorName); + assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); - if (!Operators) + if (Operators.empty()) return; for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end(); @@ -1607,10 +1542,10 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) { if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) Functions.insert(FD); // FIXME: canonical FD - } else if (FunctionTemplateDecl *FunTmpl + } else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Op)) { // FIXME: friend operators? - // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, + // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, // later? if (!FunTmpl->getDeclContext()->isRecord()) Functions.insert(FunTmpl); @@ -1618,6 +1553,14 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, } } +static void CollectFunctionDecl(Sema::FunctionSet &Functions, + Decl *D) { + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) + Functions.insert(Func); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) + Functions.insert(FunTmpl); +} + void Sema::ArgumentDependentLookup(DeclarationName Name, Expr **Args, unsigned NumArgs, FunctionSet &Functions) { @@ -1625,10 +1568,9 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; AssociatedClassSet AssociatedClasses; - bool GlobalScope = false; - FindAssociatedClassesAndNamespaces(Args, NumArgs, - AssociatedNamespaces, AssociatedClasses, - GlobalScope); + FindAssociatedClassesAndNamespaces(Args, NumArgs, + AssociatedNamespaces, + AssociatedClasses); // C++ [basic.lookup.argdep]p3: // Let X be the lookup set produced by unqualified lookup (3.4.1) @@ -1642,8 +1584,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, // Here, we compute Y and add its members to the overloaded // candidate set. for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(), - NSEnd = AssociatedNamespaces.end(); - NS != NSEnd; ++NS) { + NSEnd = AssociatedNamespaces.end(); + NS != NSEnd; ++NS) { // When considering an associated namespace, the lookup is the // same as the lookup performed when the associated namespace is // used as a qualifier (3.4.3.2) except that: @@ -1651,28 +1593,22 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, // -- Any using-directives in the associated namespace are // ignored. // - // -- FIXME: Any namespace-scope friend functions declared in + // -- Any namespace-scope friend functions declared in // associated classes are visible within their respective // namespaces even if they are not visible during an ordinary // lookup (11.4). DeclContext::lookup_iterator I, E; for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) { - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I)) - Functions.insert(Func); - else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)) - Functions.insert(FunTmpl); - } - } - - if (GlobalScope) { - DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) - = Context.getTranslationUnitDecl()->lookup(Name); - I != E; ++I) { - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I)) - Functions.insert(Func); - else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)) - Functions.insert(FunTmpl); + Decl *D = *I; + // If the only declaration here is an ordinary friend, consider + // it only if it was declared in an associated classes. + if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { + DeclContext *LexDC = D->getLexicalDeclContext(); + if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) + continue; + } + + CollectFunctionDecl(Functions, D); } } } |