diff options
author | John McCall <rjmccall@apple.com> | 2009-10-09 21:13:30 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-10-09 21:13:30 +0000 |
commit | f36e02d4aff98bf2e52e342e0038d4172fbb5e64 (patch) | |
tree | de0e84cc5c69c3749a01794221565dcbe5d22614 /lib/Sema/SemaLookup.cpp | |
parent | d7e5bdb23c6ba2786cf94788c9af555e2c1276ce (diff) |
Refactor the LookupResult API to simplify most common operations. Require users to
pass a LookupResult reference to lookup routines. Call out uses which assume a single
result.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83674 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 771 |
1 files changed, 226 insertions, 545 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 82a11b644e..1c6e936827 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -35,7 +35,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. @@ -107,178 +106,6 @@ static void AddScopeUsingDirectives(ASTContext &Context, Scope *S, } } -/// 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 = TD->getCanonicalDecl(); - 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 @@ -324,97 +151,78 @@ 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; - } - } +void Sema::LookupResult::resolveKind() { + unsigned N = Decls.size(); - NamedDecl *D = *F; - if (D) - D = D->getUnderlyingDecl(); + // Fast case: no possible ambiguity. + if (N <= 1) return; - Result.StoredKind = SingleDecl; - Result.First = reinterpret_cast<uintptr_t>(D); - Result.Last = 0; - return Result; -} + llvm::SmallPtrSet<NamedDecl*, 16> Unique; -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; + bool Ambiguous = false; + bool HasTag = false, HasFunction = false, HasNonFunction = false; + + 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++; } } - NamedDecl *D = *F; - if (D) - D = D->getUnderlyingDecl(); - - Result.StoredKind = SingleDecl; - Result.First = reinterpret_cast<uintptr_t>(D); - Result.Last = 0; - return Result; -} - -/// @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; - - case OverloadedDeclSingleDecl: - case OverloadedDeclFromIdResolver: - case OverloadedDeclFromDeclContext: - return FoundOverloaded; - - case AmbiguousLookupStoresBasePaths: - return Last? AmbiguousBaseSubobjectTypes : AmbiguousBaseSubobjects; - - case AmbiguousLookupStoresDecls: - return AmbiguousReference; - } + // 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; - // We can't ever get here. - return NotFound; + if (Ambiguous) + Kind = AmbiguousReference; + else if (N > 1) + Kind = FoundOverloaded; + else + Kind = Found; } /// @brief Converts the result of name lookup into a single (possible @@ -430,191 +238,93 @@ Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const { /// 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. -CXXBasePaths *Sema::LookupResult::getBasePaths() const { - if (StoredKind == AmbiguousLookupStoresBasePaths) - return reinterpret_cast<CXXBasePaths *>(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(); + Kind = 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(); + Kind = 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()))); - } +// 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; - 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)); - } - - // 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 (CXXBasePaths *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 @@ -625,9 +335,13 @@ CppNamespaceLookup(ASTContext &Context, DeclContext *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) { @@ -645,8 +359,8 @@ static DeclContext *findOuterContext(Scope *S) { return 0; } -std::pair<bool, Sema::LookupResult> -Sema::CppLookupName(Scope *S, DeclarationName Name, +bool +Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, LookupNameKind NameKind, bool RedeclarationOnly) { assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); @@ -684,25 +398,19 @@ 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; - DeclContext *OuterCtx = findOuterContext(S); for (; Ctx && Ctx->getPrimaryContext() != OuterCtx; Ctx = Ctx->getLookupParent()) { @@ -715,9 +423,8 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // 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. - R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly); - if (R) - return std::make_pair(true, R); + if (LookupQualifiedName(R, Ctx, Name, NameKind, RedeclarationOnly)) + return true; } } } @@ -740,8 +447,6 @@ 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; - bool LookedInCtx = false; for (; S; S = S->getParent()) { DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); if (Ctx->isTransparentContext()) @@ -751,45 +456,32 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, "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; - LookupResult Result; - 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,11 +515,10 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, /// @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 @@ -897,6 +588,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. @@ -912,20 +605,18 @@ 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 @@ -941,15 +632,16 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, // 'malloc'. Instead, we'll just error. if (getLangOptions().CPlusPlus && Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return LookupResult::CreateLookupResult(Context, 0); + return false; - return LookupResult::CreateLookupResult(Context, - LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, - S, RedeclarationOnly, Loc)); + NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, + S, RedeclarationOnly, Loc); + if (D) R.addDecl(D); + return (D != NULL); } } } - return LookupResult::CreateLookupResult(Context, 0); + return false; } /// @brief Perform qualified name lookup into a given context. @@ -982,13 +674,13 @@ 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); + return false; // If we're performing qualified name lookup (e.g., lookup into a // struct), find fields as part of ordinary name lookup. @@ -1007,15 +699,15 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, "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; + } // 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); + return false; // Perform lookup into our base classes. CXXRecordDecl *LookupRec = cast<CXXRecordDecl>(LookupCtx); @@ -1041,7 +733,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, case LookupObjCImplementationName: case LookupObjCCategoryImplName: // These lookups will never find a member in a C++ class (or base class). - return LookupResult::CreateLookupResult(Context, 0); + return false; case LookupNestedNameSpecifierName: BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; @@ -1049,7 +741,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, } if (!LookupRec->lookupInBases(BaseCallback, Name.getAsOpaquePtr(), Paths)) - return LookupResult::CreateLookupResult(Context, 0); + return false; // C++ [class.member.lookup]p2: // [...] If the resulting set of declarations are not all from @@ -1066,16 +758,15 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // 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 != Context.getCanonicalType(PathElement.Base->getType())) { // We found members of the given name in two subobjects of // different types. This lookup is ambiguous. - CXXBasePaths *PathsOnHeap = new CXXBasePaths; - 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. @@ -1111,21 +802,18 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // We have found a nonstatic member name in multiple, distinct // subobjects. Name lookup is ambiguous. - CXXBasePaths *PathsOnHeap = new CXXBasePaths; - 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 @@ -1152,17 +840,16 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, /// @param EnteringContext Indicates whether we are going to enter the /// context of the scope-specifier SS (if present). /// -/// @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, - bool EnteringContext) { +/// @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. - return LookupResult::CreateLookupResult(Context, 0); + return false; } if (SS && SS->isSet()) { @@ -1170,20 +857,20 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, // 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 LookupResult::CreateLookupResult(Context, 0); + return false; - return LookupQualifiedName(DC, Name, NameKind, RedeclarationOnly); + return LookupQualifiedName(R, DC, Name, NameKind, RedeclarationOnly); } // We could not resolve the scope specified to a specific declaration |