Skip to content

Commit 9c6d80e

Browse files
committed
[Clang] Do not eat SFINAE diagnostics for explicit template arguments
1 parent 91edbe2 commit 9c6d80e

18 files changed

+69
-25
lines changed

clang/lib/Sema/SemaOverload.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,12 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
751751
case TemplateDeductionResult::Incomplete:
752752
case TemplateDeductionResult::InvalidExplicitArguments:
753753
Result.Data = Info.Param.getOpaqueValue();
754+
if (Info.hasSFINAEDiagnostic()) {
755+
PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt(
756+
SourceLocation(), PartialDiagnostic::NullDiagnostic());
757+
Info.takeSFINAEDiagnostic(*Diag);
758+
Result.HasDiagnostic = true;
759+
}
754760
break;
755761

756762
case TemplateDeductionResult::DeducedMismatch:
@@ -822,7 +828,6 @@ void DeductionFailureInfo::Destroy() {
822828
case TemplateDeductionResult::Incomplete:
823829
case TemplateDeductionResult::TooManyArguments:
824830
case TemplateDeductionResult::TooFewArguments:
825-
case TemplateDeductionResult::InvalidExplicitArguments:
826831
case TemplateDeductionResult::CUDATargetMismatch:
827832
case TemplateDeductionResult::NonDependentConversionFailure:
828833
break;
@@ -837,6 +842,7 @@ void DeductionFailureInfo::Destroy() {
837842
Data = nullptr;
838843
break;
839844

845+
case TemplateDeductionResult::InvalidExplicitArguments:
840846
case TemplateDeductionResult::SubstitutionFailure:
841847
// FIXME: Destroy the template argument list?
842848
Data = nullptr;
@@ -12166,6 +12172,15 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
1216612172
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
1216712173
<< (index + 1);
1216812174
}
12175+
12176+
if (PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic()) {
12177+
unsigned DiagID =
12178+
S.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Note, "%0");
12179+
SmallString<128> SFINAEArgString;
12180+
PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
12181+
S.Diag(Templated->getLocation(), DiagID) << SFINAEArgString;
12182+
}
12183+
1216912184
MaybeEmitInheritedConstructorNote(S, Found);
1217012185
return;
1217112186

clang/test/AST/ByteCode/builtin-align-cxx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
// Check that we don't crash when using dependent types in __builtin_align:
66
template <typename a, a b>
7-
void *c(void *d) { // both-note{{candidate template ignored}}
7+
void *c(void *d) { // both-note{{candidate template ignored}} \
8+
// both-note {{a non-type template parameter cannot have type 'struct x' before C++20}}
89
return __builtin_align_down(d, b);
910
}
1011

clang/test/AST/ByteCode/cxx20.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,8 @@ namespace FailingDestructor {
753753
}
754754
};
755755
template<D d>
756-
void f() {} // both-note {{invalid explicitly-specified argument}}
756+
void f() {} // both-note {{invalid explicitly-specified argument}} \
757+
// both-note {{non-type template argument is not a constant expression}}
757758

758759
void g() {
759760
f<D{0, false}>(); // both-error {{no matching function}}

clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,25 @@ namespace test3 {
113113

114114
struct Derived1 : Base {
115115
using Base::foo;
116-
template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}}
116+
template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} \
117+
// expected-note {{template argument for non-type template parameter must be an expression}}
117118
};
118119

119120
struct Derived2 : Base {
120-
template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}}
121+
template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} \
122+
// expected-note {{template argument for non-type template parameter must be an expression}}
121123
using Base::foo;
122124
};
123125

124126
struct Derived3 : Base {
125127
using Base::foo;
126-
template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}}
128+
template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} \
129+
// expected-note {{template argument for template type parameter must be a type}}
127130
};
128131

129132
struct Derived4 : Base {
130-
template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}}
133+
template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} \
134+
// expected-note {{template argument for template type parameter must be a type}}
131135
using Base::foo;
132136
};
133137

clang/test/CXX/drs/cwg2xx.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,14 +650,17 @@ namespace cwg241 { // cwg241: 9
650650
C::f<3>(b);
651651
// expected-error@-1 {{no matching function for call to 'f'}}
652652
// expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
653+
// expected-note@#cwg241-C-f {{template argument for template type parameter must be a type}}
653654
C::g<3>(b);
654655
// expected-error@-1 {{no matching function for call to 'g'}}
655656
// expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
657+
// expected-note@#cwg241-C-g {{template argument for template type parameter must be a type}}
656658
using C::f;
657659
using C::g;
658660
f<3>(b);
659661
// expected-error@-1 {{no matching function for call to 'f'}}
660662
// expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
663+
// expected-note@#cwg241-C-f {{template argument for template type parameter must be a type}}
661664
// expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
662665
g<3>(b);
663666
}
@@ -952,6 +955,7 @@ namespace cwg258 { // cwg258: 2.8
952955
int &x = b.g<int>(0);
953956
// expected-error@-1 {{no matching member function for call to 'g'}}
954957
// expected-note@#cwg258-B-g {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
958+
// expected-note@#cwg258-B-g {{template argument for non-type template parameter must be an expression}}
955959
int &y = b.h();
956960
float &z = const_cast<const B&>(b).h();
957961

clang/test/CXX/drs/cwg3xx.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,9 @@ namespace cwg354 { // cwg354: 3.1 c++11
985985
int b1 = both<(int*)0>();
986986
// cxx98-error@-1 {{no matching function for call to 'both'}}
987987
// cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
988+
// cxx98-note@#cwg354-both-int-ptr {{non-type template argument does not refer to any declaration}}
988989
// cxx98-note@#cwg354-both-int {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
990+
// cxx98-note@#cwg354-both-int {{non-type template argument of type 'int *' must have an integral or enumeration type}}
989991

990992
template<int S::*> struct ptr_mem {}; // #cwg354-ptr_mem
991993
ptr_mem<0> m0; // #cwg354-m0

clang/test/CXX/expr/expr.const/p3-0x.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ void c() {
107107
break;
108108
}
109109
}
110-
template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}}
110+
template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}} \
111+
// expected-note {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}}
111112
template int f<&S::operator int>(); // expected-error {{does not refer to a function template}}
112113
template int f<(bool)&S::operator int>();
113114

clang/test/CXX/temp/temp.param/p8-cxx20.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ namespace ConstDestruction {
4040
};
4141

4242
template<D d>
43-
void f() {} // expected-note 2{{invalid explicitly-specified argument}}
43+
void f() {} // expected-note 2{{invalid explicitly-specified argument}} \
44+
// expected-note 2{{non-type template argument is not a constant expression}}
4445

4546
void g() {
4647
f<D{0, true}>();

clang/test/CXX/temp/temp.res/temp.local/p1.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ template<typename> char id;
1010
template<typename> struct TempType {};
1111
template<template<typename> class> struct TempTemp {};
1212

13-
template<typename> void use(int&); // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}}
13+
template<typename> void use(int&); // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}} \
14+
// expected-note {{use of class template 'B::template C' requires template arguments}}
1415
template<template<typename> class> void use(float&); // expected-note 2{{no known conversion}}
15-
template<int> void use(char&); // expected-note 2{{invalid explicitly-specified argument}}
16+
template<int> void use(char&); // expected-note 2{{invalid explicitly-specified argument}} \
17+
// expected-note 2{{template argument for non-type template parameter must be an expression}}
1618

1719
template<typename T> struct A {
1820
template<typename> struct C {};

clang/test/Modules/cxx-templates.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ void g() {
4343

4444
template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function for call}}
4545
// expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
46+
// expected-note@Inputs/cxx-templates-a.h:11 {{too many template arguments for class template 'Tmpl_T_C'}}
4647
// expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}
4748

4849
template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
4950
// expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
5051
// expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}
52+
// expected-note@Inputs/cxx-templates-b.h:11 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}}
5153

5254
template_param_kinds_3<Tmpl_T_T_A>();
5355
template_param_kinds_3<Tmpl_T_T_B>();

clang/test/SemaCXX/builtin-align-cxx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
// Check that we don't crash when using dependent types in __builtin_align:
55
template <typename a, a b>
6-
void *c(void *d) { // expected-note{{candidate template ignored}}
6+
void *c(void *d) { // expected-note{{candidate template ignored}} \
7+
// expected-note {{a non-type template parameter cannot have type 'struct x' before C++20}}
78
return __builtin_align_down(d, b);
89
}
910

clang/test/SemaCXX/calling-conv-compat.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ namespace D50526 {
425425
void h() { g<void, h>(); }
426426
#if !_M_X64
427427
// expected-error@-2 {{no matching function for call to}}
428-
// expected-note@-4 {{invalid explicitly-specified argument}}
428+
// expected-note@-4 {{invalid explicitly-specified argument}} \
429+
// expected-note@-4 {{non-type template argument of type 'void ()' cannot be converted to a value of type 'void (*)() __attribute__((stdcall))'}}
429430
#endif
430431
}

clang/test/SemaCXX/constexpr-function-recovery-crash.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ constexpr void test8() {
6060
throw "bad";
6161
}
6262

63-
template<int x> constexpr int f(int y) { // expected-note {{candidate template ignored}}
63+
template<int x> constexpr int f(int y) { // expected-note {{candidate template ignored}} \
64+
// expected-note {{non-type template argument is not a constant expression}}
6465
return x * y;
6566
}
6667
constexpr int test9(int x) {

clang/test/SemaCXX/cxx2a-template-lambdas.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// 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
22
// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11,cxx11-cxx14 -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions %s
33
// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx11-cxx14,cxx14 -Wno-c++20-extensions -Wno-c++17-extensions %s
4-
// RUN: %clang_cc1 -std=c++17 -verify -Wno-c++20-extensions %s
5-
// RUN: %clang_cc1 -std=c++20 -verify %s
4+
// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx17,cxx17-cxx20 -Wno-c++20-extensions %s
5+
// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20,cxx17-cxx20 %s
66

77
template<typename, typename>
88
inline const bool is_same = false;
@@ -47,6 +47,8 @@ constexpr T outer() {
4747
return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \
4848
expected-note {{candidate template ignored}} \
4949
cxx11-note {{non-literal type '<dependent type>' cannot be used in a constant expression}} \
50+
cxx11-cxx14-note {{non-type template argument does not refer to any declaration}} \
51+
cxx17-cxx20-note {{value of type 'int' is not implicitly convertible to 'int *'}} \
5052
cxx14-note {{non-literal type}}
5153
}
5254
static_assert(outer<int>() == 123); // cxx11-cxx14-error {{not an integral constant expression}} cxx11-cxx14-note {{in call}}

clang/test/SemaCXX/typo-correction.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,8 @@ int bar() {
614614

615615
namespace testIncludeTypeInTemplateArgument {
616616
template <typename T, typename U>
617-
void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}}
617+
void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}} \
618+
// expected-note {{template argument for template type parameter must be a type}}
618619

619620
class AddObservation {}; // expected-note {{declared here}}
620621
int bar1() {

clang/test/SemaTemplate/concepts-using-decl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@ struct base {
165165

166166
struct bar : public base {
167167
using base::foo;
168-
template <int N>
169-
int foo() { return 2; }; // expected-note {{candidate template ignored: substitution failure: too many template arguments for function template 'foo'}}
168+
template <int N>
169+
int foo() { return 2; };
170+
// expected-note@-1 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'N'}} \
171+
// expected-note@-1 {{too many template arguments for function template 'foo'}}
170172
};
171173

172174
void func() {

clang/test/SemaTemplate/overload-candidates.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ void test_dyn_cast(int* ptr) {
1616
(void)dyn_cast(ptr); // expected-error{{no matching function for call to 'dyn_cast'}}
1717
}
1818

19-
template<int I, typename T>
20-
void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I'}}
21-
template<template<class T> class, typename T>
22-
void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
19+
template<int I, typename T>
20+
void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I'}} \
21+
// expected-note {{template argument for non-type template parameter must be an expression}}
22+
template<template<class T> class, typename T>
23+
void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}} \
24+
// expected-note {{template argument for template template parameter must be a class template}}
2325

2426
void test_get(void *ptr) {
2527
get<int>(ptr); // expected-error{{no matching function for call to 'get'}}

clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ template <int a, unsigned b, int c>
4242
void TempFunc() {}
4343

4444
void Useage() {
45-
//expected-error@+2 {{no matching function}}
46-
//expected-note@-4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b'}}
45+
//expected-error@+3 {{no matching function}}
46+
//expected-note@-4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b'}} \
47+
//expected-note@-4 {{non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
4748
TempFunc<1, -1, 1>();
4849
}
4950
}

0 commit comments

Comments
 (0)