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 // 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
10
11 #include "Inputs/system-header-simulator-cxx.h"
12
13 void clang_analyzer_warnIfReached();
14 void clang_analyzer_numTimesReached();
15 void clang_analyzer_eval(bool);
16 void clang_analyzer_warnOnDeadSymbol(int *);
17
derefAfterMove(std::unique_ptr<int> P)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]}}
28 }
29
30 // Don't crash when attempting to model a call with unknown callee.
31 namespace testUnknownCallee {
32 struct S {
33 void foo();
34 };
bar(S * s,void (S::* func)(void))35 void bar(S *s, void (S::*func)(void)) {
36 (s->*func)(); // no-crash
37 }
38 } // namespace testUnknownCallee
39
40 class A {
41 public:
A()42 A(){};
43 void foo();
44 };
45
return_null()46 A *return_null() {
47 return nullptr;
48 }
49
derefAfterValidCtr()50 void derefAfterValidCtr() {
51 std::unique_ptr<A> P(new A());
52 clang_analyzer_numTimesReached(); // expected-warning {{1}}
53 P->foo(); // No warning.
54 }
55
derefOfUnknown(std::unique_ptr<A> P)56 void derefOfUnknown(std::unique_ptr<A> P) {
57 P->foo(); // No warning.
58 }
59
derefAfterDefaultCtr()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]}}
64 }
65
derefAfterCtrWithNull()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]}}
70 }
71
derefAfterCtrWithNullVariable()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]}}
77 }
78
derefAfterRelease()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]}}
84 }
85
derefAfterReset()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]}}
91 }
92
derefAfterResetWithNull()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]}}
97 }
98
derefAfterResetWithNonNull()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.
104 }
105
derefAfterReleaseAndResetWithNonNull()106 void derefAfterReleaseAndResetWithNonNull() {
107 std::unique_ptr<A> P(new A());
108 P.release();
109 P.reset(new A());
110 P->foo(); // No warning.
111 }
112
derefOnReleasedNullRawPtr()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]}}
117 }
118
derefOnReleasedValidRawPtr()119 void derefOnReleasedValidRawPtr() {
120 std::unique_ptr<A> P(new A());
121 A *AP = P.release();
122 AP->foo(); // No warning.
123 }
124
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);
131
regioninvalidationWithPassByRef()132 void regioninvalidationWithPassByRef() {
133 std::unique_ptr<A> P;
134 pass_smart_ptr_by_ref(P);
135 P->foo(); // no-warning
136 }
137
regioninvalidationWithPassByCostRef()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]}}
142 }
143
regioninvalidationWithPassByRValueRef()144 void regioninvalidationWithPassByRValueRef() {
145 std::unique_ptr<A> P;
146 pass_smart_ptr_by_rvalue_ref(std::move(P));
147 P->foo(); // no-warning
148 }
149
regioninvalidationWithPassByConstRValueRef()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]}}
154 }
155
regioninvalidationWithPassByPtr()156 void regioninvalidationWithPassByPtr() {
157 std::unique_ptr<A> P;
158 pass_smart_ptr_by_ptr(&P);
159 P->foo();
160 }
161
regioninvalidationWithPassByConstPtr()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]}}
166 }
167
168 struct StructWithSmartPtr {
169 std::unique_ptr<A> P;
170 };
171
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);
178
regioninvalidationWithinStructPassByRef()179 void regioninvalidationWithinStructPassByRef() {
180 StructWithSmartPtr S;
181 pass_struct_with_smart_ptr_by_ref(S);
182 S.P->foo(); // no-warning
183 }
184
regioninvalidationWithinStructPassByConstRef()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]}}
189 }
190
regioninvalidationWithinStructPassByRValueRef()191 void regioninvalidationWithinStructPassByRValueRef() {
192 StructWithSmartPtr S;
193 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S));
194 S.P->foo(); // no-warning
195 }
196
regioninvalidationWithinStructPassByConstRValueRef()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]}}
201 }
202
regioninvalidationWithinStructPassByPtr()203 void regioninvalidationWithinStructPassByPtr() {
204 StructWithSmartPtr S;
205 pass_struct_with_smart_ptr_by_ptr(&S);
206 S.P->foo(); // no-warning
207 }
208
regioninvalidationWithinStructPassByConstPtr()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]}}
213 }
214
derefAfterAssignment()215 void derefAfterAssignment() {
216 {
217 std::unique_ptr<A> P(new A());
218 std::unique_ptr<A> Q;
219 Q = std::move(P);
220 Q->foo(); // no-warning
221 }
222 {
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]}}
227 }
228 }
229
derefOnSwappedNullPtr()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]}}
236 }
237
derefOnFirstStdSwappedNullPtr()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]}}
243 }
244
derefOnSecondStdSwappedNullPtr()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]}}
250 }
251
derefOnSwappedValidPtr()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.
261 }
262
derefOnRawPtrFromGetOnNullPtr()263 void derefOnRawPtrFromGetOnNullPtr() {
264 std::unique_ptr<A> P;
265 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
266 }
267
derefOnRawPtrFromGetOnValidPtr()268 void derefOnRawPtrFromGetOnValidPtr() {
269 std::unique_ptr<A> P(new A());
270 P.get()->foo(); // No warning.
271 }
272
derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P)273 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) {
274 P.get()->foo(); // No warning.
275 }
276
derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P)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]}}
283 }
284 }
285
derefOnMovedFromValidPtr()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]}}
291 }
292
derefOnMovedToNullPtr()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.
298 }
299
derefOnNullPtrGotMovedFromValidPtr()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]}}
305 }
306
derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove)307 void derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove) {
308 std::unique_ptr<A> P;
309 P = std::move(PToMove);
310 P->foo(); // No warning.
311 }
312
derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove)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]}}
317 }
318
derefOnAssignedNullPtrToNullSmartPtr()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]}}
323 }
324
derefOnAssignedZeroToNullSmartPtr()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]}}
329 }
330
derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P)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]}}
334 }
335
336 std::unique_ptr<A> &&returnRValRefOfUniquePtr();
337
drefOnAssignedNullFromMethodPtrValidSmartPtr()338 void drefOnAssignedNullFromMethodPtrValidSmartPtr() {
339 std::unique_ptr<A> P(new A());
340 P = returnRValRefOfUniquePtr();
341 P->foo(); // No warning.
342 }
343
derefMoveConstructedWithValidPtr()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.
348 }
349
derefMoveConstructedWithNullPtr()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]}}
354 }
355
derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove)356 void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) {
357 std::unique_ptr<A> P(std::move(PToMove));
358 P->foo(); // No warning.
359 }
360
derefValidPtrMovedToConstruct()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]}}
365 }
366
derefNullPtrMovedToConstruct()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]}}
371 }
372
derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove)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]}}
376 }
377
378 std::unique_ptr<A> &&functionReturnsRValueRef();
379
derefMoveConstructedWithRValueRefReturn()380 void derefMoveConstructedWithRValueRefReturn() {
381 std::unique_ptr<A> P(functionReturnsRValueRef());
382 P->foo(); // No warning.
383 }
384
derefConditionOnNullPtr()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]}}
391 }
392
derefConditionOnNotNullPtr()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]}}
397 }
398
derefConditionOnValidPtr()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]}}
404 }
405
derefConditionOnNotValidPtr()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.
411 }
412
derefConditionOnUnKnownPtr(std::unique_ptr<A> P)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]}}
418 }
419
derefOnValidPtrAfterReset(std::unique_ptr<A> P)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.
426 }
427
innerPointerSymbolLiveness()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}}
433
boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P)434 void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) {
435 if (P) {
436 int *X = P.get();
437 clang_analyzer_warnOnDeadSymbol(X);
438 }
439 } // expected-warning{{SYMBOL DEAD}}
440
getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P)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}}
448 }
449 }
450
derefConditionOnUnKnownPtr(int * q)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]}}
457 }
458
derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P)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]}}
463 }
464 }
465
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);
471
uniquePtrComparision(std::unique_ptr<int> unknownPtr)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));
476
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}}
480
481 clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
482 clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
483
484 clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
485 clang_analyzer_eval(ptr > nullPtr); // expected-warning{{TRUE}}
486
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}}
490 }
491
uniquePtrComparisionStateSplitting(std::unique_ptr<int> unknownPtr)492 void uniquePtrComparisionStateSplitting(std::unique_ptr<int> unknownPtr) {
493 auto ptr = std::unique_ptr<int>(new int(13));
494
495 clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}}
496 // expected-warning@-1{{FALSE}}
497 }
498
uniquePtrComparisionDifferingTypes(std::unique_ptr<int> unknownPtr)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));
503
504 clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
505 clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
506
507 clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
508 clang_analyzer_eval(ptr > nullPtr); // expected-warning{{TRUE}}
509
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}}
513 }
514
515 #if __cplusplus >= 202002L
516
testOstreamOverload(std::unique_ptr<int> P)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}}
528 }
529
530 int glob;
testOstreamDoesntInvalidateGlobals(std::unique_ptr<int> P)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}}
536 }
537
538 #endif
539
540 // The following test isn't really a "smart-ptr" test
541 // It came up during a bug fix (D106296)
testCheckForFunctionsWithNoDecl(void (* bar)(bool,bool))542 void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
543 // This should NOT crash.
544 bar(true, false);
545 }
546