Author: Younan Zhang Date: 2026-05-09T13:50:27+08:00 New Revision: 6f2df1cb20cc4e6625a86670903bca6852474cb6
URL: https://github.com/llvm/llvm-project/commit/6f2df1cb20cc4e6625a86670903bca6852474cb6 DIFF: https://github.com/llvm/llvm-project/commit/6f2df1cb20cc4e6625a86670903bca6852474cb6.diff LOG: [Clang] Do not eat SFINAE diagnostics for explicit template arguments (#139066) Instead of merely suggesting the template arguments are invalid, we now provide an explanation of why the explicit template argument is invalid. Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaOverload.cpp clang/test/AST/ByteCode/cxx20.cpp clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp clang/test/CXX/drs/cwg2xx.cpp clang/test/CXX/drs/cwg3xx.cpp clang/test/CXX/expr/expr.const/p3-0x.cpp clang/test/CXX/temp/temp.param/p8-cxx20.cpp clang/test/CXX/temp/temp.res/temp.local/p1.cpp clang/test/Modules/cxx-templates.cpp clang/test/SemaCXX/builtin-align-cxx.cpp clang/test/SemaCXX/calling-conv-compat.cpp clang/test/SemaCXX/constexpr-function-recovery-crash.cpp clang/test/SemaCXX/cxx2a-template-lambdas.cpp clang/test/SemaCXX/typo-correction.cpp clang/test/SemaSYCL/sycl-kernel-launch.cpp clang/test/SemaTemplate/concepts-using-decl.cpp clang/test/SemaTemplate/overload-candidates.cpp clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2a7c315192f2d..fa19d4b576575 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -476,6 +476,8 @@ Improvements to Clang's diagnostics code can automatically be made portable to other host platforms that don't support backslashes. +- Clang now explains why template deduction fails for explicit template arguments. + - No longer emitting a ``-Wpre-c2y-compat`` or extension diagnostic about use of octal literals with a ``0o`` prefix, and no longer emitting a ``-Wdeprecated-octal-literals`` diagnostic for use of octal literals without diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9605c02b819d4..c638c23f24bb5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5231,14 +5231,14 @@ def note_ovl_candidate_inconsistent_deduction_types : Note< "candidate template ignored: deduced values % diff {" "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|" "%1 and %3 of conflicting types for parameter %0}2,4">; -def note_ovl_candidate_explicit_arg_mismatch_named : Note< - "candidate template ignored: invalid explicitly-specified argument " - "for template parameter %0">; def note_ovl_candidate_unsatisfied_constraints : Note< "candidate template ignored: constraints not satisfied%0">; -def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note< - "candidate template ignored: invalid explicitly-specified argument " - "for %ordinal0 template parameter">; +def note_ovl_candidate_explicit_arg_mismatch : Note< + "candidate template ignored: %enum_select<ExplicitArgMismatchReasonKind>{" + "%Vague{invalid explicitly-specified argument}|" + "%Detailed{%3}}2 for %enum_select<ExplicitArgMismatchNameKind>{" + "%Named{template parameter %1}|" + "%Unnamed{%ordinal1 template parameter}}0">; def note_ovl_candidate_instantiation_depth : Note< "candidate template ignored: substitution exceeded maximum template " "instantiation depth">; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 96c4ce489fe04..693aae757eb5a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/SemaAMDGPU.h" #include "clang/Sema/SemaARM.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" @@ -764,8 +765,16 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; case TemplateDeductionResult::Incomplete: + Result.Data = Info.Param.getOpaqueValue(); + break; case TemplateDeductionResult::InvalidExplicitArguments: Result.Data = Info.Param.getOpaqueValue(); + if (Info.hasSFINAEDiagnostic()) { + PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt( + SourceLocation(), PartialDiagnostic::NullDiagnostic()); + Info.takeSFINAEDiagnostic(*Diag); + Result.HasDiagnostic = true; + } break; case TemplateDeductionResult::DeducedMismatch: @@ -837,7 +846,6 @@ void DeductionFailureInfo::Destroy() { case TemplateDeductionResult::Incomplete: case TemplateDeductionResult::TooManyArguments: case TemplateDeductionResult::TooFewArguments: - case TemplateDeductionResult::InvalidExplicitArguments: case TemplateDeductionResult::CUDATargetMismatch: case TemplateDeductionResult::NonDependentConversionFailure: break; @@ -852,6 +860,7 @@ void DeductionFailureInfo::Destroy() { Data = nullptr; break; + case TemplateDeductionResult::InvalidExplicitArguments: case TemplateDeductionResult::SubstitutionFailure: // FIXME: Destroy the template argument list? Data = nullptr; @@ -12479,28 +12488,27 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } - case TemplateDeductionResult::InvalidExplicitArguments: + case TemplateDeductionResult::InvalidExplicitArguments: { assert(ParamD && "no parameter found for invalid explicit arguments"); + + auto Diag = S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_explicit_arg_mismatch); if (ParamD->getDeclName()) - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_explicit_arg_mismatch_named) - << ParamD->getDeclName(); - else { - int index = 0; - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD)) - index = TTP->getIndex(); - else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) - index = NTTP->getIndex(); - else - index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex(); - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) - << (index + 1); + Diag << diag::ExplicitArgMismatchNameKind::Named << ParamD->getDeclName(); + else + Diag << diag::ExplicitArgMismatchNameKind::Unnamed + << (getDepthAndIndex(ParamD).second + 1); + if (PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic()) { + SmallString<128> DiagContent; + PDiag->second.EmitToString(S.getDiagnostics(), DiagContent); + Diag << diag::ExplicitArgMismatchReasonKind::Detailed << DiagContent; + } else { + Diag << diag::ExplicitArgMismatchReasonKind::Vague; } + MaybeEmitInheritedConstructorNote(S, Found); return; - + } case TemplateDeductionResult::ConstraintsNotSatisfied: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp index b051c3a4984d9..d67357459653a 100644 --- a/clang/test/AST/ByteCode/cxx20.cpp +++ b/clang/test/AST/ByteCode/cxx20.cpp @@ -775,7 +775,7 @@ namespace FailingDestructor { } }; template<D d> - void f() {} // both-note {{invalid explicitly-specified argument}} + void f() {} // both-note {{non-type template argument is not a constant expression}} void g() { f<D{0, false}>(); // both-error {{no matching function}} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp index f12e0083fb0c9..8805e8f10dbdd 100644 --- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp @@ -113,21 +113,21 @@ namespace test3 { struct Derived1 : Base { using Base::foo; - template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} + template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{template argument for non-type template parameter must be an expression for template parameter 'n'}} }; struct Derived2 : Base { - template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} + template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{template argument for non-type template parameter must be an expression for template parameter 'n'}} using Base::foo; }; struct Derived3 : Base { using Base::foo; - template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} + template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{template argument for template type parameter must be a type for template parameter 'T'}} }; struct Derived4 : Base { - template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} + template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{template argument for template type parameter must be a type for template parameter 'T'}} using Base::foo; }; diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index 427320082a450..f81ab02e7d748 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -681,15 +681,15 @@ namespace cwg241 { // cwg241: 9 A::g<3>(b); C::f<3>(b); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}} + // expected-note@#cwg241-C-f {{candidate template ignored: template argument for template type parameter must be a type for template parameter 'T'}} C::g<3>(b); // expected-error@-1 {{no matching function for call to 'g'}} - // expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}} + // expected-note@#cwg241-C-g {{candidate template ignored: template argument for template type parameter must be a type for template parameter 'T'}} using C::f; using C::g; f<3>(b); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}} + // expected-note@#cwg241-C-f {{candidate template ignored: template argument for template type parameter must be a type for template parameter 'T'}} // expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}} g<3>(b); } @@ -983,7 +983,7 @@ namespace cwg258 { // cwg258: 2.8 int &w = b.f(0); int &x = b.g<int>(0); // expected-error@-1 {{no matching member function for call to 'g'}} - // expected-note@#cwg258-B-g {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} + // expected-note@#cwg258-B-g {{candidate template ignored: template argument for non-type template parameter must be an expression for 1st template parameter}} int &y = b.h(); float &z = const_cast<const B&>(b).h(); diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp index 1b7b273f76b66..10bf57e422f33 100644 --- a/clang/test/CXX/drs/cwg3xx.cpp +++ b/clang/test/CXX/drs/cwg3xx.cpp @@ -975,8 +975,8 @@ namespace cwg354 { // cwg354: 3.1 c++11 int b0 = both<0>(); int b1 = both<(int*)0>(); // cxx98-error@-1 {{no matching function for call to 'both'}} - // cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} - // cxx98-note@#cwg354-both-int {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} + // cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: non-type template argument does not refer to any declaration for 1st template parameter}} + // cxx98-note@#cwg354-both-int {{candidate template ignored: non-type template argument of type 'int *' must have an integral or enumeration type for 1st template parameter}} template<int S::*> struct ptr_mem {}; // #cwg354-ptr_mem ptr_mem<0> m0; // #cwg354-m0 diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp index 3eedef3cf7712..eb7d59f679e6b 100644 --- a/clang/test/CXX/expr/expr.const/p3-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp @@ -107,7 +107,7 @@ void c() { break; } } -template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}} +template <bool B> int f() { return B; } // expected-note {{candidate template ignored: conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression 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/temp/temp.param/p8-cxx20.cpp b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp index a3478c0669661..9b1d697cd9805 100644 --- a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp +++ b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp @@ -40,7 +40,7 @@ namespace ConstDestruction { }; template<D d> - void f() {} // expected-note 2{{invalid explicitly-specified argument}} + void f() {} // expected-note 2{{non-type template argument is not a constant expression}} void g() { f<D{0, true}>(); diff --git a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp index faa85cb5fce30..c6d7f194182dd 100644 --- a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp +++ b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp @@ -10,9 +10,9 @@ template<typename> char id; template<typename> struct TempType {}; template<template<typename> class> struct TempTemp {}; -template<typename> void use(int&); // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}} +template<typename> void use(int&); // expected-note {{use of class template 'B::template C' requires template arguments}} expected-note {{no known conversion}} template<template<typename> class> void use(float&); // expected-note 2{{no known conversion}} -template<int> void use(char&); // expected-note 2{{invalid explicitly-specified argument}} +template<int> void use(char&); // expected-note 2{{template argument for non-type template parameter must be an expression}} template<typename T> struct A { template<typename> struct C {}; diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp index 1537682f37438..15f6091774424 100644 --- a/clang/test/Modules/cxx-templates.cpp +++ b/clang/test/Modules/cxx-templates.cpp @@ -42,7 +42,7 @@ void g() { template_param_kinds_1<int>(); // ok, from cxx-templates-b.h template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function for call}} - // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}} + // expected-note@Inputs/cxx-templates-a.h:11 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}} // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}} template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}} diff --git a/clang/test/SemaCXX/builtin-align-cxx.cpp b/clang/test/SemaCXX/builtin-align-cxx.cpp index 213a285e23eb2..51e610ccc0cd1 100644 --- a/clang/test/SemaCXX/builtin-align-cxx.cpp +++ b/clang/test/SemaCXX/builtin-align-cxx.cpp @@ -4,7 +4,7 @@ // Check that we don't crash when using dependent types in __builtin_align: template <typename a, a b> -void *c(void *d) { // expected-note{{candidate template ignored}} +void *c(void *d) { // expected-note{{a non-type template parameter cannot have type 'struct x' before C++20}} return __builtin_align_down(d, b); } diff --git a/clang/test/SemaCXX/calling-conv-compat.cpp b/clang/test/SemaCXX/calling-conv-compat.cpp index 9bb448ffef225..abd595df7663a 100644 --- a/clang/test/SemaCXX/calling-conv-compat.cpp +++ b/clang/test/SemaCXX/calling-conv-compat.cpp @@ -425,6 +425,6 @@ namespace D50526 { void h() { g<void, h>(); } #if !_M_X64 // expected-error@-2 {{no matching function for call to}} - // expected-note@-4 {{invalid explicitly-specified argument}} + // expected-note@-4 {{non-type template argument of type 'void ()' cannot be converted to a value of type 'void (*)() __attribute__((stdcall))'}} #endif } diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp index 90ee7892b2fc2..de8fe057893d5 100644 --- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp +++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp @@ -60,7 +60,7 @@ constexpr void test8() { throw "bad"; } -template<int x> constexpr int f(int y) { // expected-note {{candidate template ignored}} +template<int x> constexpr int f(int y) { // expected-note {{non-type template argument is not a constant expression}} return x * y; } constexpr int test9(int x) { diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp index 00ba291fbd198..45d265e2cdc2b 100644 --- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp +++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++03 -verify -Dstatic_assert=_Static_assert -Wno-c++11-extensions -Wno-c++14-extensions -Wno-c++17-extensions -Wno-c++20-extensions %s // RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11,cxx11-cxx14 -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions %s // RUN: %clang_cc1 -std=c++14 -verify=expected,cxx11-cxx14,cxx14 -Wno-c++20-extensions -Wno-c++17-extensions %s -// RUN: %clang_cc1 -std=c++17 -verify -Wno-c++20-extensions %s -// RUN: %clang_cc1 -std=c++20 -verify %s +// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx17,cxx17-cxx20 -Wno-c++20-extensions %s +// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20,cxx17-cxx20 %s template<typename, typename> inline const bool is_same = false; @@ -45,8 +45,9 @@ template<typename T> constexpr T outer() { // FIXME: The C++11 error seems wrong return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \ - expected-note {{candidate template ignored}} \ cxx11-note {{non-literal type '<dependent type>' cannot be used in a constant expression}} \ + cxx11-cxx14-note {{non-type template argument does not refer to any declaration}} \ + cxx17-cxx20-note {{value of type 'int' is not implicitly convertible to 'int *'}} \ cxx14-note {{non-literal type}} } static_assert(outer<int>() == 123); // cxx11-cxx14-error {{not an integral constant expression}} cxx11-cxx14-note {{in call}} diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index e4dadf83e0a08..6aac3981bb1a1 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -612,7 +612,7 @@ int bar() { namespace testIncludeTypeInTemplateArgument { template <typename T, typename U> -void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}} +void foo(T t = {}, U = {}); // expected-note {{template argument for template type parameter must be a type}} class AddObservation {}; // expected-note {{declared here}} int bar1() { diff --git a/clang/test/SemaSYCL/sycl-kernel-launch.cpp b/clang/test/SemaSYCL/sycl-kernel-launch.cpp index 20d9becb81929..b673025f03b40 100644 --- a/clang/test/SemaSYCL/sycl-kernel-launch.cpp +++ b/clang/test/SemaSYCL/sycl-kernel-launch.cpp @@ -324,7 +324,7 @@ namespace bad6 { // No matching function for call to sycl_kernel_launch; mismatched template parameter kind. namespace bad7 { - // expected-note@+2 {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} + // expected-note@+2 {{candidate template ignored: template argument for non-type template parameter must be an expression}} template<int, typename... Ts> void sycl_kernel_launch(const char *, Ts...); // expected-error@+4 {{no matching function for call to 'sycl_kernel_launch'}} diff --git a/clang/test/SemaTemplate/concepts-using-decl.cpp b/clang/test/SemaTemplate/concepts-using-decl.cpp index 41f7b6d2f8faa..26bd0b60b691c 100644 --- a/clang/test/SemaTemplate/concepts-using-decl.cpp +++ b/clang/test/SemaTemplate/concepts-using-decl.cpp @@ -165,7 +165,7 @@ struct base { struct bar : public base { using base::foo; - template <int N> + template <int N> int foo() { return 2; }; // expected-note {{candidate template ignored: substitution failure: too many template arguments for function template 'foo'}} }; diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp index a9c86b2118fbb..3a5bedca938bd 100644 --- a/clang/test/SemaTemplate/overload-candidates.cpp +++ b/clang/test/SemaTemplate/overload-candidates.cpp @@ -17,9 +17,9 @@ void test_dyn_cast(int* ptr) { } template<int I, typename T> - void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I'}} + void get(const T&); // expected-note{{candidate template ignored: template argument for non-type template parameter must be an expression for template parameter 'I'}} template<template<class T> class, typename T> - void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} + void get(const T&); // expected-note{{candidate template ignored: template argument for template template parameter must be a class template}} void test_get(void *ptr) { get<int>(ptr); // expected-error{{no matching function for call to 'get'}} diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp index 0b785700ee238..ea86227d8f569 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp @@ -43,7 +43,7 @@ void TempFunc() {} void Useage() { //expected-error@+2 {{no matching function}} - //expected-note@-4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b'}} + //expected-note@-4 {{candidate template ignored: non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned int' for template parameter 'b'}} TempFunc<1, -1, 1>(); } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
