Richard Smith | cb18957 | 2017-10-28 01:15:00 +0000 | [diff] [blame] | 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 |
Richard Smith | 5786582 | 2017-08-03 19:24:27 +0000 | [diff] [blame] | 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 |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 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 | |
Richard Smith | afe4aa8 | 2017-02-10 02:19:05 +0000 | [diff] [blame] | 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)); |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 48 | |
| 49 | template<typename ...T> struct tuple { tuple(T...); }; |
Richard Smith | afe4aa8 | 2017-02-10 02:19:05 +0000 | [diff] [blame] | 50 | template<typename ...T> explicit tuple(T ...t) -> tuple<T...>; // expected-note {{declared}} |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 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}; |
Richard Smith | afe4aa8 | 2017-02-10 02:19:05 +0000 | [diff] [blame] | 59 | static_assert(has_type<tuple<int, char, const char*, int>>(tb)); |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 60 | |
Richard Smith | afe4aa8 | 2017-02-10 02:19:05 +0000 | [diff] [blame] | 61 | // FIXME: This should be tuple<tuple<...>>; when the above guide is removed. |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 62 | tuple tc = {ta}; |
Richard Smith | afe4aa8 | 2017-02-10 02:19:05 +0000 | [diff] [blame] | 63 | static_assert(has_type<tuple<int, char, const char*, int>>(tc)); |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 64 | |
Richard Smith | afe4aa8 | 2017-02-10 02:19:05 +0000 | [diff] [blame] | 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)); |
Richard Smith | 6043762 | 2017-02-09 19:17:44 +0000 | [diff] [blame] | 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 | } |
Richard Smith | 541cf97 | 2017-02-10 23:10:17 +0000 | [diff] [blame] | 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 | } |
Richard Smith | cbe0793 | 2017-02-14 00:55:25 +0000 | [diff] [blame] | 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}} |
Richard Smith | c27b3d7 | 2017-02-14 01:49:59 +0000 | [diff] [blame] | 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}; |
Richard Smith | cbe0793 | 2017-02-14 00:55:25 +0000 | [diff] [blame] | 157 | } |
Richard Smith | 4e05eaa | 2017-02-16 00:36:47 +0000 | [diff] [blame] | 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 | } |
Richard Smith | efa919a | 2017-02-16 21:29:21 +0000 | [diff] [blame] | 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 | } |
Richard Smith | b4f9625 | 2017-02-21 06:30:38 +0000 | [diff] [blame] | 184 | |
| 185 | namespace transform_params { |
| 186 | template<typename T, T N, template<T (*v)[N]> typename U, T (*X)[N]> |
Richard Smith | 1389418 | 2017-04-13 21:37:24 +0000 | [diff] [blame] | 187 | struct A { |
Richard Smith | b4f9625 | 2017-02-21 06:30:38 +0000 | [diff] [blame] | 188 | template<typename V, V M, V (*Y)[M], template<V (*v)[M]> typename W> |
Richard Smith | 1389418 | 2017-04-13 21:37:24 +0000 | [diff] [blame] | 189 | A(U<X>, W<Y>); |
Richard Smith | b4f9625 | 2017-02-21 06:30:38 +0000 | [diff] [blame] | 190 | |
| 191 | static constexpr T v = N; |
| 192 | }; |
| 193 | |
| 194 | int n[12]; |
| 195 | template<int (*)[12]> struct Q {}; |
| 196 | Q<&n> qn; |
Richard Smith | 1389418 | 2017-04-13 21:37:24 +0000 | [diff] [blame] | 197 | A a(qn, qn); |
Richard Smith | b4f9625 | 2017-02-21 06:30:38 +0000 | [diff] [blame] | 198 | static_assert(a.v == 12); |
| 199 | |
Richard Smith | 0cd9c04 | 2017-02-21 08:42:39 +0000 | [diff] [blame] | 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; |
Richard Smith | b4f9625 | 2017-02-21 06:30:38 +0000 | [diff] [blame] | 206 | }; |
Richard Smith | 0cd9c04 | 2017-02-21 08:42:39 +0000 | [diff] [blame] | 207 | B b({1, 2, 3}, "foo", {'x', 'y', 'z', 'w'}); // ok |
| 208 | |
Richard Smith | 1389418 | 2017-04-13 21:37:24 +0000 | [diff] [blame] | 209 | template<typename ...T> struct C { |
Richard Smith | 0cd9c04 | 2017-02-21 08:42:39 +0000 | [diff] [blame] | 210 | template<T ...V, template<T...> typename X> |
Richard Smith | 1389418 | 2017-04-13 21:37:24 +0000 | [diff] [blame] | 211 | C(X<V...>); |
Richard Smith | 0cd9c04 | 2017-02-21 08:42:39 +0000 | [diff] [blame] | 212 | }; |
| 213 | template<int...> struct Y {}; |
Richard Smith | 1389418 | 2017-04-13 21:37:24 +0000 | [diff] [blame] | 214 | C c(Y<0, 1, 2>{}); |
Richard Smith | 130cc44 | 2017-02-21 23:49:18 +0000 | [diff] [blame] | 215 | |
| 216 | template<typename ...T> struct D { |
| 217 | template<T ...V> D(Y<V...>); |
| 218 | }; |
| 219 | D d(Y<0, 1, 2>{}); |
Richard Smith | b4f9625 | 2017-02-21 06:30:38 +0000 | [diff] [blame] | 220 | } |
Richard Smith | 479ba8e | 2017-04-20 01:15:31 +0000 | [diff] [blame] | 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 | } |
Richard Smith | e6d4b77 | 2017-06-07 02:42:27 +0000 | [diff] [blame] | 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 | } |
Richard Smith | 4f440e3 | 2017-06-08 01:08:50 +0000 | [diff] [blame] | 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 | } |
Richard Smith | e6d4b77 | 2017-06-07 02:42:27 +0000 | [diff] [blame] | 287 | } |
Richard Smith | 5786582 | 2017-08-03 19:24:27 +0000 | [diff] [blame] | 288 | |
Richard Smith | 0887754 | 2017-08-11 02:04:19 +0000 | [diff] [blame] | 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); |
Richard Smith | cff4201 | 2018-09-28 03:18:53 +0000 | [diff] [blame] | 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>(); |
Richard Smith | 0887754 | 2017-08-11 02:04:19 +0000 | [diff] [blame] | 317 | } |
| 318 | |
Richard Smith | 1337318 | 2018-01-04 01:24:17 +0000 | [diff] [blame] | 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 | |
Richard Smith | 2600c63 | 2018-05-30 20:24:10 +0000 | [diff] [blame] | 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; |
Richard Smith | e4899c1 | 2018-05-30 22:13:43 +0000 | [diff] [blame] | 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 | }; |
Richard Smith | 2600c63 | 2018-05-30 20:24:10 +0000 | [diff] [blame] | 356 | } |
| 357 | |
Erik Pilkington | dd0b344 | 2018-07-26 23:40:42 +0000 | [diff] [blame] | 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 | |
Erik Pilkington | 69770d3 | 2018-07-27 21:23:48 +0000 | [diff] [blame] | 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 | |
Richard Smith | 5786582 | 2017-08-03 19:24:27 +0000 | [diff] [blame] | 412 | #else |
| 413 | |
| 414 | // expected-no-diagnostics |
| 415 | namespace undefined_warnings { |
| 416 | // Make sure we don't get an "undefined but used internal symbol" warning for the deduction guide here. |
| 417 | namespace { |
| 418 | template <typename T> |
| 419 | struct TemplDObj { |
| 420 | explicit TemplDObj(T func) noexcept {} |
| 421 | }; |
| 422 | auto test1 = TemplDObj(0); |
| 423 | |
| 424 | TemplDObj(float) -> TemplDObj<double>; |
| 425 | auto test2 = TemplDObj(.0f); |
| 426 | } |
| 427 | } |
| 428 | #endif |