]> granicus.if.org Git - clang/commitdiff
Don't allow the same function to enter the overload candidate set
authorDouglas Gregor <dgregor@apple.com>
Mon, 28 Sep 2009 04:47:19 +0000 (04:47 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 28 Sep 2009 04:47:19 +0000 (04:47 +0000)
multiple times. This requires to be more careful about re-adding
candidates cached from the function template definition.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82967 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
lib/Sema/SemaOverload.h

index 2acc4e455924fe913b70aa4c697aa50e017c7387..8909d98e24e32ff760bba90ce08c3282af9c0b25 100644 (file)
@@ -2186,7 +2186,9 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
     // 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 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
   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 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
   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 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
                                  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 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
                                    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 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
   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 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
   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 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
                                  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 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
                                  Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet,
                                  SourceRange OpRange) {
-
   FunctionSet Functions;
 
   QualType T1 = Args[0]->getType();
index 17f559870fdac9d6586391d507faee9dbf185c0a..898393a9e4d962c57264695d1c82cdb8ed99b854 100644 (file)
@@ -261,7 +261,16 @@ namespace clang {
 
   /// 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