diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 06d26b0b6..32a1bac13 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -285,6 +285,9 @@ static bool isNonCopyable(const Scope *scope, bool *unknown) continue; } + if (isNonCopyable(baseInfo.type->classScope, &u)) + return true; + for (const Function &func : baseInfo.type->classScope->functionList) { if (func.type != Function::eCopyConstructor) continue; diff --git a/test/testclass.cpp b/test/testclass.cpp index f96606cc1..003340ef1 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -69,6 +69,7 @@ private: TEST_CASE(copyConstructor1); TEST_CASE(copyConstructor2); // ticket #4458 TEST_CASE(copyConstructor3); // defaulted/deleted + TEST_CASE(copyConstructor4); // base class with private constructor TEST_CASE(noOperatorEq); // class with memory management should have operator eq TEST_CASE(noDestructor); // class with memory management should have destructor @@ -835,6 +836,29 @@ private: ASSERT_EQUALS("[test.cpp:3]: (style) Struct 'F' has dynamic memory/resource allocation(s). The copy constructor is explicitly defaulted but the default copy constructor does not work well. It is recommended to define or delete the copy constructor.\n", errout.str()); } + void copyConstructor4() { + checkCopyConstructor("class noncopyable {\n" + "protected:\n" + " noncopyable() {}\n" + " ~noncopyable() {}\n" + "\n" + "private:\n" + " noncopyable( const noncopyable& );\n" + " const noncopyable& operator=( const noncopyable& );\n" + "};\n" + "\n" + "class Base : private noncopyable {};\n" + "\n" + "class Foo : public Base {\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"