1 // RUN: %clang_analyze_cc1\
2 // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
3 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
4 // RUN: -analyzer-output=text -std=c++20 %s -verify=expected
6 // RUN: %clang_analyze_cc1\
7 // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
8 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
9 // RUN: -analyzer-output=text -std=c++11 %s -verify=expected
11 #include "Inputs/system-header-simulator-cxx.h"
13 void clang_analyzer_eval(bool);
25 void derefAfterDefaultCtr() {
26 std::unique_ptr
<A
> P
; // expected-note {{Default constructed smart pointer 'P' is null}}
27 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
28 // expected-note@-1{{Dereference of null smart pointer 'P'}}
31 void derefAfterCtrWithNull() {
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
; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
35 // expected-note@-1{{Dereference of null smart pointer 'P'}}
38 void derefAfterCtrWithNullVariable() {
39 A
*NullInnerPtr
= nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
40 std::unique_ptr
<A
> P(NullInnerPtr
); // expected-note {{Smart pointer 'P' is constructed using a null value}}
41 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
42 // expected-note@-1{{Dereference of null smart pointer 'P'}}
45 void derefAfterRelease() {
46 std::unique_ptr
<A
> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
47 // FIXME: should mark region as uninteresting after release, so above note will not be there
48 P
.release(); // expected-note {{Smart pointer 'P' is released and set to null}}
49 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
50 // expected-note@-1{{Dereference of null smart pointer 'P'}}
53 void derefAfterReset() {
54 std::unique_ptr
<A
> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
55 P
.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
56 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
57 // expected-note@-1{{Dereference of null smart pointer 'P'}}
60 void derefAfterResetWithNull() {
61 A
*NullInnerPtr
= nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
62 std::unique_ptr
<A
> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
63 P
.reset(NullInnerPtr
); // expected-note {{Smart pointer 'P' reset using a null value}}
64 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
65 // expected-note@-1{{Dereference of null smart pointer 'P'}}
68 // FIXME: Fix this test when support is added for tracking raw pointer
69 // and mark the smart pointer as interesting based on that and add tags.
70 void derefOnReleasedNullRawPtr() {
71 std::unique_ptr
<A
> P
; // FIXME: add note "Default constructed smart pointer 'P' is null"
72 A
*AP
= P
.release(); // expected-note {{'AP' initialized to a null pointer value}}
73 AP
->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
74 // expected-note@-1{{Called C++ object pointer is null}}
77 void derefOnSwappedNullPtr() {
78 std::unique_ptr
<A
> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
79 std::unique_ptr
<A
> PNull
;
81 PNull
->foo(); // No warning.
82 (*P
).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
83 // expected-note@-1{{Dereference of null smart pointer 'P'}}
86 void derefOnStdSwappedNullPtr() {
87 std::unique_ptr
<A
> P
; // expected-note {{Default constructed smart pointer 'P' is null}}
88 std::unique_ptr
<A
> PNull
;
90 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
91 // expected-note@-1{{Dereference of null smart pointer 'P'}}
94 struct StructWithSmartPtr
{ // expected-note {{Default constructed smart pointer 'S.P' is null}}
98 void derefAfterDefaultCtrInsideStruct() {
99 StructWithSmartPtr S
; // expected-note {{Calling implicit default constructor for 'StructWithSmartPtr'}}
100 // expected-note@-1 {{Returning from default constructor for 'StructWithSmartPtr'}}
101 S
.P
->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
102 // expected-note@-1{{Dereference of null smart pointer 'S.P'}}
105 void noNoteTagsForNonInterestingRegion() {
106 std::unique_ptr
<A
> P
; // expected-note {{Default constructed smart pointer 'P' is null}}
107 std::unique_ptr
<A
> P1
; // No note.
108 std::unique_ptr
<A
> P2
; // No note.
109 P1
.release(); // No note.
110 P1
.reset(); // No note.
111 P1
.swap(P2
); // No note.
112 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
113 // expected-note@-1{{Dereference of null smart pointer 'P'}}
116 void derefOnRawPtrFromGetOnNullPtr() {
117 std::unique_ptr
<A
> P
; // FIXME: add note "Default constructed smart pointer 'P' is null"
118 P
.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
119 // expected-note@-1 {{Called C++ object pointer is null}}
122 void derefOnRawPtrFromGetOnValidPtr() {
123 std::unique_ptr
<A
> P(new A());
124 P
.get()->foo(); // No warning.
127 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr
<A
> P
) {
128 P
.get()->foo(); // No warning.
131 void derefOnMovedFromValidPtr() {
132 std::unique_ptr
<A
> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}}
133 // FIXME: above note should go away once we fix marking region not interested.
134 std::unique_ptr
<A
> P
;
135 P
= std::move(PToMove
); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
136 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
137 // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}}
140 void derefOnMovedToNullPtr() {
141 std::unique_ptr
<A
> PToMove(new A());
142 std::unique_ptr
<A
> P
;
143 P
= std::move(PToMove
); // No note.
144 P
->foo(); // No warning.
147 void derefOnNullPtrGotMovedFromValidPtr() {
148 std::unique_ptr
<A
> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
149 // FIXME: above note should go away once we fix marking region not interested.
150 std::unique_ptr
<A
> PToMove
; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
151 P
= std::move(PToMove
); // expected-note {{A null pointer value is moved to 'P'}}
152 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
153 // expected-note@-1 {{Dereference of null smart pointer 'P'}}
156 void derefOnMovedUnknownPtr(std::unique_ptr
<A
> PToMove
) {
157 std::unique_ptr
<A
> P
;
158 P
= std::move(PToMove
); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}}
159 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
160 // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}}
163 void derefOnAssignedNullPtrToNullSmartPtr() {
164 std::unique_ptr
<A
> P
; // expected-note {{Default constructed smart pointer 'P' is null}}
165 P
= nullptr; // expected-note {{Smart pointer 'P' is assigned to null}}
166 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
167 // expected-note@-1 {{Dereference of null smart pointer 'P'}}
170 void derefOnAssignedZeroToNullSmartPtr() {
171 std::unique_ptr
<A
> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
172 // FIXME: above note should go away once we fix marking region not interested.
173 P
= 0; // expected-note {{Smart pointer 'P' is assigned to null}}
174 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
175 // expected-note@-1 {{Dereference of null smart pointer 'P'}}
178 void derefMoveConstructedWithNullPtr() {
179 std::unique_ptr
<A
> PToMove
; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
180 std::unique_ptr
<A
> P(std::move(PToMove
)); // expected-note {{A null pointer value is moved to 'P'}}
181 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
182 // expected-note@-1{{Dereference of null smart pointer 'P'}}
185 void derefValidPtrMovedToConstruct() {
186 std::unique_ptr
<A
> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}}
187 // FIXME: above note should go away once we fix marking region not interested.
188 std::unique_ptr
<A
> P(std::move(PToMove
)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
189 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
190 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
193 void derefNullPtrMovedToConstruct() {
194 std::unique_ptr
<A
> PToMove
; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
195 // FIXME: above note should go away once we fix marking region not interested.
196 std::unique_ptr
<A
> P(std::move(PToMove
)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
197 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
198 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
201 void derefUnknownPtrMovedToConstruct(std::unique_ptr
<A
> PToMove
) {
202 std::unique_ptr
<A
> P(std::move(PToMove
)); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}}
203 PToMove
->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
204 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
207 void derefConditionOnNullPtrFalseBranch() {
208 std::unique_ptr
<A
> P
; // expected-note {{Default constructed smart pointer 'P' is null}}
209 if (P
) { // expected-note {{Taking false branch}}
210 P
->foo(); // No warning.
212 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
213 // expected-note@-1{{Dereference of null smart pointer 'P'}}
217 void derefConditionOnNullPtrTrueBranch() {
218 std::unique_ptr
<A
> P
; // expected-note {{Default constructed smart pointer 'P' is null}}
219 if (!P
) { // expected-note {{Taking true branch}}
220 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
221 // expected-note@-1{{Dereference of null smart pointer 'P'}}
225 void derefConditionOnValidPtrTrueBranch() {
226 std::unique_ptr
<A
> P(new A());
227 std::unique_ptr
<A
> PNull
; // expected-note {{Default constructed smart pointer 'PNull' is null}}
228 if (P
) { // expected-note {{Taking true branch}}
229 PNull
->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
230 // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
232 PNull
->foo(); // No warning
236 void derefConditionOnValidPtrFalseBranch() {
237 std::unique_ptr
<A
> P(new A());
238 std::unique_ptr
<A
> PNull
; // expected-note {{Default constructed smart pointer 'PNull' is null}}
239 if (!P
) { // expected-note {{Taking false branch}}
240 PNull
->foo(); // No warning
242 PNull
->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
243 // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
247 void derefConditionOnNotValidPtr() {
248 std::unique_ptr
<A
> P(new A());
249 std::unique_ptr
<A
> PNull
;
251 PNull
->foo(); // No warning.
254 void derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr
<A
> P
) {
255 std::unique_ptr
<A
> PNull
; // expected-note {{Default constructed smart pointer 'PNull' is null}}
256 if (!P
) { // expected-note {{Taking true branch}}
257 // expected-note@-1{{Assuming smart pointer 'P' is null}}
258 PNull
->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
259 // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
263 void derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr
<A
> P
) {
264 std::unique_ptr
<A
> PNull
; // expected-note {{Default constructed smart pointer 'PNull' is null}}
265 if (P
) { // expected-note {{Taking true branch}}
266 // expected-note@-1{{Assuming smart pointer 'P' is non-null}}
267 PNull
->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
268 // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
272 void derefOnValidPtrAfterReset(std::unique_ptr
<A
> P
) {
275 P
->foo(); // No warning.
277 P
->foo(); // No warning.
281 std::unique_ptr
<int> P
;
284 if (!P
) { // No-note because foo() is pruned
289 int callingFooWithNullPointer() {
290 foo(); // No note on Calling 'S::foo'
291 P
.reset(new int(0)); // expected-note {{Assigning 0}}
292 return 1 / *(P
.get()); // expected-warning {{Division by zero [core.DivideZero]}}
293 // expected-note@-1 {{Division by zero}}
296 int callingFooWithValidPointer() {
297 P
.reset(new int(0)); // expected-note {{Assigning 0}}
298 foo(); // No note on Calling 'S::foo'
299 return 1 / *(P
.get()); // expected-warning {{Division by zero [core.DivideZero]}}
300 // expected-note@-1 {{Division by zero}}
303 int callingFooWithUnknownPointer(std::unique_ptr
<int> PUnknown
) {
305 foo(); // No note on Calling 'S::foo'
306 P
.reset(new int(0)); // expected-note {{Assigning 0}}
307 return 1 / *(P
.get()); // expected-warning {{Division by zero [core.DivideZero]}}
308 // expected-note@-1 {{Division by zero}}
312 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr
<A
> P
) {
314 if (!RP
) { // expected-note {{Assuming 'RP' is null}}
315 // expected-note@-1 {{Taking true branch}}
316 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
317 // expected-note@-1{{Dereference of null smart pointer 'P'}}
321 void makeUniqueReturnsNonNullUniquePtr() {
322 auto P
= std::make_unique
<A
>();
323 if (!P
) { // expected-note {{Taking false branch}}
324 P
->foo(); // should have no warning here, path is impossible
326 P
.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
329 // expected-note@-1 {{Taking true branch}}
330 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
331 // expected-note@-1{{Dereference of null smart pointer 'P'}}
335 #if __cplusplus >= 202002L
337 void makeUniqueForOverwriteReturnsNullUniquePtr() {
338 auto P
= std::make_unique_for_overwrite
<A
>();
339 if (!P
) { // expected-note {{Taking false branch}}
340 P
->foo(); // should have no warning here, path is impossible
342 P
.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
345 // expected-note@-1 {{Taking true branch}}
346 P
->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
347 // expected-note@-1{{Dereference of null smart pointer 'P'}}
362 auto P
= std::make_unique
<G
>(&x
);
363 // FIXME: There should not be a state split here, it should take the true path.
364 clang_analyzer_eval(*P
->p
== 1); // expected-warning {{TRUE}}
365 // expected-warning@-1 {{FALSE}}
366 // expected-note@-2 {{Assuming the condition is true}}
367 // expected-note@-3 {{Assuming the condition is false}}
368 // expected-note@-4 {{TRUE}}
369 // expected-note@-5 {{FALSE}}
370 // expected-note@-6 {{Assuming the condition is false}}
372 // FIXME: Should be fixed when unique_ptr desctructors are
373 // properly modelled. This includes modelling the call to
374 // the destructor of the inner pointer type.
375 clang_analyzer_eval(x
== 0); // expected-warning {{FALSE}}
376 // expected-note@-1 {{FALSE}}