[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / array-init-loop.cpp
blob4ab4489fc882f3fa85ab25a96135d97bfc70fe9e
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
3 void clang_analyzer_eval(bool);
5 void array_init() {
6 int arr[] = {1, 2, 3, 4, 5};
8 auto [a, b, c, d, e] = arr;
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}}
17 void array_uninit() {
18 int arr[5];
20 auto [a, b, c, d, e] = arr;
22 int x = e; // expected-warning{{Assigned value is garbage or undefined}}
25 void lambda_init() {
26 int arr[] = {1, 2, 3, 4, 5};
28 auto l = [arr] { return arr[0]; }();
29 clang_analyzer_eval(l == 1); // expected-warning{{TRUE}}
31 l = [arr] { return arr[1]; }();
32 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}
34 l = [arr] { return arr[2]; }();
35 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}
37 l = [arr] { return arr[3]; }();
38 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}
40 l = [arr] { return arr[4]; }();
41 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}
44 void lambda_uninit() {
45 int arr[5];
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}}
51 l = [arr] { return arr[1]; }();
52 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
54 l = [arr] { return arr[2]; }();
55 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
57 l = [arr] { return arr[3]; }();
58 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
60 l = [arr] { return arr[4]; }();
61 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
64 struct S {
65 int arr[5];
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;
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}}
84 void copy_ctor_uninit() {
85 S orig;
87 S copy = orig;
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}}
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;
107 S moved = (S &&) orig;
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}}
116 void move_ctor_uninit() {
117 S orig;
119 S moved = (S &&) orig;
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}}
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;
136 S2() : i(++c) {}
138 S2(const S2 &copy) {
139 i = copy.i + 1;
142 S2(S2 &&move) {
143 i = move.i + 2;
147 void array_init_non_pod() {
148 S2::c = 0;
149 S2 arr[4];
151 auto [a, b, c, d] = arr;
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}}
159 struct S3 {
160 int i;
163 // The duplicate is required to emit a warning at 2 different places.
164 struct S3_duplicate {
165 int i;
168 void array_uninit_non_pod() {
169 S3 arr[1];
171 auto [a] = arr; // expected-warning@159{{ in implicit constructor is garbage or undefined }}
174 void lambda_init_non_pod() {
175 S2::c = 0;
176 S2 arr[4];
178 auto l = [arr] { return arr[0].i; }();
179 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}
181 l = [arr] { return arr[1].i; }();
182 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}
184 l = [arr] { return arr[2].i; }();
185 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}
187 l = [arr] { return arr[3].i; }();
188 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}
191 void lambda_uninit_non_pod() {
192 S3_duplicate arr[4];
194 int l = [arr] { return arr[3].i; }(); // expected-warning@164{{ in implicit constructor is garbage or undefined }}
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];
204 void copy_ctor_init_non_pod() {
205 S2::c = 0;
206 S5 orig;
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}}
215 void move_ctor_init_non_pod() {
216 S2::c = 0;
217 S5 orig;
219 S5 moved = (S5 &&) orig;
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}}
227 //Note: This is the only solution I could find to check the values without
228 // crashing clang. For more details on the crash see Issue #57135.
229 void lambda_capture_multi_array() {
230 S3 arr[2][2] = {1,2,3,4};
233 int x = [arr] { return arr[0][0].i; }();
234 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
238 int x = [arr] { return arr[0][1].i; }();
239 clang_analyzer_eval(x == 2); // expected-warning{{TRUE}}
243 int x = [arr] { return arr[1][0].i; }();
244 clang_analyzer_eval(x == 3); // expected-warning{{TRUE}}
248 int x = [arr] { return arr[1][1].i; }();
249 clang_analyzer_eval(x == 4); // expected-warning{{TRUE}}
253 // This struct will force constructor inlining in MultiWrapper.
254 struct UserDefinedCtor {
255 int i;
256 UserDefinedCtor() {}
257 UserDefinedCtor(const UserDefinedCtor &copy) {
258 int j = 1;
259 i = copy.i;
263 struct MultiWrapper {
264 UserDefinedCtor arr[2][2];
267 void copy_ctor_multi() {
268 MultiWrapper MW;
270 MW.arr[0][0].i = 0;
271 MW.arr[0][1].i = 1;
272 MW.arr[1][0].i = 2;
273 MW.arr[1][1].i = 3;
275 MultiWrapper MWCopy = MW;
277 clang_analyzer_eval(MWCopy.arr[0][0].i == 0); // expected-warning{{TRUE}}
278 clang_analyzer_eval(MWCopy.arr[0][1].i == 1); // expected-warning{{TRUE}}
279 clang_analyzer_eval(MWCopy.arr[1][0].i == 2); // expected-warning{{TRUE}}
280 clang_analyzer_eval(MWCopy.arr[1][1].i == 3); // expected-warning{{TRUE}}
283 void move_ctor_multi() {
284 MultiWrapper MW;
286 MW.arr[0][0].i = 0;
287 MW.arr[0][1].i = 1;
288 MW.arr[1][0].i = 2;
289 MW.arr[1][1].i = 3;
291 MultiWrapper MWMove = (MultiWrapper &&) MW;
293 clang_analyzer_eval(MWMove.arr[0][0].i == 0); // expected-warning{{TRUE}}
294 clang_analyzer_eval(MWMove.arr[0][1].i == 1); // expected-warning{{TRUE}}
295 clang_analyzer_eval(MWMove.arr[1][0].i == 2); // expected-warning{{TRUE}}
296 clang_analyzer_eval(MWMove.arr[1][1].i == 3); // expected-warning{{TRUE}}
299 void structured_binding_multi() {
300 S3 arr[2][2] = {1,2,3,4};
302 auto [a,b] = arr;
304 clang_analyzer_eval(a[0].i == 1); // expected-warning{{TRUE}}
305 clang_analyzer_eval(a[1].i == 2); // expected-warning{{TRUE}}
306 clang_analyzer_eval(b[0].i == 3); // expected-warning{{TRUE}}
307 clang_analyzer_eval(b[1].i == 4); // expected-warning{{TRUE}}
310 // This snippet used to crash
311 namespace crash {
313 struct S
315 int x;
316 S() { x = 1; }
319 void no_crash() {
320 S arr[0];
321 int n = 1;
323 auto l = [arr, n] { return n; };
325 int x = l();
326 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
328 // FIXME: This should be 'Undefined'.
329 clang_analyzer_eval(arr[0].x); // expected-warning{{UNKNOWN}}
332 } // namespace crash