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 ©) { 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 163996b092cSisuckatcs // The duplicate is required to emit a warning at 2 different places. 164996b092cSisuckatcs struct S3_duplicate { 165996b092cSisuckatcs int i; 166996b092cSisuckatcs }; 167996b092cSisuckatcs 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; }(); 179996b092cSisuckatcs clang_analyzer_eval(l == 2); // expected-warning{{TRUE}} 1808a13326dSisuckatcs 1818a13326dSisuckatcs l = [arr] { return arr[1].i; }(); 182996b092cSisuckatcs clang_analyzer_eval(l == 3); // expected-warning{{TRUE}} 1838a13326dSisuckatcs 1848a13326dSisuckatcs l = [arr] { return arr[2].i; }(); 185996b092cSisuckatcs clang_analyzer_eval(l == 4); // expected-warning{{TRUE}} 1868a13326dSisuckatcs 1878a13326dSisuckatcs l = [arr] { return arr[3].i; }(); 188996b092cSisuckatcs clang_analyzer_eval(l == 5); // expected-warning{{TRUE}} 1898a13326dSisuckatcs } 1908a13326dSisuckatcs 1918a13326dSisuckatcs void lambda_uninit_non_pod() { 192996b092cSisuckatcs S3_duplicate arr[4]; 1938a13326dSisuckatcs 194996b092cSisuckatcs 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*c81bf940Sisuckatcs 227*c81bf940Sisuckatcs //Note: This is the only solution I could find to check the values without 228*c81bf940Sisuckatcs // crashing clang. For more details on the crash see Issue #57135. 229*c81bf940Sisuckatcs void lambda_capture_multi_array() { 230*c81bf940Sisuckatcs S3 arr[2][2] = {1,2,3,4}; 231*c81bf940Sisuckatcs 232*c81bf940Sisuckatcs { 233*c81bf940Sisuckatcs int x = [arr] { return arr[0][0].i; }(); 234*c81bf940Sisuckatcs clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 235*c81bf940Sisuckatcs } 236*c81bf940Sisuckatcs 237*c81bf940Sisuckatcs { 238*c81bf940Sisuckatcs int x = [arr] { return arr[0][1].i; }(); 239*c81bf940Sisuckatcs clang_analyzer_eval(x == 2); // expected-warning{{TRUE}} 240*c81bf940Sisuckatcs } 241*c81bf940Sisuckatcs 242*c81bf940Sisuckatcs { 243*c81bf940Sisuckatcs int x = [arr] { return arr[1][0].i; }(); 244*c81bf940Sisuckatcs clang_analyzer_eval(x == 3); // expected-warning{{TRUE}} 245*c81bf940Sisuckatcs } 246*c81bf940Sisuckatcs 247*c81bf940Sisuckatcs { 248*c81bf940Sisuckatcs int x = [arr] { return arr[1][1].i; }(); 249*c81bf940Sisuckatcs clang_analyzer_eval(x == 4); // expected-warning{{TRUE}} 250*c81bf940Sisuckatcs } 251*c81bf940Sisuckatcs } 252*c81bf940Sisuckatcs 253*c81bf940Sisuckatcs // This struct will force constructor inlining in MultiWrapper. 254*c81bf940Sisuckatcs struct UserDefinedCtor { 255*c81bf940Sisuckatcs int i; 256*c81bf940Sisuckatcs UserDefinedCtor() {} 257*c81bf940Sisuckatcs UserDefinedCtor(const UserDefinedCtor ©) { 258*c81bf940Sisuckatcs int j = 1; 259*c81bf940Sisuckatcs i = copy.i; 260*c81bf940Sisuckatcs } 261*c81bf940Sisuckatcs }; 262*c81bf940Sisuckatcs 263*c81bf940Sisuckatcs struct MultiWrapper { 264*c81bf940Sisuckatcs UserDefinedCtor arr[2][2]; 265*c81bf940Sisuckatcs }; 266*c81bf940Sisuckatcs 267*c81bf940Sisuckatcs void copy_ctor_multi() { 268*c81bf940Sisuckatcs MultiWrapper MW; 269*c81bf940Sisuckatcs 270*c81bf940Sisuckatcs MW.arr[0][0].i = 0; 271*c81bf940Sisuckatcs MW.arr[0][1].i = 1; 272*c81bf940Sisuckatcs MW.arr[1][0].i = 2; 273*c81bf940Sisuckatcs MW.arr[1][1].i = 3; 274*c81bf940Sisuckatcs 275*c81bf940Sisuckatcs MultiWrapper MWCopy = MW; 276*c81bf940Sisuckatcs 277*c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[0][0].i == 0); // expected-warning{{TRUE}} 278*c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[0][1].i == 1); // expected-warning{{TRUE}} 279*c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[1][0].i == 2); // expected-warning{{TRUE}} 280*c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[1][1].i == 3); // expected-warning{{TRUE}} 281*c81bf940Sisuckatcs } 282*c81bf940Sisuckatcs 283*c81bf940Sisuckatcs void move_ctor_multi() { 284*c81bf940Sisuckatcs MultiWrapper MW; 285*c81bf940Sisuckatcs 286*c81bf940Sisuckatcs MW.arr[0][0].i = 0; 287*c81bf940Sisuckatcs MW.arr[0][1].i = 1; 288*c81bf940Sisuckatcs MW.arr[1][0].i = 2; 289*c81bf940Sisuckatcs MW.arr[1][1].i = 3; 290*c81bf940Sisuckatcs 291*c81bf940Sisuckatcs MultiWrapper MWMove = (MultiWrapper &&) MW; 292*c81bf940Sisuckatcs 293*c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[0][0].i == 0); // expected-warning{{TRUE}} 294*c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[0][1].i == 1); // expected-warning{{TRUE}} 295*c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[1][0].i == 2); // expected-warning{{TRUE}} 296*c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[1][1].i == 3); // expected-warning{{TRUE}} 297*c81bf940Sisuckatcs } 298*c81bf940Sisuckatcs 299*c81bf940Sisuckatcs void structured_binding_multi() { 300*c81bf940Sisuckatcs S3 arr[2][2] = {1,2,3,4}; 301*c81bf940Sisuckatcs 302*c81bf940Sisuckatcs auto [a,b] = arr; 303*c81bf940Sisuckatcs 304*c81bf940Sisuckatcs clang_analyzer_eval(a[0].i == 1); // expected-warning{{TRUE}} 305*c81bf940Sisuckatcs clang_analyzer_eval(a[1].i == 2); // expected-warning{{TRUE}} 306*c81bf940Sisuckatcs clang_analyzer_eval(b[0].i == 3); // expected-warning{{TRUE}} 307*c81bf940Sisuckatcs clang_analyzer_eval(b[1].i == 4); // expected-warning{{TRUE}} 308*c81bf940Sisuckatcs } 309