[cfe-commits] r82967 - in /cfe/trunk/lib/Sema: SemaOverload.cpp SemaOverload.h

Douglas Gregor dgregor at apple.com
Sun Sep 27 21:47:19 PDT 2009


Author: dgregor
Date: Sun Sep 27 23:47:19 2009
New Revision: 82967

URL: http://llvm.org/viewvc/llvm-project?rev=82967&view=rev
Log:
Don't allow the same function to enter the overload candidate set
multiple times. This requires to be more careful about re-adding
candidates cached from the function template definition.

Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaOverload.h

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Sep 27 23:47:19 2009
@@ -2186,7 +2186,9 @@
     // argument doesn't participate in overload resolution.
   }
 
-
+  if (!CandidateSet.isNewCandidate(Function))
+    return;
+    
   // Add this candidate
   CandidateSet.push_back(OverloadCandidate());
   OverloadCandidate& Candidate = CandidateSet.back();
@@ -2256,14 +2258,29 @@
   for (FunctionSet::const_iterator F = Functions.begin(),
                                 FEnd = Functions.end();
        F != FEnd; ++F) {
-    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F))
-      AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
-                           SuppressUserConversions);
-    else
-      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F),
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) {
+      if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
+        AddMethodCandidate(cast<CXXMethodDecl>(FD),
+                           Args[0], Args + 1, NumArgs - 1, 
+                           CandidateSet, SuppressUserConversions);
+      else
+        AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
+                             SuppressUserConversions);
+    } else {
+      FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*F);
+      if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
+          !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
+        AddMethodTemplateCandidate(FunTmpl,
                                    /*FIXME: explicit args */false, 0, 0,
-                                   Args, NumArgs, CandidateSet,
+                                   Args[0], Args + 1, NumArgs - 1,
+                                   CandidateSet,
                                    SuppressUserConversions);
+      else
+        AddTemplateOverloadCandidate(FunTmpl,
+                                     /*FIXME: explicit args */false, 0, 0,
+                                     Args, NumArgs, CandidateSet,
+                                     SuppressUserConversions);
+    }
   }
 }
 
@@ -2289,6 +2306,9 @@
   assert(!isa<CXXConstructorDecl>(Method) &&
          "Use AddOverloadCandidate for constructors");
 
+  if (!CandidateSet.isNewCandidate(Method))
+    return;
+
   // Add this candidate
   CandidateSet.push_back(OverloadCandidate());
   OverloadCandidate& Candidate = CandidateSet.back();
@@ -2375,6 +2395,9 @@
                                  OverloadCandidateSet& CandidateSet,
                                  bool SuppressUserConversions,
                                  bool ForceRValue) {
+  if (!CandidateSet.isNewCandidate(MethodTmpl))
+    return;
+
   // C++ [over.match.funcs]p7:
   //   In each case where a candidate is a function template, candidate
   //   function template specializations are generated using template argument
@@ -2417,6 +2440,9 @@
                                    OverloadCandidateSet& CandidateSet,
                                    bool SuppressUserConversions,
                                    bool ForceRValue) {
+  if (!CandidateSet.isNewCandidate(FunctionTemplate))
+    return;
+
   // C++ [over.match.funcs]p7:
   //   In each case where a candidate is a function template, candidate
   //   function template specializations are generated using template argument
@@ -2458,6 +2484,9 @@
   assert(!Conversion->getDescribedFunctionTemplate() &&
          "Conversion function templates use AddTemplateConversionCandidate");
 
+  if (!CandidateSet.isNewCandidate(Conversion))
+    return;
+
   // Add this candidate
   CandidateSet.push_back(OverloadCandidate());
   OverloadCandidate& Candidate = CandidateSet.back();
@@ -2538,6 +2567,9 @@
   assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
          "Only conversion function templates permitted here");
 
+  if (!CandidateSet.isNewCandidate(FunctionTemplate))
+    return;
+
   TemplateDeductionInfo Info(Context);
   CXXConversionDecl *Specialization = 0;
   if (TemplateDeductionResult Result
@@ -2564,6 +2596,9 @@
                                  const FunctionProtoType *Proto,
                                  Expr *Object, Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet) {
+  if (!CandidateSet.isNewCandidate(Conversion))
+    return;
+
   CandidateSet.push_back(OverloadCandidate());
   OverloadCandidate& Candidate = CandidateSet.back();
   Candidate.Function = 0;
@@ -2649,7 +2684,6 @@
                                  Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet,
                                  SourceRange OpRange) {
-
   FunctionSet Functions;
 
   QualType T1 = Args[0]->getType();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Sun Sep 27 23:47:19 2009
@@ -261,7 +261,16 @@
 
   /// OverloadCandidateSet - A set of overload candidates, used in C++
   /// overload resolution (C++ 13.3).
-  typedef llvm::SmallVector<OverloadCandidate, 16> OverloadCandidateSet;
+  class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> {
+    llvm::SmallPtrSet<Decl *, 16> Functions;
+    
+  public:
+    /// \brief Determine when this overload candidate will be new to the
+    /// overload set.
+    bool isNewCandidate(Decl *F) { 
+      return Functions.insert(F->getCanonicalDecl()); 
+    }
+  };
 } // end namespace clang
 
 #endif // LLVM_CLANG_SEMA_OVERLOAD_H





More information about the cfe-commits mailing list