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
6 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\
7 // RUN: -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\
8 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
9 // RUN: -std=c++20 -verify %s
11 #include "Inputs/system-header-simulator-cxx.h"
13 void clang_analyzer_warnIfReached();
14 void clang_analyzer_numTimesReached();
15 void clang_analyzer_eval(bool);
16 void clang_analyzer_warnOnDeadSymbol(int *);
18 void derefAfterMove(std::unique_ptr
<int> P
) {
19 std::unique_ptr
<int> Q
= std::move(P
);
21 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
22 *Q
.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
24 clang_analyzer_warnIfReached(); // no-warning
25 // TODO: Report a null dereference (instead).
26 *P
.get() = 1; // expected-warning {{Method called on moved-from object 'P' [cplusplus.Move]}}
27 // expected-warning@-1 {{Dereference of null pointer [core.NullDereference]}}
30 // Don't crash when attempting to model a call with unknown callee.
31 namespace testUnknownCallee
{
35 void bar(S
*s
, void (S::*func
)(void)) {
36 (s
->*func
)(); // no-crash
38 } // namespace testUnknownCallee
50 void derefAfterValidCtr() {
51 std::unique_ptr
<A
> P(new A());
52 clang_analyzer_numTimesReached(); // expected-warning {{1}}
53 P
->foo(); // No warning.
56 void derefOfUnknown(std::unique_ptr
<A
> P
) {
57 P
->foo(); // No warning.
60 void derefAfterDefaultCtr() {
62 clang_analyzer_numTimesReached(); // expected-warning {{1}}
63 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
66 void derefAfterCtrWithNull() {
67 std::unique_ptr
<A
> P(nullptr);
68 clang_analyzer_numTimesReached(); // expected-warning {{1}}
69 *P
; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
72 void derefAfterCtrWithNullVariable() {
73 A
*InnerPtr
= nullptr;
74 std::unique_ptr
<A
> P(InnerPtr
);
75 clang_analyzer_numTimesReached(); // expected-warning {{1}}
76 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
79 void derefAfterRelease() {
80 std::unique_ptr
<A
> P(new A());
82 clang_analyzer_numTimesReached(); // expected-warning {{1}}
83 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
86 void derefAfterReset() {
87 std::unique_ptr
<A
> P(new A());
89 clang_analyzer_numTimesReached(); // expected-warning {{1}}
90 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
93 void derefAfterResetWithNull() {
94 std::unique_ptr
<A
> P(new A());
96 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
99 void derefAfterResetWithNonNull() {
100 std::unique_ptr
<A
> P
;
102 clang_analyzer_numTimesReached(); // expected-warning {{1}}
103 P
->foo(); // No warning.
106 void derefAfterReleaseAndResetWithNonNull() {
107 std::unique_ptr
<A
> P(new A());
110 P
->foo(); // No warning.
113 void derefOnReleasedNullRawPtr() {
114 std::unique_ptr
<A
> P
;
116 AP
->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
119 void derefOnReleasedValidRawPtr() {
120 std::unique_ptr
<A
> P(new A());
122 AP
->foo(); // No warning.
125 void pass_smart_ptr_by_ref(std::unique_ptr
<A
> &a
);
126 void pass_smart_ptr_by_const_ref(const std::unique_ptr
<A
> &a
);
127 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr
<A
> &&a
);
128 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr
<A
> &&a
);
129 void pass_smart_ptr_by_ptr(std::unique_ptr
<A
> *a
);
130 void pass_smart_ptr_by_const_ptr(const std::unique_ptr
<A
> *a
);
132 void regioninvalidationWithPassByRef() {
133 std::unique_ptr
<A
> P
;
134 pass_smart_ptr_by_ref(P
);
135 P
->foo(); // no-warning
138 void regioninvalidationWithPassByCostRef() {
139 std::unique_ptr
<A
> P
;
140 pass_smart_ptr_by_const_ref(P
);
141 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
144 void regioninvalidationWithPassByRValueRef() {
145 std::unique_ptr
<A
> P
;
146 pass_smart_ptr_by_rvalue_ref(std::move(P
));
147 P
->foo(); // no-warning
150 void regioninvalidationWithPassByConstRValueRef() {
151 std::unique_ptr
<A
> P
;
152 pass_smart_ptr_by_const_rvalue_ref(std::move(P
));
153 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
156 void regioninvalidationWithPassByPtr() {
157 std::unique_ptr
<A
> P
;
158 pass_smart_ptr_by_ptr(&P
);
162 void regioninvalidationWithPassByConstPtr() {
163 std::unique_ptr
<A
> P
;
164 pass_smart_ptr_by_const_ptr(&P
);
165 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
168 struct StructWithSmartPtr
{
169 std::unique_ptr
<A
> P
;
172 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr
&a
);
173 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr
&a
);
174 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr
&&a
);
175 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr
&&a
);
176 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr
*a
);
177 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr
*a
);
179 void regioninvalidationWithinStructPassByRef() {
180 StructWithSmartPtr S
;
181 pass_struct_with_smart_ptr_by_ref(S
);
182 S
.P
->foo(); // no-warning
185 void regioninvalidationWithinStructPassByConstRef() {
186 StructWithSmartPtr S
;
187 pass_struct_with_smart_ptr_by_const_ref(S
);
188 S
.P
->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
191 void regioninvalidationWithinStructPassByRValueRef() {
192 StructWithSmartPtr S
;
193 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S
));
194 S
.P
->foo(); // no-warning
197 void regioninvalidationWithinStructPassByConstRValueRef() {
198 StructWithSmartPtr S
;
199 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S
));
200 S
.P
->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
203 void regioninvalidationWithinStructPassByPtr() {
204 StructWithSmartPtr S
;
205 pass_struct_with_smart_ptr_by_ptr(&S
);
206 S
.P
->foo(); // no-warning
209 void regioninvalidationWithinStructPassByConstPtr() {
210 StructWithSmartPtr S
;
211 pass_struct_with_smart_ptr_by_const_ptr(&S
);
212 S
.P
->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
215 void derefAfterAssignment() {
217 std::unique_ptr
<A
> P(new A());
218 std::unique_ptr
<A
> Q
;
220 Q
->foo(); // no-warning
223 std::unique_ptr
<A
> P
;
224 std::unique_ptr
<A
> Q
;
226 Q
->foo(); // expected-warning {{Dereference of null smart pointer 'Q' [alpha.cplusplus.SmartPtr]}}
230 void derefOnSwappedNullPtr() {
231 std::unique_ptr
<A
> P(new A());
232 std::unique_ptr
<A
> PNull
;
234 PNull
->foo(); // No warning.
235 (*P
).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
238 void derefOnFirstStdSwappedNullPtr() {
239 std::unique_ptr
<A
> P
;
240 std::unique_ptr
<A
> PNull
;
242 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
245 void derefOnSecondStdSwappedNullPtr() {
246 std::unique_ptr
<A
> P
;
247 std::unique_ptr
<A
> PNull
;
249 PNull
->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
252 void derefOnSwappedValidPtr() {
253 std::unique_ptr
<A
> P(new A());
254 std::unique_ptr
<A
> PValid(new A());
256 (*P
).foo(); // No warning.
257 PValid
->foo(); // No warning.
258 std::swap(P
, PValid
);
259 P
->foo(); // No warning.
260 PValid
->foo(); // No warning.
263 void derefOnRawPtrFromGetOnNullPtr() {
264 std::unique_ptr
<A
> P
;
265 P
.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
268 void derefOnRawPtrFromGetOnValidPtr() {
269 std::unique_ptr
<A
> P(new A());
270 P
.get()->foo(); // No warning.
273 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr
<A
> P
) {
274 P
.get()->foo(); // No warning.
277 void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr
<A
> P
) {
280 clang_analyzer_eval(X
== Y
); // expected-warning{{TRUE}}
282 Y
->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
286 void derefOnMovedFromValidPtr() {
287 std::unique_ptr
<A
> PToMove(new A());
288 std::unique_ptr
<A
> P
;
289 P
= std::move(PToMove
);
290 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
293 void derefOnMovedToNullPtr() {
294 std::unique_ptr
<A
> PToMove(new A());
295 std::unique_ptr
<A
> P
;
296 P
= std::move(PToMove
); // No note.
297 P
->foo(); // No warning.
300 void derefOnNullPtrGotMovedFromValidPtr() {
301 std::unique_ptr
<A
> P(new A());
302 std::unique_ptr
<A
> PToMove
;
303 P
= std::move(PToMove
);
304 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
307 void derefOnMovedFromUnknownPtr(std::unique_ptr
<A
> PToMove
) {
308 std::unique_ptr
<A
> P
;
309 P
= std::move(PToMove
);
310 P
->foo(); // No warning.
313 void derefOnMovedUnknownPtr(std::unique_ptr
<A
> PToMove
) {
314 std::unique_ptr
<A
> P
;
315 P
= std::move(PToMove
);
316 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
319 void derefOnAssignedNullPtrToNullSmartPtr() {
320 std::unique_ptr
<A
> P
;
322 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
325 void derefOnAssignedZeroToNullSmartPtr() {
326 std::unique_ptr
<A
> P(new A());
328 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
331 void derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr
<A
> P
) {
333 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
336 std::unique_ptr
<A
> &&returnRValRefOfUniquePtr();
338 void drefOnAssignedNullFromMethodPtrValidSmartPtr() {
339 std::unique_ptr
<A
> P(new A());
340 P
= returnRValRefOfUniquePtr();
341 P
->foo(); // No warning.
344 void derefMoveConstructedWithValidPtr() {
345 std::unique_ptr
<A
> PToMove(new A());
346 std::unique_ptr
<A
> P(std::move(PToMove
));
347 P
->foo(); // No warning.
350 void derefMoveConstructedWithNullPtr() {
351 std::unique_ptr
<A
> PToMove
;
352 std::unique_ptr
<A
> P(std::move(PToMove
));
353 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
356 void derefMoveConstructedWithUnknownPtr(std::unique_ptr
<A
> PToMove
) {
357 std::unique_ptr
<A
> P(std::move(PToMove
));
358 P
->foo(); // No warning.
361 void derefValidPtrMovedToConstruct() {
362 std::unique_ptr
<A
> PToMove(new A());
363 std::unique_ptr
<A
> P(std::move(PToMove
));
364 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
367 void derefNullPtrMovedToConstruct() {
368 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]}}
373 void derefUnknownPtrMovedToConstruct(std::unique_ptr
<A
> PToMove
) {
374 std::unique_ptr
<A
> P(std::move(PToMove
));
375 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
378 std::unique_ptr
<A
> &&functionReturnsRValueRef();
380 void derefMoveConstructedWithRValueRefReturn() {
381 std::unique_ptr
<A
> P(functionReturnsRValueRef());
382 P
->foo(); // No warning.
385 void derefConditionOnNullPtr() {
386 std::unique_ptr
<A
> P
;
388 P
->foo(); // No warning.
390 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
393 void derefConditionOnNotNullPtr() {
394 std::unique_ptr
<A
> P
;
396 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
399 void derefConditionOnValidPtr() {
400 std::unique_ptr
<A
> P(new A());
401 std::unique_ptr
<A
> PNull
;
403 PNull
->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
406 void derefConditionOnNotValidPtr() {
407 std::unique_ptr
<A
> P(new A());
408 std::unique_ptr
<A
> PNull
;
410 PNull
->foo(); // No warning.
413 void derefConditionOnUnKnownPtr(std::unique_ptr
<A
> P
) {
415 P
->foo(); // No warning.
417 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
420 void derefOnValidPtrAfterReset(std::unique_ptr
<A
> P
) {
423 P
->foo(); // No warning.
425 P
->foo(); // No warning.
428 void innerPointerSymbolLiveness() {
429 std::unique_ptr
<int> P(new int());
430 clang_analyzer_warnOnDeadSymbol(P
.get());
431 int *RP
= P
.release();
432 } // expected-warning{{SYMBOL DEAD}}
434 void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr
<int> P
) {
437 clang_analyzer_warnOnDeadSymbol(X
);
439 } // expected-warning{{SYMBOL DEAD}}
441 void getCreatedConjuredSymbolLiveness(std::unique_ptr
<int> P
) {
443 clang_analyzer_warnOnDeadSymbol(X
);
446 Y
= *P
.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
447 // expected-warning@-1 {{SYMBOL DEAD}}
451 int derefConditionOnUnKnownPtr(int *q
) {
452 std::unique_ptr
<int> P(q
);
454 return *P
; // No warning.
456 return *P
; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
459 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr
<A
> P
) {
462 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
466 // The following is a silly function,
467 // but serves to test if we are picking out
468 // standard comparision functions from custom ones.
469 template <typename T
>
470 bool operator<(std::unique_ptr
<T
> &x
, double d
);
472 void uniquePtrComparision(std::unique_ptr
<int> unknownPtr
) {
473 auto ptr
= std::unique_ptr
<int>(new int(13));
474 auto nullPtr
= std::unique_ptr
<int>();
475 auto otherPtr
= std::unique_ptr
<int>(new int(29));
477 clang_analyzer_eval(ptr
== ptr
); // expected-warning{{TRUE}}
478 clang_analyzer_eval(ptr
> ptr
); // expected-warning{{FALSE}}
479 clang_analyzer_eval(ptr
<= ptr
); // expected-warning{{TRUE}}
481 clang_analyzer_eval(nullPtr
<= unknownPtr
); // expected-warning{{TRUE}}
482 clang_analyzer_eval(unknownPtr
>= nullPtr
); // expected-warning{{TRUE}}
484 clang_analyzer_eval(ptr
!= otherPtr
); // expected-warning{{TRUE}}
485 clang_analyzer_eval(ptr
> nullPtr
); // expected-warning{{TRUE}}
487 clang_analyzer_eval(ptr
!= nullptr); // expected-warning{{TRUE}}
488 clang_analyzer_eval(nullPtr
!= nullptr); // expected-warning{{FALSE}}
489 clang_analyzer_eval(nullptr <= unknownPtr
); // expected-warning{{TRUE}}
492 void uniquePtrComparisionStateSplitting(std::unique_ptr
<int> unknownPtr
) {
493 auto ptr
= std::unique_ptr
<int>(new int(13));
495 clang_analyzer_eval(ptr
> unknownPtr
); // expected-warning{{TRUE}}
496 // expected-warning@-1{{FALSE}}
499 void uniquePtrComparisionDifferingTypes(std::unique_ptr
<int> unknownPtr
) {
500 auto ptr
= std::unique_ptr
<int>(new int(13));
501 auto nullPtr
= std::unique_ptr
<A
>();
502 auto otherPtr
= std::unique_ptr
<double>(new double(3.14));
504 clang_analyzer_eval(nullPtr
<= unknownPtr
); // expected-warning{{TRUE}}
505 clang_analyzer_eval(unknownPtr
>= nullPtr
); // expected-warning{{TRUE}}
507 clang_analyzer_eval(ptr
!= otherPtr
); // expected-warning{{TRUE}}
508 clang_analyzer_eval(ptr
> nullPtr
); // expected-warning{{TRUE}}
510 clang_analyzer_eval(ptr
!= nullptr); // expected-warning{{TRUE}}
511 clang_analyzer_eval(nullPtr
!= nullptr); // expected-warning{{FALSE}}
512 clang_analyzer_eval(nullptr <= unknownPtr
); // expected-warning{{TRUE}}
515 #if __cplusplus >= 202002L
517 void testOstreamOverload(std::unique_ptr
<int> P
) {
518 auto &Cout
= std::cout
;
519 auto &PtrCout
= std::cout
<< P
;
520 auto &StringCout
= std::cout
<< "hello";
521 // We are testing the fact that in our modelling of
522 // operator<<(basic_ostream<T1> &, const unique_ptr<T2> &)
523 // we set the return SVal to the SVal of the ostream arg.
524 clang_analyzer_eval(&Cout
== &PtrCout
); // expected-warning {{TRUE}}
525 // FIXME: Technically, they should be equal,
526 // that hasn't been modelled yet.
527 clang_analyzer_eval(&Cout
== &StringCout
); // expected-warning {{UNKNOWN}}
531 void testOstreamDoesntInvalidateGlobals(std::unique_ptr
<int> P
) {
535 clang_analyzer_eval(x
== y
); // expected-warning {{TRUE}}
540 // The following test isn't really a "smart-ptr" test
541 // It came up during a bug fix (D106296)
542 void testCheckForFunctionsWithNoDecl(void (*bar
)(bool, bool)) {
543 // This should NOT crash.