1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
2
3 void clang_analyzer_eval(bool);
4
array_init()5 void array_init() {
6 int arr[] = {1, 2, 3, 4, 5};
7
8 auto [a, b, c, d, e] = arr;
9
10 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
11 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
12 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
13 clang_analyzer_eval(d == 4); // expected-warning{{TRUE}}
14 clang_analyzer_eval(e == 5); // expected-warning{{TRUE}}
15 }
16
array_uninit()17 void array_uninit() {
18 int arr[5];
19
20 auto [a, b, c, d, e] = arr;
21
22 int x = e; // expected-warning{{Assigned value is garbage or undefined}}
23 }
24
lambda_init()25 void lambda_init() {
26 int arr[] = {1, 2, 3, 4, 5};
27
28 auto l = [arr] { return arr[0]; }();
29 clang_analyzer_eval(l == 1); // expected-warning{{TRUE}}
30
31 l = [arr] { return arr[1]; }();
32 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}
33
34 l = [arr] { return arr[2]; }();
35 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}
36
37 l = [arr] { return arr[3]; }();
38 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}
39
40 l = [arr] { return arr[4]; }();
41 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}
42 }
43
lambda_uninit()44 void lambda_uninit() {
45 int arr[5];
46
47 // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal
48 int l = [arr] { return arr[0]; }();
49 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
50
51 l = [arr] { return arr[1]; }();
52 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
53
54 l = [arr] { return arr[2]; }();
55 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
56
57 l = [arr] { return arr[3]; }();
58 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
59
60 l = [arr] { return arr[4]; }();
61 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
62 }
63
64 struct S {
65 int arr[5];
66 };
67
copy_ctor_init()68 void copy_ctor_init() {
69 S orig;
70 orig.arr[0] = 1;
71 orig.arr[1] = 2;
72 orig.arr[2] = 3;
73 orig.arr[3] = 4;
74 orig.arr[4] = 5;
75
76 S copy = orig;
77 clang_analyzer_eval(copy.arr[0] == 1); // expected-warning{{TRUE}}
78 clang_analyzer_eval(copy.arr[1] == 2); // expected-warning{{TRUE}}
79 clang_analyzer_eval(copy.arr[2] == 3); // expected-warning{{TRUE}}
80 clang_analyzer_eval(copy.arr[3] == 4); // expected-warning{{TRUE}}
81 clang_analyzer_eval(copy.arr[4] == 5); // expected-warning{{TRUE}}
82 }
83
copy_ctor_uninit()84 void copy_ctor_uninit() {
85 S orig;
86
87 S copy = orig;
88
89 // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal.
90 // If the struct is not considered a small struct, instead of a copy, we store a lazy compound value.
91 // As the struct has an array data member, it is not considered small.
92 clang_analyzer_eval(copy.arr[0]); // expected-warning{{UNKNOWN}}
93 clang_analyzer_eval(copy.arr[1]); // expected-warning{{UNKNOWN}}
94 clang_analyzer_eval(copy.arr[2]); // expected-warning{{UNKNOWN}}
95 clang_analyzer_eval(copy.arr[3]); // expected-warning{{UNKNOWN}}
96 clang_analyzer_eval(copy.arr[4]); // expected-warning{{UNKNOWN}}
97 }
98
move_ctor_init()99 void move_ctor_init() {
100 S orig;
101 orig.arr[0] = 1;
102 orig.arr[1] = 2;
103 orig.arr[2] = 3;
104 orig.arr[3] = 4;
105 orig.arr[4] = 5;
106
107 S moved = (S &&) orig;
108
109 clang_analyzer_eval(moved.arr[0] == 1); // expected-warning{{TRUE}}
110 clang_analyzer_eval(moved.arr[1] == 2); // expected-warning{{TRUE}}
111 clang_analyzer_eval(moved.arr[2] == 3); // expected-warning{{TRUE}}
112 clang_analyzer_eval(moved.arr[3] == 4); // expected-warning{{TRUE}}
113 clang_analyzer_eval(moved.arr[4] == 5); // expected-warning{{TRUE}}
114 }
115
move_ctor_uninit()116 void move_ctor_uninit() {
117 S orig;
118
119 S moved = (S &&) orig;
120
121 // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal.
122 clang_analyzer_eval(moved.arr[0]); // expected-warning{{UNKNOWN}}
123 clang_analyzer_eval(moved.arr[1]); // expected-warning{{UNKNOWN}}
124 clang_analyzer_eval(moved.arr[2]); // expected-warning{{UNKNOWN}}
125 clang_analyzer_eval(moved.arr[3]); // expected-warning{{UNKNOWN}}
126 clang_analyzer_eval(moved.arr[4]); // expected-warning{{UNKNOWN}}
127 }
128
129 // The struct has a user defined copy and move ctor, which allow us to
130 // track the values more precisely when an array of this struct is being
131 // copy/move initialized by ArrayInitLoopExpr.
132 struct S2 {
133 inline static int c = 0;
134 int i;
135
S2S2136 S2() : i(++c) {}
137
S2S2138 S2(const S2 ©) {
139 i = copy.i + 1;
140 }
141
S2S2142 S2(S2 &&move) {
143 i = move.i + 2;
144 }
145 };
146
array_init_non_pod()147 void array_init_non_pod() {
148 S2::c = 0;
149 S2 arr[4];
150
151 auto [a, b, c, d] = arr;
152
153 clang_analyzer_eval(a.i == 2); // expected-warning{{TRUE}}
154 clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}}
155 clang_analyzer_eval(c.i == 4); // expected-warning{{TRUE}}
156 clang_analyzer_eval(d.i == 5); // expected-warning{{TRUE}}
157 }
158
159 struct S3 {
160 int i;
161 };
162
163 // The duplicate is required to emit a warning at 2 different places.
164 struct S3_duplicate {
165 int i;
166 };
167
array_uninit_non_pod()168 void array_uninit_non_pod() {
169 S3 arr[1];
170
171 auto [a] = arr; // expected-warning@159{{ in implicit constructor is garbage or undefined }}
172 }
173
lambda_init_non_pod()174 void lambda_init_non_pod() {
175 S2::c = 0;
176 S2 arr[4];
177
178 auto l = [arr] { return arr[0].i; }();
179 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}
180
181 l = [arr] { return arr[1].i; }();
182 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}
183
184 l = [arr] { return arr[2].i; }();
185 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}
186
187 l = [arr] { return arr[3].i; }();
188 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}
189 }
190
lambda_uninit_non_pod()191 void lambda_uninit_non_pod() {
192 S3_duplicate arr[4];
193
194 int l = [arr] { return arr[3].i; }(); // expected-warning@164{{ in implicit constructor is garbage or undefined }}
195 }
196
197 // If this struct is being copy/move constructed by the implicit ctors, ArrayInitLoopExpr
198 // is responsible for the initialization of 'arr' by copy/move constructing each of the
199 // elements.
200 struct S5 {
201 S2 arr[4];
202 };
203
copy_ctor_init_non_pod()204 void copy_ctor_init_non_pod() {
205 S2::c = 0;
206 S5 orig;
207
208 S5 copy = orig;
209 clang_analyzer_eval(copy.arr[0].i == 2); // expected-warning{{TRUE}}
210 clang_analyzer_eval(copy.arr[1].i == 3); // expected-warning{{TRUE}}
211 clang_analyzer_eval(copy.arr[2].i == 4); // expected-warning{{TRUE}}
212 clang_analyzer_eval(copy.arr[3].i == 5); // expected-warning{{TRUE}}
213 }
214
move_ctor_init_non_pod()215 void move_ctor_init_non_pod() {
216 S2::c = 0;
217 S5 orig;
218
219 S5 moved = (S5 &&) orig;
220
221 clang_analyzer_eval(moved.arr[0].i == 3); // expected-warning{{TRUE}}
222 clang_analyzer_eval(moved.arr[1].i == 4); // expected-warning{{TRUE}}
223 clang_analyzer_eval(moved.arr[2].i == 5); // expected-warning{{TRUE}}
224 clang_analyzer_eval(moved.arr[3].i == 6); // expected-warning{{TRUE}}
225 }
226