File: cxx20-p0388-unbound-ary.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (173 lines) | stat: -rw-r--r-- 3,776 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// 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