blob: fd8caf324aa39ff9ef5e718e836572b1178de699 [file] [log] [blame]
Jordan Rosebc403862013-02-15 00:32:15 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
Jordan Rosebf83e7c2012-08-03 23:08:36 +00002
3void clang_analyzer_eval(bool);
Jordan Rosede5277f2012-08-31 17:06:49 +00004void clang_analyzer_checkInlined(bool);
Jordan Rose1d3ca252012-07-26 20:04:30 +00005
Jordan Rosebc403862013-02-15 00:32:15 +00006// A simplified version of std::move.
7template <typename T>
8T &&move(T &obj) {
9 return static_cast<T &&>(obj);
10}
11
12
Jordan Rose1d3ca252012-07-26 20:04:30 +000013struct Wrapper {
14 __strong id obj;
15};
16
17void test() {
18 Wrapper w;
19 // force a diagnostic
20 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
21}
Jordan Rosebf83e7c2012-08-03 23:08:36 +000022
23
24struct IntWrapper {
25 int x;
26};
27
28void testCopyConstructor() {
29 IntWrapper a;
30 a.x = 42;
31
32 IntWrapper b(a);
33 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
34}
35
36struct NonPODIntWrapper {
37 int x;
38
39 virtual int get();
40};
41
42void testNonPODCopyConstructor() {
43 NonPODIntWrapper a;
44 a.x = 42;
45
46 NonPODIntWrapper b(a);
47 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
48}
49
Jordan Rose4e79fdf2012-08-15 20:07:17 +000050
51namespace ConstructorVirtualCalls {
52 class A {
53 public:
54 int *out1, *out2, *out3;
55
56 virtual int get() { return 1; }
57
58 A(int *out1) {
59 *out1 = get();
60 }
61 };
62
63 class B : public A {
64 public:
65 virtual int get() { return 2; }
66
67 B(int *out1, int *out2) : A(out1) {
68 *out2 = get();
69 }
70 };
71
72 class C : public B {
73 public:
74 virtual int get() { return 3; }
75
76 C(int *out1, int *out2, int *out3) : B(out1, out2) {
77 *out3 = get();
78 }
79 };
80
81 void test() {
82 int a, b, c;
83
84 C obj(&a, &b, &c);
85 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
86 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
87 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
88
89 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
90
91 // Sanity check for devirtualization.
92 A *base = &obj;
93 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
94 }
95}
96
Jordan Rosede5277f2012-08-31 17:06:49 +000097namespace TemporaryConstructor {
98 class BoolWrapper {
99 public:
100 BoolWrapper() {
101 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
102 value = true;
103 }
104 bool value;
105 };
Jordan Rose4e79fdf2012-08-15 20:07:17 +0000106
Jordan Rosede5277f2012-08-31 17:06:49 +0000107 void test() {
108 // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
109 if (BoolWrapper().value)
110 return;
111 }
112}
Jordan Rose0504a592012-10-01 17:51:35 +0000113
114
115namespace ConstructorUsedAsRValue {
116 using TemporaryConstructor::BoolWrapper;
117
118 bool extractValue(BoolWrapper b) {
119 return b.value;
120 }
121
122 void test() {
123 bool result = extractValue(BoolWrapper());
124 clang_analyzer_eval(result); // expected-warning{{TRUE}}
125 }
126}
Jordan Rosebc403862013-02-15 00:32:15 +0000127
128namespace PODUninitialized {
129 class POD {
130 public:
131 int x, y;
132 };
133
134 class PODWrapper {
135 public:
136 POD p;
137 };
138
139 class NonPOD {
140 public:
141 int x, y;
142
143 NonPOD() {}
144 NonPOD(const NonPOD &Other)
145 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
146 {
147 }
148 NonPOD(NonPOD &&Other)
149 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
150 {
151 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000152
153 NonPOD &operator=(const NonPOD &Other)
154 {
155 x = Other.x;
156 y = Other.y; // expected-warning {{undefined}}
157 return *this;
158 }
159 NonPOD &operator=(NonPOD &&Other)
160 {
161 x = Other.x;
162 y = Other.y; // expected-warning {{undefined}}
163 return *this;
164 }
Jordan Rosebc403862013-02-15 00:32:15 +0000165 };
166
167 class NonPODWrapper {
168 public:
169 class Inner {
170 public:
171 int x, y;
172
173 Inner() {}
174 Inner(const Inner &Other)
175 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
176 {
177 }
178 Inner(Inner &&Other)
179 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
180 {
181 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000182
183 Inner &operator=(const Inner &Other)
184 {
185 x = Other.x; // expected-warning {{undefined}}
186 y = Other.y;
187 return *this;
188 }
189 Inner &operator=(Inner &&Other)
190 {
191 x = Other.x; // expected-warning {{undefined}}
192 y = Other.y;
193 return *this;
194 }
Jordan Rosebc403862013-02-15 00:32:15 +0000195 };
196
197 Inner p;
198 };
199
200 void testPOD() {
201 POD p;
202 p.x = 1;
203 POD p2 = p; // no-warning
204 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
205 POD p3 = move(p); // no-warning
206 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
207
208 // Use rvalues as well.
209 clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
210
211 PODWrapper w;
212 w.p.y = 1;
213 PODWrapper w2 = w; // no-warning
214 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
215 PODWrapper w3 = move(w); // no-warning
216 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
217
218 // Use rvalues as well.
219 clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
220 }
221
222 void testNonPOD() {
223 NonPOD p;
224 p.x = 1;
225 NonPOD p2 = p;
226 }
227
228 void testNonPODMove() {
229 NonPOD p;
230 p.x = 1;
231 NonPOD p2 = move(p);
232 }
233
234 void testNonPODWrapper() {
235 NonPODWrapper w;
236 w.p.y = 1;
237 NonPODWrapper w2 = w;
238 }
239
240 void testNonPODWrapperMove() {
241 NonPODWrapper w;
242 w.p.y = 1;
243 NonPODWrapper w2 = move(w);
244 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000245
246 // Not strictly about constructors, but trivial assignment operators should
247 // essentially work the same way.
248 namespace AssignmentOperator {
249 void testPOD() {
250 POD p;
251 p.x = 1;
252 POD p2;
253 p2 = p; // no-warning
254 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
255 POD p3;
256 p3 = move(p); // no-warning
257 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
258
259 PODWrapper w;
260 w.p.y = 1;
261 PODWrapper w2;
262 w2 = w; // no-warning
263 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
264 PODWrapper w3;
265 w3 = move(w); // no-warning
266 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
267 }
268
269 void testReturnValue() {
270 POD p;
271 p.x = 1;
272 POD p2;
273 clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
274
275 PODWrapper w;
276 w.p.y = 1;
277 PODWrapper w2;
278 clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
279 }
280
281 void testNonPOD() {
282 NonPOD p;
283 p.x = 1;
284 NonPOD p2;
285 p2 = p;
286 }
287
288 void testNonPODMove() {
289 NonPOD p;
290 p.x = 1;
291 NonPOD p2;
292 p2 = move(p);
293 }
294
295 void testNonPODWrapper() {
296 NonPODWrapper w;
297 w.p.y = 1;
298 NonPODWrapper w2;
299 w2 = w;
300 }
301
302 void testNonPODWrapperMove() {
303 NonPODWrapper w;
304 w.p.y = 1;
305 NonPODWrapper w2;
306 w2 = move(w);
307 }
308 }
Jordan Rosebc403862013-02-15 00:32:15 +0000309}