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 #include "Inputs/system-header-simulator-cxx.h" 7 8 void clang_analyzer_warnIfReached(); 9 void clang_analyzer_numTimesReached(); 10 void clang_analyzer_eval(bool); 11 void clang_analyzer_warnOnDeadSymbol(int *); 12 derefAfterMove(std::unique_ptr<int> P)13void derefAfterMove(std::unique_ptr<int> P) { 14 std::unique_ptr<int> Q = std::move(P); 15 if (Q) 16 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 17 *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}} 18 if (P) 19 clang_analyzer_warnIfReached(); // no-warning 20 // TODO: Report a null dereference (instead). 21 *P.get() = 1; // expected-warning {{Method called on moved-from object 'P' [cplusplus.Move]}} 22 // expected-warning@-1 {{Dereference of null pointer [core.NullDereference]}} 23 } 24 25 // Don't crash when attempting to model a call with unknown callee. 26 namespace testUnknownCallee { 27 struct S { 28 void foo(); 29 }; bar(S * s,void (S::* func)(void))30void bar(S *s, void (S::*func)(void)) { 31 (s->*func)(); // no-crash 32 } 33 } // namespace testUnknownCallee 34 35 class A { 36 public: A()37 A(){}; 38 void foo(); 39 }; 40 return_null()41A *return_null() { 42 return nullptr; 43 } 44 derefAfterValidCtr()45void derefAfterValidCtr() { 46 std::unique_ptr<A> P(new A()); 47 clang_analyzer_numTimesReached(); // expected-warning {{1}} 48 P->foo(); // No warning. 49 } 50 derefOfUnknown(std::unique_ptr<A> P)51void derefOfUnknown(std::unique_ptr<A> P) { 52 P->foo(); // No warning. 53 } 54 derefAfterDefaultCtr()55void derefAfterDefaultCtr() { 56 std::unique_ptr<A> P; 57 clang_analyzer_numTimesReached(); // expected-warning {{1}} 58 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 59 } 60 derefAfterCtrWithNull()61void derefAfterCtrWithNull() { 62 std::unique_ptr<A> P(nullptr); 63 clang_analyzer_numTimesReached(); // expected-warning {{1}} 64 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 65 } 66 derefAfterCtrWithNullVariable()67void derefAfterCtrWithNullVariable() { 68 A *InnerPtr = nullptr; 69 std::unique_ptr<A> P(InnerPtr); 70 clang_analyzer_numTimesReached(); // expected-warning {{1}} 71 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 72 } 73 derefAfterRelease()74void derefAfterRelease() { 75 std::unique_ptr<A> P(new A()); 76 P.release(); 77 clang_analyzer_numTimesReached(); // expected-warning {{1}} 78 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 79 } 80 derefAfterReset()81void derefAfterReset() { 82 std::unique_ptr<A> P(new A()); 83 P.reset(); 84 clang_analyzer_numTimesReached(); // expected-warning {{1}} 85 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 86 } 87 derefAfterResetWithNull()88void derefAfterResetWithNull() { 89 std::unique_ptr<A> P(new A()); 90 P.reset(nullptr); 91 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 92 } 93 derefAfterResetWithNonNull()94void derefAfterResetWithNonNull() { 95 std::unique_ptr<A> P; 96 P.reset(new A()); 97 clang_analyzer_numTimesReached(); // expected-warning {{1}} 98 P->foo(); // No warning. 99 } 100 derefAfterReleaseAndResetWithNonNull()101void derefAfterReleaseAndResetWithNonNull() { 102 std::unique_ptr<A> P(new A()); 103 P.release(); 104 P.reset(new A()); 105 P->foo(); // No warning. 106 } 107 derefOnReleasedNullRawPtr()108void derefOnReleasedNullRawPtr() { 109 std::unique_ptr<A> P; 110 A *AP = P.release(); 111 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 112 } 113 derefOnReleasedValidRawPtr()114void derefOnReleasedValidRawPtr() { 115 std::unique_ptr<A> P(new A()); 116 A *AP = P.release(); 117 AP->foo(); // No warning. 118 } 119 120 void pass_smart_ptr_by_ref(std::unique_ptr<A> &a); 121 void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a); 122 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a); 123 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a); 124 void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a); 125 void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a); 126 regioninvalidationWithPassByRef()127void regioninvalidationWithPassByRef() { 128 std::unique_ptr<A> P; 129 pass_smart_ptr_by_ref(P); 130 P->foo(); // no-warning 131 } 132 regioninvalidationWithPassByCostRef()133void regioninvalidationWithPassByCostRef() { 134 std::unique_ptr<A> P; 135 pass_smart_ptr_by_const_ref(P); 136 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 137 } 138 regioninvalidationWithPassByRValueRef()139void regioninvalidationWithPassByRValueRef() { 140 std::unique_ptr<A> P; 141 pass_smart_ptr_by_rvalue_ref(std::move(P)); 142 P->foo(); // no-warning 143 } 144 regioninvalidationWithPassByConstRValueRef()145void regioninvalidationWithPassByConstRValueRef() { 146 std::unique_ptr<A> P; 147 pass_smart_ptr_by_const_rvalue_ref(std::move(P)); 148 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 149 } 150 regioninvalidationWithPassByPtr()151void regioninvalidationWithPassByPtr() { 152 std::unique_ptr<A> P; 153 pass_smart_ptr_by_ptr(&P); 154 P->foo(); 155 } 156 regioninvalidationWithPassByConstPtr()157void regioninvalidationWithPassByConstPtr() { 158 std::unique_ptr<A> P; 159 pass_smart_ptr_by_const_ptr(&P); 160 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 161 } 162 163 struct StructWithSmartPtr { 164 std::unique_ptr<A> P; 165 }; 166 167 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a); 168 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a); 169 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a); 170 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a); 171 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a); 172 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a); 173 regioninvalidationWithinStructPassByRef()174void regioninvalidationWithinStructPassByRef() { 175 StructWithSmartPtr S; 176 pass_struct_with_smart_ptr_by_ref(S); 177 S.P->foo(); // no-warning 178 } 179 regioninvalidationWithinStructPassByConstRef()180void regioninvalidationWithinStructPassByConstRef() { 181 StructWithSmartPtr S; 182 pass_struct_with_smart_ptr_by_const_ref(S); 183 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 184 } 185 regioninvalidationWithinStructPassByRValueRef()186void regioninvalidationWithinStructPassByRValueRef() { 187 StructWithSmartPtr S; 188 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S)); 189 S.P->foo(); // no-warning 190 } 191 regioninvalidationWithinStructPassByConstRValueRef()192void regioninvalidationWithinStructPassByConstRValueRef() { 193 StructWithSmartPtr S; 194 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S)); 195 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 196 } 197 regioninvalidationWithinStructPassByPtr()198void regioninvalidationWithinStructPassByPtr() { 199 StructWithSmartPtr S; 200 pass_struct_with_smart_ptr_by_ptr(&S); 201 S.P->foo(); // no-warning 202 } 203 regioninvalidationWithinStructPassByConstPtr()204void regioninvalidationWithinStructPassByConstPtr() { 205 StructWithSmartPtr S; 206 pass_struct_with_smart_ptr_by_const_ptr(&S); 207 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 208 } 209 derefAfterAssignment()210void derefAfterAssignment() { 211 { 212 std::unique_ptr<A> P(new A()); 213 std::unique_ptr<A> Q; 214 Q = std::move(P); 215 Q->foo(); // no-warning 216 } 217 { 218 std::unique_ptr<A> P; 219 std::unique_ptr<A> Q; 220 Q = std::move(P); 221 Q->foo(); // expected-warning {{Dereference of null smart pointer 'Q' [alpha.cplusplus.SmartPtr]}} 222 } 223 } 224 derefOnSwappedNullPtr()225void derefOnSwappedNullPtr() { 226 std::unique_ptr<A> P(new A()); 227 std::unique_ptr<A> PNull; 228 P.swap(PNull); 229 PNull->foo(); // No warning. 230 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 231 } 232 derefOnFirstStdSwappedNullPtr()233void derefOnFirstStdSwappedNullPtr() { 234 std::unique_ptr<A> P; 235 std::unique_ptr<A> PNull; 236 std::swap(P, PNull); 237 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 238 } 239 derefOnSecondStdSwappedNullPtr()240void derefOnSecondStdSwappedNullPtr() { 241 std::unique_ptr<A> P; 242 std::unique_ptr<A> PNull; 243 std::swap(P, PNull); 244 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 245 } 246 derefOnSwappedValidPtr()247void derefOnSwappedValidPtr() { 248 std::unique_ptr<A> P(new A()); 249 std::unique_ptr<A> PValid(new A()); 250 P.swap(PValid); 251 (*P).foo(); // No warning. 252 PValid->foo(); // No warning. 253 std::swap(P, PValid); 254 P->foo(); // No warning. 255 PValid->foo(); // No warning. 256 } 257 derefOnRawPtrFromGetOnNullPtr()258void derefOnRawPtrFromGetOnNullPtr() { 259 std::unique_ptr<A> P; 260 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 261 } 262 derefOnRawPtrFromGetOnValidPtr()263void derefOnRawPtrFromGetOnValidPtr() { 264 std::unique_ptr<A> P(new A()); 265 P.get()->foo(); // No warning. 266 } 267 derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P)268void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { 269 P.get()->foo(); // No warning. 270 } 271 derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P)272void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P) { 273 A *X = P.get(); 274 A *Y = P.get(); 275 clang_analyzer_eval(X == Y); // expected-warning{{TRUE}} 276 if (!X) { 277 Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 278 } 279 } 280 derefOnMovedFromValidPtr()281void derefOnMovedFromValidPtr() { 282 std::unique_ptr<A> PToMove(new A()); 283 std::unique_ptr<A> P; 284 P = std::move(PToMove); 285 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 286 } 287 derefOnMovedToNullPtr()288void derefOnMovedToNullPtr() { 289 std::unique_ptr<A> PToMove(new A()); 290 std::unique_ptr<A> P; 291 P = std::move(PToMove); // No note. 292 P->foo(); // No warning. 293 } 294 derefOnNullPtrGotMovedFromValidPtr()295void derefOnNullPtrGotMovedFromValidPtr() { 296 std::unique_ptr<A> P(new A()); 297 std::unique_ptr<A> PToMove; 298 P = std::move(PToMove); 299 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 300 } 301 derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove)302void derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove) { 303 std::unique_ptr<A> P; 304 P = std::move(PToMove); 305 P->foo(); // No warning. 306 } 307 derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove)308void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) { 309 std::unique_ptr<A> P; 310 P = std::move(PToMove); 311 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 312 } 313 derefOnAssignedNullPtrToNullSmartPtr()314void derefOnAssignedNullPtrToNullSmartPtr() { 315 std::unique_ptr<A> P; 316 P = nullptr; 317 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 318 } 319 derefOnAssignedZeroToNullSmartPtr()320void derefOnAssignedZeroToNullSmartPtr() { 321 std::unique_ptr<A> P(new A()); 322 P = 0; 323 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 324 } 325 derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P)326void derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P) { 327 P = nullptr; 328 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 329 } 330 331 std::unique_ptr<A> &&returnRValRefOfUniquePtr(); 332 drefOnAssignedNullFromMethodPtrValidSmartPtr()333void drefOnAssignedNullFromMethodPtrValidSmartPtr() { 334 std::unique_ptr<A> P(new A()); 335 P = returnRValRefOfUniquePtr(); 336 P->foo(); // No warning. 337 } 338 derefMoveConstructedWithValidPtr()339void derefMoveConstructedWithValidPtr() { 340 std::unique_ptr<A> PToMove(new A()); 341 std::unique_ptr<A> P(std::move(PToMove)); 342 P->foo(); // No warning. 343 } 344 derefMoveConstructedWithNullPtr()345void derefMoveConstructedWithNullPtr() { 346 std::unique_ptr<A> PToMove; 347 std::unique_ptr<A> P(std::move(PToMove)); 348 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 349 } 350 derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove)351void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) { 352 std::unique_ptr<A> P(std::move(PToMove)); 353 P->foo(); // No warning. 354 } 355 derefValidPtrMovedToConstruct()356void derefValidPtrMovedToConstruct() { 357 std::unique_ptr<A> PToMove(new A()); 358 std::unique_ptr<A> P(std::move(PToMove)); 359 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 360 } 361 derefNullPtrMovedToConstruct()362void derefNullPtrMovedToConstruct() { 363 std::unique_ptr<A> PToMove; 364 std::unique_ptr<A> P(std::move(PToMove)); 365 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 366 } 367 derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove)368void derefUnknownPtrMovedToConstruct(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 std::unique_ptr<A> &&functionReturnsRValueRef(); 374 derefMoveConstructedWithRValueRefReturn()375void derefMoveConstructedWithRValueRefReturn() { 376 std::unique_ptr<A> P(functionReturnsRValueRef()); 377 P->foo(); // No warning. 378 } 379 derefConditionOnNullPtr()380void derefConditionOnNullPtr() { 381 std::unique_ptr<A> P; 382 if (P) 383 P->foo(); // No warning. 384 else 385 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 386 } 387 derefConditionOnNotNullPtr()388void derefConditionOnNotNullPtr() { 389 std::unique_ptr<A> P; 390 if (!P) 391 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 392 } 393 derefConditionOnValidPtr()394void derefConditionOnValidPtr() { 395 std::unique_ptr<A> P(new A()); 396 std::unique_ptr<A> PNull; 397 if (P) 398 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 399 } 400 derefConditionOnNotValidPtr()401void derefConditionOnNotValidPtr() { 402 std::unique_ptr<A> P(new A()); 403 std::unique_ptr<A> PNull; 404 if (!P) 405 PNull->foo(); // No warning. 406 } 407 derefConditionOnUnKnownPtr(std::unique_ptr<A> P)408void derefConditionOnUnKnownPtr(std::unique_ptr<A> P) { 409 if (P) 410 P->foo(); // No warning. 411 else 412 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 413 } 414 derefOnValidPtrAfterReset(std::unique_ptr<A> P)415void derefOnValidPtrAfterReset(std::unique_ptr<A> P) { 416 P.reset(new A()); 417 if (!P) 418 P->foo(); // No warning. 419 else 420 P->foo(); // No warning. 421 } 422 innerPointerSymbolLiveness()423void innerPointerSymbolLiveness() { 424 std::unique_ptr<int> P(new int()); 425 clang_analyzer_warnOnDeadSymbol(P.get()); 426 int *RP = P.release(); 427 } // expected-warning{{SYMBOL DEAD}} 428 boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P)429void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) { 430 if (P) { 431 int *X = P.get(); 432 clang_analyzer_warnOnDeadSymbol(X); 433 } 434 } // expected-warning{{SYMBOL DEAD}} 435 getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P)436void getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) { 437 int *X = P.get(); 438 clang_analyzer_warnOnDeadSymbol(X); 439 int Y; 440 if (!P) { 441 Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}} 442 // expected-warning@-1 {{SYMBOL DEAD}} 443 } 444 } 445 derefConditionOnUnKnownPtr(int * q)446int derefConditionOnUnKnownPtr(int *q) { 447 std::unique_ptr<int> P(q); 448 if (P) 449 return *P; // No warning. 450 else 451 return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 452 } 453 derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P)454void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) { 455 A *RP = P.get(); 456 if (!RP) { 457 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 458 } 459 } 460