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:CheckPointeeInitialization=true \ |
4 | // RUN: -std=c++14 -verify %s |
5 | |
6 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \ |
7 | // RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \ |
8 | // RUN: -std=c++14 -verify %s |
9 | |
10 | //===----------------------------------------------------------------------===// |
11 | // Default constructor test. |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | class CompilerGeneratedConstructorTest { |
15 | int a, b, c, d, e, f, g, h, i, j; |
16 | |
17 | public: |
18 | CompilerGeneratedConstructorTest() = default; |
19 | }; |
20 | |
21 | void fCompilerGeneratedConstructorTest() { |
22 | CompilerGeneratedConstructorTest(); |
23 | } |
24 | |
25 | #ifdef PEDANTIC |
26 | class DefaultConstructorTest { |
27 | int a; // expected-note{{uninitialized field 'this->a'}} |
28 | |
29 | public: |
30 | DefaultConstructorTest(); |
31 | }; |
32 | |
33 | DefaultConstructorTest::DefaultConstructorTest() = default; |
34 | |
35 | void fDefaultConstructorTest() { |
36 | DefaultConstructorTest(); // expected-warning{{1 uninitialized field}} |
37 | } |
38 | #else |
39 | class DefaultConstructorTest { |
40 | int a; |
41 | |
42 | public: |
43 | DefaultConstructorTest(); |
44 | }; |
45 | |
46 | DefaultConstructorTest::DefaultConstructorTest() = default; |
47 | |
48 | void fDefaultConstructorTest() { |
49 | DefaultConstructorTest(); |
50 | } |
51 | #endif // PEDANTIC |
52 | |
53 | //===----------------------------------------------------------------------===// |
54 | // Initializer list test. |
55 | //===----------------------------------------------------------------------===// |
56 | |
57 | class InitListTest1 { |
58 | int a; |
59 | int b; |
60 | |
61 | public: |
62 | InitListTest1() |
63 | : a(1), |
64 | b(2) { |
65 | // All good! |
66 | } |
67 | }; |
68 | |
69 | void fInitListTest1() { |
70 | InitListTest1(); |
71 | } |
72 | |
73 | class InitListTest2 { |
74 | int a; |
75 | int b; // expected-note{{uninitialized field 'this->b'}} |
76 | |
77 | public: |
78 | InitListTest2() |
79 | : a(3) {} // expected-warning{{1 uninitialized field}} |
80 | }; |
81 | |
82 | void fInitListTest2() { |
83 | InitListTest2(); |
84 | } |
85 | |
86 | class InitListTest3 { |
87 | int a; // expected-note{{uninitialized field 'this->a'}} |
88 | int b; |
89 | |
90 | public: |
91 | InitListTest3() |
92 | : b(4) {} // expected-warning{{1 uninitialized field}} |
93 | }; |
94 | |
95 | void fInitListTest3() { |
96 | InitListTest3(); |
97 | } |
98 | |
99 | //===----------------------------------------------------------------------===// |
100 | // Constructor body test. |
101 | //===----------------------------------------------------------------------===// |
102 | |
103 | class CtorBodyTest1 { |
104 | int a, b; |
105 | |
106 | public: |
107 | CtorBodyTest1() { |
108 | a = 5; |
109 | b = 6; |
110 | // All good! |
111 | } |
112 | }; |
113 | |
114 | void fCtorBodyTest1() { |
115 | CtorBodyTest1(); |
116 | } |
117 | |
118 | class CtorBodyTest2 { |
119 | int a; |
120 | int b; // expected-note{{uninitialized field 'this->b'}} |
121 | |
122 | public: |
123 | CtorBodyTest2() { |
124 | a = 7; // expected-warning{{1 uninitialized field}} |
125 | } |
126 | }; |
127 | |
128 | void fCtorBodyTest2() { |
129 | CtorBodyTest2(); |
130 | } |
131 | |
132 | class CtorBodyTest3 { |
133 | int a; // expected-note{{uninitialized field 'this->a'}} |
134 | int b; |
135 | |
136 | public: |
137 | CtorBodyTest3() { |
138 | b = 8; // expected-warning{{1 uninitialized field}} |
139 | } |
140 | }; |
141 | |
142 | void fCtorBodyTest3() { |
143 | CtorBodyTest3(); |
144 | } |
145 | |
146 | #ifdef PEDANTIC |
147 | class CtorBodyTest4 { |
148 | int a; // expected-note{{uninitialized field 'this->a'}} |
149 | int b; // expected-note{{uninitialized field 'this->b'}} |
150 | |
151 | public: |
152 | CtorBodyTest4() {} |
153 | }; |
154 | |
155 | void fCtorBodyTest4() { |
156 | CtorBodyTest4(); // expected-warning{{2 uninitialized fields}} |
157 | } |
158 | #else |
159 | class CtorBodyTest4 { |
160 | int a; |
161 | int b; |
162 | |
163 | public: |
164 | CtorBodyTest4() {} |
165 | }; |
166 | |
167 | void fCtorBodyTest4() { |
168 | CtorBodyTest4(); |
169 | } |
170 | #endif |
171 | |
172 | //===----------------------------------------------------------------------===// |
173 | // Constructor delegation test. |
174 | //===----------------------------------------------------------------------===// |
175 | |
176 | class CtorDelegationTest1 { |
177 | int a; |
178 | int b; |
179 | |
180 | public: |
181 | CtorDelegationTest1(int) |
182 | : a(9) { |
183 | // leaves 'b' unintialized, but we'll never check this function |
184 | } |
185 | |
186 | CtorDelegationTest1() |
187 | : CtorDelegationTest1(int{}) { // Initializing 'a' |
188 | b = 10; |
189 | // All good! |
190 | } |
191 | }; |
192 | |
193 | void fCtorDelegationTest1() { |
194 | CtorDelegationTest1(); |
195 | } |
196 | |
197 | class CtorDelegationTest2 { |
198 | int a; // expected-note{{uninitialized field 'this->a'}} |
199 | int b; |
200 | |
201 | public: |
202 | CtorDelegationTest2(int) |
203 | : b(11) { |
204 | // leaves 'a' unintialized, but we'll never check this function |
205 | } |
206 | |
207 | CtorDelegationTest2() |
208 | : CtorDelegationTest2(int{}) { // expected-warning{{1 uninitialized field}} |
209 | } |
210 | }; |
211 | |
212 | void fCtorDelegationTest2() { |
213 | CtorDelegationTest2(); |
214 | } |
215 | |
216 | //===----------------------------------------------------------------------===// |
217 | // Tests for classes containing records. |
218 | //===----------------------------------------------------------------------===// |
219 | |
220 | class ContainsRecordTest1 { |
221 | struct RecordType { |
222 | int x; |
223 | int y; |
224 | } rec; |
225 | int c, d; |
226 | |
227 | public: |
228 | ContainsRecordTest1() |
229 | : rec({12, 13}), |
230 | c(14), |
231 | d(15) { |
232 | // All good! |
233 | } |
234 | }; |
235 | |
236 | void fContainsRecordTest1() { |
237 | ContainsRecordTest1(); |
238 | } |
239 | |
240 | class ContainsRecordTest2 { |
241 | struct RecordType { |
242 | int x; |
243 | int y; // expected-note{{uninitialized field 'this->rec.y'}} |
244 | } rec; |
245 | int c, d; |
246 | |
247 | public: |
248 | ContainsRecordTest2() |
249 | : c(16), |
250 | d(17) { |
251 | rec.x = 18; // expected-warning{{1 uninitialized field}} |
252 | } |
253 | }; |
254 | |
255 | void fContainsRecordTest2() { |
256 | ContainsRecordTest2(); |
257 | } |
258 | |
259 | class ContainsRecordTest3 { |
260 | struct RecordType { |
261 | int x; // expected-note{{uninitialized field 'this->rec.x'}} |
262 | int y; // expected-note{{uninitialized field 'this->rec.y'}} |
263 | } rec; |
264 | int c, d; |
265 | |
266 | public: |
267 | ContainsRecordTest3() |
268 | : c(19), |
269 | d(20) { // expected-warning{{2 uninitialized fields}} |
270 | } |
271 | }; |
272 | |
273 | void fContainsRecordTest3() { |
274 | ContainsRecordTest3(); |
275 | } |
276 | |
277 | class ContainsRecordTest4 { |
278 | struct RecordType { |
279 | int x; // expected-note{{uninitialized field 'this->rec.x'}} |
280 | int y; // expected-note{{uninitialized field 'this->rec.y'}} |
281 | } rec; |
282 | int c, d; // expected-note{{uninitialized field 'this->d'}} |
283 | |
284 | public: |
285 | ContainsRecordTest4() |
286 | : c(19) { // expected-warning{{3 uninitialized fields}} |
287 | } |
288 | }; |
289 | |
290 | void fContainsRecordTest4() { |
291 | ContainsRecordTest4(); |
292 | } |
293 | |
294 | //===----------------------------------------------------------------------===// |
295 | // Tests for template classes. |
296 | //===----------------------------------------------------------------------===// |
297 | |
298 | template <class T> |
299 | class IntTemplateClassTest1 { |
300 | T t; |
301 | int b; |
302 | |
303 | public: |
304 | IntTemplateClassTest1(T i) { |
305 | b = 21; |
306 | t = i; |
307 | // All good! |
308 | } |
309 | }; |
310 | |
311 | void fIntTemplateClassTest1() { |
312 | IntTemplateClassTest1<int>(22); |
313 | } |
314 | |
315 | template <class T> |
316 | class IntTemplateClassTest2 { |
317 | T t; // expected-note{{uninitialized field 'this->t'}} |
318 | int b; |
319 | |
320 | public: |
321 | IntTemplateClassTest2() { |
322 | b = 23; // expected-warning{{1 uninitialized field}} |
323 | } |
324 | }; |
325 | |
326 | void fIntTemplateClassTest2() { |
327 | IntTemplateClassTest2<int>(); |
328 | } |
329 | |
330 | struct Record { |
331 | int x; // expected-note{{uninitialized field 'this->t.x'}} |
332 | int y; // expected-note{{uninitialized field 'this->t.y'}} |
333 | }; |
334 | |
335 | template <class T> |
336 | class RecordTemplateClassTest { |
337 | T t; |
338 | int b; |
339 | |
340 | public: |
341 | RecordTemplateClassTest() { |
342 | b = 24; // expected-warning{{2 uninitialized fields}} |
343 | } |
344 | }; |
345 | |
346 | void fRecordTemplateClassTest() { |
347 | RecordTemplateClassTest<Record>(); |
348 | } |
349 | |
350 | //===----------------------------------------------------------------------===// |
351 | // Tests involving functions with unknown implementations. |
352 | //===----------------------------------------------------------------------===// |
353 | |
354 | template <class T> |
355 | void mayInitialize(T &); |
356 | |
357 | template <class T> |
358 | void wontInitialize(const T &); |
359 | |
360 | class PassingToUnknownFunctionTest1 { |
361 | int a, b; // expected-note{{uninitialized field 'this->b'}} |
362 | |
363 | public: |
364 | PassingToUnknownFunctionTest1() { |
365 | mayInitialize(a); |
366 | mayInitialize(b); |
367 | // All good! |
368 | } |
369 | |
370 | PassingToUnknownFunctionTest1(int) { |
371 | mayInitialize(a); // expected-warning{{1 uninitialized field at the end of the constructor call}} |
372 | } |
373 | |
374 | PassingToUnknownFunctionTest1(int, int) { |
375 | mayInitialize(*this); |
376 | // All good! |
377 | } |
378 | }; |
379 | |
380 | void fPassingToUnknownFunctionTest1() { |
381 | PassingToUnknownFunctionTest1(); |
382 | PassingToUnknownFunctionTest1(int()); |
383 | PassingToUnknownFunctionTest1(int(), int()); |
384 | } |
385 | |
386 | class PassingToUnknownFunctionTest2 { |
387 | int a; // expected-note{{uninitialized field 'this->a'}} |
388 | int b; |
389 | |
390 | public: |
391 | PassingToUnknownFunctionTest2() { |
392 | wontInitialize(a); |
393 | b = 4; // expected-warning{{1 uninitialized field}} |
394 | } |
395 | }; |
396 | |
397 | void fPassingToUnknownFunctionTest2() { |
398 | PassingToUnknownFunctionTest2(); |
399 | } |
400 | |
401 | //===----------------------------------------------------------------------===// |
402 | // Tests for classes containing unions. |
403 | //===----------------------------------------------------------------------===// |
404 | |
405 | // FIXME: As of writing this checker, there is no good support for union types |
406 | // in the Static Analyzer. Here is non-exhaustive list of cases. |
407 | // Note that the rules for unions are different in C and C++. |
408 | // http://lists.llvm.org/pipermail/cfe-dev/2017-March/052910.html |
409 | |
410 | class ContainsSimpleUnionTest1 { |
411 | union SimpleUnion { |
412 | float uf; |
413 | int ui; |
414 | char uc; |
415 | } u; |
416 | |
417 | public: |
418 | ContainsSimpleUnionTest1() { |
419 | u.uf = 3.14; |
420 | // All good! |
421 | } |
422 | }; |
423 | |
424 | void fContainsSimpleUnionTest1() { |
425 | ContainsSimpleUnionTest1(); |
426 | } |
427 | |
428 | class ContainsSimpleUnionTest2 { |
429 | union SimpleUnion { |
430 | float uf; |
431 | int ui; |
432 | char uc; |
433 | // TODO: we'd expect the note: {{uninitialized field 'this->u'}} |
434 | } u; // no-note |
435 | |
436 | public: |
437 | ContainsSimpleUnionTest2() {} |
438 | }; |
439 | |
440 | void fContainsSimpleUnionTest2() { |
441 | // TODO: we'd expect the warning: {{1 uninitialized field}} |
442 | ContainsSimpleUnionTest2(); // no-warning |
443 | } |
444 | |
445 | class UnionPointerTest1 { |
446 | public: |
447 | union SimpleUnion { |
448 | float uf; |
449 | int ui; |
450 | char uc; |
451 | }; |
452 | |
453 | private: |
454 | SimpleUnion *uptr; |
455 | |
456 | public: |
457 | UnionPointerTest1(SimpleUnion *uptr, int) : uptr(uptr) { |
458 | // All good! |
459 | } |
460 | }; |
461 | |
462 | void fUnionPointerTest1() { |
463 | UnionPointerTest1::SimpleUnion u; |
464 | u.uf = 41; |
465 | UnionPointerTest1(&u, int()); |
466 | } |
467 | |
468 | class UnionPointerTest2 { |
469 | public: |
470 | union SimpleUnion { |
471 | float uf; |
472 | int ui; |
473 | char uc; |
474 | }; |
475 | |
476 | private: |
477 | // TODO: we'd expect the note: {{uninitialized field 'this->uptr'}} |
478 | SimpleUnion *uptr; // no-note |
479 | |
480 | public: |
481 | UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {} |
482 | }; |
483 | |
484 | void fUnionPointerTest2() { |
485 | UnionPointerTest2::SimpleUnion u; |
486 | // TODO: we'd expect the warning: {{1 uninitialized field}} |
487 | UnionPointerTest2(&u, int()); // no-warning |
488 | } |
489 | |
490 | class ContainsUnionWithRecordTest1 { |
491 | union UnionWithRecord { |
492 | struct RecordType { |
493 | int x; |
494 | int y; |
495 | } us; |
496 | double ud; |
497 | long ul; |
498 | |
499 | UnionWithRecord(){}; |
500 | } u; |
501 | |
502 | public: |
503 | ContainsUnionWithRecordTest1() { |
504 | u.ud = 3.14; |
505 | // All good! |
506 | } |
507 | }; |
508 | |
509 | void fContainsUnionWithRecordTest1() { |
510 | ContainsUnionWithRecordTest1(); |
511 | } |
512 | |
513 | class ContainsUnionWithRecordTest2 { |
514 | union UnionWithRecord { |
515 | struct RecordType { |
516 | int x; |
517 | int y; |
518 | } us; |
519 | double ud; |
520 | long ul; |
521 | |
522 | UnionWithRecord(){}; |
523 | } u; |
524 | |
525 | public: |
526 | ContainsUnionWithRecordTest2() { |
527 | u.us = UnionWithRecord::RecordType{42, 43}; |
528 | // All good! |
529 | } |
530 | }; |
531 | |
532 | void fContainsUnionWithRecordTest2() { |
533 | ContainsUnionWithRecordTest1(); |
534 | } |
535 | |
536 | class ContainsUnionWithRecordTest3 { |
537 | union UnionWithRecord { |
538 | struct RecordType { |
539 | int x; |
540 | int y; |
541 | } us; |
542 | double ud; |
543 | long ul; |
544 | |
545 | UnionWithRecord(){}; |
546 | // TODO: we'd expect the note: {{uninitialized field 'this->u'}} |
547 | } u; // no-note |
548 | |
549 | public: |
550 | ContainsUnionWithRecordTest3() { |
551 | UnionWithRecord::RecordType rec; |
552 | rec.x = 44; |
553 | // TODO: we'd expect the warning: {{1 uninitialized field}} |
554 | u.us = rec; // no-warning |
555 | } |
556 | }; |
557 | |
558 | void fContainsUnionWithRecordTest3() { |
559 | ContainsUnionWithRecordTest3(); |
560 | } |
561 | |
562 | class ContainsUnionWithSimpleUnionTest1 { |
563 | union UnionWithSimpleUnion { |
564 | union SimpleUnion { |
565 | float uf; |
566 | int ui; |
567 | char uc; |
568 | } usu; |
569 | long ul; |
570 | unsigned uu; |
571 | } u; |
572 | |
573 | public: |
574 | ContainsUnionWithSimpleUnionTest1() { |
575 | u.usu.ui = 5; |
576 | // All good! |
577 | } |
578 | }; |
579 | |
580 | void fContainsUnionWithSimpleUnionTest1() { |
581 | ContainsUnionWithSimpleUnionTest1(); |
582 | } |
583 | |
584 | class ContainsUnionWithSimpleUnionTest2 { |
585 | union UnionWithSimpleUnion { |
586 | union SimpleUnion { |
587 | float uf; |
588 | int ui; |
589 | char uc; |
590 | } usu; |
591 | long ul; |
592 | unsigned uu; |
593 | // TODO: we'd expect the note: {{uninitialized field 'this->u'}} |
594 | } u; // no-note |
595 | |
596 | public: |
597 | ContainsUnionWithSimpleUnionTest2() {} |
598 | }; |
599 | |
600 | void fContainsUnionWithSimpleUnionTest2() { |
601 | // TODO: we'd expect the warning: {{1 uninitialized field}} |
602 | ContainsUnionWithSimpleUnionTest2(); // no-warning |
603 | } |
604 | |
605 | //===----------------------------------------------------------------------===// |
606 | // Zero initialization tests. |
607 | //===----------------------------------------------------------------------===// |
608 | |
609 | struct GlobalVariableTest { |
610 | int i; |
611 | |
612 | GlobalVariableTest() {} |
613 | }; |
614 | |
615 | GlobalVariableTest gvt; // no-warning |
616 | |
617 | //===----------------------------------------------------------------------===// |
618 | // Copy and move constructor tests. |
619 | //===----------------------------------------------------------------------===// |
620 | |
621 | template <class T> |
622 | void funcToSquelchCompilerWarnings(const T &t); |
623 | |
624 | #ifdef PEDANTIC |
625 | struct CopyConstructorTest { |
626 | int i; // expected-note{{uninitialized field 'this->i'}} |
627 | |
628 | CopyConstructorTest() : i(1337) {} |
629 | CopyConstructorTest(const CopyConstructorTest &other) {} |
630 | }; |
631 | |
632 | void fCopyConstructorTest() { |
633 | CopyConstructorTest cct; |
634 | CopyConstructorTest copy = cct; // expected-warning{{1 uninitialized field}} |
635 | funcToSquelchCompilerWarnings(copy); |
636 | } |
637 | #else |
638 | struct CopyConstructorTest { |
639 | int i; |
640 | |
641 | CopyConstructorTest() : i(1337) {} |
642 | CopyConstructorTest(const CopyConstructorTest &other) {} |
643 | }; |
644 | |
645 | void fCopyConstructorTest() { |
646 | CopyConstructorTest cct; |
647 | CopyConstructorTest copy = cct; |
648 | funcToSquelchCompilerWarnings(copy); |
649 | } |
650 | #endif // PEDANTIC |
651 | |
652 | struct MoveConstructorTest { |
653 | // TODO: we'd expect the note: {{uninitialized field 'this->i'}} |
654 | int i; // no-note |
655 | |
656 | MoveConstructorTest() : i(1337) {} |
657 | MoveConstructorTest(const CopyConstructorTest &other) = delete; |
658 | MoveConstructorTest(const CopyConstructorTest &&other) {} |
659 | }; |
660 | |
661 | void fMoveConstructorTest() { |
662 | MoveConstructorTest cct; |
663 | // TODO: we'd expect the warning: {{1 uninitialized field}} |
664 | MoveConstructorTest copy(static_cast<MoveConstructorTest &&>(cct)); // no-warning |
665 | funcToSquelchCompilerWarnings(copy); |
666 | } |
667 | |
668 | //===----------------------------------------------------------------------===// |
669 | // Array tests. |
670 | //===----------------------------------------------------------------------===// |
671 | |
672 | struct IntArrayTest { |
673 | int arr[256]; |
674 | |
675 | IntArrayTest() { |
676 | // All good! |
677 | } |
678 | }; |
679 | |
680 | void fIntArrayTest() { |
681 | IntArrayTest(); |
682 | } |
683 | |
684 | struct RecordTypeArrayTest { |
685 | struct RecordType { |
686 | int x, y; |
687 | } arr[256]; |
688 | |
689 | RecordTypeArrayTest() { |
690 | // All good! |
691 | } |
692 | }; |
693 | |
694 | void fRecordTypeArrayTest() { |
695 | RecordTypeArrayTest(); |
696 | } |
697 | |
698 | template <class T> |
699 | class CharArrayPointerTest { |
700 | T *t; // no-crash |
701 | |
702 | public: |
703 | CharArrayPointerTest(T *t, int) : t(t) {} |
704 | }; |
705 | |
706 | void fCharArrayPointerTest() { |
707 | char str[16] = "012345678912345"; |
708 | CharArrayPointerTest<char[16]>(&str, int()); |
709 | } |
710 | |
711 | //===----------------------------------------------------------------------===// |
712 | // Memset tests. |
713 | //===----------------------------------------------------------------------===// |
714 | |
715 | struct MemsetTest1 { |
716 | int a, b, c; |
717 | |
718 | MemsetTest1() { |
719 | __builtin_memset(this, 0, sizeof(decltype(*this))); |
720 | } |
721 | }; |
722 | |
723 | void fMemsetTest1() { |
724 | MemsetTest1(); |
725 | } |
726 | |
727 | struct MemsetTest2 { |
728 | int a; |
729 | |
730 | MemsetTest2() { |
731 | __builtin_memset(&a, 0, sizeof(int)); |
732 | } |
733 | }; |
734 | |
735 | void fMemsetTest2() { |
736 | MemsetTest2(); |
737 | } |
738 | |
739 | //===----------------------------------------------------------------------===// |
740 | // Lambda tests. |
741 | //===----------------------------------------------------------------------===// |
742 | |
743 | template <class Callable> |
744 | struct LambdaThisTest { |
745 | Callable functor; |
746 | |
747 | LambdaThisTest(const Callable &functor, int) : functor(functor) { |
748 | // All good! |
749 | } |
750 | }; |
751 | |
752 | struct HasCapturableThis { |
753 | void fLambdaThisTest() { |
754 | auto isEven = [this](int a) { return a % 2 == 0; }; // no-crash |
755 | LambdaThisTest<decltype(isEven)>(isEven, int()); |
756 | } |
757 | }; |
758 | |
759 | template <class Callable> |
760 | struct LambdaTest1 { |
761 | Callable functor; |
762 | |
763 | LambdaTest1(const Callable &functor, int) : functor(functor) { |
764 | // All good! |
765 | } |
766 | }; |
767 | |
768 | void fLambdaTest1() { |
769 | auto isEven = [](int a) { return a % 2 == 0; }; |
770 | LambdaTest1<decltype(isEven)>(isEven, int()); |
771 | } |
772 | |
773 | #ifdef PEDANTIC |
774 | template <class Callable> |
775 | struct LambdaTest2 { |
776 | Callable functor; |
777 | |
778 | LambdaTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}} |
779 | }; |
780 | |
781 | void fLambdaTest2() { |
782 | int b; |
783 | auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized pointee 'this->functor./*captured variable*/b'}} |
784 | LambdaTest2<decltype(equals)>(equals, int()); |
785 | } |
786 | #else |
787 | template <class Callable> |
788 | struct LambdaTest2 { |
789 | Callable functor; |
790 | |
791 | LambdaTest2(const Callable &functor, int) : functor(functor) {} |
792 | }; |
793 | |
794 | void fLambdaTest2() { |
795 | int b; |
796 | auto equals = [&b](int a) { return a == b; }; |
797 | LambdaTest2<decltype(equals)>(equals, int()); |
798 | } |
799 | #endif //PEDANTIC |
800 | |
801 | #ifdef PEDANTIC |
802 | namespace LT3Detail { |
803 | |
804 | struct RecordType { |
805 | int x; // expected-note{{uninitialized field 'this->functor./*captured variable*/rec1.x'}} |
806 | int y; // expected-note{{uninitialized field 'this->functor./*captured variable*/rec1.y'}} |
807 | }; |
808 | |
809 | } // namespace LT3Detail |
810 | template <class Callable> |
811 | struct LambdaTest3 { |
812 | Callable functor; |
813 | |
814 | LambdaTest3(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized fields}} |
815 | }; |
816 | |
817 | void fLambdaTest3() { |
818 | LT3Detail::RecordType rec1; |
819 | auto equals = [&rec1](LT3Detail::RecordType rec2) { |
820 | return rec1.x == rec2.x; |
821 | }; |
822 | LambdaTest3<decltype(equals)>(equals, int()); |
823 | } |
824 | #else |
825 | namespace LT3Detail { |
826 | |
827 | struct RecordType { |
828 | int x; |
829 | int y; |
830 | }; |
831 | |
832 | } // namespace LT3Detail |
833 | template <class Callable> |
834 | struct LambdaTest3 { |
835 | Callable functor; |
836 | |
837 | LambdaTest3(const Callable &functor, int) : functor(functor) {} |
838 | }; |
839 | |
840 | void fLambdaTest3() { |
841 | LT3Detail::RecordType rec1; |
842 | auto equals = [&rec1](LT3Detail::RecordType rec2) { |
843 | return rec1.x == rec2.x; |
844 | }; |
845 | LambdaTest3<decltype(equals)>(equals, int()); |
846 | } |
847 | #endif //PEDANTIC |
848 | |
849 | template <class Callable> |
850 | struct MultipleLambdaCapturesTest1 { |
851 | Callable functor; |
852 | int dontGetFilteredByNonPedanticMode = 0; |
853 | |
854 | MultipleLambdaCapturesTest1(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized field}} |
855 | }; |
856 | |
857 | void fMultipleLambdaCapturesTest1() { |
858 | int b1, b2 = 3, b3; |
859 | auto equals = [&b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized pointee 'this->functor./*captured variable*/b1'}} |
860 | // expected-note@-1{{uninitialized pointee 'this->functor./*captured variable*/b3'}} |
861 | MultipleLambdaCapturesTest1<decltype(equals)>(equals, int()); |
862 | } |
863 | |
864 | template <class Callable> |
865 | struct MultipleLambdaCapturesTest2 { |
866 | Callable functor; |
867 | int dontGetFilteredByNonPedanticMode = 0; |
868 | |
869 | MultipleLambdaCapturesTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}} |
870 | }; |
871 | |
872 | void fMultipleLambdaCapturesTest2() { |
873 | int b1, b2 = 3, b3; |
874 | auto equals = [b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized pointee 'this->functor./*captured variable*/b3'}} |
875 | MultipleLambdaCapturesTest2<decltype(equals)>(equals, int()); |
876 | } |
877 | |
878 | struct LambdaWrapper { |
879 | void *func; // no-crash |
880 | int dontGetFilteredByNonPedanticMode = 0; |
881 | |
882 | LambdaWrapper(void *ptr) : func(ptr) {} // expected-warning{{1 uninitialized field}} |
883 | }; |
884 | |
885 | struct ThisCapturingLambdaFactory { |
886 | int a; // expected-note{{uninitialized field 'static_cast<decltype(a.ret()) *>(this->func)->/*'this' capture*/->a'}} |
887 | |
888 | auto ret() { |
889 | return [this] { (void)this; }; |
890 | } |
891 | }; |
892 | |
893 | void fLambdaFieldWithInvalidThisCapture() { |
894 | void *ptr; |
895 | { |
896 | ThisCapturingLambdaFactory a; |
897 | decltype(a.ret()) lambda = a.ret(); |
898 | ptr = λ |
899 | } |
900 | LambdaWrapper t(ptr); |
901 | } |
902 | |
903 | //===----------------------------------------------------------------------===// |
904 | // System header tests. |
905 | //===----------------------------------------------------------------------===// |
906 | |
907 | #include "Inputs/system-header-simulator-for-cxx-uninitialized-object.h" |
908 | |
909 | struct SystemHeaderTest1 { |
910 | RecordInSystemHeader rec; // defined in the system header simulator |
911 | |
912 | SystemHeaderTest1() { |
913 | // All good! |
914 | } |
915 | }; |
916 | |
917 | void fSystemHeaderTest1() { |
918 | SystemHeaderTest1(); |
919 | } |
920 | |
921 | #ifdef PEDANTIC |
922 | struct SystemHeaderTest2 { |
923 | struct RecordType { |
924 | int x; // expected-note{{uninitialized field 'this->container.t.x}} |
925 | int y; // expected-note{{uninitialized field 'this->container.t.y}} |
926 | }; |
927 | ContainerInSystemHeader<RecordType> container; |
928 | |
929 | SystemHeaderTest2(RecordType &rec, int) : container(rec) {} // expected-warning{{2 uninitialized fields}} |
930 | }; |
931 | |
932 | void fSystemHeaderTest2() { |
933 | SystemHeaderTest2::RecordType rec; |
934 | SystemHeaderTest2(rec, int()); |
935 | } |
936 | #else |
937 | struct SystemHeaderTest2 { |
938 | struct RecordType { |
939 | int x; |
940 | int y; |
941 | }; |
942 | ContainerInSystemHeader<RecordType> container; |
943 | |
944 | SystemHeaderTest2(RecordType &rec, int) : container(rec) {} |
945 | }; |
946 | |
947 | void fSystemHeaderTest2() { |
948 | SystemHeaderTest2::RecordType rec; |
949 | SystemHeaderTest2(rec, int()); |
950 | } |
951 | #endif //PEDANTIC |
952 | |
953 | //===----------------------------------------------------------------------===// |
954 | // Incomplete type tests. |
955 | //===----------------------------------------------------------------------===// |
956 | |
957 | struct IncompleteTypeTest1 { |
958 | struct RecordType; |
959 | // no-crash |
960 | RecordType *recptr; // expected-note{{uninitialized pointer 'this->recptr}} |
961 | int dontGetFilteredByNonPedanticMode = 0; |
962 | |
963 | IncompleteTypeTest1() {} // expected-warning{{1 uninitialized field}} |
964 | }; |
965 | |
966 | void fIncompleteTypeTest1() { |
967 | IncompleteTypeTest1(); |
968 | } |
969 | |
970 | struct IncompleteTypeTest2 { |
971 | struct RecordType; |
972 | RecordType *recptr; // no-crash |
973 | int dontGetFilteredByNonPedanticMode = 0; |
974 | |
975 | RecordType *recordTypeFactory(); |
976 | |
977 | IncompleteTypeTest2() : recptr(recordTypeFactory()) {} |
978 | }; |
979 | |
980 | void fIncompleteTypeTest2() { |
981 | IncompleteTypeTest2(); |
982 | } |
983 | |
984 | struct IncompleteTypeTest3 { |
985 | struct RecordType; |
986 | RecordType &recref; // no-crash |
987 | int dontGetFilteredByNonPedanticMode = 0; |
988 | |
989 | RecordType &recordTypeFactory(); |
990 | |
991 | IncompleteTypeTest3() : recref(recordTypeFactory()) {} |
992 | }; |
993 | |
994 | void fIncompleteTypeTest3() { |
995 | IncompleteTypeTest3(); |
996 | } |
997 | |
998 | //===----------------------------------------------------------------------===// |
999 | // Builtin type or enumeration type related tests. |
1000 | //===----------------------------------------------------------------------===// |
1001 | |
1002 | struct IntegralTypeTest { |
1003 | int a; // expected-note{{uninitialized field 'this->a'}} |
1004 | int dontGetFilteredByNonPedanticMode = 0; |
1005 | |
1006 | IntegralTypeTest() {} // expected-warning{{1 uninitialized field}} |
1007 | }; |
1008 | |
1009 | void fIntegralTypeTest() { |
1010 | IntegralTypeTest(); |
1011 | } |
1012 | |
1013 | struct FloatingTypeTest { |
1014 | float a; // expected-note{{uninitialized field 'this->a'}} |
1015 | int dontGetFilteredByNonPedanticMode = 0; |
1016 | |
1017 | FloatingTypeTest() {} // expected-warning{{1 uninitialized field}} |
1018 | }; |
1019 | |
1020 | void fFloatingTypeTest() { |
1021 | FloatingTypeTest(); |
1022 | } |
1023 | |
1024 | struct NullptrTypeTypeTest { |
1025 | decltype(nullptr) a; // expected-note{{uninitialized field 'this->a'}} |
1026 | int dontGetFilteredByNonPedanticMode = 0; |
1027 | |
1028 | NullptrTypeTypeTest() {} // expected-warning{{1 uninitialized field}} |
1029 | }; |
1030 | |
1031 | void fNullptrTypeTypeTest() { |
1032 | NullptrTypeTypeTest(); |
1033 | } |
1034 | |
1035 | struct EnumTest { |
1036 | enum Enum { |
1037 | A, |
1038 | B |
1039 | } enum1; // expected-note{{uninitialized field 'this->enum1'}} |
1040 | enum class Enum2 { |
1041 | A, |
1042 | B |
1043 | } enum2; // expected-note{{uninitialized field 'this->enum2'}} |
1044 | int dontGetFilteredByNonPedanticMode = 0; |
1045 | |
1046 | EnumTest() {} // expected-warning{{2 uninitialized fields}} |
1047 | }; |
1048 | |
1049 | void fEnumTest() { |
1050 | EnumTest(); |
1051 | } |
1052 | |
1053 | //===----------------------------------------------------------------------===// |
1054 | // Tests for constructor calls within another cunstructor, without the two |
1055 | // records being in any relation. |
1056 | //===----------------------------------------------------------------------===// |
1057 | |
1058 | void halt() __attribute__((__noreturn__)); |
1059 | void assert(int b) { |
1060 | if (!b) |
1061 | halt(); |
1062 | } |
1063 | |
1064 | // While a singleton would make more sense as a static variable, that would zero |
1065 | // initialize all of its fields, hence the not too practical implementation. |
1066 | struct Singleton { |
1067 | int i; // expected-note{{uninitialized field 'this->i'}} |
1068 | int dontGetFilteredByNonPedanticMode = 0; |
1069 | |
1070 | Singleton() { |
1071 | assert(!isInstantiated); |
1072 | isInstantiated = true; // expected-warning{{1 uninitialized field}} |
1073 | } |
1074 | |
1075 | ~Singleton() { |
1076 | isInstantiated = false; |
1077 | } |
1078 | |
1079 | static bool isInstantiated; |
1080 | }; |
1081 | |
1082 | bool Singleton::isInstantiated = false; |
1083 | |
1084 | struct SingletonTest { |
1085 | int dontGetFilteredByNonPedanticMode = 0; |
1086 | |
1087 | SingletonTest() { |
1088 | Singleton(); |
1089 | } |
1090 | }; |
1091 | |
1092 | void fSingletonTest() { |
1093 | SingletonTest(); |
1094 | } |
1095 | |
1096 | //===----------------------------------------------------------------------===// |
1097 | // C++11 member initializer tests. |
1098 | //===----------------------------------------------------------------------===// |
1099 | |
1100 | struct CXX11MemberInitTest1 { |
1101 | int a = 3; |
1102 | int b; |
1103 | CXX11MemberInitTest1() : b(2) { |
1104 | // All good! |
1105 | } |
1106 | }; |
1107 | |
1108 | void fCXX11MemberInitTest1() { |
1109 | CXX11MemberInitTest1(); |
1110 | } |
1111 | |
1112 | struct CXX11MemberInitTest2 { |
1113 | struct RecordType { |
1114 | // TODO: we'd expect the note: {{uninitialized field 'this->rec.a'}} |
1115 | int a; // no-note |
1116 | // TODO: we'd expect the note: {{uninitialized field 'this->rec.b'}} |
1117 | int b; // no-note |
1118 | |
1119 | RecordType(int) {} |
1120 | }; |
1121 | |
1122 | RecordType rec = RecordType(int()); |
1123 | int dontGetFilteredByNonPedanticMode = 0; |
1124 | |
1125 | CXX11MemberInitTest2() {} |
1126 | }; |
1127 | |
1128 | void fCXX11MemberInitTest2() { |
1129 | // TODO: we'd expect the warning: {{2 uninitializeds field}} |
1130 | CXX11MemberInitTest2(); // no-warning |
1131 | } |
1132 | |