// RUN: %clang_analyze_cc1\ // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\ // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ // RUN: -analyzer-output=text -std=c++11 %s -verify=expected #include "Inputs/system-header-simulator-cxx.h" class A { public: A(){}; void foo(); }; A *return_null() { return nullptr; } void derefAfterDefaultCtr() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefAfterCtrWithNull() { A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} std::unique_ptr P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}} *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefAfterCtrWithNullVariable() { A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} std::unique_ptr P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefAfterRelease() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} // FIXME: should mark region as uninteresting after release, so above note will not be there P.release(); // expected-note {{Smart pointer 'P' is released and set to null}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefAfterReset() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefAfterResetWithNull() { A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} P.reset(NullInnerPtr); // expected-note {{Smart pointer 'P' reset using a null value}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } // FIXME: Fix this test when support is added for tracking raw pointer // and mark the smart pointer as interesting based on that and add tags. void derefOnReleasedNullRawPtr() { std::unique_ptr P; // FIXME: add note "Default constructed smart pointer 'P' is null" A *AP = P.release(); // expected-note {{'AP' initialized to a null pointer value}} AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} // expected-note@-1{{Called C++ object pointer is null}} } void derefOnSwappedNullPtr() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} P.swap(PNull); // expected-note {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} PNull->foo(); // No warning. (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } // FIXME: Fix this test when "std::swap" is modeled seperately. void derefOnStdSwappedNullPtr() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:979 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} // expected-note@-1 {{Calling 'swap'}} // expected-note@-2 {{Returning from 'swap'}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } struct StructWithSmartPtr { // expected-note {{Default constructed smart pointer 'S.P' is null}} std::unique_ptr P; }; void derefAfterDefaultCtrInsideStruct() { StructWithSmartPtr S; // expected-note {{Calling implicit default constructor for 'StructWithSmartPtr'}} // expected-note@-1 {{Returning from default constructor for 'StructWithSmartPtr'}} S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'S.P'}} } void noNoteTagsForNonInterestingRegion() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} std::unique_ptr P1; // No note. std::unique_ptr P2; // No note. P1.release(); // No note. P1.reset(); // No note. P1.swap(P2); // No note. P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefOnRawPtrFromGetOnNullPtr() { std::unique_ptr P; // FIXME: add note "Default constructed smart pointer 'P' is null" P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} // expected-note@-1 {{Called C++ object pointer is null}} } void derefOnRawPtrFromGetOnValidPtr() { std::unique_ptr P(new A()); P.get()->foo(); // No warning. } void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr P) { P.get()->foo(); // No warning. } void derefOnMovedFromValidPtr() { std::unique_ptr PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}} // FIXME: above note should go away once we fix marking region not interested. std::unique_ptr P; P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}} } void derefOnMovedToNullPtr() { std::unique_ptr PToMove(new A()); std::unique_ptr P; P = std::move(PToMove); // No note. P->foo(); // No warning. } void derefOnNullPtrGotMovedFromValidPtr() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} // FIXME: above note should go away once we fix marking region not interested. std::unique_ptr PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} P = std::move(PToMove); // expected-note {{A null pointer value is moved to 'P'}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'P'}} } void derefOnMovedUnknownPtr(std::unique_ptr PToMove) { std::unique_ptr P; P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}} PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}} } void derefOnAssignedNullPtrToNullSmartPtr() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} P = nullptr; // expected-note {{Smart pointer 'P' is assigned to null}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'P'}} } void derefOnAssignedZeroToNullSmartPtr() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} // FIXME: above note should go away once we fix marking region not interested. P = 0; // expected-note {{Smart pointer 'P' is assigned to null}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'P'}} } void derefMoveConstructedWithNullPtr() { std::unique_ptr PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} std::unique_ptr P(std::move(PToMove)); // expected-note {{A null pointer value is moved to 'P'}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefValidPtrMovedToConstruct() { std::unique_ptr PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}} // FIXME: above note should go away once we fix marking region not interested. std::unique_ptr P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} } void derefNullPtrMovedToConstruct() { std::unique_ptr PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} // FIXME: above note should go away once we fix marking region not interested. std::unique_ptr P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} } void derefUnknownPtrMovedToConstruct(std::unique_ptr PToMove) { std::unique_ptr P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}} PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} } void derefConditionOnNullPtrFalseBranch() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} if (P) { // expected-note {{Taking false branch}} P->foo(); // No warning. } else { P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } } void derefConditionOnNullPtrTrueBranch() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} if (!P) { // expected-note {{Taking true branch}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } } void derefConditionOnValidPtrTrueBranch() { std::unique_ptr P(new A()); std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} if (P) { // expected-note {{Taking true branch}} PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PNull'}} } else { PNull->foo(); // No warning } } void derefConditionOnValidPtrFalseBranch() { std::unique_ptr P(new A()); std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} if (!P) { // expected-note {{Taking false branch}} PNull->foo(); // No warning } else { PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PNull'}} } } void derefConditionOnNotValidPtr() { std::unique_ptr P(new A()); std::unique_ptr PNull; if (!P) PNull->foo(); // No warning. } void derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr P) { std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} if (!P) { // expected-note {{Taking true branch}} // expected-note@-1{{Assuming smart pointer 'P' is null}} PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PNull'}} } } void derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr P) { std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} if (P) { // expected-note {{Taking true branch}} // expected-note@-1{{Assuming smart pointer 'P' is non-null}} PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'PNull'}} } } void derefOnValidPtrAfterReset(std::unique_ptr P) { P.reset(new A()); if (!P) P->foo(); // No warning. else P->foo(); // No warning. } struct S { std::unique_ptr P; void foo() { if (!P) { // No-note because foo() is pruned return; } } int callingFooWithNullPointer() { foo(); // No note on Calling 'S::foo' P.reset(new int(0)); // expected-note {{Assigning 0}} return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} // expected-note@-1 {{Division by zero}} } int callingFooWithValidPointer() { P.reset(new int(0)); // expected-note {{Assigning 0}} foo(); // No note on Calling 'S::foo' return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} // expected-note@-1 {{Division by zero}} } int callingFooWithUnknownPointer(std::unique_ptr PUnknown) { P.swap(PUnknown); foo(); // No note on Calling 'S::foo' P.reset(new int(0)); // expected-note {{Assigning 0}} return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} // expected-note@-1 {{Division by zero}} } }; void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr P) { A *RP = P.get(); if (!RP) { // expected-note {{Assuming 'RP' is null}} // expected-note@-1 {{Taking true branch}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } }