Fix noCopyConstructor with multiple inheritance (#3203)

This commit is contained in:
ericmalenfant 2021-04-09 01:41:59 -04:00 committed by GitHub
parent f8dc9862da
commit 1e9687aa8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 8 deletions

View File

@ -298,27 +298,27 @@ void CheckClass::checkExplicitConstructors()
}
}
static bool isNonCopyable(const Scope *scope, bool *unknown)
static bool hasNonCopyableBase(const Scope *scope, bool *unknown)
{
bool u = false;
// check if there is base class that is not copyable
for (const Type::BaseInfo &baseInfo : scope->definedType->derivedFrom) {
if (!baseInfo.type || !baseInfo.type->classScope) {
u = true;
*unknown = true;
continue;
}
if (isNonCopyable(baseInfo.type->classScope, &u))
if (hasNonCopyableBase(baseInfo.type->classScope, unknown))
return true;
for (const Function &func : baseInfo.type->classScope->functionList) {
if (func.type != Function::eCopyConstructor)
continue;
if (func.access == AccessControl::Private || func.isDelete())
if (func.access == AccessControl::Private || func.isDelete()) {
*unknown = false;
return true;
}
}
*unknown = u;
}
return false;
}
@ -366,12 +366,12 @@ void CheckClass::copyconstructors()
}
if (!funcCopyCtor || funcCopyCtor->isDefault()) {
bool unknown = false;
if (!isNonCopyable(scope, &unknown) && !unknown)
if (!hasNonCopyableBase(scope, &unknown) && !unknown)
noCopyConstructorError(scope, funcCopyCtor, allocatedVars.begin()->second, unknown);
}
if (!funcOperatorEq || funcOperatorEq->isDefault()) {
bool unknown = false;
if (!isNonCopyable(scope, &unknown) && !unknown)
if (!hasNonCopyableBase(scope, &unknown) && !unknown)
noOperatorEqError(scope, funcOperatorEq, allocatedVars.begin()->second, unknown);
}
if (!funcDestructor || funcDestructor->isDefault()) {

View File

@ -71,6 +71,7 @@ private:
TEST_CASE(copyConstructor2); // ticket #4458
TEST_CASE(copyConstructor3); // defaulted/deleted
TEST_CASE(copyConstructor4); // base class with private constructor
TEST_CASE(copyConstructor5); // multiple inheritance
TEST_CASE(noOperatorEq); // class with memory management should have operator eq
TEST_CASE(noDestructor); // class with memory management should have destructor
@ -908,6 +909,30 @@ private:
ASSERT_EQUALS("", errout.str());
}
void copyConstructor5() {
checkCopyConstructor("class Copyable {};\n"
"\n"
"class Foo : public Copyable, public UnknownType {\n"
"public:\n"
" Foo() : m_ptr(new int) {}\n"
" ~Foo() { delete m_ptr; }\n"
"private:\n"
" int* m_ptr;\n"
"};");
ASSERT_EQUALS("", errout.str());
checkCopyConstructor("class Copyable {};\n"
"\n"
"class Foo : public UnknownType, public Copyable {\n"
"public:\n"
" Foo() : m_ptr(new int) {}\n"
" ~Foo() { delete m_ptr; }\n"
"private:\n"
" int* m_ptr;\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void noOperatorEq() {
checkCopyConstructor("struct F {\n"
" char* c;\n"