Replace "failed template argument deduction" diagnostic with something useful

in the one case where we've already factored out a reason code.

llvm-svn: 174036
This commit is contained in:
Richard Smith 2013-01-31 04:03:12 +00:00
parent b0944392aa
commit 8c6eeb9599
6 changed files with 54 additions and 8 deletions

View File

@ -2331,6 +2331,9 @@ def note_ovl_candidate_substitution_failure : Note<
"candidate template ignored: substitution failure%0%1">;
def note_ovl_candidate_disabled_by_enable_if : Note<
"candidate template ignored: disabled by %0%1">;
def note_ovl_candidate_failed_overload_resolution : Note<
"candidate template ignored: couldn't resolve reference to overloaded "
"function %0">;
// Note that we don't treat templates differently for this diagnostic.
def note_ovl_candidate_arity : Note<"candidate "

View File

@ -694,6 +694,10 @@ namespace clang {
/// \brief Return the second template argument this deduction failure
/// refers to, if any.
const TemplateArgument *getSecondArg();
/// \brief Return the expression this deduction failure refers to,
/// if any.
Expr *getExpr();
/// \brief Free any memory associated with this deduction failure.
void Destroy();

View File

@ -47,7 +47,7 @@ class TemplateDeductionInfo {
public:
TemplateDeductionInfo(SourceLocation Loc)
: Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { }
: Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { }
/// \brief Returns the location at which template argument is
/// occurring.
@ -150,6 +150,13 @@ public:
///
/// FIXME: Finish documenting this.
TemplateArgument SecondArg;
/// \brief The expression which caused a deduction failure.
///
/// TDK_FailedOverloadResolution: this argument is the reference to
// an overloaded function which could not be resolved to a specific
// function.
Expr *Expression;
};
}

View File

@ -588,8 +588,11 @@ static MakeDeductionFailureInfo(ASTContext &Context,
}
break;
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
Result.Data = Info.Expression;
break;
case Sema::TDK_NonDeducedMismatch:
break;
}
@ -741,6 +744,15 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
return 0;
}
Expr *
OverloadCandidate::DeductionFailureInfo::getExpr() {
if (static_cast<Sema::TemplateDeductionResult>(Result) ==
Sema::TDK_FailedOverloadResolution)
return static_cast<Expr*>(Data);
return 0;
}
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
@ -8442,10 +8454,18 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
return;
}
case Sema::TDK_FailedOverloadResolution: {
OverloadExpr::FindResult R =
OverloadExpr::find(Cand->DeductionFailure.getExpr());
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_failed_overload_resolution)
<< R.Expression->getName();
return;
}
// TODO: diagnose these individually, then kill off
// note_ovl_candidate_bad_deduction, which is uselessly vague.
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
MaybeEmitInheritedConstructorNote(S, Fn);
return;

View File

@ -2879,7 +2879,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
/// described in C++ [temp.deduct.call].
///
/// \returns true if the caller should not attempt to perform any template
/// argument deduction based on this P/A pair.
/// argument deduction based on this P/A pair because the argument is an
/// overloaded function set that could not be resolved.
static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
TemplateParameterList *TemplateParams,
QualType &ParamType,
@ -2895,7 +2896,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
if (ParamRefType) {
QualType PointeeType = ParamRefType->getPointeeType();
// If the argument has incomplete array type, try to complete it's type.
// If the argument has incomplete array type, try to complete its type.
if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
ArgType = Arg->getType();
@ -2993,8 +2994,8 @@ static bool hasDeducibleTemplateParameters(Sema &S,
/// \brief Perform template argument deduction by matching a parameter type
/// against a single expression, where the expression is an element of
/// an initializer list that was originally matched against the argument
/// type.
/// an initializer list that was originally matched against a parameter
/// of type \c initializer_list\<ParamType\>.
static Sema::TemplateDeductionResult
DeduceTemplateArgumentByListElement(Sema &S,
TemplateParameterList *TemplateParams,
@ -3023,8 +3024,10 @@ DeduceTemplateArgumentByListElement(Sema &S,
// For all other cases, just match by type.
QualType ArgType = Arg->getType();
if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
ArgType, Arg, TDF))
ArgType, Arg, TDF)) {
Info.Expression = Arg;
return Sema::TDK_FailedOverloadResolution;
}
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
}

View File

@ -199,3 +199,12 @@ namespace initlist_of_array {
f({{1,2},{3,4}});
}
}
namespace init_list_deduction_failure {
void f();
void f(int);
template<typename T> void g(std::initializer_list<T>);
// expected-note@-1 {{candidate template ignored: couldn't resolve reference to overloaded function 'f'}}
void h() { g({f}); }
// expected-error@-1 {{no matching function for call to 'g'}}
}