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 } 226c81bf940Sisuckatcs 227c81bf940Sisuckatcs //Note: This is the only solution I could find to check the values without 228c81bf940Sisuckatcs // crashing clang. For more details on the crash see Issue #57135. 229c81bf940Sisuckatcs void lambda_capture_multi_array() { 230c81bf940Sisuckatcs S3 arr[2][2] = {1,2,3,4}; 231c81bf940Sisuckatcs 232c81bf940Sisuckatcs { 233c81bf940Sisuckatcs int x = [arr] { return arr[0][0].i; }(); 234c81bf940Sisuckatcs clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 235c81bf940Sisuckatcs } 236c81bf940Sisuckatcs 237c81bf940Sisuckatcs { 238c81bf940Sisuckatcs int x = [arr] { return arr[0][1].i; }(); 239c81bf940Sisuckatcs clang_analyzer_eval(x == 2); // expected-warning{{TRUE}} 240c81bf940Sisuckatcs } 241c81bf940Sisuckatcs 242c81bf940Sisuckatcs { 243c81bf940Sisuckatcs int x = [arr] { return arr[1][0].i; }(); 244c81bf940Sisuckatcs clang_analyzer_eval(x == 3); // expected-warning{{TRUE}} 245c81bf940Sisuckatcs } 246c81bf940Sisuckatcs 247c81bf940Sisuckatcs { 248c81bf940Sisuckatcs int x = [arr] { return arr[1][1].i; }(); 249c81bf940Sisuckatcs clang_analyzer_eval(x == 4); // expected-warning{{TRUE}} 250c81bf940Sisuckatcs } 251c81bf940Sisuckatcs } 252c81bf940Sisuckatcs 253c81bf940Sisuckatcs // This struct will force constructor inlining in MultiWrapper. 254c81bf940Sisuckatcs struct UserDefinedCtor { 255c81bf940Sisuckatcs int i; 256c81bf940Sisuckatcs UserDefinedCtor() {} 257c81bf940Sisuckatcs UserDefinedCtor(const UserDefinedCtor ©) { 258c81bf940Sisuckatcs int j = 1; 259c81bf940Sisuckatcs i = copy.i; 260c81bf940Sisuckatcs } 261c81bf940Sisuckatcs }; 262c81bf940Sisuckatcs 263c81bf940Sisuckatcs struct MultiWrapper { 264c81bf940Sisuckatcs UserDefinedCtor arr[2][2]; 265c81bf940Sisuckatcs }; 266c81bf940Sisuckatcs 267c81bf940Sisuckatcs void copy_ctor_multi() { 268c81bf940Sisuckatcs MultiWrapper MW; 269c81bf940Sisuckatcs 270c81bf940Sisuckatcs MW.arr[0][0].i = 0; 271c81bf940Sisuckatcs MW.arr[0][1].i = 1; 272c81bf940Sisuckatcs MW.arr[1][0].i = 2; 273c81bf940Sisuckatcs MW.arr[1][1].i = 3; 274c81bf940Sisuckatcs 275c81bf940Sisuckatcs MultiWrapper MWCopy = MW; 276c81bf940Sisuckatcs 277c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[0][0].i == 0); // expected-warning{{TRUE}} 278c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[0][1].i == 1); // expected-warning{{TRUE}} 279c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[1][0].i == 2); // expected-warning{{TRUE}} 280c81bf940Sisuckatcs clang_analyzer_eval(MWCopy.arr[1][1].i == 3); // expected-warning{{TRUE}} 281c81bf940Sisuckatcs } 282c81bf940Sisuckatcs 283c81bf940Sisuckatcs void move_ctor_multi() { 284c81bf940Sisuckatcs MultiWrapper MW; 285c81bf940Sisuckatcs 286c81bf940Sisuckatcs MW.arr[0][0].i = 0; 287c81bf940Sisuckatcs MW.arr[0][1].i = 1; 288c81bf940Sisuckatcs MW.arr[1][0].i = 2; 289c81bf940Sisuckatcs MW.arr[1][1].i = 3; 290c81bf940Sisuckatcs 291c81bf940Sisuckatcs MultiWrapper MWMove = (MultiWrapper &&) MW; 292c81bf940Sisuckatcs 293c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[0][0].i == 0); // expected-warning{{TRUE}} 294c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[0][1].i == 1); // expected-warning{{TRUE}} 295c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[1][0].i == 2); // expected-warning{{TRUE}} 296c81bf940Sisuckatcs clang_analyzer_eval(MWMove.arr[1][1].i == 3); // expected-warning{{TRUE}} 297c81bf940Sisuckatcs } 298c81bf940Sisuckatcs 299c81bf940Sisuckatcs void structured_binding_multi() { 300c81bf940Sisuckatcs S3 arr[2][2] = {1,2,3,4}; 301c81bf940Sisuckatcs 302c81bf940Sisuckatcs auto [a,b] = arr; 303c81bf940Sisuckatcs 304c81bf940Sisuckatcs clang_analyzer_eval(a[0].i == 1); // expected-warning{{TRUE}} 305c81bf940Sisuckatcs clang_analyzer_eval(a[1].i == 2); // expected-warning{{TRUE}} 306c81bf940Sisuckatcs clang_analyzer_eval(b[0].i == 3); // expected-warning{{TRUE}} 307c81bf940Sisuckatcs clang_analyzer_eval(b[1].i == 4); // expected-warning{{TRUE}} 308c81bf940Sisuckatcs } 309e3e9082bSisuckatcs 310e3e9082bSisuckatcs // This snippet used to crash 311e3e9082bSisuckatcs namespace crash { 312e3e9082bSisuckatcs 313e3e9082bSisuckatcs struct S 314e3e9082bSisuckatcs { 315e3e9082bSisuckatcs int x; 316e3e9082bSisuckatcs S() { x = 1; } 317e3e9082bSisuckatcs }; 318e3e9082bSisuckatcs 319e3e9082bSisuckatcs void no_crash() { 320e3e9082bSisuckatcs S arr[0]; 321e3e9082bSisuckatcs int n = 1; 322e3e9082bSisuckatcs 323e3e9082bSisuckatcs auto l = [arr, n] { return n; }; 324e3e9082bSisuckatcs 325e3e9082bSisuckatcs int x = l(); 326e3e9082bSisuckatcs clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 327e3e9082bSisuckatcs 328e3e9082bSisuckatcs // FIXME: This should be 'Undefined'. 329e3e9082bSisuckatcs clang_analyzer_eval(arr[0].x); // expected-warning{{UNKNOWN}} 330e3e9082bSisuckatcs } 331e3e9082bSisuckatcs 332e3e9082bSisuckatcs } // namespace crash 333*a917ae0bSisuckatcs 334*a917ae0bSisuckatcs namespace array_subscript_initializer { 335*a917ae0bSisuckatcs struct S { 336*a917ae0bSisuckatcs int x; 337*a917ae0bSisuckatcs }; 338*a917ae0bSisuckatcs 339*a917ae0bSisuckatcs void no_crash() { 340*a917ae0bSisuckatcs S arr[][2] = {{1, 2}}; 341*a917ae0bSisuckatcs 342*a917ae0bSisuckatcs const auto [a, b] = arr[0]; // no-crash 343*a917ae0bSisuckatcs 344*a917ae0bSisuckatcs clang_analyzer_eval(a.x == 1); // expected-warning{{TRUE}} 345*a917ae0bSisuckatcs clang_analyzer_eval(b.x == 2); // expected-warning{{TRUE}} 346*a917ae0bSisuckatcs } 347*a917ae0bSisuckatcs } // namespace array_subscript_initializer 348*a917ae0bSisuckatcs 349*a917ae0bSisuckatcs namespace iterator_initializer { 350*a917ae0bSisuckatcs struct S { 351*a917ae0bSisuckatcs int x; 352*a917ae0bSisuckatcs }; 353*a917ae0bSisuckatcs 354*a917ae0bSisuckatcs void no_crash() { 355*a917ae0bSisuckatcs S arr[][2] = {{1, 2}, {3, 4}}; 356*a917ae0bSisuckatcs 357*a917ae0bSisuckatcs int i = 0; 358*a917ae0bSisuckatcs for (const auto [a, b] : arr) { // no-crash 359*a917ae0bSisuckatcs if (i == 0) { 360*a917ae0bSisuckatcs clang_analyzer_eval(a.x == 1); // expected-warning{{TRUE}} 361*a917ae0bSisuckatcs clang_analyzer_eval(b.x == 2); // expected-warning{{TRUE}} 362*a917ae0bSisuckatcs } else { 363*a917ae0bSisuckatcs clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}} 364*a917ae0bSisuckatcs clang_analyzer_eval(b.x == 4); // expected-warning{{TRUE}} 365*a917ae0bSisuckatcs } 366*a917ae0bSisuckatcs 367*a917ae0bSisuckatcs ++i; 368*a917ae0bSisuckatcs } 369*a917ae0bSisuckatcs } 370*a917ae0bSisuckatcs } // namespace iterator_initializer 371