Clang Project

clang_source_code/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
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
8namespace 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
19template<typename T> constexpr bool has_type(...) { return false; }
20template<typename T> constexpr bool has_type(T) { return true; }
21
22std::initializer_list il = {1, 2, 3, 4, 5};
23
24template<typename T> struct vector {
25  template<typename Iter> vector(Iter, Iter);
26  vector(std::initializer_list<T>);
27};
28
29template<typename T> vector(std::initializer_list<T>) -> vector<T>;
30template<typename Iter> explicit vector(Iter, Iter) -> vector<typename Iter::value_type>;
31template<typename T> explicit vector(std::size_t, T) -> vector<T>;
32
33vector v1 = {1, 2, 3, 4};
34static_assert(has_type<vector<int>>(v1));
35
36struct iter { typedef char value_type; } it, end;
37vector v2(it, end);
38static_assert(has_type<vector<char>>(v2));
39
40vector v3(5, 5);
41static_assert(has_type<vector<int>>(v3));
42
43vector v4 = {it, end};
44static_assert(has_type<vector<iter>>(v4));
45
46vector v5{it, end};
47static_assert(has_type<vector<iter>>(v5));
48
49template<typename ...T> struct tuple { tuple(T...); };
50template<typename ...T> explicit tuple(T ...t) -> tuple<T...>; // expected-note {{declared}}
51// FIXME: Remove
52template<typename ...T> tuple(tuple<T...>) -> tuple<T...>;
53
54const int n = 4;
55tuple ta = tuple{1, 'a', "foo", n};
56static_assert(has_type<tuple<int, char, const char*, int>>(ta));
57
58tuple tb{ta};
59static_assert(has_type<tuple<int, char, const char*, int>>(tb));
60
61// FIXME: This should be tuple<tuple<...>>; when the above guide is removed.
62tuple tc = {ta};
63static_assert(has_type<tuple<int, char, const char*, int>>(tc));
64
65tuple td = {1, 2, 3}; // expected-error {{selected an explicit deduction guide}}
66static_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.
70namespace new_expr {
71  tuple<int> *p = new tuple{0};
72  tuple<float, float> *q = new tuple(1.0f, 2.0f);
73}
74
75namespace 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.
90namespace 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
96namespace 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
126namespace 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
159namespace 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
177namespace 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
185namespace 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
222namespace 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
257namespace 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
289namespace 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
319namespace 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
330namespace 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
358namespace rdar41903969 {
359template <class T> struct A {};
360template <class T> struct B;
361template <class T> struct C {
362  C(A<T>&);
363  C(B<T>&);
364};
365
366void foo(A<int> &a, B<int> &b) {
367  (void)C{b};
368  (void)C{a};
369}
370
371template<typename T> struct X {
372  X(std::initializer_list<T>) = delete;
373  X(const X&);
374};
375
376template <class T> struct D : X<T> {};
377
378void bar(D<int>& d) {
379  (void)X{d};
380}
381}
382
383namespace rdar41330135 {
384template <int> struct A {};
385template <class T>
386struct S {
387  template <class U>
388  S(T a, U t, A<sizeof(t)>);
389};
390template <class T> struct D {
391  D(T t, A<sizeof(t)>);
392};
393int f() {
394  S s(0, 0, A<sizeof(int)>());
395  D d(0, A<sizeof(int)>());
396}
397
398namespace test_dupls {
399template<unsigned long> struct X {};
400template<typename T> struct A {
401  A(T t, X<sizeof(t)>);
402};
403A a(0, {});
404template<typename U> struct B {
405  B(U u, X<sizeof(u)>);
406};
407B b(0, {});
408}
409
410}
411
412#pragma clang diagnostic push
413#pragma clang diagnostic warning "-Wctad-maybe-unsupported"
414namespace test_implicit_ctad_warning {
415
416template <class T>
417struct Tag {};
418
419template <class T>
420struct 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}}
426NoExplicit ne(42);
427
428template <class U>
429struct HasExplicit {
430  HasExplicit(U) {}
431  HasExplicit(U, int) {}
432};
433template <class U> HasExplicit(U, int) -> HasExplicit<Tag<U>>;
434
435HasExplicit he(42);
436
437// Motivating examples from (taken from Stephan Lavavej's 2018 Cppcon talk)
438template <class T, class U>
439struct 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}}
445AmateurPair p1(42, "hello world"); // deduces to Pair<int, char[12]>
446
447template <class T, class U>
448struct 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}}
454AmateurPair2 p2(42, "hello world"); // deduces to Pair2<int, const char*>
455
456template <class T, class U>
457struct ProPair {
458  T first; U second;
459    explicit ProPair(T const& t, U  const& u)  {}
460};
461template<class T1, class T2>
462ProPair(T1, T2) -> ProPair<T1, T2>;
463ProPair p3(42, "hello world"); // deduces to ProPair<int, const char*>
464static_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.
468template <class T>
469struct TestExplicitCtor {
470  TestExplicitCtor(T) {}
471};
472template <class T>
473explicit TestExplicitCtor(TestExplicitCtor<T> const&) -> TestExplicitCtor<void>;
474TestExplicitCtor<int> ce1{42};
475TestExplicitCtor ce2 = ce1;
476static_assert(__is_same(decltype(ce2), TestExplicitCtor<int>), "");
477
478struct allow_ctad_t {
479  allow_ctad_t() = delete;
480};
481
482template <class T>
483struct TestSuppression {
484  TestSuppression(T) {}
485};
486TestSuppression(allow_ctad_t)->TestSuppression<void>;
487TestSuppression ta("abc");
488static_assert(__is_same(decltype(ta), TestSuppression<const char *>), "");
489}
490#pragma clang diagnostic pop
491
492#else
493
494// expected-no-diagnostics
495namespace 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