[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / smart-ptr.cpp
blobd3046d69ca839c27a089e3bca667ecaacefd5266
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);
20 if (Q)
21 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
22 *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
23 if (P)
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 {
32 struct S {
33 void foo();
35 void bar(S *s, void (S::*func)(void)) {
36 (s->*func)(); // no-crash
38 } // namespace testUnknownCallee
40 class A {
41 public:
42 A(){};
43 void foo();
46 A *return_null() {
47 return nullptr;
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() {
61 std::unique_ptr<A> P;
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());
81 P.release();
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());
88 P.reset();
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());
95 P.reset(nullptr);
96 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
99 void derefAfterResetWithNonNull() {
100 std::unique_ptr<A> P;
101 P.reset(new A());
102 clang_analyzer_numTimesReached(); // expected-warning {{1}}
103 P->foo(); // No warning.
106 void derefAfterReleaseAndResetWithNonNull() {
107 std::unique_ptr<A> P(new A());
108 P.release();
109 P.reset(new A());
110 P->foo(); // No warning.
113 void derefOnReleasedNullRawPtr() {
114 std::unique_ptr<A> P;
115 A *AP = P.release();
116 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
119 void derefOnReleasedValidRawPtr() {
120 std::unique_ptr<A> P(new A());
121 A *AP = P.release();
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);
159 P->foo();
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;
219 Q = std::move(P);
220 Q->foo(); // no-warning
223 std::unique_ptr<A> P;
224 std::unique_ptr<A> Q;
225 Q = std::move(P);
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;
233 P.swap(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;
241 std::swap(P, 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;
248 std::swap(P, 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());
255 P.swap(PValid);
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) {
278 A *X = P.get();
279 A *Y = P.get();
280 clang_analyzer_eval(X == Y); // expected-warning{{TRUE}}
281 if (!X) {
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;
321 P = nullptr;
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());
327 P = 0;
328 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
331 void derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P) {
332 P = nullptr;
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;
387 if (P)
388 P->foo(); // No warning.
389 else
390 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
393 void derefConditionOnNotNullPtr() {
394 std::unique_ptr<A> P;
395 if (!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;
402 if (P)
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;
409 if (!P)
410 PNull->foo(); // No warning.
413 void derefConditionOnUnKnownPtr(std::unique_ptr<A> P) {
414 if (P)
415 P->foo(); // No warning.
416 else
417 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
420 void derefOnValidPtrAfterReset(std::unique_ptr<A> P) {
421 P.reset(new A());
422 if (!P)
423 P->foo(); // No warning.
424 else
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) {
435 if (P) {
436 int *X = P.get();
437 clang_analyzer_warnOnDeadSymbol(X);
439 } // expected-warning{{SYMBOL DEAD}}
441 void getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) {
442 int *X = P.get();
443 clang_analyzer_warnOnDeadSymbol(X);
444 int Y;
445 if (!P) {
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);
453 if (P)
454 return *P; // No warning.
455 else
456 return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
459 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) {
460 A *RP = P.get();
461 if (!RP) {
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}}
530 int glob;
531 void testOstreamDoesntInvalidateGlobals(std::unique_ptr<int> P) {
532 int x = glob;
533 std::cout << P;
534 int y = glob;
535 clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
538 #endif
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.
544 bar(true, false);