diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 4a81f71dea..fe2b9de79e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -782,7 +782,7 @@ public: LookupResult LookupParsedName(Scope *S, const CXXScopeSpec &SS, DeclarationName Name, LookupCriteria Criteria); LookupResult LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S, - bool LookInParent = true); + bool LookInParent = true); LookupResult LookupDeclInContext(DeclarationName Name, unsigned NSI, const DeclContext *LookupCtx, bool LookInParent = true); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1559213fcb..cf71d394ce 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -39,31 +39,32 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S, return 0; DC = static_cast(SS->getScopeRep()); } - LookupResult Result = DC ? - LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) : - LookupDeclInScope(&II, Decl::IDNS_Ordinary, S); - Decl *IIDecl = 0; + + LookupResult Result = DC ? LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) : + LookupDeclInScope(&II, Decl::IDNS_Ordinary, S); + switch (Result.getKind()) { - case LookupResult::NotFound: - case LookupResult::FoundOverloaded: - case LookupResult::AmbiguousBaseSubobjectTypes: - case LookupResult::AmbiguousBaseSubobjects: - // FIXME: In the event of an ambiguous lookup, we could visit all of - // the entities found to determine whether they are all types. This - // might provide better diagnostics. - return 0; - - case LookupResult::Found: - IIDecl = Result.getAsDecl(); - break; + case LookupResult::NotFound: + case LookupResult::FoundOverloaded: + case LookupResult::AmbiguousBaseSubobjectTypes: + case LookupResult::AmbiguousBaseSubobjects: + // FIXME: In the event of an ambiguous lookup, we could visit all of + // the entities found to determine whether they are all types. This + // might provide better diagnostics. + return 0; + case LookupResult::Found: + IIDecl = Result.getAsDecl(); + break; } - if (isa(IIDecl) || - isa(IIDecl) || - isa(IIDecl) || - isa(IIDecl)) - return IIDecl; + if (IIDecl) { + if (isa(IIDecl) || + isa(IIDecl) || + isa(IIDecl) || + isa(IIDecl)) + return IIDecl; + } return 0; } @@ -265,19 +266,85 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { Sema::LookupResult Sema::LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S, bool LookInParent) { - 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; + 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)); } - // 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 @@ -2898,9 +2965,8 @@ 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. - PrevDecl = dyn_cast_or_null(LookupDeclInScope(Name, - Decl::IDNS_Tag,S) - .getAsDecl()); + Decl *D = LookupDeclInScope(Name, Decl::IDNS_Tag, S); + PrevDecl = dyn_cast_or_null(D); if (!getLangOptions().CPlusPlus && TK != TK_Reference) { // FIXME: This makes sure that we ignore the contexts associated