brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.3 KiB · b762992 Raw
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