Skip to content

Commit 968d8d1

Browse files
committed
Fixed #11101 (False positive: derived union members are initialized in constructor)
1 parent 3e09503 commit 968d8d1

2 files changed

Lines changed: 56 additions & 2 deletions

File tree

lib/checkclass.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,28 @@ static bool isVclTypeInit(const Type *type)
124124
return false;
125125
}
126126

127+
// Plain old C struct?
128+
static bool isPodStruct(const Scope *scope) {
129+
if (scope->type != Scope::ScopeType::eStruct && scope->type != Scope::ScopeType::eUnion)
130+
return false;
131+
if (!scope->functionList.empty())
132+
return false;
133+
for (const Variable& var: scope->varlist) {
134+
if (!var.valueType())
135+
return false;
136+
if (var.valueType()->isIntegral() || var.valueType()->pointer || var.valueType()->isFloat())
137+
continue;
138+
if (var.valueType()->typeScope && isPodStruct(var.valueType()->typeScope))
139+
continue;
140+
return false;
141+
}
142+
for (const Scope* childScope: scope->nestedList) {
143+
if (!isPodStruct(childScope))
144+
return false;
145+
}
146+
return true;
147+
}
148+
127149
//---------------------------------------------------------------------------
128150

129151
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
@@ -298,17 +320,30 @@ void CheckClass::constructors()
298320
const Scope *varType = var.typeScope();
299321
if (!varType || varType->type != Scope::eUnion) {
300322
const bool derived = scope != var.scope();
323+
// is the derived variable declared in a plain old C struct
324+
bool varScopeIsPodStruct = false;
325+
if (derived && scope->definedType && scope->definedType->derivedFrom.size() > 0) {
326+
for (const Scope* s = var.scope(); s; s = s ? s->nestedIn : nullptr) {
327+
for (const Type::BaseInfo& baseInfo: scope->definedType->derivedFrom) {
328+
if (s->definedType == baseInfo.type) {
329+
varScopeIsPodStruct = isPodStruct(s);
330+
s = nullptr;
331+
break;
332+
}
333+
}
334+
}
335+
}
301336
if (func.type == Function::eConstructor &&
302337
func.nestedIn && (func.nestedIn->numConstructors - func.nestedIn->numCopyOrMoveConstructors) > 1 &&
303338
func.argCount() == 0 && func.functionScope &&
304339
func.arg && func.arg->link()->next() == func.functionScope->bodyStart &&
305340
func.functionScope->bodyStart->link() == func.functionScope->bodyStart->next()) {
306341
// don't warn about user defined default constructor when there are other constructors
307-
if (printInconclusive)
342+
if (printInconclusive && (!derived || !varScopeIsPodStruct))
308343
uninitVarError(func.token, func.access == AccessControl::Private, func.type, var.scope()->className, var.name(), derived, true);
309344
} else if (missingCopy)
310345
missingMemberCopyError(func.token, func.type, var.scope()->className, var.name());
311-
else
346+
else if (!derived || !varScopeIsPodStruct)
312347
uninitVarError(func.token, func.access == AccessControl::Private, func.type, var.scope()->className, var.name(), derived, false);
313348
}
314349
}

test/testconstructors.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class TestConstructors : public TestFixture {
126126
TEST_CASE(initvar_delegate); // ticket #4302
127127
TEST_CASE(initvar_delegate2);
128128
TEST_CASE(initvar_derived_class);
129+
TEST_CASE(initvar_derived_pod_struct); // #11101
129130

130131
TEST_CASE(initvar_private_constructor); // BUG 2354171 - private constructor
131132
TEST_CASE(initvar_copy_constructor); // ticket #1611
@@ -1416,6 +1417,24 @@ class TestConstructors : public TestFixture {
14161417

14171418
}
14181419

1420+
void initvar_derived_pod_struct() {
1421+
check("struct S {\n"
1422+
" union {\n"
1423+
" unsigned short all;\n"
1424+
" struct {\n"
1425+
" unsigned char flag1;\n"
1426+
" unsigned char flag2;\n"
1427+
" };\n"
1428+
" };\n"
1429+
"};\n"
1430+
"\n"
1431+
"class C : public S {\n"
1432+
"public:\n"
1433+
" C() { all = 0; tick = 0; }\n"
1434+
"};");
1435+
ASSERT_EQUALS("", errout.str());
1436+
}
1437+
14191438
void initvar_private_constructor() {
14201439
settings.standards.cpp = Standards::CPP11;
14211440
check("class Fred\n"

0 commit comments

Comments
 (0)