dtor.cpp revision e460c46c5d602f65354cab0879c458890273591c
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-implicit-dtors -cfg-add-initializers -verify %s
2
3void clang_analyzer_eval(bool);
4
5class A {
6public:
7  ~A() {
8    int *x = 0;
9    *x = 3; // expected-warning{{Dereference of null pointer}}
10  }
11};
12
13int main() {
14  A a;
15}
16
17
18typedef __typeof(sizeof(int)) size_t;
19void *malloc(size_t);
20void free(void *);
21
22class SmartPointer {
23  void *X;
24public:
25  SmartPointer(void *x) : X(x) {}
26  ~SmartPointer() {
27    free(X);
28  }
29};
30
31void testSmartPointer() {
32  char *mem = (char*)malloc(4);
33  {
34    SmartPointer Deleter(mem);
35    // destructor called here
36  }
37  *mem = 0; // expected-warning{{Use of memory after it is freed}}
38}
39
40
41void doSomething();
42void testSmartPointer2() {
43  char *mem = (char*)malloc(4);
44  {
45    SmartPointer Deleter(mem);
46    // Remove dead bindings...
47    doSomething();
48    // destructor called here
49  }
50  *mem = 0; // expected-warning{{Use of memory after it is freed}}
51}
52
53
54class Subclass : public SmartPointer {
55public:
56  Subclass(void *x) : SmartPointer(x) {}
57};
58
59void testSubclassSmartPointer() {
60  char *mem = (char*)malloc(4);
61  {
62    Subclass Deleter(mem);
63    // Remove dead bindings...
64    doSomething();
65    // destructor called here
66  }
67  *mem = 0; // expected-warning{{Use of memory after it is freed}}
68}
69
70
71class MultipleInheritance : public Subclass, public SmartPointer {
72public:
73  MultipleInheritance(void *a, void *b) : Subclass(a), SmartPointer(b) {}
74};
75
76void testMultipleInheritance1() {
77  char *mem = (char*)malloc(4);
78  {
79    MultipleInheritance Deleter(mem, 0);
80    // Remove dead bindings...
81    doSomething();
82    // destructor called here
83  }
84  *mem = 0; // expected-warning{{Use of memory after it is freed}}
85}
86
87void testMultipleInheritance2() {
88  char *mem = (char*)malloc(4);
89  {
90    MultipleInheritance Deleter(0, mem);
91    // Remove dead bindings...
92    doSomething();
93    // destructor called here
94  }
95  *mem = 0; // expected-warning{{Use of memory after it is freed}}
96}
97
98void testMultipleInheritance3() {
99  char *mem = (char*)malloc(4);
100  {
101    MultipleInheritance Deleter(mem, mem);
102    // Remove dead bindings...
103    doSomething();
104    // destructor called here
105    // expected-warning@27 {{Attempt to free released memory}}
106  }
107}
108
109
110class SmartPointerMember {
111  SmartPointer P;
112public:
113  SmartPointerMember(void *x) : P(x) {}
114};
115
116void testSmartPointerMember() {
117  char *mem = (char*)malloc(4);
118  {
119    SmartPointerMember Deleter(mem);
120    // Remove dead bindings...
121    doSomething();
122    // destructor called here
123  }
124  *mem = 0; // expected-warning{{Use of memory after it is freed}}
125}
126
127
128struct IntWrapper {
129  IntWrapper() : x(0) {}
130  ~IntWrapper();
131  int *x;
132};
133
134void testArrayInvalidation() {
135  int i = 42;
136  int j = 42;
137
138  {
139    IntWrapper arr[2];
140
141    // There should be no undefined value warnings here.
142    // Eventually these should be TRUE as well, but right now
143    // we can't handle array constructors.
144    clang_analyzer_eval(arr[0].x == 0); // expected-warning{{UNKNOWN}}
145    clang_analyzer_eval(arr[1].x == 0); // expected-warning{{UNKNOWN}}
146
147    arr[0].x = &i;
148    arr[1].x = &j;
149    clang_analyzer_eval(*arr[0].x == 42); // expected-warning{{TRUE}}
150    clang_analyzer_eval(*arr[1].x == 42); // expected-warning{{TRUE}}
151  }
152
153  // The destructors should have invalidated i and j.
154  clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}}
155  clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}}
156}
157