Don't explicitly represent OverloadedFunctionDecls within
DeclContext. Instead, just keep the list of currently-active
declarations and only build the OverloadedFunctionDecl when we
absolutely need it.

This is a half-step toward eliminating the need to explicitly build
OverloadedFunctionDecls that store sets of overloaded
functions. This was suggested by Argiris a while back, and it's a good
thing for several reasons: first, it eliminates the messy logic that
currently tries to keep the OverloadedFunctionDecl in sync with the 
declarations that are being added. Second, it will (eventually)
eliminate the need to allocate memory for overload sets, which could
help performance. Finally, it helps set us up for when name lookup can
return multiple (possibly ambiguous) results, as can happen with
lookup of class members in C++.

Next steps: make the IdentifierResolver store overloads as separate
entries in its list rather than replacing them with an
OverloadedFunctionDecl now, then see how far we can go toward
eliminating OverloadedFunctionDecl entirely.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61357 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 48af5af..2664c57 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -479,7 +479,7 @@
                                SourceLocation *CommaLocs, 
                                SourceLocation RParenLoc);
 
-  ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
+  ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
                                       SourceLocation MemberLoc,
                                       IdentifierInfo &Member);
                                            
@@ -696,7 +696,8 @@
   virtual ExprResult ActOnArraySubscriptExpr(Scope *S, ExprTy *Base, 
                                              SourceLocation LLoc, ExprTy *Idx,
                                              SourceLocation RLoc);
-  virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+  virtual ExprResult ActOnMemberReferenceExpr(Scope *S, ExprTy *Base,
+                                              SourceLocation OpLoc,
                                               tok::TokenKind OpKind,
                                               SourceLocation MemberLoc,
                                               IdentifierInfo &Member);
@@ -747,7 +748,8 @@
                                    SourceLocation RPLoc); // "({..})"
 
   /// __builtin_offsetof(type, a.b[123][456].c)
-  virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+  virtual ExprResult ActOnBuiltinOffsetOf(Scope *S,
+                                          SourceLocation BuiltinLoc,
                                           SourceLocation TypeLoc, TypeTy *Arg1,
                                           OffsetOfComponent *CompPtr,
                                           unsigned NumComponents,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 024ca81..270de55 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -106,7 +106,7 @@
       // require some reshuffling in the identifier resolver.
       IdentifierResolver::iterator
         I = IdResolver.begin(TD->getIdentifier(), CurContext, 
-                            false/*LookInParentCtx*/);
+                             false/*LookInParentCtx*/);
       if (I != IdResolver.end()) {
        // There is already a declaration with the same name in the same
        // scope. It must be found before we find the new declaration,
@@ -123,57 +123,47 @@
     // We are pushing the name of a function, which might be an
     // overloaded name.
     FunctionDecl *FD = cast<FunctionDecl>(D);
-    Decl *Prev = LookupDecl(FD->getDeclName(), Decl::IDNS_Ordinary, S,
-                           FD->getDeclContext(), false, false);
-    if (Prev && (isa<OverloadedFunctionDecl>(Prev) || isa<FunctionDecl>(Prev))) {
-      // There is already a declaration with the same name in
-      // the same scope. It must be a function or an overloaded
-      // function.
-      OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(Prev);
-      if (!Ovl) {
-        // We haven't yet overloaded this function. Take the existing
-        // FunctionDecl and put it into an OverloadedFunctionDecl.
-        Ovl = OverloadedFunctionDecl::Create(Context, 
-                                             FD->getDeclContext(),
-                                             FD->getDeclName());
-        Ovl->addOverload(cast<FunctionDecl>(Prev));
+    if (CurContext == FD->getDeclContext()) {
+      IdentifierResolver::iterator
+        I = IdResolver.begin(FD->getDeclName(), CurContext, 
+                             false/*LookInParentCtx*/);
+      if (I != IdResolver.end() &&
+          (isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) {
+        // There is already a declaration with the same name in
+        // the same scope. It must be a function or an overloaded
+        // function.
+        OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I);
+        if (!Ovl) {
+          // We haven't yet overloaded this function. Take the existing
+          // FunctionDecl and put it into an OverloadedFunctionDecl.
+          Ovl = OverloadedFunctionDecl::Create(Context, 
+                                               FD->getDeclContext(),
+                                               FD->getDeclName());
+          Ovl->addOverload(cast<FunctionDecl>(*I));
+          
+          IdResolver.RemoveDecl(*I);
+          S->RemoveDecl(*I);
         
-        // If there is a name binding for the existing FunctionDecl,
-        // remove it.
-        for (IdentifierResolver::iterator I 
-               = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(), 
-                                  false/*LookInParentCtx*/),
-               E = IdResolver.end(); I != E; ++I) {
-          if (*I == Prev) {
-            IdResolver.RemoveDecl(*I);
-            S->RemoveDecl(*I);
-            break;
-          }
+          // Add the name binding for the OverloadedFunctionDecl.
+          IdResolver.AddDecl(Ovl);
+          
+          S->AddDecl(Ovl);
         }
-       
-        // Add the name binding for the OverloadedFunctionDecl.
-        IdResolver.AddDecl(Ovl);
 
-        // Update the context with the newly-created overloaded
-        // function set.
-        FD->getDeclContext()->insert(Context, Ovl);
-
-       S->AddDecl(Ovl);
+        // We added this function declaration to the scope earlier, but
+        // we don't want it there because it is part of the overloaded
+        // function declaration.
+        S->RemoveDecl(FD);
+        
+        // We have an OverloadedFunctionDecl. Add the new FunctionDecl
+        // to its list of overloads.
+        Ovl->addOverload(FD);
+        
+        // Add this new function declaration to the declaration context.
+        CurContext->addDecl(Context, FD);
+        
+        return;      
       }
-
-      // We added this function declaration to the scope earlier, but
-      // we don't want it there because it is part of the overloaded
-      // function declaration.
-      S->RemoveDecl(FD);
-
-      // We have an OverloadedFunctionDecl. Add the new FunctionDecl
-      // to its list of overloads.
-      Ovl->addOverload(FD);
-
-      // Add this new function declaration to the declaration context.
-      CurContext->addDecl(Context, FD, false);
-
-      return;      
     }
   }
 
@@ -216,6 +206,52 @@
   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.
+static Decl *
+MaybeConstructOverloadSet(ASTContext &Context, const DeclContext *DC,
+                          DeclContext::lookup_const_iterator I,
+                          DeclContext::lookup_const_iterator 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.
+    DeclContext::lookup_const_iterator 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, 
+                                             const_cast<DeclContext *>(DC), 
+                                             (*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;
+}
+
 /// LookupDecl - Look up the inner-most declaration in the specified
 /// namespace.
 Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
@@ -244,14 +280,12 @@
       if ((*I)->getIdentifierNamespace() & NS)
          return *I;
   } else if (LookupCtx) {
-    assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
-
     // 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(Context, Name); I != E; ++I)
       if ((*I)->getIdentifierNamespace() & NS)
-       return *I;
+        return MaybeConstructOverloadSet(Context, LookupCtx, I, E);
   } else {
     // Name lookup for ordinary names and tag names in C++ requires
     // looking into scopes that aren't strictly lexical, and
@@ -279,7 +313,7 @@
         for (llvm::tie(I, E) = Ctx->lookup(Context, Name); I != E; ++I) {
           // FIXME: Cache this result in the IdResolver
           if ((*I)->getIdentifierNamespace() & NS)
-            return  *I;
+            return MaybeConstructOverloadSet(Context, LookupCtx, I, E);
         }
         
         Ctx = Ctx->getParent();
@@ -533,6 +567,7 @@
     if (OldReturnType != NewReturnType) {
       Diag(New->getLocation(), diag::err_ovl_diff_return_type);
       Diag(Old->getLocation(), PrevDiag);
+      Redeclaration = true;
       return New;
     }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8a37bbb..918fd2a 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -20,6 +20,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include <algorithm> // for std::equal
 #include <map>
@@ -844,23 +845,7 @@
     CopyConstructor->setParams(&FromParam, 1);
 
     ClassDecl->addedConstructor(Context, CopyConstructor);
-    DeclContext::lookup_result Lookup = ClassDecl->lookup(Context, Name);
-    if (Lookup.first == Lookup.second 
-        || (!isa<CXXConstructorDecl>(*Lookup.first) &&
-            !isa<OverloadedFunctionDecl>(*Lookup.first)))
-      ClassDecl->addDecl(Context, CopyConstructor);
-    else {
-      OverloadedFunctionDecl *Ovl 
-        = dyn_cast<OverloadedFunctionDecl>(*Lookup.first);
-      if (!Ovl) {
-        Ovl = OverloadedFunctionDecl::Create(Context, ClassDecl, Name);
-        Ovl->addOverload(cast<CXXConstructorDecl>(*Lookup.first));
-        ClassDecl->insert(Context, Ovl);
-      }
-
-      Ovl->addOverload(CopyConstructor);
-      ClassDecl->addDecl(Context, CopyConstructor, false);
-    }
+    ClassDecl->addDecl(Context, CopyConstructor);
   }
 
   if (!ClassDecl->hasUserDeclaredDestructor()) {
@@ -1470,23 +1455,10 @@
   DeclarationName ConstructorName 
     = Context.DeclarationNames.getCXXConstructorName(
                        Context.getCanonicalType(ClassType.getUnqualifiedType()));
-  DeclContext::lookup_const_result Lookup 
-    = ClassDecl->lookup(Context, ConstructorName);
-  if (Lookup.first == Lookup.second)
-    /* No constructors */;
-  else if (OverloadedFunctionDecl *Constructors 
-             = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
-    for (OverloadedFunctionDecl::function_iterator Con 
-           = Constructors->function_begin();
-         Con != Constructors->function_end(); ++Con) {
-      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
-      if ((Kind == IK_Direct) ||
-          (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
-          (Kind == IK_Default && Constructor->isDefaultConstructor()))
-        AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
-    }
-  } else if (CXXConstructorDecl *Constructor 
-               = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(Context, ConstructorName);
+       Con != ConEnd; ++Con) {
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
     if ((Kind == IK_Direct) ||
         (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
         (Kind == IK_Default && Constructor->isDefaultConstructor()))
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 307e1ad..4088f44 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1254,7 +1254,7 @@
 }
 
 Action::ExprResult Sema::
-ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
+ActOnMemberReferenceExpr(Scope *S, ExprTy *Base, SourceLocation OpLoc,
                          tok::TokenKind OpKind, SourceLocation MemberLoc,
                          IdentifierInfo &Member) {
   Expr *BaseExpr = static_cast<Expr *>(Base);
@@ -1272,7 +1272,7 @@
     if (const PointerType *PT = BaseType->getAsPointerType())
       BaseType = PT->getPointeeType();
     else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
-      return BuildOverloadedArrowExpr(BaseExpr, OpLoc, MemberLoc, Member);
+      return BuildOverloadedArrowExpr(S, BaseExpr, OpLoc, MemberLoc, Member);
     else
       return Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
         << BaseType << BaseExpr->getSourceRange();
@@ -1288,42 +1288,42 @@
     // The record definition is complete, now make sure the member is valid.
     // FIXME: Qualified name lookup for C++ is a bit more complicated
     // than this.
-    DeclContext::lookup_result Lookup = RDecl->lookup(Context, &Member);
-    if (Lookup.first == Lookup.second) {
+    Decl *MemberDecl = LookupDecl(DeclarationName(&Member), Decl::IDNS_Ordinary,
+                                  S, RDecl, false, false);
+    if (!MemberDecl)
       return Diag(MemberLoc, diag::err_typecheck_no_member)
                << &Member << BaseExpr->getSourceRange();
-    } 
 
-    if (FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first)) {
+    if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
       // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
       // FIXME: Handle address space modifiers
-      QualType MemberType = MemberDecl->getType();
+      QualType MemberType = FD->getType();
       if (const ReferenceType *Ref = MemberType->getAsReferenceType())
         MemberType = Ref->getPointeeType();
       else {
         unsigned combinedQualifiers =
           MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
-        if (MemberDecl->isMutable())
+        if (FD->isMutable())
           combinedQualifiers &= ~QualType::Const;
         MemberType = MemberType.getQualifiedType(combinedQualifiers);
       }
 
-      return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
+      return new MemberExpr(BaseExpr, OpKind == tok::arrow, FD,
                             MemberLoc, MemberType);
-    } else if (CXXClassVarDecl *Var = dyn_cast<CXXClassVarDecl>(*Lookup.first))
+    } else if (CXXClassVarDecl *Var = dyn_cast<CXXClassVarDecl>(MemberDecl))
       return new MemberExpr(BaseExpr, OpKind == tok::arrow, Var, MemberLoc,
                             Var->getType().getNonReferenceType());
-    else if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(*Lookup.first))
+    else if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl))
       return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberFn, MemberLoc,
                             MemberFn->getType());
     else if (OverloadedFunctionDecl *Ovl 
-             = dyn_cast<OverloadedFunctionDecl>(*Lookup.first))
+             = dyn_cast<OverloadedFunctionDecl>(MemberDecl))
       return new MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl, MemberLoc,
                             Context.OverloadTy);
-    else if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(*Lookup.first))
+    else if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl))
       return new MemberExpr(BaseExpr, OpKind == tok::arrow, Enum, MemberLoc,
                             Enum->getType());
-    else if (isa<TypeDecl>(*Lookup.first))
+    else if (isa<TypeDecl>(MemberDecl))
       return Diag(MemberLoc, diag::err_typecheck_member_reference_type)
         << DeclarationName(&Member) << int(OpKind == tok::arrow);
 
@@ -3573,7 +3573,8 @@
   return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
 }
 
-Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+Sema::ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
+                                            SourceLocation BuiltinLoc,
                                             SourceLocation TypeLoc,
                                             TypeTy *argty,
                                             OffsetOfComponent *CompPtr,
@@ -3628,11 +3629,10 @@
       
     // Get the decl corresponding to this.
     RecordDecl *RD = RC->getDecl();
-    FieldDecl *MemberDecl = 0;
-    DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo);
-    if (Lookup.first != Lookup.second)
-      MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
-
+    FieldDecl *MemberDecl 
+      = dyn_cast_or_null<FieldDecl>(LookupDecl(OC.U.IdentInfo, 
+                                               Decl::IDNS_Ordinary,
+                                               S, RD, false, false));
     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 e18f143..eb2e647 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -18,6 +18,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
 using namespace clang;
 
 /// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
@@ -412,8 +413,9 @@
                                   DeclContext *Ctx, bool AllowMissing,
                                   FunctionDecl *&Operator)
 {
-  DeclContext::lookup_result Lookup = Ctx->lookup(Context, Name);
-  if (Lookup.first == Lookup.second) {
+  DeclContext::lookup_iterator Alloc, AllocEnd;
+  llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Context, Name);
+  if (Alloc == AllocEnd) {
     if (AllowMissing)
       return false;
     // FIXME: Bad location information.
@@ -422,21 +424,12 @@
   }
 
   OverloadCandidateSet Candidates;
-  NamedDecl *Decl = *Lookup.first;
-  // Even member operator new/delete are implicitly treated as static, so don't
-  // use AddMemberCandidate.
-  if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl))
-    AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
-                         /*SuppressUserConversions=*/false);
-  else if (OverloadedFunctionDecl *Ovl
-             = dyn_cast_or_null<OverloadedFunctionDecl>(Decl)) {
-    for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
-                                                   FEnd = Ovl->function_end();
-       F != FEnd; ++F) {
-      if (FunctionDecl *Fn = *F)
-        AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
-                             /*SuppressUserConversions=*/false);
-    }
+  for (; Alloc != AllocEnd; ++Alloc) {
+    // Even member operator new/delete are implicitly treated as
+    // static, so don't use AddMemberCandidate.
+    if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*Alloc))
+      AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
+                           /*SuppressUserConversions=*/false);
   }
 
   // Do the resolution.
@@ -555,7 +548,7 @@
                                            0, Argument, VarDecl::None, 0, 0);
   Alloc->setParams(&Param, 1);
 
-  PushOnScopeChains(Alloc, TUScope);
+  ((DeclContext *)TUScope->getEntity())->addDecl(Context, Alloc);
 }
 
 /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 8365349..8463c5d 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -20,6 +20,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeOrdering.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include <algorithm>
 
@@ -1106,22 +1107,10 @@
     DeclarationName ConstructorName 
       = Context.DeclarationNames.getCXXConstructorName(
                                              Context.getCanonicalType(ToType));
-    DeclContext::lookup_result Lookup 
-      = ToRecordDecl->lookup(Context, ConstructorName);
-    if (Lookup.first == Lookup.second)
-      /* No constructors. FIXME: Implicit copy constructor? */;
-    else if (OverloadedFunctionDecl *Constructors 
-               = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
-      for (OverloadedFunctionDecl::function_const_iterator func 
-             = Constructors->function_begin();
-           func != Constructors->function_end(); ++func) {
-        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*func);
-        if (Constructor->isConvertingConstructor())
-          AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
-                               /*SuppressUserConversions=*/true);
-      }
-    } else if (CXXConstructorDecl *Constructor 
-                 = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
+    DeclContext::lookup_iterator Con, ConEnd;
+    for (llvm::tie(Con, ConEnd) = ToRecordDecl->lookup(Context, ConstructorName);
+         Con != ConEnd; ++Con) {
+      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
       if (Constructor->isConvertingConstructor())
         AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
                              /*SuppressUserConversions=*/true);
@@ -2142,22 +2131,12 @@
   //        (13.3.1.1.1); otherwise, the set of member candidates is
   //        empty.
   if (const RecordType *T1Rec = T1->getAsRecordType()) {
-    DeclContext::lookup_const_result Lookup 
-      = T1Rec->getDecl()->lookup(Context, OpName);
-    NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
-    if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
-      AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
+    DeclContext::lookup_const_iterator Oper, OperEnd;
+    for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(Context, OpName);
+         Oper != OperEnd; ++Oper)
+      AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Args[0], 
+                         Args+1, NumArgs - 1, CandidateSet,
                          /*SuppressUserConversions=*/false);
-    else if (OverloadedFunctionDecl *Ovl 
-               = dyn_cast_or_null<OverloadedFunctionDecl>(MemberOps)) {
-      for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
-                                                  FEnd = Ovl->function_end();
-           F != FEnd; ++F) {
-        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
-          AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
-                             /*SuppressUserConversions=*/false);
-      }
-    }
   }
 
   //     -- The set of non-member candidates is the result of the
@@ -3405,22 +3384,11 @@
   //  (E).operator().
   OverloadCandidateSet CandidateSet;
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
-  DeclContext::lookup_const_result Lookup 
-    = Record->getDecl()->lookup(Context, OpName);
-  NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
-  if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
-    AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,
-                       /*SuppressUserConversions=*/false);
-  else if (OverloadedFunctionDecl *Ovl 
-           = dyn_cast_or_null<OverloadedFunctionDecl>(MemberOps)) {
-    for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
-           FEnd = Ovl->function_end();
-         F != FEnd; ++F) {
-      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
-        AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,
-                           /*SuppressUserConversions=*/false);
-    }
-  }
+  DeclContext::lookup_const_iterator Oper, OperEnd;
+  for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(Context, OpName);
+       Oper != OperEnd; ++Oper)
+    AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs, 
+                       CandidateSet, /*SuppressUserConversions=*/false);
 
   // C++ [over.call.object]p2:
   //   In addition, for each conversion function declared in T of the
@@ -3585,7 +3553,7 @@
 ///  (if one exists), where @c Base is an expression of class type and 
 /// @c Member is the name of the member we're trying to find.
 Action::ExprResult 
-Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
                                SourceLocation MemberLoc,
                                IdentifierInfo &Member) {
   assert(Base->getType()->isRecordType() && "left-hand side must have class type");
@@ -3600,22 +3568,12 @@
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
   OverloadCandidateSet CandidateSet;
   const RecordType *BaseRecord = Base->getType()->getAsRecordType();
-  DeclContext::lookup_const_result Lookup 
-    = BaseRecord->getDecl()->lookup(Context, OpName);
-  NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
-  if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
-    AddMethodCandidate(Method, Base, 0, 0, CandidateSet,
+  
+  DeclContext::lookup_const_iterator Oper, OperEnd;
+  for (llvm::tie(Oper, OperEnd) = BaseRecord->getDecl()->lookup(Context, OpName);
+       Oper != OperEnd; ++Oper)
+    AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Base, 0, 0, CandidateSet,
                        /*SuppressUserConversions=*/false);
-  else if (OverloadedFunctionDecl *Ovl 
-             = dyn_cast_or_null<OverloadedFunctionDecl>(MemberOps)) {
-    for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
-           FEnd = Ovl->function_end();
-         F != FEnd; ++F) {
-      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
-        AddMethodCandidate(Method, Base, 0, 0, CandidateSet,
-                           /*SuppressUserConversions=*/false);
-    }
-  }
 
   llvm::OwningPtr<Expr> BasePtr(Base);
 
@@ -3658,7 +3616,7 @@
   Base = new CXXOperatorCallExpr(FnExpr, &Base, 1, 
                                  Method->getResultType().getNonReferenceType(),
                                  OpLoc);
-  return ActOnMemberReferenceExpr(Base, OpLoc, tok::arrow, MemberLoc, Member);
+  return ActOnMemberReferenceExpr(S, Base, OpLoc, tok::arrow, MemberLoc, Member);
 }
 
 /// FixOverloadedFunctionReference - E is an expression that refers to