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