xref: /aosp_15_r20/external/clang/test/Analysis/dtor.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection,cplusplus -analyzer-config c++-inlining=destructors,cfg-temporary-dtors=true -Wno-null-dereference -Wno-inaccessible-base -verify %s
2*67e74705SXin Li 
3*67e74705SXin Li void clang_analyzer_eval(bool);
4*67e74705SXin Li void clang_analyzer_checkInlined(bool);
5*67e74705SXin Li 
6*67e74705SXin Li class A {
7*67e74705SXin Li public:
~A()8*67e74705SXin Li   ~A() {
9*67e74705SXin Li     int *x = 0;
10*67e74705SXin Li     *x = 3; // expected-warning{{Dereference of null pointer}}
11*67e74705SXin Li   }
12*67e74705SXin Li };
13*67e74705SXin Li 
main()14*67e74705SXin Li int main() {
15*67e74705SXin Li   A a;
16*67e74705SXin Li }
17*67e74705SXin Li 
18*67e74705SXin Li 
19*67e74705SXin Li typedef __typeof(sizeof(int)) size_t;
20*67e74705SXin Li void *malloc(size_t);
21*67e74705SXin Li void free(void *);
22*67e74705SXin Li 
23*67e74705SXin Li class SmartPointer {
24*67e74705SXin Li   void *X;
25*67e74705SXin Li public:
SmartPointer(void * x)26*67e74705SXin Li   SmartPointer(void *x) : X(x) {}
~SmartPointer()27*67e74705SXin Li   ~SmartPointer() {
28*67e74705SXin Li     free(X);
29*67e74705SXin Li   }
30*67e74705SXin Li };
31*67e74705SXin Li 
testSmartPointer()32*67e74705SXin Li void testSmartPointer() {
33*67e74705SXin Li   char *mem = (char*)malloc(4);
34*67e74705SXin Li   {
35*67e74705SXin Li     SmartPointer Deleter(mem);
36*67e74705SXin Li     // destructor called here
37*67e74705SXin Li   }
38*67e74705SXin Li   *mem = 0; // expected-warning{{Use of memory after it is freed}}
39*67e74705SXin Li }
40*67e74705SXin Li 
41*67e74705SXin Li 
42*67e74705SXin Li void doSomething();
testSmartPointer2()43*67e74705SXin Li void testSmartPointer2() {
44*67e74705SXin Li   char *mem = (char*)malloc(4);
45*67e74705SXin Li   {
46*67e74705SXin Li     SmartPointer Deleter(mem);
47*67e74705SXin Li     // Remove dead bindings...
48*67e74705SXin Li     doSomething();
49*67e74705SXin Li     // destructor called here
50*67e74705SXin Li   }
51*67e74705SXin Li   *mem = 0; // expected-warning{{Use of memory after it is freed}}
52*67e74705SXin Li }
53*67e74705SXin Li 
54*67e74705SXin Li 
55*67e74705SXin Li class Subclass : public SmartPointer {
56*67e74705SXin Li public:
Subclass(void * x)57*67e74705SXin Li   Subclass(void *x) : SmartPointer(x) {}
58*67e74705SXin Li };
59*67e74705SXin Li 
testSubclassSmartPointer()60*67e74705SXin Li void testSubclassSmartPointer() {
61*67e74705SXin Li   char *mem = (char*)malloc(4);
62*67e74705SXin Li   {
63*67e74705SXin Li     Subclass Deleter(mem);
64*67e74705SXin Li     // Remove dead bindings...
65*67e74705SXin Li     doSomething();
66*67e74705SXin Li     // destructor called here
67*67e74705SXin Li   }
68*67e74705SXin Li   *mem = 0; // expected-warning{{Use of memory after it is freed}}
69*67e74705SXin Li }
70*67e74705SXin Li 
71*67e74705SXin Li 
72*67e74705SXin Li class MultipleInheritance : public Subclass, public SmartPointer {
73*67e74705SXin Li public:
MultipleInheritance(void * a,void * b)74*67e74705SXin Li   MultipleInheritance(void *a, void *b) : Subclass(a), SmartPointer(b) {}
75*67e74705SXin Li };
76*67e74705SXin Li 
testMultipleInheritance1()77*67e74705SXin Li void testMultipleInheritance1() {
78*67e74705SXin Li   char *mem = (char*)malloc(4);
79*67e74705SXin Li   {
80*67e74705SXin Li     MultipleInheritance Deleter(mem, 0);
81*67e74705SXin Li     // Remove dead bindings...
82*67e74705SXin Li     doSomething();
83*67e74705SXin Li     // destructor called here
84*67e74705SXin Li   }
85*67e74705SXin Li   *mem = 0; // expected-warning{{Use of memory after it is freed}}
86*67e74705SXin Li }
87*67e74705SXin Li 
testMultipleInheritance2()88*67e74705SXin Li void testMultipleInheritance2() {
89*67e74705SXin Li   char *mem = (char*)malloc(4);
90*67e74705SXin Li   {
91*67e74705SXin Li     MultipleInheritance Deleter(0, mem);
92*67e74705SXin Li     // Remove dead bindings...
93*67e74705SXin Li     doSomething();
94*67e74705SXin Li     // destructor called here
95*67e74705SXin Li   }
96*67e74705SXin Li   *mem = 0; // expected-warning{{Use of memory after it is freed}}
97*67e74705SXin Li }
98*67e74705SXin Li 
testMultipleInheritance3()99*67e74705SXin Li void testMultipleInheritance3() {
100*67e74705SXin Li   char *mem = (char*)malloc(4);
101*67e74705SXin Li   {
102*67e74705SXin Li     MultipleInheritance Deleter(mem, mem);
103*67e74705SXin Li     // Remove dead bindings...
104*67e74705SXin Li     doSomething();
105*67e74705SXin Li     // destructor called here
106*67e74705SXin Li     // expected-warning@28 {{Attempt to free released memory}}
107*67e74705SXin Li   }
108*67e74705SXin Li }
109*67e74705SXin Li 
110*67e74705SXin Li 
111*67e74705SXin Li class SmartPointerMember {
112*67e74705SXin Li   SmartPointer P;
113*67e74705SXin Li public:
SmartPointerMember(void * x)114*67e74705SXin Li   SmartPointerMember(void *x) : P(x) {}
115*67e74705SXin Li };
116*67e74705SXin Li 
testSmartPointerMember()117*67e74705SXin Li void testSmartPointerMember() {
118*67e74705SXin Li   char *mem = (char*)malloc(4);
119*67e74705SXin Li   {
120*67e74705SXin Li     SmartPointerMember Deleter(mem);
121*67e74705SXin Li     // Remove dead bindings...
122*67e74705SXin Li     doSomething();
123*67e74705SXin Li     // destructor called here
124*67e74705SXin Li   }
125*67e74705SXin Li   *mem = 0; // expected-warning{{Use of memory after it is freed}}
126*67e74705SXin Li }
127*67e74705SXin Li 
128*67e74705SXin Li 
129*67e74705SXin Li struct IntWrapper {
IntWrapperIntWrapper130*67e74705SXin Li   IntWrapper() : x(0) {}
131*67e74705SXin Li   ~IntWrapper();
132*67e74705SXin Li   int *x;
133*67e74705SXin Li };
134*67e74705SXin Li 
testArrayInvalidation()135*67e74705SXin Li void testArrayInvalidation() {
136*67e74705SXin Li   int i = 42;
137*67e74705SXin Li   int j = 42;
138*67e74705SXin Li 
139*67e74705SXin Li   {
140*67e74705SXin Li     IntWrapper arr[2];
141*67e74705SXin Li 
142*67e74705SXin Li     // There should be no undefined value warnings here.
143*67e74705SXin Li     // Eventually these should be TRUE as well, but right now
144*67e74705SXin Li     // we can't handle array constructors.
145*67e74705SXin Li     clang_analyzer_eval(arr[0].x == 0); // expected-warning{{UNKNOWN}}
146*67e74705SXin Li     clang_analyzer_eval(arr[1].x == 0); // expected-warning{{UNKNOWN}}
147*67e74705SXin Li 
148*67e74705SXin Li     arr[0].x = &i;
149*67e74705SXin Li     arr[1].x = &j;
150*67e74705SXin Li     clang_analyzer_eval(*arr[0].x == 42); // expected-warning{{TRUE}}
151*67e74705SXin Li     clang_analyzer_eval(*arr[1].x == 42); // expected-warning{{TRUE}}
152*67e74705SXin Li   }
153*67e74705SXin Li 
154*67e74705SXin Li   // The destructors should have invalidated i and j.
155*67e74705SXin Li   clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}}
156*67e74705SXin Li   clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}}
157*67e74705SXin Li }
158*67e74705SXin Li 
159*67e74705SXin Li 
160*67e74705SXin Li 
161*67e74705SXin Li // Don't crash on a default argument inside an initializer.
162*67e74705SXin Li struct DefaultArg {
DefaultArgDefaultArg163*67e74705SXin Li   DefaultArg(int x = 0) {}
164*67e74705SXin Li   ~DefaultArg();
165*67e74705SXin Li };
166*67e74705SXin Li 
167*67e74705SXin Li struct InheritsDefaultArg : DefaultArg {
InheritsDefaultArgInheritsDefaultArg168*67e74705SXin Li   InheritsDefaultArg() {}
169*67e74705SXin Li   virtual ~InheritsDefaultArg();
170*67e74705SXin Li };
171*67e74705SXin Li 
testDefaultArg()172*67e74705SXin Li void testDefaultArg() {
173*67e74705SXin Li   InheritsDefaultArg a;
174*67e74705SXin Li   // Force a bug to be emitted.
175*67e74705SXin Li   *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
176*67e74705SXin Li }
177*67e74705SXin Li 
178*67e74705SXin Li 
179*67e74705SXin Li namespace DestructorVirtualCalls {
180*67e74705SXin Li   class A {
181*67e74705SXin Li   public:
182*67e74705SXin Li     int *out1, *out2, *out3;
183*67e74705SXin Li 
get()184*67e74705SXin Li     virtual int get() { return 1; }
185*67e74705SXin Li 
~A()186*67e74705SXin Li     ~A() {
187*67e74705SXin Li       *out1 = get();
188*67e74705SXin Li     }
189*67e74705SXin Li   };
190*67e74705SXin Li 
191*67e74705SXin Li   class B : public A {
192*67e74705SXin Li   public:
get()193*67e74705SXin Li     virtual int get() { return 2; }
194*67e74705SXin Li 
~B()195*67e74705SXin Li     ~B() {
196*67e74705SXin Li       *out2 = get();
197*67e74705SXin Li     }
198*67e74705SXin Li   };
199*67e74705SXin Li 
200*67e74705SXin Li   class C : public B {
201*67e74705SXin Li   public:
get()202*67e74705SXin Li     virtual int get() { return 3; }
203*67e74705SXin Li 
~C()204*67e74705SXin Li     ~C() {
205*67e74705SXin Li       *out3 = get();
206*67e74705SXin Li     }
207*67e74705SXin Li   };
208*67e74705SXin Li 
test()209*67e74705SXin Li   void test() {
210*67e74705SXin Li     int a, b, c;
211*67e74705SXin Li 
212*67e74705SXin Li     // New scope for the C object.
213*67e74705SXin Li     {
214*67e74705SXin Li       C obj;
215*67e74705SXin Li       clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
216*67e74705SXin Li 
217*67e74705SXin Li       // Sanity check for devirtualization.
218*67e74705SXin Li       A *base = &obj;
219*67e74705SXin Li       clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
220*67e74705SXin Li 
221*67e74705SXin Li       obj.out1 = &a;
222*67e74705SXin Li       obj.out2 = &b;
223*67e74705SXin Li       obj.out3 = &c;
224*67e74705SXin Li     }
225*67e74705SXin Li 
226*67e74705SXin Li     clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
227*67e74705SXin Li     clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
228*67e74705SXin Li     clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
229*67e74705SXin Li   }
230*67e74705SXin Li }
231*67e74705SXin Li 
232*67e74705SXin Li 
233*67e74705SXin Li namespace DestructorsShouldNotAffectReturnValues {
234*67e74705SXin Li   class Dtor {
235*67e74705SXin Li   public:
~Dtor()236*67e74705SXin Li     ~Dtor() {
237*67e74705SXin Li       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
238*67e74705SXin Li     }
239*67e74705SXin Li   };
240*67e74705SXin Li 
allocate()241*67e74705SXin Li   void *allocate() {
242*67e74705SXin Li     Dtor d;
243*67e74705SXin Li     return malloc(4); // no-warning
244*67e74705SXin Li   }
245*67e74705SXin Li 
test()246*67e74705SXin Li   void test() {
247*67e74705SXin Li     // At one point we had an issue where the statements inside an
248*67e74705SXin Li     // inlined destructor kept us from finding the return statement,
249*67e74705SXin Li     // leading the analyzer to believe that the malloc'd memory had leaked.
250*67e74705SXin Li     void *p = allocate();
251*67e74705SXin Li     free(p); // no-warning
252*67e74705SXin Li   }
253*67e74705SXin Li }
254*67e74705SXin Li 
255*67e74705SXin Li namespace MultipleInheritanceVirtualDtors {
256*67e74705SXin Li   class VirtualDtor {
257*67e74705SXin Li   protected:
~VirtualDtor()258*67e74705SXin Li     virtual ~VirtualDtor() {
259*67e74705SXin Li       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
260*67e74705SXin Li     }
261*67e74705SXin Li   };
262*67e74705SXin Li 
263*67e74705SXin Li   class NonVirtualDtor {
264*67e74705SXin Li   protected:
~NonVirtualDtor()265*67e74705SXin Li     ~NonVirtualDtor() {
266*67e74705SXin Li       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
267*67e74705SXin Li     }
268*67e74705SXin Li   };
269*67e74705SXin Li 
270*67e74705SXin Li   class SubclassA : public VirtualDtor, public NonVirtualDtor {
271*67e74705SXin Li   public:
~SubclassA()272*67e74705SXin Li     virtual ~SubclassA() {}
273*67e74705SXin Li   };
274*67e74705SXin Li   class SubclassB : public NonVirtualDtor, public VirtualDtor {
275*67e74705SXin Li   public:
~SubclassB()276*67e74705SXin Li     virtual ~SubclassB() {}
277*67e74705SXin Li   };
278*67e74705SXin Li 
test()279*67e74705SXin Li   void test() {
280*67e74705SXin Li     SubclassA a;
281*67e74705SXin Li     SubclassB b;
282*67e74705SXin Li   }
283*67e74705SXin Li }
284*67e74705SXin Li 
285*67e74705SXin Li namespace ExplicitDestructorCall {
286*67e74705SXin Li   class VirtualDtor {
287*67e74705SXin Li   public:
~VirtualDtor()288*67e74705SXin Li     virtual ~VirtualDtor() {
289*67e74705SXin Li       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
290*67e74705SXin Li     }
291*67e74705SXin Li   };
292*67e74705SXin Li 
293*67e74705SXin Li   class Subclass : public VirtualDtor {
294*67e74705SXin Li   public:
~Subclass()295*67e74705SXin Li     virtual ~Subclass() {
296*67e74705SXin Li       clang_analyzer_checkInlined(false); // no-warning
297*67e74705SXin Li     }
298*67e74705SXin Li   };
299*67e74705SXin Li 
destroy(Subclass * obj)300*67e74705SXin Li   void destroy(Subclass *obj) {
301*67e74705SXin Li     obj->VirtualDtor::~VirtualDtor();
302*67e74705SXin Li   }
303*67e74705SXin Li }
304*67e74705SXin Li 
305*67e74705SXin Li 
306*67e74705SXin Li namespace MultidimensionalArrays {
testArrayInvalidation()307*67e74705SXin Li   void testArrayInvalidation() {
308*67e74705SXin Li     int i = 42;
309*67e74705SXin Li     int j = 42;
310*67e74705SXin Li 
311*67e74705SXin Li     {
312*67e74705SXin Li       IntWrapper arr[2][2];
313*67e74705SXin Li 
314*67e74705SXin Li       // There should be no undefined value warnings here.
315*67e74705SXin Li       // Eventually these should be TRUE as well, but right now
316*67e74705SXin Li       // we can't handle array constructors.
317*67e74705SXin Li       clang_analyzer_eval(arr[0][0].x == 0); // expected-warning{{UNKNOWN}}
318*67e74705SXin Li       clang_analyzer_eval(arr[1][1].x == 0); // expected-warning{{UNKNOWN}}
319*67e74705SXin Li 
320*67e74705SXin Li       arr[0][0].x = &i;
321*67e74705SXin Li       arr[1][1].x = &j;
322*67e74705SXin Li       clang_analyzer_eval(*arr[0][0].x == 42); // expected-warning{{TRUE}}
323*67e74705SXin Li       clang_analyzer_eval(*arr[1][1].x == 42); // expected-warning{{TRUE}}
324*67e74705SXin Li     }
325*67e74705SXin Li 
326*67e74705SXin Li     // The destructors should have invalidated i and j.
327*67e74705SXin Li     clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}}
328*67e74705SXin Li     clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}}
329*67e74705SXin Li   }
330*67e74705SXin Li }
331*67e74705SXin Li 
332*67e74705SXin Li namespace LifetimeExtension {
333*67e74705SXin Li   struct IntWrapper {
334*67e74705SXin Li 	int x;
IntWrapperLifetimeExtension::IntWrapper335*67e74705SXin Li 	IntWrapper(int y) : x(y) {}
IntWrapperLifetimeExtension::IntWrapper336*67e74705SXin Li 	IntWrapper() {
337*67e74705SXin Li       extern void use(int);
338*67e74705SXin Li       use(x); // no-warning
339*67e74705SXin Li 	}
340*67e74705SXin Li   };
341*67e74705SXin Li 
342*67e74705SXin Li   struct DerivedWrapper : public IntWrapper {
DerivedWrapperLifetimeExtension::DerivedWrapper343*67e74705SXin Li 	DerivedWrapper(int y) : IntWrapper(y) {}
344*67e74705SXin Li   };
345*67e74705SXin Li 
get()346*67e74705SXin Li   DerivedWrapper get() {
347*67e74705SXin Li 	return DerivedWrapper(1);
348*67e74705SXin Li   }
349*67e74705SXin Li 
test()350*67e74705SXin Li   void test() {
351*67e74705SXin Li 	const DerivedWrapper &d = get(); // lifetime extended here
352*67e74705SXin Li   }
353*67e74705SXin Li 
354*67e74705SXin Li 
355*67e74705SXin Li   class SaveOnDestruct {
356*67e74705SXin Li   public:
357*67e74705SXin Li     static int lastOutput;
358*67e74705SXin Li     int value;
359*67e74705SXin Li 
360*67e74705SXin Li     SaveOnDestruct();
~SaveOnDestruct()361*67e74705SXin Li     ~SaveOnDestruct() {
362*67e74705SXin Li       lastOutput = value;
363*67e74705SXin Li     }
364*67e74705SXin Li   };
365*67e74705SXin Li 
testSimple()366*67e74705SXin Li   void testSimple() {
367*67e74705SXin Li     {
368*67e74705SXin Li       const SaveOnDestruct &obj = SaveOnDestruct();
369*67e74705SXin Li       if (obj.value != 42)
370*67e74705SXin Li         return;
371*67e74705SXin Li       // destructor called here
372*67e74705SXin Li     }
373*67e74705SXin Li 
374*67e74705SXin Li     clang_analyzer_eval(SaveOnDestruct::lastOutput == 42); // expected-warning{{TRUE}}
375*67e74705SXin Li   }
376*67e74705SXin Li 
377*67e74705SXin Li   struct NRCheck {
378*67e74705SXin Li     bool bool_;
NRCheckLifetimeExtension::NRCheck379*67e74705SXin Li     NRCheck():bool_(true) {}
380*67e74705SXin Li     ~NRCheck() __attribute__((noreturn));
operator boolLifetimeExtension::NRCheck381*67e74705SXin Li     operator bool() const { return bool_; }
382*67e74705SXin Li   };
383*67e74705SXin Li 
384*67e74705SXin Li   struct CheckAutoDestructor {
385*67e74705SXin Li     bool bool_;
CheckAutoDestructorLifetimeExtension::CheckAutoDestructor386*67e74705SXin Li     CheckAutoDestructor():bool_(true) {}
operator boolLifetimeExtension::CheckAutoDestructor387*67e74705SXin Li     operator bool() const { return bool_; }
388*67e74705SXin Li   };
389*67e74705SXin Li 
390*67e74705SXin Li   struct CheckCustomDestructor {
391*67e74705SXin Li     bool bool_;
CheckCustomDestructorLifetimeExtension::CheckCustomDestructor392*67e74705SXin Li     CheckCustomDestructor():bool_(true) {}
393*67e74705SXin Li     ~CheckCustomDestructor();
operator boolLifetimeExtension::CheckCustomDestructor394*67e74705SXin Li     operator bool() const { return bool_; }
395*67e74705SXin Li   };
396*67e74705SXin Li 
testUnnamedNR()397*67e74705SXin Li   bool testUnnamedNR() {
398*67e74705SXin Li     if (NRCheck())
399*67e74705SXin Li       return true;
400*67e74705SXin Li     return false;
401*67e74705SXin Li   }
402*67e74705SXin Li 
testNamedNR()403*67e74705SXin Li   bool testNamedNR() {
404*67e74705SXin Li     if (NRCheck c = NRCheck())
405*67e74705SXin Li       return true;
406*67e74705SXin Li     return false;
407*67e74705SXin Li   }
408*67e74705SXin Li 
testUnnamedAutoDestructor()409*67e74705SXin Li   bool testUnnamedAutoDestructor() {
410*67e74705SXin Li     if (CheckAutoDestructor())
411*67e74705SXin Li       return true;
412*67e74705SXin Li     return false;
413*67e74705SXin Li   }
414*67e74705SXin Li 
testNamedAutoDestructor()415*67e74705SXin Li   bool testNamedAutoDestructor() {
416*67e74705SXin Li     if (CheckAutoDestructor c = CheckAutoDestructor())
417*67e74705SXin Li       return true;
418*67e74705SXin Li     return false;
419*67e74705SXin Li   }
420*67e74705SXin Li 
testUnnamedCustomDestructor()421*67e74705SXin Li   bool testUnnamedCustomDestructor() {
422*67e74705SXin Li     if (CheckCustomDestructor())
423*67e74705SXin Li       return true;
424*67e74705SXin Li     return false;
425*67e74705SXin Li   }
426*67e74705SXin Li 
427*67e74705SXin Li   // This case used to cause an unexpected "Undefined or garbage value returned
428*67e74705SXin Li   // to caller" warning
testNamedCustomDestructor()429*67e74705SXin Li   bool testNamedCustomDestructor() {
430*67e74705SXin Li     if (CheckCustomDestructor c = CheckCustomDestructor())
431*67e74705SXin Li       return true;
432*67e74705SXin Li     return false;
433*67e74705SXin Li   }
434*67e74705SXin Li 
testMultipleTemporariesCustomDestructor()435*67e74705SXin Li   bool testMultipleTemporariesCustomDestructor() {
436*67e74705SXin Li     if (CheckCustomDestructor c = (CheckCustomDestructor(), CheckCustomDestructor()))
437*67e74705SXin Li       return true;
438*67e74705SXin Li     return false;
439*67e74705SXin Li   }
440*67e74705SXin Li 
441*67e74705SXin Li   class VirtualDtorBase {
442*67e74705SXin Li   public:
443*67e74705SXin Li     int value;
~VirtualDtorBase()444*67e74705SXin Li     virtual ~VirtualDtorBase() {}
445*67e74705SXin Li   };
446*67e74705SXin Li 
447*67e74705SXin Li   class SaveOnVirtualDestruct : public VirtualDtorBase {
448*67e74705SXin Li   public:
449*67e74705SXin Li     static int lastOutput;
450*67e74705SXin Li 
451*67e74705SXin Li     SaveOnVirtualDestruct();
~SaveOnVirtualDestruct()452*67e74705SXin Li     virtual ~SaveOnVirtualDestruct() {
453*67e74705SXin Li       lastOutput = value;
454*67e74705SXin Li     }
455*67e74705SXin Li   };
456*67e74705SXin Li 
testVirtual()457*67e74705SXin Li   void testVirtual() {
458*67e74705SXin Li     {
459*67e74705SXin Li       const VirtualDtorBase &obj = SaveOnVirtualDestruct();
460*67e74705SXin Li       if (obj.value != 42)
461*67e74705SXin Li         return;
462*67e74705SXin Li       // destructor called here
463*67e74705SXin Li     }
464*67e74705SXin Li 
465*67e74705SXin Li     clang_analyzer_eval(SaveOnVirtualDestruct::lastOutput == 42); // expected-warning{{TRUE}}
466*67e74705SXin Li   }
467*67e74705SXin Li }
468*67e74705SXin Li 
469*67e74705SXin Li namespace NoReturn {
470*67e74705SXin Li   struct NR {
471*67e74705SXin Li     ~NR() __attribute__((noreturn));
472*67e74705SXin Li   };
473*67e74705SXin Li 
f(int ** x)474*67e74705SXin Li   void f(int **x) {
475*67e74705SXin Li     NR nr;
476*67e74705SXin Li   }
477*67e74705SXin Li 
g()478*67e74705SXin Li   void g() {
479*67e74705SXin Li     int *x;
480*67e74705SXin Li     f(&x);
481*67e74705SXin Li     *x = 47; // no warning
482*67e74705SXin Li   }
483*67e74705SXin Li 
g2(int * x)484*67e74705SXin Li   void g2(int *x) {
485*67e74705SXin Li     if (! x) NR();
486*67e74705SXin Li     *x = 47; // no warning
487*67e74705SXin Li   }
488*67e74705SXin Li }
489*67e74705SXin Li 
490*67e74705SXin Li namespace PseudoDtor {
491*67e74705SXin Li   template <typename T>
destroy(T & obj)492*67e74705SXin Li   void destroy(T &obj) {
493*67e74705SXin Li     clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
494*67e74705SXin Li     obj.~T();
495*67e74705SXin Li   }
496*67e74705SXin Li 
test()497*67e74705SXin Li   void test() {
498*67e74705SXin Li     int i;
499*67e74705SXin Li     destroy(i);
500*67e74705SXin Li     clang_analyzer_eval(true); // expected-warning{{TRUE}}
501*67e74705SXin Li   }
502*67e74705SXin Li }
503*67e74705SXin Li 
504*67e74705SXin Li namespace Incomplete {
505*67e74705SXin Li   class Foo; // expected-note{{forward declaration}}
f(Foo * foo)506*67e74705SXin Li   void f(Foo *foo) { delete foo; } // expected-warning{{deleting pointer to incomplete type}}
507*67e74705SXin Li }
508*67e74705SXin Li 
509*67e74705SXin Li namespace TypeTraitExpr {
510*67e74705SXin Li template <bool IsSimple, typename T>
511*67e74705SXin Li struct copier {
512*67e74705SXin Li   static void do_copy(T *dest, const T *src, unsigned count);
513*67e74705SXin Li };
514*67e74705SXin Li template <typename T, typename U>
do_copy(T * dest,const U * src,unsigned count)515*67e74705SXin Li void do_copy(T *dest, const U *src, unsigned count) {
516*67e74705SXin Li   const bool IsSimple = __is_trivial(T) && __is_same(T, U);
517*67e74705SXin Li   copier<IsSimple, T>::do_copy(dest, src, count);
518*67e74705SXin Li }
519*67e74705SXin Li struct NonTrivial {
520*67e74705SXin Li   int *p;
NonTrivialTypeTraitExpr::NonTrivial521*67e74705SXin Li   NonTrivial() : p(new int[1]) { p[0] = 0; }
NonTrivialTypeTraitExpr::NonTrivial522*67e74705SXin Li   NonTrivial(const NonTrivial &other) {
523*67e74705SXin Li     p = new int[1];
524*67e74705SXin Li     do_copy(p, other.p, 1);
525*67e74705SXin Li   }
operator =TypeTraitExpr::NonTrivial526*67e74705SXin Li   NonTrivial &operator=(const NonTrivial &other) {
527*67e74705SXin Li     p = other.p;
528*67e74705SXin Li     return *this;
529*67e74705SXin Li   }
~NonTrivialTypeTraitExpr::NonTrivial530*67e74705SXin Li   ~NonTrivial() {
531*67e74705SXin Li     delete[] p; // expected-warning {{free released memory}}
532*67e74705SXin Li   }
533*67e74705SXin Li };
534*67e74705SXin Li 
f()535*67e74705SXin Li void f() {
536*67e74705SXin Li   NonTrivial nt1;
537*67e74705SXin Li   NonTrivial nt2(nt1);
538*67e74705SXin Li   nt1 = nt2;
539*67e74705SXin Li   clang_analyzer_eval(__is_trivial(NonTrivial)); // expected-warning{{FALSE}}
540*67e74705SXin Li   clang_analyzer_eval(__alignof(NonTrivial) > 0); // expected-warning{{TRUE}}
541*67e74705SXin Li }
542*67e74705SXin Li }
543