1 // RUN: %clang_analyze_cc1\
2 // RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
3 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
4 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
5 
6 #include "Inputs/system-header-simulator-cxx.h"
7 
8 class A {
9 public:
10   A(){};
11   void foo();
12 };
13 
14 A *return_null() {
15   return nullptr;
16 }
17 
18 void derefAfterDefaultCtr() {
19   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
20   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
21   // expected-note@-1{{Dereference of null smart pointer 'P'}}
22 }
23 
24 void derefAfterCtrWithNull() {
25   A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
26   std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}}
27   *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
28   // expected-note@-1{{Dereference of null smart pointer 'P'}}
29 }
30 
31 void derefAfterCtrWithNullVariable() {
32   A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
33   std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}}
34   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
35   // expected-note@-1{{Dereference of null smart pointer 'P'}}
36 }
37 
38 void derefAfterRelease() {
39   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
40   // FIXME: should mark region as uninteresting after release, so above note will not be there
41   P.release(); // expected-note {{Smart pointer 'P' is released and set to null}}
42   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
43   // expected-note@-1{{Dereference of null smart pointer 'P'}}
44 }
45 
46 void derefAfterReset() {
47   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
48   P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
49   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
50   // expected-note@-1{{Dereference of null smart pointer 'P'}}
51 }
52 
53 void derefAfterResetWithNull() {
54   A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
55   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
56   P.reset(NullInnerPtr); // expected-note {{Smart pointer 'P' reset using a null value}}
57   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
58   // expected-note@-1{{Dereference of null smart pointer 'P'}}
59 }
60 
61 // FIXME: Fix this test when support is added for tracking raw pointer
62 // and mark the smart pointer as interesting based on that and add tags.
63 void derefOnReleasedNullRawPtr() {
64   std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null"
65   A *AP = P.release(); // expected-note {{'AP' initialized to a null pointer value}}
66   AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
67   // expected-note@-1{{Called C++ object pointer is null}}
68 }
69 
70 void derefOnSwappedNullPtr() {
71   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
72   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
73   P.swap(PNull); // expected-note {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
74   PNull->foo(); // No warning.
75   (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
76   // expected-note@-1{{Dereference of null smart pointer 'P'}}
77 }
78 
79 // FIXME: Fix this test when "std::swap" is modeled seperately.
80 void derefOnStdSwappedNullPtr() {
81   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
82   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
83   std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:978 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
84   // expected-note@-1 {{Calling 'swap<A>'}}
85   // expected-note@-2 {{Returning from 'swap<A>'}}
86   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
87   // expected-note@-1{{Dereference of null smart pointer 'P'}}
88 }
89 
90 struct StructWithSmartPtr { // expected-note {{Default constructed smart pointer 'S.P' is null}}
91   std::unique_ptr<A> P;
92 };
93 
94 void derefAfterDefaultCtrInsideStruct() {
95   StructWithSmartPtr S; // expected-note {{Calling implicit default constructor for 'StructWithSmartPtr'}}
96   // expected-note@-1 {{Returning from default constructor for 'StructWithSmartPtr'}}
97   S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
98   // expected-note@-1{{Dereference of null smart pointer 'S.P'}}
99 }
100 
101 void noNoteTagsForNonInterestingRegion() {
102   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
103   std::unique_ptr<A> P1; // No note.
104   std::unique_ptr<A> P2; // No note.
105   P1.release(); // No note.
106   P1.reset(); // No note.
107   P1.swap(P2); // No note.
108   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
109   // expected-note@-1{{Dereference of null smart pointer 'P'}}
110 }
111 
112 void noNoteTagsForNonMatchingBugType() {
113   std::unique_ptr<A> P; // No note.
114   std::unique_ptr<A> P1; // No note.
115   P1 = std::move(P); // expected-note {{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}}
116   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' of type 'std::unique_ptr' [cplusplus.Move]}}
117   // expected-note@-1 {{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
118 }
119