xref: /llvm-project/clang/test/Analysis/array-init-loop.cpp (revision 996b092c5e170786572e925345e502e5376feaee)
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 }
1288a13326dSisuckatcs 
1298a13326dSisuckatcs // The struct has a user defined copy and move ctor, which allow us to
1308a13326dSisuckatcs // track the values more precisely when an array of this struct is being
1318a13326dSisuckatcs // copy/move initialized by ArrayInitLoopExpr.
1328a13326dSisuckatcs struct S2 {
1338a13326dSisuckatcs   inline static int c = 0;
1348a13326dSisuckatcs   int i;
1358a13326dSisuckatcs 
1368a13326dSisuckatcs   S2() : i(++c) {}
1378a13326dSisuckatcs 
1388a13326dSisuckatcs   S2(const S2 &copy) {
1398a13326dSisuckatcs     i = copy.i + 1;
1408a13326dSisuckatcs   }
1418a13326dSisuckatcs 
1428a13326dSisuckatcs   S2(S2 &&move) {
1438a13326dSisuckatcs     i = move.i + 2;
1448a13326dSisuckatcs   }
1458a13326dSisuckatcs };
1468a13326dSisuckatcs 
1478a13326dSisuckatcs void array_init_non_pod() {
1488a13326dSisuckatcs   S2::c = 0;
1498a13326dSisuckatcs   S2 arr[4];
1508a13326dSisuckatcs 
1518a13326dSisuckatcs   auto [a, b, c, d] = arr;
1528a13326dSisuckatcs 
1538a13326dSisuckatcs   clang_analyzer_eval(a.i == 2); // expected-warning{{TRUE}}
1548a13326dSisuckatcs   clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}}
1558a13326dSisuckatcs   clang_analyzer_eval(c.i == 4); // expected-warning{{TRUE}}
1568a13326dSisuckatcs   clang_analyzer_eval(d.i == 5); // expected-warning{{TRUE}}
1578a13326dSisuckatcs }
1588a13326dSisuckatcs 
1598a13326dSisuckatcs struct S3 {
1608a13326dSisuckatcs   int i;
1618a13326dSisuckatcs };
1628a13326dSisuckatcs 
163*996b092cSisuckatcs // The duplicate is required to emit a warning at 2 different places.
164*996b092cSisuckatcs struct S3_duplicate {
165*996b092cSisuckatcs   int i;
166*996b092cSisuckatcs };
167*996b092cSisuckatcs 
1688a13326dSisuckatcs void array_uninit_non_pod() {
1698a13326dSisuckatcs   S3 arr[1];
1708a13326dSisuckatcs 
1718a13326dSisuckatcs   auto [a] = arr; // expected-warning@159{{ in implicit constructor is garbage or undefined }}
1728a13326dSisuckatcs }
1738a13326dSisuckatcs 
1748a13326dSisuckatcs void lambda_init_non_pod() {
1758a13326dSisuckatcs   S2::c = 0;
1768a13326dSisuckatcs   S2 arr[4];
1778a13326dSisuckatcs 
1788a13326dSisuckatcs   auto l = [arr] { return arr[0].i; }();
179*996b092cSisuckatcs   clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}
1808a13326dSisuckatcs 
1818a13326dSisuckatcs   l = [arr] { return arr[1].i; }();
182*996b092cSisuckatcs   clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}
1838a13326dSisuckatcs 
1848a13326dSisuckatcs   l = [arr] { return arr[2].i; }();
185*996b092cSisuckatcs   clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}
1868a13326dSisuckatcs 
1878a13326dSisuckatcs   l = [arr] { return arr[3].i; }();
188*996b092cSisuckatcs   clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}
1898a13326dSisuckatcs }
1908a13326dSisuckatcs 
1918a13326dSisuckatcs void lambda_uninit_non_pod() {
192*996b092cSisuckatcs   S3_duplicate arr[4];
1938a13326dSisuckatcs 
194*996b092cSisuckatcs   int l = [arr] { return arr[3].i; }(); // expected-warning@164{{ in implicit constructor is garbage or undefined }}
1958a13326dSisuckatcs }
1968a13326dSisuckatcs 
1978a13326dSisuckatcs // If this struct is being copy/move constructed by the implicit ctors, ArrayInitLoopExpr
1988a13326dSisuckatcs // is responsible for the initialization of 'arr' by copy/move constructing each of the
1998a13326dSisuckatcs // elements.
2008a13326dSisuckatcs struct S5 {
2018a13326dSisuckatcs   S2 arr[4];
2028a13326dSisuckatcs };
2038a13326dSisuckatcs 
2048a13326dSisuckatcs void copy_ctor_init_non_pod() {
2058a13326dSisuckatcs   S2::c = 0;
2068a13326dSisuckatcs   S5 orig;
2078a13326dSisuckatcs 
2088a13326dSisuckatcs   S5 copy = orig;
2098a13326dSisuckatcs   clang_analyzer_eval(copy.arr[0].i == 2); // expected-warning{{TRUE}}
2108a13326dSisuckatcs   clang_analyzer_eval(copy.arr[1].i == 3); // expected-warning{{TRUE}}
2118a13326dSisuckatcs   clang_analyzer_eval(copy.arr[2].i == 4); // expected-warning{{TRUE}}
2128a13326dSisuckatcs   clang_analyzer_eval(copy.arr[3].i == 5); // expected-warning{{TRUE}}
2138a13326dSisuckatcs }
2148a13326dSisuckatcs 
2158a13326dSisuckatcs void move_ctor_init_non_pod() {
2168a13326dSisuckatcs   S2::c = 0;
2178a13326dSisuckatcs   S5 orig;
2188a13326dSisuckatcs 
2198a13326dSisuckatcs   S5 moved = (S5 &&) orig;
2208a13326dSisuckatcs 
2218a13326dSisuckatcs   clang_analyzer_eval(moved.arr[0].i == 3); // expected-warning{{TRUE}}
2228a13326dSisuckatcs   clang_analyzer_eval(moved.arr[1].i == 4); // expected-warning{{TRUE}}
2238a13326dSisuckatcs   clang_analyzer_eval(moved.arr[2].i == 5); // expected-warning{{TRUE}}
2248a13326dSisuckatcs   clang_analyzer_eval(moved.arr[3].i == 6); // expected-warning{{TRUE}}
2258a13326dSisuckatcs }
226