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)13 void 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))30 void 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()41 A *return_null() {
42   return nullptr;
43 }
44 
derefAfterValidCtr()45 void 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)51 void derefOfUnknown(std::unique_ptr<A> P) {
52   P->foo(); // No warning.
53 }
54 
derefAfterDefaultCtr()55 void 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()61 void 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()67 void 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()74 void 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()81 void 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()88 void 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()94 void 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()101 void 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()108 void 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()114 void 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()127 void regioninvalidationWithPassByRef() {
128   std::unique_ptr<A> P;
129   pass_smart_ptr_by_ref(P);
130   P->foo(); // no-warning
131 }
132 
regioninvalidationWithPassByCostRef()133 void 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()139 void 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()145 void 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()151 void regioninvalidationWithPassByPtr() {
152   std::unique_ptr<A> P;
153   pass_smart_ptr_by_ptr(&P);
154   P->foo();
155 }
156 
regioninvalidationWithPassByConstPtr()157 void 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()174 void regioninvalidationWithinStructPassByRef() {
175   StructWithSmartPtr S;
176   pass_struct_with_smart_ptr_by_ref(S);
177   S.P->foo(); // no-warning
178 }
179 
regioninvalidationWithinStructPassByConstRef()180 void 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()186 void 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()192 void 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()198 void regioninvalidationWithinStructPassByPtr() {
199   StructWithSmartPtr S;
200   pass_struct_with_smart_ptr_by_ptr(&S);
201   S.P->foo(); // no-warning
202 }
203 
regioninvalidationWithinStructPassByConstPtr()204 void 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()210 void 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()225 void 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()233 void 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()240 void 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()247 void 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()258 void derefOnRawPtrFromGetOnNullPtr() {
259   std::unique_ptr<A> P;
260   P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
261 }
262 
derefOnRawPtrFromGetOnValidPtr()263 void derefOnRawPtrFromGetOnValidPtr() {
264   std::unique_ptr<A> P(new A());
265   P.get()->foo(); // No warning.
266 }
267 
derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P)268 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) {
269   P.get()->foo(); // No warning.
270 }
271 
derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P)272 void 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()281 void 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()288 void 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()295 void 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)302 void 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)308 void 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()314 void 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()320 void 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)326 void 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()333 void drefOnAssignedNullFromMethodPtrValidSmartPtr() {
334   std::unique_ptr<A> P(new A());
335   P = returnRValRefOfUniquePtr();
336   P->foo(); // No warning.
337 }
338 
derefMoveConstructedWithValidPtr()339 void 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()345 void 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)351 void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) {
352   std::unique_ptr<A> P(std::move(PToMove));
353   P->foo(); // No warning.
354 }
355 
derefValidPtrMovedToConstruct()356 void 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()362 void 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)368 void 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()375 void derefMoveConstructedWithRValueRefReturn() {
376   std::unique_ptr<A> P(functionReturnsRValueRef());
377   P->foo(); // No warning.
378 }
379 
derefConditionOnNullPtr()380 void 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()388 void 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()394 void 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()401 void 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)408 void 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)415 void 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()423 void 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)429 void 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)436 void 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)446 int 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)454 void 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