[cfe-commits] r62245 - in /cfe/trunk: lib/Sema/CMakeLists.txt lib/Sema/IdentifierResolver.h lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaL
Douglas Gregor
dgregor at apple.com
Fri Jan 16 15:33:58 PST 2009
On Jan 16, 2009, at 3:16 PM, Daniel Dunbar wrote:
> Sorry to be incredibly boring, but my tester is pointing at this for a
> 2.13% regression in -fsyntax-only on Cocoa.h. Necessary or avoidable?
Darn! Steve and I are chatting about this... there are a few micro-
optimizations we can do, and (at some cost to our sanity) we could
make LookupResult a POD.
- Doug
> On Wed, Jan 14, 2009 at 2:20 PM, Douglas Gregor <dgregor at apple.com>
> wrote:
>> Author: dgregor
>> Date: Wed Jan 14 16:20:51 2009
>> New Revision: 62245
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=62245&view=rev
>> Log:
>> Refactor name lookup.
>>
>> This change refactors and cleans up our handling of name lookup with
>> LookupDecl. There are several aspects to this refactoring:
>>
>> - The criteria for name lookup is now encapsulated into the class
>> LookupCriteria, which replaces the hideous set of boolean values
>> that LookupDecl currently has.
>>
>> - The results of name lookup are returned in a new class
>> LookupResult, which can lazily build OverloadedFunctionDecls for
>> overloaded function sets (and, eventually, eliminate the need to
>> allocate member for OverloadedFunctionDecls) and contains a
>> placeholder for handling ambiguous name lookup (for C++).
>>
>> - The primary entry points for name lookup are now LookupName (for
>> unqualified name lookup) and LookupQualifiedName (for qualified
>> name lookup). There is also a convenience function
>> LookupParsedName that handles qualified/unqualified name lookup
>> when given a scope specifier. Together, these routines are meant
>> to gradually replace the kludgy LookupDecl, but this won't happen
>> until after we have base class lookup (which forces us to cope
>> with ambiguities).
>>
>> - Documented the heck out of name lookup. Experimenting a little
>> with using Doxygen's member groups to make some sense of the Sema
>> class. Feedback welcome!
>>
>> - Fixes some lingering issues with name lookup for
>> nested-name-specifiers, which now goes through
>> LookupName/LookupQualifiedName.
>>
>>
>> Added:
>> cfe/trunk/lib/Sema/SemaLookup.cpp
>> Modified:
>> cfe/trunk/lib/Sema/CMakeLists.txt
>> cfe/trunk/lib/Sema/IdentifierResolver.h
>> cfe/trunk/lib/Sema/Sema.h
>> cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
>> cfe/trunk/lib/Sema/SemaDecl.cpp
>> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> cfe/trunk/lib/Sema/SemaExpr.cpp
>> cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> cfe/trunk/test/Parser/cxx-using-directive.cpp
>> cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
>>
>> Modified: cfe/trunk/lib/Sema/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/CMakeLists.txt (original)
>> +++ cfe/trunk/lib/Sema/CMakeLists.txt Wed Jan 14 16:20:51 2009
>> @@ -15,6 +15,7 @@
>> SemaExprObjC.cpp
>> SemaInherit.cpp
>> SemaInit.cpp
>> + SemaLookup.cpp
>> SemaNamedCast.cpp
>> SemaOverload.cpp
>> SemaStmt.cpp
>>
>> Modified: cfe/trunk/lib/Sema/IdentifierResolver.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.h?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/IdentifierResolver.h (original)
>> +++ cfe/trunk/lib/Sema/IdentifierResolver.h Wed Jan 14 16:20:51 2009
>> @@ -181,6 +181,14 @@
>> 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();
>> };
>>
>> Modified: cfe/trunk/lib/Sema/Sema.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/Sema.h (original)
>> +++ cfe/trunk/lib/Sema/Sema.h Wed Jan 14 16:20:51 2009
>> @@ -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 @@
>>
>> 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);
>> -
>> - 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);
>> - }
>> + /// \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.
>> + //@{
>> +
>> + /// @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<uintptr_t>
>> (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<uintptr_t>(F)),
>> + Last(reinterpret_cast<uintptr_t>(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);
>>
>> Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Wed Jan 14 16:20:51 2009
>> @@ -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<TypedefDecl>(*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<TypedefDecl>(*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 @@
>> SourceLocation
>> IdLoc,
>> SourceLocation
>> CCLoc,
>> IdentifierInfo
>> &II) {
>> - DeclContext *DC = static_cast<DeclContext*>(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<TypedefDecl>(SD)) {
>> @@ -104,19 +50,29 @@
>> return cast<DeclContext>(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;
>>
>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jan 14 16:20:51 2009
>> @@ -205,52 +205,6 @@
>> return dyn_cast_or_null<ObjCInterfaceDecl>(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<typename DeclIterator>
>> -static Decl *
>> -MaybeConstructOverloadSet(ASTContext &Context,
>> - DeclIterator I, DeclIterator IEnd) {
>> - assert(I != IEnd && "Iterator range cannot be empty");
>> - assert(!isa<OverloadedFunctionDecl>(*I) &&
>> - "Cannot have an overloaded function");
>> -
>> - if (isa<FunctionDecl>(*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<FunctionDecl>(*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<ScopedDecl>(*I)-
>> >getDeclContext(),
>> - (*I)->getDeclName());
>> - Ovl->addOverload(cast<FunctionDecl>(*I));
>> - }
>> - Ovl->addOverload(cast<FunctionDecl>(*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 @@
>> /// 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;
>> -
>> - // 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 == 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<RecordDecl>(SearchCtx) || isa<EnumDecl>(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<NamespaceDecl>(*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<NamespaceDecl>(*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<DeclContext *>(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<NamespaceDecl>(*I))
>> - continue;
>> - return MaybeConstructOverloadSet(Context, I, E);
>> - }
>> - }
>> -
>> - if (!LookInParent && !Ctx->isTransparentContext())
>> - return 0;
>> -
>> - Ctx = Ctx->getParent();
>> - }
>> - }
>> - }
>> +///
>> +/// 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");
>>
>> - // 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<TranslationUnitDecl>(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;
>> + if (LookupCtx)
>> + return LookupQualifiedName(const_cast<DeclContext *>
>> (LookupCtx), Name,
>> + LookupCriteria(Kind, !LookInParent,
>> + getLangOptions
>> ().CPlusPlus));
>> +
>> + // Unqualified lookup
>> + return LookupName(S, Name,
>> + LookupCriteria(Kind, !LookInParent,
>> + getLangOptions().CPlusPlus));
>> }
>>
>> void Sema::InitBuiltinVaListType() {
>> @@ -489,7 +330,7 @@
>> 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<NamespaceDecl>(Std);
>> }
>> @@ -2944,7 +2785,8 @@
>>
>> DC = static_cast<DeclContext*>(SS.getScopeRep());
>> // Look-up name inside 'foo::'.
>> - PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name,
>> Decl::IDNS_Tag,S,DC));
>> + PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name,
>> Decl::IDNS_Tag,S,DC)
>> + .getAsDecl());
>>
>> // A tag 'foo::bar' must already exist.
>> if (PrevDecl == 0) {
>> @@ -2956,7 +2798,8 @@
>> // 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<ScopedDecl>(LookupDecl(Name,
>> Decl::IDNS_Tag,S));
>> + PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name,
>> Decl::IDNS_Tag,S)
>> + .getAsDecl());
>>
>> if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
>> // FIXME: This makes sure that we ignore the contexts associated
>>
>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jan 14 16:20:51 2009
>> @@ -1393,7 +1393,7 @@
>> // 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 @@
>> assert(IdentLoc.isValid() && "Invalid NamespceName location.");
>>
>> // FIXME: This still requires lot more checks, and AST support.
>> +
>> // Lookup namespace name.
>> - DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());
>> + LookupCriteria Criteria(LookupCriteria::Namespace, /
>> *RedeclarationOnly=*/false,
>> + /*CPlusPlus=*/true);
>> + Decl *NS = 0;
>> + if (SS.isSet())
>> + NS = LookupQualifiedName(static_cast<DeclContext*>
>> (SS.getScopeRep()),
>> + NamespcName, Criteria);
>> + else
>> + NS = LookupName(S, NamespcName, Criteria);
>>
>> - if (Decl *NS = LookupNamespaceName(NamespcName, S, DC)) {
>> + if (NS) {
>> assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
>> } else {
>> Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange
>> ();
>>
>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jan 14 16:20:51 2009
>> @@ -3843,7 +3843,7 @@
>> FieldDecl *MemberDecl
>> = dyn_cast_or_null<FieldDecl>(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);
>>
>> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Jan 14 16:20:51 2009
>> @@ -61,8 +61,7 @@
>> 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<RecordDecl>
>> (TypeInfoDecl);
>> if (!TypeInfoRecordDecl)
>>
>> Added: cfe/trunk/lib/Sema/SemaLookup.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=62245&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/lib/Sema/SemaLookup.cpp (added)
>> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Jan 14 16:20:51 2009
>> @@ -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<typename DeclIterator>
>> +static Decl *
>> +MaybeConstructOverloadSet(ASTContext &Context,
>> + DeclIterator I, DeclIterator IEnd) {
>> + assert(I != IEnd && "Iterator range cannot be empty");
>> + assert(!isa<OverloadedFunctionDecl>(*I) &&
>> + "Cannot have an overloaded function");
>> +
>> + if (isa<FunctionDecl>(*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<FunctionDecl>(*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<ScopedDecl>(*I)-
>> >getDeclContext(),
>> + (*I)->getDeclName());
>> + Ovl->addOverload(cast<FunctionDecl>(*I));
>> + }
>> + Ovl->addOverload(cast<FunctionDecl>(*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<TypedefDecl>(D) || D->isInIdentifierNamespace
>> (Decl::IDNS_Tag);
>> +
>> + case Namespace:
>> + return isa<NamespaceDecl>(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<Decl *>(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<Decl *>(First);
>> +
>> + case OverloadedDeclFromIdResolver:
>> + return MaybeConstructOverloadSet(*Context,
>> +
>> IdentifierResolver::iterator::getFromOpaqueValue(First),
>> +
>> IdentifierResolver::iterator::getFromOpaqueValue(Last));
>> +
>> + case OverloadedDeclFromDeclContext:
>> + return MaybeConstructOverloadSet(*Context,
>> +
>> reinterpret_cast<DeclContext::lookup_iterator>(First),
>> +
>> reinterpret_cast<DeclContext::lookup_iterator>(Last));
>> +
>> + case 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<RecordDecl>(SearchCtx) || isa<EnumDecl>(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<DeclContext *>(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<DeclContext *>
>> (SS.getScopeRep()),
>> + Name, Criteria);
>> +
>> + return LookupName(S, Name, Criteria);
>> +}
>> +
>> +
>>
>> Modified: cfe/trunk/test/Parser/cxx-using-directive.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-using-directive.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/test/Parser/cxx-using-directive.cpp (original)
>> +++ cfe/trunk/test/Parser/cxx-using-directive.cpp Wed Jan 14
>> 16:20:51 2009
>> @@ -31,3 +31,10 @@
>> 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;
>> +}
>> +
>>
>> Modified: cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp?rev=62245&r1=62244&r2=62245&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp Wed Jan 14
>> 16:20:51 2009
>> @@ -49,7 +49,7 @@
>> namespace N {
>> float& f1(int x) {
>> N::f1::type& i1 = x;
>> - // FIXME: currently fails f1::type& i2 = x;
>> + f1::type& i2 = x;
>> }
>>
>> struct f2 {
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
More information about the cfe-commits
mailing list