1077 lines · cpp
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=core6 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-DEBUG12 13// CHECK-INVALID-DEBUG: (frontend): invalid input for analyzer-config option14// CHECK-INVALID-DEBUG-SAME: 'track-conditions-debug', that expects15// CHECK-INVALID-DEBUG-SAME: 'track-conditions' to also be enabled16//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=core23 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=core28 29namespace example_1 {30int flag;31bool coin();32 33void foo() {34 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}35}36 37void 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_157 58namespace example_2 {59int flag;60bool coin();61 62void foo() {63 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}64}65 66void 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_288 89namespace global_variable_invalidation {90int flag;91bool coin();92 93void 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 99int bar;100 101void 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_invalidation119 120namespace variable_declaration_in_condition {121bool coin();122 123bool foo() {124 return coin();125}126 127int bar;128 129void 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_condition140 141namespace conversion_to_bool {142bool coin();143 144struct ConvertsToBool {145 operator bool() const { return coin(); }146};147 148void 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_bool159 160namespace note_from_different_but_not_nested_stackframe {161 162void 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 171void 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_stackframe181 182namespace important_returning_pointer_loaded_from {183bool coin();184 185int *getIntPtr();186 187void storeValue(int **i) {188 *i = getIntPtr();189}190 191int *conjurePointer() {192 int *i;193 storeValue(&i);194 return i;195}196 197void 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_from208 209namespace unimportant_returning_pointer_loaded_from {210bool coin();211 212int *getIntPtr();213 214int *conjurePointer() {215 int *i = getIntPtr();216 return i;217}218 219void 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_from230 231namespace unimportant_returning_pointer_loaded_from_through_cast {232 233void *conjure();234 235int *cast(void *P) {236 return static_cast<int *>(P);237}238 239void 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_cast251 252namespace unimportant_returning_value_note {253bool coin();254 255bool flipCoin() { return coin(); }256 257void 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_note268 269namespace important_returning_value_note {270bool coin();271 272bool flipCoin() {273 if (coin())274 return true;275 return coin();276}277 278void 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_note289 290namespace important_returning_value_note_in_linear_function {291bool coin();292int flag;293 294struct super_complicated_template_hackery {295 static constexpr bool value = false;296};297 298void 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 306void 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_function322 323namespace tracked_condition_is_only_initialized {324int getInt();325 326void 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_initialized336 337namespace tracked_condition_written_in_same_stackframe {338int flag;339int getInt();340 341void 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_stackframe353 354namespace tracked_condition_written_in_nested_stackframe {355int flag;356int getInt();357 358void 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 364void 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_stackframe377 378namespace condition_written_in_nested_stackframe_before_assignment {379int flag = 0;380int getInt();381 382void foo() {383 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}384}385 386void 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_assignment401 402namespace dont_explain_foreach_loops {403 404struct 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 413struct Container {414 Iterator begin();415 Iterator end();416};417 418void 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_loops434 435namespace condition_lambda_capture_by_reference_last_write {436int getInt();437 438[[noreturn]] void halt();439 440void 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_write457 458namespace condition_lambda_capture_by_value_assumption {459int getInt();460 461[[noreturn]] void halt();462 463void bar(int &flag) {464 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}465}466 467void 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_assumption488 489namespace condition_lambda_capture_by_reference_assumption {490int getInt();491 492[[noreturn]] void halt();493 494void bar(int &flag) {495 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}496}497 498void 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_assumption519 520namespace collapse_point_not_in_condition_bool {521 522[[noreturn]] void halt();523 524void 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 530void 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_bool543 544namespace collapse_point_not_in_condition {545 546[[noreturn]] void halt();547 548void 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 554void 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_condition568 569namespace unimportant_write_before_collapse_point {570 571[[noreturn]] void halt();572 573void 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}578int getInt();579 580void 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_point595 596namespace dont_crash_on_nonlogical_binary_operator {597 598void 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_operator607 608namespace collapse_point_not_in_condition_binary_op {609 610[[noreturn]] void halt();611 612void 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 618void 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_op632 633namespace collapse_point_not_in_condition_as_field {634 635[[noreturn]] void halt();636struct 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 648void 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_field661 662namespace assignemnt_in_condition_in_nested_stackframe {663int flag;664 665bool coin();666 667[[noreturn]] void halt();668 669void 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 679void 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_stackframe691 692namespace condition_variable_less {693int flag;694 695bool coin();696 697[[noreturn]] void halt();698 699void 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 708void 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_less720 721namespace dont_track_assertlike_conditions {722 723extern 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 729int getInt();730 731int cond1;732 733void bar() {734 cond1 = getInt();735}736 737void 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 assert754} // end of namespace dont_track_assertlike_conditions755 756namespace dont_track_assertlike_and_conditions {757 758extern 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 764int getInt();765 766int cond1;767int cond2;768 769void bar() {770 cond1 = getInt();771 cond2 = getInt();772}773 774void 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 assert794} // end of namespace dont_track_assertlike_and_conditions795 796namespace dont_track_assertlike_or_conditions {797 798extern 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 804int getInt();805 806int cond1;807int cond2;808 809void bar() {810 cond1 = getInt();811 cond2 = getInt();812}813 814void 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 assert832} // end of namespace dont_track_assertlike_or_conditions833 834namespace dont_track_assert2like_conditions {835 836extern 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 845int getInt();846 847int cond1;848 849void bar() {850 cond1 = getInt();851}852 853void 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 assert871} // end of namespace dont_track_assert2like_conditions872 873namespace dont_track_assert2like_and_conditions {874 875extern 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 884int getInt();885 886int cond1;887int cond2;888 889void bar() {890 cond1 = getInt();891 cond2 = getInt();892}893 894void 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 assert915} // end of namespace dont_track_assert2like_and_conditions916 917namespace dont_track_assert2like_or_conditions {918 919extern 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 928int getInt();929 930int cond1;931int cond2;932 933void bar() {934 cond1 = getInt();935 cond2 = getInt();936}937 938void 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 assert958} // end of namespace dont_track_assert2like_or_conditions959 960namespace only_track_the_evaluated_condition {961 962bool coin();963 964void bar(int &flag) {965 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}966}967 968void bar2(int &flag2) {969 flag2 = coin();970}971 972void 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_condition993 994namespace operator_call_in_condition_point {995 996struct Error {997 explicit operator bool() {998 return true;999 }1000};1001 1002Error couldFail();1003 1004void 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_point1012 1013namespace cxx17_ifinit__operator_call_in_condition_point {1014 1015struct Error {1016 explicit operator bool() {1017 return true;1018 }1019};1020 1021Error couldFail();1022 1023void 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_point1031 1032namespace funcion_call_in_condition_point {1033 1034int alwaysTrue() {1035 return true;1036}1037 1038void 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_point1046 1047namespace funcion_call_negated_in_condition_point {1048 1049int alwaysFalse() {1050 return false;1051}1052 1053void 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_point1061 1062namespace funcion_call_part_of_logical_expr_in_condition_point {1063 1064int alwaysFalse() {1065 return false;1066}1067 1068void 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_point1077