From 8c5d4078bb40642847164e7613828262d32db973 Mon Sep 17 00:00:00 2001 From: Larisse Voufo Date: Fri, 19 Jul 2013 22:53:23 +0000 Subject: [PATCH] Revert "Use function overloading instead of template specialization for diagnosis of bad template argument deductions." This reverts commit a730f548325756d050d4caaa28fcbffdae8dfe95. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186729 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Overload.h | 48 ++- include/clang/Sema/Sema.h | 25 +- include/clang/Sema/TemplateDeduction.h | 122 +----- lib/Sema/SemaOverload.cpp | 360 +++++------------- lib/Sema/SemaTemplate.cpp | 51 ++- lib/Sema/SemaTemplateDeduction.cpp | 25 +- lib/Sema/SemaTemplateInstantiate.cpp | 9 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 3 +- test/CXX/expr/expr.const/p3-0x.cpp | 2 +- test/CXX/over/over.over/p2.cpp | 3 +- .../addr-of-overloaded-function-casting.cpp | 8 +- test/SemaCXX/cxx1y-deduced-return-type.cpp | 15 +- test/SemaObjCXX/arc-nsconsumed-errors.mm | 6 +- test/SemaTemplate/explicit-instantiation.cpp | 15 +- .../function-template-specialization.cpp | 3 +- 15 files changed, 222 insertions(+), 473 deletions(-) diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 54f08367da..490caf091f 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -22,7 +22,6 @@ #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" @@ -657,6 +656,53 @@ 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/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9543dc549b..6501e52fe0 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -176,8 +176,6 @@ namespace clang { class VisibilityAttr; class VisibleDeclConsumer; class IndirectFieldDecl; - struct DeductionFailureInfo; - class TemplateSpecCandidateSet; namespace sema { class AccessedEntity; @@ -5775,15 +5773,16 @@ public: SourceLocation Loc, TemplatePartialOrderingContext TPOC, unsigned NumCallArguments); - 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()); + 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()); ClassTemplatePartialSpecializationDecl * getMoreSpecializedPartialSpecialization( @@ -7745,10 +7744,6 @@ public: } }; -DeductionFailureInfo -MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK, - sema::TemplateDeductionInfo &Info); - } // end namespace clang #endif diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index 1daa6891ed..8292045fdb 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -20,7 +20,6 @@ namespace clang { class TemplateArgumentList; -class Sema; namespace sema { @@ -163,124 +162,7 @@ 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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7ebcd88fe5..04aaf181af 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -548,13 +548,13 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { } namespace { - // Structure used by DeductionFailureInfo to store + // Structure used by OverloadCandidate::DeductionFailureInfo to store // template argument information. struct DFIArguments { TemplateArgument FirstArg; TemplateArgument SecondArg; }; - // Structure used by DeductionFailureInfo to store + // Structure used by OverloadCandidate::DeductionFailureInfo to store // template parameter and template argument information. struct DFIParamWithArguments : DFIArguments { TemplateParameter Param; @@ -563,10 +563,11 @@ namespace { /// \brief Convert from Sema's representation of template deduction information /// to the form used in overload-candidate information. -DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, - Sema::TemplateDeductionResult TDK, - TemplateDeductionInfo &Info) { - DeductionFailureInfo Result; +OverloadCandidate::DeductionFailureInfo +static MakeDeductionFailureInfo(ASTContext &Context, + Sema::TemplateDeductionResult TDK, + TemplateDeductionInfo &Info) { + OverloadCandidate::DeductionFailureInfo Result; Result.Result = static_cast(TDK); Result.HasDiagnostic = false; Result.Data = 0; @@ -624,7 +625,7 @@ DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, return Result; } -void DeductionFailureInfo::Destroy() { +void OverloadCandidate::DeductionFailureInfo::Destroy() { switch (static_cast(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -658,13 +659,15 @@ void DeductionFailureInfo::Destroy() { } } -PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() { +PartialDiagnosticAt * +OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() { if (HasDiagnostic) return static_cast(static_cast(Diagnostic)); return 0; } -TemplateParameter DeductionFailureInfo::getTemplateParameter() { +TemplateParameter +OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { switch (static_cast(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -692,7 +695,8 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { return TemplateParameter(); } -TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { +TemplateArgumentList * +OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { switch (static_cast(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -718,7 +722,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { return 0; } -const TemplateArgument *DeductionFailureInfo::getFirstArg() { +const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { switch (static_cast(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -744,7 +748,8 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { return 0; } -const TemplateArgument *DeductionFailureInfo::getSecondArg() { +const TemplateArgument * +OverloadCandidate::DeductionFailureInfo::getSecondArg() { switch (static_cast(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -770,7 +775,8 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { return 0; } -Expr *DeductionFailureInfo::getExpr() { +Expr * +OverloadCandidate::DeductionFailureInfo::getExpr() { if (static_cast(Result) == Sema::TDK_FailedOverloadResolution) return static_cast(Data); @@ -8122,7 +8128,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, return isTemplate ? oc_function_template : oc_function; } -void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) { +void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { const CXXConstructorDecl *Ctor = dyn_cast(Fn); if (!Ctor) return; @@ -8408,52 +8414,30 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { MaybeEmitInheritedConstructorNote(S, Fn); } -/// 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) { +void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, + unsigned NumFormalArgs) { + // TODO: treat calls to a missing default constructor as a special case + 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 in fact it looks like we have the + // have an arity mismatch when it 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 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(); + return; // 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" @@ -8461,6 +8445,9 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { 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 @@ -8482,42 +8469,25 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { MaybeEmitInheritedConstructorNote(S, Fn); } -/// 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); -} - -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, +void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) { - TemplateParameter Param = DeductionFailure.getTemplateParameter(); + FunctionDecl *Fn = Cand->Function; // pattern + + TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter(); NamedDecl *ParamD; (ParamD = Param.dyn_cast()) || (ParamD = Param.dyn_cast()) || (ParamD = Param.dyn_cast()); - switch (DeductionFailure.Result) { + switch (Cand->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(Templated->getLocation(), - diag::note_ovl_candidate_incomplete_deduction) - << ParamD->getDeclName(); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) + << ParamD->getDeclName(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -8525,7 +8495,7 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, assert(ParamD && "no parameter found for bad qualifiers deduction result"); TemplateTypeParmDecl *TParam = cast(ParamD); - QualType Param = DeductionFailure.getFirstArg()->getAsType(); + QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType(); // Param will have been canonicalized, but it should just be a // qualified version of ParamD, so move the qualifiers to that. @@ -8538,11 +8508,11 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, // 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 = DeductionFailure.getSecondArg()->getAsType(); + QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType(); - S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified) - << ParamD->getDeclName() << Arg << NonCanonParam; - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified) + << ParamD->getDeclName() << Arg << NonCanonParam; + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -8557,20 +8527,20 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, which = 2; } - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_inconsistent_deduction) - << which << ParamD->getDeclName() << *DeductionFailure.getFirstArg() - << *DeductionFailure.getSecondArg(); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction) + << which << ParamD->getDeclName() + << *Cand->DeductionFailure.getFirstArg() + << *Cand->DeductionFailure.getSecondArg(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } case Sema::TDK_InvalidExplicitArguments: assert(ParamD && "no parameter found for invalid explicit arguments"); if (ParamD->getDeclName()) - S.Diag(Templated->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_named) - << ParamD->getDeclName(); + << ParamD->getDeclName(); else { int index = 0; if (TemplateTypeParmDecl *TTP = dyn_cast(ParamD)) @@ -8580,36 +8550,35 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, index = NTTP->getIndex(); else index = cast(ParamD)->getIndex(); - S.Diag(Templated->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) - << (index + 1); + << (index + 1); } - MaybeEmitInheritedConstructorNote(S, Templated); + MaybeEmitInheritedConstructorNote(S, Fn); return; case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: - DiagnoseArityMismatch(S, Templated, NumArgs); + DiagnoseArityMismatch(S, Cand, NumArgs); return; case Sema::TDK_InstantiationDepth: - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_instantiation_depth); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth); + MaybeEmitInheritedConstructorNote(S, Fn); return; case Sema::TDK_SubstitutionFailure: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; if (TemplateArgumentList *Args = - DeductionFailure.getTemplateArgumentList()) { + Cand->DeductionFailure.getTemplateArgumentList()) { TemplateArgString = " "; TemplateArgString += S.getTemplateArgumentBindingsText( - getDescribedTemplate(Templated)->getTemplateParameters(), *Args); + Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args); } // If this candidate was disabled by enable_if, say so. - PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic(); + PartialDiagnosticAt *PDiag = Cand->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 @@ -8630,25 +8599,25 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString); } - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_substitution_failure) - << TemplateArgString << SFINAEArgString << R; - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) + << TemplateArgString << SFINAEArgString << R; + MaybeEmitInheritedConstructorNote(S, Fn); return; } case Sema::TDK_FailedOverloadResolution: { - OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr()); - S.Diag(Templated->getLocation(), + OverloadExpr::FindResult R = + OverloadExpr::find(Cand->DeductionFailure.getExpr()); + S.Diag(Fn->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 = *DeductionFailure.getFirstArg(); - TemplateArgument SecondTA = *DeductionFailure.getSecondArg(); + TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg(); + TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg(); if (FirstTA.getKind() == TemplateArgument::Template && SecondTA.getKind() == TemplateArgument::Template) { TemplateName FirstTN = FirstTA.getAsTemplate(); @@ -8663,38 +8632,26 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, // 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(Templated->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch_qualified) << FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl(); return; } } } - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_non_deduced_mismatch) - << FirstTA << SecondTA; + S.Diag(Fn->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(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); + MaybeEmitInheritedConstructorNote(S, Fn); 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); @@ -8842,7 +8799,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, } } -static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { +SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { if (Cand->Function) return Cand->Function->getLocation(); if (Cand->IsSurrogate) @@ -8850,7 +8807,8 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { return SourceLocation(); } -static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { +static unsigned +RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { switch ((Sema::TemplateDeductionResult)DFI.Result) { case Sema::TDK_Success: llvm_unreachable("TDK_success while diagnosing bad deduction"); @@ -9143,108 +9101,6 @@ 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) @@ -9287,19 +9143,18 @@ 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), - FailedCandidates(OvlExpr->getNameLoc()) { + 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) + { ExtractUnqualifiedFunctionTypeFromTargetType(); if (!TargetFunctionType->isFunctionType()) { @@ -9377,16 +9232,13 @@ private: // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(OvlExpr->getNameLoc()); if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(FunctionTemplate, &OvlExplicitTemplateArgs, TargetFunctionType, Specialization, Info, /*InOverloadResolution=*/true)) { - // Make a note of the failed deduction for diagnostics. - FailedCandidates.addCandidate() - .set(FunctionTemplate->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, Result, Info)); + // FIXME: make a note of the failed deduction for diagnostics. (void)Result; return false; } @@ -9491,15 +9343,15 @@ private: for (unsigned I = 0, E = Matches.size(); I != E; ++I) MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); - // 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); + 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); if (Result != MatchesCopy.end()) { // Make it the first and only element @@ -9528,7 +9380,6 @@ 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); } @@ -9645,7 +9496,6 @@ 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. @@ -9668,16 +9518,12 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info, /*InOverloadResolution=*/true)) { - // 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)); + // FIXME: make a note of the failed deduction for diagnostics. (void)Result; continue; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7939c48c64..6f1ab19f10 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/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,16 +5969,13 @@ bool Sema::CheckFunctionTemplateSpecialization( // Perform template argument deduction to determine whether we may be // specializing this template. // FIXME: It is somewhat wasteful to build - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(FD->getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT, Specialization, Info)) { - // Template argument deduction failed; record why it failed, so + // FIXME: 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; } @@ -5989,14 +5986,14 @@ bool Sema::CheckFunctionTemplateSpecialization( } // Find the most specialized function template. - 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)); - + 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)); if (Result == Candidates.end()) return true; @@ -6815,7 +6812,6 @@ 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; @@ -6835,16 +6831,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!FunTmpl) continue; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(D.getIdentifierLoc()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, (HasExplicitTemplateArgs ? &TemplateArgs : 0), R, Specialization, Info)) { - // Keep track of almost-matches. - FailedCandidates.addCandidate() - .set(FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK, Info)); + // FIXME: Keep track of almost-matches? (void)TDK; continue; } @@ -6853,12 +6846,12 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, } // Find the most specialized function template specialization. - 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)); + 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)); if (Result == Matches.end()) return true; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 8d6aaa096d..29ee6dfa99 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -4148,18 +4148,23 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// /// \returns the most specialized function template specialization, if /// found. Otherwise, returns SpecEnd. -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) { +/// +/// \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) { if (SpecBegin == SpecEnd) { - if (Complain) { + if (Complain) Diag(Loc, NoneDiag); - FailedCandidates.NoteCandidates(*this, Loc); - } return SpecEnd; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 7632bba8c9..3904daa47f 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2252,18 +2252,15 @@ 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(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(PointOfInstantiation); if (TemplateDeductionResult Result = DeduceTemplateArguments(Partial, ClassTemplateSpec->getTemplateArgs(), Info)) { - // 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)); + // FIXME: Store the failed-deduction information for use in + // diagnostics, later. (void)Result; } else { Matched.push_back(PartialSpecMatchResult()); diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index cf422972a2..122a400d9b 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -72,8 +72,7 @@ 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; // expected-note {{candidate template ignored: could not match 'T () const' against 'char ()'}} + template T g() const; }; // explicit specialization can differ in constepxr diff --git a/test/CXX/expr/expr.const/p3-0x.cpp b/test/CXX/expr/expr.const/p3-0x.cpp index e3e32dfe09..047e238190 100644 --- a/test/CXX/expr/expr.const/p3-0x.cpp +++ b/test/CXX/expr/expr.const/p3-0x.cpp @@ -93,7 +93,7 @@ void c() { break; } } -template int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}} +template int f() { return 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/test/CXX/over/over.over/p2.cpp b/test/CXX/over/over.over/p2.cpp index b6c1d6bfa2..3e8d0f1d8c 100644 --- a/test/CXX/over/over.over/p2.cpp +++ b/test/CXX/over/over.over/p2.cpp @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template -T f0(T, T); // expected-note{{candidate}} expected-note{{candidate function}} +template T f0(T, T); //expected-note{{candidate}} void test_f0() { int (*f0a)(int, int) = f0; diff --git a/test/SemaCXX/addr-of-overloaded-function-casting.cpp b/test/SemaCXX/addr-of-overloaded-function-casting.cpp index 8698736b3a..cfd55eed81 100644 --- a/test/SemaCXX/addr-of-overloaded-function-casting.cpp +++ b/test/SemaCXX/addr-of-overloaded-function-casting.cpp @@ -4,12 +4,8 @@ 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}} \ - // 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 t(T); // expected-note 6{{candidate function}} +template void t(T*); // expected-note 6{{candidate function}} template void u(T); diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index 743ef4fbf2..d3067eb411 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -112,8 +112,7 @@ 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(); // expected-note {{candidate template ignored: could not match 'auto ()' against 'int ()'}} + template auto fwd_decl(); int g = fwd_decl(); auto (*p)() = f1; // expected-error {{incompatible initializer}} @@ -127,8 +126,7 @@ 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}} \ - // expected-note {{candidate template ignored: could not match 'auto ()' against 'void ()'}} + template auto instantiate() { T::error; } // expected-error {{has no members}} extern template auto instantiate(); // ok int k = instantiate(); // expected-note {{in instantiation of}} template<> auto instantiate() {} // ok @@ -159,8 +157,7 @@ namespace Templates { double &mem_check4 = take_fn(Outer::arg_multi); namespace Deduce1 { - template auto f() { return 0; } // expected-note {{candidate}} \ - // expected-note {{candidate function has different return type ('int' expected but has 'auto')}} + template auto f() { return 0; } // expected-note {{candidate}} template void g(T(*)()); // expected-note 2{{candidate}} void h() { auto p = f; @@ -173,8 +170,7 @@ namespace Templates { } namespace Deduce2 { - template auto f(int) { return 0; } // expected-note {{candidate}} \ - // expected-note {{candidate function has different return type ('int' expected but has 'auto')}} + template auto f(int) { return 0; } // expected-note {{candidate}} template void g(T(*)(int)); // expected-note 2{{candidate}} void h() { auto p = f; @@ -326,8 +322,7 @@ 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}} \ - // expected-note {{candidate function [with T = int]}} + template auto g(T t) { return t; } // expected-note {{candidate}} template auto g(int); template char g(char); // expected-error {{does not refer to a function}} template<> auto g(double); diff --git a/test/SemaObjCXX/arc-nsconsumed-errors.mm b/test/SemaObjCXX/arc-nsconsumed-errors.mm index c1ce81b669..10ae10d049 100644 --- a/test/SemaObjCXX/arc-nsconsumed-errors.mm +++ b/test/SemaObjCXX/arc-nsconsumed-errors.mm @@ -29,13 +29,11 @@ void releaser(__attribute__((ns_consumed)) id); releaser_t r2 = releaser; // no-warning template -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}} +void templateFunction(T) {} // expected-note {{candidate function}} 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) { } // expected-note 2{{candidate template ignored: failed template argument deduction}} +void templateReleaser(__attribute__((ns_consumed)) T) {} releaser_t r4 = templateReleaser; // no-warning diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp index 04a863bdc1..e3e77d0828 100644 --- a/test/SemaTemplate/explicit-instantiation.cpp +++ b/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(); } // 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 + T f0(T, U) { return T(); } }; template @@ -59,14 +59,13 @@ template int *X2::f1(int *); // okay template void X2::f2(int *, int *); // expected-error{{ambiguous}} -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(); -template -void print_type(T *) {} // expected-note {{candidate template ignored: could not match 'void (int *)' against 'void (float *)'}} +template void print_type(T*) { } template void print_type(int*); template void print_type(float*); // expected-error{{does not refer}} @@ -95,7 +94,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/test/SemaTemplate/function-template-specialization.cpp b/test/SemaTemplate/function-template-specialization.cpp index 6327ff64c3..2338b6701c 100644 --- a/test/SemaTemplate/function-template-specialization.cpp +++ b/test/SemaTemplate/function-template-specialization.cpp @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template -void f0(int (&array)[N]); // expected-note {{candidate template ignored: could not match 'int' against 'char'}} +template void f0(int (&array)[N]); // Simple function template specialization (using overloading) template<> void f0(int (&array)[1]); -- 2.40.0