Index: lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- lib/Sema/SemaTemplateDeduction.cpp +++ lib/Sema/SemaTemplateDeduction.cpp @@ -1056,6 +1056,12 @@ return false; } +static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatchInner( + Sema &S, TemplateParameterList *TemplateParams, QualType ParamIn, + QualType ArgIn, TemplateDeductionInfo &Info, + SmallVectorImpl &Deduced, unsigned TDF, + bool PartialOrdering, bool DeducedFromArrayBound); + /// \brief Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// @@ -1080,15 +1086,34 @@ /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. -static Sema::TemplateDeductionResult -DeduceTemplateArgumentsByTypeMatch(Sema &S, - TemplateParameterList *TemplateParams, - QualType ParamIn, QualType ArgIn, - TemplateDeductionInfo &Info, - SmallVectorImpl &Deduced, - unsigned TDF, - bool PartialOrdering, - bool DeducedFromArrayBound) { +static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( + Sema &S, TemplateParameterList *TemplateParams, QualType ParamIn, + QualType ArgIn, TemplateDeductionInfo &Info, + SmallVectorImpl &Deduced, unsigned TDF, + bool PartialOrdering, bool DeducedFromArrayBound) { + // Because DeduceTemplateArgumentsByTypeMatchInner is recursive, and tends to + // modify Info.FirstArg and SecondArg even when deduction succeeds, save the + // original values and restore them if no error occurred. + const auto OriginalFirstArg = Info.FirstArg; + const auto OriginalSecondArg = Info.SecondArg; + + const auto Result = DeduceTemplateArgumentsByTypeMatchInner( + S, TemplateParams, ParamIn, ArgIn, Info, Deduced, TDF, PartialOrdering, + DeducedFromArrayBound); + + if (Result == Sema::TDK_Success) { + Info.FirstArg = OriginalFirstArg; + Info.SecondArg = OriginalSecondArg; + } + return Result; +} + +/// \see DeduceTemplateArgumentsByTypeMatch() +static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatchInner( + Sema &S, TemplateParameterList *TemplateParams, QualType ParamIn, + QualType ArgIn, TemplateDeductionInfo &Info, + SmallVectorImpl &Deduced, unsigned TDF, + bool PartialOrdering, bool DeducedFromArrayBound) { // We only want to look at the canonical types, since typedefs and // sugar are not part of template argument deduction. QualType Param = S.Context.getCanonicalType(ParamIn); 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}} + } +}