1 /* PR tree-optimization/84095 - false-positive -Wrestrict warnings for
2    strcpy within array
3    { dg-do compile }
4    { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */
5 
6 typedef __SIZE_TYPE__ size_t;
7 
8 extern void* memcpy (void* restrict, const void* restrict, size_t);
9 extern char* strcpy (char* restrict, const char* restrict);
10 
11 #define T(d, s)   strcpy (d, s)
12 
13 struct MemArrays {
14   char pad[8];
15   char a2[3][9];
16   char a3[3][4][9];
17 } a[2];
18 
19 struct NestedMemArrays {
20   struct MemArrays ma;
21   struct MemArrays ma1[2];
22 } nma[2];
23 
24 /* Use a variable as the source of a copy to verify that VAR_DECL
25    is handled correctly when it's the source of GIMPLE assignment.  */
26 const char *str = "1234567";
27 
test_obj_2_dim_const(void)28 void test_obj_2_dim_const (void)
29 {
30   const char *s = strcpy (a[0].a2[0], "1234567");
31 
32   T (a[0].a2[1], s);
33   T (a[0].a2[2], s);
34 
35   /* Ideally, the offsets in the warning below would be relative to
36      the beginning of the accessed array member.  Unfortunately, when
37      the offset is represented as
38      MEM_REF (char[9], A, offsetof (struct MemArrays, A[0].A2[0]) + 1)
39      as it is in this instance it's difficult to determine the member
40      that is being accessed and tease out from the MEM_REF the offset
41      as it appears in the source.  As a result, the warning mentions
42      the offset from the beginning of A instead.  This is suboptimal
43      and should be fixed, either by printing the correct offsets or
44      by mentioning the base object that the offset is relative to.  */
45   T (a[0].a2[0] + 1, s);      /* { dg-warning "accessing 8 bytes at offsets \(1|9\) and \(0|8\) overlaps 7 bytes at offset \(1|9\)." } */
46   T (a[0].a2[1] + 2, s);
47   T (a[0].a2[2] + 3, s);
48 
49   T (a[1].a2[0], s);
50   T (a[1].a2[1], s);
51   T (a[1].a2[2], s);
52 
53   T (a[1].a2[0] + 1, s);
54   T (a[1].a2[1] + 2, s);
55   T (a[1].a2[2] + 3, s);
56 }
57 
test_obj_nested_2_dim_const(void)58 void test_obj_nested_2_dim_const (void)
59 {
60   const char *s = strcpy (nma[0].ma.a2[0], str);
61 
62   T (nma[0].ma.a2[1], s);
63   T (nma[0].ma.a2[2], s);
64 
65   T (nma[0].ma.a2[0] + 1, s);      /* { dg-warning "accessing 8 bytes at offsets 1 and 0 overlaps 7 bytes at offset 1" "bug " { xfail *-*-* } } */
66   T (nma[0].ma.a2[1] + 2, s);
67   T (nma[0].ma.a2[2] + 3, s);
68 
69   T (nma[1].ma.a2[1], s);
70   T (nma[1].ma.a2[2], s);
71 
72   T (nma[1].ma.a2[0] + 1, s);
73   T (nma[1].ma.a2[1] + 2, s);
74   T (nma[1].ma.a2[2] + 3, s);
75 
76 
77   T (nma[0].ma1[0].a2[1], s);
78   T (nma[0].ma1[0].a2[2], s);
79 
80   T (nma[0].ma1[0].a2[0] + 1, s);
81   T (nma[0].ma1[0].a2[1] + 2, s);
82   T (nma[0].ma1[0].a2[2] + 3, s);
83 
84   T (nma[1].ma1[0].a2[1], s);
85   T (nma[1].ma1[0].a2[2], s);
86 
87   T (nma[1].ma1[0].a2[0] + 1, s);
88   T (nma[1].ma1[0].a2[1] + 2, s);
89   T (nma[1].ma1[0].a2[2] + 3, s);
90 }
91 
test_obj_2_dim_var(int i,int j)92 void test_obj_2_dim_var (int i, int j)
93 {
94   const char *s = memcpy (a[0].a2[0], "1234567", 8);
95 
96   T (a[i].a2[0], s);          /* { dg-bogus "\\\[-Wrestrict]" } */
97   T (a[i].a2[1], s);
98   T (a[i].a2[2], s);
99 
100   T (a[i].a2[0] + 1, s);
101   T (a[i].a2[1] + 1, s);
102   T (a[i].a2[2] + 1, s);
103 
104   T (a[0].a2[i], s);          /* { dg-bogus "\\\[-Wrestrict]" } */
105   T (a[1].a2[i], s);
106 
107   T (a[i].a2[0] + j, s);
108   T (a[i].a2[1] + j, s);
109   T (a[i].a2[2] + j, s);
110 
111   T (a[0].a2[i] + 1, s);
112   T (a[1].a2[i] + 1, s);
113 
114   T (a[0].a2[i] + j, s);
115   T (a[1].a2[i] + j, s);
116 
117   if (i < 0 || 1 < i)
118     i = 1;
119 
120   T (a[i].a2[0], s);
121   T (a[i].a2[1], s);
122   T (a[i].a2[2], s);
123 
124   T (a[i].a2[0] + 1, s);
125   T (a[i].a2[1] + 1, s);
126   T (a[i].a2[2] + 1, s);
127 
128   T (a[0].a2[i], s);
129   T (a[1].a2[i], s);
130 
131   T (a[i].a2[0] + j, s);
132   T (a[i].a2[1] + j, s);
133   T (a[i].a2[2] + j, s);
134 
135   T (a[0].a2[i] + 1, s);
136   T (a[1].a2[i] + 1, s);
137 
138   T (a[0].a2[i] + j, s);
139   T (a[1].a2[i] + j, s);
140 }
141 
test_obj_nested_2_dim_var(int i,int j)142 void test_obj_nested_2_dim_var (int i, int j)
143 {
144   const char *s = strcpy (nma[0].ma.a2[0], "1234567");
145 
146   T (nma[i].ma.a2[0], s);     /* { dg-bogus "\\\[-Wrestrict]" } */
147   T (nma[i].ma.a2[1], s);
148   T (nma[i].ma.a2[2], s);
149 
150   T (nma[i].ma.a2[0] + 1, s);
151   T (nma[i].ma.a2[1] + 1, s);
152   T (nma[i].ma.a2[2] + 1, s);
153 
154   T (nma[0].ma.a2[i], s);     /* { dg-bogus "\\\[-Wrestrict]" } */
155   T (nma[1].ma.a2[i], s);
156 
157   T (nma[i].ma.a2[0] + j, s);
158   T (nma[i].ma.a2[1] + j, s);
159   T (nma[i].ma.a2[2] + j, s);
160 
161   T (nma[0].ma.a2[i] + 1, s);
162   T (nma[1].ma.a2[i] + 1, s);
163 
164   T (nma[0].ma.a2[i] + j, s);
165   T (nma[1].ma.a2[i] + j, s);
166 }
167 
test_ref_2_dim_const(struct MemArrays * p)168 void test_ref_2_dim_const (struct MemArrays *p)
169 {
170   strcpy (p[0].a2[0], "1234567");
171   const char *s = p[0].a2[0];
172 
173   T (p[0].a2[1], s);
174   T (p[0].a2[2], s);
175 
176   T (p[1].a2[0], s);
177   T (p[1].a2[1], s);
178   T (p[1].a2[2], s);
179 }
180 
test_ref_2_dim_var(struct MemArrays * p,int i,int j)181 void test_ref_2_dim_var (struct MemArrays *p, int i, int j)
182 {
183   strcpy (p[0].a2[0], "1234567");
184   const char *s = p[0].a2[0];
185 
186   T (p[i].a2[0], s);          /* { dg-bogus "\\\[-Wrestrict]" } */
187   T (p[i].a2[1], s);
188   T (p[i].a2[2], s);
189 
190   T (p[0].a2[i], s);
191   T (p[1].a2[i], s);
192 
193   T (p[i].a2[0] + j, s);
194   T (p[i].a2[1] + j, s);
195   T (p[i].a2[2] + j, s);
196 
197   T (p[0].a2[i] + j, s);
198   T (p[1].a2[i] + j, s);
199 }
200 
test_obj_3_dim_var(int i,int j)201 void test_obj_3_dim_var (int i, int j)
202 {
203   strcpy (a[0].a3[0][0], "1234567");
204   const char *s = a[0].a3[0][0];
205 
206   T (a[0].a3[0][i], s);
207   T (a[0].a3[1][i], s);
208   T (a[0].a3[2][i], s);
209 
210   T (a[1].a3[0][i], s);
211   T (a[1].a3[1][i], s);
212   T (a[1].a3[2][i], s);
213 
214   T (a[0].a3[i][0], s);       /* { dg-bogus "\\\[-Wrestrict\]" } */
215   T (a[0].a3[i][1], s);
216   T (a[0].a3[i][2], s);
217 
218   T (a[1].a3[i][0], s);
219   T (a[1].a3[i][1], s);
220   T (a[1].a3[i][2], s);
221 
222   T (a[i].a3[0][0], s);       /* { dg-bogus "\\\[-Wrestrict\]" } */
223   T (a[i].a3[0][1], s);
224   T (a[i].a3[0][2], s);
225 
226   T (a[i].a3[1][0], s);
227   T (a[i].a3[1][1], s);
228   T (a[i].a3[1][2], s);
229 
230   T (a[i].a3[2][0], s);
231   T (a[i].a3[2][1], s);
232   T (a[i].a3[2][2], s);
233 
234 
235   T (a[0].a3[0][i] + 1, s);
236   T (a[0].a3[1][i] + 1, s);
237   T (a[0].a3[2][i] + 1, s);
238 
239   T (a[1].a3[0][i] + 1, s);
240   T (a[1].a3[1][i] + 1, s);
241   T (a[1].a3[2][i] + 1, s);
242 
243 
244   T (a[0].a3[0][i] + j, s);
245   T (a[0].a3[1][i] + j, s);
246   T (a[0].a3[2][i] + j, s);
247 
248   T (a[1].a3[0][i] + j, s);
249   T (a[1].a3[1][i] + j, s);
250   T (a[1].a3[2][i] + j, s);
251 
252   T (a[0].a3[i][0] + j, s);
253   T (a[0].a3[i][1] + j, s);
254   T (a[0].a3[i][2] + j, s);
255 
256   T (a[1].a3[i][0] + j, s);
257   T (a[1].a3[i][1] + j, s);
258   T (a[1].a3[i][2] + j, s);
259 
260   T (a[i].a3[0][0] + j, s);
261   T (a[i].a3[0][1] + j, s);
262   T (a[i].a3[0][2] + j, s);
263 
264   T (a[i].a3[1][0] + j, s);
265   T (a[i].a3[1][1] + j, s);
266   T (a[i].a3[1][2] + j, s);
267 
268   T (a[i].a3[2][0] + j, s);
269   T (a[i].a3[2][1] + j, s);
270   T (a[i].a3[2][2] + j, s);
271 }
272 
test_obj_3_dim_const(struct MemArrays * p)273 void test_obj_3_dim_const (struct MemArrays *p)
274 {
275   strcpy (p[0].a3[0][0], "1234567");
276   const char *s = p[0].a3[0][0];
277 
278   T (p[0].a3[0][1], s);
279   T (p[0].a3[0][2], s);
280   T (p[0].a3[0][3], s);
281 
282   T (p[0].a3[0][1] + 1, s);
283   T (p[0].a3[0][2] + 1, s);
284   T (p[0].a3[0][3] + 1, s);
285 
286   T (p[0].a3[1][0], s);
287   T (p[0].a3[1][1], s);
288   T (p[0].a3[1][2], s);
289   T (p[0].a3[1][3], s);
290 
291   T (p[0].a3[1][0] + 1, s);
292   T (p[0].a3[1][1] + 1, s);
293   T (p[0].a3[1][2] + 1, s);
294   T (p[0].a3[1][3] + 1, s);
295 
296   T (p[0].a3[2][0], s);
297   T (p[0].a3[2][1], s);
298   T (p[0].a3[2][2], s);
299   T (p[0].a3[2][3], s);
300 
301   T (p[1].a3[0][0], s);
302   T (p[1].a3[0][1], s);
303   T (p[1].a3[0][2], s);
304   T (p[1].a3[0][3], s);
305 
306   T (p[1].a3[1][0], s);
307   T (p[1].a3[1][1], s);
308   T (p[1].a3[1][2], s);
309   T (p[1].a3[1][3], s);
310 
311   T (p[1].a3[2][0], s);
312   T (p[1].a3[2][1], s);
313   T (p[1].a3[2][2], s);
314   T (p[1].a3[2][3], s);
315 }
316