Fixed #11101 (False positive: derived union members are initialized in constructor)

This commit is contained in:
Daniel Marjamäki 2022-06-16 20:17:43 +02:00
parent 3e09503561
commit 968d8d153e
2 changed files with 56 additions and 2 deletions

View File

@ -124,6 +124,28 @@ static bool isVclTypeInit(const Type *type)
return false;
}
// Plain old C struct?
static bool isPodStruct(const Scope *scope) {
if (scope->type != Scope::ScopeType::eStruct && scope->type != Scope::ScopeType::eUnion)
return false;
if (!scope->functionList.empty())
return false;
for (const Variable& var: scope->varlist) {
if (!var.valueType())
return false;
if (var.valueType()->isIntegral() || var.valueType()->pointer || var.valueType()->isFloat())
continue;
if (var.valueType()->typeScope && isPodStruct(var.valueType()->typeScope))
continue;
return false;
}
for (const Scope* childScope: scope->nestedList) {
if (!isPodStruct(childScope))
return false;
}
return true;
}
//---------------------------------------------------------------------------
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
@ -298,17 +320,30 @@ void CheckClass::constructors()
const Scope *varType = var.typeScope();
if (!varType || varType->type != Scope::eUnion) {
const bool derived = scope != var.scope();
// is the derived variable declared in a plain old C struct
bool varScopeIsPodStruct = false;
if (derived && scope->definedType && scope->definedType->derivedFrom.size() > 0) {
for (const Scope* s = var.scope(); s; s = s ? s->nestedIn : nullptr) {
for (const Type::BaseInfo& baseInfo: scope->definedType->derivedFrom) {
if (s->definedType == baseInfo.type) {
varScopeIsPodStruct = isPodStruct(s);
s = nullptr;
break;
}
}
}
}
if (func.type == Function::eConstructor &&
func.nestedIn && (func.nestedIn->numConstructors - func.nestedIn->numCopyOrMoveConstructors) > 1 &&
func.argCount() == 0 && func.functionScope &&
func.arg && func.arg->link()->next() == func.functionScope->bodyStart &&
func.functionScope->bodyStart->link() == func.functionScope->bodyStart->next()) {
// don't warn about user defined default constructor when there are other constructors
if (printInconclusive)
if (printInconclusive && (!derived || !varScopeIsPodStruct))
uninitVarError(func.token, func.access == AccessControl::Private, func.type, var.scope()->className, var.name(), derived, true);
} else if (missingCopy)
missingMemberCopyError(func.token, func.type, var.scope()->className, var.name());
else
else if (!derived || !varScopeIsPodStruct)
uninitVarError(func.token, func.access == AccessControl::Private, func.type, var.scope()->className, var.name(), derived, false);
}
}

View File

@ -126,6 +126,7 @@ private:
TEST_CASE(initvar_delegate); // ticket #4302
TEST_CASE(initvar_delegate2);
TEST_CASE(initvar_derived_class);
TEST_CASE(initvar_derived_pod_struct); // #11101
TEST_CASE(initvar_private_constructor); // BUG 2354171 - private constructor
TEST_CASE(initvar_copy_constructor); // ticket #1611
@ -1416,6 +1417,24 @@ private:
}
void initvar_derived_pod_struct() {
check("struct S {\n"
" union {\n"
" unsigned short all;\n"
" struct {\n"
" unsigned char flag1;\n"
" unsigned char flag2;\n"
" };\n"
" };\n"
"};\n"
"\n"
"class C : public S {\n"
"public:\n"
" C() { all = 0; tick = 0; }\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void initvar_private_constructor() {
settings.standards.cpp = Standards::CPP11;
check("class Fred\n"