Fixed #11101 (False positive: derived union members are initialized in constructor)
This commit is contained in:
parent
3e09503561
commit
968d8d153e
|
@ -124,6 +124,28 @@ static bool isVclTypeInit(const Type *type)
|
||||||
return false;
|
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)
|
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||||
|
@ -298,17 +320,30 @@ void CheckClass::constructors()
|
||||||
const Scope *varType = var.typeScope();
|
const Scope *varType = var.typeScope();
|
||||||
if (!varType || varType->type != Scope::eUnion) {
|
if (!varType || varType->type != Scope::eUnion) {
|
||||||
const bool derived = scope != var.scope();
|
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 &&
|
if (func.type == Function::eConstructor &&
|
||||||
func.nestedIn && (func.nestedIn->numConstructors - func.nestedIn->numCopyOrMoveConstructors) > 1 &&
|
func.nestedIn && (func.nestedIn->numConstructors - func.nestedIn->numCopyOrMoveConstructors) > 1 &&
|
||||||
func.argCount() == 0 && func.functionScope &&
|
func.argCount() == 0 && func.functionScope &&
|
||||||
func.arg && func.arg->link()->next() == func.functionScope->bodyStart &&
|
func.arg && func.arg->link()->next() == func.functionScope->bodyStart &&
|
||||||
func.functionScope->bodyStart->link() == func.functionScope->bodyStart->next()) {
|
func.functionScope->bodyStart->link() == func.functionScope->bodyStart->next()) {
|
||||||
// don't warn about user defined default constructor when there are other constructors
|
// 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);
|
uninitVarError(func.token, func.access == AccessControl::Private, func.type, var.scope()->className, var.name(), derived, true);
|
||||||
} else if (missingCopy)
|
} else if (missingCopy)
|
||||||
missingMemberCopyError(func.token, func.type, var.scope()->className, var.name());
|
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);
|
uninitVarError(func.token, func.access == AccessControl::Private, func.type, var.scope()->className, var.name(), derived, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@ private:
|
||||||
TEST_CASE(initvar_delegate); // ticket #4302
|
TEST_CASE(initvar_delegate); // ticket #4302
|
||||||
TEST_CASE(initvar_delegate2);
|
TEST_CASE(initvar_delegate2);
|
||||||
TEST_CASE(initvar_derived_class);
|
TEST_CASE(initvar_derived_class);
|
||||||
|
TEST_CASE(initvar_derived_pod_struct); // #11101
|
||||||
|
|
||||||
TEST_CASE(initvar_private_constructor); // BUG 2354171 - private constructor
|
TEST_CASE(initvar_private_constructor); // BUG 2354171 - private constructor
|
||||||
TEST_CASE(initvar_copy_constructor); // ticket #1611
|
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() {
|
void initvar_private_constructor() {
|
||||||
settings.standards.cpp = Standards::CPP11;
|
settings.standards.cpp = Standards::CPP11;
|
||||||
check("class Fred\n"
|
check("class Fred\n"
|
||||||
|
|
Loading…
Reference in New Issue