aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-28 04:47:19 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-28 04:47:19 +0000
commit3f396029a502fdec8c12d02d8c405d6097d8b417 (patch)
treeabe89843f9207ff7e908675d6a62367922ce7636
parent6a6840326e9b4ac8e81a5a212165f33743847ab8 (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.cpp50
-rw-r--r--lib/Sema/SemaOverload.h11
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