[cfe-commits] r61386 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/AST/DeclBase.cpp lib/Sema/IdentifierResolver.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp

Douglas Gregor dgregor at apple.com
Tue Dec 23 13:05:06 PST 2008


Author: dgregor
Date: Tue Dec 23 15:05:05 2008
New Revision: 61386

URL: http://llvm.org/viewvc/llvm-project?rev=61386&view=rev
Log:
Don't push OverloadedFunctionDecls onto the chain of declarations
attached to an identifier. Instead, all overloaded functions will be
pushed into scope, and we'll synthesize an OverloadedFunctionDecl on
the fly when we need it. 


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Dec 23 15:05:05 2008
@@ -200,6 +200,15 @@
       return true;
   }
 
+  /// declarationReplaces - Determine whether this declaration, if
+  /// known to be well-formed within its context, will replace the
+  /// declaration OldD if introduced into scope. A declaration will
+  /// replace another declaration if, for example, it is a
+  /// redeclaration of the same variable or function, but not if it is
+  /// a declaration of a different kind (function vs. class) or an
+  /// overloaded function.
+  bool declarationReplaces(NamedDecl *OldD) const;
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() >= ScopedFirst && D->getKind() <= ScopedLast;

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Dec 23 15:05:05 2008
@@ -174,6 +174,19 @@
     delete getMultipleDC();
 }
 
+bool ScopedDecl::declarationReplaces(NamedDecl *OldD) const {
+  assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
+    // 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 this->getKind() == OldD->getKind();
+}
+
 //===----------------------------------------------------------------------===//
 // VarDecl Implementation
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Dec 23 15:05:05 2008
@@ -17,6 +17,8 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Type.h"
 #include "llvm/ADT/DenseMap.h"
+#include <algorithm>
+#include <functional>
 #include <vector>
 using namespace clang;
 
@@ -543,19 +545,6 @@
     insertImpl(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;
 
@@ -591,7 +580,7 @@
         if (Array[LastMatch]->getDeclName() != D->getDeclName())
           break;
 
-        if (isRedeclarationOf(D, Array[LastMatch])) {
+        if (D->declarationReplaces(Array[LastMatch])) {
           // D is a redeclaration of an existing element in the
           // array. Replace that element with D.
           Array[LastMatch] = D;
@@ -640,15 +629,13 @@
   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;
-        }
+      std::vector<ScopedDecl *>::iterator Redecl
+        = std::find_if(Pos->second.begin(), Pos->second.end(),
+                     std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces),
+                                  D));
+      if (Redecl != Pos->second.end()) {
+        *Redecl = D;
+        return;
       }
     }
 

Modified: cfe/trunk/lib/Sema/IdentifierResolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.h?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.h (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.h Tue Dec 23 15:05:05 2008
@@ -128,6 +128,13 @@
   /// It will walk or not the parent declaration contexts depending on how
   /// it was instantiated.
   class iterator {
+  public:
+    typedef NamedDecl *             value_type;
+    typedef NamedDecl *             reference;
+    typedef NamedDecl *             pointer;
+    typedef std::input_iterator_tag iterator_category;
+    typedef std::ptrdiff_t          difference_type;
+
     /// Ptr - There are 3 forms that 'Ptr' represents:
     /// 1) A single NamedDecl. (Ptr & 0x1 == 0)
     /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 23 15:05:05 2008
@@ -26,6 +26,8 @@
 #include "clang/Lex/HeaderSearch.h" 
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+#include <functional>
 
 using namespace clang;
 
@@ -93,6 +95,12 @@
 void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
   S->AddDecl(D);
 
+  // Add scoped declarations into their context, so that they can be
+  // found later. Declarations without a context won't be inserted
+  // into any context.
+  if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
+    CurContext->addDecl(Context, SD);
+
   // C++ [basic.scope]p4:
   //   -- exactly one declaration shall declare a class name or
   //   enumeration name that is not a typedef name and the other
@@ -105,74 +113,56 @@
       // We're pushing the tag into the current context, which might
       // require some reshuffling in the identifier resolver.
       IdentifierResolver::iterator
-        I = IdResolver.begin(TD->getIdentifier(), CurContext, 
-                             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,
-       // so swap the order on the shadowed declaration chain.
-       IdResolver.AddShadowedDecl(TD, *I);
-
-       // Add this declaration to the current context.
-       CurContext->addDecl(Context, TD);
-       
-       return;
+        I = IdResolver.begin(TD->getDeclName(), CurContext, 
+                             false/*LookInParentCtx*/),
+        IEnd = IdResolver.end();
+      if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
+        NamedDecl *PrevDecl = *I;
+        for (; I != IEnd && isDeclInScope(*I, CurContext, S); 
+             PrevDecl = *I, ++I) {
+          if (TD->declarationReplaces(*I)) {
+            // This is a redeclaration. Remove it from the chain and
+            // break out, so that we'll add in the shadowed
+            // declaration.
+            S->RemoveDecl(*I);
+            if (PrevDecl == *I) {
+              IdResolver.RemoveDecl(*I);
+              IdResolver.AddDecl(TD);
+              return;
+            } else {
+              IdResolver.RemoveDecl(*I);
+              break;
+            }
+          }
+        }
+
+        // There is already a declaration with the same name in the same
+        // scope, which is not a tag declaration. It must be found
+        // before we find the new declaration, so insert the new
+        // declaration at the end of the chain.
+        IdResolver.AddShadowedDecl(TD, PrevDecl);
+        
+        return;
       }
     }
   } else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
     // We are pushing the name of a function, which might be an
     // overloaded name.
     FunctionDecl *FD = cast<FunctionDecl>(D);
-    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);
-        
-          // Add the name binding for the OverloadedFunctionDecl.
-          IdResolver.AddDecl(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;      
-      }
+    IdentifierResolver::iterator Redecl
+      = std::find_if(IdResolver.begin(FD->getDeclName(), CurContext, 
+                                      false/*LookInParentCtx*/),
+                     IdResolver.end(),
+                     std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces),
+                                  FD));
+    if (Redecl != IdResolver.end()) {
+      // There is already a declaration of a function on our
+      // IdResolver chain. Replace it with this declaration.
+      S->RemoveDecl(*Redecl);
+      IdResolver.RemoveDecl(*Redecl);
     }
   }
 
-  // Add scoped declarations into their context, so that they can be
-  // found later. Declarations without a context won't be inserted
-  // into any context.
-  if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
-    CurContext->addDecl(Context, SD);
-
   IdResolver.AddDecl(D);
 }
 
@@ -217,10 +207,10 @@
 /// probably be able to return multiple results, to deal with cases of
 /// ambiguity and overloaded functions without needing to create a
 /// Decl node.
+template<typename DeclIterator>
 static Decl *
-MaybeConstructOverloadSet(ASTContext &Context, const DeclContext *DC,
-                          DeclContext::lookup_const_iterator I,
-                          DeclContext::lookup_const_iterator IEnd) {
+MaybeConstructOverloadSet(ASTContext &Context, 
+                          DeclIterator I, DeclIterator IEnd) {
   assert(I != IEnd && "Iterator range cannot be empty");
   assert(!isa<OverloadedFunctionDecl>(*I) && 
          "Cannot have an overloaded function");
@@ -228,7 +218,7 @@
   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;
+    DeclIterator Last = I;
     OverloadedFunctionDecl *Ovl = 0;
     for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
       if (!Ovl) {
@@ -236,7 +226,7 @@
         // stop building the declarations for these overload sets, so
         // there will be nothing to leak.
         Ovl = OverloadedFunctionDecl::Create(Context, 
-                                             const_cast<DeclContext *>(DC), 
+                                         cast<ScopedDecl>(*I)->getDeclContext(),
                                              (*I)->getDeclName());
         Ovl->addOverload(cast<FunctionDecl>(*I));
       }
@@ -285,7 +275,7 @@
     DeclContext::lookup_const_iterator I, E;
     for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
       if ((*I)->getIdentifierNamespace() & NS)
-        return MaybeConstructOverloadSet(Context, LookupCtx, I, E);
+        return MaybeConstructOverloadSet(Context, I, E);
   } else {
     // Name lookup for ordinary names and tag names in C++ requires
     // looking into scopes that aren't strictly lexical, and
@@ -297,9 +287,21 @@
     for (; S; S = S->getParent()) {
       // Check whether the IdResolver has anything in this scope.
       // FIXME: The isDeclScope check could be expensive. Can we do better?
-      for (; I != IEnd && S->isDeclScope(*I); ++I)
-        if ((*I)->getIdentifierNamespace() & NS)
-          return *I;
+      for (; I != IEnd && S->isDeclScope(*I); ++I) {
+        if ((*I)->getIdentifierNamespace() & NS) {
+          // We found something. Look for anything else in our scope
+          // with this same name and in an acceptable identifier
+          // namespace, so that we can construct an overload set if we
+          // need to.
+          IdentifierResolver::iterator LastI = I;
+          for (++LastI; LastI != IEnd; ++LastI) {
+            if (((*LastI)->getIdentifierNamespace() & NS) == 0 ||
+                !S->isDeclScope(*LastI))
+              break;
+          }
+          return MaybeConstructOverloadSet(Context, I, LastI);
+        }
+      }
       
       // If there is an entity associated with this scope, it's a
       // DeclContext. We might need to perform qualified lookup into
@@ -313,7 +315,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 MaybeConstructOverloadSet(Context, LookupCtx, I, E);
+            return MaybeConstructOverloadSet(Context, I, E);
         }
         
         Ctx = Ctx->getParent();
@@ -652,6 +654,8 @@
   bool VDIsTentative = isTentativeDefinition(VD);
   bool VDIsIncompleteArray = VD->getType()->isIncompleteArrayType();
   
+  // FIXME: I don't 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*/), 
@@ -1132,7 +1136,7 @@
       assert(DC->isCXXRecord() &&
              "Constructors can only be declared in a member context");
 
-      bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC);
+      InvalidDecl = InvalidDecl || CheckConstructorDeclarator(D, R, SC);
 
       // Create the new declaration
       NewFD = CXXConstructorDecl::Create(Context, 
@@ -1141,12 +1145,12 @@
                                          isExplicit, isInline,
                                          /*isImplicitlyDeclared=*/false);
 
-      if (isInvalidDecl)
+      if (InvalidDecl)
         NewFD->setInvalidDecl();
     } else if (D.getKind() == Declarator::DK_Destructor) {
       // This is a C++ destructor declaration.
       if (DC->isCXXRecord()) {
-        bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);
+        InvalidDecl = InvalidDecl || CheckDestructorDeclarator(D, R, SC);
 
         NewFD = CXXDestructorDecl::Create(Context,
                                           cast<CXXRecordDecl>(DC),
@@ -1154,16 +1158,18 @@
                                           isInline,
                                           /*isImplicitlyDeclared=*/false);
 
-        if (isInvalidDecl)
+        if (InvalidDecl)
           NewFD->setInvalidDecl();
       } else {
         Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
+
         // Create a FunctionDecl to satisfy the function definition parsing
         // code path.
         NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
                                      Name, R, SC, isInline, LastDeclarator,
                                      // FIXME: Move to DeclGroup...
                                    D.getDeclSpec().getSourceRange().getBegin());
+        InvalidDecl = true;
         NewFD->setInvalidDecl();
       }
     } else if (D.getKind() == Declarator::DK_Conversion) {
@@ -1172,14 +1178,14 @@
              diag::err_conv_function_not_member);
         return 0;
       } else {
-        bool isInvalidDecl = CheckConversionDeclarator(D, R, SC);
+        InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
 
         NewFD = CXXConversionDecl::Create(Context, 
                                           cast<CXXRecordDecl>(DC),
                                           D.getIdentifierLoc(), Name, R,
                                           isInline, isExplicit);
         
-        if (isInvalidDecl)
+        if (InvalidDecl)
           NewFD->setInvalidDecl();
       }
     } else if (DC->isCXXRecord()) {
@@ -1316,48 +1322,14 @@
         if (Redeclaration) {
           NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
 
-          if (OldDecl == PrevDecl) {
-            // Remove the name binding for the previous
-            // declaration.
-           if (S->isDeclScope(PrevDecl)) {
-             IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
-             S->RemoveDecl(PrevDecl);
-           }
-
-           // Introduce the new binding for this declaration.
-           IdResolver.AddDecl(NewFD);
-           if (getLangOptions().CPlusPlus && NewFD->getParent())
-             NewFD->getParent()->insert(Context, NewFD);
-
-           // Add the redeclaration to the current scope, since we'll
-           // be skipping PushOnScopeChains.
-           S->AddDecl(NewFD);
-          } else {
-            // We need to update the OverloadedFunctionDecl with the
-            // latest declaration of this function, so that name
-            // lookup will always refer to the latest declaration of
-            // this function.
-            *MatchedDecl = NewFD;
-         }
-           
-          if (getLangOptions().CPlusPlus) {
-            // Add this declaration to the current context.
-            CurContext->addDecl(Context, NewFD, false);
-
-            // Check default arguments now that we have merged decls.
-            CheckCXXDefaultArguments(NewFD);
-
-            // An out-of-line member function declaration must also be a
-            // definition (C++ [dcl.meaning]p1).
-            if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
-                !InvalidDecl) {
-              Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
-                << D.getCXXScopeSpec().getRange();
-              NewFD->setInvalidDecl();
-            }
+          // An out-of-line member function declaration must also be a
+          // definition (C++ [dcl.meaning]p1).
+          if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
+              !InvalidDecl) {
+            Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
+              << D.getCXXScopeSpec().getRange();
+            NewFD->setInvalidDecl();
           }
-
-         return NewFD;
         }
       }
 
@@ -1417,7 +1389,7 @@
 
       // An out-of-line member function declaration must also be a
       // definition (C++ [dcl.meaning]p1).
-      if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet()) {
+      if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() && !InvalidDecl) {
         Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
           << D.getCXXScopeSpec().getRange();
         InvalidDecl = true;

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Dec 23 15:05:05 2008
@@ -515,26 +515,15 @@
   DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
 
   // Check if this function is already declared.
-  IdentifierResolver::iterator I = IdResolver.begin(Name, GlobalCtx,
-                                                    /*CheckParent=*/false);
-
-  if (I != IdResolver.end()) {
-    NamedDecl *Decl = *I;
-    if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(Decl)) {
-      // The return type fits. This is checked when the function is declared.
-      if (Fn->getNumParams() == 1 &&
-          Context.getCanonicalType(Fn->getParamDecl(0)->getType()) == Argument)
+  {
+    DeclContext::decl_iterator Alloc, AllocEnd;
+    for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Context, Name);
+         Alloc != AllocEnd; ++Alloc) {
+      // FIXME: Do we need to check for default arguments here?
+      FunctionDecl *Func = cast<FunctionDecl>(*Alloc);
+      if (Func->getNumParams() == 1 &&
+          Context.getCanonicalType(Func->getParamDecl(0)->getType()) == Argument)
         return;
-    } else if(OverloadedFunctionDecl *Ovl =
-                  dyn_cast<OverloadedFunctionDecl>(Decl)) {
-      for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
-                                                     FEnd = Ovl->function_end();
-               F != FEnd; ++F) {
-        if ((*F)->getNumParams() == 1 &&
-            Context.getCanonicalType((*F)->getParamDecl(0)->getType())
-                == Argument)
-          return;
-      }
     }
   }
 
@@ -548,6 +537,9 @@
                                            0, Argument, VarDecl::None, 0, 0);
   Alloc->setParams(&Param, 1);
 
+  // FIXME: Also add this declaration to the IdentifierResolver, but
+  // make sure it is at the end of the chain to coincide with the
+  // global scope.
   ((DeclContext *)TUScope->getEntity())->addDecl(Context, Alloc);
 }
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=61386&r1=61385&r2=61386&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Dec 23 15:05:05 2008
@@ -2160,10 +2160,10 @@
   //        of type T2 or “reference to (possibly cv-qualified) T2”,
   //        when T2 is an enumeration type, are candidate functions.
   {
-    NamedDecl *NonMemberOps = 0;
-    for (IdentifierResolver::iterator I 
-           = IdResolver.begin(OpName, CurContext, true/*LookInParentCtx*/);
-         I != IdResolver.end(); ++I) {
+    IdentifierResolver::iterator
+      I = IdResolver.begin(OpName, CurContext, true/*LookInParentCtx*/),
+      IEnd = IdResolver.end();
+    for (; I != IEnd; ++I) {
       // We don't need to check the identifier namespace, because
       // operator names can only be ordinary identifiers.
 
@@ -2174,22 +2174,20 @@
       } 
 
       // We found something with this name. We're done.
-      NonMemberOps = *I;
       break;
     }
 
-    if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NonMemberOps)) {
-      if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
-        AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
-                             /*SuppressUserConversions=*/false);
-    } else if (OverloadedFunctionDecl *Ovl
-                 = dyn_cast_or_null<OverloadedFunctionDecl>(NonMemberOps)) {
-      for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
-                                                  FEnd = Ovl->function_end();
-           F != FEnd; ++F) {
-        if (IsAcceptableNonMemberOperatorCandidate(*F, T1, T2, Context)) 
-          AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, 
-                               /*SuppressUserConversions=*/false);
+    if (I != IEnd && isa<ScopedDecl>(*I)) {
+      ScopedDecl *FirstDecl = cast<ScopedDecl>(*I);
+      for (; I != IEnd; ++I) {
+        ScopedDecl *SD = cast<ScopedDecl>(*I);
+        if (FirstDecl->getDeclContext() != SD->getDeclContext())
+          break;
+
+        if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
+          if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
+            AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
+                                 /*SuppressUserConversions=*/false);
       }
     }
   }





More information about the cfe-commits mailing list