From 4c921ae760cbdd9270c16d48417d7d527eb0ceb8 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 30 Jan 2009 01:04:22 +0000 Subject: [PATCH] Eliminated LookupCriteria, whose creation was causing a bottleneck for LookupName et al. Instead, use an enum and a bool to describe its contents. Optimized the C/Objective-C path through LookupName, eliminating any unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing some code and arguments that are no longer used. Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers over to LookupName, LookupQualifiedName, or LookupParsedName, as appropriate. All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and -disable-free. Plus, we're down to three name-lookup routines. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63354 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/IdentifierResolver.cpp | 26 +---- lib/Sema/IdentifierResolver.h | 36 +++--- lib/Sema/Sema.h | 123 +++++++++----------- lib/Sema/SemaCXXScopeSpec.cpp | 10 +- lib/Sema/SemaDecl.cpp | 175 ++++------------------------ lib/Sema/SemaDeclCXX.cpp | 15 +-- lib/Sema/SemaDeclObjC.cpp | 16 +-- lib/Sema/SemaExpr.cpp | 21 ++-- lib/Sema/SemaExprCXX.cpp | 4 +- lib/Sema/SemaExprObjC.cpp | 6 +- lib/Sema/SemaInherit.cpp | 3 +- lib/Sema/SemaInherit.h | 10 +- lib/Sema/SemaLookup.cpp | 196 +++++++++++++++----------------- lib/Sema/SemaOverload.cpp | 5 +- lib/Sema/SemaTemplate.cpp | 8 +- 15 files changed, 223 insertions(+), 431 deletions(-) diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 4e9d085a75..781d89a0e9 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -225,14 +225,9 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { return toIdDeclInfo(Ptr)->RemoveDecl(D); } -/// begin - Returns an iterator for decls with name 'Name', starting at -/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the -/// decls of parent declaration contexts too. +/// begin - Returns an iterator for decls with name 'Name'. IdentifierResolver::iterator -IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx, - bool LookInParentCtx) { - assert(Ctx && "null param passed"); - +IdentifierResolver::begin(DeclarationName Name) { void *Ptr = Name.getFETokenInfo(); if (!Ptr) return end(); @@ -245,26 +240,11 @@ IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx, IdDeclInfo::DeclsTy::iterator I = IDI->decls_end(); if (I != IDI->decls_begin()) - return iterator(I-1, LookInParentCtx); + return iterator(I-1); else // No decls found. return end(); } -/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter. -void IdentifierResolver::iterator::PreIncIter() { - NamedDecl *D = **this; - void *InfoPtr = D->getDeclName().getFETokenInfo(); - assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); - IdDeclInfo *Info = toIdDeclInfo(InfoPtr); - - BaseIter I = getIterator(); - if (I != Info->decls_begin()) - *this = iterator(I-1, LookInParentCtx()); - else // No more decls. - *this = end(); -} - - //===----------------------------------------------------------------------===// // IdDeclInfoMap Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h index a44323e1b0..50b894a725 100644 --- a/lib/Sema/IdentifierResolver.h +++ b/lib/Sema/IdentifierResolver.h @@ -136,19 +136,12 @@ public: } /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration /// contexts depending on 'LookInParentCtx'. - iterator(BaseIter I, bool LookInParentCtx) { + iterator(BaseIter I) { Ptr = reinterpret_cast(I) | 0x1; - assert((Ptr & 0x2) == 0 && "Invalid Ptr!"); - if (LookInParentCtx) Ptr |= 0x2; } bool isIterator() const { return (Ptr & 0x1); } - bool LookInParentCtx() const { - assert(isIterator() && "Ptr not an iterator!"); - return (Ptr & 0x2) != 0; - } - BaseIter getIterator() const { assert(isIterator() && "Ptr not an iterator!"); return reinterpret_cast(Ptr & ~0x3); @@ -176,29 +169,32 @@ public: iterator& operator++() { if (!isIterator()) // common case. Ptr = 0; - else - PreIncIter(); + else { + NamedDecl *D = **this; + void *InfoPtr = D->getDeclName().getFETokenInfo(); + assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); + IdDeclInfo *Info = toIdDeclInfo(InfoPtr); + + BaseIter I = getIterator(); + if (I != Info->decls_begin()) + *this = iterator(I-1); + else // No more decls. + *this = iterator(); + } return *this; } uintptr_t getAsOpaqueValue() const { return Ptr; } static iterator getFromOpaqueValue(uintptr_t P) { - iterator Result(0); + iterator Result; Result.Ptr = P; return Result; } - - private: - void PreIncIter(); }; - /// begin - Returns an iterator for decls with the name 'Name', starting at - /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the - /// decls of parent declaration contexts too. - /// Default for 'LookInParentCtx is true. - static iterator begin(DeclarationName Name, const DeclContext *Ctx, - bool LookInParentCtx = true); + /// begin - Returns an iterator for decls with the name 'Name'. + static iterator begin(DeclarationName Name); /// end - Returns an iterator that has 'finished'. static iterator end() { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index fe2b9de79e..6e3a552686 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -559,7 +559,7 @@ public: /// for capturing language semantics (certain lookups will ignore /// certain names, for example) and for performance, since name /// lookup is often a bottleneck in the compilation of C++. Name - /// lookup criteria is specified via the LookupCriteria class. + /// lookup criteria is specified via the LookupCriteria enumeration. /// /// The results of name lookup can vary based on the kind of name /// lookup performed, the current language, and the translation @@ -571,65 +571,26 @@ public: /// the ability to distinguish among them. //@{ - /// @brief Describes the criteria by which name lookup will - /// determine whether a given name will be found. - /// - /// The LookupCriteria class captures the information required to - /// direct name lookup to find the appropriate kind of name. It - /// includes information about which kinds of names to consider - /// (ordinary names, tag names, class/struct/union member names, - /// namespace names, etc.) and where to look for those - /// names. LookupCriteria is used throughout semantic analysis to - /// specify how to search for a name, e.g., with the LookupName and - /// LookupQualifiedName functions. - struct LookupCriteria { - /// NameKind - The kinds of names that we are looking for. - enum NameKind { - /// Ordinary - Ordinary name lookup, which finds ordinary names - /// (functions, variables, typedefs, etc.) in C and most kinds - /// of names (functions, variables, members, types, etc.) in - /// C++. - Ordinary, - /// Tag - Tag name lookup, which finds the names of enums, - /// classes, structs, and unions. - Tag, - /// Member - Member name lookup, which finds the names of - /// class/struct/union members. - Member, - /// NestedNameSpecifier - Look up of a name that precedes the - /// '::' scope resolution operator in C++. This lookup - /// completely ignores operator, function, and enumerator names - /// (C++ [basic.lookup.qual]p1). - NestedNameSpecifier, - /// Namespace - Look up a namespace name within a C++ - /// using directive or namespace alias definition, ignoring - /// non-namespace names (C++ [basic.lookup.udir]p1). - Namespace - } Kind; - - /// AllowLazyBuiltinCreation - If true, permits name lookup to - /// lazily build declarations for built-in names, e.g., - /// __builtin_expect. - bool AllowLazyBuiltinCreation; - - /// RedeclarationOnly - If true, the lookup will only - /// consider entities within the scope where the lookup - /// began. Entities that might otherwise meet the lookup criteria - /// but are not within the original lookup scope will be ignored. - bool RedeclarationOnly; - - /// IDNS - Bitwise OR of the appropriate Decl::IDNS_* flags that - /// describe the namespaces where we should look for names. This - /// field is determined by the kind of name we're searching for. - unsigned IDNS; - - LookupCriteria() - : Kind(Ordinary), AllowLazyBuiltinCreation(true), - RedeclarationOnly(false), IDNS(Decl::IDNS_Ordinary) { } - - LookupCriteria(NameKind K, bool RedeclarationOnly, bool CPlusPlus); - - bool isLookupResult(Decl *D) const; + /// @brief Describes the kind of name lookup to perform. + enum LookupNameKind { + /// Ordinary name lookup, which finds ordinary names (functions, + /// variables, typedefs, etc.) in C and most kinds of names + /// (functions, variables, members, types, etc.) in C++. + LookupOrdinaryName = 0, + /// Tag name lookup, which finds the names of enums, classes, + /// structs, and unions. + LookupTagName, + /// Member name lookup, which finds the names of + /// class/struct/union members. + LookupMemberName, + /// Look up of a name that precedes the '::' scope resolution + /// operator in C++. This lookup completely ignores operator, + /// function, and enumerator names (C++ [basic.lookup.qual]p1). + LookupNestedNameSpecifierName, + /// Look up a namespace name within a C++ using directive or + /// namespace alias definition, ignoring non-namespace names (C++ + /// [basic.lookup.udir]p1). + LookupNamespaceName }; /// @brief Represents the results of name lookup. @@ -775,18 +736,38 @@ public: BasePaths *getBasePaths() const; }; - LookupResult LookupName(Scope *S, DeclarationName Name, - LookupCriteria Criteria); - LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, - LookupCriteria Criteria); - LookupResult LookupParsedName(Scope *S, const CXXScopeSpec &SS, - DeclarationName Name, LookupCriteria Criteria); - LookupResult LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S, - bool LookInParent = true); - LookupResult LookupDeclInContext(DeclarationName Name, unsigned NSI, - const DeclContext *LookupCtx, - bool LookInParent = true); + /// Determines whether D is a suitable lookup result according to the + /// lookup criteria. + bool isAcceptableLookupResult(Decl *D, LookupNameKind NameKind, + unsigned IDNS) const { + switch (NameKind) { + case Sema::LookupOrdinaryName: + case Sema::LookupTagName: + case Sema::LookupMemberName: + return D->isInIdentifierNamespace(IDNS); + + case Sema::LookupNestedNameSpecifierName: + return isa(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag); + + case Sema::LookupNamespaceName: + return isa(D); + } + + assert(false && + "isNameAcceptableLookupResult always returns before this point"); + return false; + } + LookupResult LookupName(Scope *S, DeclarationName Name, + LookupNameKind NameKind, + bool RedeclarationOnly = false); + LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, + LookupNameKind NameKind, + bool RedeclarationOnly = false); + LookupResult LookupParsedName(Scope *S, const CXXScopeSpec *SS, + DeclarationName Name, + LookupNameKind NameKind, + bool RedeclarationOnly = false); bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, SourceLocation NameLoc, SourceRange LookupRange = SourceRange()); diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index cf93571eb2..c77325f42d 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -36,10 +36,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II) { - Decl *SD = LookupParsedName(S, SS, &II, - LookupCriteria(LookupCriteria::NestedNameSpecifier, - /*RedeclarationOnly=*/false, - /*CPlusPlus=*/true)); + Decl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName); if (SD) { if (TypedefDecl *TD = dyn_cast(SD)) { @@ -60,10 +57,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, // ordinary name lookup, which can help us produce better error // messages. if (!SD) - SD = LookupParsedName(S, SS, &II, - LookupCriteria(LookupCriteria::Ordinary, - /*RedeclarationOnly=*/false, - /*CPlusPlus=*/true)); + SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName); unsigned DiagID; if (SD) DiagID = diag::err_expected_class_or_namespace; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cf71d394ce..ad6a719771 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -32,18 +32,8 @@ using namespace clang; Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS) { - DeclContext *DC = 0; - - if (SS) { - if (SS->isInvalid()) - return 0; - DC = static_cast(SS->getScopeRep()); - } Decl *IIDecl = 0; - - LookupResult Result = DC ? LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) : - LookupDeclInScope(&II, Decl::IDNS_Ordinary, S); - + LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, false); switch (Result.getKind()) { case LookupResult::NotFound: case LookupResult::FoundOverloaded: @@ -139,8 +129,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { // We're pushing the tag into the current context, which might // require some reshuffling in the identifier resolver. IdentifierResolver::iterator - I = IdResolver.begin(TD->getDeclName(), CurContext, - false/*LookInParentCtx*/), + I = IdResolver.begin(TD->getDeclName()), IEnd = IdResolver.end(); if (I != IEnd && isDeclInScope(*I, CurContext, S)) { NamedDecl *PrevDecl = *I; @@ -175,10 +164,8 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { // We are pushing the name of a function, which might be an // overloaded name. FunctionDecl *FD = cast(D); - DeclContext *DC = FD->getDeclContext()->getLookupContext(); IdentifierResolver::iterator Redecl - = std::find_if(IdResolver.begin(FD->getDeclName(), DC, - false/*LookInParentCtx*/), + = std::find_if(IdResolver.begin(FD->getDeclName()), IdResolver.end(), std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces), FD)); @@ -218,7 +205,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { // The third "scope" argument is 0 since we aren't enabling lazy built-in // creation from this context. - Decl *IDecl = LookupDeclInScope(Id, Decl::IDNS_Ordinary, 0); + Decl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName); return dyn_cast_or_null(IDecl); } @@ -255,123 +242,12 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { return S; } -/// LookupDeclInScope - Look up the inner-most declaration in the specified -/// namespace. NamespaceNameOnly - during lookup only namespace names -/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1 -/// 'When looking up a namespace-name in a using-directive or -/// namespace-alias-definition, only namespace names are considered.' -/// -/// Note: The use of this routine is deprecated. Please use -/// LookupName, LookupQualifiedName, or LookupParsedName instead. -Sema::LookupResult -Sema::LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S, - bool LookInParent) { - if (getLangOptions().CPlusPlus) { - LookupCriteria::NameKind Kind; - if (NSI == Decl::IDNS_Ordinary) { - Kind = LookupCriteria::Ordinary; - } else if (NSI == Decl::IDNS_Tag) - Kind = LookupCriteria::Tag; - else { - assert(NSI == Decl::IDNS_Member &&"Unable to grok LookupDecl NSI argument"); - Kind = LookupCriteria::Member; - } - // Unqualified lookup - return LookupName(S, Name, - LookupCriteria(Kind, !LookInParent, - getLangOptions().CPlusPlus)); - } - // Fast path for C/ObjC. - - // Unqualified name lookup in C/Objective-C is purely lexical, so - // search in the declarations attached to the name. - - // For the purposes of unqualified name lookup, structs and unions - // don't have scopes at all. For example: - // - // struct X { - // struct T { int i; } x; - // }; - // - // void f() { - // struct T t; // okay: T is defined lexically within X, but - // // semantically at global scope - // }; - // - // FIXME: Is there a better way to deal with this? - DeclContext *SearchCtx = CurContext; - while (isa(SearchCtx) || isa(SearchCtx)) - SearchCtx = SearchCtx->getParent(); - IdentifierResolver::iterator I - = IdResolver.begin(Name, SearchCtx, LookInParent); - - // Scan up the scope chain looking for a decl that matches this - // identifier that is in the appropriate namespace. This search - // should not take long, as shadowing of names is uncommon, and - // deep shadowing is extremely uncommon. - for (; I != IdResolver.end(); ++I) { - switch (NSI) { - case Decl::IDNS_Ordinary: - case Decl::IDNS_Tag: - case Decl::IDNS_Member: - if ((*I)->isInIdentifierNamespace(NSI)) - return LookupResult::CreateLookupResult(Context, *I); - break; - default: - assert(0 && "Unable to grok LookupDecl NSI argument"); - } - } - if (NSI == Decl::IDNS_Ordinary) { - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (II) { - // If this is a builtin on this (or all) targets, create the decl. - if (unsigned BuiltinID = II->getBuiltinID()) - return LookupResult::CreateLookupResult(Context, - LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, - S)); - } - if (getLangOptions().ObjC1 && II) { - // @interface and @compatibility_alias introduce typedef-like names. - // Unlike typedef's, they can only be introduced at file-scope (and are - // therefore not scoped decls). They can, however, be shadowed by - // other names in IDNS_Ordinary. - ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II); - if (IDI != ObjCInterfaceDecls.end()) - return LookupResult::CreateLookupResult(Context, IDI->second); - ObjCAliasTy::iterator I = ObjCAliasDecls.find(II); - if (I != ObjCAliasDecls.end()) - return LookupResult::CreateLookupResult(Context, - I->second->getClassInterface()); - } - } - return LookupResult::CreateLookupResult(Context, 0); -} - -Sema::LookupResult -Sema::LookupDeclInContext(DeclarationName Name, unsigned NSI, - const DeclContext *LookupCtx, - bool LookInParent) { - assert(LookupCtx && "LookupDeclInContext(): Missing DeclContext"); - LookupCriteria::NameKind Kind; - if (NSI == Decl::IDNS_Ordinary) { - Kind = LookupCriteria::Ordinary; - } else if (NSI == Decl::IDNS_Tag) - Kind = LookupCriteria::Tag; - else { - assert(NSI == Decl::IDNS_Member &&"Unable to grok LookupDecl NSI argument"); - Kind = LookupCriteria::Member; - } - return LookupQualifiedName(const_cast(LookupCtx), Name, - LookupCriteria(Kind, !LookInParent, - getLangOptions().CPlusPlus)); -} - void Sema::InitBuiltinVaListType() { if (!Context.getBuiltinVaListType().isNull()) return; IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list"); - Decl *VaDecl = LookupDeclInScope(VaIdent, Decl::IDNS_Ordinary, TUScope); + Decl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName); TypedefDecl *VaTypedef = cast(VaDecl); Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef)); } @@ -420,7 +296,7 @@ NamespaceDecl *Sema::GetStdNamespace() { if (!StdNamespace) { IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std"); DeclContext *Global = Context.getTranslationUnitDecl(); - Decl *Std = LookupDeclInContext(StdIdent, Decl::IDNS_Ordinary, Global); + Decl *Std = LookupQualifiedName(Global, StdIdent, LookupNamespaceName); StdNamespace = dyn_cast_or_null(Std); } return StdNamespace; @@ -689,10 +565,9 @@ void Sema::CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD) { // FIXME: I don't think this will actually see all of the // redefinitions. Can't we check this property on-the-fly? - for (IdentifierResolver::iterator - I = IdResolver.begin(VD->getIdentifier(), - VD->getDeclContext(), false/*LookInParentCtx*/), - E = IdResolver.end(); I != E; ++I) { + for (IdentifierResolver::iterator I = IdResolver.begin(VD->getIdentifier()), + E = IdResolver.end(); + I != E; ++I) { if (*I != VD && isDeclInScope(*I, VD->getDeclContext(), S)) { VarDecl *OldDecl = dyn_cast(*I); @@ -864,8 +739,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - Decl *PrevDecl = LookupDeclInContext((*F)->getDeclName(), - Decl::IDNS_Ordinary, Owner, false); + Decl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(), + LookupOrdinaryName, true); if (PrevDecl && !isa(PrevDecl)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be @@ -1312,13 +1187,12 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, bool InvalidDecl = false; // See if this is a redefinition of a variable in the same scope. - if (!D.getCXXScopeSpec().isSet()) { + if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) { DC = CurContext; - PrevDecl = LookupDeclInScope(Name, Decl::IDNS_Ordinary, S); + PrevDecl = LookupName(S, Name, LookupOrdinaryName); } else { // Something like "int foo::x;" DC = static_cast(D.getCXXScopeSpec().getScopeRep()); - PrevDecl = DC ? LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC) - : LookupDeclInScope(Name, Decl::IDNS_Ordinary, S); + PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName); // C++ 7.3.1.2p2: // Members (including explicit specializations of templates) of a named @@ -1807,7 +1681,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << D.getCXXScopeSpec().getRange(); InvalidDecl = true; - PrevDecl = LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC); + PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName); if (!PrevDecl) { // Nothing to suggest. } else if (OverloadedFunctionDecl *Ovl @@ -2662,7 +2536,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // among each other. Here they can only shadow globals, which is ok. IdentifierInfo *II = D.getIdentifier(); if (II) { - if (Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, S)) { + if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); @@ -2954,7 +2828,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, DC = static_cast(SS.getScopeRep()); // Look-up name inside 'foo::'. PrevDecl = dyn_cast_or_null( - LookupDeclInContext(Name, Decl::IDNS_Tag, DC).getAsDecl()); + LookupQualifiedName(DC, Name, LookupTagName).getAsDecl()); // A tag 'foo::bar' must already exist. if (PrevDecl == 0) { @@ -2965,14 +2839,14 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, } else if (Name) { // If this is a named struct, check to see if there was a previous forward // declaration or definition. - Decl *D = LookupDeclInScope(Name, Decl::IDNS_Tag, S); + Decl *D = LookupName(S, Name, LookupTagName); PrevDecl = dyn_cast_or_null(D); if (!getLangOptions().CPlusPlus && TK != TK_Reference) { // FIXME: This makes sure that we ignore the contexts associated // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak - // in Sema::LookupDecl; is there a better way to deal with this? + // in Sema::LookupName; is there a better way to deal with this? while (isa(SearchDC) || isa(SearchDC)) SearchDC = SearchDC->getParent(); } @@ -3158,9 +3032,7 @@ CreateNewDecl: // shall not be declared with the same name as a typedef-name // that is declared in that scope and refers to a type other // than the class or enumeration itself. - LookupResult Lookup = LookupName(S, Name, - LookupCriteria(LookupCriteria::Ordinary, - true, true)); + LookupResult Lookup = LookupName(S, Name, LookupOrdinaryName, true); TypedefDecl *PrevTypedef = 0; if (Lookup.getKind() == LookupResult::Found) PrevTypedef = dyn_cast(Lookup.getAsDecl()); @@ -3352,8 +3224,7 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD, DeclSpec::SCS_mutable); if (II) { - Decl *PrevDecl - = LookupDeclInScope(II, Decl::IDNS_Member, S, false); + Decl *PrevDecl = LookupName(S, II, LookupMemberName, true); if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -3445,7 +3316,7 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S, (Expr *)BitfieldWidth); if (II) { - Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Member, S, false); + Decl *PrevDecl = LookupName(S, II, LookupMemberName, true); if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -3621,7 +3492,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, // Verify that there isn't already something declared with this name in this // scope. - Decl *PrevDecl = LookupDeclInScope(Id, Decl::IDNS_Ordinary, S); + Decl *PrevDecl = LookupName(S, Id, LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1870a8fdd3..24f753164d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1375,8 +1375,8 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // original-namespace-definition is the name of the namespace. Subsequently // in that declarative region, it is treated as an original-namespace-name. - Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, DeclRegionScope, - /*LookupInParent=*/false); + Decl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName, + true); if (NamespaceDecl *OrigNS = dyn_cast_or_null(PrevDecl)) { // This is an extended namespace definition. @@ -1437,14 +1437,7 @@ Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S, // FIXME: This still requires lot more checks, and AST support. // Lookup namespace name. - LookupCriteria Criteria(LookupCriteria::Namespace, /*RedeclarationOnly=*/false, - /*CPlusPlus=*/true); - Decl *NS = 0; - if (SS.isSet()) - NS = LookupQualifiedName(static_cast(SS.getScopeRep()), - NamespcName, Criteria); - else - NS = LookupName(S, NamespcName, Criteria); + Decl *NS = LookupParsedName(S, &SS, NamespcName, LookupNamespaceName, false); if (NS) { assert(isa(NS) && "expected namespace decl"); @@ -2179,7 +2172,7 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) // FIXME: Need to check for abstract classes. IdentifierInfo *II = D.getIdentifier(); - if (Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, S)) { + if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration. assert(!S->isDeclScope(PrevDecl)); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 3371e3ea6e..c3519f8f01 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -64,7 +64,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. - Decl *PrevDecl = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope); + Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(ClassLoc, PrevDecl); @@ -107,7 +107,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (SuperName) { ObjCInterfaceDecl* SuperClassEntry = 0; // Check if a different kind of symbol declared in this scope. - PrevDecl = LookupDeclInScope(SuperName, Decl::IDNS_Ordinary, TUScope); + PrevDecl = LookupName(TUScope, SuperName, LookupOrdinaryName); if (PrevDecl && !isa(PrevDecl)) { Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); @@ -149,7 +149,7 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, IdentifierInfo *ClassName, SourceLocation ClassLocation) { // Look for previous declaration of alias name - Decl *ADecl = LookupDeclInScope(AliasName, Decl::IDNS_Ordinary, TUScope); + Decl *ADecl = LookupName(TUScope, AliasName, LookupOrdinaryName); if (ADecl) { if (isa(ADecl)) Diag(AliasLocation, diag::warn_previous_alias_decl); @@ -159,13 +159,13 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, return 0; } // Check for class declaration - Decl *CDeclU = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope); + Decl *CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName); if (const TypedefDecl *TDecl = dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCInterfaceType()) { if (NamedDecl *IDecl = T->getAsObjCInterfaceType()->getDecl()) { ClassName = IDecl->getIdentifier(); - CDeclU = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope); + CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName); } } } @@ -535,7 +535,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( SourceLocation SuperClassLoc) { ObjCInterfaceDecl* IDecl = 0; // Check for another declaration kind with the same name. - Decl *PrevDecl = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope); + Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName); if (PrevDecl && !isa(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); @@ -551,7 +551,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( ObjCInterfaceDecl* SDecl = 0; if (SuperClassname) { // Check if a different kind of symbol declared in this scope. - PrevDecl = LookupDeclInScope(SuperClassname, Decl::IDNS_Ordinary, TUScope); + PrevDecl = LookupName(TUScope, SuperClassname, LookupOrdinaryName); if (PrevDecl && !isa(PrevDecl)) { Diag(SuperClassLoc, diag::err_redefinition_different_kind) << SuperClassname; @@ -909,7 +909,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, for (unsigned i = 0; i != NumElts; ++i) { // Check for another declaration kind with the same name. - Decl *PrevDecl = LookupDeclInScope(IdentList[i], Decl::IDNS_Ordinary, TUScope); + Decl *PrevDecl = LookupName(TUScope, IdentList[i], LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5ebec0270b..129967a14b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -555,14 +555,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Could be enum-constant, value decl, instance variable, etc. Decl *D = 0; - LookupResult Lookup; - if (SS && !SS->isEmpty()) { - DeclContext *DC = static_cast(SS->getScopeRep()); - if (DC == 0) - return ExprError(); - Lookup = LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC); - } else - Lookup = LookupDeclInScope(Name, Decl::IDNS_Ordinary, S); + if (SS && SS->isInvalid()) + return ExprError(); + LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName); if (Lookup.isAmbiguous()) { DiagnoseAmbiguousLookup(Lookup, Name, Loc, @@ -1519,9 +1514,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // than this. LookupResult Result = LookupQualifiedName(RDecl, DeclarationName(&Member), - LookupCriteria(LookupCriteria::Member, - /*RedeclarationOnly=*/false, - getLangOptions().CPlusPlus)); + LookupMemberName, false); Decl *MemberDecl = 0; if (!Result) @@ -4030,9 +4023,9 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, // Get the decl corresponding to this. RecordDecl *RD = RC->getDecl(); FieldDecl *MemberDecl - = dyn_cast_or_null(LookupDeclInContext(OC.U.IdentInfo, - Decl::IDNS_Ordinary, - RD, false).getAsDecl()); + = dyn_cast_or_null(LookupQualifiedName(RD, OC.U.IdentInfo, + LookupMemberName) + .getAsDecl()); if (!MemberDecl) return Diag(BuiltinLoc, diag::err_typecheck_no_member) << OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d0ceb97b3a..3c8184d24d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -55,12 +55,12 @@ Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc, Action::ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { - const NamespaceDecl *StdNs = GetStdNamespace(); + NamespaceDecl *StdNs = GetStdNamespace(); if (!StdNs) return Diag(OpLoc, diag::err_need_header_before_typeid); IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); - Decl *TypeInfoDecl = LookupDeclInContext(TypeInfoII, Decl::IDNS_Tag, StdNs); + Decl *TypeInfoDecl = LookupQualifiedName(StdNs, TypeInfoII, LookupTagName); RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null(TypeInfoDecl); if (!TypeInfoRecordDecl) return Diag(OpLoc, diag::err_need_header_before_typeid); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index f436e61ee9..f893f1eec5 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -52,7 +52,7 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Initialize the constant string interface lazily. This assumes // the NSConstantString interface is seen in this translation unit. IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); - Decl *IFace = LookupDeclInScope(NSIdent, Decl::IDNS_Ordinary, TUScope); + Decl *IFace = LookupName(TUScope, NSIdent, LookupOrdinaryName); ObjCInterfaceDecl *strIFace = dyn_cast_or_null(IFace); if (strIFace) Context.setObjCConstantStringInterface(strIFace); @@ -209,7 +209,7 @@ Sema::ExprResult Sema::ActOnClassMessage( } else { // 'super' has been used outside a method context. If a variable named // 'super' has been declared, redirect. If not, produce a diagnostic. - Decl *SuperDecl = LookupDeclInScope(receiverName, Decl::IDNS_Ordinary, S); + Decl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName); ValueDecl *VD = dyn_cast_or_null(SuperDecl); if (VD) { ExprResult ReceiverExpr = new DeclRefExpr(VD, VD->getType(), @@ -234,7 +234,7 @@ Sema::ExprResult Sema::ActOnClassMessage( // // If necessary, the following lookup could move to getObjCInterfaceDecl(). if (!ClassDecl) { - Decl *IDecl = LookupDeclInScope(receiverName, Decl::IDNS_Ordinary, 0); + Decl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName); if (TypedefDecl *OCTD = dyn_cast_or_null(IDecl)) { const ObjCInterfaceType *OCIT; OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType(); diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp index cb58063d84..0772bc3c1e 100644 --- a/lib/Sema/SemaInherit.cpp +++ b/lib/Sema/SemaInherit.cpp @@ -153,7 +153,8 @@ bool Sema::LookupInBases(CXXRecordDecl *Class, } else { Paths.ScratchPath.Decls = BaseRecord->lookup(Criteria.Name); while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) { - if (Criteria.Criteria.isLookupResult(*Paths.ScratchPath.Decls.first)) { + if (isAcceptableLookupResult(*Paths.ScratchPath.Decls.first, + Criteria.NameKind, Criteria.IDNS)) { FoundPathToThisBase = true; break; } diff --git a/lib/Sema/SemaInherit.h b/lib/Sema/SemaInherit.h index 87a4a663ae..eb169a2982 100644 --- a/lib/Sema/SemaInherit.h +++ b/lib/Sema/SemaInherit.h @@ -193,8 +193,9 @@ namespace clang { /// MemberLookupCriteria - Constructs member lookup criteria to /// search for a class member with the given Name. explicit MemberLookupCriteria(DeclarationName Name, - Sema::LookupCriteria Criteria) - : LookupBase(false), Name(Name), Criteria(Criteria) { } + Sema::LookupNameKind NameKind, + unsigned IDNS) + : LookupBase(false), Name(Name), NameKind(NameKind), IDNS(IDNS) { } /// LookupBase - True if we are looking for a base class (whose /// type is Base). If false, we are looking for a named member of @@ -209,9 +210,8 @@ namespace clang { /// LookupBase is false. DeclarationName Name; - /// Criteria - The criteria by which we evaluate a named member, - /// if LookupBase is false. - Sema::LookupCriteria Criteria; + Sema::LookupNameKind NameKind; + unsigned IDNS; }; } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 7353bc37e4..abb265da49 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -31,8 +31,8 @@ using namespace clang; /// OverloadeFunctionDecl that represents the overloaded functions in /// [I, IEnd). /// -/// The existance of this routine is temporary; LookupDecl should -/// probably be able to return multiple results, to deal with cases of +/// 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 @@ -69,64 +69,6 @@ MaybeConstructOverloadSet(ASTContext &Context, return *I; } -/// @brief Constructs name lookup criteria. -/// -/// @param K The kind of name that we're searching for. -/// -/// @param RedeclarationOnly If true, then name lookup will only look -/// into the current scope for names, not in parent scopes. This -/// option should be set when we're looking to introduce a new -/// declaration into scope. -/// -/// @param CPlusPlus Whether we are performing C++ name lookup or not. -Sema::LookupCriteria::LookupCriteria(NameKind K, bool RedeclarationOnly, - bool CPlusPlus) - : Kind(K), AllowLazyBuiltinCreation(K == Ordinary), - RedeclarationOnly(RedeclarationOnly) { - switch (Kind) { - case Ordinary: - IDNS = Decl::IDNS_Ordinary; - if (CPlusPlus) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member; - break; - - case Tag: - IDNS = Decl::IDNS_Tag; - break; - - case Member: - IDNS = Decl::IDNS_Member; - if (CPlusPlus) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; - break; - - case NestedNameSpecifier: - case Namespace: - IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member; - break; - } -} - -/// isLookupResult - Determines whether D is a suitable lookup result -/// according to the lookup criteria. -bool Sema::LookupCriteria::isLookupResult(Decl *D) const { - switch (Kind) { - case Ordinary: - case Tag: - case Member: - return D->isInIdentifierNamespace(IDNS); - - case NestedNameSpecifier: - return isa(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag); - - case Namespace: - return isa(D); - } - - assert(false && "isLookupResult always returns before this point"); - return false; -} - /// @brief Moves the name-lookup results from Other to this LookupResult. Sema::LookupResult Sema::LookupResult::CreateLookupResult(ASTContext &Context, @@ -239,6 +181,37 @@ BasePaths *Sema::LookupResult::getBasePaths() const { return reinterpret_cast(First); } +// Retrieve the set of identifier namespaces that correspond to a +// specific kind of name lookup. +inline unsigned +getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, + bool CPlusPlus) { + unsigned IDNS = 0; + switch (NameKind) { + case Sema::LookupOrdinaryName: + IDNS = Decl::IDNS_Ordinary; + if (CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member; + break; + + case Sema::LookupTagName: + IDNS = Decl::IDNS_Tag; + break; + + case Sema::LookupMemberName: + IDNS = Decl::IDNS_Member; + if (CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; + break; + + case Sema::LookupNestedNameSpecifierName: + case Sema::LookupNamespaceName: + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member; + break; + } + return IDNS; +} + /// @brief Perform unqualified name lookup starting from a given /// scope. /// @@ -276,52 +249,58 @@ BasePaths *Sema::LookupResult::getBasePaths() const { /// declarations and possibly additional information used to diagnose /// ambiguities. Sema::LookupResult -Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) { +Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, + bool RedeclarationOnly) { if (!Name) return LookupResult::CreateLookupResult(Context, 0); if (!getLangOptions().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. + unsigned IDNS = 0; + switch (NameKind) { + case Sema::LookupOrdinaryName: + IDNS = Decl::IDNS_Ordinary; + break; + + case Sema::LookupTagName: + IDNS = Decl::IDNS_Tag; + break; + + case Sema::LookupMemberName: + IDNS = Decl::IDNS_Member; + break; + + case Sema::LookupNestedNameSpecifierName: + case Sema::LookupNamespaceName: + assert(false && "C does not perform these kinds of name lookup"); + break; + } - // For the purposes of unqualified name lookup, structs and unions - // don't have scopes at all. For example: - // - // struct X { - // struct T { int i; } x; - // }; - // - // void f() { - // struct T t; // okay: T is defined lexically within X, but - // // semantically at global scope - // }; - // - // FIXME: Is there a better way to deal with this? - DeclContext *SearchCtx = CurContext; - while (isa(SearchCtx) || isa(SearchCtx)) - SearchCtx = SearchCtx->getParent(); - IdentifierResolver::iterator I - = IdResolver.begin(Name, SearchCtx, !Criteria.RedeclarationOnly); - // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search // should not take long, as shadowing of names is uncommon, and // deep shadowing is extremely uncommon. - for (; I != IdResolver.end(); ++I) - if (Criteria.isLookupResult(*I)) + for (IdentifierResolver::iterator I = IdResolver.begin(Name), + IEnd = IdResolver.end(); + I != IEnd; ++I) + if ((*I)->isInIdentifierNamespace(IDNS)) return LookupResult::CreateLookupResult(Context, *I); } else { + unsigned IDNS + = getIdentifierNamespacesFromLookupNameKind(NameKind, + getLangOptions().CPlusPlus); + // Unqualified name lookup in C++ requires looking into scopes // that aren't strictly lexical, and therefore we walk through the // context as well as walking through the scopes. // FIXME: does "true" for LookInParentCtx actually make sense? - IdentifierResolver::iterator - I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/), - IEnd = IdResolver.end(); + IdentifierResolver::iterator I = IdResolver.begin(Name), + IEnd = IdResolver.end(); for (; S; S = S->getParent()) { // Check whether the IdResolver has anything in this scope. for (; I != IEnd && S->isDeclScope(*I); ++I) { - if (Criteria.isLookupResult(*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 @@ -356,10 +335,11 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) { Ctx = Ctx->getParent(); while (Ctx && (Ctx->isNamespace() || Ctx->isRecord())) { // Look for declarations of this name in this scope. - if (LookupResult Result = LookupQualifiedName(Ctx, Name, Criteria)) + if (LookupResult Result = LookupQualifiedName(Ctx, Name, NameKind, + RedeclarationOnly)) return Result; - if (Criteria.RedeclarationOnly && !Ctx->isTransparentContext()) + if (RedeclarationOnly && !Ctx->isTransparentContext()) return LookupResult::CreateLookupResult(Context, 0); Ctx = Ctx->getParent(); @@ -370,9 +350,9 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) { // 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 (Criteria.Kind == LookupCriteria::Ordinary) { + if (NameKind == LookupOrdinaryName) { IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (Criteria.AllowLazyBuiltinCreation && II) { + if (II) { // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) return LookupResult::CreateLookupResult(Context, @@ -428,25 +408,28 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) { /// ambiguities. Sema::LookupResult Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, - LookupCriteria Criteria) { + LookupNameKind NameKind, bool RedeclarationOnly) { assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); if (!Name) return LookupResult::CreateLookupResult(Context, 0); // If we're performing qualified name lookup (e.g., lookup into a // struct), find fields as part of ordinary name lookup. - if (Criteria.Kind == LookupCriteria::Ordinary) - Criteria.IDNS |= Decl::IDNS_Member; + unsigned IDNS + = getIdentifierNamespacesFromLookupNameKind(NameKind, + getLangOptions().CPlusPlus); + if (NameKind == LookupOrdinaryName) + IDNS |= Decl::IDNS_Member; // Perform qualified name lookup into the LookupCtx. DeclContext::lookup_iterator I, E; for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) - if (Criteria.isLookupResult(*I)) + if (isAcceptableLookupResult(*I, NameKind, IDNS)) return LookupResult::CreateLookupResult(Context, I, E); // If this isn't a C++ class or we aren't allowed to look into base // classes, we're done. - if (Criteria.RedeclarationOnly || !isa(LookupCtx)) + if (RedeclarationOnly || !isa(LookupCtx)) return LookupResult::CreateLookupResult(Context, 0); // Perform lookup into our base classes. @@ -455,7 +438,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // Look for this member in our base classes if (!LookupInBases(cast(LookupCtx), - MemberLookupCriteria(Name, Criteria), Paths)) + MemberLookupCriteria(Name, NameKind, IDNS), Paths)) return LookupResult::CreateLookupResult(Context, 0); // C++ [class.member.lookup]p2: @@ -552,18 +535,21 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, /// @param Name The name of the entity that name lookup will /// search for. /// -/// @param Criteria The criteria that will determine which entities -/// are visible to name lookup. -/// /// @returns The result of qualified or unqualified name lookup. Sema::LookupResult -Sema::LookupParsedName(Scope *S, const CXXScopeSpec &SS, - DeclarationName Name, LookupCriteria Criteria) { - if (SS.isSet()) - return LookupQualifiedName(static_cast(SS.getScopeRep()), - Name, Criteria); +Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, + DeclarationName Name, LookupNameKind NameKind, + bool RedeclarationOnly) { + if (SS) { + if (SS->isInvalid()) + return LookupResult::CreateLookupResult(Context, 0); - return LookupName(S, Name, Criteria); + if (SS->isSet()) + return LookupQualifiedName(static_cast(SS->getScopeRep()), + Name, NameKind, RedeclarationOnly); + } + + return LookupName(S, Name, NameKind, RedeclarationOnly); } /// @brief Produce a diagnostic describing the ambiguity that resulted diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 0f9f0cf9c6..17ad387ac3 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2279,9 +2279,8 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, // of type T2 or “reference to (possibly cv-qualified) T2”, // when T2 is an enumeration type, are candidate functions. { - IdentifierResolver::iterator - I = IdResolver.begin(OpName, CurContext, true/*LookInParentCtx*/), - IEnd = IdResolver.end(); + IdentifierResolver::iterator I = IdResolver.begin(OpName), + IEnd = IdResolver.end(); for (; I != IEnd; ++I) { // We don't need to check the identifier namespace, because // operator names can only be ordinary identifiers. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7ecac00277..f1b8617dae 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -32,9 +32,7 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S, return 0; DC = static_cast(SS->getScopeRep()); } - Decl *IIDecl = DC ? - LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC, false) : - LookupDeclInScope(&II, Decl::IDNS_Ordinary, S, false); + Decl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName); if (IIDecl) { // FIXME: We need to represent templates via some kind of @@ -96,7 +94,7 @@ Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Invalid = false; if (ParamName) { - Decl *PrevDecl = LookupDeclInScope(ParamName, Decl::IDNS_Tag, S); + Decl *PrevDecl = LookupName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl); @@ -132,7 +130,7 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, IdentifierInfo *ParamName = D.getIdentifier(); if (ParamName) { - Decl *PrevDecl = LookupDeclInScope(ParamName, Decl::IDNS_Tag, S); + Decl *PrevDecl = LookupName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);