]>
Commit | Line | Data |
---|---|---|
a2c2cee9 MS |
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; | |
a1108556 | 115 | q[2] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } |
a2c2cee9 MS |
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; | |
a1108556 MS |
238 | q[1] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } |
239 | q[9] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } | |
a2c2cee9 MS |
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; | |
a1108556 | 251 | q[j] = __LINE__; // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } |
a2c2cee9 | 252 | } |