1 /* PR middle-end/95353 - spurious -Wstringop-overflow writing to a trailing
2 array plus offset
3 { dg-do compile }
4 { dg-options "-O2 -Wall" } */
5
6 typedef __SIZE_TYPE__ size_t;
7
8 struct S0 { char n, a[0]; };
9
10
11 void s0_nowarn_cstidx (struct S0 *p)
12 {
13 char *q = p->a;
14 q[1] = __LINE__;
15 q[9] = __LINE__;
16 }
17
18 void s0_nowarn_cstoff_cstidx (struct S0 *p)
19 {
20 char *q = p->a + 1;
21 q[1] = __LINE__;
22 q[9] = __LINE__;
23 }
24
25 void s0_nowarn_varoff_cstdix (struct S0 *p, int i)
26 {
27 char *q = p->a + i;
28 q[1] = __LINE__; // { dg-bogus "\\\[-Wstringop-overflow" }
29 q[9] = __LINE__; // { dg-bogus "\\\[-Wstringop-overflow" }
30 }
31
32 void s0_nowarn_cstoff_varidx (struct S0 *p, int i)
33 {
34 char *q = p->a + 1;
35 q[i] = __LINE__;
36 }
37
38 void s0_nowarn_varoff_varidx (struct S0 *p, int i, int j)
39 {
40 char *q = p->a + i;
41 q[j] = __LINE__; // { dg-bogus "\\\[-Wstringop-overflow" }
42 }
43
44
45 /* Accesses past the end of a trailing array with one element is
46 discouraged but still reluctantly not diagnosed. This should
47 change. */
48
49 struct S1 { char n, a[1]; };
50
51
52 void s1_nowarn_cstidx (struct S1 *p)
53 {
54 char *q = p->a;
55 q[1] = __LINE__;
56 q[9] = __LINE__;
57 }
58
59 void s1_nowarn_cstoff_cstidx (struct S1 *p)
60 {
61 char *q = p->a + 1;
62 q[1] = __LINE__;
63 q[9] = __LINE__;
64 }
65
66 void s1_nowarn_varoff_cstdix (struct S1 *p, int i)
67 {
68 char *q = p->a + i;
69 q[1] = __LINE__; // { dg-bogus "\\\[-Wstringop-overflow" }
70 q[9] = __LINE__; // { dg-bogus "\\\[-Wstringop-overflow" }
71 }
72
73 void s1_nowarn_cstoff_varidx (struct S1 *p, int i)
74 {
75 char *q = p->a + 1;
76 q[i] = __LINE__;
77 }
78
79 void s1_nowarn_varoff_varidx (struct S1 *p, int i, int j)
80 {
81 char *q = p->a + i;
82 q[j] = __LINE__;
83 }
84
85
86 /* Accesses past the end of a trailing array with more than one
87 element should be diagnosed but aren't yet because the MEM_REF
88 makes the out-of-bounds accesses indistinguishable from valid
89 ones to subsequent elements of the array pointed by P. */
90
91 struct S2 { char n, a[2]; };
92
93
94 void s2_warn_cstidx (struct S2 *p)
95 {
96 char *q = p->a;
97
98 /* The following invalid store is represented as
99 MEM[(char *)p_1(D) + 3B] = __LINE__;
100 which is indistinguishable from the valid
101 q = &p[1].n; q[0] = __LINE__;
102 */
103 q[2] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
104 }
105
106 void s2_warn_cstoff_cstidx (struct S2 *p)
107 {
108 char *q = p->a + 1;
109 q[1] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
110 }
111
112 void s2_warn_varoff_cstdix (struct S2 *p, int i)
113 {
114 char *q = p->a + i;
115 q[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
116 }
117
118 void s2_warn_cstoff_varidx (struct S2 *p, int i)
119 {
120 char *q = p->a + 1;
121 q[i] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
122 }
123
124 void s2_warn_varoff_varidx (struct S2 *p, int i, int j)
125 {
126 char *q = p->a + i;
127 q[j] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
128 }
129
130
131 /* Verify that none of these triggers a bogus warning (not tested
132 elsewhere but triggered during bootstrap). */
133
134 void s2_nowarn_varidx_int (struct S2 *p, int i)
135 {
136 extern struct S2 s2;
137 extern struct S2 s2a[];
138
139 s2.a[i - 1] = __LINE__;
140 s2.a[i] = __LINE__;
141 s2.a[i + 1] = __LINE__;
142
143 s2a[i].a[i - 1] = __LINE__;
144 s2a[i].a[i] = __LINE__;
145 s2a[i].a[i + 1] = __LINE__;
146
147 p[i].a[i - 1] = __LINE__;
148 p[i].a[i] = __LINE__;
149 p[i].a[i + 1] = __LINE__;
150
151 char *q = p->a;
152 q[i - 1] = __LINE__;
153 q[i] = __LINE__;
154 q[i + 1] = __LINE__;
155 }
156
157 /* Same as above but with a size_t index in range [1, SIZE_MAX]. */
158
159 void* s2_nowarn_varidx_size (struct S2 *p, size_t i, size_t j)
160 {
161 extern struct S2 s2;
162 extern struct S2 s2a[];
163 struct S2 *ps2 = __builtin_malloc (3 * sizeof *ps2);
164
165 s2.a[i - 1] = __LINE__;
166 s2.a[i] = __LINE__;
167 s2.a[i + 1] = __LINE__;
168
169 s2a[i].a[i - 1] = __LINE__;
170 s2a[i].a[i] = __LINE__;
171 s2a[i].a[i + 1] = __LINE__;
172
173 p[i].a[i - 1] = __LINE__;
174 p[i].a[i] = __LINE__;
175 p[i].a[i + 1] = __LINE__;
176
177 ps2->a[i - 1] = __LINE__;
178 ps2->a[i] = __LINE__;
179 ps2->a[i + 1] = __LINE__;
180
181 char *q = p->a;
182 q[i - 1] = __LINE__;
183 q[i] = __LINE__;
184 q[i + 1] = __LINE__;
185
186 if (j == 0)
187 return ps2;
188
189 s2.a[j - 1] = __LINE__;
190 s2.a[j] = __LINE__;
191 s2.a[j + 1] = __LINE__;
192
193 s2a[j].a[j - 1] = __LINE__;
194 s2a[j].a[j] = __LINE__;
195 s2a[j].a[j + 1] = __LINE__;
196
197 p[j].a[j - 1] = __LINE__;
198 p[j].a[j] = __LINE__;
199 p[j].a[j + 1] = __LINE__;
200
201 ps2->a[j - 1] = __LINE__;
202 ps2->a[j] = __LINE__;
203 ps2->a[j + 1] = __LINE__;
204
205 q = p->a;
206 q[j - 1] = __LINE__;
207 q[j] = __LINE__;
208 q[j + 1] = __LINE__;
209
210 return ps2;
211 }
212
213 /* Verify that accesses to an interior zero-length array are diagnosed. */
214
215 struct Si0 { char c, a[0], d; };
216
217 void si0_warn_cstidx (struct Si0 *p)
218 {
219 // These are indistinguishable from valid accesses to p->d:
220 // MEM[(char *)p_1(D) + 1B] = 0;
221 char *q = p->a;
222 q[1] = __LINE__; // { dg-warning "writing 1 byte into a region of size 0" "pr?????" { xfail *-*-* } }
223 q[9] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
224 }
225
226 void si0_warn_cstoff_cstidx (struct Si0 *p)
227 {
228 // Like those above, these too are indistinguishable from valid accesses
229 // to p->d.
230 char *q = p->a + 1;
231 q[1] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
232 q[9] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
233 }
234
235 void si0_warn_varoff_cstdix (struct Si0 *p, int i)
236 {
237 char *q = p->a + i;
238 q[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
239 q[9] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
240 }
241
242 void si0_warn_cstoff_varidx (struct Si0 *p, int i)
243 {
244 char *q = p->a + 1;
245 q[i] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
246 }
247
248 void si0_warn_varoff_varidx (struct Si0 *p, int i, int j)
249 {
250 char *q = p->a + i;
251 q[j] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
252 }