[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
Daniel Dunbar
daniel at zuster.org
Fri Jan 16 15:16:34 PST 2009
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?
- Daniel
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