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.

llvm-svn: 82967
This commit is contained in:
Douglas Gregor 2009-09-28 04:47:19 +00:00
parent 16787bda38
commit 5b0f2a2fbe
2 changed files with 52 additions and 9 deletions

View File

@ -2186,6 +2186,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// argument doesn't participate in overload resolution.
}
if (!CandidateSet.isNewCandidate(Function))
return;
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
@ -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();

View 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