[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