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