Clang Project

clang_source_code/test/Analysis/cxx-uninitialized-object-unguarded-access.cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
2// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
3// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:IgnoreGuardedFields=true \
4// 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}
441