| // RUN: %clang_cc1 -std=c++20 -verify %s |
| // RUN: %clang_cc1 -std=c++17 -verify %s |
| |
| // p0388 conversions to unbounded array |
| // dcl.init.list/3 |
| |
| namespace One { |
| int ga[1]; |
| |
| auto &frob1() { |
| int(&r1)[] = ga; |
| #if __cplusplus < 202002 |
| // expected-error@-2{{cannot bind to a value of unrelated type}} |
| #endif |
| |
| return r1; |
| } |
| |
| auto &frob2(int (&arp)[1]) { |
| int(&r2)[] = arp; |
| #if __cplusplus < 202002 |
| // expected-error@-2{{cannot bind to a value of unrelated type}} |
| #endif |
| |
| return r2; |
| } |
| } // namespace One |
| |
| namespace Two { |
| int ga[1]; |
| |
| auto *frob1() { |
| int(*r1)[] = &ga; |
| #if __cplusplus < 202002 |
| // expected-error@-2{{with an rvalue of type}} |
| #endif |
| |
| return r1; |
| } |
| |
| auto *frob2(int (*arp)[1]) { |
| int(*r2)[] = arp; |
| #if __cplusplus < 202002 |
| // expected-error@-2{{with an lvalue of type}} |
| #endif |
| |
| return r2; |
| } |
| } // namespace Two |
| |
| namespace Four { |
| using Inc = int[2]; |
| using Mat = Inc[1]; |
| Mat *ga[2]; |
| |
| auto *frob1() { |
| Inc(*const(*r1)[])[] = &ga; |
| #if __cplusplus < 202002 |
| // expected-error@-2{{with an rvalue of type}} |
| #else |
| // missing a required 'const' |
| Inc(*(*r2)[])[] = &ga; // expected-error{{cannot initialize}} |
| #endif |
| |
| return r1; |
| } |
| |
| auto *frob2(Mat *(*arp)[1]) { |
| Inc(*const(*r2)[])[] = arp; |
| #if __cplusplus < 202002 |
| // expected-error@-2{{with an lvalue of type}} |
| #else |
| Inc(*(*r3)[])[] = arp; // expected-error{{cannot initialize}} |
| #endif |
| |
| return r2; |
| } |
| |
| } // namespace Four |
| |
| namespace Five { |
| // from the paper |
| char (&b(int(&&)[]))[1]; // #1 |
| char (&b(long(&&)[]))[2]; // #2 |
| char (&b(int(&&)[1]))[3]; // #3 |
| char (&b(long(&&)[1]))[4]; // #4 |
| char (&b(int(&&)[2]))[5]; // #5 |
| #if __cplusplus < 202002 |
| // expected-note@-6{{cannot convert initializer}} |
| // expected-note@-6{{cannot convert initializer}} |
| // expected-note@-6{{too many initializers}} |
| // expected-note@-6{{too many initializers}} |
| // expected-note@-6{{too many initializers}} |
| #endif |
| |
| void f() { |
| static_assert(sizeof(b({1})) == 3); |
| static_assert(sizeof(b({1, 2})) == 5); |
| static_assert(sizeof(b({1, 2, 3})) == 1); |
| #if __cplusplus < 202002 |
| // expected-error@-2{{no matching function}} |
| #endif |
| } |
| } // namespace Five |
| |
| #if __cplusplus >= 202002 |
| namespace Six { |
| // from over.ics.rank 3.1 |
| char (&f(int(&&)[]))[1]; // #1 |
| char (&f(double(&&)[]))[2]; // #2 |
| char (&f(int(&&)[2]))[3]; // #3 |
| |
| void toto() { |
| // Calls #1: Better than #2 due to conversion, better than #3 due to bounds |
| static_assert(sizeof(f({1})) == 1); |
| |
| // Calls #2: Identity conversion is better than floating-integral conversion |
| static_assert(sizeof(f({1.0})) == 2); |
| |
| // Calls #2: Identity conversion is better than floating-integral conversion |
| static_assert(sizeof(f({1.0, 2.0})) == 2); |
| |
| // Calls #3: Converting to array of known bound is better than to unknown |
| // bound, and an identity conversion is better than |
| // floating-integral conversion |
| static_assert(sizeof(f({1, 2})) == 3); |
| } |
| |
| } // namespace Six |
| |
| namespace Seven { |
| |
| char (&f(int(&&)[]))[1]; // #1 |
| char (&f(double(&&)[1]))[2]; // #2 |
| |
| void quux() { |
| // Calls #2, float-integral conversion rather than create zero-sized array |
| static_assert(sizeof(f({})) == 2); |
| } |
| |
| } // namespace Seven |
| |
| namespace Eight { |
| |
| // brace-elision is not a thing here: |
| struct A { |
| int x, y; |
| }; |
| |
| char (&f1(int(&&)[]))[1]; // #1 |
| char (&f1(A(&&)[]))[2]; // #2 |
| |
| void g1() { |
| // pick #1, even though that is more elements than #2 |
| // 6 ints, as opposed to 3 As |
| static_assert(sizeof(f1({1, 2, 3, 4, 5, 6})) == 1); |
| } |
| |
| void f2(A(&&)[]); // expected-note{{candidate function not viable}} |
| void g2() { |
| f2({1, 2, 3, 4, 5, 6}); // expected-error{{no matching function}} |
| } |
| |
| void f3(A(&&)[]); |
| void g3() { |
| auto &f = f3; |
| |
| f({1, 2, 3, 4, 5, 6}); // OK! We're coercing to an already-selected function |
| } |
| |
| } // namespace Eight |
| |
| #endif |