1 // RUN: %clang_analyze_cc1 %s -std=c++14 \ 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++14 -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++14 \ 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++14 -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 // debug-note-re@-1{{{{^}}Tracking condition 'ConvertsToBool()'{{$}}}} 153 // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}} 154 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} 155 *x = 5; // expected-warning{{Dereference of null pointer}} 156 // expected-note@-1{{Dereference of null pointer}} 157 } 158 159 } // end of namespace variable_declaration_in_condition 160 161 namespace note_from_different_but_not_nested_stackframe { 162 163 void nullptrDeref(int *ptr, bool True) { 164 if (True) // expected-note-re{{{{^}}'True' is true{{$}}}} 165 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 166 // debug-note-re@-2{{{{^}}Tracking condition 'True'{{$}}}} 167 *ptr = 5; 168 // expected-note@-1{{Dereference of null pointer (loaded from variable 'ptr')}} 169 // expected-warning@-2{{Dereference of null pointer (loaded from variable 'ptr')}} 170 } 171 172 void f() { 173 int *ptr = nullptr; 174 // expected-note-re@-1{{{{^}}'ptr' initialized to a null pointer value{{$}}}} 175 bool True = true; 176 nullptrDeref(ptr, True); 177 // expected-note-re@-1{{{{^}}Passing null pointer value via 1st parameter 'ptr'{{$}}}} 178 // expected-note-re@-2{{{{^}}Calling 'nullptrDeref'{{$}}}} 179 } 180 181 } // end of namespace note_from_different_but_not_nested_stackframe 182 183 namespace important_returning_pointer_loaded_from { 184 bool coin(); 185 186 int *getIntPtr(); 187 188 void storeValue(int **i) { 189 *i = getIntPtr(); // tracking-note-re{{{{^}}Value assigned to 'i', which participates in a condition later{{$}}}} 190 } 191 192 int *conjurePointer() { 193 int *i; 194 storeValue(&i); // tracking-note-re{{{{^}}Calling 'storeValue'{{$}}}} 195 // tracking-note-re@-1{{{{^}}Returning from 'storeValue'{{$}}}} 196 return i; // tracking-note-re{{{{^}}Returning pointer (loaded from 'i'), which participates in a condition later{{$}}}} 197 } 198 199 void f(int *ptr) { 200 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 201 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 202 ; 203 if (!conjurePointer()) 204 // tracking-note-re@-1{{{{^}}Calling 'conjurePointer'{{$}}}} 205 // tracking-note-re@-2{{{{^}}Returning from 'conjurePointer'{{$}}}} 206 // debug-note-re@-3{{{{^}}Tracking condition '!conjurePointer()'{{$}}}} 207 // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}} 208 // expected-note-re@-5{{{{^}}Taking true branch{{$}}}} 209 *ptr = 5; // expected-warning{{Dereference of null pointer}} 210 // expected-note@-1{{Dereference of null pointer}} 211 } 212 } // end of namespace important_returning_pointer_loaded_from 213 214 namespace unimportant_returning_pointer_loaded_from { 215 bool coin(); 216 217 int *getIntPtr(); 218 219 int *conjurePointer() { 220 int *i = getIntPtr(); 221 return i; 222 } 223 224 void f(int *ptr) { 225 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 226 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 227 ; 228 if (!conjurePointer()) 229 // debug-note-re@-1{{{{^}}Tracking condition '!conjurePointer()'{{$}}}} 230 // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}} 231 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} 232 *ptr = 5; // expected-warning{{Dereference of null pointer}} 233 // expected-note@-1{{Dereference of null pointer}} 234 } 235 } // end of namespace unimportant_returning_pointer_loaded_from 236 237 namespace unimportant_returning_pointer_loaded_from_through_cast { 238 239 void *conjure(); 240 241 int *cast(void *P) { 242 return static_cast<int *>(P); 243 } 244 245 void f() { 246 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 247 248 if (cast(conjure())) 249 // debug-note-re@-1{{{{^}}Tracking condition 'cast(conjure())'{{$}}}} 250 // expected-note-re@-2{{{{^}}Assuming the condition is false{{$}}}} 251 // expected-note-re@-3{{{{^}}Taking false branch{{$}}}} 252 return; 253 *x = 5; // expected-warning{{Dereference of null pointer}} 254 // expected-note@-1{{Dereference of null pointer}} 255 } 256 257 } // end of namespace unimportant_returning_pointer_loaded_from_through_cast 258 259 namespace unimportant_returning_value_note { 260 bool coin(); 261 262 bool flipCoin() { return coin(); } 263 264 void i(int *ptr) { 265 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 266 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 267 ; 268 if (!flipCoin()) 269 // debug-note-re@-1{{{{^}}Tracking condition '!flipCoin()'{{$}}}} 270 // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}} 271 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} 272 *ptr = 5; // expected-warning{{Dereference of null pointer}} 273 // expected-note@-1{{Dereference of null pointer}} 274 } 275 } // end of namespace unimportant_returning_value_note 276 277 namespace important_returning_value_note { 278 bool coin(); 279 280 bool flipCoin() { 281 if (coin()) // tracking-note-re{{{{^}}Assuming the condition is false{{$}}}} 282 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 283 // debug-note-re@-2{{{{^}}Tracking condition 'coin()'{{$}}}} 284 return true; 285 return coin(); // tracking-note-re{{{{^}}Returning value, which participates in a condition later{{$}}}} 286 } 287 288 void i(int *ptr) { 289 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 290 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 291 ; 292 if (!flipCoin()) 293 // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}} 294 // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}} 295 // debug-note-re@-3{{{{^}}Tracking condition '!flipCoin()'{{$}}}} 296 // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}} 297 // expected-note-re@-5{{{{^}}Taking true branch{{$}}}} 298 *ptr = 5; // expected-warning{{Dereference of null pointer}} 299 // expected-note@-1{{Dereference of null pointer}} 300 } 301 } // end of namespace important_returning_value_note 302 303 namespace important_returning_value_note_in_linear_function { 304 bool coin(); 305 306 struct super_complicated_template_hackery { 307 static constexpr bool value = false; 308 }; 309 310 bool flipCoin() { 311 if (super_complicated_template_hackery::value) 312 // tracking-note-re@-1{{{{^}}'value' is false{{$}}}} 313 // tracking-note-re@-2{{{{^}}Taking false branch{{$}}}} 314 return true; 315 return coin(); // tracking-note-re{{{{^}}Returning value, which participates in a condition later{{$}}}} 316 } 317 318 void i(int *ptr) { 319 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} 320 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 321 ; 322 if (!flipCoin()) 323 // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}} 324 // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}} 325 // debug-note-re@-3{{{{^}}Tracking condition '!flipCoin()'{{$}}}} 326 // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}} 327 // expected-note-re@-5{{{{^}}Taking true branch{{$}}}} 328 *ptr = 5; // expected-warning{{Dereference of null pointer}} 329 // expected-note@-1{{Dereference of null pointer}} 330 } 331 } // end of namespace important_returning_value_note_in_linear_function 332 333 namespace tracked_condition_is_only_initialized { 334 int getInt(); 335 336 void f() { 337 int flag = getInt(); 338 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 339 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 340 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 341 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 342 *x = 5; // expected-warning{{Dereference of null pointer}} 343 // expected-note@-1{{Dereference of null pointer}} 344 } 345 } // end of namespace tracked_condition_is_only_initialized 346 347 namespace tracked_condition_written_in_same_stackframe { 348 int flag; 349 int getInt(); 350 351 void f(int y) { 352 y = 1; 353 flag = y; 354 355 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 356 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}} 357 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 358 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 359 *x = 5; // expected-warning{{Dereference of null pointer}} 360 // expected-note@-1{{Dereference of null pointer}} 361 } 362 } // end of namespace tracked_condition_written_in_same_stackframe 363 364 namespace tracked_condition_written_in_nested_stackframe { 365 int flag; 366 int getInt(); 367 368 void foo() { 369 int y; 370 y = 1; 371 flag = y; // tracking-note-re{{{{^}}The value 1 is assigned to 'flag', which participates in a condition later{{$}}}} 372 } 373 374 void f(int y) { 375 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 376 377 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 378 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 379 380 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}} 381 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 382 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 383 *x = 5; // expected-warning{{Dereference of null pointer}} 384 // expected-note@-1{{Dereference of null pointer}} 385 } 386 } // end of namespace tracked_condition_written_in_nested_stackframe 387 388 namespace condition_written_in_nested_stackframe_before_assignment { 389 int flag = 0; 390 int getInt(); 391 392 void foo() { 393 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 394 } 395 396 void f() { 397 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 398 int y = 0; 399 400 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 401 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 402 y = flag; 403 404 if (y) // expected-note-re{{{{^}}Assuming 'y' is not equal to 0{{$}}}} 405 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 406 // debug-note-re@-2{{{{^}}Tracking condition 'y'{{$}}}} 407 *x = 5; // expected-warning{{Dereference of null pointer}} 408 // expected-note@-1{{Dereference of null pointer}} 409 } 410 } // end of namespace condition_written_in_nested_stackframe_before_assignment 411 412 namespace dont_explain_foreach_loops { 413 414 struct Iterator { 415 int *pos; 416 bool operator!=(Iterator other) const { 417 return pos && other.pos && pos != other.pos; 418 } 419 int operator*(); 420 Iterator operator++(); 421 }; 422 423 struct Container { 424 Iterator begin(); 425 Iterator end(); 426 }; 427 428 void f(Container Cont) { 429 int flag = 0; 430 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 431 for (int i : Cont) 432 if (i) // expected-note-re {{{{^}}Assuming 'i' is not equal to 0{{$}}}} 433 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 434 // debug-note-re@-2{{{{^}}Tracking condition 'i'{{$}}}} 435 flag = i; 436 437 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 438 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 439 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 440 *x = 5; // expected-warning{{Dereference of null pointer}} 441 // expected-note@-1{{Dereference of null pointer}} 442 } 443 } // end of namespace dont_explain_foreach_loops 444 445 namespace condition_lambda_capture_by_reference_last_write { 446 int getInt(); 447 448 [[noreturn]] void halt(); 449 450 void f(int flag) { 451 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 452 453 auto lambda = [&flag]() { 454 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 455 }; 456 457 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} 458 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} 459 460 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 461 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 462 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 463 *x = 5; // expected-warning{{Dereference of null pointer}} 464 // expected-note@-1{{Dereference of null pointer}} 465 } 466 } // end of namespace condition_lambda_capture_by_reference_last_write 467 468 namespace condition_lambda_capture_by_value_assumption { 469 int getInt(); 470 471 [[noreturn]] void halt(); 472 473 void bar(int &flag) { 474 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 475 } 476 477 void f(int flag) { 478 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 479 480 auto lambda = [flag]() { 481 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} 482 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 483 halt(); 484 }; 485 486 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} 487 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} 488 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} 489 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} 490 491 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 492 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 493 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 494 *x = 5; // expected-warning{{Dereference of null pointer}} 495 // expected-note@-1{{Dereference of null pointer}} 496 } 497 } // end of namespace condition_lambda_capture_by_value_assumption 498 499 namespace condition_lambda_capture_by_reference_assumption { 500 int getInt(); 501 502 [[noreturn]] void halt(); 503 504 void bar(int &flag) { 505 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 506 } 507 508 void f(int flag) { 509 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 510 511 auto lambda = [&flag]() { 512 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} 513 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 514 halt(); 515 }; 516 517 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} 518 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} 519 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} 520 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} 521 522 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 523 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 524 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 525 *x = 5; // expected-warning{{Dereference of null pointer}} 526 // expected-note@-1{{Dereference of null pointer}} 527 } 528 } // end of namespace condition_lambda_capture_by_reference_assumption 529 530 namespace collapse_point_not_in_condition_bool { 531 532 [[noreturn]] void halt(); 533 534 void check(bool b) { 535 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is true, which participates in a condition later{{$}}}} 536 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 537 halt(); 538 } 539 540 void f(bool flag) { 541 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 542 543 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}} 544 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}} 545 546 if (flag) // expected-note-re{{{{^}}'flag' is true{{$}}}} 547 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 548 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 549 *x = 5; // expected-warning{{Dereference of null pointer}} 550 // expected-note@-1{{Dereference of null pointer}} 551 } 552 } // end of namespace collapse_point_not_in_condition_bool 553 554 namespace collapse_point_not_in_condition { 555 556 [[noreturn]] void halt(); 557 558 void assert(int b) { 559 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}} 560 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 561 halt(); 562 } 563 564 void f(int flag) { 565 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 566 567 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}} 568 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}} 569 570 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 571 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 572 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 573 *x = 5; // expected-warning{{Dereference of null pointer}} 574 // expected-note@-1{{Dereference of null pointer}} 575 } 576 577 } // end of namespace collapse_point_not_in_condition 578 579 namespace unimportant_write_before_collapse_point { 580 581 [[noreturn]] void halt(); 582 583 void assert(int b) { 584 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}} 585 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 586 halt(); 587 } 588 int getInt(); 589 590 void f(int flag) { 591 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 592 593 flag = getInt(); 594 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}} 595 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}} 596 597 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 598 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 599 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 600 *x = 5; // expected-warning{{Dereference of null pointer}} 601 // expected-note@-1{{Dereference of null pointer}} 602 } 603 604 } // end of namespace unimportant_write_before_collapse_point 605 606 namespace dont_crash_on_nonlogical_binary_operator { 607 608 void f6(int x) { 609 int a[20]; 610 if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}} 611 // expected-note@-1{{Taking true branch}} 612 if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}} 613 // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}} 614 } 615 616 } // end of namespace dont_crash_on_nonlogical_binary_operator 617 618 namespace collapse_point_not_in_condition_binary_op { 619 620 [[noreturn]] void halt(); 621 622 void check(int b) { 623 if (b == 1) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 1, which participates in a condition later{{$}}}} 624 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 625 halt(); 626 } 627 628 void f(int flag) { 629 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 630 631 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}} 632 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}} 633 634 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 635 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 636 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 637 *x = 5; // expected-warning{{Dereference of null pointer}} 638 // expected-note@-1{{Dereference of null pointer}} 639 } 640 641 } // end of namespace collapse_point_not_in_condition_binary_op 642 643 namespace collapse_point_not_in_condition_as_field { 644 645 [[noreturn]] void halt(); 646 struct IntWrapper { 647 int b; 648 IntWrapper(); 649 650 void check() { 651 if (!b) // tracking-note-re{{{{^}}Assuming field 'b' is not equal to 0, which participates in a condition later{{$}}}} 652 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} 653 halt(); 654 return; 655 } 656 }; 657 658 void f(IntWrapper i) { 659 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 660 661 i.check(); // tracking-note-re{{{{^}}Calling 'IntWrapper::check'{{$}}}} 662 // tracking-note-re@-1{{{{^}}Returning from 'IntWrapper::check'{{$}}}} 663 if (i.b) // expected-note-re{{{{^}}Field 'b' is not equal to 0{{$}}}} 664 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 665 // debug-note-re@-2{{{{^}}Tracking condition 'i.b'{{$}}}} 666 *x = 5; // expected-warning{{Dereference of null pointer}} 667 // expected-note@-1{{Dereference of null pointer}} 668 } 669 670 } // end of namespace collapse_point_not_in_condition_as_field 671 672 namespace assignemnt_in_condition_in_nested_stackframe { 673 int flag; 674 675 bool coin(); 676 677 [[noreturn]] void halt(); 678 679 void foo() { 680 if ((flag = coin())) 681 // tracking-note-re@-1{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 682 // tracking-note-re@-2{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} 683 // tracking-note-re@-3{{{{^}}Taking true branch{{$}}}} 684 return; 685 halt(); 686 return; 687 } 688 689 void f() { 690 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 691 692 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 693 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 694 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 695 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 696 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 697 *x = 5; // expected-warning{{Dereference of null pointer}} 698 // expected-note@-1{{Dereference of null pointer}} 699 } 700 } // end of namespace assignemnt_in_condition_in_nested_stackframe 701 702 namespace condition_variable_less { 703 int flag; 704 705 bool coin(); 706 707 [[noreturn]] void halt(); 708 709 void foo() { 710 if (flag > 0) 711 // tracking-note-re@-1{{{{^}}Assuming 'flag' is > 0, which participates in a condition later{{$}}}} 712 // tracking-note-re@-2{{{{^}}Taking true branch{{$}}}} 713 return; 714 halt(); 715 return; 716 } 717 718 void f() { 719 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 720 721 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} 722 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} 723 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} 724 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 725 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 726 *x = 5; // expected-warning{{Dereference of null pointer}} 727 // expected-note@-1{{Dereference of null pointer}} 728 } 729 } // end of namespace condition_variable_less 730 731 namespace dont_track_assertlike_conditions { 732 733 extern void __assert_fail(__const char *__assertion, __const char *__file, 734 unsigned int __line, __const char *__function) 735 __attribute__((__noreturn__)); 736 #define assert(expr) \ 737 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) 738 739 int getInt(); 740 741 int cond1; 742 743 void bar() { 744 cond1 = getInt(); 745 } 746 747 void f(int flag) { 748 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 749 750 flag = getInt(); 751 752 bar(); 753 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 754 // expected-note-re@-1{{{{^}}'?' condition is true{{$}}}} 755 756 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 757 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 758 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 759 *x = 5; // expected-warning{{Dereference of null pointer}} 760 // expected-note@-1{{Dereference of null pointer}} 761 } 762 763 #undef assert 764 } // end of namespace dont_track_assertlike_conditions 765 766 namespace dont_track_assertlike_and_conditions { 767 768 extern void __assert_fail(__const char *__assertion, __const char *__file, 769 unsigned int __line, __const char *__function) 770 __attribute__((__noreturn__)); 771 #define assert(expr) \ 772 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) 773 774 int getInt(); 775 776 int cond1; 777 int cond2; 778 779 void bar() { 780 cond1 = getInt(); 781 cond2 = getInt(); 782 } 783 784 void f(int flag) { 785 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 786 787 flag = getInt(); 788 789 bar(); 790 assert(cond1 && cond2); 791 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 792 // expected-note-re@-2{{{{^}}Assuming 'cond2' is not equal to 0{{$}}}} 793 // expected-note-re@-3{{{{^}}'?' condition is true{{$}}}} 794 // expected-note-re@-4{{{{^}}Left side of '&&' is true{{$}}}} 795 796 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 797 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 798 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 799 *x = 5; // expected-warning{{Dereference of null pointer}} 800 // expected-note@-1{{Dereference of null pointer}} 801 } 802 803 #undef assert 804 } // end of namespace dont_track_assertlike_and_conditions 805 806 namespace dont_track_assertlike_or_conditions { 807 808 extern void __assert_fail(__const char *__assertion, __const char *__file, 809 unsigned int __line, __const char *__function) 810 __attribute__((__noreturn__)); 811 #define assert(expr) \ 812 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) 813 814 int getInt(); 815 816 int cond1; 817 int cond2; 818 819 void bar() { 820 cond1 = getInt(); 821 cond2 = getInt(); 822 } 823 824 void f(int flag) { 825 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 826 827 flag = getInt(); 828 829 bar(); 830 assert(cond1 || cond2); 831 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 832 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}} 833 834 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 835 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 836 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 837 *x = 5; // expected-warning{{Dereference of null pointer}} 838 // expected-note@-1{{Dereference of null pointer}} 839 } 840 841 #undef assert 842 } // end of namespace dont_track_assertlike_or_conditions 843 844 namespace dont_track_assert2like_conditions { 845 846 extern void __assert_fail(__const char *__assertion, __const char *__file, 847 unsigned int __line, __const char *__function) 848 __attribute__((__noreturn__)); 849 #define assert(expr) \ 850 do { \ 851 if (!(expr)) \ 852 __assert_fail(#expr, __FILE__, __LINE__, __func__); \ 853 } while (0) 854 855 int getInt(); 856 857 int cond1; 858 859 void bar() { 860 cond1 = getInt(); 861 } 862 863 void f(int flag) { 864 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 865 866 flag = getInt(); 867 868 bar(); 869 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 870 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} 871 // expected-note-re@-2{{{{^}}Loop condition is false. Exiting loop{{$}}}} 872 873 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 874 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 875 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 876 *x = 5; // expected-warning{{Dereference of null pointer}} 877 // expected-note@-1{{Dereference of null pointer}} 878 } 879 880 #undef assert 881 } // end of namespace dont_track_assert2like_conditions 882 883 namespace dont_track_assert2like_and_conditions { 884 885 extern void __assert_fail(__const char *__assertion, __const char *__file, 886 unsigned int __line, __const char *__function) 887 __attribute__((__noreturn__)); 888 #define assert(expr) \ 889 do { \ 890 if (!(expr)) \ 891 __assert_fail(#expr, __FILE__, __LINE__, __func__); \ 892 } while (0) 893 894 int getInt(); 895 896 int cond1; 897 int cond2; 898 899 void bar() { 900 cond1 = getInt(); 901 cond2 = getInt(); 902 } 903 904 void f(int flag) { 905 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 906 907 flag = getInt(); 908 909 bar(); 910 assert(cond1 && cond2); 911 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 912 // expected-note-re@-2{{{{^}}Left side of '&&' is true{{$}}}} 913 // expected-note-re@-3{{{{^}}Assuming the condition is false{{$}}}} 914 // expected-note-re@-4{{{{^}}Taking false branch{{$}}}} 915 // expected-note-re@-5{{{{^}}Loop condition is false. Exiting loop{{$}}}} 916 917 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 918 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 919 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 920 *x = 5; // expected-warning{{Dereference of null pointer}} 921 // expected-note@-1{{Dereference of null pointer}} 922 } 923 924 #undef assert 925 } // end of namespace dont_track_assert2like_and_conditions 926 927 namespace dont_track_assert2like_or_conditions { 928 929 extern void __assert_fail(__const char *__assertion, __const char *__file, 930 unsigned int __line, __const char *__function) 931 __attribute__((__noreturn__)); 932 #define assert(expr) \ 933 do { \ 934 if (!(expr)) \ 935 __assert_fail(#expr, __FILE__, __LINE__, __func__); \ 936 } while (0) 937 938 int getInt(); 939 940 int cond1; 941 int cond2; 942 943 void bar() { 944 cond1 = getInt(); 945 cond2 = getInt(); 946 } 947 948 void f(int flag) { 949 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} 950 951 flag = getInt(); 952 953 bar(); 954 assert(cond1 || cond2); 955 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} 956 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}} 957 // expected-note-re@-3{{{{^}}Taking false branch{{$}}}} 958 // expected-note-re@-4{{{{^}}Loop condition is false. Exiting loop{{$}}}} 959 960 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} 961 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} 962 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 963 *x = 5; // expected-warning{{Dereference of null pointer}} 964 // expected-note@-1{{Dereference of null pointer}} 965 } 966 967 #undef assert 968 } // end of namespace dont_track_assert2like_or_conditions 969 970 namespace only_track_the_evaluated_condition { 971 972 bool coin(); 973 974 void bar(int &flag) { 975 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} 976 } 977 978 void bar2(int &flag2) { 979 flag2 = coin(); 980 } 981 982 void f(int *x) { 983 if (x) // expected-note-re{{{{^}}Assuming 'x' is null{{$}}}} 984 // debug-note-re@-1{{{{^}}Tracking condition 'x'{{$}}}} 985 // expected-note-re@-2{{{{^}}Taking false branch{{$}}}} 986 return; 987 988 int flag, flag2; 989 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} 990 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} 991 bar2(flag2); 992 993 if (flag && flag2) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} 994 // expected-note-re@-1{{{{^}}Left side of '&&' is false{{$}}}} 995 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} 996 return; 997 998 *x = 5; // expected-warning{{Dereference of null pointer}} 999 // expected-note@-1{{Dereference of null pointer}} 1000 } 1001 1002 } // end of namespace only_track_the_evaluated_condition 1003