From 98b20f1278e097f9f56b0c3bdb6740e230a47832 Mon Sep 17 00:00:00 2001 From: Larisse Voufo Date: Fri, 19 Jul 2013 23:00:19 +0000 Subject: [PATCH] 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 --- clang/include/clang/Sema/Overload.h | 48 +-- clang/include/clang/Sema/Sema.h | 25 +- clang/include/clang/Sema/TemplateDeduction.h | 122 +++++- clang/lib/Sema/SemaOverload.cpp | 362 +++++++++++++----- clang/lib/Sema/SemaTemplate.cpp | 51 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 25 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 +- clang/lib/Sema/TreeTransform.h | 4 - .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 3 +- clang/test/CXX/expr/expr.const/p3-0x.cpp | 2 +- clang/test/CXX/over/over.over/p2.cpp | 3 +- .../addr-of-overloaded-function-casting.cpp | 8 +- .../SemaCXX/cxx1y-deduced-return-type.cpp | 15 +- .../test/SemaObjCXX/arc-nsconsumed-errors.mm | 6 +- clang/test/SemaTemplate/alias-templates.cpp | 7 - .../SemaTemplate/explicit-instantiation.cpp | 15 +- .../function-template-specialization.cpp | 3 +- 17 files changed, 474 insertions(+), 234 deletions(-) diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 490caf091f2a..54f08367da3d 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -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; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6501e52fe008..9543dc549b89 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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 diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h index 8292045fdb91..1daa6891ed12 100644 --- a/clang/include/clang/Sema/TemplateDeduction.h +++ b/clang/include/clang/Sema/TemplateDeduction.h @@ -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 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::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(this)->NoteCandidates(S, Loc); + } +}; + +} // end namespace clang #endif diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 04aaf181af34..7ebcd88fe5f6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -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(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(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(static_cast(Diagnostic)); return 0; } -TemplateParameter -OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { +TemplateParameter DeductionFailureInfo::getTemplateParameter() { switch (static_cast(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(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(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(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(Result) == Sema::TDK_FailedOverloadResolution) return static_cast(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(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(); - 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(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(D); + + // TODO: treat calls to a missing default constructor as a special case + const FunctionProtoType *FnTy = Fn->getType()->getAs(); + 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(Templated)) + return FD->getDescribedFunctionTemplate(); + else if (CXXRecordDecl *RD = dyn_cast(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()) || (ParamD = Param.dyn_cast()) || (ParamD = Param.dyn_cast()); - 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(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(ParamD)) @@ -8550,35 +8580,36 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, index = NTTP->getIndex(); else index = cast(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(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 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::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, 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()), - 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()), + 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; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6f1ab19f10e0..7939c48c64b6 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -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; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 29ee6dfa994d..8d6aaa096dfb 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3904daa47f13..7632bba8c9c5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2252,15 +2252,18 @@ Sema::InstantiateClassTemplateSpecialization( SmallVector Matched; SmallVector 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()); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4a41b6036428..34fdbad87b34 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4269,10 +4269,6 @@ bool TreeTransform:: if (NewType.isNull()) return true; - if (NewType->containsUnexpandedParameterPack()) - NewType = getSema().Context.getPackExpansionType(NewType, - NumExpansions); - OutParamTypes.push_back(NewType); if (PVars) PVars->push_back(0); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 122a400d9b4e..cf422972a280 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -72,7 +72,8 @@ template constexpr T ft(T t) { return t; } template T gt(T t) { return t; } struct S { template constexpr T f(); // expected-warning {{C++1y}} - template T g() const; + template + T g() const; // expected-note {{candidate template ignored: could not match 'T () const' against 'char ()'}} }; // explicit specialization can differ in constepxr diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp index 047e238190f8..e3e32dfe0900 100644 --- a/clang/test/CXX/expr/expr.const/p3-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp @@ -93,7 +93,7 @@ void c() { break; } } -template int f() { return B; } +template 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>(); diff --git a/clang/test/CXX/over/over.over/p2.cpp b/clang/test/CXX/over/over.over/p2.cpp index 3e8d0f1d8cdd..b6c1d6bfa25b 100644 --- a/clang/test/CXX/over/over.over/p2.cpp +++ b/clang/test/CXX/over/over.over/p2.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template T f0(T, T); //expected-note{{candidate}} +template +T f0(T, T); // expected-note{{candidate}} expected-note{{candidate function}} void test_f0() { int (*f0a)(int, int) = f0; diff --git a/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp b/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp index cfd55eed81d5..8698736b3aeb 100644 --- a/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp +++ b/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp @@ -4,8 +4,12 @@ void g(); void f(); // expected-note 9{{candidate function}} void f(int); // expected-note 9{{candidate function}} -template void t(T); // expected-note 6{{candidate function}} -template void t(T*); // expected-note 6{{candidate function}} +template +void t(T); // expected-note 6{{candidate function}} \ + // expected-note 3{{candidate template ignored: could not match 'void' against 'int'}} +template +void t(T *); // expected-note 6{{candidate function}} \ + // expected-note 3{{candidate template ignored: could not match 'void' against 'int'}} template void u(T); diff --git a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp b/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp index d3067eb411c5..743ef4fbf2bc 100644 --- a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -112,7 +112,8 @@ namespace Templates { int e = fwd_decl(); // expected-error {{cannot be used before it is defined}} template auto fwd_decl() { return 0; } int f = fwd_decl(); - template auto fwd_decl(); + template + auto fwd_decl(); // expected-note {{candidate template ignored: could not match 'auto ()' against 'int ()'}} int g = fwd_decl(); auto (*p)() = f1; // expected-error {{incompatible initializer}} @@ -126,7 +127,8 @@ namespace Templates { extern template int fwd_decl(); // expected-error {{does not refer to a function template}} int k2 = fwd_decl(); - template auto instantiate() { T::error; } // expected-error {{has no members}} + template auto instantiate() { T::error; } // expected-error {{has no members}} \ + // expected-note {{candidate template ignored: could not match 'auto ()' against 'void ()'}} extern template auto instantiate(); // ok int k = instantiate(); // expected-note {{in instantiation of}} template<> auto instantiate() {} // ok @@ -157,7 +159,8 @@ namespace Templates { double &mem_check4 = take_fn(Outer::arg_multi); namespace Deduce1 { - template auto f() { return 0; } // expected-note {{candidate}} + template auto f() { return 0; } // expected-note {{candidate}} \ + // expected-note {{candidate function has different return type ('int' expected but has 'auto')}} template void g(T(*)()); // expected-note 2{{candidate}} void h() { auto p = f; @@ -170,7 +173,8 @@ namespace Templates { } namespace Deduce2 { - template auto f(int) { return 0; } // expected-note {{candidate}} + template auto f(int) { return 0; } // expected-note {{candidate}} \ + // expected-note {{candidate function has different return type ('int' expected but has 'auto')}} template void g(T(*)(int)); // expected-note 2{{candidate}} void h() { auto p = f; @@ -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 auto g(T t) { return t; } // expected-note {{candidate}} + template 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); diff --git a/clang/test/SemaObjCXX/arc-nsconsumed-errors.mm b/clang/test/SemaObjCXX/arc-nsconsumed-errors.mm index 10ae10d04988..c1ce81b66938 100644 --- a/clang/test/SemaObjCXX/arc-nsconsumed-errors.mm +++ b/clang/test/SemaObjCXX/arc-nsconsumed-errors.mm @@ -29,11 +29,13 @@ void releaser(__attribute__((ns_consumed)) id); releaser_t r2 = releaser; // no-warning template -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; // expected-error {{address of overloaded function 'templateFunction' does not match required type 'void (id)'}} template -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; // no-warning diff --git a/clang/test/SemaTemplate/alias-templates.cpp b/clang/test/SemaTemplate/alias-templates.cpp index f495620b54fb..eeb6b9518976 100644 --- a/clang/test/SemaTemplate/alias-templates.cpp +++ b/clang/test/SemaTemplate/alias-templates.cpp @@ -189,10 +189,3 @@ namespace PR16646 { } } } - -namespace VariadicAliasWithFunctionType { - template struct A { }; - template using B = A; - template void f(B, A...>) {} - void g() { f(A,A)>()); } -} diff --git a/clang/test/SemaTemplate/explicit-instantiation.cpp b/clang/test/SemaTemplate/explicit-instantiation.cpp index e3e77d082844..04a863bdc17e 100644 --- a/clang/test/SemaTemplate/explicit-instantiation.cpp +++ b/clang/test/SemaTemplate/explicit-instantiation.cpp @@ -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 - T f0(T, U) { return T(); } + + template 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 @@ -59,13 +59,14 @@ template int *X2::f1(int *); // okay template void X2::f2(int *, int *); // expected-error{{ambiguous}} - -template void print_type() { } +template +void print_type() {} // expected-note {{candidate template ignored: could not match 'void ()' against 'void (float *)'}} template void print_type(); template void print_type(); -template void print_type(T*) { } +template +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(float*); // expected-error{{does not refer}} @@ -94,7 +95,7 @@ namespace PR7622 { template 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; } diff --git a/clang/test/SemaTemplate/function-template-specialization.cpp b/clang/test/SemaTemplate/function-template-specialization.cpp index 2338b6701c44..6327ff64c336 100644 --- a/clang/test/SemaTemplate/function-template-specialization.cpp +++ b/clang/test/SemaTemplate/function-template-specialization.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template void f0(int (&array)[N]); +template +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]);