| 1 | // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors |
| 2 | // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors |
| 3 | // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors |
| 4 | // RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors |
| 5 | |
| 6 | namespace dr1512 { // dr1512: 4 |
| 7 | void f(char *p) { |
| 8 | if (p > 0) {} // expected-error {{ordered comparison between pointer and zero}} |
| 9 | #if __cplusplus >= 201103L |
| 10 | if (p > nullptr) {} // expected-error {{invalid operands}} |
| 11 | #endif |
| 12 | } |
| 13 | bool g(int **x, const int **y) { |
| 14 | return x < y; |
| 15 | } |
| 16 | |
| 17 | template<typename T> T val(); |
| 18 | |
| 19 | template<typename A, typename B, typename C> void composite_pointer_type_is_base() { |
| 20 | typedef __typeof(true ? val<A>() : val<B>()) type; |
| 21 | typedef C type; |
| 22 | |
| 23 | typedef __typeof(val<A>() == val<B>()) cmp; |
| 24 | typedef __typeof(val<A>() != val<B>()) cmp; |
| 25 | typedef bool cmp; |
| 26 | } |
| 27 | |
| 28 | template<typename A, typename B, typename C> void composite_pointer_type_is_ord() { |
| 29 | composite_pointer_type_is_base<A, B, C>(); |
| 30 | |
| 31 | typedef __typeof(val<A>() < val<B>()) cmp; |
| 32 | typedef __typeof(val<A>() <= val<B>()) cmp; |
| 33 | typedef __typeof(val<A>() > val<B>()) cmp; |
| 34 | typedef __typeof(val<A>() >= val<B>()) cmp; |
| 35 | typedef bool cmp; |
| 36 | } |
| 37 | |
| 38 | template <typename A, typename B, typename C> |
| 39 | void composite_pointer_type_is_unord(int = 0) { |
| 40 | composite_pointer_type_is_base<A, B, C>(); |
| 41 | } |
| 42 | template <typename A, typename B, typename C> |
| 43 | void composite_pointer_type_is_unord(__typeof(val<A>() < val<B>()) * = 0); |
| 44 | template <typename A, typename B, typename C> |
| 45 | void composite_pointer_type_is_unord(__typeof(val<A>() <= val<B>()) * = 0); |
| 46 | template <typename A, typename B, typename C> |
| 47 | void composite_pointer_type_is_unord(__typeof(val<A>() > val<B>()) * = 0); |
| 48 | template <typename A, typename B, typename C> |
| 49 | void composite_pointer_type_is_unord(__typeof(val<A>() >= val<B>()) * = 0); |
| 50 | |
| 51 | // A call to this is ambiguous if a composite pointer type exists. |
| 52 | template<typename A, typename B> |
| 53 | void no_composite_pointer_type(__typeof((true ? val<A>() : val<B>()), void()) * = 0); |
| 54 | template<typename A, typename B> void no_composite_pointer_type(int = 0); |
| 55 | |
| 56 | struct A {}; |
| 57 | struct B : A {}; |
| 58 | struct C {}; |
| 59 | |
| 60 | void test() { |
| 61 | #if __cplusplus >= 201103L |
| 62 | using nullptr_t = decltype(nullptr); |
| 63 | composite_pointer_type_is_unord<nullptr_t, nullptr_t, nullptr_t>(); |
| 64 | no_composite_pointer_type<nullptr_t, int>(); |
| 65 | |
| 66 | composite_pointer_type_is_unord<nullptr_t, const char**, const char**>(); |
| 67 | composite_pointer_type_is_unord<const char**, nullptr_t, const char**>(); |
| 68 | #endif |
| 69 | |
| 70 | composite_pointer_type_is_ord<const int *, volatile void *, const volatile void*>(); |
| 71 | composite_pointer_type_is_ord<const void *, volatile int *, const volatile void*>(); |
| 72 | |
| 73 | composite_pointer_type_is_ord<const A*, volatile B*, const volatile A*>(); |
| 74 | composite_pointer_type_is_ord<const B*, volatile A*, const volatile A*>(); |
| 75 | |
| 76 | composite_pointer_type_is_unord<const int *A::*, volatile int *B::*, const volatile int *const B::*>(); |
| 77 | composite_pointer_type_is_unord<const int *B::*, volatile int *A::*, const volatile int *const B::*>(); |
| 78 | no_composite_pointer_type<int (A::*)(), int (C::*)()>(); |
| 79 | no_composite_pointer_type<const int (A::*)(), volatile int (C::*)()>(); |
| 80 | |
| 81 | #if __cplusplus > 201402 |
| 82 | composite_pointer_type_is_ord<int (*)() noexcept, int (*)(), int (*)()>(); |
| 83 | composite_pointer_type_is_ord<int (*)(), int (*)() noexcept, int (*)()>(); |
| 84 | composite_pointer_type_is_unord<int (A::*)() noexcept, int (A::*)(), int (A::*)()>(); |
| 85 | composite_pointer_type_is_unord<int (A::*)(), int (A::*)() noexcept, int (A::*)()>(); |
| 86 | // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'. |
| 87 | composite_pointer_type_is_unord<int (B::*)(), int (A::*)() noexcept, int (B::*)()>(); |
| 88 | composite_pointer_type_is_unord<int (A::*)() noexcept, int (B::*)(), int (B::*)()>(); |
| 89 | composite_pointer_type_is_unord<int (B::*)() noexcept, int (A::*)(), int (B::*)()>(); |
| 90 | composite_pointer_type_is_unord<int (A::*)(), int (B::*)() noexcept, int (B::*)()>(); |
| 91 | |
| 92 | // FIXME: It would be reasonable to permit these, with a common type of 'int (*const *)()'. |
| 93 | no_composite_pointer_type<int (**)() noexcept, int (**)()>(); |
| 94 | no_composite_pointer_type<int (**)(), int (**)() noexcept>(); |
| 95 | |
| 96 | // FIXME: It would be reasonable to permit these, with a common type of 'int (A::*)()'. |
| 97 | no_composite_pointer_type<int (A::*)() const, int (A::*)()>(); |
| 98 | no_composite_pointer_type<int (A::*)(), int (A::*)() const>(); |
| 99 | |
| 100 | // FIXME: It would be reasonable to permit these, with a common type of |
| 101 | // 'int (A::*)() &' and 'int (A::*)() &&', respectively. |
| 102 | no_composite_pointer_type<int (A::*)() &, int (A::*)()>(); |
| 103 | no_composite_pointer_type<int (A::*)(), int (A::*)() &>(); |
| 104 | no_composite_pointer_type<int (A::*)() &&, int (A::*)()>(); |
| 105 | no_composite_pointer_type<int (A::*)(), int (A::*)() &&>(); |
| 106 | |
| 107 | no_composite_pointer_type<int (A::*)() &&, int (A::*)() &>(); |
| 108 | no_composite_pointer_type<int (A::*)() &, int (A::*)() &&>(); |
| 109 | |
| 110 | no_composite_pointer_type<int (C::*)(), int (A::*)() noexcept>(); |
| 111 | no_composite_pointer_type<int (A::*)() noexcept, int (C::*)()>(); |
| 112 | #endif |
| 113 | } |
| 114 | |
| 115 | #if __cplusplus >= 201103L |
| 116 | template<typename T> struct Wrap { operator T(); }; // expected-note 4{{converted to type 'nullptr_t'}} expected-note 4{{converted to type 'int *'}} |
| 117 | void test_overload() { |
| 118 | using nullptr_t = decltype(nullptr); |
| 119 | void(Wrap<nullptr_t>() == Wrap<nullptr_t>()); |
| 120 | void(Wrap<nullptr_t>() != Wrap<nullptr_t>()); |
| 121 | void(Wrap<nullptr_t>() < Wrap<nullptr_t>()); // expected-error {{invalid operands}} |
| 122 | void(Wrap<nullptr_t>() > Wrap<nullptr_t>()); // expected-error {{invalid operands}} |
| 123 | void(Wrap<nullptr_t>() <= Wrap<nullptr_t>()); // expected-error {{invalid operands}} |
| 124 | void(Wrap<nullptr_t>() >= Wrap<nullptr_t>()); // expected-error {{invalid operands}} |
| 125 | |
| 126 | // Under dr1213, this is ill-formed: we select the builtin operator<(int*, int*) |
| 127 | // but then only convert as far as 'nullptr_t', which we then can't convert to 'int*'. |
| 128 | void(Wrap<nullptr_t>() == Wrap<int*>()); |
| 129 | void(Wrap<nullptr_t>() != Wrap<int*>()); |
| 130 | void(Wrap<nullptr_t>() < Wrap<int*>()); // expected-error {{invalid operands to binary expression ('Wrap<nullptr_t>' and 'Wrap<int *>')}} |
| 131 | void(Wrap<nullptr_t>() > Wrap<int*>()); // expected-error {{invalid operands}} |
| 132 | void(Wrap<nullptr_t>() <= Wrap<int*>()); // expected-error {{invalid operands}} |
| 133 | void(Wrap<nullptr_t>() >= Wrap<int*>()); // expected-error {{invalid operands}} |
| 134 | } |
| 135 | #endif |
| 136 | } |
| 137 | |
| 138 | namespace dr1518 { // dr1518: 4 |
| 139 | #if __cplusplus >= 201103L |
| 140 | struct Z0 { // expected-note 0+ {{candidate}} |
| 141 | explicit Z0() = default; // expected-note 0+ {{here}} |
| 142 | }; |
| 143 | struct Z { // expected-note 0+ {{candidate}} |
| 144 | explicit Z(); // expected-note 0+ {{here}} |
| 145 | explicit Z(int); |
| 146 | explicit Z(int, int); // expected-note 0+ {{here}} |
| 147 | }; |
| 148 | template <class T> int Eat(T); // expected-note 0+ {{candidate}} |
| 149 | Z0 a; |
| 150 | Z0 b{}; |
| 151 | Z0 c = {}; // expected-error {{explicit in copy-initialization}} |
| 152 | int i = Eat<Z0>({}); // expected-error {{no matching function for call to 'Eat'}} |
| 153 | |
| 154 | Z c2 = {}; // expected-error {{explicit in copy-initialization}} |
| 155 | int i2 = Eat<Z>({}); // expected-error {{no matching function for call to 'Eat'}} |
| 156 | Z a1 = 1; // expected-error {{no viable conversion}} |
| 157 | Z a3 = Z(1); |
| 158 | Z a2(1); |
| 159 | Z *p = new Z(1); |
| 160 | Z a4 = (Z)1; |
| 161 | Z a5 = static_cast<Z>(1); |
| 162 | Z a6 = {4, 3}; // expected-error {{explicit in copy-initialization}} |
| 163 | |
| 164 | struct UserProvidedBaseCtor { // expected-note 0+ {{candidate}} |
| 165 | UserProvidedBaseCtor() {} |
| 166 | }; |
| 167 | struct DoesntInheritCtor : UserProvidedBaseCtor { // expected-note 0+ {{candidate}} |
| 168 | int x; |
| 169 | }; |
| 170 | DoesntInheritCtor I{{}, 42}; |
| 171 | #if __cplusplus <= 201402L |
| 172 | // expected-error@-2 {{no matching constructor}} |
| 173 | #endif |
| 174 | |
| 175 | struct BaseCtor { BaseCtor() = default; }; // expected-note 0+ {{candidate}} |
| 176 | struct InheritsCtor : BaseCtor { // expected-note 1+ {{candidate}} |
| 177 | using BaseCtor::BaseCtor; // expected-note 2 {{inherited here}} |
| 178 | int x; |
| 179 | }; |
| 180 | InheritsCtor II = {{}, 42}; // expected-error {{no matching constructor}} |
| 181 | |
| 182 | namespace std_example { |
| 183 | struct A { |
| 184 | explicit A() = default; // expected-note 2{{declared here}} |
| 185 | }; |
| 186 | |
| 187 | struct B : A { |
| 188 | explicit B() = default; // expected-note 2{{declared here}} |
| 189 | }; |
| 190 | |
| 191 | struct C { |
| 192 | explicit C(); // expected-note 2{{declared here}} |
| 193 | }; |
| 194 | |
| 195 | struct D : A { |
| 196 | C c; |
| 197 | explicit D() = default; // expected-note 2{{declared here}} |
| 198 | }; |
| 199 | |
| 200 | template <typename T> void f() { |
| 201 | T t; // ok |
| 202 | T u{}; // ok |
| 203 | T v = {}; // expected-error 4{{explicit}} |
| 204 | } |
| 205 | template <typename T> void g() { |
| 206 | void x(T t); // expected-note 4{{parameter}} |
| 207 | x({}); // expected-error 4{{explicit}} |
| 208 | } |
| 209 | |
| 210 | void test() { |
| 211 | f<A>(); // expected-note {{instantiation of}} |
| 212 | f<B>(); // expected-note {{instantiation of}} |
| 213 | f<C>(); // expected-note {{instantiation of}} |
| 214 | f<D>(); // expected-note {{instantiation of}} |
| 215 | g<A>(); // expected-note {{instantiation of}} |
| 216 | g<B>(); // expected-note {{instantiation of}} |
| 217 | g<C>(); // expected-note {{instantiation of}} |
| 218 | g<D>(); // expected-note {{instantiation of}} |
| 219 | } |
| 220 | } |
| 221 | #endif // __cplusplus >= 201103L |
| 222 | } |
| 223 | |
| 224 | namespace dr1550 { // dr1550: yes |
| 225 | int f(bool b, int n) { |
| 226 | return (b ? (throw 0) : n) + (b ? n : (throw 0)); |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | namespace dr1560 { // dr1560: 3.5 |
| 231 | void f(bool b, int n) { |
| 232 | (b ? throw 0 : n) = (b ? n : throw 0) = 0; |
| 233 | } |
| 234 | class X { X(const X&); }; |
| 235 | const X &get(); |
| 236 | const X &x = true ? get() : throw 0; |
| 237 | } |
| 238 | |
| 239 | namespace dr1573 { // dr1573: 3.9 |
| 240 | #if __cplusplus >= 201103L |
| 241 | // ellipsis is inherited (p0136r1 supersedes this part). |
| 242 | struct A { A(); A(int, char, ...); }; |
| 243 | struct B : A { using A::A; }; |
| 244 | B b(1, 'x', 4.0, "hello"); // ok |
| 245 | |
| 246 | // inherited constructor is effectively constexpr if the user-written constructor would be |
| 247 | struct C { C(); constexpr C(int) {} }; |
| 248 | struct D : C { using C::C; }; |
| 249 | constexpr D d = D(0); // ok |
| 250 | struct E : C { using C::C; A a; }; // expected-note {{non-literal type}} |
| 251 | constexpr E e = E(0); // expected-error {{non-literal type}} |
| 252 | // FIXME: This diagnostic is pretty bad; we should explain that the problem |
| 253 | // is that F::c would be initialized by a non-constexpr constructor. |
| 254 | struct F : C { using C::C; C c; }; // expected-note {{here}} |
| 255 | constexpr F f = F(0); // expected-error {{constant expression}} expected-note {{constructor inherited from base class 'C'}} |
| 256 | |
| 257 | // inherited constructor is effectively deleted if the user-written constructor would be |
| 258 | struct G { G(int); }; |
| 259 | struct H : G { using G::G; G g; }; // expected-note {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} |
| 260 | H h(0); // expected-error {{constructor inherited by 'H' from base class 'G' is implicitly deleted}} |
| 261 | #endif |
| 262 | } |
| 263 | |
| 264 | #if __cplusplus >= 201103L |
| 265 | namespace std { |
| 266 | typedef decltype(sizeof(int)) size_t; |
| 267 | |
| 268 | // libc++'s implementation |
| 269 | template <class _E> |
| 270 | class initializer_list |
| 271 | { |
| 272 | const _E* __begin_; |
| 273 | size_t __size_; |
| 274 | |
| 275 | initializer_list(const _E* __b, size_t __s) |
| 276 | : __begin_(__b), __size_(__s) {} |
| 277 | |
| 278 | public: |
| 279 | typedef _E value_type; |
| 280 | typedef const _E& reference; |
| 281 | typedef const _E& const_reference; |
| 282 | typedef size_t size_type; |
| 283 | |
| 284 | typedef const _E* iterator; |
| 285 | typedef const _E* const_iterator; |
| 286 | |
| 287 | initializer_list() : __begin_(nullptr), __size_(0) {} |
| 288 | |
| 289 | size_t size() const {return __size_;} |
| 290 | const _E* begin() const {return __begin_;} |
| 291 | const _E* end() const {return __begin_ + __size_;} |
| 292 | }; |
| 293 | |
| 294 | template < class _T1, class _T2 > struct pair { _T2 second; }; |
| 295 | |
| 296 | template<typename T> struct basic_string { |
| 297 | basic_string(const T* x) {} |
| 298 | ~basic_string() {}; |
| 299 | }; |
| 300 | typedef basic_string<char> string; |
| 301 | |
| 302 | } // std |
| 303 | |
| 304 | namespace dr1579 { // dr1579: 3.9 |
| 305 | template<class T> |
| 306 | struct GenericMoveOnly { |
| 307 | GenericMoveOnly(); |
| 308 | template<class U> GenericMoveOnly(const GenericMoveOnly<U> &) = delete; // expected-note 5 {{marked deleted here}} |
| 309 | GenericMoveOnly(const int &) = delete; // expected-note 2 {{marked deleted here}} |
| 310 | template<class U> GenericMoveOnly(GenericMoveOnly<U> &&); |
| 311 | GenericMoveOnly(int &&); |
| 312 | }; |
| 313 | |
| 314 | GenericMoveOnly<float> DR1579_Eligible(GenericMoveOnly<char> CharMO) { |
| 315 | int i; |
| 316 | GenericMoveOnly<char> GMO; |
| 317 | |
| 318 | if (0) |
| 319 | return i; |
| 320 | else if (0) |
| 321 | return GMO; |
| 322 | else if (0) |
| 323 | return ((GMO)); |
| 324 | else |
| 325 | return CharMO; |
| 326 | } |
| 327 | |
| 328 | GenericMoveOnly<char> GlobalMO; |
| 329 | |
| 330 | GenericMoveOnly<float> DR1579_Ineligible(int &AnInt, |
| 331 | GenericMoveOnly<char> &CharMO) { |
| 332 | static GenericMoveOnly<char> StaticMove; |
| 333 | extern GenericMoveOnly<char> ExternMove; |
| 334 | |
| 335 | if (0) |
| 336 | return AnInt; // expected-error{{invokes a deleted function}} |
| 337 | else if (0) |
| 338 | return GlobalMO; // expected-error{{invokes a deleted function}} |
| 339 | else if (0) |
| 340 | return StaticMove; // expected-error{{invokes a deleted function}} |
| 341 | else if (0) |
| 342 | return ExternMove; // expected-error{{invokes a deleted function}} |
| 343 | else if (0) |
| 344 | return AnInt; // expected-error{{invokes a deleted function}} |
| 345 | else |
| 346 | return CharMO; // expected-error{{invokes a deleted function}} |
| 347 | } |
| 348 | |
| 349 | auto DR1579_lambda_valid = [](GenericMoveOnly<float> mo) -> |
| 350 | GenericMoveOnly<char> { |
| 351 | return mo; |
| 352 | }; |
| 353 | |
| 354 | auto DR1579_lambda_invalid = []() -> GenericMoveOnly<char> { |
| 355 | static GenericMoveOnly<float> mo; |
| 356 | return mo; // expected-error{{invokes a deleted function}} |
| 357 | }; |
| 358 | } // end namespace dr1579 |
| 359 | |
| 360 | namespace dr1584 { |
| 361 | // Deducing function types from cv-qualified types |
| 362 | template<typename T> void f(const T *); // expected-note {{candidate template ignored}} |
| 363 | template<typename T> void g(T *, const T * = 0); |
| 364 | template<typename T> void h(T *) { T::error; } // expected-error {{no members}} |
| 365 | template<typename T> void h(const T *); |
| 366 | void i() { |
| 367 | f(&i); // expected-error {{no matching function}} |
| 368 | g(&i); |
| 369 | h(&i); // expected-note {{here}} |
| 370 | } |
| 371 | } |
| 372 | |
| 373 | namespace dr1589 { // dr1589: 3.7 c++11 |
| 374 | // Ambiguous ranking of list-initialization sequences |
| 375 | |
| 376 | void f0(long, int=0); // Would makes selection of #0 ambiguous |
| 377 | void f0(long); // #0 |
| 378 | void f0(std::initializer_list<int>); // #00 |
| 379 | void g0() { f0({1L}); } // chooses #00 |
| 380 | |
| 381 | void f1(int, int=0); // Would make selection of #1 ambiguous |
| 382 | void f1(int); // #1 |
| 383 | void f1(std::initializer_list<long>); // #2 |
| 384 | void g1() { f1({42}); } // chooses #2 |
| 385 | |
| 386 | void f2(std::pair<const char*, const char*>, int = 0); // Would makes selection of #3 ambiguous |
| 387 | void f2(std::pair<const char*, const char*>); // #3 |
| 388 | void f2(std::initializer_list<std::string>); // #4 |
| 389 | void g2() { f2({"foo","bar"}); } // chooses #4 |
| 390 | |
| 391 | namespace with_error { |
| 392 | void f0(long); // #0 expected-note {{candidate function}} |
| 393 | void f0(std::initializer_list<int>); // #00 expected-note {{candidate function}} |
| 394 | void f0(std::initializer_list<int>, int = 0); // Makes selection of #00 ambiguous \ |
| 395 | // expected-note {{candidate function}} |
| 396 | void g0() { f0({1L}); } // chooses #00 expected-error{{call to 'f0' is ambiguous}} |
| 397 | |
| 398 | void f1(int); // #1 expected-note {{candidate function}} |
| 399 | void f1(std::initializer_list<long>); // #2 expected-note {{candidate function}} |
| 400 | void f1(std::initializer_list<long>, int = 0); // Makes selection of #00 ambiguous \ |
| 401 | // expected-note {{candidate function}} |
| 402 | void g1() { f1({42}); } // chooses #2 expected-error{{call to 'f1' is ambiguous}} |
| 403 | |
| 404 | void f2(std::pair<const char*, const char*>); // #3 TODO: expected- note {{candidate function}} |
| 405 | void f2(std::initializer_list<std::string>); // #4 expected-note {{candidate function}} |
| 406 | void f2(std::initializer_list<std::string>, int = 0); // Makes selection of #00 ambiguous \ |
| 407 | // expected-note {{candidate function}} |
| 408 | void g2() { f2({"foo","bar"}); } // chooses #4 expected-error{{call to 'f2' is ambiguous}} |
| 409 | } |
| 410 | |
| 411 | } // dr1589 |
| 412 | |
| 413 | namespace dr1591 { //dr1591. Deducing array bound and element type from initializer list |
| 414 | template<class T, int N> int h(T const(&)[N]); |
| 415 | int X = h({1,2,3}); // T deduced to int, N deduced to 3 |
| 416 | |
| 417 | template<class T> int j(T const(&)[3]); |
| 418 | int Y = j({42}); // T deduced to int, array bound not considered |
| 419 | |
| 420 | struct Aggr { int i; int j; }; |
| 421 | template<int N> int k(Aggr const(&)[N]); //expected-note{{not viable}} |
| 422 | int Y0 = k({1,2,3}); //expected-error{{no matching function}} |
| 423 | int Z = k({{1},{2},{3}}); // OK, N deduced to 3 |
| 424 | |
| 425 | template<int M, int N> int m(int const(&)[M][N]); |
| 426 | int X0 = m({{1,2},{3,4}}); // M and N both deduced to 2 |
| 427 | |
| 428 | template<class T, int N> int n(T const(&)[N], T); |
| 429 | int X1 = n({{1},{2},{3}},Aggr()); // OK, T is Aggr, N is 3 |
| 430 | |
| 431 | |
| 432 | namespace check_multi_dim_arrays { |
| 433 | template<class T, int N, int M, int O> int ***f(const T (&a)[N][M][O]); //expected-note{{deduced conflicting values}} |
| 434 | template<class T, int N, int M> int **f(const T (&a)[N][M]); //expected-note{{couldn't infer}} |
| 435 | |
| 436 | template<class T, int N> int *f(const T (&a)[N]); //expected-note{{couldn't infer}} |
| 437 | int ***p3 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); |
| 438 | int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); //expected-error{{no matching}} |
| 439 | int **p2 = f({ {1,2,3}, {3, 4, 5} }); |
| 440 | int **p22 = f({ {1,2}, {3, 4} }); |
| 441 | int *p1 = f({1, 2, 3}); |
| 442 | } |
| 443 | namespace check_multi_dim_arrays_rref { |
| 444 | template<class T, int N, int M, int O> int ***f(T (&&a)[N][M][O]); //expected-note{{deduced conflicting values}} |
| 445 | template<class T, int N, int M> int **f(T (&&a)[N][M]); //expected-note{{couldn't infer}} |
| 446 | |
| 447 | template<class T, int N> int *f(T (&&a)[N]); //expected-note{{couldn't infer}} |
| 448 | int ***p3 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); |
| 449 | int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); //expected-error{{no matching}} |
| 450 | int **p2 = f({ {1,2,3}, {3, 4, 5} }); |
| 451 | int **p22 = f({ {1,2}, {3, 4} }); |
| 452 | int *p1 = f({1, 2, 3}); |
| 453 | } |
| 454 | |
| 455 | namespace check_arrays_of_init_list { |
| 456 | template<class T, int N> float *f(const std::initializer_list<T> (&)[N]); |
| 457 | template<class T, int N> double *f(const T(&)[N]); |
| 458 | double *p = f({1, 2, 3}); |
| 459 | float *fp = f({{1}, {1, 2}, {1, 2, 3}}); |
| 460 | } |
| 461 | namespace core_reflector_28543 { |
| 462 | |
| 463 | template<class T, int N> int *f(T (&&)[N]); // #1 |
| 464 | template<class T> char *f(std::initializer_list<T> &&); //#2 |
| 465 | template<class T, int N, int M> int **f(T (&&)[N][M]); //#3 expected-note{{candidate}} |
| 466 | template<class T, int N> char **f(std::initializer_list<T> (&&)[N]); //#4 expected-note{{candidate}} |
| 467 | |
| 468 | template<class T> short *f(T (&&)[2]); //#5 |
| 469 | |
| 470 | template<class T> using Arr = T[]; |
| 471 | |
| 472 | char *pc = f({1, 2, 3}); // OK prefer #2 via 13.3.3.2 [over.ics.rank] |
| 473 | char *pc2 = f({1, 2}); // #2 also |
| 474 | int *pi = f(Arr<int>{1, 2, 3}); // OK prefer #1 |
| 475 | |
| 476 | void *pv1 = f({ {1, 2, 3}, {4, 5, 6} }); // expected-error{{ambiguous}} btw 3 & 4 |
| 477 | char **pcc = f({ {1}, {2, 3} }); // OK #4 |
| 478 | |
| 479 | short *ps = f(Arr<int>{1, 2}); // OK #5 |
| 480 | } |
| 481 | } // dr1591 |
| 482 | |
| 483 | #endif |
| 484 | |