diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-28 04:47:19 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-28 04:47:19 +0000 |
commit | 3f396029a502fdec8c12d02d8c405d6097d8b417 (patch) | |
tree | abe89843f9207ff7e908675d6a62367922ce7636 | |
parent | 6a6840326e9b4ac8e81a5a212165f33743847ab8 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82967 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.h | 11 |
2 files changed, 52 insertions, 9 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 2acc4e4559..8909d98e24 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(); diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index 17f559870f..898393a9e4 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -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 |