[flang] Fix crash in HLFIR generation (#118399)
[llvm-project.git] / clang / test / SemaTemplate / cwg2398.cpp
blob6dc7af6ea17899151006e2a7752c7ebceb76234d
1 // RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -verify=expected,new
2 // RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -fno-relaxed-template-template-args -verify=expected,old
4 namespace issue1 {
5 template<class T, class U = T> class B {};
6 template<template<class> class P, class T> void f(P<T>);
7 // new-note@-1 {{deduced type 'B<[...], (default) int>' of 1st parameter does not match adjusted type 'B<[...], float>' of argument [with P = B, T = int]}}
8 // old-note@-2 2{{template template argument has different template parameters}}
10 void g() {
11 f(B<int>()); // old-error {{no matching function for call}}
12 f(B<int,float>()); // expected-error {{no matching function for call}}
14 } // namespace issue1
16 namespace issue2 {
17 template<typename> struct match;
19 template<template<typename> class t,typename T> struct match<t<T>>;
21 template<template<typename,typename> class t,typename T0,typename T1>
22 struct match<t<T0,T1>> {};
24 template<typename,typename = void> struct other {};
25 template struct match<other<void,void>>;
26 } // namespace issue2
28 namespace type {
29 template<class T1, class T2 = float> struct A;
31 template<class T3> struct B;
32 template<template<class T4 > class TT1, class T5 > struct B<TT1<T5 >> ;
33 template<template<class T6, class T7> class TT2, class T8, class T9> struct B<TT2<T8, T9>> {};
34 template struct B<A<int>>;
35 } // namespace type
37 namespace value {
38 template<class T1, int V1 = 1> struct A;
40 template<class T2> struct B;
41 template<template<class T3 > class TT1, class T4 > struct B<TT1<T4 >> ;
42 template<template<class T5, int V2> class TT2, class T6, int V3> struct B<TT2<T6, V3>> {};
43 template struct B<A<int>>;
44 } // namespace value
46 namespace templ {
47 template <class T1> struct A;
49 template<class T2, template <class T3> class T4 = A> struct B {};
51 template<class T5> struct C;
53 template<template<class T6> class TT1, class T7> struct C<TT1<T7>>;
55 template<template<class T8, template <class T9> class> class TT2,
56 class T10, template <class T11> class TT3>
57 struct C<TT2<T10, TT3>> {};
59 template struct C<B<int>>;
60 } // namespace templ
62 namespace class_template {
63 template <class T1, class T2 = float> struct A;
65 template <class T3> struct B;
67 template <template <class T4> class TT1, class T5> struct B<TT1<T5>>;
69 template <class T6, class T7> struct B<A<T6, T7>> {};
71 template struct B<A<int>>;
72 } // namespace class_template
74 namespace class_template_func {
75 template <class T1, class T2 = float> struct A {};
77 template <template <class T4> class TT1, class T5> void f(TT1<T5>);
78 template <class T6, class T7> void f(A<T6, T7>) {};
80 void g() {
81 f(A<int>());
83 } // namespace class_template_func
85 namespace type_pack1 {
86 template<class T2> struct A;
87 template<template<class ...T3s> class TT1, class T4> struct A<TT1<T4>> ;
88 template<template<class T5 > class TT2, class T6> struct A<TT2<T6>> {};
90 template<class T1> struct B;
91 template struct A<B<char>>;
92 } // namespace type_pack1
94 namespace type_pack2 {
95 template<class T2> struct A;
96 template<template<class ...T3s> class TT1, class ...T4> struct A<TT1<T4...>> ;
97 template<template<class T5 > class TT2, class ...T6> struct A<TT2<T6...>> {};
99 template<class T1> struct B;
100 template struct A<B<char>>;
101 } // namespace type_pack2
103 namespace type_pack3 {
104 template<class T1, class T2 = float> struct A;
106 template<class T3> struct B;
108 template<template<class T4 > class TT1, class T5 > struct B<TT1<T5 >>;
109 // new-note@-1 {{template is declared here}}
110 template<template<class T6, class ...T7s> class TT2, class T8, class ...T9s> struct B<TT2<T8, T9s...>>;
111 // old-note@-1 {{template is declared here}}
113 template struct B<A<int>>;
114 // expected-error@-1 {{explicit instantiation of undefined template}}
115 } // namespace type_pack3
117 namespace gcc_issue {
118 template<class T1, class T2> struct A;
120 template<template<class T1> class TT1, class T2> struct A<TT1<T2>, typename TT1<T2>::type>;
121 // new-note@-1 {{partial specialization matches}}
123 template<template<class T3, class T4> class TT2, class T5, class T6>
124 struct A<TT2<T5, T6>, typename TT2<T5, T5>::type>;
125 // new-note@-1 {{partial specialization matches}}
126 // old-note@-2 {{template is declared here}}
128 template <class T7, class T8 = T7> struct B { using type = int; };
130 template struct A<B<int>, int>;
131 // new-error@-1 {{ambiguous partial specializations}}
132 // old-error@-2 {{explicit instantiation of undefined template}}
133 } // namespace gcc_issue
135 namespace ttp_defaults {
136 template <template <class T1> class TT1> struct A {};
137 // old-note@-1 2{{previous template template parameter}}
139 template <template <class T2> class TT2> void f(A<TT2>);
140 // new-note@-1 {{explicit instantiation candidate}}
141 // old-note@-2 {{invalid explicitly-specified argument for template parameter 'TT2'}}
143 // FIXME: The default arguments on the TTP are not available during partial ordering.
144 template <template <class T3, class T4 = float> class TT3> void f(A<TT3>) {};
145 // new-note@-1 {{explicit instantiation candidate}}
146 // old-error@-2 {{template template argument has different template parameters}}
147 // old-note@-3 {{too many template parameters}}
149 template <class T5, class T6 = int> struct B;
150 // old-note@-1 {{too many template parameters}}
152 template void f<B>(A<B>);
153 // new-error@-1 {{partial ordering for explicit instantiation of 'f' is ambiguous}}
154 // old-error@-2 {{template template argument has different template parameters}}
155 // old-error@-3 {{explicit instantiation of 'f' does not refer to a function template}}
156 } // namespace ttp_defaults
158 namespace ttp_only {
159 template <template <class... > class TT1> struct A { static constexpr int V = 0; };
160 template <template <class > class TT2> struct A<TT2> { static constexpr int V = 1; };
161 // new-note@-1 {{partial specialization matches}}
162 template <template <class, class> class TT3> struct A<TT3> { static constexpr int V = 2; };
163 // new-note@-1 {{partial specialization matches}}
165 template <class ... > struct B;
166 template <class > struct C;
167 template <class, class > struct D;
168 template <class, class, class> struct E;
170 static_assert(A<B>::V == 0); // new-error {{ambiguous partial specializations}}
171 static_assert(A<C>::V == 1);
172 static_assert(A<D>::V == 2);
173 static_assert(A<E>::V == 0);
174 } // namespace ttp_only
176 namespace consistency {
177 template<class T> struct nondeduced { using type = T; };
178 template<class T8, class T9 = float> struct B;
180 namespace t1 {
181 template<class T1, class T2, class T3> struct A;
183 template<template<class, class> class TT1,
184 class T1, class T2, class T3, class T4>
185 struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T2>>::type> {};
187 template<template<class> class UU1,
188 template<class> class UU2,
189 class U1, class U2>
190 struct A<UU1<U1>, UU2<U2>, typename nondeduced<UU1<U1>>::type>;
192 template struct A<B<int>, B<int>, B<int>>;
193 } // namespace t1
194 namespace t2 {
195 template<class T1, class T2, class T3> struct A;
197 template<template<class, class> class TT1,
198 class T1, class T2, class T3, class T4>
199 struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T4>>::type> {};
200 // new-note@-1 {{partial specialization matches}}
202 template<template<class> class UU1,
203 template<class> class UU2,
204 class U1, class U2>
205 struct A<UU1<U1>, UU2<U2>, typename nondeduced<UU1<U1>>::type>;
206 // new-note@-1 {{partial specialization matches}}
208 template struct A<B<int>, B<int>, B<int>>;
209 // new-error@-1 {{ambiguous partial specializations}}
210 } // namespace t2
211 namespace t3 {
212 template<class T1, class T2, class T3> struct A;
214 template<template<class, class> class TT1,
215 class T1, class T2, class T3, class T4>
216 struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T2>>::type> {};
217 // new-note@-1 {{partial specialization matches}}
219 template<template<class> class UU1,
220 class U1, class U2>
221 struct A<UU1<U1>, UU1<U2>, typename nondeduced<UU1<U1>>::type>;
222 // new-note@-1 {{partial specialization matches}}
224 template struct A<B<int>, B<int>, B<int>>;
225 // new-error@-1 {{ambiguous partial specializations}}
226 } // namespace t3
227 namespace t4 {
228 template<class T1, class T2, class T3> struct A;
230 template<template<class, class> class TT1,
231 class T1, class T2, class T3, class T4>
232 struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T4>>::type> {};
233 // new-note@-1 {{partial specialization matches}}
235 template<template<class> class UU1,
236 class U1, class U2>
237 struct A<UU1<U1>, UU1<U2>, typename nondeduced<UU1<U1>>::type>;
238 // new-note@-1 {{partial specialization matches}}
240 template struct A<B<int>, B<int>, B<int>>;
241 // new-error@-1 {{ambiguous partial specializations}}
242 } // namespace t4
243 namespace t5 {
244 template<class T1, class T2> struct A;
246 template<template<class, class> class TT1,
247 class T1, class T2, class T3, class T4>
248 struct A<TT1<T1, T2>, TT1<T3, T4>> {};
249 // new-note@-1 {{partial specialization matches}}
251 template<template<class> class UU1,
252 class U1, class U2>
253 struct A<UU1<U1>, UU1<U2>>;
254 // new-note@-1 {{partial specialization matches}}
256 template struct A<B<int>, B<int>>;
257 // new-error@-1 {{ambiguous partial specializations}}
258 } // namespace t5
259 namespace t6 {
260 template<class T1, class T2> struct A;
262 template<template<class, class> class TT1,
263 class T1, class T2, class T3>
264 struct A<TT1<T1, T2>, TT1<T1, T3>> {};
265 // new-note@-1 {{partial specialization matches}}
267 template<template<class> class UU1,
268 class U1, class U2>
269 struct A<UU1<U1>, UU1<U2>>;
270 // new-note@-1 {{partial specialization matches}}
272 template struct A<B<int>, B<int>>;
273 // new-error@-1 {{ambiguous partial specializations}}
274 } // namespace t6
275 } // namespace consistency
277 namespace classes {
278 namespace canon {
279 template<class T, class U> struct A {};
281 template<template<class> class TT> auto f(TT<int> a) { return a; }
282 // old-note@-1 2{{template template argument has different template parameters}}
283 // new-note@-2 2{{substitution failure: too few template arguments}}
285 A<int, float> v1;
286 A<int, double> v2;
288 using X = decltype(f(v1));
289 // expected-error@-1 {{no matching function for call}}
291 using X = decltype(f(v2));
292 // expected-error@-1 {{no matching function for call}}
293 } // namespace canon
294 namespace expr {
295 template <class T1, int E1> struct A {
296 static constexpr auto val = E1;
298 template <template <class T3> class TT> void f(TT<int> v) {
299 // old-note@-1 {{template template argument has different template parameters}}
300 // new-note@-2 {{substitution failure: too few template arguments}}
301 static_assert(v.val == 3);
303 void test() {
304 f(A<int, 3>());
305 // expected-error@-1 {{no matching function for call}}
307 } // namespace expr
308 namespace packs {
309 template <class T1, class ...T2s> struct A {
310 static constexpr auto val = sizeof...(T2s);
313 template <template <class T3> class TT> void f(TT<int> v) {
314 // old-note@-1 {{template template argument has different template parameters}}
315 // new-note@-2 {{deduced type 'A<[...], (no argument), (no argument), (no argument)>' of 1st parameter does not match adjusted type 'A<[...], void, void, void>' of argument [with TT = A]}}
316 static_assert(v.val == 3);
318 void test() {
319 f(A<int, void, void, void>());
320 // expected-error@-1 {{no matching function for call}}
322 } // namespace packs
323 namespace nested {
324 template <class T1, int V1, int V2> struct A {
325 using type = T1;
326 static constexpr int v1 = V1, v2 = V2;
329 template <template <class T1> class TT1> auto f(TT1<int>) {
330 return TT1<float>();
333 template <template <class T2, int V3> class TT2> auto g(TT2<double, 1>) {
334 // new-note@-1 {{too few template arguments for class template 'A'}}
335 // old-note@-2 {{template template argument has different template parameters}}
336 return f(TT2<int, 2>());
339 using B = decltype(g(A<double, 1, 3>()));
340 // expected-error@-1 {{no matching function for call}}
342 using X = B::type; // expected-error {{undeclared identifier 'B'}}
343 using X = float;
344 static_assert(B::v1 == 2); // expected-error {{undeclared identifier 'B'}}
345 static_assert(B::v2 == 3); // expected-error {{undeclared identifier 'B'}}
347 namespace defaulted {
348 template <class T1, class T2 = T1*> struct A {
349 using type = T2;
352 template <template <class> class TT> TT<float> f(TT<int>);
353 // new-note@-1 {{deduced type 'A<[...], (default) int *>' of 1st parameter does not match adjusted type 'A<[...], double *>' of argument [with TT = A]}}
354 // old-note@-2 2{{template template argument has different template parameters}}
356 using X = int*; // new-note {{previous definition is here}}
357 using X = decltype(f(A<int>()))::type;
358 // new-error@-1 {{different types ('decltype(f(A<int>()))::type' (aka 'float *') vs 'int *')}}
359 // old-error@-2 {{no matching function for call}}
361 using Y = double*;
362 using Y = decltype(f(A<int, double*>()))::type;
363 // expected-error@-1 {{no matching function for call}}
364 } // namespace defaulted
365 } // namespace classes
367 namespace regression1 {
368 template <typename T, typename Y> struct map {};
369 template <typename T> class foo {};
371 template <template <typename...> class MapType, typename Value>
372 Value bar(MapType<int, Value> map);
374 template <template <typename...> class MapType, typename Value>
375 Value bar(MapType<int, foo<Value>> map);
377 void aux() {
378 map<int, foo<int>> input;
379 bar(input);
381 } // namespace regression1
383 namespace regression2 {
384 template <class> struct D {};
386 template <class ET, template <class> class VT>
387 struct D<VT<ET>>;
389 template <typename, int> struct Matrix;
390 template struct D<Matrix<double, 3>>;
391 } // namespace regression2