1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-disable-checker=cplusplus -analyzer-config c++-inlining=constructors -verify %s
2 
3 #include "Inputs/system-header-simulator-cxx.h"
4 
5 void clang_analyzer_eval(bool);
6 
7 struct s {
8   int x;
9   int y;
10 };
11 
12 void a1(void) {
13   s arr[3];
14   int x = arr[0].x;
15   // expected-warning@-1{{Assigned value is garbage or undefined}}
16 }
17 
18 void a2(void) {
19   s arr[3];
20   int x = arr[1].x;
21   // expected-warning@-1{{Assigned value is garbage or undefined}}
22 }
23 
24 void a3(void) {
25   s arr[3];
26   int x = arr[2].x;
27   // expected-warning@-1{{Assigned value is garbage or undefined}}
28 }
29 
30 struct s2 {
31   int x;
32   int y = 2;
33 };
34 
35 void b1(void) {
36   s2 arr[3];
37 
38   clang_analyzer_eval(arr[0].y == 2); // expected-warning{{TRUE}}
39   int x = arr[0].x;
40   // expected-warning@-1{{Assigned value is garbage or undefined}}
41 }
42 
43 void b2(void) {
44   s2 arr[3];
45 
46   clang_analyzer_eval(arr[1].y == 2); // expected-warning{{TRUE}}
47   int x = arr[1].x;
48   // expected-warning@-1{{Assigned value is garbage or undefined}}
49 }
50 
51 void b3(void) {
52   s2 arr[3];
53 
54   clang_analyzer_eval(arr[2].y == 2); // expected-warning{{TRUE}}
55   int x = arr[2].x;
56   // expected-warning@-1{{Assigned value is garbage or undefined}}
57 }
58 
59 void c1(void) {
60   {
61     s2 arr[2];
62     arr[1].x = 3;
63 
64     clang_analyzer_eval(arr[1].y == 2); // expected-warning{{TRUE}}
65     clang_analyzer_eval(arr[1].x == 3); // expected-warning{{TRUE}}
66   }
67 
68   {
69     s2 arr[2];
70 
71     clang_analyzer_eval(arr[1].y == 2); // expected-warning{{TRUE}}
72     int x = arr[1].x;
73     // expected-warning@-1{{Assigned value is garbage or undefined}}
74   }
75 }
76 
77 struct s3 {
78   int x = 1;
79   int y = 2;
80 };
81 
82 struct s4 {
83   s3 arr[2];
84   s sarr[2];
85 };
86 
87 void e1(void) {
88   s4 arr[2];
89 
90   clang_analyzer_eval(arr[0].arr[0].x == 1); // expected-warning{{TRUE}}
91   clang_analyzer_eval(arr[0].arr[0].y == 2); // expected-warning{{TRUE}}
92 
93   clang_analyzer_eval(arr[0].arr[1].x == 1); // expected-warning{{TRUE}}
94   clang_analyzer_eval(arr[0].arr[1].y == 2); // expected-warning{{TRUE}}
95 
96   clang_analyzer_eval(arr[1].arr[0].x == 1); // expected-warning{{TRUE}}
97   clang_analyzer_eval(arr[1].arr[0].y == 2); // expected-warning{{TRUE}}
98 
99   clang_analyzer_eval(arr[1].arr[1].x == 1); // expected-warning{{TRUE}}
100   clang_analyzer_eval(arr[1].arr[1].y == 2); // expected-warning{{TRUE}}
101 
102   int x = arr[1].sarr[1].x;
103   // expected-warning@-1{{Assigned value is garbage or undefined}}
104 }
105 
106 void f1(void) {
107   s2 arr[2][2];
108 
109   clang_analyzer_eval(arr[1][1].y == 2); // expected-warning{{TRUE}}
110   int x = arr[1][1].x;
111   // expected-warning@-1{{Assigned value is garbage or undefined}}
112 }
113 
114 struct s5 {
115   static int c;
116   int x;
117 
118   s5() : x(c++) {}
119 };
120 
121 void g1(void) {
122   // FIXME: This test requires -analyzer-disable-checker=cplusplus,
123   // because of the checker's weird behaviour in case of arrays.
124   // E.g.:
125   //        s3 *arr = new s3[4];
126   //        s3 *arr2 = new (arr + 1) s3[1];
127   //                   ^~~~~~~~~~~~~~~~~~~
128   //                   warning: 12 bytes is possibly not enough
129   //                            for array allocation which requires
130   //                            4 bytes.
131 
132   s5::c = 0;
133   s5 *arr = new s5[4];
134   new (arr + 1) s5[3];
135 
136   clang_analyzer_eval(arr[0].x == 0); // expected-warning{{TRUE}}
137   clang_analyzer_eval(arr[1].x == 4); // expected-warning{{TRUE}}
138   clang_analyzer_eval(arr[2].x == 5); // expected-warning{{TRUE}}
139   clang_analyzer_eval(arr[3].x == 6); // expected-warning{{TRUE}}
140 }
141 
142 void g2(void) {
143   s5::c = 0;
144   s5 arr[4];
145 
146   clang_analyzer_eval(arr[0].x == 0); // expected-warning{{TRUE}}
147   clang_analyzer_eval(arr[1].x == 1); // expected-warning{{TRUE}}
148   clang_analyzer_eval(arr[2].x == 2); // expected-warning{{TRUE}}
149   clang_analyzer_eval(arr[3].x == 3); // expected-warning{{TRUE}}
150 }
151 
152 void g3(void) {
153   s5::c = 0;
154   s5 arr[2][2];
155 
156   clang_analyzer_eval(arr[0][0].x == 0); // expected-warning{{TRUE}}
157   clang_analyzer_eval(arr[0][1].x == 1); // expected-warning{{TRUE}}
158   clang_analyzer_eval(arr[1][0].x == 2); // expected-warning{{TRUE}}
159   clang_analyzer_eval(arr[1][1].x == 3); // expected-warning{{TRUE}}
160 }
161 
162 void h1(void) {
163   s5::c = 0;
164   s5 a[2][2], b[2][2];
165 
166   clang_analyzer_eval(a[0][0].x == 0); // expected-warning{{TRUE}}
167   clang_analyzer_eval(a[0][1].x == 1); // expected-warning{{TRUE}}
168   clang_analyzer_eval(a[1][0].x == 2); // expected-warning{{TRUE}}
169   clang_analyzer_eval(a[1][1].x == 3); // expected-warning{{TRUE}}
170 
171   clang_analyzer_eval(b[0][0].x == 4); // expected-warning{{TRUE}}
172   clang_analyzer_eval(b[0][1].x == 5); // expected-warning{{TRUE}}
173   clang_analyzer_eval(b[1][0].x == 6); // expected-warning{{TRUE}}
174   clang_analyzer_eval(b[1][1].x == 7); // expected-warning{{TRUE}}
175 }
176 
177 void h2(void) {
178   s a[2][2], b[2][2];
179 
180   int x = a[1][1].x;
181   // expected-warning@-1{{Assigned value is garbage or undefined}}
182 }
183 
184 void h3(void) {
185   s a[2][2], b[2][2];
186 
187   int x = b[1][1].y;
188   // expected-warning@-1{{Assigned value is garbage or undefined}}
189 }
190 
191 struct Base {
192   int x;
193   int y;
194 
195   Base(int x, int y) : x(x), y(y) {}
196 };
197 
198 struct Derived : public Base {
199   int i;
200   int j;
201 
202   Derived(int x, int y, int i, int j) : Base(x, y), i(i), j(j) {}
203 };
204 
205 void delegate(void) {
206   Derived arr[2] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
207 
208   clang_analyzer_eval(arr[0].x == 1); // expected-warning{{TRUE}}
209   clang_analyzer_eval(arr[0].y == 2); // expected-warning{{TRUE}}
210   clang_analyzer_eval(arr[0].i == 3); // expected-warning{{TRUE}}
211   clang_analyzer_eval(arr[0].j == 4); // expected-warning{{TRUE}}
212 
213   clang_analyzer_eval(arr[1].x == 5); // expected-warning{{TRUE}}
214   clang_analyzer_eval(arr[1].y == 6); // expected-warning{{TRUE}}
215   clang_analyzer_eval(arr[1].i == 7); // expected-warning{{TRUE}}
216   clang_analyzer_eval(arr[1].j == 8); // expected-warning{{TRUE}}
217 }
218 
219 void delegate_heap(void) {
220   Derived *arr = new Derived[2]{{1, 2, 3, 4}, {5, 6, 7, 8}};
221 
222   clang_analyzer_eval(arr[0].x == 1); // expected-warning{{TRUE}}
223   clang_analyzer_eval(arr[0].y == 2); // expected-warning{{TRUE}}
224   clang_analyzer_eval(arr[0].i == 3); // expected-warning{{TRUE}}
225   clang_analyzer_eval(arr[0].j == 4); // expected-warning{{TRUE}}
226 
227   clang_analyzer_eval(arr[1].x == 5); // expected-warning{{TRUE}}
228   clang_analyzer_eval(arr[1].y == 6); // expected-warning{{TRUE}}
229   clang_analyzer_eval(arr[1].i == 7); // expected-warning{{TRUE}}
230   clang_analyzer_eval(arr[1].j == 8); // expected-warning{{TRUE}}
231 }
232 
233 struct Member {
234   int x;
235   int y;
236 };
237 
238 struct Parent {
239   Member arr[2];
240 
241   Parent() : arr{{1, 2}, {3, 4}} {}
242 };
243 
244 void member() {
245   Parent arr[2];
246 
247   // FIXME: Ideally these are TRUE, but at the moment InitListExpr has no
248   // knowledge about where the initializer list is used, so we can't bind
249   // the initializer list to the required region.
250   clang_analyzer_eval(arr[0].arr[0].x == 1); // expected-warning{{UNKNOWN}}
251   clang_analyzer_eval(arr[0].arr[0].y == 2); // expected-warning{{UNKNOWN}}
252   clang_analyzer_eval(arr[0].arr[1].x == 3); // expected-warning{{UNKNOWN}}
253   clang_analyzer_eval(arr[0].arr[1].y == 4); // expected-warning{{UNKNOWN}}
254 
255   clang_analyzer_eval(arr[1].arr[0].x == 1); // expected-warning{{UNKNOWN}}
256   clang_analyzer_eval(arr[1].arr[0].y == 2); // expected-warning{{UNKNOWN}}
257   clang_analyzer_eval(arr[1].arr[1].x == 3); // expected-warning{{UNKNOWN}}
258   clang_analyzer_eval(arr[1].arr[1].y == 4); // expected-warning{{UNKNOWN}}
259 }
260