blob: 53e72e7c5f4f7c01d121474d9a79c6d833632073 [file] [log] [blame]
Kristof Umann85e0ff72019-04-19 23:33:50 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \
2// RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
3// RUN: -analyzer-config optin.cplusplus.UninitializedObject:IgnoreGuardedFields=true \
Kristof Umannffe93a12019-02-02 14:50:04 +00004// RUN: -std=c++11 -verify %s
5
6//===----------------------------------------------------------------------===//
7// Helper functions for tests.
8//===----------------------------------------------------------------------===//
9
10[[noreturn]] void halt();
11
12void assert(int b) {
13 if (!b)
14 halt();
15}
16
17int rand();
18
19//===----------------------------------------------------------------------===//
20// Tests for fields properly guarded by asserts.
21//===----------------------------------------------------------------------===//
22
23class NoUnguardedFieldsTest {
24public:
25 enum Kind {
26 V,
27 A
28 };
29
30private:
31 int Volume, Area;
32 Kind K;
33
34public:
35 NoUnguardedFieldsTest(Kind K) : K(K) {
36 switch (K) {
37 case V:
38 Volume = 0;
39 break;
40 case A:
41 Area = 0;
42 break;
43 }
44 }
45
46 void operator-() {
47 assert(K == Kind::A);
48 (void)Area;
49 }
50
51 void operator+() {
52 assert(K == Kind::V);
53 (void)Volume;
54 }
55};
56
57void fNoUnguardedFieldsTest() {
58 NoUnguardedFieldsTest T1(NoUnguardedFieldsTest::Kind::A);
59 NoUnguardedFieldsTest T2(NoUnguardedFieldsTest::Kind::V);
60}
61
62class NoUngardedFieldsNoReturnFuncCalledTest {
63public:
64 enum Kind {
65 V,
66 A
67 };
68
69private:
70 int Volume, Area;
71 Kind K;
72
73public:
74 NoUngardedFieldsNoReturnFuncCalledTest(Kind K) : K(K) {
75 switch (K) {
76 case V:
77 Volume = 0;
78 break;
79 case A:
80 Area = 0;
81 break;
82 }
83 }
84
85 void operator-() {
86 halt();
87 (void)Area;
88 }
89
90 void operator+() {
91 halt();
92 (void)Volume;
93 }
94};
95
96void fNoUngardedFieldsNoReturnFuncCalledTest() {
97 NoUngardedFieldsNoReturnFuncCalledTest
98 T1(NoUngardedFieldsNoReturnFuncCalledTest::Kind::A);
99 NoUngardedFieldsNoReturnFuncCalledTest
100 T2(NoUngardedFieldsNoReturnFuncCalledTest::Kind::V);
101}
102
103class NoUnguardedFieldsWithUndefMethodTest {
104public:
105 enum Kind {
106 V,
107 A
108 };
109
110private:
111 int Volume, Area;
112 Kind K;
113
114public:
115 NoUnguardedFieldsWithUndefMethodTest(Kind K) : K(K) {
116 switch (K) {
117 case V:
118 Volume = 0;
119 break;
120 case A:
121 Area = 0;
122 break;
123 }
124 }
125
126 void operator-() {
127 assert(K == Kind::A);
128 (void)Area;
129 }
130
131 void operator+() {
132 assert(K == Kind::V);
133 (void)Volume;
134 }
135
136 // We're checking method definitions for guards, so this is a no-crash test
137 // whether we handle methods without definitions.
138 void methodWithoutDefinition();
139};
140
141void fNoUnguardedFieldsWithUndefMethodTest() {
142 NoUnguardedFieldsWithUndefMethodTest
143 T1(NoUnguardedFieldsWithUndefMethodTest::Kind::A);
144 NoUnguardedFieldsWithUndefMethodTest
145 T2(NoUnguardedFieldsWithUndefMethodTest::Kind::V);
146}
147
148class UnguardedFieldThroughMethodTest {
149public:
150 enum Kind {
151 V,
152 A
153 };
154
155private:
156 int Volume, Area; // expected-note {{uninitialized field 'this->Volume'}}
157 Kind K;
158
159public:
160 UnguardedFieldThroughMethodTest(Kind K) : K(K) {
161 switch (K) {
162 case V:
163 Volume = 0;
164 break;
165 case A:
166 Area = 0; // expected-warning {{1 uninitialized field}}
167 break;
168 }
169 }
170
171 void operator-() {
172 assert(K == Kind::A);
173 (void)Area;
174 }
175
176 void operator+() {
177 (void)Volume;
178 }
179};
180
181void fUnguardedFieldThroughMethodTest() {
182 UnguardedFieldThroughMethodTest T1(UnguardedFieldThroughMethodTest::Kind::A);
183}
184
185class UnguardedPublicFieldsTest {
186public:
187 enum Kind {
188 V,
189 A
190 };
191
192public:
193 // Note that fields are public.
194 int Volume, Area; // expected-note {{uninitialized field 'this->Volume'}}
195 Kind K;
196
197public:
198 UnguardedPublicFieldsTest(Kind K) : K(K) {
199 switch (K) {
200 case V:
201 Volume = 0;
202 break;
203 case A:
204 Area = 0; // expected-warning {{1 uninitialized field}}
205 break;
206 }
207 }
208
209 void operator-() {
210 assert(K == Kind::A);
211 (void)Area;
212 }
213
214 void operator+() {
215 assert(K == Kind::V);
216 (void)Volume;
217 }
218};
219
220void fUnguardedPublicFieldsTest() {
221 UnguardedPublicFieldsTest T1(UnguardedPublicFieldsTest::Kind::A);
222}
223
224//===----------------------------------------------------------------------===//
225// Highlights of some false negatives due to syntactic checking.
226//===----------------------------------------------------------------------===//
227
228class UnguardedFalseNegativeTest1 {
229public:
230 enum Kind {
231 V,
232 A
233 };
234
235private:
236 int Volume, Area;
237 Kind K;
238
239public:
240 UnguardedFalseNegativeTest1(Kind K) : K(K) {
241 switch (K) {
242 case V:
243 Volume = 0;
244 break;
245 case A:
246 Area = 0;
247 break;
248 }
249 }
250
251 void operator-() {
252 if (rand())
253 assert(K == Kind::A);
254 (void)Area;
255 }
256
257 void operator+() {
258 if (rand())
259 assert(K == Kind::V);
260 (void)Volume;
261 }
262};
263
264void fUnguardedFalseNegativeTest1() {
265 UnguardedFalseNegativeTest1 T1(UnguardedFalseNegativeTest1::Kind::A);
266}
267
268class UnguardedFalseNegativeTest2 {
269public:
270 enum Kind {
271 V,
272 A
273 };
274
275private:
276 int Volume, Area;
277 Kind K;
278
279public:
280 UnguardedFalseNegativeTest2(Kind K) : K(K) {
281 switch (K) {
282 case V:
283 Volume = 0;
284 break;
285 case A:
286 Area = 0;
287 break;
288 }
289 }
290
291 void operator-() {
292 assert(rand());
293 (void)Area;
294 }
295
296 void operator+() {
297 assert(rand());
298 (void)Volume;
299 }
300};
301
302void fUnguardedFalseNegativeTest2() {
303 UnguardedFalseNegativeTest2 T1(UnguardedFalseNegativeTest2::Kind::A);
304}
305
306//===----------------------------------------------------------------------===//
307// Tests for other guards. These won't be as thorough, as other guards are
308// matched the same way as asserts, so if they are recognized, they are expected
309// to work as well as asserts do.
310//
311// None of these tests expect warnings, since the flag works correctly if these
312// fields are regarded properly guarded.
313//===----------------------------------------------------------------------===//
314
315class IfGuardedFieldsTest {
316public:
317 enum Kind {
318 V,
319 A
320 };
321
322private:
323 int Volume, Area;
324 Kind K;
325
326public:
327 IfGuardedFieldsTest(Kind K) : K(K) {
328 switch (K) {
329 case V:
330 Volume = 0;
331 break;
332 case A:
333 Area = 0;
334 break;
335 }
336 }
337
338 void operator-() {
339 if (K != Kind::A)
340 return;
341 (void)Area;
342 }
343
344 void operator+() {
345 if (K != Kind::V)
346 return;
347 (void)Volume;
348 }
349};
350
351void fIfGuardedFieldsTest() {
352 IfGuardedFieldsTest T1(IfGuardedFieldsTest::Kind::A);
353 IfGuardedFieldsTest T2(IfGuardedFieldsTest::Kind::V);
354}
355
356class SwitchGuardedFieldsTest {
357public:
358 enum Kind {
359 V,
360 A
361 };
362
363private:
364 int Volume, Area;
365 Kind K;
366
367public:
368 SwitchGuardedFieldsTest(Kind K) : K(K) {
369 switch (K) {
370 case V:
371 Volume = 0;
372 break;
373 case A:
374 Area = 0;
375 break;
376 }
377 }
378
379 int operator-() {
380 switch (K) {
381 case Kind::A:
382 return Area;
383 case Kind::V:
384 return -1;
385 }
386 }
387
388 int operator+() {
389 switch (K) {
390 case Kind::A:
391 return Area;
392 case Kind::V:
393 return -1;
394 }
395 }
396};
397
398void fSwitchGuardedFieldsTest() {
399 SwitchGuardedFieldsTest T1(SwitchGuardedFieldsTest::Kind::A);
400 SwitchGuardedFieldsTest T2(SwitchGuardedFieldsTest::Kind::V);
401}
402
403class ConditionalOperatorGuardedFieldsTest {
404public:
405 enum Kind {
406 V,
407 A
408 };
409
410private:
411 int Volume, Area;
412 Kind K;
413
414public:
415 ConditionalOperatorGuardedFieldsTest(Kind K) : K(K) {
416 switch (K) {
417 case V:
418 Volume = 0;
419 break;
420 case A:
421 Area = 0;
422 break;
423 }
424 }
425
426 int operator-() {
427 return K == Kind::A ? Area : -1;
428 }
429
430 int operator+() {
431 return K == Kind::V ? Volume : -1;
432 }
433};
434
435void fConditionalOperatorGuardedFieldsTest() {
436 ConditionalOperatorGuardedFieldsTest
437 T1(ConditionalOperatorGuardedFieldsTest::Kind::A);
438 ConditionalOperatorGuardedFieldsTest
439 T2(ConditionalOperatorGuardedFieldsTest::Kind::V);
440}