1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++14 -analyzer-config exploration_strategy=unexplored_first_queue %s 2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true,exploration_strategy=dfs -verify -std=c++14 -DDFS=1 %s 3 4 void clang_analyzer_numTimesReached(); 5 void clang_analyzer_warnIfReached(); 6 7 int getNum(); 8 void foo(int &); 9 10 int simple_unroll1() { 11 int a[9]; 12 int k = 42; 13 for (int i = 0; i < 9; i++) { 14 clang_analyzer_numTimesReached(); // expected-warning {{9}} 15 a[i] = 42; 16 } 17 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 18 return 0; 19 } 20 21 int simple_unroll2() { 22 int a[9]; 23 int k = 42; 24 int i; 25 for (i = 0; i < 9; i++) { 26 clang_analyzer_numTimesReached(); // expected-warning {{9}} 27 a[i] = 42; 28 } 29 30 for (int j = 0; j <= 9; ++j) { 31 clang_analyzer_numTimesReached(); // expected-warning {{10}} 32 a[j] = 42; 33 } 34 35 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 36 return 0; 37 } 38 39 int simple_unroll3_unsigned() { 40 int a[9]; 41 int k = 42; 42 for (unsigned i = 0; i < 9; i++) { 43 clang_analyzer_numTimesReached(); // expected-warning {{9}} 44 a[i] = 42; 45 } 46 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 47 return 0; 48 } 49 50 int simple_unroll4_unsigned() { 51 int a[9]; 52 int k = 42; 53 unsigned i; 54 for (i = (0); i < 9; i++) { 55 clang_analyzer_numTimesReached(); // expected-warning {{9}} 56 a[i] = 42; 57 } 58 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 59 return 0; 60 } 61 62 int simple_no_unroll1() { 63 int a[9]; 64 int k = 42; 65 for (int i = 0; i < 9; i++) { 66 clang_analyzer_numTimesReached(); // expected-warning {{2}} 67 a[i] = 42; 68 foo(i); 69 } 70 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 71 return 0; 72 } 73 74 int simple_no_unroll2() { 75 int a[9]; 76 int k = 42; 77 int i; 78 for (i = 0; i < 9; i++) { 79 clang_analyzer_numTimesReached(); // expected-warning {{2}} 80 a[i] = 42; 81 i += getNum(); 82 } 83 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 84 return 0; 85 } 86 87 int simple_no_unroll3() { 88 int a[9]; 89 int k = 42; 90 for (int i = 0; i < 9; i++) { 91 clang_analyzer_numTimesReached(); // expected-warning {{4}} 92 a[i] = 42; 93 (void)&i; 94 } 95 int b = 22 / (k - 42); // no-warning 96 return 0; 97 } 98 99 int simple_no_unroll4() { 100 int a[9]; 101 int k = 42; 102 int i; 103 for (i = 0; i < 9; i++) { 104 clang_analyzer_numTimesReached(); // expected-warning {{4}} 105 a[i] = 42; 106 int &j = i; 107 } 108 int b = 22 / (k - 42); // no-warning 109 return 0; 110 } 111 112 int simple_no_unroll5() { 113 int a[9]; 114 int k = 42; 115 int i; 116 for (i = 0; i < 9; i++) { 117 clang_analyzer_numTimesReached(); // expected-warning {{4}} 118 a[i] = 42; 119 int &j{i}; 120 } 121 int b = 22 / (k - 42); // no-warning 122 return 0; 123 } 124 125 int no_unroll_assignment() { 126 for (int i = 0; i < 9; i++) { 127 i = i + 1; 128 clang_analyzer_numTimesReached(); // expected-warning {{4}} 129 } 130 return 0; 131 } 132 133 int no_unroll_assignment2() { 134 for (int i = 0; i < 9; i++) { 135 i *= 2; 136 clang_analyzer_numTimesReached(); // expected-warning {{4}} 137 } 138 return 0; 139 } 140 141 int no_unroll_assignment3() { 142 for (int i = 128; i > 0; i--) { 143 i /= 2; 144 clang_analyzer_numTimesReached(); // expected-warning {{4}} 145 } 146 return 0; 147 } 148 149 int no_unroll_assignment4() { 150 for (int i = 0; i < 9; i++) { 151 i -= 2; 152 clang_analyzer_numTimesReached(); // expected-warning {{4}} 153 } 154 return 0; 155 } 156 157 int no_unroll_assignment5() { 158 for (int i = 0; i < 9; i++) { 159 i += 1; 160 clang_analyzer_numTimesReached(); // expected-warning {{4}} 161 } 162 return 0; 163 } 164 165 int no_unroll_assignment6() { 166 for (int i = 128; i > 0; i--) { 167 i >>= 1; 168 clang_analyzer_numTimesReached(); // expected-warning {{4}} 169 } 170 return 0; 171 } 172 173 int no_unroll_assignment7() { 174 for (int i = 0; i < 512; i++) { 175 i <<= 1; 176 clang_analyzer_numTimesReached(); // expected-warning {{4}} 177 } 178 return 0; 179 } 180 181 int no_unroll_assignment8() { 182 for (int i = 0; i < 9; i++) { 183 i %= 8; 184 clang_analyzer_numTimesReached(); // expected-warning {{4}} 185 } 186 return 0; 187 } 188 189 int no_unroll_assignment9() { 190 for (int i = 0; i < 9; i++) { 191 i &= 31; 192 clang_analyzer_numTimesReached(); // expected-warning {{4}} 193 } 194 return 0; 195 } 196 197 int no_unroll_assignment10() { 198 for (int i = 0; i < 9; i++) { 199 i |= 2; 200 clang_analyzer_numTimesReached(); // expected-warning {{4}} 201 } 202 return 0; 203 } 204 205 int no_unroll_assignment11() { 206 for (int i = 0; i < 9; i++) { 207 i ^= 2; 208 clang_analyzer_numTimesReached(); // expected-warning {{4}} 209 } 210 return 0; 211 } 212 213 int make_new_branches_loop_cached() { 214 for (int i = 0; i < 8; i++) { 215 clang_analyzer_numTimesReached(); // expected-warning {{4}} 216 if (getNum()) { 217 (void)i; // Since this Stmt does not change the State the analyzer 218 // won't make a new execution path but reuse the earlier nodes. 219 } 220 } 221 clang_analyzer_warnIfReached(); // no-warning 222 return 0; 223 } 224 225 int make_new_branches_loop_uncached() { 226 int l = 2; 227 for (int i = 0; i < 8; i++) { 228 clang_analyzer_numTimesReached(); // expected-warning {{10}} 229 if (getNum()) { 230 ++l; 231 } 232 } 233 clang_analyzer_warnIfReached(); // no-warning 234 return 0; 235 } 236 237 int make_new_branches_loop_uncached2() { 238 int l = 2; 239 for (int i = 0; i < 8; i++) { 240 clang_analyzer_numTimesReached(); // expected-warning {{10}} 241 if (getNum()) { 242 ++l; 243 } 244 (void)&i; // This ensures that the loop won't be unrolled. 245 } 246 clang_analyzer_warnIfReached(); // no-warning 247 return 0; 248 } 249 250 251 int escape_before_loop_no_unroll1() { 252 int a[9]; 253 int k = 42; 254 int i; 255 int &j = i; 256 for (i = 0; i < 9; i++) { 257 clang_analyzer_numTimesReached(); // expected-warning {{4}} 258 a[i] = 42; 259 } 260 int b = 22 / (k - 42); // no-warning 261 return 0; 262 } 263 264 int escape_before_loop_no_unroll2() { 265 int a[9]; 266 int k = 42; 267 int i; 268 int *p = &i; 269 for (i = 0; i < 9; i++) { 270 clang_analyzer_numTimesReached(); // expected-warning {{4}} 271 a[i] = 42; 272 } 273 int b = 22 / (k - 42); // no-warning 274 return 0; 275 } 276 277 int escape_before_loop_no_unroll3() { 278 int a[9]; 279 int k = 42; 280 int i; 281 foo(i); 282 for (i = 0; i < 9; i++) { 283 clang_analyzer_numTimesReached(); // expected-warning {{4}} 284 a[i] = 42; 285 } 286 int b = 22 / (k - 42); // no-warning 287 return 0; 288 } 289 290 int nested_outer_unrolled() { 291 int a[9]; 292 int k = 42; 293 int j = 0; 294 for (int i = 0; i < 9; i++) { 295 clang_analyzer_numTimesReached(); // expected-warning {{1}} 296 for (j = 0; j < 9; ++j) { 297 clang_analyzer_numTimesReached(); // expected-warning {{4}} 298 a[j] = 22; 299 (void)&j; // ensures that the inner loop won't be unrolled 300 } 301 a[i] = 42; 302 } 303 int b = 22 / (k - 42); // no-warning 304 return 0; 305 } 306 307 int nested_inner_unrolled() { 308 int a[9]; 309 int k = 42; 310 int j = 0; 311 for (int i = 0; i < getNum(); i++) { 312 clang_analyzer_numTimesReached(); // expected-warning {{2}} 313 for (j = 0; j < 8; ++j) { 314 clang_analyzer_numTimesReached(); // expected-warning {{16}} 315 a[j] = 22; 316 } 317 a[i] = 42; 318 } 319 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 320 return 0; 321 } 322 323 int nested_both_unrolled() { 324 int a[9]; 325 int k = 42; 326 int j = 0; 327 for (int i = 0; i < 7; i++) { 328 clang_analyzer_numTimesReached(); // expected-warning {{7}} 329 for (j = 0; j < 6; ++j) { 330 clang_analyzer_numTimesReached(); // expected-warning {{42}} 331 a[j] = 22; 332 } 333 a[i] = 42; 334 } 335 int b = 22 / (k - 42); // expected-warning {{Division by zero}} 336 return 0; 337 } 338 339 int simple_known_bound_loop() { 340 for (int i = 2; i < 12; i++) { 341 // This function is inlined in nested_inlined_unroll1() 342 clang_analyzer_numTimesReached(); // expected-warning {{90}} 343 } 344 return 0; 345 } 346 347 int simple_unknown_bound_loop() { 348 for (int i = 2; i < getNum(); i++) { 349 clang_analyzer_numTimesReached(); // expected-warning {{8}} 350 } 351 return 0; 352 } 353 354 int nested_inlined_unroll1() { 355 int k; 356 for (int i = 0; i < 9; i++) { 357 clang_analyzer_numTimesReached(); // expected-warning {{9}} 358 k = simple_known_bound_loop(); // no reevaluation without inlining 359 } 360 int a = 22 / k; // expected-warning {{Division by zero}} 361 return 0; 362 } 363 364 int nested_inlined_no_unroll1() { 365 int k; 366 for (int i = 0; i < 9; i++) { 367 clang_analyzer_numTimesReached(); // expected-warning {{10}} 368 k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well 369 } 370 int a = 22 / k; // no-warning 371 return 0; 372 } 373 374 int recursion_unroll1(bool b) { 375 int k = 2; 376 for (int i = 0; i < 5; i++) { 377 clang_analyzer_numTimesReached(); // expected-warning {{13}} 378 if (i == 0 && b) // Splits the state in the first iteration but the recursion 379 // call will be unrolled anyway since the condition is known there. 380 recursion_unroll1(false); 381 clang_analyzer_numTimesReached(); // expected-warning {{14}} 382 } 383 int a = 22 / k; // no-warning 384 return 0; 385 } 386 387 int recursion_unroll2(bool b) { 388 int k = 0; 389 for (int i = 0; i < 5; i++) { 390 clang_analyzer_numTimesReached(); // expected-warning {{9}} 391 if (i == 0 && b) 392 recursion_unroll2(false); 393 clang_analyzer_numTimesReached(); // expected-warning {{9}} 394 } 395 int a = 22 / k; // expected-warning {{Division by zero}} 396 return 0; 397 } 398 399 int recursion_unroll3(bool b) { 400 int k = 2; 401 for (int i = 0; i < 5; i++) { 402 clang_analyzer_numTimesReached(); // expected-warning {{10}} 403 if (i == 4 && b) { 404 recursion_unroll3(false); 405 break; 406 } 407 clang_analyzer_numTimesReached(); // expected-warning {{10}} 408 } 409 int a = 22 / k; 410 return 0; 411 } 412 413 int recursion_unroll4(bool b) { 414 int k = 2; 415 for (int i = 0; i < 5; i++) { 416 clang_analyzer_numTimesReached(); // expected-warning {{13}} 417 if (i == 0 && b) { 418 recursion_unroll4(false); 419 continue; 420 } 421 clang_analyzer_numTimesReached(); // expected-warning {{13}} 422 } 423 int a = 22 / k; 424 return 0; 425 } 426 427 int loop_exit_while_empty_loop_stack() { 428 if (getNum()) 429 for (int i = 1; i < 8; i++) 430 ; 431 return 0; 432 } 433 434 int num_steps_on_limit() { 435 for (int i = 0; i < 128; i++) { 436 clang_analyzer_numTimesReached(); // expected-warning {{128}} 437 } 438 clang_analyzer_numTimesReached(); // expected-warning {{1}} 439 return 0; 440 } 441 442 int num_steps_over_limit1() { 443 for (int i = 0; i < 129; i++) { 444 clang_analyzer_numTimesReached(); // expected-warning {{4}} 445 } 446 return 0; 447 } 448 449 int num_steps_on_limit2() { 450 for (int i = 0; i < 2; i++) { 451 for (int j = 0; j < 64; j++) { 452 clang_analyzer_numTimesReached(); // expected-warning {{128}} 453 } 454 } 455 return 0; 456 } 457 458 int num_steps_over_limit2() { 459 for (int i = 0; i < 2; i++) { 460 clang_analyzer_numTimesReached(); // expected-warning {{1}} 461 for (int j = 0; j <= 64; j++) { 462 clang_analyzer_numTimesReached(); // expected-warning {{4}} 463 } 464 } 465 return 0; 466 } 467 468 int num_steps_on_limit3() { 469 for (int i = 0; i < getNum(); i++) { 470 clang_analyzer_numTimesReached(); // expected-warning {{2}} 471 for (int j = 0; j < 32; j++) { 472 // Here the loop unrollig logic calculates with four potential iterations 473 // in the outer loop where it cannot determine the iteration count in 474 // advance; but after two loops the analyzer conservatively assumes that 475 // the (still opaque) loop condition is false. 476 clang_analyzer_numTimesReached(); // expected-warning {{64}} 477 } 478 } 479 return 0; 480 } 481 482 int num_steps_over_limit3() { 483 for (int i = 0; i < getNum(); i++) { 484 clang_analyzer_numTimesReached(); // expected-warning {{1}} 485 for (int j = 0; j < 33; j++) { 486 clang_analyzer_numTimesReached(); // expected-warning {{4}} 487 } 488 } 489 return 0; 490 } 491 492 int num_steps_on_limit4() { 493 for (int i = 0; i < 4; i++) { 494 clang_analyzer_numTimesReached(); // expected-warning {{4}} 495 for (int j = 0; j < 32; j++) { 496 clang_analyzer_numTimesReached(); // expected-warning {{128}} 497 } 498 } 499 return 0; 500 } 501 502 void pr34943() { 503 for (int i = 0; i < 6L; ++i) { 504 clang_analyzer_numTimesReached(); // expected-warning {{6}} 505 } 506 } 507 508 void parm_by_value_as_loop_counter(int i) { 509 for (i = 0; i < 10; ++i) { 510 clang_analyzer_numTimesReached(); // expected-warning {{10}} 511 } 512 } 513 514 void parm_by_ref_as_loop_counter(int &i) { 515 for (i = 0; i < 10; ++i) { 516 clang_analyzer_numTimesReached(); // expected-warning {{4}} 517 } 518 } 519 520 void capture_by_value_as_loop_counter() { 521 int out = 0; 522 auto l = [i = out]() mutable { 523 for (i = 0; i < 10; ++i) { 524 clang_analyzer_numTimesReached(); // expected-warning {{10}} 525 } 526 }; 527 } 528 529 void capture_by_ref_as_loop_counter() { 530 int out = 0; 531 auto l = [&i = out]() { 532 for (i = 0; i < 10; ++i) { 533 clang_analyzer_numTimesReached(); // expected-warning {{4}} 534 } 535 }; 536 } 537 538 void capture_implicitly_by_value_as_loop_counter() { 539 int i = 0; 540 auto l = [=]() mutable { 541 for (i = 0; i < 10; ++i) { 542 clang_analyzer_numTimesReached(); // expected-warning {{10}} 543 } 544 }; 545 } 546 547 void capture_implicitly_by_ref_as_loop_counter() { 548 int i = 0; 549 auto l = [&]() mutable { 550 for (i = 0; i < 10; ++i) { 551 clang_analyzer_numTimesReached(); // expected-warning {{4}} 552 } 553 }; 554 } 555 556 557 void test_escaping_on_var_before_switch_case_no_crash(int c) { 558 // https://github.com/llvm/llvm-project/issues/68819 559 switch (c) { 560 int i; // no-crash: The declaration of `i` is found here. 561 case 0: { 562 for (i = 0; i < 16; i++) {} 563 break; 564 } 565 } 566 } 567