Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.

Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.

Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.

All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63354 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 4e9d085..781d89a 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -225,14 +225,9 @@
   return toIdDeclInfo(Ptr)->RemoveDecl(D);
 }
 
-/// begin - Returns an iterator for decls with name 'Name', starting at
-/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
-/// decls of parent declaration contexts too.
+/// begin - Returns an iterator for decls with name 'Name'.
 IdentifierResolver::iterator
-IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx,
-                          bool LookInParentCtx) {
-  assert(Ctx && "null param passed");
-
+IdentifierResolver::begin(DeclarationName Name) {
   void *Ptr = Name.getFETokenInfo<void>();
   if (!Ptr) return end();
 
@@ -245,26 +240,11 @@
 
   IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
   if (I != IDI->decls_begin())
-    return iterator(I-1, LookInParentCtx);
+    return iterator(I-1);
   else // No decls found.
     return end();
 }
 
-/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
-void IdentifierResolver::iterator::PreIncIter() {
-  NamedDecl *D = **this;
-  void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
-  assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
-  IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
-
-  BaseIter I = getIterator();
-  if (I != Info->decls_begin())
-    *this = iterator(I-1, LookInParentCtx());
-  else // No more decls.
-    *this = end();
-}
-
-
 //===----------------------------------------------------------------------===//
 // IdDeclInfoMap Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h
index a44323e..50b894a 100644
--- a/lib/Sema/IdentifierResolver.h
+++ b/lib/Sema/IdentifierResolver.h
@@ -136,19 +136,12 @@
     }
     /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
     /// contexts depending on 'LookInParentCtx'.
-    iterator(BaseIter I, bool LookInParentCtx) {
+    iterator(BaseIter I) {
       Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
-      assert((Ptr & 0x2) == 0 && "Invalid Ptr!");
-      if (LookInParentCtx) Ptr |= 0x2;
     }
 
     bool isIterator() const { return (Ptr & 0x1); }
 
-    bool LookInParentCtx() const {
-      assert(isIterator() && "Ptr not an iterator!");
-      return (Ptr & 0x2) != 0;
-    }
-
     BaseIter getIterator() const {
       assert(isIterator() && "Ptr not an iterator!");
       return reinterpret_cast<BaseIter>(Ptr & ~0x3);
@@ -176,29 +169,32 @@
     iterator& operator++() {
       if (!isIterator()) // common case.
         Ptr = 0;
-      else
-        PreIncIter();
+      else {
+        NamedDecl *D = **this;
+        void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+        assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
+        IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
+        
+        BaseIter I = getIterator();
+        if (I != Info->decls_begin())
+          *this = iterator(I-1);
+        else // No more decls.
+          *this = iterator();
+      }
       return *this;
     }
 
     uintptr_t getAsOpaqueValue() const { return Ptr; }
     
     static iterator getFromOpaqueValue(uintptr_t P) {
-      iterator Result(0);
+      iterator Result;
       Result.Ptr = P;
       return Result;
     }
-    
-  private:
-    void PreIncIter();
   };
 
-  /// begin - Returns an iterator for decls with the name 'Name', starting at
-  /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
-  /// decls of parent declaration contexts too.
-  /// Default for 'LookInParentCtx is true.
-  static iterator begin(DeclarationName Name, const DeclContext *Ctx,
-                        bool LookInParentCtx = true);
+  /// begin - Returns an iterator for decls with the name 'Name'.
+  static iterator begin(DeclarationName Name);
 
   /// end - Returns an iterator that has 'finished'.
   static iterator end() {
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index fe2b9de..6e3a552 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -559,7 +559,7 @@
   /// 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.
+  /// lookup criteria is specified via the LookupCriteria enumeration.
   ///
   /// The results of name lookup can vary based on the kind of name
   /// lookup performed, the current language, and the translation
@@ -571,65 +571,26 @@
   /// 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() 
-      : Kind(Ordinary), AllowLazyBuiltinCreation(true), 
-        RedeclarationOnly(false), IDNS(Decl::IDNS_Ordinary) { }
-
-    LookupCriteria(NameKind K, bool RedeclarationOnly, bool CPlusPlus);
-    
-    bool isLookupResult(Decl *D) const;
+  /// @brief Describes the kind of name lookup to perform.
+  enum LookupNameKind {
+    /// 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++.
+    LookupOrdinaryName = 0,
+    /// Tag name lookup, which finds the names of enums, classes,
+    /// structs, and unions.
+    LookupTagName,
+    /// Member name lookup, which finds the names of
+    /// class/struct/union members.
+    LookupMemberName,
+    /// 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).
+    LookupNestedNameSpecifierName,
+    /// Look up a namespace name within a C++ using directive or
+    /// namespace alias definition, ignoring non-namespace names (C++
+    /// [basic.lookup.udir]p1).
+    LookupNamespaceName
   };
 
   /// @brief Represents the results of name lookup.
@@ -775,18 +736,38 @@
     BasePaths *getBasePaths() 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 LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
-                          bool LookInParent = true);
-  LookupResult LookupDeclInContext(DeclarationName Name, unsigned NSI,
-                          const DeclContext *LookupCtx,
-                          bool LookInParent = true);
+  /// Determines whether D is a suitable lookup result according to the
+  /// lookup criteria.
+  bool isAcceptableLookupResult(Decl *D, LookupNameKind NameKind,
+                                unsigned IDNS) const {
+    switch (NameKind) {
+    case Sema::LookupOrdinaryName:
+    case Sema::LookupTagName:
+    case Sema::LookupMemberName:
+      return D->isInIdentifierNamespace(IDNS);
+      
+    case Sema::LookupNestedNameSpecifierName:
+      return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
+      
+    case Sema::LookupNamespaceName:
+      return isa<NamespaceDecl>(D);
+    }
+    
+    assert(false && 
+           "isNameAcceptableLookupResult always returns before this point");
+    return false;
+  }
 
+  LookupResult LookupName(Scope *S, DeclarationName Name, 
+                          LookupNameKind NameKind, 
+                          bool RedeclarationOnly = false);
+  LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
+                                   LookupNameKind NameKind, 
+                                   bool RedeclarationOnly = false);
+  LookupResult LookupParsedName(Scope *S, const CXXScopeSpec *SS, 
+                                DeclarationName Name,
+                                LookupNameKind NameKind, 
+                                bool RedeclarationOnly = false);
   bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
                                SourceLocation NameLoc, 
                                SourceRange LookupRange = SourceRange());
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index cf93571..c77325f 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -36,10 +36,7 @@
                                                     SourceLocation IdLoc,

                                                     SourceLocation CCLoc,

                                                     IdentifierInfo &II) {

-  Decl *SD = LookupParsedName(S, SS, &II,

-                              LookupCriteria(LookupCriteria::NestedNameSpecifier, 

-                                             /*RedeclarationOnly=*/false, 

-                                             /*CPlusPlus=*/true));

+  Decl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName);

 

   if (SD) {

     if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {

@@ -60,10 +57,7 @@
   // 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));

+    SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName);

   unsigned DiagID;

   if (SD)

     DiagID = diag::err_expected_class_or_namespace;

diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index cf71d39..ad6a719 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -32,18 +32,8 @@
 
 Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S,
                                 const CXXScopeSpec *SS) {
-  DeclContext *DC = 0;
-  
-  if (SS) {
-    if (SS->isInvalid())
-      return 0;
-    DC = static_cast<DeclContext*>(SS->getScopeRep());
-  }
   Decl *IIDecl = 0;
-  
-  LookupResult Result =  DC ? LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) :
-                              LookupDeclInScope(&II, Decl::IDNS_Ordinary, S);
-                 
+  LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, false);
   switch (Result.getKind()) {
     case LookupResult::NotFound:
     case LookupResult::FoundOverloaded:
@@ -139,8 +129,7 @@
       // We're pushing the tag into the current context, which might
       // require some reshuffling in the identifier resolver.
       IdentifierResolver::iterator
-        I = IdResolver.begin(TD->getDeclName(), CurContext, 
-                             false/*LookInParentCtx*/),
+        I = IdResolver.begin(TD->getDeclName()),
         IEnd = IdResolver.end();
       if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
         NamedDecl *PrevDecl = *I;
@@ -175,10 +164,8 @@
     // We are pushing the name of a function, which might be an
     // overloaded name.
     FunctionDecl *FD = cast<FunctionDecl>(D);
-    DeclContext *DC = FD->getDeclContext()->getLookupContext();
     IdentifierResolver::iterator Redecl
-      = std::find_if(IdResolver.begin(FD->getDeclName(), DC, 
-                                      false/*LookInParentCtx*/),
+      = std::find_if(IdResolver.begin(FD->getDeclName()),
                      IdResolver.end(),
                      std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
                                   FD));
@@ -218,7 +205,7 @@
 ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
   // The third "scope" argument is 0 since we aren't enabling lazy built-in
   // creation from this context.
-  Decl *IDecl = LookupDeclInScope(Id, Decl::IDNS_Ordinary, 0);
+  Decl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName);
   
   return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
 }
@@ -255,123 +242,12 @@
   return S;
 }
 
-/// LookupDeclInScope - Look up the inner-most declaration in the specified
-/// namespace. NamespaceNameOnly - during lookup only namespace names
-/// 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.'
-///
-/// Note: The use of this routine is deprecated. Please use
-/// LookupName, LookupQualifiedName, or LookupParsedName instead.
-Sema::LookupResult
-Sema::LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
-                        bool LookInParent) {
-  if (getLangOptions().CPlusPlus) {
-    LookupCriteria::NameKind Kind;
-    if (NSI == Decl::IDNS_Ordinary) {
-      Kind = LookupCriteria::Ordinary;
-    } else if (NSI == Decl::IDNS_Tag) 
-      Kind = LookupCriteria::Tag;
-    else {
-      assert(NSI == Decl::IDNS_Member &&"Unable to grok LookupDecl NSI argument");
-      Kind = LookupCriteria::Member;
-    }
-    // Unqualified lookup
-    return LookupName(S, Name, 
-                      LookupCriteria(Kind, !LookInParent,
-                                     getLangOptions().CPlusPlus));
-  }
-  // Fast path for C/ObjC.
-  
-  // Unqualified name lookup in C/Objective-C is purely lexical, so
-  // search in the declarations attached to the name.
-
-  // For the purposes of unqualified name lookup, structs and unions
-  // don't have scopes at all. For example:
-  //
-  //   struct X {
-  //     struct T { int i; } x;
-  //   };
-  //
-  //   void f() {
-  //     struct T t; // okay: T is defined lexically within X, but
-  //                 // semantically at global scope
-  //   };
-  //
-  // FIXME: Is there a better way to deal with this?
-  DeclContext *SearchCtx = CurContext;
-  while (isa<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) {
-    switch (NSI) {
-      case Decl::IDNS_Ordinary:
-      case Decl::IDNS_Tag:
-      case Decl::IDNS_Member:
-        if ((*I)->isInIdentifierNamespace(NSI))
-          return LookupResult::CreateLookupResult(Context, *I);
-        break;
-      default:
-        assert(0 && "Unable to grok LookupDecl NSI argument");
-    }
-  }
-  if (NSI == Decl::IDNS_Ordinary) {
-    IdentifierInfo *II = Name.getAsIdentifierInfo();
-    if (II) {
-      // If this is a builtin on this (or all) targets, create the decl.
-      if (unsigned BuiltinID = II->getBuiltinID())
-        return LookupResult::CreateLookupResult(Context,
-                            LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
-                                                S));
-    }
-    if (getLangOptions().ObjC1 && II) {
-      // @interface and @compatibility_alias introduce typedef-like names.
-      // Unlike typedef's, they can only be introduced at file-scope (and are 
-      // therefore not scoped decls). They can, however, be shadowed by
-      // other names in IDNS_Ordinary.
-      ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
-      if (IDI != ObjCInterfaceDecls.end())
-        return LookupResult::CreateLookupResult(Context, IDI->second);
-      ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
-      if (I != ObjCAliasDecls.end())
-        return LookupResult::CreateLookupResult(Context, 
-                                                I->second->getClassInterface());
-    }
-  }
-  return LookupResult::CreateLookupResult(Context, 0);
-}
-
-Sema::LookupResult
-Sema::LookupDeclInContext(DeclarationName Name, unsigned NSI,
-                          const DeclContext *LookupCtx,
-                          bool LookInParent) {
-  assert(LookupCtx && "LookupDeclInContext(): Missing DeclContext");
-  LookupCriteria::NameKind Kind;
-  if (NSI == Decl::IDNS_Ordinary) {
-    Kind = LookupCriteria::Ordinary;
-  } else if (NSI == Decl::IDNS_Tag) 
-    Kind = LookupCriteria::Tag;
-  else {
-    assert(NSI == Decl::IDNS_Member &&"Unable to grok LookupDecl NSI argument");
-    Kind = LookupCriteria::Member;
-  }
-  return LookupQualifiedName(const_cast<DeclContext *>(LookupCtx), Name, 
-                             LookupCriteria(Kind, !LookInParent,
-                                            getLangOptions().CPlusPlus));
-}
-
 void Sema::InitBuiltinVaListType() {
   if (!Context.getBuiltinVaListType().isNull())
     return;
   
   IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
-  Decl *VaDecl = LookupDeclInScope(VaIdent, Decl::IDNS_Ordinary, TUScope);
+  Decl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName);
   TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
   Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
 }
@@ -420,7 +296,7 @@
   if (!StdNamespace) {
     IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std");
     DeclContext *Global = Context.getTranslationUnitDecl();
-    Decl *Std = LookupDeclInContext(StdIdent, Decl::IDNS_Ordinary, Global);
+    Decl *Std = LookupQualifiedName(Global, StdIdent, LookupNamespaceName);
     StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
   }
   return StdNamespace;
@@ -689,10 +565,9 @@
   
   // FIXME: I don't think this will actually see all of the
   // redefinitions. Can't we check this property on-the-fly?
-  for (IdentifierResolver::iterator
-       I = IdResolver.begin(VD->getIdentifier(), 
-                            VD->getDeclContext(), false/*LookInParentCtx*/), 
-       E = IdResolver.end(); I != E; ++I) {
+  for (IdentifierResolver::iterator I = IdResolver.begin(VD->getIdentifier()), 
+                                    E = IdResolver.end(); 
+       I != E; ++I) {
     if (*I != VD && isDeclInScope(*I, VD->getDeclContext(), S)) {
       VarDecl *OldDecl = dyn_cast<VarDecl>(*I);
       
@@ -864,8 +739,8 @@
                                FEnd = AnonRecord->field_end();
        F != FEnd; ++F) {
     if ((*F)->getDeclName()) {
-      Decl *PrevDecl = LookupDeclInContext((*F)->getDeclName(), 
-                         Decl::IDNS_Ordinary, Owner, false);
+      Decl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(),
+                                           LookupOrdinaryName, true);
       if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
         // C++ [class.union]p2:
         //   The names of the members of an anonymous union shall be
@@ -1312,13 +1187,12 @@
   bool InvalidDecl = false;
  
   // See if this is a redefinition of a variable in the same scope.
-  if (!D.getCXXScopeSpec().isSet()) {
+  if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) {
     DC = CurContext;
-    PrevDecl = LookupDeclInScope(Name, Decl::IDNS_Ordinary, S);
+    PrevDecl = LookupName(S, Name, LookupOrdinaryName);
   } else { // Something like "int foo::x;"
     DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
-    PrevDecl = DC ? LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC)
-                  : LookupDeclInScope(Name, Decl::IDNS_Ordinary, S);
+    PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName);
 
     // C++ 7.3.1.2p2:
     // Members (including explicit specializations of templates) of a named
@@ -1807,7 +1681,7 @@
         << D.getCXXScopeSpec().getRange();
       InvalidDecl = true;
         
-      PrevDecl = LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC);
+      PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName);
       if (!PrevDecl) {
         // Nothing to suggest.
       } else if (OverloadedFunctionDecl *Ovl 
@@ -2662,7 +2536,7 @@
   // among each other.  Here they can only shadow globals, which is ok.
   IdentifierInfo *II = D.getIdentifier();
   if (II) {
-    if (Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, S)) {
+    if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
       if (PrevDecl->isTemplateParameter()) {
         // Maybe we will complain about the shadowed template parameter.
         DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
@@ -2954,7 +2828,7 @@
     DC = static_cast<DeclContext*>(SS.getScopeRep());
     // Look-up name inside 'foo::'.
     PrevDecl = dyn_cast_or_null<TagDecl>(
-                 LookupDeclInContext(Name, Decl::IDNS_Tag, DC).getAsDecl());
+                     LookupQualifiedName(DC, Name, LookupTagName).getAsDecl());
 
     // A tag 'foo::bar' must already exist.
     if (PrevDecl == 0) {
@@ -2965,14 +2839,14 @@
   } else if (Name) {
     // If this is a named struct, check to see if there was a previous forward
     // declaration or definition.
-    Decl *D = LookupDeclInScope(Name, Decl::IDNS_Tag, S);
+    Decl *D = LookupName(S, Name, LookupTagName);
     PrevDecl = dyn_cast_or_null<NamedDecl>(D);
 
     if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
       // FIXME: This makes sure that we ignore the contexts associated
       // with C structs, unions, and enums when looking for a matching
       // tag declaration or definition. See the similar lookup tweak
-      // in Sema::LookupDecl; is there a better way to deal with this?
+      // in Sema::LookupName; is there a better way to deal with this?
       while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
         SearchDC = SearchDC->getParent();
     }
@@ -3158,9 +3032,7 @@
     //   shall not be declared with the same name as a typedef-name
     //   that is declared in that scope and refers to a type other
     //   than the class or enumeration itself.
-    LookupResult Lookup = LookupName(S, Name, 
-                                     LookupCriteria(LookupCriteria::Ordinary, 
-                                                    true, true));
+    LookupResult Lookup = LookupName(S, Name, LookupOrdinaryName, true);
     TypedefDecl *PrevTypedef = 0;
     if (Lookup.getKind() == LookupResult::Found)
       PrevTypedef = dyn_cast<TypedefDecl>(Lookup.getAsDecl());
@@ -3352,8 +3224,7 @@
                               DeclSpec::SCS_mutable);
 
   if (II) {
-    Decl *PrevDecl 
-      = LookupDeclInScope(II, Decl::IDNS_Member, S, false);
+    Decl *PrevDecl = LookupName(S, II, LookupMemberName, true);
     if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S)
         && !isa<TagDecl>(PrevDecl)) {
       Diag(Loc, diag::err_duplicate_member) << II;
@@ -3445,7 +3316,7 @@
                                              (Expr *)BitfieldWidth);
   
   if (II) {
-    Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Member, S, false);
+    Decl *PrevDecl = LookupName(S, II, LookupMemberName, true);
     if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S)
         && !isa<TagDecl>(PrevDecl)) {
       Diag(Loc, diag::err_duplicate_member) << II;
@@ -3621,7 +3492,7 @@
   
   // Verify that there isn't already something declared with this name in this
   // scope.
-  Decl *PrevDecl = LookupDeclInScope(Id, Decl::IDNS_Ordinary, S);
+  Decl *PrevDecl = LookupName(S, Id, LookupOrdinaryName);
   if (PrevDecl && PrevDecl->isTemplateParameter()) {
     // Maybe we will complain about the shadowed template parameter.
     DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1870a8f..24f7531 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1375,8 +1375,8 @@
     // original-namespace-definition is the name of the namespace. Subsequently
     // in that declarative region, it is treated as an original-namespace-name.
 
-    Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, DeclRegionScope, 
-                                       /*LookupInParent=*/false);
+    Decl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName,
+                                true);
     
     if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
       // This is an extended namespace definition.
@@ -1437,14 +1437,7 @@
   // FIXME: This still requires lot more checks, and AST support.
 
   // Lookup namespace name.
-  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);
+  Decl *NS = LookupParsedName(S, &SS, NamespcName, LookupNamespaceName, false);
 
   if (NS) {
     assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
@@ -2179,7 +2172,7 @@
   // FIXME: Need to check for abstract classes.
 
   IdentifierInfo *II = D.getIdentifier();
-  if (Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, S)) {
+  if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
     // The scope should be freshly made just for us. There is just no way
     // it contains any previous declaration.
     assert(!S->isDeclScope(PrevDecl));
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 3371e3e..c3519f8 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -64,7 +64,7 @@
   assert(ClassName && "Missing class identifier");
   
   // Check for another declaration kind with the same name.
-  Decl *PrevDecl = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
+  Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName);
   if (PrevDecl && PrevDecl->isTemplateParameter()) {
     // Maybe we will complain about the shadowed template parameter.
     DiagnoseTemplateParameterShadow(ClassLoc, PrevDecl);
@@ -107,7 +107,7 @@
   if (SuperName) {
     ObjCInterfaceDecl* SuperClassEntry = 0;
     // Check if a different kind of symbol declared in this scope.
-    PrevDecl = LookupDeclInScope(SuperName, Decl::IDNS_Ordinary, TUScope);
+    PrevDecl = LookupName(TUScope, SuperName, LookupOrdinaryName);
     if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
       Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
       Diag(PrevDecl->getLocation(), diag::note_previous_definition);
@@ -149,7 +149,7 @@
                                            IdentifierInfo *ClassName,
                                            SourceLocation ClassLocation) {
   // Look for previous declaration of alias name
-  Decl *ADecl = LookupDeclInScope(AliasName, Decl::IDNS_Ordinary, TUScope);
+  Decl *ADecl = LookupName(TUScope, AliasName, LookupOrdinaryName);
   if (ADecl) {
     if (isa<ObjCCompatibleAliasDecl>(ADecl))
       Diag(AliasLocation, diag::warn_previous_alias_decl);
@@ -159,13 +159,13 @@
     return 0;
   }
   // Check for class declaration
-  Decl *CDeclU = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
+  Decl *CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName);
   if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) {
     QualType T = TDecl->getUnderlyingType();
     if (T->isObjCInterfaceType()) {
       if (NamedDecl *IDecl = T->getAsObjCInterfaceType()->getDecl()) {
         ClassName = IDecl->getIdentifier();
-        CDeclU = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
+        CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName);
       }
     }
   }
@@ -535,7 +535,7 @@
                       SourceLocation SuperClassLoc) {
   ObjCInterfaceDecl* IDecl = 0;
   // Check for another declaration kind with the same name.
-  Decl *PrevDecl = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
+  Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName);
   if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
     Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
     Diag(PrevDecl->getLocation(), diag::note_previous_definition);
@@ -551,7 +551,7 @@
   ObjCInterfaceDecl* SDecl = 0;
   if (SuperClassname) {
     // Check if a different kind of symbol declared in this scope.
-    PrevDecl = LookupDeclInScope(SuperClassname, Decl::IDNS_Ordinary, TUScope);
+    PrevDecl = LookupName(TUScope, SuperClassname, LookupOrdinaryName);
     if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
       Diag(SuperClassLoc, diag::err_redefinition_different_kind)
         << SuperClassname;
@@ -909,7 +909,7 @@
   
   for (unsigned i = 0; i != NumElts; ++i) {
     // Check for another declaration kind with the same name.
-    Decl *PrevDecl = LookupDeclInScope(IdentList[i], Decl::IDNS_Ordinary, TUScope);
+    Decl *PrevDecl = LookupName(TUScope, IdentList[i], LookupOrdinaryName);
     if (PrevDecl && PrevDecl->isTemplateParameter()) {
       // Maybe we will complain about the shadowed template parameter.
       DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5ebec02..129967a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -555,14 +555,9 @@
 
   // Could be enum-constant, value decl, instance variable, etc.
   Decl *D = 0;
-  LookupResult Lookup;
-  if (SS && !SS->isEmpty()) {
-    DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
-    if (DC == 0)
-      return ExprError();
-    Lookup = LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC);
-  } else
-    Lookup = LookupDeclInScope(Name, Decl::IDNS_Ordinary, S);
+  if (SS && SS->isInvalid())
+    return ExprError();
+  LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName);
 
   if (Lookup.isAmbiguous()) {
     DiagnoseAmbiguousLookup(Lookup, Name, Loc,
@@ -1519,9 +1514,7 @@
     // than this.
     LookupResult Result
       = LookupQualifiedName(RDecl, DeclarationName(&Member), 
-                            LookupCriteria(LookupCriteria::Member,
-                                           /*RedeclarationOnly=*/false, 
-                                           getLangOptions().CPlusPlus));
+                            LookupMemberName, false);
 
     Decl *MemberDecl = 0;
     if (!Result)
@@ -4030,9 +4023,9 @@
     // Get the decl corresponding to this.
     RecordDecl *RD = RC->getDecl();
     FieldDecl *MemberDecl 
-      = dyn_cast_or_null<FieldDecl>(LookupDeclInContext(OC.U.IdentInfo, 
-                                               Decl::IDNS_Ordinary,
-                                               RD, false).getAsDecl());
+      = dyn_cast_or_null<FieldDecl>(LookupQualifiedName(RD, OC.U.IdentInfo, 
+                                                        LookupMemberName)
+                                      .getAsDecl());
     if (!MemberDecl)
       return Diag(BuiltinLoc, diag::err_typecheck_no_member)
        << OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d0ceb97..3c8184d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -55,12 +55,12 @@
 Action::ExprResult
 Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
                      bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
-  const NamespaceDecl *StdNs = GetStdNamespace();
+  NamespaceDecl *StdNs = GetStdNamespace();
   if (!StdNs)
     return Diag(OpLoc, diag::err_need_header_before_typeid);
   
   IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
-  Decl *TypeInfoDecl = LookupDeclInContext(TypeInfoII, Decl::IDNS_Tag, StdNs);
+  Decl *TypeInfoDecl = LookupQualifiedName(StdNs, TypeInfoII, LookupTagName);
   RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl);
   if (!TypeInfoRecordDecl)
     return Diag(OpLoc, diag::err_need_header_before_typeid);
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index f436e61..f893f1e 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -52,7 +52,7 @@
     // Initialize the constant string interface lazily. This assumes
     // the NSConstantString interface is seen in this translation unit.
     IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString");
-    Decl *IFace = LookupDeclInScope(NSIdent, Decl::IDNS_Ordinary, TUScope);
+    Decl *IFace = LookupName(TUScope, NSIdent, LookupOrdinaryName);
     ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace);
     if (strIFace)
       Context.setObjCConstantStringInterface(strIFace);
@@ -209,7 +209,7 @@
     } else {
       // 'super' has been used outside a method context. If a variable named
       // 'super' has been declared, redirect. If not, produce a diagnostic.
-      Decl *SuperDecl = LookupDeclInScope(receiverName, Decl::IDNS_Ordinary, S);
+      Decl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName);
       ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
       if (VD) {
         ExprResult ReceiverExpr = new DeclRefExpr(VD, VD->getType(), 
@@ -234,7 +234,7 @@
   //
   // If necessary, the following lookup could move to getObjCInterfaceDecl().
   if (!ClassDecl) {
-    Decl *IDecl = LookupDeclInScope(receiverName, Decl::IDNS_Ordinary, 0);
+    Decl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName);
     if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) {
       const ObjCInterfaceType *OCIT;
       OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType();
diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
index cb58063..0772bc3 100644
--- a/lib/Sema/SemaInherit.cpp
+++ b/lib/Sema/SemaInherit.cpp
@@ -153,7 +153,8 @@
     } else {
       Paths.ScratchPath.Decls = BaseRecord->lookup(Criteria.Name);
       while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) {
-        if (Criteria.Criteria.isLookupResult(*Paths.ScratchPath.Decls.first)) {
+        if (isAcceptableLookupResult(*Paths.ScratchPath.Decls.first,
+                                     Criteria.NameKind, Criteria.IDNS)) {
           FoundPathToThisBase = true;
           break;
         }
diff --git a/lib/Sema/SemaInherit.h b/lib/Sema/SemaInherit.h
index 87a4a66..eb169a2 100644
--- a/lib/Sema/SemaInherit.h
+++ b/lib/Sema/SemaInherit.h
@@ -193,8 +193,9 @@
     /// MemberLookupCriteria - Constructs member lookup criteria to
     /// search for a class member with the given Name.
     explicit MemberLookupCriteria(DeclarationName Name, 
-                                  Sema::LookupCriteria Criteria) 
-      : LookupBase(false), Name(Name), Criteria(Criteria) { }
+                                  Sema::LookupNameKind NameKind,
+                                  unsigned IDNS) 
+      : LookupBase(false), Name(Name), NameKind(NameKind), IDNS(IDNS) { }
 
     /// LookupBase - True if we are looking for a base class (whose
     /// type is Base). If false, we are looking for a named member of
@@ -209,9 +210,8 @@
     /// LookupBase is false.
     DeclarationName Name;
 
-    /// Criteria - The criteria by which we evaluate a named member,
-    /// if LookupBase is false.
-    Sema::LookupCriteria Criteria;
+    Sema::LookupNameKind NameKind;
+    unsigned IDNS;
   };
 }
 
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 7353bc3..abb265d 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -31,8 +31,8 @@
 /// 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
+/// The existance of this routine is temporary; users of LookupResult
+/// should be able to handle multiple results, to deal with cases of
 /// ambiguity and overloaded functions without needing to create a
 /// Decl node.
 template<typename DeclIterator>
@@ -69,64 +69,6 @@
   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 Moves the name-lookup results from Other to this LookupResult.
 Sema::LookupResult
 Sema::LookupResult::CreateLookupResult(ASTContext &Context, 
@@ -239,6 +181,37 @@
   return reinterpret_cast<BasePaths *>(First);
 }
 
+// Retrieve the set of identifier namespaces that correspond to a
+// specific kind of name lookup.
+inline unsigned 
+getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, 
+                                          bool CPlusPlus) {
+  unsigned IDNS = 0;
+  switch (NameKind) {
+  case Sema::LookupOrdinaryName:
+    IDNS = Decl::IDNS_Ordinary;
+    if (CPlusPlus)
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
+    break;
+
+  case Sema::LookupTagName:
+    IDNS = Decl::IDNS_Tag;
+    break;
+
+  case Sema::LookupMemberName:
+    IDNS = Decl::IDNS_Member;
+    if (CPlusPlus)
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;    
+    break;
+
+  case Sema::LookupNestedNameSpecifierName:
+  case Sema::LookupNamespaceName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
+    break;
+  }
+  return IDNS;
+}
+
 /// @brief Perform unqualified name lookup starting from a given
 /// scope.
 ///
@@ -276,52 +249,58 @@
 /// declarations and possibly additional information used to diagnose
 /// ambiguities.
 Sema::LookupResult 
-Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) {
+Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
+                 bool RedeclarationOnly) {
   if (!Name) return LookupResult::CreateLookupResult(Context, 0);
 
   if (!getLangOptions().CPlusPlus) {
     // Unqualified name lookup in C/Objective-C is purely lexical, so
     // search in the declarations attached to the name.
+    unsigned IDNS = 0;
+    switch (NameKind) {
+    case Sema::LookupOrdinaryName:
+      IDNS = Decl::IDNS_Ordinary;
+      break;
 
-    // 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);
-    
+    case Sema::LookupTagName:
+      IDNS = Decl::IDNS_Tag;
+      break;
+
+    case Sema::LookupMemberName:
+      IDNS = Decl::IDNS_Member;
+      break;
+
+    case Sema::LookupNestedNameSpecifierName:
+    case Sema::LookupNamespaceName:
+      assert(false && "C does not perform these kinds of name lookup");
+      break;
+    }
+
     // 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))
+    for (IdentifierResolver::iterator I = IdResolver.begin(Name),
+                                   IEnd = IdResolver.end(); 
+         I != IEnd; ++I)
+      if ((*I)->isInIdentifierNamespace(IDNS))
         return LookupResult::CreateLookupResult(Context, *I);
   } else {
+    unsigned IDNS 
+      = getIdentifierNamespacesFromLookupNameKind(NameKind, 
+                                                  getLangOptions().CPlusPlus);
+
     // 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();
+    IdentifierResolver::iterator I = IdResolver.begin(Name),
+                              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)) {
+        if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
           // 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
@@ -356,10 +335,11 @@
         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))
+        if (LookupResult Result = LookupQualifiedName(Ctx, Name, NameKind, 
+                                                      RedeclarationOnly))
           return Result;
         
-        if (Criteria.RedeclarationOnly && !Ctx->isTransparentContext())
+        if (RedeclarationOnly && !Ctx->isTransparentContext())
           return LookupResult::CreateLookupResult(Context, 0);
 
         Ctx = Ctx->getParent();
@@ -370,9 +350,9 @@
   // 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) {
+  if (NameKind == LookupOrdinaryName) {
     IdentifierInfo *II = Name.getAsIdentifierInfo();
-    if (Criteria.AllowLazyBuiltinCreation && II) {
+    if (II) {
       // If this is a builtin on this (or all) targets, create the decl.
       if (unsigned BuiltinID = II->getBuiltinID())
         return LookupResult::CreateLookupResult(Context,
@@ -428,25 +408,28 @@
 /// ambiguities.
 Sema::LookupResult
 Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
-                          LookupCriteria Criteria) {
+                          LookupNameKind NameKind, bool RedeclarationOnly) {
   assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
   
   if (!Name) return LookupResult::CreateLookupResult(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;
+  unsigned IDNS
+    = getIdentifierNamespacesFromLookupNameKind(NameKind, 
+                                                getLangOptions().CPlusPlus);
+  if (NameKind == LookupOrdinaryName)
+    IDNS |= Decl::IDNS_Member;
 
   // Perform qualified name lookup into the LookupCtx.
   DeclContext::lookup_iterator I, E;
   for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I)
-    if (Criteria.isLookupResult(*I))
+    if (isAcceptableLookupResult(*I, NameKind, IDNS))
       return LookupResult::CreateLookupResult(Context, I, E);
 
   // If this isn't a C++ class or we aren't allowed to look into base
   // classes, we're done.
-  if (Criteria.RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
+  if (RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
     return LookupResult::CreateLookupResult(Context, 0);
 
   // Perform lookup into our base classes.
@@ -455,7 +438,7 @@
 
   // Look for this member in our base classes
   if (!LookupInBases(cast<CXXRecordDecl>(LookupCtx), 
-                     MemberLookupCriteria(Name, Criteria), Paths))
+                     MemberLookupCriteria(Name, NameKind, IDNS), Paths))
     return LookupResult::CreateLookupResult(Context, 0);
 
   // C++ [class.member.lookup]p2:
@@ -552,18 +535,21 @@
 /// @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);
+Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, 
+                       DeclarationName Name, LookupNameKind NameKind,
+                       bool RedeclarationOnly) {
+  if (SS) {
+    if (SS->isInvalid())
+      return LookupResult::CreateLookupResult(Context, 0);
 
-  return LookupName(S, Name, Criteria);
+    if (SS->isSet())
+      return LookupQualifiedName(static_cast<DeclContext *>(SS->getScopeRep()),
+                                 Name, NameKind, RedeclarationOnly);
+  }
+
+  return LookupName(S, Name, NameKind, RedeclarationOnly);
 }
 
 /// @brief Produce a diagnostic describing the ambiguity that resulted
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 0f9f0cf..17ad387 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2279,9 +2279,8 @@
   //        of type T2 or “reference to (possibly cv-qualified) T2”,
   //        when T2 is an enumeration type, are candidate functions.
   {
-    IdentifierResolver::iterator
-      I = IdResolver.begin(OpName, CurContext, true/*LookInParentCtx*/),
-      IEnd = IdResolver.end();
+    IdentifierResolver::iterator I = IdResolver.begin(OpName),
+                              IEnd = IdResolver.end();
     for (; I != IEnd; ++I) {
       // We don't need to check the identifier namespace, because
       // operator names can only be ordinary identifiers.
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 7ecac00..f1b8617 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -32,9 +32,7 @@
       return 0;
     DC = static_cast<DeclContext*>(SS->getScopeRep());
   }
-  Decl *IIDecl = DC ? 
-                 LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC, false) :
-                 LookupDeclInScope(&II, Decl::IDNS_Ordinary, S, false);
+  Decl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
 
   if (IIDecl) {
     // FIXME: We need to represent templates via some kind of
@@ -96,7 +94,7 @@
   bool Invalid = false;
 
   if (ParamName) {
-    Decl *PrevDecl = LookupDeclInScope(ParamName, Decl::IDNS_Tag, S);
+    Decl *PrevDecl = LookupName(S, ParamName, LookupTagName);
     if (PrevDecl && PrevDecl->isTemplateParameter())
       Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
 							   PrevDecl);
@@ -132,7 +130,7 @@
 
   IdentifierInfo *ParamName = D.getIdentifier();
   if (ParamName) {
-    Decl *PrevDecl = LookupDeclInScope(ParamName, Decl::IDNS_Tag, S);
+    Decl *PrevDecl = LookupName(S, ParamName, LookupTagName);
     if (PrevDecl && PrevDecl->isTemplateParameter())
       Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
 							   PrevDecl);