diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index fd961fa2c0b6..6beab5843cfb 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -15,6 +15,7 @@ add_clang_library(clangSema SemaExprObjC.cpp SemaInherit.cpp SemaInit.cpp + SemaLookup.cpp SemaNamedCast.cpp SemaOverload.cpp SemaStmt.cpp diff --git a/clang/lib/Sema/IdentifierResolver.h b/clang/lib/Sema/IdentifierResolver.h index 3dab1b53a75d..c29fffb36d29 100644 --- a/clang/lib/Sema/IdentifierResolver.h +++ b/clang/lib/Sema/IdentifierResolver.h @@ -181,6 +181,14 @@ public: return *this; } + uintptr_t getAsOpaqueValue() const { return Ptr; } + + static iterator getFromOpaqueValue(uintptr_t P) { + iterator Result(0); + Result.Ptr = P; + return Result; + } + private: void PreIncIter(); }; diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3a5f93fc8f4f..899cb4a20908 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -18,6 +18,7 @@ #include "IdentifierResolver.h" #include "CXXFieldCollector.h" #include "SemaOverload.h" +#include "clang/AST/DeclBase.h" #include "clang/Parse/Action.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallVector.h" @@ -516,26 +517,206 @@ public: Scope *getNonFieldDeclScope(Scope *S); - /// More parsing and symbol table subroutines. - Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, - const DeclContext *LookupCtx = 0, - bool enableLazyBuiltinCreation = true, - bool LookInParent = true, - bool NamespaceNameOnly = false); + /// \name Name lookup + /// + /// These routines provide name lookup that is used during semantic + /// analysis to resolve the various kinds of names (identifiers, + /// overloaded operator names, constructor names, etc.) into zero or + /// more declarations within a particular scope. The major entry + /// points are LookupName, which performs unqualified name lookup, + /// and LookupQualifiedName, which performs qualified name lookup. + /// + /// All name lookup is performed based on some specific criteria, + /// which specify what names will be visible to name lookup and how + /// far name lookup should work. These criteria are important both + /// 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. + /// + /// The results of name lookup can vary based on the kind of name + /// lookup performed, the current language, and the translation + /// unit. In C, for example, name lookup will either return nothing + /// (no entity found) or a single declaration. In C++, name lookup + /// can additionally refer to a set of overloaded functions or + /// result in an ambiguity. All of the possible results of name + /// lookup are captured by the LookupResult class, which provides + /// the ability to distinguish among them. + //@{ - Decl *LookupNamespaceName(DeclarationName Name, Scope *S, - const DeclContext *LookupCtx) { - return LookupDecl(Name, Decl::IDNS_Tag | Decl::IDNS_Ordinary, S, - LookupCtx, - /* enableLazyBuiltinCreation */ false, - /* LookInParent */ true, - /* NamespaceNameOnly */ true); - } + /// @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(NameKind K, bool RedeclarationOnly, bool CPlusPlus); + + bool isLookupResult(Decl *D) const; + }; + + /// @brief Represents the results of name lookup. + /// + /// An instance of the LookupResult class captures the results of a + /// single name lookup, which can return no result (nothing found), + /// a single declaration, a set of overloaded functions, or an + /// ambiguity. Use the getKind() method to determine which of these + /// results occurred for a given lookup. + /// + /// Any non-ambiguous lookup can be converted into a single + /// (possibly NULL) @c Decl* via a conversion function or the + /// getAsDecl() method. This conversion permits the common-case + /// usage in C and Objective-C where name lookup will always return + /// a single declaration. + class LookupResult { + /// The kind of entity that is actually stored within the + /// LookupResult object. + mutable enum { + /// First is a single declaration (a Decl*), which may be NULL. + SingleDecl, + /// [First, Last) is an iterator range represented as opaque + /// pointers used to reconstruct IdentifierResolver::iterators. + OverloadedDeclFromIdResolver, + /// [First, Last) is an iterator range represented as opaque + /// pointers used to reconstruct DeclContext::lookup_iterators. + OverloadedDeclFromDeclContext, + /// FIXME: Cope with ambiguous name lookup. + AmbiguousLookup + } StoredKind; + + /// The first lookup result, whose contents depend on the kind of + /// lookup result. This may be a Decl* (if StoredKind == + /// SingleDecl), the opaque pointer from an + /// IdentifierResolver::iterator (if StoredKind == + /// OverloadedDeclFromIdResolver), or a + /// DeclContext::lookup_iterator (if StoredKind == + /// OverloadedDeclFromDeclContext). + mutable uintptr_t First; + + /// The last lookup result, whose contents depend on the kind of + /// lookup result. This may be unused (if StoredKind == + /// SingleDecl) or it may have the same type as First (for + /// overloaded function declarations). + mutable uintptr_t Last; + + /// Context - The context in which we will build any + /// OverloadedFunctionDecl nodes needed by the conversion to + /// Decl*. + ASTContext *Context; + + public: + /// @brief The kind of entity found by name lookup. + enum LookupKind { + /// @brief No entity found met the criteria. + NotFound = 0, + /// @brief Name lookup found a single declaration that met the + /// criteria. + Found, + /// @brief Name lookup found a set of overloaded functions that + /// met the criteria. + FoundOverloaded, + /// @brief Name lookup resulted in an ambiguity, e.g., because + /// the name was found in two different base classes. + Ambiguous + }; + + LookupResult(ASTContext &Context, Decl *D) + : StoredKind(SingleDecl), First(reinterpret_cast(D)), + Last(0), Context(&Context) { } + + LookupResult(ASTContext &Context, + IdentifierResolver::iterator F, IdentifierResolver::iterator L) + : StoredKind(OverloadedDeclFromIdResolver), + First(F.getAsOpaqueValue()), Last(L.getAsOpaqueValue()), + Context(&Context) { } + + LookupResult(ASTContext &Context, + DeclContext::lookup_iterator F, DeclContext::lookup_iterator L) + : StoredKind(OverloadedDeclFromDeclContext), + First(reinterpret_cast(F)), + Last(reinterpret_cast(L)), + Context(&Context) { } + + LookupKind getKind() const; + + /// @brief Determine whether name look found something. + operator bool() const { return getKind() != NotFound; } + + /// @brief Allows conversion of a lookup result into a + /// declaration, with the same behavior as getAsDecl. + operator Decl*() const { return getAsDecl(); } + + Decl* getAsDecl() 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 LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, + const DeclContext *LookupCtx = 0, + bool enableLazyBuiltinCreation = true, + bool LookInParent = true, + bool NamespaceNameOnly = false); + //@} + ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id); ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S); ScopedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S); + + // More parsing and symbol table subroutines. + // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Decl *D, const Declarator &PD); void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index dcb2a5fba551..0c0fa35a5e76 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -19,54 +19,6 @@ using namespace clang; -namespace { - Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx, - DeclarationName Name, bool &IdIsUndeclared, - ASTContext &Context) { - if (LookupCtx && !LookInParentCtx) { - IdIsUndeclared = true; - DeclContext::lookup_const_iterator I, E; - for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) { - IdIsUndeclared = false; - if (((*I)->isInIdentifierNamespace(Decl::IDNS_Tag)) || - isa(*I)) - return *I; - } - - return 0; - } - - // FIXME: Decouple this from the IdentifierResolver so that we can - // deal with lookups into the semantic parent contexts that aren't - // lexical parent contexts. - - IdentifierResolver::iterator - I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx), - E = IdentifierResolver::end(); - - if (I == E) { - IdIsUndeclared = true; - return 0; - } - IdIsUndeclared = false; - - // C++ 3.4.3p1 : - // During the lookup for a name preceding the :: scope resolution operator, - // object, function, and enumerator names are ignored. If the name found is - // not a class-name or namespace-name, the program is ill-formed. - - for (; I != E; ++I) { - if (isa(*I)) { - break; - } - if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag)) - break; - } - - return (I != E ? *I : 0); - } -} // anonymous namespace - /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the /// global scope ('::'). Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, @@ -85,16 +37,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II) { - DeclContext *DC = static_cast(SS.getScopeRep()); - Decl *SD; - bool IdIsUndeclared; - - if (DC) - SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared, - Context); - else - SD = LookupNestedName(CurContext, true/*LookInParent*/, &II, - IdIsUndeclared, Context); + Decl *SD = LookupParsedName(S, SS, &II, + LookupCriteria(LookupCriteria::NestedNameSpecifier, + /*RedeclarationOnly=*/false, + /*CPlusPlus=*/true)); if (SD) { if (TypedefDecl *TD = dyn_cast(SD)) { @@ -104,19 +50,29 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, return cast(SD); } + // FIXME: C++0x scoped enums + // Fall through to produce an error: we found something that isn't // a class or a namespace. } + // If we didn't find anything during our lookup, try again with + // 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)); unsigned DiagID; - if (!IdIsUndeclared) + if (SD) DiagID = diag::err_expected_class_or_namespace; - else if (DC) + else if (SS.isSet()) DiagID = diag::err_typecheck_no_member; else DiagID = diag::err_undeclared_var_use; - if (DC) + if (SS.isSet()) Diag(IdLoc, DiagID) << &II << SS.getRange(); else Diag(IdLoc, DiagID) << &II; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8ba6f31da80d..5119388dbc71 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -205,52 +205,6 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { return dyn_cast_or_null(IDecl); } -/// 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 -/// 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 -/// ambiguity and overloaded functions without needing to create a -/// Decl node. -template -static Decl * -MaybeConstructOverloadSet(ASTContext &Context, - DeclIterator I, DeclIterator IEnd) { - assert(I != IEnd && "Iterator range cannot be empty"); - assert(!isa(*I) && - "Cannot have an overloaded function"); - - if (isa(*I)) { - // 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 && isa(*Last); ++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, - cast(*I)->getDeclContext(), - (*I)->getDeclName()); - Ovl->addOverload(cast(*I)); - } - Ovl->addOverload(cast(*Last)); - } - - // If we had more than one function, we built an overload - // set. Return it. - if (Ovl) - return Ovl; - } - - return *I; -} - /// getNonFieldDeclScope - Retrieves the innermost scope, starting /// from S, where a non-field would be declared. This routine copes /// with the difference between C and C++ scoping rules in structs and @@ -288,150 +242,37 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { /// 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.' -Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, - const DeclContext *LookupCtx, - bool enableLazyBuiltinCreation, - bool LookInParent, - bool NamespaceNameOnly) { - if (!Name) return 0; - unsigned NS = NSI; +/// +/// Note: The use of this routine is deprecated. Please use +/// LookupName, LookupQualifiedName, or LookupParsedName instead. +Sema::LookupResult +Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, + const DeclContext *LookupCtx, + bool enableLazyBuiltinCreation, + bool LookInParent, + bool NamespaceNameOnly) { + LookupCriteria::NameKind Kind; + if (NSI == Decl::IDNS_Ordinary) { + if (NamespaceNameOnly) + Kind = LookupCriteria::Namespace; + else + Kind = LookupCriteria::Ordinary; + } else if (NSI == Decl::IDNS_Tag) + Kind = LookupCriteria::Tag; + else if (NSI == Decl::IDNS_Member) + Kind = LookupCriteria::Member; + else + assert(false && "Unable to grok LookupDecl NSI argument"); - // In C++, ordinary and member lookup will always find all - // kinds of names. - if (getLangOptions().CPlusPlus && - (NS & (Decl::IDNS_Ordinary | Decl::IDNS_Member))) - NS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Ordinary; + if (LookupCtx) + return LookupQualifiedName(const_cast(LookupCtx), Name, + LookupCriteria(Kind, !LookInParent, + getLangOptions().CPlusPlus)); - if (LookupCtx == 0 && !getLangOptions().CPlusPlus) { - // Unqualified name lookup in C/Objective-C is purely lexical, so - // search in the declarations attached to the name. - assert(!LookupCtx && "Can't perform qualified name lookup here"); - assert(!NamespaceNameOnly && "Can't perform namespace name lookup here"); - - // 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) - if ((*I)->isInIdentifierNamespace(NS)) - return *I; - } else if (LookupCtx) { - // If we're performing qualified name lookup (e.g., lookup into a - // struct), find fields as part of ordinary name lookup. - if (NS & Decl::IDNS_Ordinary) - NS |= Decl::IDNS_Member; - - // Perform qualified name lookup into the LookupCtx. - // FIXME: Will need to look into base classes and such. - DeclContext::lookup_const_iterator I, E; - for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) - if ((*I)->isInIdentifierNamespace(NS)) { - // Ignore non-namespace names if we're only looking for namespaces. - if (NamespaceNameOnly && !isa(*I)) continue; - - return MaybeConstructOverloadSet(Context, I, E); - } - } else { - // Name lookup for ordinary names and tag names 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. - IdentifierResolver::iterator - I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/), - IEnd = IdResolver.end(); - for (; S; S = S->getParent()) { - // Check whether the IdResolver has anything in this scope. - // FIXME: The isDeclScope check could be expensive. Can we do better? - for (; I != IEnd && S->isDeclScope(*I); ++I) { - if ((*I)->isInIdentifierNamespace(NS)) { - // Ignore non-namespace names if we're only looking for namespaces. - if (NamespaceNameOnly && !isa(*I)) - continue; - - // 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 (!(*LastI)->isInIdentifierNamespace(NS) || - !S->isDeclScope(*LastI)) - break; - } - return MaybeConstructOverloadSet(Context, I, LastI); - } - } - - // If there is an entity associated with this scope, it's a - // DeclContext. We might need to perform qualified lookup into - // it. - DeclContext *Ctx = static_cast(S->getEntity()); - while (Ctx && Ctx->isFunctionOrMethod()) - Ctx = Ctx->getParent(); - while (Ctx && (Ctx->isNamespace() || Ctx->isRecord())) { - // Look for declarations of this name in this scope. - DeclContext::lookup_const_iterator I, E; - for (llvm::tie(I, E) = Ctx->lookup(Name); I != E; ++I) { - // FIXME: Cache this result in the IdResolver - if ((*I)->isInIdentifierNamespace(NS)) { - if (NamespaceNameOnly && !isa(*I)) - continue; - return MaybeConstructOverloadSet(Context, I, E); - } - } - - if (!LookInParent && !Ctx->isTransparentContext()) - return 0; - - Ctx = Ctx->getParent(); - } - } - } - - // 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 (NS & Decl::IDNS_Ordinary) { - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (enableLazyBuiltinCreation && II && - (LookupCtx == 0 || isa(LookupCtx))) { - // If this is a builtin on this (or all) targets, create the decl. - if (unsigned BuiltinID = II->getBuiltinID()) - return 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 IDI->second; - ObjCAliasTy::iterator I = ObjCAliasDecls.find(II); - if (I != ObjCAliasDecls.end()) - return I->second->getClassInterface(); - } - } - return 0; + // Unqualified lookup + return LookupName(S, Name, + LookupCriteria(Kind, !LookInParent, + getLangOptions().CPlusPlus)); } void Sema::InitBuiltinVaListType() { @@ -489,7 +330,7 @@ NamespaceDecl *Sema::GetStdNamespace() { if (!StdNamespace) { IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std"); DeclContext *Global = Context.getTranslationUnitDecl(); - Decl *Std = LookupDecl(StdIdent, Decl::IDNS_Tag | Decl::IDNS_Ordinary, + Decl *Std = LookupDecl(StdIdent, Decl::IDNS_Ordinary, 0, Global, /*enableLazyBuiltinCreation=*/false); StdNamespace = dyn_cast_or_null(Std); } @@ -2944,7 +2785,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, DC = static_cast(SS.getScopeRep()); // Look-up name inside 'foo::'. - PrevDecl = dyn_cast_or_null(LookupDecl(Name, Decl::IDNS_Tag,S,DC)); + PrevDecl = dyn_cast_or_null(LookupDecl(Name, Decl::IDNS_Tag,S,DC) + .getAsDecl()); // A tag 'foo::bar' must already exist. if (PrevDecl == 0) { @@ -2956,7 +2798,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, // If this is a named struct, check to see if there was a previous forward // declaration or definition. // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up. - PrevDecl = dyn_cast_or_null(LookupDecl(Name, Decl::IDNS_Tag,S)); + PrevDecl = dyn_cast_or_null(LookupDecl(Name, Decl::IDNS_Tag,S) + .getAsDecl()); if (!getLangOptions().CPlusPlus && TK != TK_Reference) { // FIXME: This makes sure that we ignore the contexts associated diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 20f05228acca..33a31c7500df 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1393,7 +1393,7 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // in that declarative region, it is treated as an original-namespace-name. Decl *PrevDecl = - LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0, + LookupDecl(II, Decl::IDNS_Ordinary, DeclRegionScope, 0, /*enableLazyBuiltinCreation=*/false, /*LookupInParent=*/false); @@ -1454,10 +1454,18 @@ Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S, assert(IdentLoc.isValid() && "Invalid NamespceName location."); // FIXME: This still requires lot more checks, and AST support. - // Lookup namespace name. - DeclContext *DC = static_cast(SS.getScopeRep()); - if (Decl *NS = LookupNamespaceName(NamespcName, S, DC)) { + // 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); + + if (NS) { assert(isa(NS) && "expected namespace decl"); } else { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f802f5126c43..d478df0bc3bd 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3843,7 +3843,7 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, FieldDecl *MemberDecl = dyn_cast_or_null(LookupDecl(OC.U.IdentInfo, Decl::IDNS_Ordinary, - S, RD, false, false)); + S, RD, false, false).getAsDecl()); if (!MemberDecl) return Diag(BuiltinLoc, diag::err_typecheck_no_member) << OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 51cdc5c378c5..0a42de06cad4 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -61,8 +61,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return Diag(OpLoc, diag::err_need_header_before_typeid); IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); - Decl *TypeInfoDecl = LookupDecl(TypeInfoII, - Decl::IDNS_Tag | Decl::IDNS_Ordinary, + Decl *TypeInfoDecl = LookupDecl(TypeInfoII, Decl::IDNS_Tag, 0, StdNs, /*createBuiltins=*/false); RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null(TypeInfoDecl); if (!TypeInfoRecordDecl) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp new file mode 100644 index 000000000000..a9ec3f2faf61 --- /dev/null +++ b/clang/lib/Sema/SemaLookup.cpp @@ -0,0 +1,422 @@ +//===--------------------- SemaLookup.cpp - Name Lookup ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements name lookup for C, C++, Objective-C, and +// Objective-C++. +// +//===----------------------------------------------------------------------===// +#include "Sema.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Parse/DeclSpec.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/STLExtras.h" + +using namespace clang; + +/// 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 +/// 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 +/// ambiguity and overloaded functions without needing to create a +/// Decl node. +template +static Decl * +MaybeConstructOverloadSet(ASTContext &Context, + DeclIterator I, DeclIterator IEnd) { + assert(I != IEnd && "Iterator range cannot be empty"); + assert(!isa(*I) && + "Cannot have an overloaded function"); + + if (isa(*I)) { + // 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 && isa(*Last); ++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, + cast(*I)->getDeclContext(), + (*I)->getDeclName()); + Ovl->addOverload(cast(*I)); + } + Ovl->addOverload(cast(*Last)); + } + + // If we had more than one function, we built an overload + // set. Return it. + if (Ovl) + return Ovl; + } + + 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 Determine the result of name lookup. +Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const { + switch (StoredKind) { + case SingleDecl: + return (reinterpret_cast(First) != 0)? Found : NotFound; + + case OverloadedDeclFromIdResolver: + case OverloadedDeclFromDeclContext: + return FoundOverloaded; + + case AmbiguousLookup: + return Ambiguous; + } + + // We can't get here, but GCC complains nonetheless. + return Ambiguous; +} + +/// @brief Converts the result of name lookup into a single (possible +/// NULL) pointer to a declaration. +/// +/// The resulting declaration will either be the declaration we found +/// (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. +/// +/// 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. +Decl *Sema::LookupResult::getAsDecl() const { + switch (StoredKind) { + case SingleDecl: + return reinterpret_cast(First); + + case OverloadedDeclFromIdResolver: + return MaybeConstructOverloadSet(*Context, + IdentifierResolver::iterator::getFromOpaqueValue(First), + IdentifierResolver::iterator::getFromOpaqueValue(Last)); + + case OverloadedDeclFromDeclContext: + return MaybeConstructOverloadSet(*Context, + reinterpret_cast(First), + reinterpret_cast(Last)); + + case AmbiguousLookup: + assert(false && + "Name lookup returned an ambiguity that could not be handled"); + break; + } + + return 0; +} + +/// @brief Perform unqualified name lookup starting from a given +/// scope. +/// +/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is +/// used to find names within the current scope. For example, 'x' in +/// @code +/// int x; +/// int f() { +/// return x; // unqualified name look finds 'x' in the global scope +/// } +/// @endcode +/// +/// Different lookup criteria can find different names. For example, a +/// particular scope can have both a struct and a function of the same +/// name, and each can be found by certain lookup criteria. For more +/// information about lookup criteria, see the documentation for the +/// class LookupCriteria. +/// +/// @param S The scope from which unqualified name lookup will +/// begin. If the lookup criteria permits, name lookup may also search +/// in the parent scopes. +/// +/// @param Name The name of the entity that we are searching for. +/// +/// @param Criteria The criteria that this routine will use to +/// determine which names are visible and which names will be +/// found. Note that name lookup will find a name that is visible by +/// the given criteria, but the entity itself may not be semantically +/// correct or even the kind of entity expected based on the +/// lookup. For example, searching for a nested-name-specifier name +/// might result in an EnumDecl, which is visible but is not permitted +/// as a nested-name-specifier in C++03. +/// +/// @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, LookupCriteria Criteria) { + if (!Name) return LookupResult(Context, 0); + + if (!getLangOptions().CPlusPlus) { + // 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, !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)) + return LookupResult(Context, *I); + } else { + // 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(); + 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)) { + // 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(*LastI)) + break; + } + return LookupResult(Context, I, LastI); + } + } + + // If there is an entity associated with this scope, it's a + // DeclContext. We might need to perform qualified lookup into + // it. + // FIXME: We're performing redundant lookups here, where the + // scope stack mirrors the semantic nested of classes and + // namespaces. We can save some work by checking the lexical + // scope against the semantic scope and avoiding any lookups + // when they are the same. + // 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. However, we cannot perform this optimization when the + // lexical and semantic scopes don't line up, e.g., in an + // out-of-line member definition. + DeclContext *Ctx = static_cast(S->getEntity()); + while (Ctx && Ctx->isFunctionOrMethod()) + 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)) + return Result; + + if (Criteria.RedeclarationOnly && !Ctx->isTransparentContext()) + return LookupResult(Context, 0); + + Ctx = Ctx->getParent(); + } + } + } + + // 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) { + IdentifierInfo *II = Name.getAsIdentifierInfo(); + if (Criteria.AllowLazyBuiltinCreation && II) { + // If this is a builtin on this (or all) targets, create the decl. + if (unsigned BuiltinID = II->getBuiltinID()) + return LookupResult(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(Context, IDI->second); + ObjCAliasTy::iterator I = ObjCAliasDecls.find(II); + if (I != ObjCAliasDecls.end()) + return LookupResult(Context, I->second->getClassInterface()); + } + } + return LookupResult(Context, 0); +} + +/// @brief Perform qualified name lookup into a given context. +/// +/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find +/// names when the context of those names is explicit specified, e.g., +/// "std::vector" or "x->member". +/// +/// Different lookup criteria can find different names. For example, a +/// particular scope can have both a struct and a function of the same +/// name, and each can be found by certain lookup criteria. For more +/// information about lookup criteria, see the documentation for the +/// class LookupCriteria. +/// +/// @param LookupCtx The context in which qualified name lookup will +/// search. If the lookup criteria permits, name lookup may also search +/// in the parent contexts or (for C++ classes) base classes. +/// +/// @param Name The name of the entity that we are searching for. +/// +/// @param Criteria The criteria that this routine will use to +/// determine which names are visible and which names will be +/// found. Note that name lookup will find a name that is visible by +/// the given criteria, but the entity itself may not be semantically +/// correct or even the kind of entity expected based on the +/// lookup. For example, searching for a nested-name-specifier name +/// might result in an EnumDecl, which is visible but is not permitted +/// as a nested-name-specifier in C++03. +/// +/// @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, + LookupCriteria Criteria) { + assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); + + if (!Name) return LookupResult(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; + + // Perform qualified name lookup into the LookupCtx. + // FIXME: Will need to look into base classes and such. + DeclContext::lookup_iterator I, E; + for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) + if (Criteria.isLookupResult(*I)) + return LookupResult(Context, I, E); + + return LookupResult(Context, 0); +} + +/// @brief Performs name lookup for a name that was parsed in the +/// source code, and may contain a C++ scope specifier. +/// +/// This routine is a convenience routine meant to be called from +/// contexts that receive a name and an optional C++ scope specifier +/// (e.g., "N::M::x"). It will then perform either qualified or +/// unqualified name lookup (with LookupQualifiedName or LookupName, +/// respectively) on the given name and return those results. +/// +/// @param S The scope from which unqualified name lookup will +/// begin. +/// +/// @param SS An optional C++ scope-specified, e.g., "::N::M". +/// +/// @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); + + return LookupName(S, Name, Criteria); +} + + diff --git a/clang/test/Parser/cxx-using-directive.cpp b/clang/test/Parser/cxx-using-directive.cpp index 73f1e002c2dc..2ee014e54f4f 100644 --- a/clang/test/Parser/cxx-using-directive.cpp +++ b/clang/test/Parser/cxx-using-directive.cpp @@ -31,3 +31,10 @@ using namespace A ; // expected-error{{expected namespace name}} using namespace ::A // expected-error{{expected namespace name}} B ; // expected-error{{expected ';' after namespace name}} +void test_nslookup() { + int B; + class C; + using namespace B; + using namespace C; +} + diff --git a/clang/test/SemaCXX/qualified-id-lookup.cpp b/clang/test/SemaCXX/qualified-id-lookup.cpp index cbc197ddc797..34c06140d893 100644 --- a/clang/test/SemaCXX/qualified-id-lookup.cpp +++ b/clang/test/SemaCXX/qualified-id-lookup.cpp @@ -49,7 +49,7 @@ void N::f1::foo(int) { } namespace N { float& f1(int x) { N::f1::type& i1 = x; - // FIXME: currently fails f1::type& i2 = x; + f1::type& i2 = x; } struct f2 {