xref: /llvm-project/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp (revision 444ec0957c58492ecce0569bb20b7d3ad59d37bb)
1 // RUN: %clang_cc1 -std=c++20 -verify %s
2 // RUN: %clang_cc1 -std=c++17 -verify %s
3 
4 // p0388 conversions to unbounded array
5 // dcl.init.list/3
6 
7 namespace One {
8 int ga[1];
9 
frob1()10 auto &frob1() {
11   int(&r1)[] = ga;
12 #if __cplusplus < 202002
13   // expected-error@-2{{cannot bind to a value of unrelated type}}
14 #endif
15 
16   return r1;
17 }
18 
frob2(int (& arp)[1])19 auto &frob2(int (&arp)[1]) {
20   int(&r2)[] = arp;
21 #if __cplusplus < 202002
22   // expected-error@-2{{cannot bind to a value of unrelated type}}
23 #endif
24 
25   return r2;
26 }
27 } // namespace One
28 
29 namespace Two {
30 int ga[1];
31 
frob1()32 auto *frob1() {
33   int(*r1)[] = &ga;
34 #if __cplusplus < 202002
35   // expected-error@-2{{with an rvalue of type}}
36 #endif
37 
38   return r1;
39 }
40 
frob2(int (* arp)[1])41 auto *frob2(int (*arp)[1]) {
42   int(*r2)[] = arp;
43 #if __cplusplus < 202002
44   // expected-error@-2{{with an lvalue of type}}
45 #endif
46 
47   return r2;
48 }
49 } // namespace Two
50 
51 namespace Four {
52 using Inc = int[2];
53 using Mat = Inc[1];
54 Mat *ga[2];
55 
frob1()56 auto *frob1() {
57   Inc(*const(*r1)[])[] = &ga;
58 #if __cplusplus < 202002
59   // expected-error@-2{{with an rvalue of type}}
60 #else
61   // missing a required 'const'
62   Inc(*(*r2)[])[] = &ga; // expected-error{{cannot initialize}}
63 #endif
64 
65   return r1;
66 }
67 
frob2(Mat * (* arp)[1])68 auto *frob2(Mat *(*arp)[1]) {
69   Inc(*const(*r2)[])[] = arp;
70 #if __cplusplus < 202002
71   // expected-error@-2{{with an lvalue of type}}
72 #else
73   Inc(*(*r3)[])[] = arp; // expected-error{{cannot initialize}}
74 #endif
75 
76   return r2;
77 }
78 
79 } // namespace Four
80 
81 namespace Five {
82 // from the paper
83 char (&b(int(&&)[]))[1];   // #1
84 char (&b(long(&&)[]))[2];  // #2
85 char (&b(int(&&)[1]))[3];  // #3
86 char (&b(long(&&)[1]))[4]; // #4
87 char (&b(int(&&)[2]))[5];  // #5
88 #if __cplusplus < 202002
89     // 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 #endif
95 
f()96 void 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 < 202002
101   // expected-error@-2{{no matching function}}
102 #endif
103 }
104 } // namespace Five
105 
106 #if __cplusplus >= 202002
107 namespace Six {
108 // from over.ics.rank 3.1
109 char (&f(int(&&)[]))[1];    // #1
110 char (&f(double(&&)[]))[2]; // #2
111 char (&f(int(&&)[2]))[3];   // #3
112 
toto()113 void toto() {
114   // Calls #1: Better than #2 due to conversion, better than #3 due to bounds
115   static_assert(sizeof(f({1})) == 1);
116 
117   // Calls #2: Identity conversion is better than floating-integral conversion
118   static_assert(sizeof(f({1.0})) == 2);
119 
120   // Calls #2: Identity conversion is better than floating-integral conversion
121   static_assert(sizeof(f({1.0, 2.0})) == 2);
122 
123   // Calls #3: Converting to array of known bound is better than to unknown
124   //           bound, and an identity conversion is better than
125   //           floating-integral conversion
126   static_assert(sizeof(f({1, 2})) == 3);
127 }
128 
129 } // namespace Six
130 
131 namespace Seven {
132 
133 char (&f(int(&&)[]))[1];     // #1
134 char (&f(double(&&)[1]))[2]; // #2
135 
quux()136 void quux() {
137   // Calls #2, float-integral conversion rather than create zero-sized array
138   static_assert(sizeof(f({})) == 2);
139 }
140 
141 } // namespace Seven
142 
143 namespace Eight {
144 
145 // brace-elision is not a thing here:
146 struct A {
147   int x, y;
148 };
149 
150 char (&f1(int(&&)[]))[1]; // #1
151 char (&f1(A(&&)[]))[2];   // #2
152 
g1()153 void g1() {
154   // pick #1, even though that is more elements than #2
155   // 6 ints, as opposed to 3 As
156   static_assert(sizeof(f1({1, 2, 3, 4, 5, 6})) == 1);
157 }
158 
159 void f2(A(&&)[]); // expected-note{{candidate function not viable}}
g2()160 void g2() {
161   f2({1, 2, 3, 4, 5, 6}); // expected-error{{no matching function}}
162 }
163 
164 void f3(A(&&)[]);
g3()165 void g3() {
166   auto &f = f3;
167 
168   f({1, 2, 3, 4, 5, 6}); // OK! We're coercing to an already-selected function
169 }
170 
171 } // namespace Eight
172 
173 #endif
174