174 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -verify %s2// RUN: %clang_cc1 -std=c++17 -verify %s3 4// p0388 conversions to unbounded array5// dcl.init.list/36 7namespace One {8int ga[1];9 10auto &frob1() {11 int(&r1)[] = ga;12#if __cplusplus < 20200213 // expected-error@-2{{cannot bind to a value of unrelated type}}14#endif15 16 return r1;17}18 19auto &frob2(int (&arp)[1]) {20 int(&r2)[] = arp;21#if __cplusplus < 20200222 // expected-error@-2{{cannot bind to a value of unrelated type}}23#endif24 25 return r2;26}27} // namespace One28 29namespace Two {30int ga[1];31 32auto *frob1() {33 int(*r1)[] = &ga;34#if __cplusplus < 20200235 // expected-error@-2{{with an rvalue of type}}36#endif37 38 return r1;39}40 41auto *frob2(int (*arp)[1]) {42 int(*r2)[] = arp;43#if __cplusplus < 20200244 // expected-error@-2{{with an lvalue of type}}45#endif46 47 return r2;48}49} // namespace Two50 51namespace Four {52using Inc = int[2];53using Mat = Inc[1];54Mat *ga[2];55 56auto *frob1() {57 Inc(*const(*r1)[])[] = &ga;58#if __cplusplus < 20200259 // expected-error@-2{{with an rvalue of type}}60#else61 // missing a required 'const'62 Inc(*(*r2)[])[] = &ga; // expected-error{{cannot initialize}}63#endif64 65 return r1;66}67 68auto *frob2(Mat *(*arp)[1]) {69 Inc(*const(*r2)[])[] = arp;70#if __cplusplus < 20200271 // expected-error@-2{{with an lvalue of type}}72#else73 Inc(*(*r3)[])[] = arp; // expected-error{{cannot initialize}}74#endif75 76 return r2;77}78 79} // namespace Four80 81namespace Five {82// from the paper83char (&b(int(&&)[]))[1]; // #184char (&b(long(&&)[]))[2]; // #285char (&b(int(&&)[1]))[3]; // #386char (&b(long(&&)[1]))[4]; // #487char (&b(int(&&)[2]))[5]; // #588#if __cplusplus < 20200289 // expected-note@-6{{cannot convert initializer}}90 // expected-note@-6{{cannot convert initializer}}91 // expected-note@-6{{too many initializers}}92 // expected-note@-6{{too many initializers}}93 // expected-note@-6{{too many initializers}}94#endif95 96void f() {97 static_assert(sizeof(b({1})) == 3);98 static_assert(sizeof(b({1, 2})) == 5);99 static_assert(sizeof(b({1, 2, 3})) == 1);100#if __cplusplus < 202002101 // expected-error@-2{{no matching function}}102#endif103}104} // namespace Five105 106#if __cplusplus >= 202002107namespace Six {108// from over.ics.rank 3.1109char (&f(int(&&)[]))[1]; // #1110char (&f(double(&&)[]))[2]; // #2111char (&f(int(&&)[2]))[3]; // #3112 113void toto() {114 // Calls #1: Better than #2 due to conversion, better than #3 due to bounds115 static_assert(sizeof(f({1})) == 1);116 117 // Calls #2: Identity conversion is better than floating-integral conversion118 static_assert(sizeof(f({1.0})) == 2);119 120 // Calls #2: Identity conversion is better than floating-integral conversion121 static_assert(sizeof(f({1.0, 2.0})) == 2);122 123 // Calls #3: Converting to array of known bound is better than to unknown124 // bound, and an identity conversion is better than125 // floating-integral conversion126 static_assert(sizeof(f({1, 2})) == 3);127}128 129} // namespace Six130 131namespace Seven {132 133char (&f(int(&&)[]))[1]; // #1134char (&f(double(&&)[1]))[2]; // #2135 136void quux() {137 // Calls #2, float-integral conversion rather than create zero-sized array138 static_assert(sizeof(f({})) == 2);139}140 141} // namespace Seven142 143namespace Eight {144 145// brace-elision is not a thing here:146struct A {147 int x, y;148};149 150char (&f1(int(&&)[]))[1]; // #1151char (&f1(A(&&)[]))[2]; // #2152 153void g1() {154 // pick #1, even though that is more elements than #2155 // 6 ints, as opposed to 3 As156 static_assert(sizeof(f1({1, 2, 3, 4, 5, 6})) == 1);157}158 159void f2(A(&&)[]); // expected-note{{candidate function not viable}}160void g2() {161 f2({1, 2, 3, 4, 5, 6}); // expected-error{{no matching function}}162}163 164void f3(A(&&)[]);165void g3() {166 auto &f = f3;167 168 f({1, 2, 3, 4, 5, 6}); // OK! We're coercing to an already-selected function169}170 171} // namespace Eight172 173#endif174