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:
A()10   A(){};
11   void foo();
12 };
13 
return_null()14 A *return_null() {
15   return nullptr;
16 }
17 
derefAfterDefaultCtr()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 
derefAfterCtrWithNull()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 
derefAfterCtrWithNullVariable()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 
derefAfterRelease()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 
derefAfterReset()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 
derefAfterResetWithNull()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.
derefOnReleasedNullRawPtr()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 
derefOnSwappedNullPtr()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.
derefOnStdSwappedNullPtr()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:979 {{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 
derefAfterDefaultCtrInsideStruct()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 
noNoteTagsForNonInterestingRegion()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 
derefOnRawPtrFromGetOnNullPtr()112 void derefOnRawPtrFromGetOnNullPtr() {
113   std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null"
114   P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
115   // expected-note@-1 {{Called C++ object pointer is null}}
116 }
117 
derefOnRawPtrFromGetOnValidPtr()118 void derefOnRawPtrFromGetOnValidPtr() {
119   std::unique_ptr<A> P(new A());
120   P.get()->foo(); // No warning.
121 }
122 
derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P)123 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) {
124   P.get()->foo(); // No warning.
125 }
126 
derefOnMovedFromValidPtr()127 void derefOnMovedFromValidPtr() {
128   std::unique_ptr<A> PToMove(new A());  // expected-note {{Smart pointer 'PToMove' is constructed}}
129   // FIXME: above note should go away once we fix marking region not interested.
130   std::unique_ptr<A> P;
131   P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
132   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
133   // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}}
134 }
135 
derefOnMovedToNullPtr()136 void derefOnMovedToNullPtr() {
137   std::unique_ptr<A> PToMove(new A());
138   std::unique_ptr<A> P;
139   P = std::move(PToMove); // No note.
140   P->foo(); // No warning.
141 }
142 
derefOnNullPtrGotMovedFromValidPtr()143 void derefOnNullPtrGotMovedFromValidPtr() {
144   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
145   // FIXME: above note should go away once we fix marking region not interested.
146   std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
147   P = std::move(PToMove); // expected-note {{A null pointer value is moved to 'P'}}
148   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
149   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
150 }
151 
derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove)152 void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) {
153   std::unique_ptr<A> P;
154   P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}}
155   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
156   // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}}
157 }
158 
derefOnAssignedNullPtrToNullSmartPtr()159 void derefOnAssignedNullPtrToNullSmartPtr() {
160   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
161   P = nullptr; // expected-note {{Smart pointer 'P' is assigned to null}}
162   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
163   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
164 }
165 
derefOnAssignedZeroToNullSmartPtr()166 void derefOnAssignedZeroToNullSmartPtr() {
167   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
168   // FIXME: above note should go away once we fix marking region not interested.
169   P = 0; // expected-note {{Smart pointer 'P' is assigned to null}}
170   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
171   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
172 }
173 
derefMoveConstructedWithNullPtr()174 void derefMoveConstructedWithNullPtr() {
175   std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
176   std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{A null pointer value is moved to 'P'}}
177   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
178   // expected-note@-1{{Dereference of null smart pointer 'P'}}
179 }
180 
derefValidPtrMovedToConstruct()181 void derefValidPtrMovedToConstruct() {
182   std::unique_ptr<A> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}}
183   // FIXME: above note should go away once we fix marking region not interested.
184   std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
185   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
186   // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
187 }
188 
derefNullPtrMovedToConstruct()189 void derefNullPtrMovedToConstruct() {
190   std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
191   // FIXME: above note should go away once we fix marking region not interested.
192   std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
193   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
194   // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
195 }
196 
derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove)197 void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) {
198   std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}}
199   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
200   // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
201 }
202 
derefConditionOnNullPtrFalseBranch()203 void derefConditionOnNullPtrFalseBranch() {
204   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
205   if (P) { // expected-note {{Taking false branch}}
206     P->foo(); // No warning.
207   } else {
208     P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
209     // expected-note@-1{{Dereference of null smart pointer 'P'}}
210   }
211 }
212 
derefConditionOnNullPtrTrueBranch()213 void derefConditionOnNullPtrTrueBranch() {
214   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
215   if (!P) { // expected-note {{Taking true branch}}
216     P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
217     // expected-note@-1{{Dereference of null smart pointer 'P'}}
218   }
219 }
220 
derefConditionOnValidPtrTrueBranch()221 void derefConditionOnValidPtrTrueBranch() {
222   std::unique_ptr<A> P(new A());
223   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
224   if (P) { // expected-note {{Taking true branch}}
225     PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
226     // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
227   } else {
228     PNull->foo(); // No warning
229   }
230 }
231 
derefConditionOnValidPtrFalseBranch()232 void derefConditionOnValidPtrFalseBranch() {
233   std::unique_ptr<A> P(new A());
234   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
235   if (!P) { // expected-note {{Taking false branch}}
236     PNull->foo(); // No warning
237   } else {
238     PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
239     // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
240   }
241 }
242 
derefConditionOnNotValidPtr()243 void derefConditionOnNotValidPtr() {
244   std::unique_ptr<A> P(new A());
245   std::unique_ptr<A> PNull;
246   if (!P)
247     PNull->foo(); // No warning.
248 }
249 
derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr<A> P)250 void derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr<A> P) {
251   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
252   if (!P) { // expected-note {{Taking true branch}}
253     // expected-note@-1{{Assuming smart pointer 'P' is null}}
254     PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
255     // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
256   }
257 }
258 
derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr<A> P)259 void derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr<A> P) {
260   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
261   if (P) { // expected-note {{Taking true branch}}
262     // expected-note@-1{{Assuming smart pointer 'P' is non-null}}
263     PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
264     // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
265   }
266 }
267 
derefOnValidPtrAfterReset(std::unique_ptr<A> P)268 void derefOnValidPtrAfterReset(std::unique_ptr<A> P) {
269   P.reset(new A());
270   if (!P)
271     P->foo(); // No warning.
272   else
273     P->foo(); // No warning.
274 }
275 
276 struct S {
277   std::unique_ptr<int> P;
278 
fooS279   void foo() {
280     if (!P) { // No-note because foo() is pruned
281       return;
282     }
283   }
284 
callingFooWithNullPointerS285   int callingFooWithNullPointer() {
286     foo(); // No note on Calling 'S::foo'
287     P.reset(new int(0)); // expected-note {{Assigning 0}}
288     return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}}
289     // expected-note@-1 {{Division by zero}}
290   }
291 
callingFooWithValidPointerS292   int callingFooWithValidPointer() {
293     P.reset(new int(0)); // expected-note {{Assigning 0}}
294     foo(); // No note on Calling 'S::foo'
295     return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}}
296     // expected-note@-1 {{Division by zero}}
297   }
298 
callingFooWithUnknownPointerS299   int callingFooWithUnknownPointer(std::unique_ptr<int> PUnknown) {
300     P.swap(PUnknown);
301     foo(); // No note on Calling 'S::foo'
302     P.reset(new int(0)); // expected-note {{Assigning 0}}
303     return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}}
304     // expected-note@-1 {{Division by zero}}
305   }
306 };
307 
derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P)308 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) {
309   A *RP = P.get();
310   if (!RP) { // expected-note {{Assuming 'RP' is null}}
311     // expected-note@-1 {{Taking true branch}}
312     P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
313     // expected-note@-1{{Dereference of null smart pointer 'P'}}
314   }
315 }
316