1 // RUN: %clang_analyze_cc1 %s -std=c++17 \ 2 // RUN: -verify=expected,tracking \ 3 // RUN: -analyzer-config track-conditions=true \ 4 // RUN: -analyzer-output=text \ 5 // RUN: -analyzer-checker=core 6 7 // RUN: not %clang_analyze_cc1 -std=c++17 -verify %s \ 8 // RUN: -analyzer-checker=core \ 9 // RUN: -analyzer-config track-conditions=false \ 10 // RUN: -analyzer-config track-conditions-debug=true \ 11 // RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-DEBUG 12 13 // CHECK-INVALID-DEBUG: (frontend): invalid input for analyzer-config option 14 // CHECK-INVALID-DEBUG-SAME: 'track-conditions-debug', that expects 15 // CHECK-INVALID-DEBUG-SAME: 'track-conditions' to also be enabled 16 // 17 // RUN: %clang_analyze_cc1 %s -std=c++17 \ 18 // RUN: -verify=expected,tracking,debug \ 19 // RUN: -analyzer-config track-conditions=true \ 20 // RUN: -analyzer-config track-conditions-debug=true \ 21 // RUN: -analyzer-output=text \ 22 // RUN: -analyzer-checker=core 23 24 // RUN: %clang_analyze_cc1 %s -std=c++17 -verify \ 25 // RUN: -analyzer-output=text \ 26 // RUN: -analyzer-config track-conditions=false \ 27 // RUN: -analyzer-checker=core 28 29 namespace example_1 { 30 int flag; 31 bool coin(); 32 33 void foo() { 34 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 35 } 36 37 void test() { 38 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 39 flag = 1; 40 41 foo(); // TODO: Add nodes here about flag's value being invalidated. 42 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} 43 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 44 x = new int; 45 46 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 47 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 48 49 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 50 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 51 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 52 53 *x = 5; // expected-warning{{Dereference of null pointer}} 54 // expected-note@-1{{Dereference of null pointer}} 55 } 56 } // end of namespace example_1 57 58 namespace example_2 { 59 int flag; 60 bool coin(); 61 62 void foo() { 63 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 64 } 65 66 void test() { 67 int *x = 0; 68 flag = 1; 69 70 foo(); 71 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} 72 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 73 x = new int; 74 75 x = 0; // expected-note-re{{{{^}}Null pointer value stored to 'x'{{$}}}} 76 77 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 78 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 79 80 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 81 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 82 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 83 84 *x = 5; // expected-warning{{Dereference of null pointer}} 85 // expected-note@-1{{Dereference of null pointer}} 86 } 87 } // end of namespace example_2 88 89 namespace global_variable_invalidation { 90 int flag; 91 bool coin(); 92 93 void foo() { 94 // coin() could write bar, do it's invalidated. 95 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 96 // tracking-note-re@-1{{{{^}}Value assigned to 'bar', which participates in a condition later{{$}}}} 97 } 98 99 int bar; 100 101 void test() { 102 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 103 flag = 1; 104 105 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 106 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 107 108 if (bar) // expected-note-re {{{{^}}Assuming 'bar' is not equal to 0{{$}}}} 109 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 110 // debug-note-re@-2{{{{^}}Tracking condition 'bar'{{$}}}} 111 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 112 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 113 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 114 115 *x = 5; // expected-warning{{Dereference of null pointer}} 116 // expected-note@-1{{Dereference of null pointer}} 117 } 118 } // end of namespace global_variable_invalidation 119 120 namespace variable_declaration_in_condition { 121 bool coin(); 122 123 bool foo() { 124 return coin(); 125 } 126 127 int bar; 128 129 void test() { 130 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 131 132 if (int flag = foo()) // debug-note-re{{{{^}}Tracking condition 'flag'{{$}}}} 133 // expected-note-re@-1{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 134 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} 135 136 *x = 5; // expected-warning{{Dereference of null pointer}} 137 // expected-note@-1{{Dereference of null pointer}} 138 } 139 } // end of namespace variable_declaration_in_condition 140 141 namespace conversion_to_bool { 142 bool coin(); 143 144 struct ConvertsToBool { 145 operator bool() const { return coin(); } 146 }; 147 148 void test() { 149 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 150 151 if (ConvertsToBool()) 152 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}} 153 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} 154 *x = 5; // expected-warning{{Dereference of null pointer}} 155 // expected-note@-1{{Dereference of null pointer}} 156 } 157 158 } // namespace conversion_to_bool 159 160 namespace note_from_different_but_not_nested_stackframe { 161 162 void nullptrDeref(int *ptr, bool True) { 163 if (True) // expected-note-re{{{{^}}'True' is true{{$}}}} 164 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 165 // debug-note-re@-2{{{{^}}Tracking condition 'True'{{$}}}} 166 *ptr = 5; 167 // expected-note@-1{{Dereference of null pointer (loaded from variable 'ptr')}} 168 // expected-warning@-2{{Dereference of null pointer (loaded from variable 'ptr')}} 169 } 170 171 void f() { 172 int *ptr = nullptr; 173 // expected-note-re@-1{{{{^}}'ptr' initialized to a null pointer value{{$}}}} 174 bool True = true; 175 nullptrDeref(ptr, True); 176 // expected-note-re@-1{{{{^}}Passing null pointer value via 1st parameter 'ptr'{{$}}}} 177 // expected-note-re@-2{{{{^}}Calling 'nullptrDeref'{{$}}}} 178 } 179 180 } // end of namespace note_from_different_but_not_nested_stackframe 181 182 namespace important_returning_pointer_loaded_from { 183 bool coin(); 184 185 int *getIntPtr(); 186 187 void storeValue(int **i) { 188 *i = getIntPtr(); 189 } 190 191 int *conjurePointer() { 192 int *i; 193 storeValue(&i); 194 return i; 195 } 196 197 void f(int *ptr) { 198 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 199 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 200 ; 201 if (!conjurePointer()) 202 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}} 203 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} 204 *ptr = 5; // expected-warning{{Dereference of null pointer}} 205 // expected-note@-1{{Dereference of null pointer}} 206 } 207 } // end of namespace important_returning_pointer_loaded_from 208 209 namespace unimportant_returning_pointer_loaded_from { 210 bool coin(); 211 212 int *getIntPtr(); 213 214 int *conjurePointer() { 215 int *i = getIntPtr(); 216 return i; 217 } 218 219 void f(int *ptr) { 220 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 221 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 222 ; 223 if (!conjurePointer()) 224 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}} 225 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} 226 *ptr = 5; // expected-warning{{Dereference of null pointer}} 227 // expected-note@-1{{Dereference of null pointer}} 228 } 229 } // end of namespace unimportant_returning_pointer_loaded_from 230 231 namespace unimportant_returning_pointer_loaded_from_through_cast { 232 233 void *conjure(); 234 235 int *cast(void *P) { 236 return static_cast<int *>(P); 237 } 238 239 void f() { 240 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 241 242 if (cast(conjure())) 243 // expected-note-re@-1{{{{^}}Assuming the condition is false{{$}}}} 244 // expected-note-re@-2{{{{^}}Taking false branch{{$}}}} 245 return; 246 *x = 5; // expected-warning{{Dereference of null pointer}} 247 // expected-note@-1{{Dereference of null pointer}} 248 } 249 250 } // end of namespace unimportant_returning_pointer_loaded_from_through_cast 251 252 namespace unimportant_returning_value_note { 253 bool coin(); 254 255 bool flipCoin() { return coin(); } 256 257 void i(int *ptr) { 258 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 259 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 260 ; 261 if (!flipCoin()) 262 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}} 263 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} 264 *ptr = 5; // expected-warning{{Dereference of null pointer}} 265 // expected-note@-1{{Dereference of null pointer}} 266 } 267 } // end of namespace unimportant_returning_value_note 268 269 namespace important_returning_value_note { 270 bool coin(); 271 272 bool flipCoin() { 273 if (coin()) 274 return true; 275 return coin(); 276 } 277 278 void i(int *ptr) { 279 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 280 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 281 ; 282 if (!flipCoin()) 283 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}} 284 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} 285 *ptr = 5; // expected-warning{{Dereference of null pointer}} 286 // expected-note@-1{{Dereference of null pointer}} 287 } 288 } // end of namespace important_returning_value_note 289 290 namespace important_returning_value_note_in_linear_function { 291 bool coin(); 292 int flag; 293 294 struct super_complicated_template_hackery { 295 static constexpr bool value = false; 296 }; 297 298 void flipCoin() { 299 if (super_complicated_template_hackery::value) 300 // tracking-note-re@-1{{{{^}}'value' is false{{$}}}} 301 // tracking-note-re@-2{{{{^}}Taking false branch{{$}}}} 302 return; 303 flag = false; // tracking-note-re{{{{^}}The value 0 is assigned to 'flag', which participates in a condition later{{$}}}} 304 } 305 306 void i(int *ptr) { 307 flag = true; 308 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 309 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 310 ; 311 flipCoin(); 312 // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}} 313 // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}} 314 if (!flag) 315 // debug-note-re@-1{{{{^}}Tracking condition '!flag'{{$}}}} 316 // expected-note-re@-2{{{{^}}'flag' is 0{{$}}}} 317 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} 318 *ptr = 5; // expected-warning{{Dereference of null pointer}} 319 // expected-note@-1{{Dereference of null pointer}} 320 } 321 } // end of namespace important_returning_value_note_in_linear_function 322 323 namespace tracked_condition_is_only_initialized { 324 int getInt(); 325 326 void f() { 327 int flag = getInt(); 328 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 329 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 330 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 331 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 332 *x = 5; // expected-warning{{Dereference of null pointer}} 333 // expected-note@-1{{Dereference of null pointer}} 334 } 335 } // end of namespace tracked_condition_is_only_initialized 336 337 namespace tracked_condition_written_in_same_stackframe { 338 int flag; 339 int getInt(); 340 341 void f(int y) { 342 y = 1; 343 flag = y; 344 345 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 346 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}} 347 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 348 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 349 *x = 5; // expected-warning{{Dereference of null pointer}} 350 // expected-note@-1{{Dereference of null pointer}} 351 } 352 } // end of namespace tracked_condition_written_in_same_stackframe 353 354 namespace tracked_condition_written_in_nested_stackframe { 355 int flag; 356 int getInt(); 357 358 void foo() { 359 int y; 360 y = 1; 361 flag = y; // tracking-note-re{{{{^}}The value 1 is assigned to 'flag', which participates in a condition later{{$}}}} 362 } 363 364 void f(int y) { 365 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 366 367 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 368 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 369 370 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}} 371 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 372 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 373 *x = 5; // expected-warning{{Dereference of null pointer}} 374 // expected-note@-1{{Dereference of null pointer}} 375 } 376 } // end of namespace tracked_condition_written_in_nested_stackframe 377 378 namespace condition_written_in_nested_stackframe_before_assignment { 379 int flag = 0; 380 int getInt(); 381 382 void foo() { 383 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 384 } 385 386 void f() { 387 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 388 int y = 0; 389 390 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 391 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 392 y = flag; 393 394 if (y) // expected-note-re{{{{^}}Assuming 'y' is not equal to 0{{$}}}} 395 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 396 // debug-note-re@-2{{{{^}}Tracking condition 'y'{{$}}}} 397 *x = 5; // expected-warning{{Dereference of null pointer}} 398 // expected-note@-1{{Dereference of null pointer}} 399 } 400 } // end of namespace condition_written_in_nested_stackframe_before_assignment 401 402 namespace dont_explain_foreach_loops { 403 404 struct Iterator { 405 int *pos; 406 bool operator!=(Iterator other) const { 407 return pos && other.pos && pos != other.pos; 408 } 409 int operator*(); 410 Iterator operator++(); 411 }; 412 413 struct Container { 414 Iterator begin(); 415 Iterator end(); 416 }; 417 418 void f(Container Cont) { 419 int flag = 0; 420 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 421 for (int i : Cont) 422 if (i) // expected-note-re {{{{^}}Assuming 'i' is not equal to 0{{$}}}} 423 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 424 // debug-note-re@-2{{{{^}}Tracking condition 'i'{{$}}}} 425 flag = i; 426 427 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 428 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 429 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 430 *x = 5; // expected-warning{{Dereference of null pointer}} 431 // expected-note@-1{{Dereference of null pointer}} 432 } 433 } // end of namespace dont_explain_foreach_loops 434 435 namespace condition_lambda_capture_by_reference_last_write { 436 int getInt(); 437 438 [[noreturn]] void halt(); 439 440 void f(int flag) { 441 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 442 443 auto lambda = [&flag]() { 444 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 445 }; 446 447 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} 448 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} 449 450 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 451 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 452 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 453 *x = 5; // expected-warning{{Dereference of null pointer}} 454 // expected-note@-1{{Dereference of null pointer}} 455 } 456 } // end of namespace condition_lambda_capture_by_reference_last_write 457 458 namespace condition_lambda_capture_by_value_assumption { 459 int getInt(); 460 461 [[noreturn]] void halt(); 462 463 void bar(int &flag) { 464 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 465 } 466 467 void f(int flag) { 468 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 469 470 auto lambda = [flag]() { 471 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} 472 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 473 halt(); 474 }; 475 476 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} 477 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} 478 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} 479 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} 480 481 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 482 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 483 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 484 *x = 5; // expected-warning{{Dereference of null pointer}} 485 // expected-note@-1{{Dereference of null pointer}} 486 } 487 } // end of namespace condition_lambda_capture_by_value_assumption 488 489 namespace condition_lambda_capture_by_reference_assumption { 490 int getInt(); 491 492 [[noreturn]] void halt(); 493 494 void bar(int &flag) { 495 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 496 } 497 498 void f(int flag) { 499 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 500 501 auto lambda = [&flag]() { 502 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} 503 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 504 halt(); 505 }; 506 507 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} 508 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} 509 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} 510 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} 511 512 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 513 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 514 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 515 *x = 5; // expected-warning{{Dereference of null pointer}} 516 // expected-note@-1{{Dereference of null pointer}} 517 } 518 } // end of namespace condition_lambda_capture_by_reference_assumption 519 520 namespace collapse_point_not_in_condition_bool { 521 522 [[noreturn]] void halt(); 523 524 void check(bool b) { 525 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is true, which participates in a condition later{{$}}}} 526 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 527 halt(); 528 } 529 530 void f(bool flag) { 531 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 532 533 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}} 534 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}} 535 536 if (flag) // expected-note-re{{{{^}}'flag' is true{{$}}}} 537 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 538 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 539 *x = 5; // expected-warning{{Dereference of null pointer}} 540 // expected-note@-1{{Dereference of null pointer}} 541 } 542 } // end of namespace collapse_point_not_in_condition_bool 543 544 namespace collapse_point_not_in_condition { 545 546 [[noreturn]] void halt(); 547 548 void assert(int b) { 549 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}} 550 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 551 halt(); 552 } 553 554 void f(int flag) { 555 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 556 557 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}} 558 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}} 559 560 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 561 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 562 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 563 *x = 5; // expected-warning{{Dereference of null pointer}} 564 // expected-note@-1{{Dereference of null pointer}} 565 } 566 567 } // end of namespace collapse_point_not_in_condition 568 569 namespace unimportant_write_before_collapse_point { 570 571 [[noreturn]] void halt(); 572 573 void assert(int b) { 574 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}} 575 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 576 halt(); 577 } 578 int getInt(); 579 580 void f(int flag) { 581 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 582 583 flag = getInt(); 584 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}} 585 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}} 586 587 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 588 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 589 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 590 *x = 5; // expected-warning{{Dereference of null pointer}} 591 // expected-note@-1{{Dereference of null pointer}} 592 } 593 594 } // end of namespace unimportant_write_before_collapse_point 595 596 namespace dont_crash_on_nonlogical_binary_operator { 597 598 void f6(int x) { 599 int a[20]; 600 if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}} 601 // expected-note@-1{{Taking true branch}} 602 if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}} 603 // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}} 604 } 605 606 } // end of namespace dont_crash_on_nonlogical_binary_operator 607 608 namespace collapse_point_not_in_condition_binary_op { 609 610 [[noreturn]] void halt(); 611 612 void check(int b) { 613 if (b == 1) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 1, which participates in a condition later{{$}}}} 614 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 615 halt(); 616 } 617 618 void f(int flag) { 619 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 620 621 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}} 622 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}} 623 624 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 625 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 626 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 627 *x = 5; // expected-warning{{Dereference of null pointer}} 628 // expected-note@-1{{Dereference of null pointer}} 629 } 630 631 } // end of namespace collapse_point_not_in_condition_binary_op 632 633 namespace collapse_point_not_in_condition_as_field { 634 635 [[noreturn]] void halt(); 636 struct IntWrapper { 637 int b; 638 IntWrapper(); 639 640 void check() { 641 if (!b) // tracking-note-re{{{{^}}Assuming field 'b' is not equal to 0, which participates in a condition later{{$}}}} 642 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 643 halt(); 644 return; 645 } 646 }; 647 648 void f(IntWrapper i) { 649 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 650 651 i.check(); // tracking-note-re{{{{^}}Calling 'IntWrapper::check'{{$}}}} 652 // tracking-note-re@-1{{{{^}}Returning from 'IntWrapper::check'{{$}}}} 653 if (i.b) // expected-note-re{{{{^}}Field 'b' is not equal to 0{{$}}}} 654 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 655 // debug-note-re@-2{{{{^}}Tracking condition 'i.b'{{$}}}} 656 *x = 5; // expected-warning{{Dereference of null pointer}} 657 // expected-note@-1{{Dereference of null pointer}} 658 } 659 660 } // end of namespace collapse_point_not_in_condition_as_field 661 662 namespace assignemnt_in_condition_in_nested_stackframe { 663 int flag; 664 665 bool coin(); 666 667 [[noreturn]] void halt(); 668 669 void foo() { 670 if ((flag = coin())) 671 // tracking-note-re@-1{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 672 // tracking-note-re@-2{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} 673 // tracking-note-re@-3{{{{^}}Taking true branch{{$}}}} 674 return; 675 halt(); 676 return; 677 } 678 679 void f() { 680 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 681 682 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 683 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 684 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 685 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 686 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 687 *x = 5; // expected-warning{{Dereference of null pointer}} 688 // expected-note@-1{{Dereference of null pointer}} 689 } 690 } // end of namespace assignemnt_in_condition_in_nested_stackframe 691 692 namespace condition_variable_less { 693 int flag; 694 695 bool coin(); 696 697 [[noreturn]] void halt(); 698 699 void foo() { 700 if (flag > 0) 701 // tracking-note-re@-1{{{{^}}Assuming 'flag' is > 0, which participates in a condition later{{$}}}} 702 // tracking-note-re@-2{{{{^}}Taking true branch{{$}}}} 703 return; 704 halt(); 705 return; 706 } 707 708 void f() { 709 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 710 711 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 712 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 713 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 714 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 715 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 716 *x = 5; // expected-warning{{Dereference of null pointer}} 717 // expected-note@-1{{Dereference of null pointer}} 718 } 719 } // end of namespace condition_variable_less 720 721 namespace dont_track_assertlike_conditions { 722 723 extern void __assert_fail(__const char *__assertion, __const char *__file, 724 unsigned int __line, __const char *__function) 725 __attribute__((__noreturn__)); 726 #define assert(expr) \ 727 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) 728 729 int getInt(); 730 731 int cond1; 732 733 void bar() { 734 cond1 = getInt(); 735 } 736 737 void f(int flag) { 738 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 739 740 flag = getInt(); 741 742 bar(); 743 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 744 // expected-note-re@-1{{{{^}}'?' condition is true{{$}}}} 745 746 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 747 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 748 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 749 *x = 5; // expected-warning{{Dereference of null pointer}} 750 // expected-note@-1{{Dereference of null pointer}} 751 } 752 753 #undef assert 754 } // end of namespace dont_track_assertlike_conditions 755 756 namespace dont_track_assertlike_and_conditions { 757 758 extern void __assert_fail(__const char *__assertion, __const char *__file, 759 unsigned int __line, __const char *__function) 760 __attribute__((__noreturn__)); 761 #define assert(expr) \ 762 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) 763 764 int getInt(); 765 766 int cond1; 767 int cond2; 768 769 void bar() { 770 cond1 = getInt(); 771 cond2 = getInt(); 772 } 773 774 void f(int flag) { 775 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 776 777 flag = getInt(); 778 779 bar(); 780 assert(cond1 && cond2); 781 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 782 // expected-note-re@-2{{{{^}}Assuming 'cond2' is not equal to 0{{$}}}} 783 // expected-note-re@-3{{{{^}}'?' condition is true{{$}}}} 784 // expected-note-re@-4{{{{^}}Left side of '&&' is true{{$}}}} 785 786 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 787 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 788 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 789 *x = 5; // expected-warning{{Dereference of null pointer}} 790 // expected-note@-1{{Dereference of null pointer}} 791 } 792 793 #undef assert 794 } // end of namespace dont_track_assertlike_and_conditions 795 796 namespace dont_track_assertlike_or_conditions { 797 798 extern void __assert_fail(__const char *__assertion, __const char *__file, 799 unsigned int __line, __const char *__function) 800 __attribute__((__noreturn__)); 801 #define assert(expr) \ 802 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) 803 804 int getInt(); 805 806 int cond1; 807 int cond2; 808 809 void bar() { 810 cond1 = getInt(); 811 cond2 = getInt(); 812 } 813 814 void f(int flag) { 815 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 816 817 flag = getInt(); 818 819 bar(); 820 assert(cond1 || cond2); 821 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 822 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}} 823 824 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 825 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 826 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 827 *x = 5; // expected-warning{{Dereference of null pointer}} 828 // expected-note@-1{{Dereference of null pointer}} 829 } 830 831 #undef assert 832 } // end of namespace dont_track_assertlike_or_conditions 833 834 namespace dont_track_assert2like_conditions { 835 836 extern void __assert_fail(__const char *__assertion, __const char *__file, 837 unsigned int __line, __const char *__function) 838 __attribute__((__noreturn__)); 839 #define assert(expr) \ 840 do { \ 841 if (!(expr)) \ 842 __assert_fail(#expr, __FILE__, __LINE__, __func__); \ 843 } while (0) 844 845 int getInt(); 846 847 int cond1; 848 849 void bar() { 850 cond1 = getInt(); 851 } 852 853 void f(int flag) { 854 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 855 856 flag = getInt(); 857 858 bar(); 859 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 860 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 861 // expected-note-re@-2{{{{^}}Loop condition is false. Exiting loop{{$}}}} 862 863 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 864 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 865 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 866 *x = 5; // expected-warning{{Dereference of null pointer}} 867 // expected-note@-1{{Dereference of null pointer}} 868 } 869 870 #undef assert 871 } // end of namespace dont_track_assert2like_conditions 872 873 namespace dont_track_assert2like_and_conditions { 874 875 extern void __assert_fail(__const char *__assertion, __const char *__file, 876 unsigned int __line, __const char *__function) 877 __attribute__((__noreturn__)); 878 #define assert(expr) \ 879 do { \ 880 if (!(expr)) \ 881 __assert_fail(#expr, __FILE__, __LINE__, __func__); \ 882 } while (0) 883 884 int getInt(); 885 886 int cond1; 887 int cond2; 888 889 void bar() { 890 cond1 = getInt(); 891 cond2 = getInt(); 892 } 893 894 void f(int flag) { 895 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 896 897 flag = getInt(); 898 899 bar(); 900 assert(cond1 && cond2); 901 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 902 // expected-note-re@-2{{{{^}}Left side of '&&' is true{{$}}}} 903 // expected-note-re@-3{{{{^}}Assuming the condition is false{{$}}}} 904 // expected-note-re@-4{{{{^}}Taking false branch{{$}}}} 905 // expected-note-re@-5{{{{^}}Loop condition is false. Exiting loop{{$}}}} 906 907 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 908 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 909 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 910 *x = 5; // expected-warning{{Dereference of null pointer}} 911 // expected-note@-1{{Dereference of null pointer}} 912 } 913 914 #undef assert 915 } // end of namespace dont_track_assert2like_and_conditions 916 917 namespace dont_track_assert2like_or_conditions { 918 919 extern void __assert_fail(__const char *__assertion, __const char *__file, 920 unsigned int __line, __const char *__function) 921 __attribute__((__noreturn__)); 922 #define assert(expr) \ 923 do { \ 924 if (!(expr)) \ 925 __assert_fail(#expr, __FILE__, __LINE__, __func__); \ 926 } while (0) 927 928 int getInt(); 929 930 int cond1; 931 int cond2; 932 933 void bar() { 934 cond1 = getInt(); 935 cond2 = getInt(); 936 } 937 938 void f(int flag) { 939 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 940 941 flag = getInt(); 942 943 bar(); 944 assert(cond1 || cond2); 945 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 946 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}} 947 // expected-note-re@-3{{{{^}}Taking false branch{{$}}}} 948 // expected-note-re@-4{{{{^}}Loop condition is false. Exiting loop{{$}}}} 949 950 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 951 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 952 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 953 *x = 5; // expected-warning{{Dereference of null pointer}} 954 // expected-note@-1{{Dereference of null pointer}} 955 } 956 957 #undef assert 958 } // end of namespace dont_track_assert2like_or_conditions 959 960 namespace only_track_the_evaluated_condition { 961 962 bool coin(); 963 964 void bar(int &flag) { 965 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 966 } 967 968 void bar2(int &flag2) { 969 flag2 = coin(); 970 } 971 972 void f(int *x) { 973 if (x) // expected-note-re{{{{^}}Assuming 'x' is null{{$}}}} 974 // debug-note-re@-1{{{{^}}Tracking condition 'x'{{$}}}} 975 // expected-note-re@-2{{{{^}}Taking false branch{{$}}}} 976 return; 977 978 int flag, flag2; 979 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} 980 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} 981 bar2(flag2); 982 983 if (flag && flag2) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} 984 // expected-note-re@-1{{{{^}}Left side of '&&' is false{{$}}}} 985 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 986 return; 987 988 *x = 5; // expected-warning{{Dereference of null pointer}} 989 // expected-note@-1{{Dereference of null pointer}} 990 } 991 992 } // end of namespace only_track_the_evaluated_condition 993 994 namespace operator_call_in_condition_point { 995 996 struct Error { 997 explicit operator bool() { 998 return true; 999 } 1000 }; 1001 1002 Error couldFail(); 1003 1004 void f(int *x) { 1005 x = nullptr; // expected-note {{Null pointer value stored to 'x'}} 1006 if (auto e = couldFail()) // expected-note {{Taking true branch}} 1007 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}} 1008 // expected-note@-1 {{Dereference}} 1009 } 1010 1011 } // namespace operator_call_in_condition_point 1012 1013 namespace cxx17_ifinit__operator_call_in_condition_point { 1014 1015 struct Error { 1016 explicit operator bool() { 1017 return true; 1018 } 1019 }; 1020 1021 Error couldFail(); 1022 1023 void f(int *x) { 1024 x = nullptr; // expected-note {{Null pointer value stored to 'x'}} 1025 if (auto e = couldFail(); e) // expected-note {{Taking true branch}} 1026 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}} 1027 // expected-note@-1 {{Dereference}} 1028 } 1029 1030 } // namespace cxx17_ifinit__operator_call_in_condition_point 1031 1032 namespace funcion_call_in_condition_point { 1033 1034 int alwaysTrue() { 1035 return true; 1036 } 1037 1038 void f(int *x) { 1039 x = nullptr; // expected-note {{Null pointer value stored to 'x'}} 1040 if (alwaysTrue()) // expected-note {{Taking true branch}} 1041 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}} 1042 // expected-note@-1 {{Dereference}} 1043 } 1044 1045 } // namespace funcion_call_in_condition_point 1046 1047 namespace funcion_call_negated_in_condition_point { 1048 1049 int alwaysFalse() { 1050 return false; 1051 } 1052 1053 void f(int *x) { 1054 x = nullptr; // expected-note {{Null pointer value stored to 'x'}} 1055 if (!alwaysFalse()) // expected-note {{Taking true branch}} 1056 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}} 1057 // expected-note@-1 {{Dereference}} 1058 } 1059 1060 } // namespace funcion_call_negated_in_condition_point 1061 1062 namespace funcion_call_part_of_logical_expr_in_condition_point { 1063 1064 int alwaysFalse() { 1065 return false; 1066 } 1067 1068 void f(int *x) { 1069 x = nullptr; // expected-note {{Null pointer value stored to 'x'}} 1070 if (!alwaysFalse() && true) // expected-note {{Taking true branch}} 1071 // expected-note@-1 {{Left side of '&&' is true}} 1072 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}} 1073 // expected-note@-1 {{Dereference}} 1074 } 1075 1076 } // namespace funcion_call_part_of_logical_expr_in_condition_point 1077