aboutsummaryrefslogtreecommitdiff
path: root/test/Analysis/cxx-uninitialized-object.cpp
diff options
context:
space:
mode:
authorKristof Umann <dkszelethus@gmail.com>2018-06-18 11:50:17 +0000
committerKristof Umann <dkszelethus@gmail.com>2018-06-18 11:50:17 +0000
commit6402a97d5b74108b300f5833af0b85b3d4c5d6b6 (patch)
treed8cbd3c62fb05b37fada65472a1f9b6d48507eb4 /test/Analysis/cxx-uninitialized-object.cpp
parent07caa7f2a1dae8d2569ec59a2f6785ad5d4ea3d9 (diff)
[analyzer] Checker for uninitialized C++ objects
This checker analyzes C++ constructor calls, and reports uninitialized fields. Due to the nature of this problem (uninitialized fields after an object construction), this checker doesn't search for bugs, but rather is a tool to enforce a specific programming model where every field needs to be initialized. This checker lands in alpha for now, and a number of followup patches will be made to reduce false negatives and to make it easier for the user to understand what rules the checker relies on, eg. whether a derived class' constructor is responsible for initializing inherited data members or whether it should be handled in the base class' constructor. Differential Revision: https://reviews.llvm.org/D45532 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334935 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Analysis/cxx-uninitialized-object.cpp')
-rw-r--r--test/Analysis/cxx-uninitialized-object.cpp1058
1 files changed, 1058 insertions, 0 deletions
diff --git a/test/Analysis/cxx-uninitialized-object.cpp b/test/Analysis/cxx-uninitialized-object.cpp
new file mode 100644
index 0000000000..617ac78f40
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object.cpp
@@ -0,0 +1,1058 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+
+//===----------------------------------------------------------------------===//
+// Default constructor test.
+//===----------------------------------------------------------------------===//
+
+class CompilerGeneratedConstructorTest {
+ int a, b, c, d, e, f, g, h, i, j;
+
+public:
+ CompilerGeneratedConstructorTest() = default;
+};
+
+void fCompilerGeneratedConstructorTest() {
+ CompilerGeneratedConstructorTest();
+}
+
+#ifdef PEDANTIC
+class DefaultConstructorTest {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+
+public:
+ DefaultConstructorTest();
+};
+
+DefaultConstructorTest::DefaultConstructorTest() = default;
+
+void fDefaultConstructorTest() {
+ DefaultConstructorTest(); // expected-warning{{1 uninitialized field}}
+}
+#else
+class DefaultConstructorTest {
+ int a;
+
+public:
+ DefaultConstructorTest();
+};
+
+DefaultConstructorTest::DefaultConstructorTest() = default;
+
+void fDefaultConstructorTest() {
+ DefaultConstructorTest();
+}
+#endif // PEDANTIC
+
+//===----------------------------------------------------------------------===//
+// Initializer list test.
+//===----------------------------------------------------------------------===//
+
+class InitListTest1 {
+ int a;
+ int b;
+
+public:
+ InitListTest1()
+ : a(1),
+ b(2) {
+ // All good!
+ }
+};
+
+void fInitListTest1() {
+ InitListTest1();
+}
+
+class InitListTest2 {
+ int a;
+ int b; // expected-note{{uninitialized field 'this->b'}}
+
+public:
+ InitListTest2()
+ : a(3) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fInitListTest2() {
+ InitListTest2();
+}
+
+class InitListTest3 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ InitListTest3()
+ : b(4) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fInitListTest3() {
+ InitListTest3();
+}
+
+//===----------------------------------------------------------------------===//
+// Constructor body test.
+//===----------------------------------------------------------------------===//
+
+class CtorBodyTest1 {
+ int a, b;
+
+public:
+ CtorBodyTest1() {
+ a = 5;
+ b = 6;
+ // All good!
+ }
+};
+
+void fCtorBodyTest1() {
+ CtorBodyTest1();
+}
+
+class CtorBodyTest2 {
+ int a;
+ int b; // expected-note{{uninitialized field 'this->b'}}
+
+public:
+ CtorBodyTest2() {
+ a = 7; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCtorBodyTest2() {
+ CtorBodyTest2();
+}
+
+class CtorBodyTest3 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ CtorBodyTest3() {
+ b = 8; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCtorBodyTest3() {
+ CtorBodyTest3();
+}
+
+#ifdef PEDANTIC
+class CtorBodyTest4 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b; // expected-note{{uninitialized field 'this->b'}}
+
+public:
+ CtorBodyTest4() {}
+};
+
+void fCtorBodyTest4() {
+ CtorBodyTest4(); // expected-warning{{2 uninitialized fields}}
+}
+#else
+class CtorBodyTest4 {
+ int a;
+ int b;
+
+public:
+ CtorBodyTest4() {}
+};
+
+void fCtorBodyTest4() {
+ CtorBodyTest4();
+}
+#endif
+
+//===----------------------------------------------------------------------===//
+// Constructor delegation test.
+//===----------------------------------------------------------------------===//
+
+class CtorDelegationTest1 {
+ int a;
+ int b;
+
+public:
+ CtorDelegationTest1(int)
+ : a(9) {
+ // leaves 'b' unintialized, but we'll never check this function
+ }
+
+ CtorDelegationTest1()
+ : CtorDelegationTest1(int{}) { // Initializing 'a'
+ b = 10;
+ // All good!
+ }
+};
+
+void fCtorDelegationTest1() {
+ CtorDelegationTest1();
+}
+
+class CtorDelegationTest2 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ CtorDelegationTest2(int)
+ : b(11) {
+ // leaves 'a' unintialized, but we'll never check this function
+ }
+
+ CtorDelegationTest2()
+ : CtorDelegationTest2(int{}) { // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fCtorDelegationTest2() {
+ CtorDelegationTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for classes containing records.
+//===----------------------------------------------------------------------===//
+
+class ContainsRecordTest1 {
+ struct RecordType {
+ int x;
+ int y;
+ } rec;
+ int c, d;
+
+public:
+ ContainsRecordTest1()
+ : rec({12, 13}),
+ c(14),
+ d(15) {
+ // All good!
+ }
+};
+
+void fContainsRecordTest1() {
+ ContainsRecordTest1();
+}
+
+class ContainsRecordTest2 {
+ struct RecordType {
+ int x;
+ int y; // expected-note{{uninitialized field 'this->rec.y'}}
+ } rec;
+ int c, d;
+
+public:
+ ContainsRecordTest2()
+ : c(16),
+ d(17) {
+ rec.x = 18; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fContainsRecordTest2() {
+ ContainsRecordTest2();
+}
+
+class ContainsRecordTest3 {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->rec.x'}}
+ int y; // expected-note{{uninitialized field 'this->rec.y'}}
+ } rec;
+ int c, d;
+
+public:
+ ContainsRecordTest3()
+ : c(19),
+ d(20) { // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fContainsRecordTest3() {
+ ContainsRecordTest3();
+}
+
+class ContainsRecordTest4 {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->rec.x'}}
+ int y; // expected-note{{uninitialized field 'this->rec.y'}}
+ } rec;
+ int c, d; // expected-note{{uninitialized field 'this->d'}}
+
+public:
+ ContainsRecordTest4()
+ : c(19) { // expected-warning{{3 uninitialized fields}}
+ }
+};
+
+void fContainsRecordTest4() {
+ ContainsRecordTest4();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for template classes.
+//===----------------------------------------------------------------------===//
+
+template <class T>
+class IntTemplateClassTest1 {
+ T t;
+ int b;
+
+public:
+ IntTemplateClassTest1(T i) {
+ b = 21;
+ t = i;
+ // All good!
+ }
+};
+
+void fIntTemplateClassTest1() {
+ IntTemplateClassTest1<int>(22);
+}
+
+template <class T>
+class IntTemplateClassTest2 {
+ T t; // expected-note{{uninitialized field 'this->t'}}
+ int b;
+
+public:
+ IntTemplateClassTest2() {
+ b = 23; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fIntTemplateClassTest2() {
+ IntTemplateClassTest2<int>();
+}
+
+struct Record {
+ int x; // expected-note{{uninitialized field 'this->t.x'}}
+ int y; // expected-note{{uninitialized field 'this->t.y'}}
+};
+
+template <class T>
+class RecordTemplateClassTest {
+ T t;
+ int b;
+
+public:
+ RecordTemplateClassTest() {
+ b = 24; // expected-warning{{2 uninitialized fields}}
+ }
+};
+
+void fRecordTemplateClassTest() {
+ RecordTemplateClassTest<Record>();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests involving functions with unknown implementations.
+//===----------------------------------------------------------------------===//
+
+template <class T>
+void mayInitialize(T &);
+
+template <class T>
+void wontInitialize(const T &);
+
+class PassingToUnknownFunctionTest1 {
+ int a, b;
+
+public:
+ PassingToUnknownFunctionTest1() {
+ mayInitialize(a);
+ mayInitialize(b);
+ // All good!
+ }
+
+ PassingToUnknownFunctionTest1(int) {
+ mayInitialize(a);
+ // All good!
+ }
+
+ PassingToUnknownFunctionTest1(int, int) {
+ mayInitialize(*this);
+ // All good!
+ }
+};
+
+void fPassingToUnknownFunctionTest1() {
+ PassingToUnknownFunctionTest1();
+ PassingToUnknownFunctionTest1(int());
+ PassingToUnknownFunctionTest1(int(), int());
+}
+
+class PassingToUnknownFunctionTest2 {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int b;
+
+public:
+ PassingToUnknownFunctionTest2() {
+ wontInitialize(a);
+ b = 4; // expected-warning{{1 uninitialized field}}
+ }
+};
+
+void fPassingToUnknownFunctionTest2() {
+ PassingToUnknownFunctionTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for classes containing unions.
+//===----------------------------------------------------------------------===//
+
+// FIXME: As of writing this checker, there is no good support for union types
+// in the Static Analyzer. Here is non-exhaustive list of cases.
+// Note that the rules for unions are different in C and C++.
+// http://lists.llvm.org/pipermail/cfe-dev/2017-March/052910.html
+
+class ContainsSimpleUnionTest1 {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ } u;
+
+public:
+ ContainsSimpleUnionTest1() {
+ u.uf = 3.14;
+ // All good!
+ }
+};
+
+void fContainsSimpleUnionTest1() {
+ ContainsSimpleUnionTest1();
+}
+
+class ContainsSimpleUnionTest2 {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ // TODO: we'd expect the note: {{uninitialized field 'this->u'}}
+ } u; // no-note
+
+public:
+ ContainsSimpleUnionTest2() {}
+};
+
+void fContainsSimpleUnionTest2() {
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ ContainsSimpleUnionTest2(); // no-warning
+}
+
+class UnionPointerTest1 {
+public:
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ };
+
+private:
+ SimpleUnion *uptr;
+
+public:
+ UnionPointerTest1(SimpleUnion *uptr, int) : uptr(uptr) {
+ // All good!
+ }
+};
+
+void fUnionPointerTest1() {
+ UnionPointerTest1::SimpleUnion u;
+ u.uf = 41;
+ UnionPointerTest1(&u, int());
+}
+
+class UnionPointerTest2 {
+public:
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ };
+
+private:
+ // TODO: we'd expect the note: {{uninitialized field 'this->uptr'}}
+ SimpleUnion *uptr; // no-note
+
+public:
+ UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {}
+};
+
+void fUnionPointerTest2() {
+ UnionPointerTest2::SimpleUnion u;
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ UnionPointerTest2(&u, int()); // no-warning
+}
+
+class ContainsUnionWithRecordTest1 {
+ union UnionWithRecord {
+ struct RecordType {
+ int x;
+ int y;
+ } us;
+ double ud;
+ long ul;
+
+ UnionWithRecord(){};
+ } u;
+
+public:
+ ContainsUnionWithRecordTest1() {
+ u.ud = 3.14;
+ // All good!
+ }
+};
+
+void fContainsUnionWithRecordTest1() {
+ ContainsUnionWithRecordTest1();
+}
+
+class ContainsUnionWithRecordTest2 {
+ union UnionWithRecord {
+ struct RecordType {
+ int x;
+ int y;
+ } us;
+ double ud;
+ long ul;
+
+ UnionWithRecord(){};
+ } u;
+
+public:
+ ContainsUnionWithRecordTest2() {
+ u.us = UnionWithRecord::RecordType{42, 43};
+ // All good!
+ }
+};
+
+void fContainsUnionWithRecordTest2() {
+ ContainsUnionWithRecordTest1();
+}
+
+class ContainsUnionWithRecordTest3 {
+ union UnionWithRecord {
+ struct RecordType {
+ int x;
+ int y;
+ } us;
+ double ud;
+ long ul;
+
+ UnionWithRecord(){};
+ // TODO: we'd expect the note: {{uninitialized field 'this->u'}}
+ } u; // no-note
+
+public:
+ ContainsUnionWithRecordTest3() {
+ UnionWithRecord::RecordType rec;
+ rec.x = 44;
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ u.us = rec; // no-warning
+ }
+};
+
+void fContainsUnionWithRecordTest3() {
+ ContainsUnionWithRecordTest3();
+}
+
+class ContainsUnionWithSimpleUnionTest1 {
+ union UnionWithSimpleUnion {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ } usu;
+ long ul;
+ unsigned uu;
+ } u;
+
+public:
+ ContainsUnionWithSimpleUnionTest1() {
+ u.usu.ui = 5;
+ // All good!
+ }
+};
+
+void fContainsUnionWithSimpleUnionTest1() {
+ ContainsUnionWithSimpleUnionTest1();
+}
+
+class ContainsUnionWithSimpleUnionTest2 {
+ union UnionWithSimpleUnion {
+ union SimpleUnion {
+ float uf;
+ int ui;
+ char uc;
+ } usu;
+ long ul;
+ unsigned uu;
+ // TODO: we'd expect the note: {{uninitialized field 'this->u'}}
+ } u; // no-note
+
+public:
+ ContainsUnionWithSimpleUnionTest2() {}
+};
+
+void fContainsUnionWithSimpleUnionTest2() {
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ ContainsUnionWithSimpleUnionTest2(); // no-warning
+}
+
+//===----------------------------------------------------------------------===//
+// Zero initialization tests.
+//===----------------------------------------------------------------------===//
+
+struct GlobalVariableTest {
+ int i;
+
+ GlobalVariableTest() {}
+};
+
+GlobalVariableTest gvt; // no-warning
+
+//===----------------------------------------------------------------------===//
+// Copy and move constructor tests.
+//===----------------------------------------------------------------------===//
+
+template <class T>
+void funcToSquelchCompilerWarnings(const T &t);
+
+#ifdef PEDANTIC
+struct CopyConstructorTest {
+ int i; // expected-note{{uninitialized field 'this->i'}}
+
+ CopyConstructorTest() : i(1337) {}
+ CopyConstructorTest(const CopyConstructorTest &other) {}
+};
+
+void fCopyConstructorTest() {
+ CopyConstructorTest cct;
+ CopyConstructorTest copy = cct; // expected-warning{{1 uninitialized field}}
+ funcToSquelchCompilerWarnings(copy);
+}
+#else
+struct CopyConstructorTest {
+ int i;
+
+ CopyConstructorTest() : i(1337) {}
+ CopyConstructorTest(const CopyConstructorTest &other) {}
+};
+
+void fCopyConstructorTest() {
+ CopyConstructorTest cct;
+ CopyConstructorTest copy = cct;
+ funcToSquelchCompilerWarnings(copy);
+}
+#endif // PEDANTIC
+
+struct MoveConstructorTest {
+ // TODO: we'd expect the note: {{uninitialized field 'this->i'}}
+ int i; // no-note
+
+ MoveConstructorTest() : i(1337) {}
+ MoveConstructorTest(const CopyConstructorTest &other) = delete;
+ MoveConstructorTest(const CopyConstructorTest &&other) {}
+};
+
+void fMoveConstructorTest() {
+ MoveConstructorTest cct;
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ MoveConstructorTest copy(static_cast<MoveConstructorTest &&>(cct)); // no-warning
+ funcToSquelchCompilerWarnings(copy);
+}
+
+//===----------------------------------------------------------------------===//
+// Array tests.
+//===----------------------------------------------------------------------===//
+
+struct IntArrayTest {
+ int arr[256];
+
+ IntArrayTest() {
+ // All good!
+ }
+};
+
+void fIntArrayTest() {
+ IntArrayTest();
+}
+
+struct RecordTypeArrayTest {
+ struct RecordType {
+ int x, y;
+ } arr[256];
+
+ RecordTypeArrayTest() {
+ // All good!
+ }
+};
+
+void fRecordTypeArrayTest() {
+ RecordTypeArrayTest();
+}
+
+template <class T>
+class CharArrayPointerTest {
+ T *t; // no-crash
+
+public:
+ CharArrayPointerTest(T *t, int) : t(t) {}
+};
+
+void fCharArrayPointerTest() {
+ char str[16] = "012345678912345";
+ CharArrayPointerTest<char[16]>(&str, int());
+}
+
+//===----------------------------------------------------------------------===//
+// Memset tests.
+//===----------------------------------------------------------------------===//
+
+struct MemsetTest1 {
+ int a, b, c;
+
+ MemsetTest1() {
+ __builtin_memset(this, 0, sizeof(decltype(*this)));
+ }
+};
+
+void fMemsetTest1() {
+ MemsetTest1();
+}
+
+struct MemsetTest2 {
+ int a;
+
+ MemsetTest2() {
+ __builtin_memset(&a, 0, sizeof(int));
+ }
+};
+
+void fMemsetTest2() {
+ MemsetTest2();
+}
+
+//===----------------------------------------------------------------------===//
+// Lambda tests.
+//===----------------------------------------------------------------------===//
+
+template <class Callable>
+struct LambdaTest1 {
+ Callable functor;
+
+ LambdaTest1(const Callable &functor, int) : functor(functor) {
+ // All good!
+ }
+};
+
+void fLambdaTest1() {
+ auto isEven = [](int a) { return a % 2 == 0; };
+ LambdaTest1<decltype(isEven)>(isEven, int());
+}
+
+#ifdef PEDANTIC
+template <class Callable>
+struct LambdaTest2 {
+ Callable functor;
+
+ LambdaTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fLambdaTest2() {
+ int b;
+ auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized field 'this->functor.'}}
+ LambdaTest2<decltype(equals)>(equals, int());
+}
+#else
+template <class Callable>
+struct LambdaTest2 {
+ Callable functor;
+
+ LambdaTest2(const Callable &functor, int) : functor(functor) {}
+};
+
+void fLambdaTest2() {
+ int b;
+ auto equals = [&b](int a) { return a == b; };
+ LambdaTest2<decltype(equals)>(equals, int());
+}
+#endif //PEDANTIC
+
+#ifdef PEDANTIC
+namespace LT3Detail {
+
+struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->functor..x'}}
+ int y; // expected-note{{uninitialized field 'this->functor..y'}}
+};
+
+} // namespace LT3Detail
+template <class Callable>
+struct LambdaTest3 {
+ Callable functor;
+
+ LambdaTest3(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fLambdaTest3() {
+ LT3Detail::RecordType rec1;
+ auto equals = [&rec1](LT3Detail::RecordType rec2) {
+ return rec1.x == rec2.x;
+ };
+ LambdaTest3<decltype(equals)>(equals, int());
+}
+#else
+namespace LT3Detail {
+
+struct RecordType {
+ int x;
+ int y;
+};
+
+} // namespace LT3Detail
+template <class Callable>
+struct LambdaTest3 {
+ Callable functor;
+
+ LambdaTest3(const Callable &functor, int) : functor(functor) {}
+};
+
+void fLambdaTest3() {
+ LT3Detail::RecordType rec1;
+ auto equals = [&rec1](LT3Detail::RecordType rec2) {
+ return rec1.x == rec2.x;
+ };
+ LambdaTest3<decltype(equals)>(equals, int());
+}
+#endif //PEDANTIC
+
+//===----------------------------------------------------------------------===//
+// System header tests.
+//===----------------------------------------------------------------------===//
+
+#include "Inputs/system-header-simulator-for-cxx-uninitialized-object.h"
+
+struct SystemHeaderTest1 {
+ RecordInSystemHeader rec; // defined in the system header simulator
+
+ SystemHeaderTest1() {
+ // All good!
+ }
+};
+
+void fSystemHeaderTest1() {
+ SystemHeaderTest1();
+}
+
+#ifdef PEDANTIC
+struct SystemHeaderTest2 {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'this->container.t.x}}
+ int y; // expected-note{{uninitialized field 'this->container.t.y}}
+ };
+ ContainerInSystemHeader<RecordType> container;
+
+ SystemHeaderTest2(RecordType &rec, int) : container(rec) {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fSystemHeaderTest2() {
+ SystemHeaderTest2::RecordType rec;
+ SystemHeaderTest2(rec, int());
+}
+#else
+struct SystemHeaderTest2 {
+ struct RecordType {
+ int x;
+ int y;
+ };
+ ContainerInSystemHeader<RecordType> container;
+
+ SystemHeaderTest2(RecordType &rec, int) : container(rec) {}
+};
+
+void fSystemHeaderTest2() {
+ SystemHeaderTest2::RecordType rec;
+ SystemHeaderTest2(rec, int());
+}
+#endif //PEDANTIC
+
+//===----------------------------------------------------------------------===//
+// Incomplete type tests.
+//===----------------------------------------------------------------------===//
+
+struct IncompleteTypeTest1 {
+ struct RecordType;
+ // no-crash
+ RecordType *recptr; // expected-note{{uninitialized pointer 'this->recptr}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IncompleteTypeTest1() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fIncompleteTypeTest1() {
+ IncompleteTypeTest1();
+}
+
+struct IncompleteTypeTest2 {
+ struct RecordType;
+ RecordType *recptr; // no-crash
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ RecordType *recordTypeFactory();
+
+ IncompleteTypeTest2() : recptr(recordTypeFactory()) {}
+};
+
+void fIncompleteTypeTest2() {
+ IncompleteTypeTest2();
+}
+
+struct IncompleteTypeTest3 {
+ struct RecordType;
+ RecordType &recref; // no-crash
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ RecordType &recordTypeFactory();
+
+ IncompleteTypeTest3() : recref(recordTypeFactory()) {}
+};
+
+void fIncompleteTypeTest3() {
+ IncompleteTypeTest3();
+}
+
+//===----------------------------------------------------------------------===//
+// Builtin type or enumeration type related tests.
+//===----------------------------------------------------------------------===//
+
+struct IntegralTypeTest {
+ int a; // expected-note{{uninitialized field 'this->a'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IntegralTypeTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fIntegralTypeTest() {
+ IntegralTypeTest();
+}
+
+struct FloatingTypeTest {
+ float a; // expected-note{{uninitialized field 'this->a'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ FloatingTypeTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fFloatingTypeTest() {
+ FloatingTypeTest();
+}
+
+struct NullptrTypeTypeTest {
+ decltype(nullptr) a; // expected-note{{uninitialized field 'this->a'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ NullptrTypeTypeTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fNullptrTypeTypeTest() {
+ NullptrTypeTypeTest();
+}
+
+struct EnumTest {
+ enum Enum {
+ A,
+ B
+ } enum1; // expected-note{{uninitialized field 'this->enum1'}}
+ enum class Enum2 {
+ A,
+ B
+ } enum2; // expected-note{{uninitialized field 'this->enum2'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ EnumTest() {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fEnumTest() {
+ EnumTest();
+}
+
+//===----------------------------------------------------------------------===//
+// Tests for constructor calls within another cunstructor, without the two
+// records being in any relation.
+//===----------------------------------------------------------------------===//
+
+void halt() __attribute__((__noreturn__));
+void assert(int b) {
+ if (!b)
+ halt();
+}
+
+// While a singleton would make more sense as a static variable, that would zero
+// initialize all of its fields, hence the not too practical implementation.
+struct Singleton {
+ // TODO: we'd expect the note: {{uninitialized field 'this->i'}}
+ int i; // no-note
+
+ Singleton() {
+ assert(!isInstantiated);
+ // TODO: we'd expect the warning: {{1 uninitialized field}}
+ isInstantiated = true; // no-warning
+ }
+
+ ~Singleton() {
+ isInstantiated = false;
+ }
+
+ static bool isInstantiated;
+};
+
+bool Singleton::isInstantiated = false;
+
+struct SingletonTest {
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ SingletonTest() {
+ Singleton();
+ }
+};
+
+void fSingletonTest() {
+ SingletonTest();
+}
+
+//===----------------------------------------------------------------------===//
+// C++11 member initializer tests.
+//===----------------------------------------------------------------------===//
+
+struct CXX11MemberInitTest1 {
+ int a = 3;
+ int b;
+ CXX11MemberInitTest1() : b(2) {
+ // All good!
+ }
+};
+
+void fCXX11MemberInitTest1() {
+ CXX11MemberInitTest1();
+}
+
+struct CXX11MemberInitTest2 {
+ struct RecordType {
+ // TODO: we'd expect the note: {{uninitialized field 'this->rec.a'}}
+ int a; // no-note
+ // TODO: we'd expect the note: {{uninitialized field 'this->rec.b'}}
+ int b; // no-note
+
+ RecordType(int) {}
+ };
+
+ RecordType rec = RecordType(int());
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CXX11MemberInitTest2() {}
+};
+
+void fCXX11MemberInitTest2() {
+ // TODO: we'd expect the warning: {{2 uninitializeds field}}
+ CXX11MemberInitTest2(); // no-warning
+}