1 /* PR tree-optimization/84095 - false-positive -Wrestrict warnings for
2    memcpy 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 
10 #define T(d, s, n)   memcpy (d, s, n)
11 
12 struct S1 { char c; } a8_1[8];
13 
test_1_dim_var(int i,int j)14 void test_1_dim_var (int i, int j)
15 {
16   /* Variable destination index and constant source index.  */
17   T (&a8_1[i], &a8_1[0], 1);
18   T (&a8_1[i], &a8_1[0], 2);
19   T (&a8_1[i], &a8_1[0], 3);
20   T (&a8_1[i], &a8_1[0], 4);
21 
22   T (&a8_1[i], &a8_1[0], 5);    /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and 0 overlaps between 2 and 5 bytes at offset \\\[0, 3\\\]" } */
23   T (&a8_1[i], &a8_1[0], 6);    /* { dg-warning "accessing 6 bytes at offsets \\\[0, 8] and 0 overlaps between 4 and 6 bytes at offset \\\[0, 2\\\]" } */
24   T (&a8_1[i], &a8_1[0], 7);    /* { dg-warning "accessing 7 bytes at offsets \\\[0, 8] and 0 overlaps between 6 and 7 bytes at offset \\\[0, 1\\\]" } */
25   T (&a8_1[i], &a8_1[0], 8);    /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and 0 overlaps 8 bytes at offset 0" } */
26 
27   /* The following is diagnosed by -Warray-bounds when it's enabled
28      rather than by -Wrestrict.  */
29   T (&a8_1[i], &a8_1[0], 9);    /* { dg-warning "accessing 9 bytes at offsets \\\[0, 8] and 0 overlaps 9 bytes at offset 0" } */
30 
31   /* Same as above but with constant destination index and variable
32      source index.  */
33   T (&a8_1[0], &a8_1[i], 1);
34   T (&a8_1[0], &a8_1[i], 2);
35   T (&a8_1[0], &a8_1[i], 3);
36   T (&a8_1[0], &a8_1[i], 4);
37 
38   T (&a8_1[0], &a8_1[i], 5);    /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3\\\]" } */
39   T (&a8_1[0], &a8_1[i], 6);    /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[0, 8] overlaps between 4 and 6 bytes at offset \\\[0, 2\\\]" } */
40   T (&a8_1[0], &a8_1[i], 7);    /* { dg-warning "accessing 7 bytes at offsets 0 and \\\[0, 8] overlaps between 6 and 7 bytes at offset \\\[0, 1\\\]" } */
41   T (&a8_1[0], &a8_1[i], 8);    /* { dg-warning "accessing 8 bytes at offsets 0 and \\\[0, 8] overlaps 8 bytes at offset 0" } */
42   T (&a8_1[0], &a8_1[i], 9);    /* { dg-warning "accessing 9 bytes at offsets 0 and \\\[0, 8] overlaps 9 bytes at offset 0" } */
43 
44 
45   /* Variable destination and source indices.  */
46   T (&a8_1[i], &a8_1[j], 1);
47   T (&a8_1[i], &a8_1[j], 2);
48   T (&a8_1[i], &a8_1[j], 3);
49   T (&a8_1[i], &a8_1[j], 4);
50 
51   T (&a8_1[i], &a8_1[j], 5);    /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3\\\]" } */
52   T (&a8_1[i], &a8_1[j], 6);    /* { dg-warning "accessing 6 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 4 and 6 bytes at offset \\\[0, 2\\\]" } */
53   T (&a8_1[i], &a8_1[j], 7);    /* { dg-warning "accessing 7 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 6 and 7 bytes at offset \\\[0, 1\\\]" } */
54   T (&a8_1[i], &a8_1[j], 8);    /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 8 bytes at offset 0" } */
55 
56   /* The following is diagnosed by -Warray-bounds when it's enabled
57      rather than by -Wrestrict.  */
58   T (&a8_1[i], &a8_1[j], 9);    /* { dg-warning "accessing 9 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 9 bytes at offset 0" } */
59 }
60 
61 struct S4 { char a4[4]; } a2_4[2];
62 
test_2_dim(int i,int j)63 void test_2_dim (int i, int j)
64 {
65   T (&a2_4[i], &a2_4[0], 1);
66   T (&a2_4[i], &a2_4[0], 4);
67 
68   T (&a2_4[i], &a2_4[0], 5);    /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and 0 overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
69   T (&a2_4[i], &a2_4[0], 6);    /* { dg-warning "accessing 6 bytes at offsets \\\[0, 8] and 0 overlaps between 4 and 6 bytes at offset \\\[0, 2]" } */
70   T (&a2_4[i], &a2_4[0], 7);    /* { dg-warning "accessing 7 bytes at offsets \\\[0, 8] and 0 overlaps between 6 and 7 bytes at offset \\\[0, 1]" } */
71   T (&a2_4[i], &a2_4[0], 8);    /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and 0 overlaps 8 bytes at offset 0" } */
72 
73   T (a2_4[i].a4, a2_4[0].a4, 1);
74   T (a2_4[i].a4, a2_4[0].a4, 4);
75 
76   T (a2_4[i].a4, a2_4[0].a4, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and 0 overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
77   T (a2_4[i].a4, a2_4[0].a4, 8);   /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and 0 overlaps 8 bytes at offset 0" } */
78 
79   T (a2_4[i].a4, a2_4[j].a4, 1);
80   T (a2_4[i].a4, a2_4[j].a4, 4);
81 
82   /* The destination and source offsets printed below ignore the size
83      of the copy and only indicate the values that are valid for each
84      of the destination and source arguments on its own, without
85      considering the size of the overlapping access.  */
86   T (a2_4[i].a4, a2_4[j].a4, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
87   T (a2_4[i].a4, a2_4[j].a4, 8);   /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 8 bytes at offset 0" } */
88 
89   /* Same as above but referencing the first elements of each array.  */
90   T (&a2_4[i].a4[0], &a2_4[j].a4[0], 1);
91   T (&a2_4[i].a4[0], &a2_4[j].a4[0], 4);
92 
93   T (&a2_4[i].a4[0], &a2_4[j].a4[0], 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
94   T (&a2_4[i].a4[0], &a2_4[j].a4[0], 8);   /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 8 bytes at offset 0" } */
95 
96   T (&a2_4[i].a4[0], &a2_4[j].a4[1], 3);
97   T (&a2_4[i].a4[0], &a2_4[j].a4[2], 2);
98   T (&a2_4[i].a4[0], &a2_4[j].a4[3], 1);
99 }
100 
101 struct { int i; } a2[2][8];
102 
test_single_2_dim_major(int i)103 void test_single_2_dim_major (int i)
104 {
105   memcpy (&a2[i], &a2[0], sizeof *a2);   /* { dg-bogus "\\\[-Wrestrict]" } */
106 }
107 
test_single_2_dim_minor(int i)108 void test_single_2_dim_minor (int i)
109 {
110   memcpy (&a2[i][0], &a2[0][0], sizeof a2[0][0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
111 }
112 
test_single_2_dim_major_minor(int i,int j)113 void test_single_2_dim_major_minor (int i, int j)
114 {
115   memcpy (&a2[i][j], &a2[0][0], sizeof a2[0][0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
116 }
117