]> granicus.if.org Git - clang/commitdiff
Don't explicitly represent OverloadedFunctionDecls within
authorDouglas Gregor <dgregor@apple.com>
Tue, 23 Dec 2008 00:26:44 +0000 (00:26 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 23 Dec 2008 00:26:44 +0000 (00:26 +0000)
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

Driver/PrintParserCallbacks.cpp
include/clang/AST/DeclBase.h
include/clang/Parse/Action.h
lib/AST/DeclBase.cpp
lib/Parse/ParseExpr.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaOverload.cpp

index 3f6562893c4e2e43d0a55f1bd8323a3db500dc2c..c97e95a51a9f23cb4f4320796cf74ac0b4e43461 100644 (file)
@@ -483,7 +483,8 @@ namespace {
       llvm::cout << __FUNCTION__ << "\n";
       return 0;
     }
-    virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+    virtual ExprResult ActOnMemberReferenceExpr(Scope *S, ExprTy *Base,
+                                                SourceLocation OpLoc,
                                                 tok::TokenKind OpKind,
                                                 SourceLocation MemberLoc,
                                                 IdentifierInfo &Member) {
@@ -565,7 +566,7 @@ namespace {
       return 0;
     }
   
-    virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+    virtual ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
                                             SourceLocation TypeLoc, TypeTy *Arg1,
                                             OffsetOfComponent *CompPtr,
                                             unsigned NumComponents,
index 68a484666e73680972767af29c6817b7dbd3891f..9ceb78017258dc42598d38cf98e076457ff624f2 100644 (file)
@@ -191,6 +191,8 @@ public:
     case EnumConstant:
     case NonTypeTemplateParm:
     case Field:
+    case ObjCAtDefsField:
+    case ObjCIvar:
     case ObjCInterface:
     case ObjCCompatibleAlias:
     case OverloadedFunction:
@@ -267,8 +269,7 @@ class DeclContext {
   /// LookupPtrKind - Describes what kind of pointer LookupPtr
   /// actually is. 
   enum LookupPtrKind {
-    /// LookupIsMap - Indicates that LookupPtr is actually a
-    /// DenseMap<DeclarationName, TwoNamedDecls> pointer.
+    /// LookupIsMap - Indicates that LookupPtr is actually a map.
     LookupIsMap = 7
   };
 
@@ -276,9 +277,10 @@ class DeclContext {
   /// declarations within this context. If the context contains fewer
   /// than seven declarations, the number of declarations is provided
   /// in the 3 lowest-order bits and the upper bits are treated as a
-  /// pointer to an array of NamedDecl pointers. If the context
+  /// pointer to an array of ScopedDecl pointers. If the context
   /// contains seven or more declarations, the upper bits are treated
-  /// as a pointer to a DenseMap<DeclarationName, TwoNamedDecls>.
+  /// as a pointer to a DenseMap<DeclarationName, std::vector<ScopedDecl>>.
+  /// FIXME: We need a better data structure for this.
   llvm::PointerIntPair<void*, 3> LookupPtr;
 
   /// Decls - Contains all of the declarations that are defined inside
@@ -440,11 +442,11 @@ public:
 
   /// lookup_iterator - An iterator that provides access to the results
   /// of looking up a name within this context.
-  typedef NamedDecl **lookup_iterator;
+  typedef ScopedDecl **lookup_iterator;
 
   /// lookup_const_iterator - An iterator that provides non-mutable
   /// access to the results of lookup up a name within this context.
-  typedef NamedDecl * const * lookup_const_iterator;
+  typedef ScopedDecl * const * lookup_const_iterator;
 
   typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
   typedef std::pair<lookup_const_iterator, lookup_const_iterator>
@@ -471,7 +473,7 @@ public:
   /// that this replacement is semantically correct, e.g., that
   /// declarations are only replaced by later declarations of the same
   /// entity and not a declaration of some other kind of entity.
-  void insert(ASTContext &Context, NamedDecl *D);
+  void insert(ASTContext &Context, ScopedDecl *D);
 
   static bool classof(const Decl *D) {
     switch (D->getKind()) {
@@ -503,7 +505,7 @@ public:
   static bool classof(const BlockDecl *D) { return true; }
 
 private:
-  void insertImpl(NamedDecl *D);
+  void insertImpl(ScopedDecl *D);
 
   void EmitOutRec(llvm::Serializer& S) const;
   void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
index 249f1224c7a368fbb0c1586cd3635d11cd219bd6..39de870d12d9bc4dffd66900f148694b5beeaa29 100644 (file)
@@ -569,7 +569,8 @@ public:
                                              ExprTy *Idx, SourceLocation RLoc) {
     return 0;
   }
-  virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
+  virtual ExprResult ActOnMemberReferenceExpr(Scope *S, ExprTy *Base,
+                                              SourceLocation OpLoc,
                                               tok::TokenKind OpKind,
                                               SourceLocation MemberLoc,
                                               IdentifierInfo &Member) {
@@ -650,7 +651,7 @@ public:
     } U;
   };
   
-  virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+  virtual ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
                                           SourceLocation TypeLoc, TypeTy *Arg1,
                                           OffsetOfComponent *CompPtr,
                                           unsigned NumComponents,
index 5d70493d1d6a211ce069337da4de67d3bba562c8..87ebf85b41d3079bb398acb83b3ea9558a07c9ce 100644 (file)
@@ -17,6 +17,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Type.h"
 #include "llvm/ADT/DenseMap.h"
+#include <vector>
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -375,21 +376,15 @@ const DeclContext *DeclContext::getLexicalParent() const {
   return getParent();
 }
 
-/// TwoNamedDecls - Stores up to two NamedDecls. The first
-/// declaration, if any, is in the ordinary identifier namespace, and
-/// corresponds to values (functions, variables, etc.). The second
-/// declaration, if any, is in the tag identifier namespace, and
-/// corresponds to tag types (classes, enums).
-struct TwoNamedDecls {
-  NamedDecl* Decls[2];
-};
-
 // FIXME: We really want to use a DenseSet here to eliminate the
 // redundant storage of the declaration names, but (1) it doesn't give
 // us the ability to search based on DeclarationName, (2) we really
 // need something more like a DenseMultiSet, and (3) it's
-// implemented in terms of DenseMap anyway.
-typedef llvm::DenseMap<DeclarationName, TwoNamedDecls> StoredDeclsMap;
+// implemented in terms of DenseMap anyway. However, this data
+// structure is really space-inefficient, so we'll have to do
+// something.
+typedef llvm::DenseMap<DeclarationName, std::vector<ScopedDecl*> >
+  StoredDeclsMap;
 
 DeclContext::~DeclContext() {
   unsigned Size = LookupPtr.getInt();
@@ -397,7 +392,7 @@ DeclContext::~DeclContext() {
     StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
     delete Map;
   } else {
-    NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
+    ScopedDecl **Array = static_cast<ScopedDecl**>(LookupPtr.getPointer());
     delete [] Array;
   }
 }
@@ -497,7 +492,7 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
   if (PrimaryContext != this)
     return PrimaryContext->lookup(Context, Name);
 
-  /// If there is no lookup data structure, build one now by talking
+  /// If there is no lookup data structure, build one now by walking
   /// all of the linked DeclContexts (in declaration order!) and
   /// inserting their values.
   if (LookupPtr.getPointer() == 0) {
@@ -506,32 +501,27 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
         insertImpl(*D);
   }
 
-  lookup_result Result(0, 0);
   if (isLookupMap()) {
     StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
     StoredDeclsMap::iterator Pos = Map->find(Name);
-    if (Pos != Map->end()) {
-      Result.first = Pos->second.Decls[0]? &Pos->second.Decls[0] 
-                                        : &Pos->second.Decls[1];
-      Result.second = Pos->second.Decls[1]? &Pos->second.Decls[2]
-                                         : &Pos->second.Decls[1];
-    }
-    return Result;
+    if (Pos != Map->end())
+      return lookup_result(&Pos->second.front(), 
+                           &Pos->second.front() + Pos->second.size());
+    return lookup_result(0, 0);
   } 
 
   // We have a small array. Look into it.
   unsigned Size = LookupPtr.getInt();
-  NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
+  ScopedDecl **Array = static_cast<ScopedDecl**>(LookupPtr.getPointer());
   for (unsigned Idx = 0; Idx != Size; ++Idx)
     if (Array[Idx]->getDeclName() == Name) {
-      Result.first = &Array[Idx];
-      Result.second = Result.first + 1;
-      if (Idx + 1 < Size && Array[Idx + 1]->getDeclName() == Name)
-        ++Result.second;
-      break;
+      unsigned Last = Idx + 1;
+      while (Last != Size && Array[Last]->getDeclName() == Name)
+        ++Last;
+      return lookup_result(&Array[Idx], &Array[Last]);
     }
 
-  return Result;
+  return lookup_result(0, 0);
 }
 
 DeclContext::lookup_const_result 
@@ -539,7 +529,7 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
   return const_cast<DeclContext*>(this)->lookup(Context, Name);
 }
 
-void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
+void DeclContext::insert(ASTContext &Context, ScopedDecl *D) {
   DeclContext *PrimaryContext = getPrimaryContext(Context);
   if (PrimaryContext != this) {
     PrimaryContext->insert(Context, D);
@@ -553,60 +543,80 @@ void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
     insertImpl(D);
 }
 
-void DeclContext::insertImpl(NamedDecl *D) {
+static bool isRedeclarationOf(ScopedDecl *D, ScopedDecl *OldD) {
+  assert(D->getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    // For function declarations, we keep track of redeclarations.
+    return FD->getPreviousDeclaration() == OldD;
+
+  // For non-function declarations, if the declarations are of the
+  // same kind then this must be a redeclaration, or semantic analysis
+  // would not have given us the new declaration.
+  return D->getKind() == OldD->getKind();
+}
+
+void DeclContext::insertImpl(ScopedDecl *D) {
+  bool MayBeRedeclaration = true;
+
   if (!isLookupMap()) {
     unsigned Size = LookupPtr.getInt();
 
     // The lookup data is stored as an array. Search through the array
     // to find the insertion location.
-    NamedDecl **Array;
+    ScopedDecl **Array;
     if (Size == 0) {
-      Array = new NamedDecl*[LookupIsMap - 1];
+      Array = new ScopedDecl*[LookupIsMap - 1];
       LookupPtr.setPointer(Array);
     } else {
-      Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
+      Array = static_cast<ScopedDecl **>(LookupPtr.getPointer());
     }
 
     // We always keep declarations of the same name next to each other
     // in the array, so that it is easy to return multiple results
-    // from lookup(). There will be zero, one, or two declarations of
-    // the same name.
-    unsigned Match;
-    for (Match = 0; Match != Size; ++Match)
-      if (Array[Match]->getDeclName() == D->getDeclName())
+    // from lookup(). 
+    unsigned FirstMatch;
+    for (FirstMatch = 0; FirstMatch != Size; ++FirstMatch)
+      if (Array[FirstMatch]->getDeclName() == D->getDeclName())
         break;
 
-    if (Match != Size) {
-      // We found another declaration with the same name. If it's also
-      // in the same identifier namespace, update the declaration in
-      // place.
-      Decl::IdentifierNamespace NS = D->getIdentifierNamespace();
-      if (Array[Match]->getIdentifierNamespace() == NS) {
-       Array[Match] = D;
-       return;
-      }
-      if (Match + 1 < Size && Array[Match + 1]->getIdentifierNamespace() == NS) {
-       Array[Match + 1] = D;
-       return;
+    unsigned InsertPos = FirstMatch;
+    if (FirstMatch != Size) {
+      // We found another declaration with the same name. First
+      // determine whether this is a redeclaration of an existing
+      // declaration in this scope, in which case we will replace the
+      // existing declaration.
+      unsigned LastMatch = FirstMatch;
+      for (; LastMatch != Size; ++LastMatch) {
+        if (Array[LastMatch]->getDeclName() != D->getDeclName())
+          break;
+
+        if (isRedeclarationOf(D, Array[LastMatch])) {
+          // D is a redeclaration of an existing element in the
+          // array. Replace that element with D.
+          Array[LastMatch] = D;
+          return;
+        }
       }
 
-      // If there is an existing declaration in the namespace of
-      // ordinary identifiers, then it must precede the tag
-      // declaration for C++ name lookup to operate properly. Therefore,
-      // if our match is an ordinary name and the new name is in the
-      // tag namespace, we'll insert the new declaration after it. 
-      if (Match != Size && (NS == Decl::IDNS_Tag) && 
-         (Array[Match]->getIdentifierNamespace() & Decl::IDNS_Ordinary))
-       ++Match;
+      // [FirstMatch, LastMatch) contains the set of declarations that
+      // have the same name as this declaration. Determine where the
+      // declaration D will be inserted into this range. 
+      if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
+        InsertPos = LastMatch;
+      else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
+        InsertPos = LastMatch - 1;
+      else
+        InsertPos = LastMatch;
     }
        
     if (Size < LookupIsMap - 1) {
       // The new declaration will fit in the array. Insert the new
       // declaration at the position Match in the array. 
-      for (unsigned Idx = Size; Idx > Match; --Idx)
+      for (unsigned Idx = Size; Idx > InsertPos; --Idx)
        Array[Idx] = Array[Idx-1];
       
-      Array[Match] = D;
+      Array[InsertPos] = D;
       LookupPtr.setInt(Size + 1);
       return;
     }
@@ -621,20 +631,37 @@ void DeclContext::insertImpl(NamedDecl *D) {
     delete [] Array;
 
     // Fall through to perform insertion into the map.
-  } 
+    MayBeRedeclaration = false;
+  }
 
   // Insert this declaration into the map.
   StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
   StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
-  unsigned IndexOfD = D->getIdentifierNamespace() & Decl::IDNS_Ordinary? 0 : 1;
+  if (Pos != Map->end()) {
+    if (MayBeRedeclaration) {
+      // Determine if this declaration is actually a redeclaration.
+      for (std::vector<ScopedDecl *>::iterator I = Pos->second.begin(),
+                                            IEnd = Pos->second.end();
+           I != IEnd; ++I) {
+        if (isRedeclarationOf(D, *I)) {
+          // D is a redeclaration of *I. Replace *I with D and we're
+          // done.
+          *I = D;
+          return;
+        }
+      }
+    }
 
-  if (Pos == Map->end()) {
     // Put this declaration into the appropriate slot.
-    TwoNamedDecls Val;
-    Val.Decls[IndexOfD] = D;
-    Val.Decls[!IndexOfD] = 0;
-    Map->insert(std::make_pair(D->getDeclName(),Val)).first;
+    if (D->getIdentifierNamespace() == Decl::IDNS_Tag || Pos->second.empty())
+      Pos->second.push_back(D);
+    else if (Pos->second.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
+      ScopedDecl *TagD = Pos->second.back();
+      Pos->second.back() = D;
+      Pos->second.push_back(TagD);
+    } else
+      Pos->second.push_back(D);
   } else {
-    Pos->second.Decls[IndexOfD] = D;
+    (*Map)[D->getDeclName()].push_back(D);
   }
 }
index 127ddf40783379b5c3be5f9bdc695ca8a6a1d60d..0c25fab4f44a1943c4381a5d33f1699bd9a5a457 100644 (file)
@@ -745,8 +745,8 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
       }
 
       if (!LHS.isInvalid()) {
-        LHS = Actions.ActOnMemberReferenceExpr(LHS.release(), OpLoc, OpKind,
-                                               Tok.getLocation(),
+        LHS = Actions.ActOnMemberReferenceExpr(CurScope, LHS.release(), OpLoc,
+                                               OpKind, Tok.getLocation(),
                                                *Tok.getIdentifierInfo());
       }
       ConsumeToken();
@@ -920,8 +920,9 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
         Comps.back().LocEnd =
           MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
       } else if (Tok.is(tok::r_paren)) {
-        Res = Actions.ActOnBuiltinOffsetOf(StartLoc, TypeLoc, Ty, &Comps[0],
-                                           Comps.size(), ConsumeParen());
+        Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, Ty, 
+                                           &Comps[0], Comps.size(), 
+                                           ConsumeParen());
         break;
       } else {
         // Error occurred.
index 48af5af0a37f3487f708be60f807d609384d19b6..2664c57ee4bba1de979a64690aad0405965de8a9 100644 (file)
@@ -479,7 +479,7 @@ public:
                                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 @@ public:
   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 @@ public:
                                    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,
index 024ca8138a6a9c9b7e0fadffb1fddfee8e266c63..270de5546bcad6aa76c7e1ac3ba67c05ca2228f9 100644 (file)
@@ -106,7 +106,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
       // 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 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
     // 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 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
   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 @@ Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
       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 @@ Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
         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 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
     if (OldReturnType != NewReturnType) {
       Diag(New->getLocation(), diag::err_ovl_diff_return_type);
       Diag(Old->getLocation(), PrevDiag);
+      Redeclaration = true;
       return New;
     }
 
index 8a37bbbe7b4890e91b68ab2a8a66fb7db3e58298..918fd2ac9a78c312633849a2f220177462ea2747 100644 (file)
@@ -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 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
     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 @@ Sema::PerformInitializationByConstructor(QualType ClassType,
   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()))
index 307e1ad45ee1ca3ee47dfef6f7fd886f45b258b0..4088f443f75f0737dbc98edc1159af88feb5d611 100644 (file)
@@ -1254,7 +1254,7 @@ static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
 }
 
 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 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
     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 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
     // 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 @@ Sema::ExprResult Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtTy *substmt,
   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 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
       
     // 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);
index e18f1437ab6394054bb19e043a1a01aa0379f9a1..eb2e647f0134bf1a58afcca6a3290484219f6e40 100644 (file)
@@ -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 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
                                   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 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
   }
 
   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 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
                                            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:
index 836534951326bb9353b9e10f477415d2e0e4ea45..8463c5d34ba5e6d81b2641fd6eb6c6de32425f6a 100644 (file)
@@ -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 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
     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 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
   //        (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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
   //  (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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
 ///  (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 @@ Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
   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 @@ Sema::BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc,
   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