summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp157
1 files changed, 136 insertions, 21 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index f21b38a649..ada1a2b432 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1302,6 +1302,19 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType)
FromType.getUnqualifiedType() == ToType.getUnqualifiedType();
}
+/// \brief Given a function template or function, extract the function template
+/// declaration (if any) and the underlying function declaration.
+template<typename T>
+static void GetFunctionAndTemplate(AnyFunctionDecl Orig, T *&Function,
+ FunctionTemplateDecl *&FunctionTemplate) {
+ FunctionTemplate = dyn_cast<FunctionTemplateDecl>(Orig);
+ if (FunctionTemplate)
+ Function = cast<T>(FunctionTemplate->getTemplatedDecl());
+ else
+ Function = cast<T>(Orig);
+}
+
+
/// Determines whether there is a user-defined conversion sequence
/// (C++ [over.ics.user]) that converts expression From to the type
/// ToType. If such a conversion exists, User will contain the
@@ -1381,9 +1394,21 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
for (OverloadedFunctionDecl::function_iterator Func
= Conversions->function_begin();
Func != Conversions->function_end(); ++Func) {
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
- if (AllowExplicit || !Conv->isExplicit())
- AddConversionCandidate(Conv, From, ToType, CandidateSet);
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
+ if (ConvTemplate)
+ Conv = dyn_cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = dyn_cast<CXXConversionDecl>(*Func);
+
+ if (AllowExplicit || !Conv->isExplicit()) {
+ if (ConvTemplate)
+ AddTemplateConversionCandidate(ConvTemplate, From, ToType,
+ CandidateSet);
+ else
+ AddConversionCandidate(Conv, From, ToType, CandidateSet);
+ }
}
}
}
@@ -2295,9 +2320,9 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
CandidateSet, SuppressUserConversions, ForceRValue);
}
-/// \brief Add a C++ function template as a candidate in the candidate set,
-/// using template argument deduction to produce an appropriate function
-/// template specialization.
+/// \brief Add a C++ function template specialization as a candidate
+/// in the candidate set, using template argument deduction to produce
+/// an appropriate function template specialization.
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
@@ -2345,6 +2370,9 @@ void
Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet) {
+ assert(!Conversion->getDescribedFunctionTemplate() &&
+ "Conversion function templates use AddTemplateConversionCandidate");
+
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
@@ -2404,6 +2432,35 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
}
}
+/// \brief Adds a conversion function template specialization
+/// candidate to the overload set, using template argument deduction
+/// to deduce the template arguments of the conversion function
+/// template from the type that we are converting to (C++
+/// [temp.deduct.conv]).
+void
+Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet) {
+ assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
+ "Only conversion function templates permitted here");
+
+ TemplateDeductionInfo Info(Context);
+ CXXConversionDecl *Specialization = 0;
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, ToType,
+ Specialization, Info)) {
+ // FIXME: Record what happened with template argument deduction, so
+ // that we can give the user a beautiful diagnostic.
+ (void)Result;
+ return;
+ }
+
+ // Add the conversion function template specialization produced by
+ // template argument deduction as a candidate.
+ assert(Specialization && "Missing function template specialization?");
+ AddConversionCandidate(Specialization, From, ToType, CandidateSet);
+}
+
/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
/// converts the given @c Object to a function pointer via the
/// conversion function @c Conversion, and then attempts to call it
@@ -2801,7 +2858,15 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
for (OverloadedFunctionDecl::function_iterator Func
= Conversions->function_begin();
Func != Conversions->function_end(); ++Func) {
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
+
+ // Skip conversion function templates; they don't tell us anything
+ // about which builtin types we can convert to.
+ if (ConvTemplate)
+ continue;
+
if (AllowExplicitConversions || !Conv->isExplicit())
AddTypesConvertedFrom(Conv->getConversionType(), false, false);
}
@@ -3543,8 +3608,11 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
// if not that,
if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
Cand2.Function && Cand2.Function->getPrimaryTemplate())
- // FIXME: Implement partial ordering of function templates.
- Diag(SourceLocation(), diag::unsup_function_template_partial_ordering);
+ if (FunctionTemplateDecl *BetterTemplate
+ = getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
+ Cand2.Function->getPrimaryTemplate(),
+ true))
+ return BetterTemplate == Cand1.Function->getPrimaryTemplate();
// -- the context is an initialization by user-defined conversion
// (see 8.5, 13.3.1.5) and the standard conversion sequence
@@ -3842,21 +3910,61 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// C++ [over.over]p4:
// If more than one function is selected, [...]
llvm::SmallVector<FunctionDecl *, 4> RemainingMatches;
+ typedef llvm::SmallPtrSet<FunctionDecl *, 4>::iterator MatchIter;
if (FoundNonTemplateFunction) {
- // [...] any function template specializations in the set are eliminated
- // if the set also contains a non-template function, [...]
- for (llvm::SmallPtrSet<FunctionDecl *, 4>::iterator M = Matches.begin(),
- MEnd = Matches.end();
- M != MEnd; ++M)
+ // [...] any function template specializations in the set are
+ // eliminated if the set also contains a non-template function, [...]
+ for (MatchIter M = Matches.begin(), MEnd = Matches.end(); M != MEnd; ++M)
if ((*M)->getPrimaryTemplate() == 0)
RemainingMatches.push_back(*M);
} else {
- // [...] and any given function template specialization F1 is eliminated
- // if the set contains a second function template specialization whose
- // function template is more specialized than the function template of F1
- // according to the partial ordering rules of 14.5.5.2.
- // FIXME: Implement this!
- RemainingMatches.append(Matches.begin(), Matches.end());
+ // [...] and any given function template specialization F1 is
+ // eliminated if the set contains a second function template
+ // specialization whose function template is more specialized
+ // than the function template of F1 according to the partial
+ // ordering rules of 14.5.5.2.
+
+ // The algorithm specified above is quadratic. We instead use a
+ // two-pass algorithm (similar to the one used to identify the
+ // best viable function in an overload set) that identifies the
+ // best function template (if it exists).
+ MatchIter Best = Matches.begin();
+ MatchIter M = Best, MEnd = Matches.end();
+ // Find the most specialized function.
+ for (++M; M != MEnd; ++M)
+ if (getMoreSpecializedTemplate((*M)->getPrimaryTemplate(),
+ (*Best)->getPrimaryTemplate(),
+ false)
+ == (*M)->getPrimaryTemplate())
+ Best = M;
+
+ // Determine whether this function template is more specialized
+ // that all of the others.
+ bool Ambiguous = false;
+ for (M = Matches.begin(); M != MEnd; ++M) {
+ if (M != Best &&
+ getMoreSpecializedTemplate((*M)->getPrimaryTemplate(),
+ (*Best)->getPrimaryTemplate(),
+ false)
+ != (*Best)->getPrimaryTemplate()) {
+ Ambiguous = true;
+ break;
+ }
+ }
+
+ // If one function template was more specialized than all of the
+ // others, return it.
+ if (!Ambiguous)
+ return *Best;
+
+ // We could not find a most-specialized function template, which
+ // is equivalent to having a set of function templates with more
+ // than one such template. So, we place all of the function
+ // templates into the set of remaining matches and produce a
+ // diagnostic below. FIXME: we could perform the quadratic
+ // algorithm here, pruning the result set to limit the number of
+ // candidates output later.
+ RemainingMatches.append(Matches.begin(), Matches.end());
}
// [...] After such eliminations, if any, there shall remain exactly one
@@ -4468,7 +4576,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end();
Func != FuncEnd; ++Func) {
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
+
+ // Skip over templated conversion functions; they aren't
+ // surrogates.
+ if (ConvTemplate)
+ continue;
// Strip the reference type (if any) and then the pointer type (if
// any) to get down to what might be a function type.