1 /* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
2    Exercise warnings for writing into one of two or more declared objects.
3    { dg-do compile }
4    { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
5 
6 #include "range.h"
7 
8 #define INT_MAX __INT_MAX__
9 
10 extern void* memset (void*, int, size_t);
11 #define memset(d, c, n) sink (memset (d, c, n))
12 
13 void sink (int, ...);
14 #define sink(...) sink (0, __VA_ARGS__)
15 
16 volatile int cond1, cond2;
17 
18 extern char ca0[0], ca1[1], ca2[2], ca3[3], ca4[4],
19             ca5[5], ca6[6], ca7[7], ca8[8], ca9[9], cax[];
20 
21 #define CHOOSE_DECL_2(n1, n2)			\
22   (cond1 ? ca ## n1 : ca ## n2)
23 #define CHOOSE_DECL_3(n1, n2, n3)			\
24   (cond1 < 0 ? ca ## n1 : 0 < cond1 ? ca ## n2 : ca ## n3)
25 
26 
memset_decl_2(void)27 void memset_decl_2 (void)
28 {
29   {
30     char *p0_1 = CHOOSE_DECL_2 (0, 1);
31 
32     memset (p0_1, 0, 0);
33     /* Writing more than the smallest destination should trigger a "may
34        write" warning if the access is unconditionally reachable from
35        the block where the pointer to either object is assigned.  */
36     memset (p0_1, 0, 1);
37     memset (p0_1, 0, 2);      // { dg-warning "memset' writing 2 bytes into a region of size 1 " }
38     memset (p0_1, 0, 9);      // { dg-warning "memset' writing 9 bytes into a region of size 1 " }
39   }
40 
41   {
42     char *p0_x = CHOOSE_DECL_2 (0, x);
43 
44     memset (p0_x, 0, 0);
45     memset (p0_x, 0, 1);
46     memset (p0_x, 0, 2);
47     memset (p0_x, 0, 9);
48   }
49 
50   {
51     char *p3_5 = CHOOSE_DECL_2 (3, 5);
52 
53     memset (p3_5, 0, 1);
54     memset (p3_5, 0, 3);
55     memset (p3_5, 0, 4);
56     memset (p3_5, 0, 5);
57     memset (p3_5, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
58   }
59 
60   {
61     char *p5_3 = CHOOSE_DECL_2 (5, 3);
62 
63     memset (p5_3, 0, 3);
64     memset (p5_3, 0, 4);
65     memset (p5_3, 0, 5);
66     memset (p5_3, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
67   }
68 
69   {
70     char *px_3 = CHOOSE_DECL_2 (x, 3);
71 
72     memset (px_3, 0, 1);
73     memset (px_3, 0, 3);
74     memset (px_3, 0, 4);
75     memset (px_3, 0, 1234);
76   }
77 
78   {
79     char *p5_x = CHOOSE_DECL_2 (5, x);
80 
81     memset (p5_x, 0, 1);
82     memset (p5_x, 0, 5);
83     memset (p5_x, 0, 6);
84     memset (p5_x, 0, 1234);
85   }
86 
87 }
88 
89 
memset_decl_3(void)90 void memset_decl_3 (void)
91 {
92   {
93     char *p0_1_2 = CHOOSE_DECL_3 (0, 1, 2);
94     memset (p0_1_2, 0, 0);
95     memset (p0_1_2, 0, 1);
96     memset (p0_1_2, 0, 2);
97     memset (p0_1_2, 0, 3);    // { dg-warning "memset' writing 3 bytes into a region of size 2 " }
98     memset (p0_1_2, 0, 9);    // { dg-warning "memset' writing 9 bytes into a region of size 2 " }
99   }
100 
101   {
102     char *p0_2_x = CHOOSE_DECL_3 (0, 2, x);
103 
104     memset (p0_2_x, 0, 0);
105     memset (p0_2_x, 0, 1);
106     memset (p0_2_x, 0, 3);
107     memset (p0_2_x, 0, 9);
108   }
109 
110   {
111     char *p3_4_5 = CHOOSE_DECL_3 (3, 4, 5);
112 
113     memset (p3_4_5, 0, 3);
114     memset (p3_4_5, 0, 4);
115     memset (p3_4_5, 0, 5);
116     memset (p3_4_5, 0, 6);    // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
117   }
118 
119   {
120     char *p5_3_4 = CHOOSE_DECL_3 (5, 3, 4);
121 
122     memset (p5_3_4, 0, 3);
123     memset (p5_3_4, 0, 4);
124     memset (p5_3_4, 0, 5);
125     memset (p5_3_4, 0, 6);    // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
126   }
127 
128   {
129     char *p9_8_7 = CHOOSE_DECL_3 (9, 8, 7);
130 
131     memset (p9_8_7, 0, 7);
132     memset (p9_8_7, 0, 8);
133     memset (p9_8_7, 0, 9);
134     memset (p9_8_7, 0, 10);   // { dg-warning "memset' writing 10 bytes into a region of size 9 " }
135   }
136 }
137 
138 
139 /* Verify conditionally writing into one of two objects with the same
140    size.  */
141 
memset_decl_2_same_size(int i)142 void memset_decl_2_same_size (int i)
143 {
144   {
145     char a4_1[4], a4_2[4];
146     char *p4 = cond1 ? a4_1 : a4_2;
147 
148     memset (p4, 0, 1);
149     memset (p4, 0, 2);
150     memset (p4, 0, 3);
151     memset (p4, 0, 4);
152     memset (p4, 0, 5);        // { dg-warning "memset' writing 5 bytes into a region of size 4" }
153   }
154 
155   {
156     char a4_1[4];             // { dg-message "destination object 'a4_1" "note" }
157     char a4_2[4];             // { dg-message "destination object 'a4_2" "note" }
158     char *p4 = cond1 ? a4_1 : a4_2;
159     char *p4_i = p4 + i;
160 
161     memset (p4_i, 0, 5);      // { dg-warning "memset' writing 5 bytes into a region of size 4" }
162   }
163 
164   {
165     if (i < 1)
166       i = 1;
167 
168     char a4_1[4];             // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" }
169     char a4_2[4];             // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" }
170     char *p4 = cond1 ? a4_1 : a4_2;
171     char *p4_i = p4 + i;
172 
173     memset (p4_i, 0, 3);
174     memset (p4_i, 0, 4);      // { dg-warning "memset' writing 4 bytes into a region of size 3 " }
175   }
176 }
177 
178 
memset_decl_2_off(void)179 void memset_decl_2_off (void)
180 {
181   int i1 = SR (1, INT_MAX);
182   int i2 = SR (2, INT_MAX);
183 
184   {
185     char a5[5];               // { dg-warning "at offset [1, 5] into destination object 'a5'
186     char a7[7];               // { dg-warning "at offset [2, 7] into destination object 'a7'
187     char *p5_p1 = a5 + i1;
188     char *p7_p2 = a7 + i2;
189     char *p5_7 = cond1 ? p5_p1 : p7_p2;
190 
191     memset (p5_7, 0, 1);
192     memset (p5_7, 0, 2);
193     memset (p5_7, 0, 3);
194     memset (p5_7, 0, 4);
195     memset (p5_7, 0, 5);
196     memset (p5_7, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
197   }
198 
199   int i3 = SR (3, INT_MAX);
200 
201   {
202     char a5[5];
203     // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
204     // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
205     // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
206     // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
207     char a9[9];
208     // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
209     // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
210     // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
211     // { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 }
212     char *p5_p2 = a5 + i2;    // 3 bytes left
213     char *p9_p3 = a9 + i3;    // 6 bytes left
214     char *p =
215       cond1 ? p5_p2 : p9_p3;  // [3 - 6] bytes left
216     char *q = p + i1;         // [2 - 5] bytes left
217 
218     memset (q, 0, 1);
219     memset (q, 0, 2);
220     memset (q, 0, 3);
221     memset (q, 0, 4);
222     memset (q, 0, 5);
223     memset (q, 0, 6);         // { dg-warning "memset' writing 6 bytes into a region of size 5" }
224 
225     --q;                      // [3 - 6] bytes left
226     memset (q, 0, 1);
227     memset (q, 0, 2);
228     memset (q, 0, 3);
229     memset (q, 0, 4);
230     memset (q, 0, 5);
231     memset (q, 0, 6);
232     memset (q, 0, 7);         // { dg-warning "memset' writing 7 bytes into a region of size 6" }
233 
234     --q;                      // [4 - 7] bytes left
235     memset (q, 0, 1);
236     memset (q, 0, 2);
237     memset (q, 0, 3);
238     memset (q, 0, 4);
239     memset (q, 0, 5);
240     memset (q, 0, 6);
241     memset (q, 0, 7);
242     memset (q, 0, 8);         // { dg-warning "memset' writing 8 bytes into a region of size 7" }
243 
244     int m1_x = SR (-1, INT_MAX);
245     int m2_x = SR (-2, INT_MAX);
246 
247     q += cond2 ? m1_x : m2_x;   // [5 - 9] bytes left
248 
249     memset (q, 0, 1);
250     memset (q, 0, 2);
251     memset (q, 0, 3);
252     memset (q, 0, 4);
253     memset (q, 0, 5);
254     memset (q, 0, 6);
255     memset (q, 0, 7);
256     memset (q, 0, 8);
257     memset (q, 0, 9);
258     memset (q, 0, 10);        // { dg-warning "memset' writing 10 bytes into a region of size 9" }
259   }
260 }
261