1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\ 2 // RUN: -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\ 3 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 4 // RUN: -std=c++11 -verify %s 5 6 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\ 7 // RUN: -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\ 8 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 9 // RUN: -std=c++20 -verify %s 10 11 #include "Inputs/system-header-simulator-cxx.h" 12 13 void clang_analyzer_warnIfReached(); 14 void clang_analyzer_numTimesReached(); 15 void clang_analyzer_eval(bool); 16 void clang_analyzer_warnOnDeadSymbol(int *); 17 18 void derefAfterMove(std::unique_ptr<int> P) { 19 std::unique_ptr<int> Q = std::move(P); 20 if (Q) 21 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 22 *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}} 23 if (P) 24 clang_analyzer_warnIfReached(); // no-warning 25 // TODO: Report a null dereference (instead). 26 *P.get() = 1; // expected-warning {{Method called on moved-from object 'P' [cplusplus.Move]}} 27 // expected-warning@-1 {{Dereference of null pointer [core.NullDereference]}} 28 } 29 30 // Don't crash when attempting to model a call with unknown callee. 31 namespace testUnknownCallee { 32 struct S { 33 void foo(); 34 }; 35 void bar(S *s, void (S::*func)(void)) { 36 (s->*func)(); // no-crash 37 } 38 } // namespace testUnknownCallee 39 40 class A { 41 public: 42 A(){}; 43 void foo(); 44 }; 45 46 A *return_null() { 47 return nullptr; 48 } 49 50 void derefAfterValidCtr() { 51 std::unique_ptr<A> P(new A()); 52 clang_analyzer_numTimesReached(); // expected-warning {{1}} 53 P->foo(); // No warning. 54 } 55 56 void derefOfUnknown(std::unique_ptr<A> P) { 57 P->foo(); // No warning. 58 } 59 60 void derefAfterDefaultCtr() { 61 std::unique_ptr<A> P; 62 clang_analyzer_numTimesReached(); // expected-warning {{1}} 63 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 64 } 65 66 void derefAfterCtrWithNull() { 67 std::unique_ptr<A> P(nullptr); 68 clang_analyzer_numTimesReached(); // expected-warning {{1}} 69 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 70 } 71 72 void derefAfterCtrWithNullVariable() { 73 A *InnerPtr = nullptr; 74 std::unique_ptr<A> P(InnerPtr); 75 clang_analyzer_numTimesReached(); // expected-warning {{1}} 76 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 77 } 78 79 void derefAfterRelease() { 80 std::unique_ptr<A> P(new A()); 81 P.release(); 82 clang_analyzer_numTimesReached(); // expected-warning {{1}} 83 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 84 } 85 86 void derefAfterReset() { 87 std::unique_ptr<A> P(new A()); 88 P.reset(); 89 clang_analyzer_numTimesReached(); // expected-warning {{1}} 90 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 91 } 92 93 void derefAfterResetWithNull() { 94 std::unique_ptr<A> P(new A()); 95 P.reset(nullptr); 96 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 97 } 98 99 void derefAfterResetWithNonNull() { 100 std::unique_ptr<A> P; 101 P.reset(new A()); 102 clang_analyzer_numTimesReached(); // expected-warning {{1}} 103 P->foo(); // No warning. 104 } 105 106 void derefAfterReleaseAndResetWithNonNull() { 107 std::unique_ptr<A> P(new A()); 108 P.release(); 109 P.reset(new A()); 110 P->foo(); // No warning. 111 } 112 113 void derefOnReleasedNullRawPtr() { 114 std::unique_ptr<A> P; 115 A *AP = P.release(); 116 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 117 } 118 119 void derefOnReleasedValidRawPtr() { 120 std::unique_ptr<A> P(new A()); 121 A *AP = P.release(); 122 AP->foo(); // No warning. 123 } 124 125 void pass_smart_ptr_by_ref(std::unique_ptr<A> &a); 126 void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a); 127 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a); 128 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a); 129 void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a); 130 void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a); 131 132 void regioninvalidationWithPassByRef() { 133 std::unique_ptr<A> P; 134 pass_smart_ptr_by_ref(P); 135 P->foo(); // no-warning 136 } 137 138 void regioninvalidationWithPassByCostRef() { 139 std::unique_ptr<A> P; 140 pass_smart_ptr_by_const_ref(P); 141 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 142 } 143 144 void regioninvalidationWithPassByRValueRef() { 145 std::unique_ptr<A> P; 146 pass_smart_ptr_by_rvalue_ref(std::move(P)); 147 P->foo(); // no-warning 148 } 149 150 void regioninvalidationWithPassByConstRValueRef() { 151 std::unique_ptr<A> P; 152 pass_smart_ptr_by_const_rvalue_ref(std::move(P)); 153 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 154 } 155 156 void regioninvalidationWithPassByPtr() { 157 std::unique_ptr<A> P; 158 pass_smart_ptr_by_ptr(&P); 159 P->foo(); 160 } 161 162 void regioninvalidationWithPassByConstPtr() { 163 std::unique_ptr<A> P; 164 pass_smart_ptr_by_const_ptr(&P); 165 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 166 } 167 168 struct StructWithSmartPtr { 169 std::unique_ptr<A> P; 170 }; 171 172 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a); 173 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a); 174 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a); 175 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a); 176 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a); 177 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a); 178 179 void regioninvalidationWithinStructPassByRef() { 180 StructWithSmartPtr S; 181 pass_struct_with_smart_ptr_by_ref(S); 182 S.P->foo(); // no-warning 183 } 184 185 void regioninvalidationWithinStructPassByConstRef() { 186 StructWithSmartPtr S; 187 pass_struct_with_smart_ptr_by_const_ref(S); 188 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 189 } 190 191 void regioninvalidationWithinStructPassByRValueRef() { 192 StructWithSmartPtr S; 193 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S)); 194 S.P->foo(); // no-warning 195 } 196 197 void regioninvalidationWithinStructPassByConstRValueRef() { 198 StructWithSmartPtr S; 199 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S)); 200 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 201 } 202 203 void regioninvalidationWithinStructPassByPtr() { 204 StructWithSmartPtr S; 205 pass_struct_with_smart_ptr_by_ptr(&S); 206 S.P->foo(); // no-warning 207 } 208 209 void regioninvalidationWithinStructPassByConstPtr() { 210 StructWithSmartPtr S; 211 pass_struct_with_smart_ptr_by_const_ptr(&S); 212 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 213 } 214 215 void derefAfterAssignment() { 216 { 217 std::unique_ptr<A> P(new A()); 218 std::unique_ptr<A> Q; 219 Q = std::move(P); 220 Q->foo(); // no-warning 221 } 222 { 223 std::unique_ptr<A> P; 224 std::unique_ptr<A> Q; 225 Q = std::move(P); 226 Q->foo(); // expected-warning {{Dereference of null smart pointer 'Q' [alpha.cplusplus.SmartPtr]}} 227 } 228 } 229 230 void derefOnSwappedNullPtr() { 231 std::unique_ptr<A> P(new A()); 232 std::unique_ptr<A> PNull; 233 P.swap(PNull); 234 PNull->foo(); // No warning. 235 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 236 } 237 238 void derefOnFirstStdSwappedNullPtr() { 239 std::unique_ptr<A> P; 240 std::unique_ptr<A> PNull; 241 std::swap(P, PNull); 242 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 243 } 244 245 void derefOnSecondStdSwappedNullPtr() { 246 std::unique_ptr<A> P; 247 std::unique_ptr<A> PNull; 248 std::swap(P, PNull); 249 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 250 } 251 252 void derefOnSwappedValidPtr() { 253 std::unique_ptr<A> P(new A()); 254 std::unique_ptr<A> PValid(new A()); 255 P.swap(PValid); 256 (*P).foo(); // No warning. 257 PValid->foo(); // No warning. 258 std::swap(P, PValid); 259 P->foo(); // No warning. 260 PValid->foo(); // No warning. 261 } 262 263 void derefOnRawPtrFromGetOnNullPtr() { 264 std::unique_ptr<A> P; 265 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 266 } 267 268 void derefOnRawPtrFromGetOnValidPtr() { 269 std::unique_ptr<A> P(new A()); 270 P.get()->foo(); // No warning. 271 } 272 273 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { 274 P.get()->foo(); // No warning. 275 } 276 277 void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P) { 278 A *X = P.get(); 279 A *Y = P.get(); 280 clang_analyzer_eval(X == Y); // expected-warning{{TRUE}} 281 if (!X) { 282 Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 283 } 284 } 285 286 void derefOnMovedFromValidPtr() { 287 std::unique_ptr<A> PToMove(new A()); 288 std::unique_ptr<A> P; 289 P = std::move(PToMove); 290 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 291 } 292 293 void derefOnMovedToNullPtr() { 294 std::unique_ptr<A> PToMove(new A()); 295 std::unique_ptr<A> P; 296 P = std::move(PToMove); // No note. 297 P->foo(); // No warning. 298 } 299 300 void derefOnNullPtrGotMovedFromValidPtr() { 301 std::unique_ptr<A> P(new A()); 302 std::unique_ptr<A> PToMove; 303 P = std::move(PToMove); 304 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 305 } 306 307 void derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove) { 308 std::unique_ptr<A> P; 309 P = std::move(PToMove); 310 P->foo(); // No warning. 311 } 312 313 void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) { 314 std::unique_ptr<A> P; 315 P = std::move(PToMove); 316 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 317 } 318 319 void derefOnAssignedNullPtrToNullSmartPtr() { 320 std::unique_ptr<A> P; 321 P = nullptr; 322 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 323 } 324 325 void derefOnAssignedZeroToNullSmartPtr() { 326 std::unique_ptr<A> P(new A()); 327 P = 0; 328 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 329 } 330 331 void derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P) { 332 P = nullptr; 333 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 334 } 335 336 std::unique_ptr<A> &&returnRValRefOfUniquePtr(); 337 338 void drefOnAssignedNullFromMethodPtrValidSmartPtr() { 339 std::unique_ptr<A> P(new A()); 340 P = returnRValRefOfUniquePtr(); 341 P->foo(); // No warning. 342 } 343 344 void derefMoveConstructedWithValidPtr() { 345 std::unique_ptr<A> PToMove(new A()); 346 std::unique_ptr<A> P(std::move(PToMove)); 347 P->foo(); // No warning. 348 } 349 350 void derefMoveConstructedWithNullPtr() { 351 std::unique_ptr<A> PToMove; 352 std::unique_ptr<A> P(std::move(PToMove)); 353 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 354 } 355 356 void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) { 357 std::unique_ptr<A> P(std::move(PToMove)); 358 P->foo(); // No warning. 359 } 360 361 void derefValidPtrMovedToConstruct() { 362 std::unique_ptr<A> PToMove(new A()); 363 std::unique_ptr<A> P(std::move(PToMove)); 364 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 365 } 366 367 void derefNullPtrMovedToConstruct() { 368 std::unique_ptr<A> PToMove; 369 std::unique_ptr<A> P(std::move(PToMove)); 370 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 371 } 372 373 void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) { 374 std::unique_ptr<A> P(std::move(PToMove)); 375 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 376 } 377 378 std::unique_ptr<A> &&functionReturnsRValueRef(); 379 380 void derefMoveConstructedWithRValueRefReturn() { 381 std::unique_ptr<A> P(functionReturnsRValueRef()); 382 P->foo(); // No warning. 383 } 384 385 void derefConditionOnNullPtr() { 386 std::unique_ptr<A> P; 387 if (P) 388 P->foo(); // No warning. 389 else 390 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 391 } 392 393 void derefConditionOnNotNullPtr() { 394 std::unique_ptr<A> P; 395 if (!P) 396 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 397 } 398 399 void derefConditionOnValidPtr() { 400 std::unique_ptr<A> P(new A()); 401 std::unique_ptr<A> PNull; 402 if (P) 403 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 404 } 405 406 void derefConditionOnNotValidPtr() { 407 std::unique_ptr<A> P(new A()); 408 std::unique_ptr<A> PNull; 409 if (!P) 410 PNull->foo(); // No warning. 411 } 412 413 void derefConditionOnUnKnownPtr(std::unique_ptr<A> P) { 414 if (P) 415 P->foo(); // No warning. 416 else 417 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 418 } 419 420 void derefOnValidPtrAfterReset(std::unique_ptr<A> P) { 421 P.reset(new A()); 422 if (!P) 423 P->foo(); // No warning. 424 else 425 P->foo(); // No warning. 426 } 427 428 void innerPointerSymbolLiveness() { 429 std::unique_ptr<int> P(new int()); 430 clang_analyzer_warnOnDeadSymbol(P.get()); 431 int *RP = P.release(); 432 } // expected-warning{{SYMBOL DEAD}} 433 434 void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) { 435 if (P) { 436 int *X = P.get(); 437 clang_analyzer_warnOnDeadSymbol(X); 438 } 439 } // expected-warning{{SYMBOL DEAD}} 440 441 void getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) { 442 int *X = P.get(); 443 clang_analyzer_warnOnDeadSymbol(X); 444 int Y; 445 if (!P) { 446 Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}} 447 // expected-warning@-1 {{SYMBOL DEAD}} 448 } 449 } 450 451 int derefConditionOnUnKnownPtr(int *q) { 452 std::unique_ptr<int> P(q); 453 if (P) 454 return *P; // No warning. 455 else 456 return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 457 } 458 459 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) { 460 A *RP = P.get(); 461 if (!RP) { 462 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 463 } 464 } 465 466 // The following is a silly function, 467 // but serves to test if we are picking out 468 // standard comparision functions from custom ones. 469 template <typename T> 470 bool operator<(std::unique_ptr<T> &x, double d); 471 472 void uniquePtrComparision(std::unique_ptr<int> unknownPtr) { 473 auto ptr = std::unique_ptr<int>(new int(13)); 474 auto nullPtr = std::unique_ptr<int>(); 475 auto otherPtr = std::unique_ptr<int>(new int(29)); 476 477 clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}} 478 clang_analyzer_eval(ptr > ptr); // expected-warning{{FALSE}} 479 clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}} 480 481 clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}} 482 clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}} 483 484 clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}} 485 clang_analyzer_eval(ptr > nullPtr); // expected-warning{{TRUE}} 486 487 clang_analyzer_eval(ptr != nullptr); // expected-warning{{TRUE}} 488 clang_analyzer_eval(nullPtr != nullptr); // expected-warning{{FALSE}} 489 clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}} 490 } 491 492 void uniquePtrComparisionStateSplitting(std::unique_ptr<int> unknownPtr) { 493 auto ptr = std::unique_ptr<int>(new int(13)); 494 495 clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}} 496 // expected-warning@-1{{FALSE}} 497 } 498 499 void uniquePtrComparisionDifferingTypes(std::unique_ptr<int> unknownPtr) { 500 auto ptr = std::unique_ptr<int>(new int(13)); 501 auto nullPtr = std::unique_ptr<A>(); 502 auto otherPtr = std::unique_ptr<double>(new double(3.14)); 503 504 clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}} 505 clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}} 506 507 clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}} 508 clang_analyzer_eval(ptr > nullPtr); // expected-warning{{TRUE}} 509 510 clang_analyzer_eval(ptr != nullptr); // expected-warning{{TRUE}} 511 clang_analyzer_eval(nullPtr != nullptr); // expected-warning{{FALSE}} 512 clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}} 513 } 514 515 #if __cplusplus >= 202002L 516 517 void testOstreamOverload(std::unique_ptr<int> P) { 518 auto &Cout = std::cout; 519 auto &PtrCout = std::cout << P; 520 auto &StringCout = std::cout << "hello"; 521 // We are testing the fact that in our modelling of 522 // operator<<(basic_ostream<T1> &, const unique_ptr<T2> &) 523 // we set the return SVal to the SVal of the ostream arg. 524 clang_analyzer_eval(&Cout == &PtrCout); // expected-warning {{TRUE}} 525 // FIXME: Technically, they should be equal, 526 // that hasn't been modelled yet. 527 clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}} 528 } 529 530 int glob; 531 void testOstreamDoesntInvalidateGlobals(std::unique_ptr<int> P) { 532 int x = glob; 533 std::cout << P; 534 int y = glob; 535 clang_analyzer_eval(x == y); // expected-warning {{TRUE}} 536 } 537 538 #endif 539 540 // The following test isn't really a "smart-ptr" test 541 // It came up during a bug fix (D106296) 542 void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) { 543 // This should NOT crash. 544 bar(true, false); 545 } 546