xref: /llvm-project/clang/test/Analysis/array-init-loop.cpp (revision 8a13326d184c2829a51d7c00f467ded06412f858)
18ef62808Sisuckatcs // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
28ef62808Sisuckatcs 
38ef62808Sisuckatcs void clang_analyzer_eval(bool);
48ef62808Sisuckatcs 
58ef62808Sisuckatcs void array_init() {
68ef62808Sisuckatcs   int arr[] = {1, 2, 3, 4, 5};
78ef62808Sisuckatcs 
88ef62808Sisuckatcs   auto [a, b, c, d, e] = arr;
98ef62808Sisuckatcs 
108ef62808Sisuckatcs   clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
118ef62808Sisuckatcs   clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
128ef62808Sisuckatcs   clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
138ef62808Sisuckatcs   clang_analyzer_eval(d == 4); // expected-warning{{TRUE}}
148ef62808Sisuckatcs   clang_analyzer_eval(e == 5); // expected-warning{{TRUE}}
158ef62808Sisuckatcs }
168ef62808Sisuckatcs 
178ef62808Sisuckatcs void array_uninit() {
188ef62808Sisuckatcs   int arr[5];
198ef62808Sisuckatcs 
208ef62808Sisuckatcs   auto [a, b, c, d, e] = arr;
218ef62808Sisuckatcs 
228ef62808Sisuckatcs   int x = e; // expected-warning{{Assigned value is garbage or undefined}}
238ef62808Sisuckatcs }
248ef62808Sisuckatcs 
258ef62808Sisuckatcs void lambda_init() {
268ef62808Sisuckatcs   int arr[] = {1, 2, 3, 4, 5};
278ef62808Sisuckatcs 
288ef62808Sisuckatcs   auto l = [arr] { return arr[0]; }();
298ef62808Sisuckatcs   clang_analyzer_eval(l == 1); // expected-warning{{TRUE}}
308ef62808Sisuckatcs 
318ef62808Sisuckatcs   l = [arr] { return arr[1]; }();
328ef62808Sisuckatcs   clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}
338ef62808Sisuckatcs 
348ef62808Sisuckatcs   l = [arr] { return arr[2]; }();
358ef62808Sisuckatcs   clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}
368ef62808Sisuckatcs 
378ef62808Sisuckatcs   l = [arr] { return arr[3]; }();
388ef62808Sisuckatcs   clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}
398ef62808Sisuckatcs 
408ef62808Sisuckatcs   l = [arr] { return arr[4]; }();
418ef62808Sisuckatcs   clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}
428ef62808Sisuckatcs }
438ef62808Sisuckatcs 
448ef62808Sisuckatcs void lambda_uninit() {
458ef62808Sisuckatcs   int arr[5];
468ef62808Sisuckatcs 
478ef62808Sisuckatcs   // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal
488ef62808Sisuckatcs   int l = [arr] { return arr[0]; }();
498ef62808Sisuckatcs   clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
508ef62808Sisuckatcs 
518ef62808Sisuckatcs   l = [arr] { return arr[1]; }();
528ef62808Sisuckatcs   clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
538ef62808Sisuckatcs 
548ef62808Sisuckatcs   l = [arr] { return arr[2]; }();
558ef62808Sisuckatcs   clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
568ef62808Sisuckatcs 
578ef62808Sisuckatcs   l = [arr] { return arr[3]; }();
588ef62808Sisuckatcs   clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
598ef62808Sisuckatcs 
608ef62808Sisuckatcs   l = [arr] { return arr[4]; }();
618ef62808Sisuckatcs   clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
628ef62808Sisuckatcs }
638ef62808Sisuckatcs 
648ef62808Sisuckatcs struct S {
658ef62808Sisuckatcs   int arr[5];
668ef62808Sisuckatcs };
678ef62808Sisuckatcs 
688ef62808Sisuckatcs void copy_ctor_init() {
698ef62808Sisuckatcs   S orig;
708ef62808Sisuckatcs   orig.arr[0] = 1;
718ef62808Sisuckatcs   orig.arr[1] = 2;
728ef62808Sisuckatcs   orig.arr[2] = 3;
738ef62808Sisuckatcs   orig.arr[3] = 4;
748ef62808Sisuckatcs   orig.arr[4] = 5;
758ef62808Sisuckatcs 
768ef62808Sisuckatcs   S copy = orig;
778ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[0] == 1); // expected-warning{{TRUE}}
788ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[1] == 2); // expected-warning{{TRUE}}
798ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[2] == 3); // expected-warning{{TRUE}}
808ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[3] == 4); // expected-warning{{TRUE}}
818ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[4] == 5); // expected-warning{{TRUE}}
828ef62808Sisuckatcs }
838ef62808Sisuckatcs 
848ef62808Sisuckatcs void copy_ctor_uninit() {
858ef62808Sisuckatcs   S orig;
868ef62808Sisuckatcs 
878ef62808Sisuckatcs   S copy = orig;
888ef62808Sisuckatcs 
898ef62808Sisuckatcs   // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal.
908ef62808Sisuckatcs   // If the struct is not considered a small struct, instead of a copy, we store a lazy compound value.
918ef62808Sisuckatcs   // As the struct has an array data member, it is not considered small.
928ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[0]); // expected-warning{{UNKNOWN}}
938ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[1]); // expected-warning{{UNKNOWN}}
948ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[2]); // expected-warning{{UNKNOWN}}
958ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[3]); // expected-warning{{UNKNOWN}}
968ef62808Sisuckatcs   clang_analyzer_eval(copy.arr[4]); // expected-warning{{UNKNOWN}}
978ef62808Sisuckatcs }
988ef62808Sisuckatcs 
998ef62808Sisuckatcs void move_ctor_init() {
1008ef62808Sisuckatcs   S orig;
1018ef62808Sisuckatcs   orig.arr[0] = 1;
1028ef62808Sisuckatcs   orig.arr[1] = 2;
1038ef62808Sisuckatcs   orig.arr[2] = 3;
1048ef62808Sisuckatcs   orig.arr[3] = 4;
1058ef62808Sisuckatcs   orig.arr[4] = 5;
1068ef62808Sisuckatcs 
1078ef62808Sisuckatcs   S moved = (S &&) orig;
1088ef62808Sisuckatcs 
1098ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[0] == 1); // expected-warning{{TRUE}}
1108ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[1] == 2); // expected-warning{{TRUE}}
1118ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[2] == 3); // expected-warning{{TRUE}}
1128ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[3] == 4); // expected-warning{{TRUE}}
1138ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[4] == 5); // expected-warning{{TRUE}}
1148ef62808Sisuckatcs }
1158ef62808Sisuckatcs 
1168ef62808Sisuckatcs void move_ctor_uninit() {
1178ef62808Sisuckatcs   S orig;
1188ef62808Sisuckatcs 
1198ef62808Sisuckatcs   S moved = (S &&) orig;
1208ef62808Sisuckatcs 
1218ef62808Sisuckatcs   // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal.
1228ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[0]); // expected-warning{{UNKNOWN}}
1238ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[1]); // expected-warning{{UNKNOWN}}
1248ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[2]); // expected-warning{{UNKNOWN}}
1258ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[3]); // expected-warning{{UNKNOWN}}
1268ef62808Sisuckatcs   clang_analyzer_eval(moved.arr[4]); // expected-warning{{UNKNOWN}}
1278ef62808Sisuckatcs }
128*8a13326dSisuckatcs 
129*8a13326dSisuckatcs // The struct has a user defined copy and move ctor, which allow us to
130*8a13326dSisuckatcs // track the values more precisely when an array of this struct is being
131*8a13326dSisuckatcs // copy/move initialized by ArrayInitLoopExpr.
132*8a13326dSisuckatcs struct S2 {
133*8a13326dSisuckatcs   inline static int c = 0;
134*8a13326dSisuckatcs   int i;
135*8a13326dSisuckatcs 
136*8a13326dSisuckatcs   S2() : i(++c) {}
137*8a13326dSisuckatcs 
138*8a13326dSisuckatcs   S2(const S2 &copy) {
139*8a13326dSisuckatcs     i = copy.i + 1;
140*8a13326dSisuckatcs   }
141*8a13326dSisuckatcs 
142*8a13326dSisuckatcs   S2(S2 &&move) {
143*8a13326dSisuckatcs     i = move.i + 2;
144*8a13326dSisuckatcs   }
145*8a13326dSisuckatcs };
146*8a13326dSisuckatcs 
147*8a13326dSisuckatcs void array_init_non_pod() {
148*8a13326dSisuckatcs   S2::c = 0;
149*8a13326dSisuckatcs   S2 arr[4];
150*8a13326dSisuckatcs 
151*8a13326dSisuckatcs   auto [a, b, c, d] = arr;
152*8a13326dSisuckatcs 
153*8a13326dSisuckatcs   clang_analyzer_eval(a.i == 2); // expected-warning{{TRUE}}
154*8a13326dSisuckatcs   clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}}
155*8a13326dSisuckatcs   clang_analyzer_eval(c.i == 4); // expected-warning{{TRUE}}
156*8a13326dSisuckatcs   clang_analyzer_eval(d.i == 5); // expected-warning{{TRUE}}
157*8a13326dSisuckatcs }
158*8a13326dSisuckatcs 
159*8a13326dSisuckatcs struct S3 {
160*8a13326dSisuckatcs   int i;
161*8a13326dSisuckatcs };
162*8a13326dSisuckatcs 
163*8a13326dSisuckatcs void array_uninit_non_pod() {
164*8a13326dSisuckatcs   S3 arr[1];
165*8a13326dSisuckatcs 
166*8a13326dSisuckatcs   auto [a] = arr; // expected-warning@159{{ in implicit constructor is garbage or undefined }}
167*8a13326dSisuckatcs }
168*8a13326dSisuckatcs 
169*8a13326dSisuckatcs void lambda_init_non_pod() {
170*8a13326dSisuckatcs   S2::c = 0;
171*8a13326dSisuckatcs   S2 arr[4];
172*8a13326dSisuckatcs 
173*8a13326dSisuckatcs   // FIXME: These should be TRUE, but we fail to capture the array properly.
174*8a13326dSisuckatcs   auto l = [arr] { return arr[0].i; }();
175*8a13326dSisuckatcs   clang_analyzer_eval(l == 2); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
176*8a13326dSisuckatcs 
177*8a13326dSisuckatcs   l = [arr] { return arr[1].i; }();
178*8a13326dSisuckatcs   clang_analyzer_eval(l == 3); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
179*8a13326dSisuckatcs 
180*8a13326dSisuckatcs   l = [arr] { return arr[2].i; }();
181*8a13326dSisuckatcs   clang_analyzer_eval(l == 4); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
182*8a13326dSisuckatcs 
183*8a13326dSisuckatcs   l = [arr] { return arr[3].i; }();
184*8a13326dSisuckatcs   clang_analyzer_eval(l == 5); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
185*8a13326dSisuckatcs }
186*8a13326dSisuckatcs 
187*8a13326dSisuckatcs void lambda_uninit_non_pod() {
188*8a13326dSisuckatcs   S3 arr[4];
189*8a13326dSisuckatcs 
190*8a13326dSisuckatcs   int l = [arr] { return arr[3].i; }();
191*8a13326dSisuckatcs }
192*8a13326dSisuckatcs 
193*8a13326dSisuckatcs // If this struct is being copy/move constructed by the implicit ctors, ArrayInitLoopExpr
194*8a13326dSisuckatcs // is responsible for the initialization of 'arr' by copy/move constructing each of the
195*8a13326dSisuckatcs // elements.
196*8a13326dSisuckatcs struct S5 {
197*8a13326dSisuckatcs   S2 arr[4];
198*8a13326dSisuckatcs };
199*8a13326dSisuckatcs 
200*8a13326dSisuckatcs void copy_ctor_init_non_pod() {
201*8a13326dSisuckatcs   S2::c = 0;
202*8a13326dSisuckatcs   S5 orig;
203*8a13326dSisuckatcs 
204*8a13326dSisuckatcs   S5 copy = orig;
205*8a13326dSisuckatcs   clang_analyzer_eval(copy.arr[0].i == 2); // expected-warning{{TRUE}}
206*8a13326dSisuckatcs   clang_analyzer_eval(copy.arr[1].i == 3); // expected-warning{{TRUE}}
207*8a13326dSisuckatcs   clang_analyzer_eval(copy.arr[2].i == 4); // expected-warning{{TRUE}}
208*8a13326dSisuckatcs   clang_analyzer_eval(copy.arr[3].i == 5); // expected-warning{{TRUE}}
209*8a13326dSisuckatcs }
210*8a13326dSisuckatcs 
211*8a13326dSisuckatcs void move_ctor_init_non_pod() {
212*8a13326dSisuckatcs   S2::c = 0;
213*8a13326dSisuckatcs   S5 orig;
214*8a13326dSisuckatcs 
215*8a13326dSisuckatcs   S5 moved = (S5 &&) orig;
216*8a13326dSisuckatcs 
217*8a13326dSisuckatcs   clang_analyzer_eval(moved.arr[0].i == 3); // expected-warning{{TRUE}}
218*8a13326dSisuckatcs   clang_analyzer_eval(moved.arr[1].i == 4); // expected-warning{{TRUE}}
219*8a13326dSisuckatcs   clang_analyzer_eval(moved.arr[2].i == 5); // expected-warning{{TRUE}}
220*8a13326dSisuckatcs   clang_analyzer_eval(moved.arr[3].i == 6); // expected-warning{{TRUE}}
221*8a13326dSisuckatcs }
222