llvm-project/clang/test/Analysis/cxx-uninitialized-object.cpp
Kristof Umann 015b059569 [analyzer][UninitializedObjectChecker] Refactoring p4.: Wrap FieldRegions and reduce weight on FieldChainInfo
Before this patch, FieldChainInfo used a spaghetti: it took care of way too many cases,
even though it was always meant as a lightweight wrapper around
ImmutableList<const FieldRegion *>.
This problem is solved by introducing a lightweight polymorphic wrapper around const
FieldRegion *, FieldNode. It is an interface that abstracts away special cases like
pointers/references, objects that need to be casted to another type for a proper note
messages.

Changes to FieldChainInfo:

  * Now wraps ImmutableList<const FieldNode &>.
  * Any pointer/reference related fields and methods were removed
  * Got a new add method. This replaces it's former constructors as a way to create a
    new FieldChainInfo objects with a new element.

Changes to FindUninitializedField:

  * In order not to deal with dynamic memory management, when an uninitialized field is
    found, the note message for it is constructed and is stored instead of a
    FieldChainInfo object. (see doc around addFieldToUninits).

Some of the test files are changed too, from now on uninitialized pointees of references
always print "uninitialized pointee" instead of "uninitialized field" (which should've
really been like this from the beginning).

I also updated every comment according to these changes.

Differential Revision: https://reviews.llvm.org/D50506

llvm-svn: 339599
2018-08-13 18:43:08 +00:00

1108 lines
24 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -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 LambdaThisTest {
Callable functor;
LambdaThisTest(const Callable &functor, int) : functor(functor) {
// All good!
}
};
struct HasCapturableThis {
void fLambdaThisTest() {
auto isEven = [this](int a) { return a % 2 == 0; }; // no-crash
LambdaThisTest<decltype(isEven)>(isEven, int());
}
};
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 pointee 'this->functor.b'}}
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.rec1.x'}}
int y; // expected-note{{uninitialized field 'this->functor.rec1.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
template <class Callable>
struct MultipleLambdaCapturesTest1 {
Callable functor;
int dontGetFilteredByNonPedanticMode = 0;
MultipleLambdaCapturesTest1(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized field}}
};
void fMultipleLambdaCapturesTest1() {
int b1, b2 = 3, b3;
auto equals = [&b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized pointee 'this->functor.b1'}}
// expected-note@-1{{uninitialized pointee 'this->functor.b3'}}
MultipleLambdaCapturesTest1<decltype(equals)>(equals, int());
}
template <class Callable>
struct MultipleLambdaCapturesTest2 {
Callable functor;
int dontGetFilteredByNonPedanticMode = 0;
MultipleLambdaCapturesTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}}
};
void fMultipleLambdaCapturesTest2() {
int b1, b2 = 3, b3;
auto equals = [b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized pointee 'this->functor.b3'}}
MultipleLambdaCapturesTest2<decltype(equals)>(equals, int());
}
//===----------------------------------------------------------------------===//
// 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 {
int i; // expected-note{{uninitialized field 'this->i'}}
int dontGetFilteredByNonPedanticMode = 0;
Singleton() {
assert(!isInstantiated);
isInstantiated = true; // expected-warning{{1 uninitialized field}}
}
~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
}