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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue