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