Index: lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- lib/Sema/SemaTemplateDeduction.cpp +++ lib/Sema/SemaTemplateDeduction.cpp @@ -1289,10 +1289,6 @@ return Sema::TDK_Success; } - // Set up the template argument deduction information for a failure. - Info.FirstArg = TemplateArgument(ParamIn); - Info.SecondArg = TemplateArgument(ArgIn); - // If the parameter is an already-substituted template parameter // pack, do nothing: we don't know which of its arguments to look // at, so we have to wait until all of the parameter packs in this @@ -1300,16 +1296,27 @@ if (isa(Param)) return Sema::TDK_Success; + // Use this when returning a failure result in order to fill in the + // corresponding failure info. Don't use this when returning the + // result of a recursive call, as the callee will have already set + // their own failure info. + const auto WithFailureInfo = + [&Info, &ParamIn, &ArgIn](Sema::TemplateDeductionResult Result) { + Info.FirstArg = TemplateArgument(ParamIn); + Info.SecondArg = TemplateArgument(ArgIn); + return Result; + }; + // Check the cv-qualifiers on the parameter and argument types. CanQualType CanParam = S.Context.getCanonicalType(Param); CanQualType CanArg = S.Context.getCanonicalType(Arg); if (!(TDF & TDF_IgnoreQualifiers)) { if (TDF & TDF_ParamWithReferenceType) { if (hasInconsistentOrSupersetQualifiersOf(Param, Arg)) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } else if (!IsPossiblyOpaquelyQualifiedType(Param)) { if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } // If the parameter type is not dependent, there is nothing to deduce. @@ -1319,9 +1326,8 @@ (TDF & TDF_AllowCompatibleFunctionType) ? !S.isSameOrCompatibleFunctionType(CanParam, CanArg) : Param != Arg; - if (NonDeduced) { - return Sema::TDK_NonDeducedMismatch; - } + if (NonDeduced) + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } return Sema::TDK_Success; } @@ -1366,7 +1372,10 @@ Arg = Arg.getUnqualifiedType(); } - return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch; + if (Param == Arg) + return Sema::TDK_Success; + + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } // _Complex T [placeholder extension] @@ -1377,7 +1386,7 @@ ComplexArg->getElementType(), Info, Deduced, TDF); - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); // _Atomic T [extension] case Type::Atomic: @@ -1387,7 +1396,7 @@ AtomicArg->getValueType(), Info, Deduced, TDF); - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); // T * case Type::Pointer: { @@ -1398,7 +1407,7 @@ = Arg->getAs()) { PointeeType = PointerArg->getPointeeType(); } else { - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass); @@ -1413,7 +1422,7 @@ const LValueReferenceType *ReferenceArg = Arg->getAs(); if (!ReferenceArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, cast(Param)->getPointeeType(), @@ -1425,7 +1434,7 @@ const RValueReferenceType *ReferenceArg = Arg->getAs(); if (!ReferenceArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, cast(Param)->getPointeeType(), @@ -1438,7 +1447,7 @@ const IncompleteArrayType *IncompleteArrayArg = S.Context.getAsIncompleteArrayType(Arg); if (!IncompleteArrayArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); unsigned SubTDF = TDF & TDF_IgnoreQualifiers; return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, @@ -1452,12 +1461,12 @@ const ConstantArrayType *ConstantArrayArg = S.Context.getAsConstantArrayType(Arg); if (!ConstantArrayArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); const ConstantArrayType *ConstantArrayParm = S.Context.getAsConstantArrayType(Param); if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize()) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); unsigned SubTDF = TDF & TDF_IgnoreQualifiers; return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, @@ -1470,7 +1479,7 @@ case Type::DependentSizedArray: { const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg); if (!ArrayArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); unsigned SubTDF = TDF & TDF_IgnoreQualifiers; @@ -1510,7 +1519,7 @@ Info, Deduced); // Incomplete type does not match a dependently-sized array type - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } // type(*)(T) @@ -1521,7 +1530,7 @@ const FunctionProtoType *FunctionProtoArg = dyn_cast(Arg); if (!FunctionProtoArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); const FunctionProtoType *FunctionProtoParam = cast(Param); @@ -1531,7 +1540,7 @@ FunctionProtoParam->getRefQualifier() != FunctionProtoArg->getRefQualifier() || FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic()) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); // Check return types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( @@ -1715,7 +1724,7 @@ const MemberPointerType *MemPtrParam = cast(Param); const MemberPointerType *MemPtrArg = dyn_cast(Arg); if (!MemPtrArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); QualType ParamPointeeType = MemPtrParam->getPointeeType(); if (ParamPointeeType->isFunctionType()) @@ -1751,7 +1760,7 @@ const BlockPointerType *BlockPtrArg = dyn_cast(Arg); if (!BlockPtrArg) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, BlockPtrParam->getPointeeType(), @@ -1767,7 +1776,7 @@ if (const ExtVectorType *VectorArg = dyn_cast(Arg)) { // Make sure that the vectors have the same number of elements. if (VectorParam->getNumElements() != VectorArg->getNumElements()) - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); // Perform deduction on the element types. return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, @@ -1789,7 +1798,7 @@ Info, Deduced, TDF); } - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } // (clang extension) @@ -1845,7 +1854,7 @@ Info, Deduced); } - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } // (clang extension) @@ -1898,7 +1907,7 @@ true, Info, Deduced); } - return Sema::TDK_NonDeducedMismatch; + return WithFailureInfo(Sema::TDK_NonDeducedMismatch); } case Type::TypeOfExpr: Index: test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp =================================================================== --- test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp +++ test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -45,3 +45,11 @@ func(foo()); // expected-error {{no matching function}} } } + +namespace test4 { + // expected-note@+1 {{candidate template ignored: could not match 'int [N]' against 'int []'}} + template void f1(int (&arr)[N]); + template void f2(int (&arr)[]) { + f1(arr); // expected-error {{no matching function}} + } +}