Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -4144,10 +4144,9 @@ bool resolveAndFixAddressOfSingleOverloadCandidate( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); - FunctionDecl * - ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, - bool Complain = false, - DeclAccessPair *Found = nullptr); + FunctionDecl *ResolveSingleFunctionTemplateSpecialization( + OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr, + TemplateSpecCandidateSet *FailedTSC = nullptr); bool ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false, @@ -9133,11 +9132,12 @@ TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); - TemplateDeductionResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, - QualType &Result, - sema::TemplateDeductionInfo &Info, - bool DependentDeduction = false, - bool IgnoreConstraints = false); + TemplateDeductionResult + DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result, + sema::TemplateDeductionInfo &Info, + bool DependentDeduction = false, + bool IgnoreConstraints = false, + TemplateSpecCandidateSet *FailedTSC = nullptr); void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); Index: clang/include/clang/Sema/TemplateDeduction.h =================================================================== --- clang/include/clang/Sema/TemplateDeduction.h +++ clang/include/clang/Sema/TemplateDeduction.h @@ -335,7 +335,8 @@ void destroyCandidates(); public: - TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false) + TemplateSpecCandidateSet(SourceLocation Loc = SourceLocation{}, + bool ForTakingAddress = false) : Loc(Loc), ForTakingAddress(ForTakingAddress) {} TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete; TemplateSpecCandidateSet & @@ -343,6 +344,7 @@ ~TemplateSpecCandidateSet() { destroyCandidates(); } SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } /// Clear out all of the candidates. /// TODO: This may be unnecessary. Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -12799,10 +12799,9 @@ /// /// If no template-ids are found, no diagnostics are emitted and NULL is /// returned. -FunctionDecl * -Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, - bool Complain, - DeclAccessPair *FoundResult) { +FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( + OverloadExpr *ovl, bool Complain, DeclAccessPair *FoundResult, + TemplateSpecCandidateSet *FailedTSC) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] @@ -12816,7 +12815,8 @@ TemplateArgumentListInfo ExplicitTemplateArgs; ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); - TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc()); + if (FailedTSC) + FailedTSC->setLocation(ovl->getNameLoc()); // Look through all of the overloaded functions, searching for one // whose type matches exactly. @@ -12839,16 +12839,16 @@ // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = nullptr; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info, /*IsAddressOfFunction*/true)) { // Make a note of the failed deduction for diagnostics. - // TODO: Actually use the failed-deduction info? - FailedCandidates.addCandidate() - .set(I.getPair(), FunctionTemplate->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, Result, Info)); + if (FailedTSC) + FailedTSC->addCandidate().set( + I.getPair(), FunctionTemplate->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, Result, Info)); continue; } Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -3825,9 +3825,12 @@ { // Otherwise, [...] deduce a value for U using the rules of template // argument deduction. - TemplateDeductionInfo Info(RetExpr->getExprLoc()); - TemplateDeductionResult Res = - DeduceAutoType(OrigResultType, RetExpr, Deduced, Info); + auto RetExprLoc = RetExpr->getExprLoc(); + TemplateDeductionInfo Info(RetExprLoc); + TemplateSpecCandidateSet FailedTSC; + TemplateDeductionResult Res = DeduceAutoType( + OrigResultType, RetExpr, Deduced, Info, /*DependentDeduction=*/false, + /*IgnoreConstraints=*/false, &FailedTSC); if (Res != TDK_Success && FD->isInvalidDecl()) return true; switch (Res) { @@ -3853,6 +3856,7 @@ default: Diag(RetExpr->getExprLoc(), diag::err_auto_fn_deduction_failure) << OrigResultType.getType() << RetExpr->getType(); + FailedTSC.NoteCandidates(*this, RetExprLoc); return true; } } Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3748,7 +3748,8 @@ static QualType ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, Expr *Arg, QualType ParamType, - bool ParamWasReference) { + bool ParamWasReference, + TemplateSpecCandidateSet *FailedTSC = nullptr) { OverloadExpr::FindResult R = OverloadExpr::find(Arg); @@ -3770,8 +3771,10 @@ !ParamType->isMemberFunctionPointerType()) { if (Ovl->hasExplicitTemplateArgs()) { // But we can still look for an explicit specialization. - if (FunctionDecl *ExplicitSpec - = S.ResolveSingleFunctionTemplateSpecialization(Ovl)) + if (FunctionDecl *ExplicitSpec = + S.ResolveSingleFunctionTemplateSpecialization( + Ovl, /*Complain=*/false, + /*FoundDeclAccessPair=*/nullptr, FailedTSC)) return GetTypeOfFunction(S, R, ExplicitSpec); } @@ -3853,7 +3856,8 @@ /// overloaded function set that could not be resolved. static bool AdjustFunctionParmAndArgTypesForDeduction( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType &ParamType, QualType &ArgType, Expr *Arg, unsigned &TDF) { + QualType &ParamType, QualType &ArgType, Expr *Arg, unsigned &TDF, + TemplateSpecCandidateSet *FailedTSC = nullptr) { // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P's type // are ignored for type deduction. @@ -3870,9 +3874,8 @@ // but there are sometimes special circumstances. Typically // involving a template-id-expr. if (ArgType == S.Context.OverloadTy) { - ArgType = ResolveOverloadForDeduction(S, TemplateParams, - Arg, ParamType, - ParamRefType != nullptr); + ArgType = ResolveOverloadForDeduction(S, TemplateParams, Arg, ParamType, + ParamRefType != nullptr, FailedTSC); if (ArgType.isNull()) return true; } @@ -3950,7 +3953,8 @@ QualType ParamType, Expr *Arg, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, SmallVectorImpl &OriginalCallArgs, - bool DecomposedParam, unsigned ArgIdx, unsigned TDF); + bool DecomposedParam, unsigned ArgIdx, unsigned TDF, + TemplateSpecCandidateSet *FailedTSC = nullptr); /// Attempt template argument deduction from an initializer list /// deemed to be an argument in a function call. @@ -4026,14 +4030,16 @@ QualType ParamType, Expr *Arg, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, SmallVectorImpl &OriginalCallArgs, - bool DecomposedParam, unsigned ArgIdx, unsigned TDF) { + bool DecomposedParam, unsigned ArgIdx, unsigned TDF, + TemplateSpecCandidateSet *FailedTSC) { QualType ArgType = Arg->getType(); QualType OrigParamType = ParamType; // If P is a reference type [...] // If P is a cv-qualified type [...] - if (AdjustFunctionParmAndArgTypesForDeduction( - S, TemplateParams, FirstInnerIndex, ParamType, ArgType, Arg, TDF)) + if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, + FirstInnerIndex, ParamType, + ArgType, Arg, TDF, FailedTSC)) return Sema::TDK_Success; // If [...] the argument is a non-empty initializer list [...] @@ -4716,11 +4722,11 @@ /// should be specified in the 'Info' parameter. /// \param IgnoreConstraints Set if we should not fail if the deduced type does /// not satisfy the type-constraint in the auto type. -Sema::TemplateDeductionResult Sema::DeduceAutoType(TypeLoc Type, Expr *Init, - QualType &Result, - TemplateDeductionInfo &Info, - bool DependentDeduction, - bool IgnoreConstraints) { +Sema::TemplateDeductionResult +Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, + TemplateDeductionInfo &Info, bool DependentDeduction, + bool IgnoreConstraints, + TemplateSpecCandidateSet *FailedTSC) { assert(DependentDeduction || Info.getDeducedDepth() == 0); if (Init->containsErrors()) return TDK_AlreadyDiagnosed; @@ -4834,7 +4840,8 @@ "substituting template parameter for 'auto' failed"); if (auto TDK = DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), 0, FuncParam, Init, Info, Deduced, - OriginalCallArgs, /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0)) + OriginalCallArgs, /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, + FailedTSC)) return DeductionFailed(TDK); } Index: clang/test/SemaCXX/auto-type-from-cxx.cpp =================================================================== --- clang/test/SemaCXX/auto-type-from-cxx.cpp +++ clang/test/SemaCXX/auto-type-from-cxx.cpp @@ -18,3 +18,28 @@ new __auto_type; // expected-error {{'__auto_type' not allowed in type allocated by 'new'}} } +namespace TestDeductionFail { + +template +void caller(T x) {x.fun();} // expected-note {{candidate template ignored: substitution failure [with T = TestDeductionFail::Abstract]: parameter type 'TestDeductionFail::Abstract' is an abstract class}} + +template +auto getCaller(){ + return caller; // expected-error {{cannot deduce return type 'auto' from returned value of type ''}} +} + +class Abstract{ + public: + void fun(); + virtual void vfun()=0; + void call(){getCaller()(*this);} // expected-note {{in instantiation of function template specialization 'TestDeductionFail::getCaller' requested here}} +}; + +class Derived: public Abstract{ + public: + void vfun(); +}; + +Derived X; + +}