xref: /llvm-project/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp (revision 73b51ae160af6b94d4468331ff3fb6855cff3b18)
1 // RUN: %clang_cc1 -std=c++1z -verify %s -DERRORS -Wundefined-func-template
2 // RUN: %clang_cc1 -std=c++1z -verify %s -UERRORS -Wundefined-func-template
3 
4 // This test is split into two because we only produce "undefined internal"
5 // warnings if we didn't produce any errors.
6 #if ERRORS
7 
8 namespace std {
9   using size_t = decltype(sizeof(0));
10   template<typename T> struct initializer_list {
11     const T *p;
12     size_t n;
13     initializer_list();
14   };
15   // FIXME: This should probably not be necessary.
16   template<typename T> initializer_list(initializer_list<T>) -> initializer_list<T>;
17 }
18 
19 template<typename T> constexpr bool has_type(...) { return false; }
20 template<typename T> constexpr bool has_type(T) { return true; }
21 
22 std::initializer_list il = {1, 2, 3, 4, 5};
23 
24 template<typename T> struct vector {
25   template<typename Iter> vector(Iter, Iter);
26   vector(std::initializer_list<T>);
27 };
28 
29 template<typename T> vector(std::initializer_list<T>) -> vector<T>;
30 template<typename Iter> explicit vector(Iter, Iter) -> vector<typename Iter::value_type>;
31 template<typename T> explicit vector(std::size_t, T) -> vector<T>;
32 
33 vector v1 = {1, 2, 3, 4};
34 static_assert(has_type<vector<int>>(v1));
35 
36 struct iter { typedef char value_type; } it, end;
37 vector v2(it, end);
38 static_assert(has_type<vector<char>>(v2));
39 
40 vector v3(5, 5);
41 static_assert(has_type<vector<int>>(v3));
42 
43 vector v4 = {it, end};
44 static_assert(has_type<vector<iter>>(v4));
45 
46 vector v5{it, end};
47 static_assert(has_type<vector<iter>>(v5));
48 
49 template<typename ...T> struct tuple { tuple(T...); };
50 template<typename ...T> explicit tuple(T ...t) -> tuple<T...>; // expected-note {{declared}}
51 // FIXME: Remove
52 template<typename ...T> tuple(tuple<T...>) -> tuple<T...>;
53 
54 const int n = 4;
55 tuple ta = tuple{1, 'a', "foo", n};
56 static_assert(has_type<tuple<int, char, const char*, int>>(ta));
57 
58 tuple tb{ta};
59 static_assert(has_type<tuple<int, char, const char*, int>>(tb));
60 
61 // FIXME: This should be tuple<tuple<...>>; when the above guide is removed.
62 tuple tc = {ta};
63 static_assert(has_type<tuple<int, char, const char*, int>>(tc));
64 
65 tuple td = {1, 2, 3}; // expected-error {{selected an explicit deduction guide}}
66 static_assert(has_type<tuple<int, char, const char*, int>>(td));
67 
68 // FIXME: This is a GCC extension for now; if CWG don't allow this, at least
69 // add a warning for it.
70 namespace new_expr {
71   tuple<int> *p = new tuple{0};
72   tuple<float, float> *q = new tuple(1.0f, 2.0f);
73 }
74 
75 namespace ambiguity {
76   template<typename T> struct A {};
77   A(unsigned short) -> A<int>; // expected-note {{candidate}}
78   A(short) -> A<int>; // expected-note {{candidate}}
79   A a = 0; // expected-error {{ambiguous deduction for template arguments of 'A'}}
80 
81   template<typename T> struct B {};
82   template<typename T> B(T(&)(int)) -> B<int>; // expected-note {{candidate function [with T = int]}}
83   template<typename T> B(int(&)(T)) -> B<int>; // expected-note {{candidate function [with T = int]}}
84   int f(int);
85   B b = f; // expected-error {{ambiguous deduction for template arguments of 'B'}}
86 }
87 
88 // FIXME: Revisit this once CWG decides if attributes, and [[deprecated]] in
89 // particular, should be permitted here.
90 namespace deprecated {
91   template<typename T> struct A { A(int); };
92   [[deprecated]] A(int) -> A<void>; // expected-note {{marked deprecated here}}
93   A a = 0; // expected-warning {{'<deduction guide for A>' is deprecated}}
94 }
95 
96 namespace dependent {
97   template<template<typename...> typename A> decltype(auto) a = A{1, 2, 3};
98   static_assert(has_type<vector<int>>(a<vector>));
99   static_assert(has_type<tuple<int, int, int>>(a<tuple>));
100 
101   struct B {
102     template<typename T> struct X { X(T); };
103     X(int) -> X<int>;
104     template<typename T> using Y = X<T>; // expected-note {{template}}
105   };
106   template<typename T> void f() {
107     typename T::X tx = 0;
108     typename T::Y ty = 0; // expected-error {{alias template 'Y' requires template arguments; argument deduction only allowed for class templates}}
109   }
110   template void f<B>(); // expected-note {{in instantiation of}}
111 
112   template<typename T> struct C { C(T); };
113   template<typename T> C(T) -> C<T>;
114   template<typename T> void g(T a) {
115     C b = 0;
116     C c = a;
117     using U = decltype(b); // expected-note {{previous}}
118     using U = decltype(c); // expected-error {{different types ('C<const char *>' vs 'C<int>')}}
119   }
120   void h() {
121     g(0);
122     g("foo"); // expected-note {{instantiation of}}
123   }
124 }
125 
126 namespace look_into_current_instantiation {
127   template<typename U> struct Q {};
128   template<typename T> struct A {
129     using U = T;
130     template<typename> using V = Q<A<T>::U>;
131     template<typename W = int> A(V<W>);
132   };
133   A a = Q<float>(); // ok, can look through class-scope typedefs and alias
134                     // templates, and members of the current instantiation
135   A<float> &r = a;
136 
137   template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}}
138     struct X {
139       typedef T type;
140     };
141     B(typename X::type); // expected-note {{couldn't infer template argument 'T'}}
142   };
143   B b = 0; // expected-error {{no viable}}
144 
145   // We should have a substitution failure in the immediate context of
146   // deduction when using the C(T, U) constructor (probably; core wording
147   // unclear).
148   template<typename T> struct C {
149     using U = typename T::type;
150     C(T, U);
151   };
152 
153   struct R { R(int); typedef R type; };
154   C(...) -> C<R>;
155 
156   C c = {1, 2};
157 }
158 
159 namespace nondeducible {
160   template<typename A, typename B> struct X {};
161 
162   template<typename A> // expected-note {{non-deducible template parameter 'A'}}
163   X() -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
164 
165   template<typename A> // expected-note {{non-deducible template parameter 'A'}}
166   X(typename X<A, int>::type) -> X<A, int>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
167 
168   template<typename A = int,
169            typename B> // expected-note {{non-deducible template parameter 'B'}}
170   X(int) -> X<A, B>; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
171 
172   template<typename A = int,
173            typename ...B>
174   X(float) -> X<A, B...>; // ok
175 }
176 
177 namespace default_args_from_ctor {
178   template <class A> struct S { S(A = 0) {} };
179   S s(0);
180 
181   template <class A> struct T { template<typename B> T(A = 0, B = 0) {} };
182   T t(0, 0);
183 }
184 
185 namespace transform_params {
186   template<typename T, T N, template<T (*v)[N]> typename U, T (*X)[N]>
187   struct A {
188     template<typename V, V M, V (*Y)[M], template<V (*v)[M]> typename W>
189     A(U<X>, W<Y>);
190 
191     static constexpr T v = N;
192   };
193 
194   int n[12];
195   template<int (*)[12]> struct Q {};
196   Q<&n> qn;
197   A a(qn, qn);
198   static_assert(a.v == 12);
199 
200   template<typename ...T> struct B {
201     template<T ...V> B(const T (&...p)[V]) {
202       constexpr int Vs[] = {V...};
203       static_assert(Vs[0] == 3 && Vs[1] == 4 && Vs[2] == 4);
204     }
205     static constexpr int (*p)(T...) = (int(*)(int, char, char))nullptr;
206   };
207   B b({1, 2, 3}, "foo", {'x', 'y', 'z', 'w'}); // ok
208 
209   template<typename ...T> struct C {
210     template<T ...V, template<T...> typename X>
211       C(X<V...>);
212   };
213   template<int...> struct Y {};
214   C c(Y<0, 1, 2>{});
215 
216   template<typename ...T> struct D {
217     template<T ...V> D(Y<V...>);
218   };
219   D d(Y<0, 1, 2>{});
220 }
221 
222 namespace variadic {
223   int arr3[3], arr4[4];
224 
225   // PR32673
226   template<typename T> struct A {
227     template<typename ...U> A(T, U...);
228   };
229   A a(1, 2, 3);
230 
231   template<typename T> struct B {
232     template<int ...N> B(T, int (&...r)[N]);
233   };
234   B b(1, arr3, arr4);
235 
236   template<typename T> struct C {
237     template<template<typename> typename ...U> C(T, U<int>...);
238   };
239   C c(1, a, b);
240 
241   template<typename ...U> struct X {
242     template<typename T> X(T, U...);
243   };
244   X x(1, 2, 3);
245 
246   template<int ...N> struct Y {
247     template<typename T> Y(T, int (&...r)[N]);
248   };
249   Y y(1, arr3, arr4);
250 
251   template<template<typename> typename ...U> struct Z {
252     template<typename T> Z(T, U<int>...);
253   };
254   Z z(1, a, b);
255 }
256 
257 namespace tuple_tests {
258   // The converting n-ary constructor appears viable, deducing T as an empty
259   // pack (until we check its SFINAE constraints).
260   namespace libcxx_1 {
261     template<class ...T> struct tuple {
262       template<class ...Args> struct X { static const bool value = false; };
263       template<class ...U, bool Y = X<U...>::value> tuple(U &&...u);
264     };
265     tuple a = {1, 2, 3};
266   }
267 
268   // Don't get caught by surprise when X<...> doesn't even exist in the
269   // selected specialization!
270   namespace libcxx_2 {
271     template<class ...T> struct tuple { // expected-note {{candidate}}
272       template<class ...Args> struct X { static const bool value = false; };
273       template<class ...U, bool Y = X<U...>::value> tuple(U &&...u);
274       // expected-note@-1 {{substitution failure [with T = <>, U = <int, int, int>]: cannot reference member of primary template because deduced class template specialization 'tuple<>' is an explicit specialization}}
275     };
276     template <> class tuple<> {};
277     tuple a = {1, 2, 3}; // expected-error {{no viable constructor or deduction guide}}
278   }
279 
280   namespace libcxx_3 {
281     template<typename ...T> struct scoped_lock {
282       scoped_lock(T...);
283     };
284     template<> struct scoped_lock<> {};
285     scoped_lock l = {};
286   }
287 }
288 
289 namespace dependent {
290   template<typename T> struct X {
291     X(T);
292   };
293   template<typename T> int Var(T t) {
294     X x(t);
295     return X(x) + 1; // expected-error {{invalid operands}}
296   }
297   template<typename T> int Cast(T t) {
298     return X(X(t)) + 1; // expected-error {{invalid operands}}
299   }
300   template<typename T> int New(T t) {
301     return X(new X(t)) + 1; // expected-error {{invalid operands}}
302   };
303   template int Var(float); // expected-note {{instantiation of}}
304   template int Cast(float); // expected-note {{instantiation of}}
305   template int New(float); // expected-note {{instantiation of}}
306   template<typename T> int operator+(X<T>, int);
307   template int Var(int);
308   template int Cast(int);
309   template int New(int);
310 
311   template<template<typename> typename Y> void test() {
312     Y(0);
313     new Y(0);
314     Y y(0);
315   }
316   template void test<X>();
317 }
318 
319 namespace injected_class_name {
320   template<typename T = void> struct A {
321     A();
322     template<typename U> A(A<U>);
323   };
324   A<int> a;
325   A b = a;
326   using T = decltype(a);
327   using T = decltype(b);
328 }
329 
330 namespace member_guides {
331   // PR34520
332   template<class>
333   struct Foo {
334     template <class T> struct Bar {
335       Bar(...) {}
336     };
337     Bar(int) -> Bar<int>;
338   };
339   Foo<int>::Bar b = 0;
340 
341   struct A {
342     template<typename T> struct Public; // expected-note {{declared public}}
343     Public(float) -> Public<float>;
344   protected: // expected-note {{declared protected by intervening access specifier}}
345     template<typename T> struct Protected; // expected-note 2{{declared protected}}
346     Protected(float) -> Protected<float>;
347     Public(int) -> Public<int>; // expected-error {{different access}}
348   private: // expected-note {{declared private by intervening access specifier}}
349     template<typename T> struct Private; // expected-note {{declared private}}
350     Protected(int) -> Protected<int>; // expected-error {{different access}}
351   public: // expected-note 2{{declared public by intervening access specifier}}
352     template<typename T> Public(T) -> Public<T>;
353     template<typename T> Protected(T) -> Protected<T>; // expected-error {{different access}}
354     template<typename T> Private(T) -> Private<T>; // expected-error {{different access}}
355   };
356 }
357 
358 namespace rdar41903969 {
359 template <class T> struct A {};
360 template <class T> struct B;
361 template <class T> struct C {
362   C(A<T>&);
363   C(B<T>&);
364 };
365 
366 void foo(A<int> &a, B<int> &b) {
367   (void)C{b};
368   (void)C{a};
369 }
370 
371 template<typename T> struct X {
372   X(std::initializer_list<T>) = delete;
373   X(const X&);
374 };
375 
376 template <class T> struct D : X<T> {};
377 
378 void bar(D<int>& d) {
379   (void)X{d};
380 }
381 }
382 
383 namespace rdar41330135 {
384 template <int> struct A {};
385 template <class T>
386 struct S {
387   template <class U>
388   S(T a, U t, A<sizeof(t)>);
389 };
390 template <class T> struct D {
391   D(T t, A<sizeof(t)>);
392 };
393 int f() {
394   S s(0, 0, A<sizeof(int)>());
395   D d(0, A<sizeof(int)>());
396 }
397 
398 namespace test_dupls {
399 template<unsigned long> struct X {};
400 template<typename T> struct A {
401   A(T t, X<sizeof(t)>);
402 };
403 A a(0, {});
404 template<typename U> struct B {
405   B(U u, X<sizeof(u)>);
406 };
407 B b(0, {});
408 }
409 
410 }
411 
412 #pragma clang diagnostic push
413 #pragma clang diagnostic warning "-Wctad-maybe-unsupported"
414 namespace test_implicit_ctad_warning {
415 
416 template <class T>
417 struct Tag {};
418 
419 template <class T>
420 struct NoExplicit { // expected-note {{add a deduction guide to suppress this warning}}
421   NoExplicit(T) {}
422   NoExplicit(T, int) {}
423 };
424 
425 // expected-warning@+1 {{'NoExplicit' may not intend to support class template argument deduction}}
426 NoExplicit ne(42);
427 
428 template <class U>
429 struct HasExplicit {
430   HasExplicit(U) {}
431   HasExplicit(U, int) {}
432 };
433 template <class U> HasExplicit(U, int) -> HasExplicit<Tag<U>>;
434 
435 HasExplicit he(42);
436 
437 // Motivating examples from (taken from Stephan Lavavej's 2018 Cppcon talk)
438 template <class T, class U>
439 struct AmateurPair { // expected-note {{add a deduction guide to suppress this warning}}
440   T first;
441   U second;
442   explicit AmateurPair(const T &t, const U &u) {}
443 };
444 // expected-warning@+1 {{'AmateurPair' may not intend to support class template argument deduction}}
445 AmateurPair p1(42, "hello world"); // deduces to Pair<int, char[12]>
446 
447 template <class T, class U>
448 struct AmateurPair2 { // expected-note {{add a deduction guide to suppress this warning}}
449   T first;
450   U second;
451   explicit AmateurPair2(T t, U u) {}
452 };
453 // expected-warning@+1 {{'AmateurPair2' may not intend to support class template argument deduction}}
454 AmateurPair2 p2(42, "hello world"); // deduces to Pair2<int, const char*>
455 
456 template <class T, class U>
457 struct ProPair {
458   T first; U second;
459     explicit ProPair(T const& t, U  const& u)  {}
460 };
461 template<class T1, class T2>
462 ProPair(T1, T2) -> ProPair<T1, T2>;
463 ProPair p3(42, "hello world"); // deduces to ProPair<int, const char*>
464 static_assert(__is_same(decltype(p3), ProPair<int, const char*>));
465 
466 // Test that user-defined explicit guides suppress the warning even if they
467 // aren't used as candidates.
468 template <class T>
469 struct TestExplicitCtor {
470   TestExplicitCtor(T) {}
471 };
472 template <class T>
473 explicit TestExplicitCtor(TestExplicitCtor<T> const&) -> TestExplicitCtor<void>;
474 TestExplicitCtor<int> ce1{42};
475 TestExplicitCtor ce2 = ce1;
476 static_assert(__is_same(decltype(ce2), TestExplicitCtor<int>), "");
477 
478 struct allow_ctad_t {
479   allow_ctad_t() = delete;
480 };
481 
482 template <class T>
483 struct TestSuppression {
484   TestSuppression(T) {}
485 };
486 TestSuppression(allow_ctad_t)->TestSuppression<void>;
487 TestSuppression ta("abc");
488 static_assert(__is_same(decltype(ta), TestSuppression<const char *>), "");
489 }
490 #pragma clang diagnostic pop
491 
492 #else
493 
494 // expected-no-diagnostics
495 namespace undefined_warnings {
496   // Make sure we don't get an "undefined but used internal symbol" warning for the deduction guide here.
497   namespace {
498     template <typename T>
499     struct TemplDObj {
500       explicit TemplDObj(T func) noexcept {}
501     };
502     auto test1 = TemplDObj(0);
503 
504     TemplDObj(float) -> TemplDObj<double>;
505     auto test2 = TemplDObj(.0f);
506   }
507 }
508 #endif
509