forked from OSchip/llvm-project
FIXME fix: improving diagnostics for template arguments deduction of class templates and explicit specializations
This patch essentially removes all the FIXMEs following calls to DeduceTemplateArguments() that want to keep track of deduction failure info. llvm-svn: 186730
This commit is contained in:
parent
47c0845e0b
commit
98b20f1278
|
@ -22,6 +22,7 @@
|
|||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/UnresolvedSet.h"
|
||||
#include "clang/Sema/SemaFixItUtils.h"
|
||||
#include "clang/Sema/TemplateDeduction.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
@ -656,53 +657,6 @@ namespace clang {
|
|||
/// \brief The number of call arguments that were explicitly provided,
|
||||
/// to be used while performing partial ordering of function templates.
|
||||
unsigned ExplicitCallArguments;
|
||||
|
||||
/// A structure used to record information about a failed
|
||||
/// template argument deduction.
|
||||
struct DeductionFailureInfo {
|
||||
/// A Sema::TemplateDeductionResult.
|
||||
unsigned Result : 8;
|
||||
|
||||
/// \brief Indicates whether a diagnostic is stored in Diagnostic.
|
||||
unsigned HasDiagnostic : 1;
|
||||
|
||||
/// \brief Opaque pointer containing additional data about
|
||||
/// this deduction failure.
|
||||
void *Data;
|
||||
|
||||
/// \brief A diagnostic indicating why deduction failed.
|
||||
union {
|
||||
void *Align;
|
||||
char Diagnostic[sizeof(PartialDiagnosticAt)];
|
||||
};
|
||||
|
||||
/// \brief Retrieve the diagnostic which caused this deduction failure,
|
||||
/// if any.
|
||||
PartialDiagnosticAt *getSFINAEDiagnostic();
|
||||
|
||||
/// \brief Retrieve the template parameter this deduction failure
|
||||
/// refers to, if any.
|
||||
TemplateParameter getTemplateParameter();
|
||||
|
||||
/// \brief Retrieve the template argument list associated with this
|
||||
/// deduction failure, if any.
|
||||
TemplateArgumentList *getTemplateArgumentList();
|
||||
|
||||
/// \brief Return the first template argument this deduction failure
|
||||
/// refers to, if any.
|
||||
const TemplateArgument *getFirstArg();
|
||||
|
||||
/// \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();
|
||||
};
|
||||
|
||||
union {
|
||||
DeductionFailureInfo DeductionFailure;
|
||||
|
|
|
@ -176,6 +176,8 @@ namespace clang {
|
|||
class VisibilityAttr;
|
||||
class VisibleDeclConsumer;
|
||||
class IndirectFieldDecl;
|
||||
struct DeductionFailureInfo;
|
||||
class TemplateSpecCandidateSet;
|
||||
|
||||
namespace sema {
|
||||
class AccessedEntity;
|
||||
|
@ -5773,16 +5775,15 @@ public:
|
|||
SourceLocation Loc,
|
||||
TemplatePartialOrderingContext TPOC,
|
||||
unsigned NumCallArguments);
|
||||
UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
|
||||
UnresolvedSetIterator SEnd,
|
||||
TemplatePartialOrderingContext TPOC,
|
||||
unsigned NumCallArguments,
|
||||
SourceLocation Loc,
|
||||
const PartialDiagnostic &NoneDiag,
|
||||
const PartialDiagnostic &AmbigDiag,
|
||||
const PartialDiagnostic &CandidateDiag,
|
||||
bool Complain = true,
|
||||
QualType TargetType = QualType());
|
||||
UnresolvedSetIterator
|
||||
getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
|
||||
TemplateSpecCandidateSet &FailedCandidates,
|
||||
TemplatePartialOrderingContext TPOC,
|
||||
unsigned NumCallArguments, SourceLocation Loc,
|
||||
const PartialDiagnostic &NoneDiag,
|
||||
const PartialDiagnostic &AmbigDiag,
|
||||
const PartialDiagnostic &CandidateDiag,
|
||||
bool Complain = true, QualType TargetType = QualType());
|
||||
|
||||
ClassTemplatePartialSpecializationDecl *
|
||||
getMoreSpecializedPartialSpecialization(
|
||||
|
@ -7744,6 +7745,10 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
DeductionFailureInfo
|
||||
MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK,
|
||||
sema::TemplateDeductionInfo &Info);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
namespace clang {
|
||||
|
||||
class TemplateArgumentList;
|
||||
class Sema;
|
||||
|
||||
namespace sema {
|
||||
|
||||
|
@ -162,7 +163,124 @@ public:
|
|||
Expr *Expression;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // end namespace sema
|
||||
|
||||
/// A structure used to record information about a failed
|
||||
/// template argument deduction, for diagnosis.
|
||||
struct DeductionFailureInfo {
|
||||
/// A Sema::TemplateDeductionResult.
|
||||
unsigned Result : 8;
|
||||
|
||||
/// \brief Indicates whether a diagnostic is stored in Diagnostic.
|
||||
unsigned HasDiagnostic : 1;
|
||||
|
||||
/// \brief Opaque pointer containing additional data about
|
||||
/// this deduction failure.
|
||||
void *Data;
|
||||
|
||||
/// \brief A diagnostic indicating why deduction failed.
|
||||
union {
|
||||
void *Align;
|
||||
char Diagnostic[sizeof(PartialDiagnosticAt)];
|
||||
};
|
||||
|
||||
/// \brief Retrieve the diagnostic which caused this deduction failure,
|
||||
/// if any.
|
||||
PartialDiagnosticAt *getSFINAEDiagnostic();
|
||||
|
||||
/// \brief Retrieve the template parameter this deduction failure
|
||||
/// refers to, if any.
|
||||
TemplateParameter getTemplateParameter();
|
||||
|
||||
/// \brief Retrieve the template argument list associated with this
|
||||
/// deduction failure, if any.
|
||||
TemplateArgumentList *getTemplateArgumentList();
|
||||
|
||||
/// \brief Return the first template argument this deduction failure
|
||||
/// refers to, if any.
|
||||
const TemplateArgument *getFirstArg();
|
||||
|
||||
/// \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();
|
||||
};
|
||||
|
||||
/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
|
||||
/// which keeps track of template argument deduction failure info, when
|
||||
/// handling explicit specializations (and instantiations) of templates
|
||||
/// beyond function overloading.
|
||||
/// For now, assume that the candidates are non-matching specializations.
|
||||
/// TODO: In the future, we may need to unify/generalize this with
|
||||
/// OverloadCandidate.
|
||||
struct TemplateSpecCandidate {
|
||||
/// Specialization - The actual specialization that this candidate
|
||||
/// represents. When NULL, this may be a built-in candidate.
|
||||
Decl *Specialization;
|
||||
|
||||
/// Template argument deduction info
|
||||
DeductionFailureInfo DeductionFailure;
|
||||
|
||||
void set(Decl *Spec, DeductionFailureInfo Info) {
|
||||
Specialization = Spec;
|
||||
DeductionFailure = Info;
|
||||
}
|
||||
|
||||
/// Diagnose a template argument deduction failure.
|
||||
void NoteDeductionFailure(Sema &S);
|
||||
};
|
||||
|
||||
/// TemplateSpecCandidateSet - A set of generalized overload candidates,
|
||||
/// used in template specializations.
|
||||
/// TODO: In the future, we may need to unify/generalize this with
|
||||
/// OverloadCandidateSet.
|
||||
class TemplateSpecCandidateSet {
|
||||
SmallVector<TemplateSpecCandidate, 16> Candidates;
|
||||
SourceLocation Loc;
|
||||
|
||||
TemplateSpecCandidateSet(
|
||||
const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
void destroyCandidates();
|
||||
|
||||
public:
|
||||
TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {}
|
||||
~TemplateSpecCandidateSet() { destroyCandidates(); }
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
|
||||
/// \brief Clear out all of the candidates.
|
||||
/// TODO: This may be unnecessary.
|
||||
void clear();
|
||||
|
||||
typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
|
||||
iterator begin() { return Candidates.begin(); }
|
||||
iterator end() { return Candidates.end(); }
|
||||
|
||||
size_t size() const { return Candidates.size(); }
|
||||
bool empty() const { return Candidates.empty(); }
|
||||
|
||||
/// \brief Add a new candidate with NumConversions conversion sequence slots
|
||||
/// to the overload set.
|
||||
TemplateSpecCandidate &addCandidate() {
|
||||
Candidates.push_back(TemplateSpecCandidate());
|
||||
return Candidates.back();
|
||||
}
|
||||
|
||||
void NoteCandidates(Sema &S, SourceLocation Loc);
|
||||
|
||||
void NoteCandidates(Sema &S, SourceLocation Loc) const {
|
||||
const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -548,13 +548,13 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
|
|||
}
|
||||
|
||||
namespace {
|
||||
// Structure used by OverloadCandidate::DeductionFailureInfo to store
|
||||
// Structure used by DeductionFailureInfo to store
|
||||
// template argument information.
|
||||
struct DFIArguments {
|
||||
TemplateArgument FirstArg;
|
||||
TemplateArgument SecondArg;
|
||||
};
|
||||
// Structure used by OverloadCandidate::DeductionFailureInfo to store
|
||||
// Structure used by DeductionFailureInfo to store
|
||||
// template parameter and template argument information.
|
||||
struct DFIParamWithArguments : DFIArguments {
|
||||
TemplateParameter Param;
|
||||
|
@ -563,11 +563,10 @@ namespace {
|
|||
|
||||
/// \brief Convert from Sema's representation of template deduction information
|
||||
/// to the form used in overload-candidate information.
|
||||
OverloadCandidate::DeductionFailureInfo
|
||||
static MakeDeductionFailureInfo(ASTContext &Context,
|
||||
Sema::TemplateDeductionResult TDK,
|
||||
TemplateDeductionInfo &Info) {
|
||||
OverloadCandidate::DeductionFailureInfo Result;
|
||||
DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
|
||||
Sema::TemplateDeductionResult TDK,
|
||||
TemplateDeductionInfo &Info) {
|
||||
DeductionFailureInfo Result;
|
||||
Result.Result = static_cast<unsigned>(TDK);
|
||||
Result.HasDiagnostic = false;
|
||||
Result.Data = 0;
|
||||
|
@ -625,7 +624,7 @@ static MakeDeductionFailureInfo(ASTContext &Context,
|
|||
return Result;
|
||||
}
|
||||
|
||||
void OverloadCandidate::DeductionFailureInfo::Destroy() {
|
||||
void DeductionFailureInfo::Destroy() {
|
||||
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
|
||||
case Sema::TDK_Success:
|
||||
case Sema::TDK_Invalid:
|
||||
|
@ -659,15 +658,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
|
|||
}
|
||||
}
|
||||
|
||||
PartialDiagnosticAt *
|
||||
OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() {
|
||||
PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
|
||||
if (HasDiagnostic)
|
||||
return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TemplateParameter
|
||||
OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
|
||||
TemplateParameter DeductionFailureInfo::getTemplateParameter() {
|
||||
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
|
||||
case Sema::TDK_Success:
|
||||
case Sema::TDK_Invalid:
|
||||
|
@ -695,8 +692,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
|
|||
return TemplateParameter();
|
||||
}
|
||||
|
||||
TemplateArgumentList *
|
||||
OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
|
||||
TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
|
||||
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
|
||||
case Sema::TDK_Success:
|
||||
case Sema::TDK_Invalid:
|
||||
|
@ -722,7 +718,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
|
||||
const TemplateArgument *DeductionFailureInfo::getFirstArg() {
|
||||
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
|
||||
case Sema::TDK_Success:
|
||||
case Sema::TDK_Invalid:
|
||||
|
@ -748,8 +744,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const TemplateArgument *
|
||||
OverloadCandidate::DeductionFailureInfo::getSecondArg() {
|
||||
const TemplateArgument *DeductionFailureInfo::getSecondArg() {
|
||||
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
|
||||
case Sema::TDK_Success:
|
||||
case Sema::TDK_Invalid:
|
||||
|
@ -775,8 +770,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Expr *
|
||||
OverloadCandidate::DeductionFailureInfo::getExpr() {
|
||||
Expr *DeductionFailureInfo::getExpr() {
|
||||
if (static_cast<Sema::TemplateDeductionResult>(Result) ==
|
||||
Sema::TDK_FailedOverloadResolution)
|
||||
return static_cast<Expr*>(Data);
|
||||
|
@ -8128,7 +8122,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
|
|||
return isTemplate ? oc_function_template : oc_function;
|
||||
}
|
||||
|
||||
void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
|
||||
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
|
||||
const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
|
||||
if (!Ctor) return;
|
||||
|
||||
|
@ -8414,30 +8408,52 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
|
|||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
}
|
||||
|
||||
void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
|
||||
unsigned NumFormalArgs) {
|
||||
// TODO: treat calls to a missing default constructor as a special case
|
||||
|
||||
/// Additional arity mismatch diagnosis specific to a function overload
|
||||
/// candidates. This is not covered by the more general DiagnoseArityMismatch()
|
||||
/// over a candidate in any candidate set.
|
||||
bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
|
||||
unsigned NumArgs) {
|
||||
FunctionDecl *Fn = Cand->Function;
|
||||
const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
|
||||
|
||||
unsigned MinParams = Fn->getMinRequiredArguments();
|
||||
|
||||
// With invalid overloaded operators, it's possible that we think we
|
||||
// have an arity mismatch when it fact it looks like we have the
|
||||
// have an arity mismatch when in fact it looks like we have the
|
||||
// right number of arguments, because only overloaded operators have
|
||||
// the weird behavior of overloading member and non-member functions.
|
||||
// Just don't report anything.
|
||||
if (Fn->isInvalidDecl() &&
|
||||
Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (NumArgs < MinParams) {
|
||||
assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
|
||||
(Cand->FailureKind == ovl_fail_bad_deduction &&
|
||||
Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
|
||||
} else {
|
||||
assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
|
||||
(Cand->FailureKind == ovl_fail_bad_deduction &&
|
||||
Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// General arity mismatch diagnosis over a candidate in a candidate set.
|
||||
void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
|
||||
assert(isa<FunctionDecl>(D) &&
|
||||
"The templated declaration should at least be a function"
|
||||
" when diagnosing bad template argument deduction due to too many"
|
||||
" or too few arguments");
|
||||
|
||||
FunctionDecl *Fn = cast<FunctionDecl>(D);
|
||||
|
||||
// TODO: treat calls to a missing default constructor as a special case
|
||||
const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
|
||||
unsigned MinParams = Fn->getMinRequiredArguments();
|
||||
|
||||
// at least / at most / exactly
|
||||
unsigned mode, modeCount;
|
||||
if (NumFormalArgs < MinParams) {
|
||||
assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
|
||||
(Cand->FailureKind == ovl_fail_bad_deduction &&
|
||||
Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
|
||||
if (MinParams != FnTy->getNumArgs() ||
|
||||
FnTy->isVariadic() || FnTy->isTemplateVariadic())
|
||||
mode = 0; // "at least"
|
||||
|
@ -8445,9 +8461,6 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
|
|||
mode = 2; // "exactly"
|
||||
modeCount = MinParams;
|
||||
} else {
|
||||
assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
|
||||
(Cand->FailureKind == ovl_fail_bad_deduction &&
|
||||
Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
|
||||
if (MinParams != FnTy->getNumArgs())
|
||||
mode = 1; // "at most"
|
||||
else
|
||||
|
@ -8469,25 +8482,42 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
|
|||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
}
|
||||
|
||||
/// Diagnose a failed template-argument deduction.
|
||||
void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
||||
unsigned NumArgs) {
|
||||
FunctionDecl *Fn = Cand->Function; // pattern
|
||||
/// Arity mismatch diagnosis specific to a function overload candidate.
|
||||
void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
|
||||
unsigned NumFormalArgs) {
|
||||
if (!CheckArityMismatch(S, Cand, NumFormalArgs))
|
||||
DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
|
||||
}
|
||||
|
||||
TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
|
||||
TemplateDecl *getDescribedTemplate(Decl *Templated) {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
|
||||
return FD->getDescribedFunctionTemplate();
|
||||
else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
|
||||
return RD->getDescribedClassTemplate();
|
||||
|
||||
llvm_unreachable("Unsupported: Getting the described template declaration"
|
||||
" for bad deduction diagnosis");
|
||||
}
|
||||
|
||||
/// Diagnose a failed template-argument deduction.
|
||||
void DiagnoseBadDeduction(Sema &S, Decl *Templated,
|
||||
DeductionFailureInfo &DeductionFailure,
|
||||
unsigned NumArgs) {
|
||||
TemplateParameter Param = DeductionFailure.getTemplateParameter();
|
||||
NamedDecl *ParamD;
|
||||
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
|
||||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
|
||||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
|
||||
switch (Cand->DeductionFailure.Result) {
|
||||
switch (DeductionFailure.Result) {
|
||||
case Sema::TDK_Success:
|
||||
llvm_unreachable("TDK_success while diagnosing bad deduction");
|
||||
|
||||
case Sema::TDK_Incomplete: {
|
||||
assert(ParamD && "no parameter found for incomplete deduction result");
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
|
||||
<< ParamD->getDeclName();
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_incomplete_deduction)
|
||||
<< ParamD->getDeclName();
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8495,7 +8525,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
|||
assert(ParamD && "no parameter found for bad qualifiers deduction result");
|
||||
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
|
||||
|
||||
QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
|
||||
QualType Param = DeductionFailure.getFirstArg()->getAsType();
|
||||
|
||||
// Param will have been canonicalized, but it should just be a
|
||||
// qualified version of ParamD, so move the qualifiers to that.
|
||||
|
@ -8508,11 +8538,11 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
|||
// about that. It also doesn't matter as much, because it won't
|
||||
// have any template parameters in it (because deduction isn't
|
||||
// done on dependent types).
|
||||
QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
|
||||
QualType Arg = DeductionFailure.getSecondArg()->getAsType();
|
||||
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
|
||||
<< ParamD->getDeclName() << Arg << NonCanonParam;
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified)
|
||||
<< ParamD->getDeclName() << Arg << NonCanonParam;
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8527,20 +8557,20 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
|||
which = 2;
|
||||
}
|
||||
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
|
||||
<< which << ParamD->getDeclName()
|
||||
<< *Cand->DeductionFailure.getFirstArg()
|
||||
<< *Cand->DeductionFailure.getSecondArg();
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_inconsistent_deduction)
|
||||
<< which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
|
||||
<< *DeductionFailure.getSecondArg();
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
}
|
||||
|
||||
case Sema::TDK_InvalidExplicitArguments:
|
||||
assert(ParamD && "no parameter found for invalid explicit arguments");
|
||||
if (ParamD->getDeclName())
|
||||
S.Diag(Fn->getLocation(),
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_explicit_arg_mismatch_named)
|
||||
<< ParamD->getDeclName();
|
||||
<< ParamD->getDeclName();
|
||||
else {
|
||||
int index = 0;
|
||||
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
|
||||
|
@ -8550,35 +8580,36 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
|||
index = NTTP->getIndex();
|
||||
else
|
||||
index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
|
||||
S.Diag(Fn->getLocation(),
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
|
||||
<< (index + 1);
|
||||
<< (index + 1);
|
||||
}
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
|
||||
case Sema::TDK_TooManyArguments:
|
||||
case Sema::TDK_TooFewArguments:
|
||||
DiagnoseArityMismatch(S, Cand, NumArgs);
|
||||
DiagnoseArityMismatch(S, Templated, NumArgs);
|
||||
return;
|
||||
|
||||
case Sema::TDK_InstantiationDepth:
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_instantiation_depth);
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
|
||||
case Sema::TDK_SubstitutionFailure: {
|
||||
// Format the template argument list into the argument string.
|
||||
SmallString<128> TemplateArgString;
|
||||
if (TemplateArgumentList *Args =
|
||||
Cand->DeductionFailure.getTemplateArgumentList()) {
|
||||
DeductionFailure.getTemplateArgumentList()) {
|
||||
TemplateArgString = " ";
|
||||
TemplateArgString += S.getTemplateArgumentBindingsText(
|
||||
Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args);
|
||||
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
|
||||
}
|
||||
|
||||
// If this candidate was disabled by enable_if, say so.
|
||||
PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic();
|
||||
PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic();
|
||||
if (PDiag && PDiag->second.getDiagID() ==
|
||||
diag::err_typename_nested_not_found_enable_if) {
|
||||
// FIXME: Use the source range of the condition, and the fully-qualified
|
||||
|
@ -8599,25 +8630,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
|||
PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
|
||||
}
|
||||
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
|
||||
<< TemplateArgString << SFINAEArgString << R;
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_substitution_failure)
|
||||
<< TemplateArgString << SFINAEArgString << R;
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
}
|
||||
|
||||
case Sema::TDK_FailedOverloadResolution: {
|
||||
OverloadExpr::FindResult R =
|
||||
OverloadExpr::find(Cand->DeductionFailure.getExpr());
|
||||
S.Diag(Fn->getLocation(),
|
||||
OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr());
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_failed_overload_resolution)
|
||||
<< R.Expression->getName();
|
||||
<< R.Expression->getName();
|
||||
return;
|
||||
}
|
||||
|
||||
case Sema::TDK_NonDeducedMismatch: {
|
||||
// FIXME: Provide a source location to indicate what we couldn't match.
|
||||
TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg();
|
||||
TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg();
|
||||
TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
|
||||
TemplateArgument SecondTA = *DeductionFailure.getSecondArg();
|
||||
if (FirstTA.getKind() == TemplateArgument::Template &&
|
||||
SecondTA.getKind() == TemplateArgument::Template) {
|
||||
TemplateName FirstTN = FirstTA.getAsTemplate();
|
||||
|
@ -8632,26 +8663,38 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
|
|||
// 2) The diagnostic printer only attempts to find a better
|
||||
// name for types, not decls.
|
||||
// Ideally, this should folded into the diagnostic printer.
|
||||
S.Diag(Fn->getLocation(),
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_non_deduced_mismatch_qualified)
|
||||
<< FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch)
|
||||
<< FirstTA << SecondTA;
|
||||
S.Diag(Templated->getLocation(),
|
||||
diag::note_ovl_candidate_non_deduced_mismatch)
|
||||
<< FirstTA << SecondTA;
|
||||
return;
|
||||
}
|
||||
// TODO: diagnose these individually, then kill off
|
||||
// note_ovl_candidate_bad_deduction, which is uselessly vague.
|
||||
case Sema::TDK_MiscellaneousDeductionFailure:
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
|
||||
MaybeEmitInheritedConstructorNote(S, Templated);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Diagnose a failed template-argument deduction, for function calls.
|
||||
void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
|
||||
unsigned TDK = Cand->DeductionFailure.Result;
|
||||
if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
|
||||
if (CheckArityMismatch(S, Cand, NumArgs))
|
||||
return;
|
||||
}
|
||||
DiagnoseBadDeduction(S, Cand->Function, // pattern
|
||||
Cand->DeductionFailure, NumArgs);
|
||||
}
|
||||
|
||||
/// CUDA: diagnose an invalid call across targets.
|
||||
void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
|
||||
FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
|
||||
|
@ -8799,7 +8842,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
|
|||
}
|
||||
}
|
||||
|
||||
SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
|
||||
static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
|
||||
if (Cand->Function)
|
||||
return Cand->Function->getLocation();
|
||||
if (Cand->IsSurrogate)
|
||||
|
@ -8807,8 +8850,7 @@ SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
|
|||
return SourceLocation();
|
||||
}
|
||||
|
||||
static unsigned
|
||||
RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) {
|
||||
static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
|
||||
switch ((Sema::TemplateDeductionResult)DFI.Result) {
|
||||
case Sema::TDK_Success:
|
||||
llvm_unreachable("TDK_success while diagnosing bad deduction");
|
||||
|
@ -9101,6 +9143,108 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
|
|||
S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
|
||||
}
|
||||
|
||||
static SourceLocation
|
||||
GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
|
||||
return Cand->Specialization ? Cand->Specialization->getLocation()
|
||||
: SourceLocation();
|
||||
}
|
||||
|
||||
struct CompareTemplateSpecCandidatesForDisplay {
|
||||
Sema &S;
|
||||
CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {}
|
||||
|
||||
bool operator()(const TemplateSpecCandidate *L,
|
||||
const TemplateSpecCandidate *R) {
|
||||
// Fast-path this check.
|
||||
if (L == R)
|
||||
return false;
|
||||
|
||||
// Assuming that both candidates are not matches...
|
||||
|
||||
// Sort by the ranking of deduction failures.
|
||||
if (L->DeductionFailure.Result != R->DeductionFailure.Result)
|
||||
return RankDeductionFailure(L->DeductionFailure) <
|
||||
RankDeductionFailure(R->DeductionFailure);
|
||||
|
||||
// Sort everything else by location.
|
||||
SourceLocation LLoc = GetLocationForCandidate(L);
|
||||
SourceLocation RLoc = GetLocationForCandidate(R);
|
||||
|
||||
// Put candidates without locations (e.g. builtins) at the end.
|
||||
if (LLoc.isInvalid())
|
||||
return false;
|
||||
if (RLoc.isInvalid())
|
||||
return true;
|
||||
|
||||
return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
|
||||
}
|
||||
};
|
||||
|
||||
/// Diagnose a template argument deduction failure.
|
||||
/// We are treating these failures as overload failures due to bad
|
||||
/// deductions.
|
||||
void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) {
|
||||
DiagnoseBadDeduction(S, Specialization, // pattern
|
||||
DeductionFailure, /*NumArgs=*/0);
|
||||
}
|
||||
|
||||
void TemplateSpecCandidateSet::destroyCandidates() {
|
||||
for (iterator i = begin(), e = end(); i != e; ++i) {
|
||||
i->DeductionFailure.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void TemplateSpecCandidateSet::clear() {
|
||||
destroyCandidates();
|
||||
Candidates.clear();
|
||||
}
|
||||
|
||||
/// NoteCandidates - When no template specialization match is found, prints
|
||||
/// diagnostic messages containing the non-matching specializations that form
|
||||
/// the candidate set.
|
||||
/// This is analoguous to OverloadCandidateSet::NoteCandidates() with
|
||||
/// OCD == OCD_AllCandidates and Cand->Viable == false.
|
||||
void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
|
||||
// Sort the candidates by position (assuming no candidate is a match).
|
||||
// Sorting directly would be prohibitive, so we make a set of pointers
|
||||
// and sort those.
|
||||
SmallVector<TemplateSpecCandidate *, 32> Cands;
|
||||
Cands.reserve(size());
|
||||
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
|
||||
if (Cand->Specialization)
|
||||
Cands.push_back(Cand);
|
||||
// Otherwise, this is a non matching builtin candidate. We do not,
|
||||
// in general, want to list every possible builtin candidate.
|
||||
}
|
||||
|
||||
std::sort(Cands.begin(), Cands.end(),
|
||||
CompareTemplateSpecCandidatesForDisplay(S));
|
||||
|
||||
// FIXME: Perhaps rename OverloadsShown and getShowOverloads()
|
||||
// for generalization purposes (?).
|
||||
const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
|
||||
|
||||
SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E;
|
||||
unsigned CandsShown = 0;
|
||||
for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
|
||||
TemplateSpecCandidate *Cand = *I;
|
||||
|
||||
// Set an arbitrary limit on the number of candidates we'll spam
|
||||
// the user with. FIXME: This limit should depend on details of the
|
||||
// candidate list.
|
||||
if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
|
||||
break;
|
||||
++CandsShown;
|
||||
|
||||
assert(Cand->Specialization &&
|
||||
"Non-matching built-in candidates are not added to Cands.");
|
||||
Cand->NoteDeductionFailure(S);
|
||||
}
|
||||
|
||||
if (I != E)
|
||||
S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I);
|
||||
}
|
||||
|
||||
// [PossiblyAFunctionType] --> [Return]
|
||||
// NonFunctionType --> NonFunctionType
|
||||
// R (A) --> R(A)
|
||||
|
@ -9143,18 +9287,19 @@ class AddressOfFunctionResolver
|
|||
OverloadExpr *OvlExpr;
|
||||
TemplateArgumentListInfo OvlExplicitTemplateArgs;
|
||||
SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
|
||||
TemplateSpecCandidateSet FailedCandidates;
|
||||
|
||||
public:
|
||||
AddressOfFunctionResolver(Sema &S, Expr* SourceExpr,
|
||||
const QualType& TargetType, bool Complain)
|
||||
: S(S), SourceExpr(SourceExpr), TargetType(TargetType),
|
||||
Complain(Complain), Context(S.getASTContext()),
|
||||
TargetTypeIsNonStaticMemberFunction(
|
||||
!!TargetType->getAs<MemberPointerType>()),
|
||||
FoundNonTemplateFunction(false),
|
||||
OvlExprInfo(OverloadExpr::find(SourceExpr)),
|
||||
OvlExpr(OvlExprInfo.Expression)
|
||||
{
|
||||
AddressOfFunctionResolver(Sema &S, Expr *SourceExpr,
|
||||
const QualType &TargetType, bool Complain)
|
||||
: S(S), SourceExpr(SourceExpr), TargetType(TargetType),
|
||||
Complain(Complain), Context(S.getASTContext()),
|
||||
TargetTypeIsNonStaticMemberFunction(
|
||||
!!TargetType->getAs<MemberPointerType>()),
|
||||
FoundNonTemplateFunction(false),
|
||||
OvlExprInfo(OverloadExpr::find(SourceExpr)),
|
||||
OvlExpr(OvlExprInfo.Expression),
|
||||
FailedCandidates(OvlExpr->getNameLoc()) {
|
||||
ExtractUnqualifiedFunctionTypeFromTargetType();
|
||||
|
||||
if (!TargetFunctionType->isFunctionType()) {
|
||||
|
@ -9232,13 +9377,16 @@ private:
|
|||
// function template specialization, which is added to the set of
|
||||
// overloaded functions considered.
|
||||
FunctionDecl *Specialization = 0;
|
||||
TemplateDeductionInfo Info(OvlExpr->getNameLoc());
|
||||
TemplateDeductionInfo Info(FailedCandidates.getLocation());
|
||||
if (Sema::TemplateDeductionResult Result
|
||||
= S.DeduceTemplateArguments(FunctionTemplate,
|
||||
&OvlExplicitTemplateArgs,
|
||||
TargetFunctionType, Specialization,
|
||||
Info, /*InOverloadResolution=*/true)) {
|
||||
// FIXME: make a note of the failed deduction for diagnostics.
|
||||
// Make a note of the failed deduction for diagnostics.
|
||||
FailedCandidates.addCandidate()
|
||||
.set(FunctionTemplate->getTemplatedDecl(),
|
||||
MakeDeductionFailureInfo(Context, Result, Info));
|
||||
(void)Result;
|
||||
return false;
|
||||
}
|
||||
|
@ -9343,15 +9491,15 @@ private:
|
|||
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
|
||||
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
|
||||
|
||||
UnresolvedSetIterator Result =
|
||||
S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
|
||||
TPOC_Other, 0, SourceExpr->getLocStart(),
|
||||
S.PDiag(),
|
||||
S.PDiag(diag::err_addr_ovl_ambiguous)
|
||||
<< Matches[0].second->getDeclName(),
|
||||
S.PDiag(diag::note_ovl_candidate)
|
||||
<< (unsigned) oc_function_template,
|
||||
Complain, TargetFunctionType);
|
||||
// TODO: It looks like FailedCandidates does not serve much purpose
|
||||
// here, since the no_viable diagnostic has index 0.
|
||||
UnresolvedSetIterator Result = S.getMostSpecialized(
|
||||
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, TPOC_Other, 0,
|
||||
SourceExpr->getLocStart(), S.PDiag(),
|
||||
S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
|
||||
.second->getDeclName(),
|
||||
S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template,
|
||||
Complain, TargetFunctionType);
|
||||
|
||||
if (Result != MatchesCopy.end()) {
|
||||
// Make it the first and only element
|
||||
|
@ -9380,6 +9528,7 @@ public:
|
|||
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
|
||||
<< OvlExpr->getName() << TargetFunctionType
|
||||
<< OvlExpr->getSourceRange();
|
||||
FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
|
||||
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
|
||||
}
|
||||
|
||||
|
@ -9496,6 +9645,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
|
|||
|
||||
TemplateArgumentListInfo ExplicitTemplateArgs;
|
||||
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
|
||||
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
|
||||
|
||||
// Look through all of the overloaded functions, searching for one
|
||||
// whose type matches exactly.
|
||||
|
@ -9518,12 +9668,16 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
|
|||
// function template specialization, which is added to the set of
|
||||
// overloaded functions considered.
|
||||
FunctionDecl *Specialization = 0;
|
||||
TemplateDeductionInfo Info(ovl->getNameLoc());
|
||||
TemplateDeductionInfo Info(FailedCandidates.getLocation());
|
||||
if (TemplateDeductionResult Result
|
||||
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
|
||||
Specialization, Info,
|
||||
/*InOverloadResolution=*/true)) {
|
||||
// FIXME: make a note of the failed deduction for diagnostics.
|
||||
// Make a note of the failed deduction for diagnostics.
|
||||
// TODO: Actually use the failed-deduction info?
|
||||
FailedCandidates.addCandidate()
|
||||
.set(FunctionTemplate->getTemplatedDecl(),
|
||||
MakeDeductionFailureInfo(Context, Result, Info));
|
||||
(void)Result;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -5925,13 +5925,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
///
|
||||
/// \param Previous the set of declarations that may be specialized by
|
||||
/// this function specialization.
|
||||
bool
|
||||
Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous) {
|
||||
bool Sema::CheckFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous) {
|
||||
// The set of function template specializations that could match this
|
||||
// explicit function template specialization.
|
||||
UnresolvedSet<8> Candidates;
|
||||
TemplateSpecCandidateSet FailedCandidates(FD->getLocation());
|
||||
|
||||
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
|
||||
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
|
||||
|
@ -5969,13 +5969,16 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
// Perform template argument deduction to determine whether we may be
|
||||
// specializing this template.
|
||||
// FIXME: It is somewhat wasteful to build
|
||||
TemplateDeductionInfo Info(FD->getLocation());
|
||||
TemplateDeductionInfo Info(FailedCandidates.getLocation());
|
||||
FunctionDecl *Specialization = 0;
|
||||
if (TemplateDeductionResult TDK
|
||||
= DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT,
|
||||
Specialization, Info)) {
|
||||
// FIXME: Template argument deduction failed; record why it failed, so
|
||||
// Template argument deduction failed; record why it failed, so
|
||||
// that we can provide nifty diagnostics.
|
||||
FailedCandidates.addCandidate()
|
||||
.set(FunTmpl->getTemplatedDecl(),
|
||||
MakeDeductionFailureInfo(Context, TDK, Info));
|
||||
(void)TDK;
|
||||
continue;
|
||||
}
|
||||
|
@ -5986,14 +5989,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
}
|
||||
|
||||
// Find the most specialized function template.
|
||||
UnresolvedSetIterator Result
|
||||
= getMostSpecialized(Candidates.begin(), Candidates.end(),
|
||||
TPOC_Other, 0, FD->getLocation(),
|
||||
PDiag(diag::err_function_template_spec_no_match)
|
||||
<< FD->getDeclName(),
|
||||
PDiag(diag::err_function_template_spec_ambiguous)
|
||||
<< FD->getDeclName() << (ExplicitTemplateArgs != 0),
|
||||
PDiag(diag::note_function_template_spec_matched));
|
||||
UnresolvedSetIterator Result = getMostSpecialized(
|
||||
Candidates.begin(), Candidates.end(), FailedCandidates, TPOC_Other, 0,
|
||||
FD->getLocation(),
|
||||
PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
|
||||
PDiag(diag::err_function_template_spec_ambiguous)
|
||||
<< FD->getDeclName() << (ExplicitTemplateArgs != 0),
|
||||
PDiag(diag::note_function_template_spec_matched));
|
||||
|
||||
if (Result == Candidates.end())
|
||||
return true;
|
||||
|
||||
|
@ -6812,6 +6815,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
// instantiated from the member definition associated with its class
|
||||
// template.
|
||||
UnresolvedSet<8> Matches;
|
||||
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
|
||||
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
|
||||
P != PEnd; ++P) {
|
||||
NamedDecl *Prev = *P;
|
||||
|
@ -6831,13 +6835,16 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
if (!FunTmpl)
|
||||
continue;
|
||||
|
||||
TemplateDeductionInfo Info(D.getIdentifierLoc());
|
||||
TemplateDeductionInfo Info(FailedCandidates.getLocation());
|
||||
FunctionDecl *Specialization = 0;
|
||||
if (TemplateDeductionResult TDK
|
||||
= DeduceTemplateArguments(FunTmpl,
|
||||
(HasExplicitTemplateArgs ? &TemplateArgs : 0),
|
||||
R, Specialization, Info)) {
|
||||
// FIXME: Keep track of almost-matches?
|
||||
// Keep track of almost-matches.
|
||||
FailedCandidates.addCandidate()
|
||||
.set(FunTmpl->getTemplatedDecl(),
|
||||
MakeDeductionFailureInfo(Context, TDK, Info));
|
||||
(void)TDK;
|
||||
continue;
|
||||
}
|
||||
|
@ -6846,12 +6853,12 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
}
|
||||
|
||||
// Find the most specialized function template specialization.
|
||||
UnresolvedSetIterator Result
|
||||
= getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0,
|
||||
D.getIdentifierLoc(),
|
||||
PDiag(diag::err_explicit_instantiation_not_known) << Name,
|
||||
PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
|
||||
PDiag(diag::note_explicit_instantiation_candidate));
|
||||
UnresolvedSetIterator Result = getMostSpecialized(
|
||||
Matches.begin(), Matches.end(), FailedCandidates, TPOC_Other, 0,
|
||||
D.getIdentifierLoc(),
|
||||
PDiag(diag::err_explicit_instantiation_not_known) << Name,
|
||||
PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
|
||||
PDiag(diag::note_explicit_instantiation_candidate));
|
||||
|
||||
if (Result == Matches.end())
|
||||
return true;
|
||||
|
|
|
@ -4148,23 +4148,18 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
|
|||
///
|
||||
/// \returns the most specialized function template specialization, if
|
||||
/// found. Otherwise, returns SpecEnd.
|
||||
///
|
||||
/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
|
||||
/// template argument deduction.
|
||||
UnresolvedSetIterator
|
||||
Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
|
||||
UnresolvedSetIterator SpecEnd,
|
||||
TemplatePartialOrderingContext TPOC,
|
||||
unsigned NumCallArguments,
|
||||
SourceLocation Loc,
|
||||
const PartialDiagnostic &NoneDiag,
|
||||
const PartialDiagnostic &AmbigDiag,
|
||||
const PartialDiagnostic &CandidateDiag,
|
||||
bool Complain,
|
||||
QualType TargetType) {
|
||||
UnresolvedSetIterator Sema::getMostSpecialized(
|
||||
UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd,
|
||||
TemplateSpecCandidateSet &FailedCandidates,
|
||||
TemplatePartialOrderingContext TPOC, unsigned NumCallArguments,
|
||||
SourceLocation Loc, const PartialDiagnostic &NoneDiag,
|
||||
const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag,
|
||||
bool Complain, QualType TargetType) {
|
||||
if (SpecBegin == SpecEnd) {
|
||||
if (Complain)
|
||||
if (Complain) {
|
||||
Diag(Loc, NoneDiag);
|
||||
FailedCandidates.NoteCandidates(*this, Loc);
|
||||
}
|
||||
return SpecEnd;
|
||||
}
|
||||
|
||||
|
|
|
@ -2252,15 +2252,18 @@ Sema::InstantiateClassTemplateSpecialization(
|
|||
SmallVector<MatchResult, 4> Matched;
|
||||
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
|
||||
Template->getPartialSpecializations(PartialSpecs);
|
||||
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
|
||||
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
|
||||
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
|
||||
TemplateDeductionInfo Info(PointOfInstantiation);
|
||||
TemplateDeductionInfo Info(FailedCandidates.getLocation());
|
||||
if (TemplateDeductionResult Result
|
||||
= DeduceTemplateArguments(Partial,
|
||||
ClassTemplateSpec->getTemplateArgs(),
|
||||
Info)) {
|
||||
// FIXME: Store the failed-deduction information for use in
|
||||
// diagnostics, later.
|
||||
// Store the failed-deduction information for use in diagnostics, later.
|
||||
// TODO: Actually use the failed-deduction info?
|
||||
FailedCandidates.addCandidate()
|
||||
.set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
|
||||
(void)Result;
|
||||
} else {
|
||||
Matched.push_back(PartialSpecMatchResult());
|
||||
|
|
|
@ -4269,10 +4269,6 @@ bool TreeTransform<Derived>::
|
|||
if (NewType.isNull())
|
||||
return true;
|
||||
|
||||
if (NewType->containsUnexpandedParameterPack())
|
||||
NewType = getSema().Context.getPackExpansionType(NewType,
|
||||
NumExpansions);
|
||||
|
||||
OutParamTypes.push_back(NewType);
|
||||
if (PVars)
|
||||
PVars->push_back(0);
|
||||
|
|
|
@ -72,7 +72,8 @@ template <typename T> constexpr T ft(T t) { return t; }
|
|||
template <typename T> T gt(T t) { return t; }
|
||||
struct S {
|
||||
template<typename T> constexpr T f(); // expected-warning {{C++1y}}
|
||||
template<typename T> T g() const;
|
||||
template <typename T>
|
||||
T g() const; // expected-note {{candidate template ignored: could not match 'T () const' against 'char ()'}}
|
||||
};
|
||||
|
||||
// explicit specialization can differ in constepxr
|
||||
|
|
|
@ -93,7 +93,7 @@ void c() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
template<bool B> int f() { return B; }
|
||||
template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}}
|
||||
template int f<&S::operator int>(); // expected-error {{does not refer to a function template}}
|
||||
template int f<(bool)&S::operator int>();
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
template<typename T> T f0(T, T); //expected-note{{candidate}}
|
||||
template <typename T>
|
||||
T f0(T, T); // expected-note{{candidate}} expected-note{{candidate function}}
|
||||
|
||||
void test_f0() {
|
||||
int (*f0a)(int, int) = f0;
|
||||
|
|
|
@ -4,8 +4,12 @@ void g();
|
|||
void f(); // expected-note 9{{candidate function}}
|
||||
void f(int); // expected-note 9{{candidate function}}
|
||||
|
||||
template<class T> void t(T); // expected-note 6{{candidate function}}
|
||||
template<class T> void t(T*); // expected-note 6{{candidate function}}
|
||||
template <class T>
|
||||
void t(T); // expected-note 6{{candidate function}} \
|
||||
// expected-note 3{{candidate template ignored: could not match 'void' against 'int'}}
|
||||
template <class T>
|
||||
void t(T *); // expected-note 6{{candidate function}} \
|
||||
// expected-note 3{{candidate template ignored: could not match 'void' against 'int'}}
|
||||
|
||||
template<class T> void u(T);
|
||||
|
||||
|
|
|
@ -112,7 +112,8 @@ namespace Templates {
|
|||
int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}}
|
||||
template<typename T> auto fwd_decl() { return 0; }
|
||||
int f = fwd_decl<int>();
|
||||
template<typename T> auto fwd_decl();
|
||||
template <typename T>
|
||||
auto fwd_decl(); // expected-note {{candidate template ignored: could not match 'auto ()' against 'int ()'}}
|
||||
int g = fwd_decl<char>();
|
||||
|
||||
auto (*p)() = f1; // expected-error {{incompatible initializer}}
|
||||
|
@ -126,7 +127,8 @@ namespace Templates {
|
|||
extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}}
|
||||
int k2 = fwd_decl<char>();
|
||||
|
||||
template<typename T> auto instantiate() { T::error; } // expected-error {{has no members}}
|
||||
template <typename T> auto instantiate() { T::error; } // expected-error {{has no members}} \
|
||||
// expected-note {{candidate template ignored: could not match 'auto ()' against 'void ()'}}
|
||||
extern template auto instantiate<int>(); // ok
|
||||
int k = instantiate<int>(); // expected-note {{in instantiation of}}
|
||||
template<> auto instantiate<char>() {} // ok
|
||||
|
@ -157,7 +159,8 @@ namespace Templates {
|
|||
double &mem_check4 = take_fn<double>(Outer<double>::arg_multi);
|
||||
|
||||
namespace Deduce1 {
|
||||
template<typename T> auto f() { return 0; } // expected-note {{candidate}}
|
||||
template <typename T> auto f() { return 0; } // expected-note {{candidate}} \
|
||||
// expected-note {{candidate function has different return type ('int' expected but has 'auto')}}
|
||||
template<typename T> void g(T(*)()); // expected-note 2{{candidate}}
|
||||
void h() {
|
||||
auto p = f<int>;
|
||||
|
@ -170,7 +173,8 @@ namespace Templates {
|
|||
}
|
||||
|
||||
namespace Deduce2 {
|
||||
template<typename T> auto f(int) { return 0; } // expected-note {{candidate}}
|
||||
template <typename T> auto f(int) { return 0; } // expected-note {{candidate}} \
|
||||
// expected-note {{candidate function has different return type ('int' expected but has 'auto')}}
|
||||
template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}}
|
||||
void h() {
|
||||
auto p = f<int>;
|
||||
|
@ -322,7 +326,8 @@ namespace Redecl {
|
|||
int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
|
||||
decltype(auto) f(); // expected-error {{cannot be overloaded}}
|
||||
|
||||
template<typename T> auto g(T t) { return t; } // expected-note {{candidate}}
|
||||
template <typename T> auto g(T t) { return t; } // expected-note {{candidate}} \
|
||||
// expected-note {{candidate function [with T = int]}}
|
||||
template auto g(int);
|
||||
template char g(char); // expected-error {{does not refer to a function}}
|
||||
template<> auto g(double);
|
||||
|
|
|
@ -29,11 +29,13 @@ void releaser(__attribute__((ns_consumed)) id);
|
|||
releaser_t r2 = releaser; // no-warning
|
||||
|
||||
template <typename T>
|
||||
void templateFunction(T) {} // expected-note {{candidate function}}
|
||||
void templateFunction(T) { } // expected-note {{candidate function}} \
|
||||
// expected-note {{candidate template ignored: could not match 'void (__strong id)' against 'void (id)'}} \
|
||||
// expected-note {{candidate template ignored: failed template argument deduction}}
|
||||
releaser_t r3 = templateFunction<id>; // expected-error {{address of overloaded function 'templateFunction' does not match required type 'void (id)'}}
|
||||
|
||||
template <typename T>
|
||||
void templateReleaser(__attribute__((ns_consumed)) T) {}
|
||||
void templateReleaser(__attribute__((ns_consumed)) T) { } // expected-note 2{{candidate template ignored: failed template argument deduction}}
|
||||
releaser_t r4 = templateReleaser<id>; // no-warning
|
||||
|
||||
|
||||
|
|
|
@ -189,10 +189,3 @@ namespace PR16646 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace VariadicAliasWithFunctionType {
|
||||
template <class T> struct A { };
|
||||
template <class ...Args> using B = A<int(Args ...x)>;
|
||||
template <class ...Args> void f(B<A<int>, A<Args>...>) {}
|
||||
void g() { f(A<int(A<int>,A<int>)>()); }
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ struct X0 {
|
|||
return x + 1; // expected-error{{invalid operands}}
|
||||
}
|
||||
T* f0(T*, T*) { return T(); } // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
|
||||
|
||||
template<typename U>
|
||||
T f0(T, U) { return T(); }
|
||||
|
||||
template <typename U> T f0(T, U) { return T(); } // expected-note {{candidate template ignored: could not match 'int (int, U)' against 'int (int) const'}} \
|
||||
// expected-note {{candidate template ignored: could not match 'int' against 'int *'}}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -59,13 +59,14 @@ template int *X2::f1(int *); // okay
|
|||
|
||||
template void X2::f2(int *, int *); // expected-error{{ambiguous}}
|
||||
|
||||
|
||||
template<typename T> void print_type() { }
|
||||
template <typename T>
|
||||
void print_type() {} // expected-note {{candidate template ignored: could not match 'void ()' against 'void (float *)'}}
|
||||
|
||||
template void print_type<int>();
|
||||
template void print_type<float>();
|
||||
|
||||
template<typename T> void print_type(T*) { }
|
||||
template <typename T>
|
||||
void print_type(T *) {} // expected-note {{candidate template ignored: could not match 'void (int *)' against 'void (float *)'}}
|
||||
|
||||
template void print_type(int*);
|
||||
template void print_type<int>(float*); // expected-error{{does not refer}}
|
||||
|
@ -94,7 +95,7 @@ namespace PR7622 {
|
|||
|
||||
template<typename,typename>
|
||||
struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \
|
||||
// expected-error{{expected member name or ';' after declaration specifiers}}
|
||||
// expected-error{{expected member name or ';' after declaration specifiers}}
|
||||
template struct basic_streambuf<int>;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
template<int N> void f0(int (&array)[N]);
|
||||
template <int N>
|
||||
void f0(int (&array)[N]); // expected-note {{candidate template ignored: could not match 'int' against 'char'}}
|
||||
|
||||
// Simple function template specialization (using overloading)
|
||||
template<> void f0(int (&array)[1]);
|
||||
|
|
Loading…
Reference in New Issue