1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s 2 3 void clang_analyzer_eval(bool); 4 5 void array_init() { 6 int arr[] = {1, 2, 3, 4, 5}; 7 8 auto [a, b, c, d, e] = arr; 9 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}} 15 } 16 17 void array_uninit() { 18 int arr[5]; 19 20 auto [a, b, c, d, e] = arr; 21 22 int x = e; // expected-warning{{Assigned value is garbage or undefined}} 23 } 24 25 void lambda_init() { 26 int arr[] = {1, 2, 3, 4, 5}; 27 28 auto l = [arr] { return arr[0]; }(); 29 clang_analyzer_eval(l == 1); // expected-warning{{TRUE}} 30 31 l = [arr] { return arr[1]; }(); 32 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}} 33 34 l = [arr] { return arr[2]; }(); 35 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}} 36 37 l = [arr] { return arr[3]; }(); 38 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}} 39 40 l = [arr] { return arr[4]; }(); 41 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}} 42 } 43 44 void lambda_uninit() { 45 int arr[5]; 46 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}} 50 51 l = [arr] { return arr[1]; }(); 52 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}} 53 54 l = [arr] { return arr[2]; }(); 55 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}} 56 57 l = [arr] { return arr[3]; }(); 58 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}} 59 60 l = [arr] { return arr[4]; }(); 61 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}} 62 } 63 64 struct S { 65 int arr[5]; 66 }; 67 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; 75 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}} 82 } 83 84 void copy_ctor_uninit() { 85 S orig; 86 87 S copy = orig; 88 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}} 97 } 98 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; 106 107 S moved = (S &&) orig; 108 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}} 114 } 115 116 void move_ctor_uninit() { 117 S orig; 118 119 S moved = (S &&) orig; 120 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}} 127 } 128 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; 135 136 S2() : i(++c) {} 137 138 S2(const S2 ©) { 139 i = copy.i + 1; 140 } 141 142 S2(S2 &&move) { 143 i = move.i + 2; 144 } 145 }; 146 147 void array_init_non_pod() { 148 S2::c = 0; 149 S2 arr[4]; 150 151 auto [a, b, c, d] = arr; 152 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}} 157 } 158 159 struct S3 { 160 int i; 161 }; 162 163 // The duplicate is required to emit a warning at 2 different places. 164 struct S3_duplicate { 165 int i; 166 }; 167 168 void array_uninit_non_pod() { 169 S3 arr[1]; 170 171 auto [a] = arr; // expected-warning@159{{ in implicit constructor is garbage or undefined }} 172 } 173 174 void lambda_init_non_pod() { 175 S2::c = 0; 176 S2 arr[4]; 177 178 auto l = [arr] { return arr[0].i; }(); 179 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}} 180 181 l = [arr] { return arr[1].i; }(); 182 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}} 183 184 l = [arr] { return arr[2].i; }(); 185 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}} 186 187 l = [arr] { return arr[3].i; }(); 188 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}} 189 } 190 191 void lambda_uninit_non_pod() { 192 S3_duplicate arr[4]; 193 194 int l = [arr] { return arr[3].i; }(); // expected-warning@164{{ in implicit constructor is garbage or undefined }} 195 } 196 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]; 202 }; 203 204 void copy_ctor_init_non_pod() { 205 S2::c = 0; 206 S5 orig; 207 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}} 213 } 214 215 void move_ctor_init_non_pod() { 216 S2::c = 0; 217 S5 orig; 218 219 S5 moved = (S5 &&) orig; 220 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}} 225 } 226 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}; 231 232 { 233 int x = [arr] { return arr[0][0].i; }(); 234 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 235 } 236 237 { 238 int x = [arr] { return arr[0][1].i; }(); 239 clang_analyzer_eval(x == 2); // expected-warning{{TRUE}} 240 } 241 242 { 243 int x = [arr] { return arr[1][0].i; }(); 244 clang_analyzer_eval(x == 3); // expected-warning{{TRUE}} 245 } 246 247 { 248 int x = [arr] { return arr[1][1].i; }(); 249 clang_analyzer_eval(x == 4); // expected-warning{{TRUE}} 250 } 251 } 252 253 // This struct will force constructor inlining in MultiWrapper. 254 struct UserDefinedCtor { 255 int i; 256 UserDefinedCtor() {} 257 UserDefinedCtor(const UserDefinedCtor ©) { 258 int j = 1; 259 i = copy.i; 260 } 261 }; 262 263 struct MultiWrapper { 264 UserDefinedCtor arr[2][2]; 265 }; 266 267 void copy_ctor_multi() { 268 MultiWrapper MW; 269 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; 274 275 MultiWrapper MWCopy = MW; 276 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}} 281 } 282 283 void move_ctor_multi() { 284 MultiWrapper MW; 285 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; 290 291 MultiWrapper MWMove = (MultiWrapper &&) MW; 292 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}} 297 } 298 299 void structured_binding_multi() { 300 S3 arr[2][2] = {1,2,3,4}; 301 302 auto [a,b] = arr; 303 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}} 308 } 309 310 // This snippet used to crash 311 namespace crash { 312 313 struct S 314 { 315 int x; 316 S() { x = 1; } 317 }; 318 319 void no_crash() { 320 S arr[0]; 321 int n = 1; 322 323 auto l = [arr, n] { return n; }; 324 325 int x = l(); 326 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 327 328 // FIXME: This should be 'Undefined'. 329 clang_analyzer_eval(arr[0].x); // expected-warning{{UNKNOWN}} 330 } 331 332 } // namespace crash 333 334 namespace array_subscript_initializer { 335 struct S { 336 int x; 337 }; 338 339 void no_crash() { 340 S arr[][2] = {{1, 2}}; 341 342 const auto [a, b] = arr[0]; // no-crash 343 344 clang_analyzer_eval(a.x == 1); // expected-warning{{TRUE}} 345 clang_analyzer_eval(b.x == 2); // expected-warning{{TRUE}} 346 } 347 } // namespace array_subscript_initializer 348 349 namespace iterator_initializer { 350 struct S { 351 int x; 352 }; 353 354 void no_crash() { 355 S arr[][2] = {{1, 2}, {3, 4}}; 356 357 int i = 0; 358 for (const auto [a, b] : arr) { // no-crash 359 if (i == 0) { 360 clang_analyzer_eval(a.x == 1); // expected-warning{{TRUE}} 361 clang_analyzer_eval(b.x == 2); // expected-warning{{TRUE}} 362 } else { 363 clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}} 364 clang_analyzer_eval(b.x == 4); // expected-warning{{TRUE}} 365 } 366 367 ++i; 368 } 369 } 370 } // namespace iterator_initializer 371