From 8631ee65a3586fd59a13156e96e0daa348807a90 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 18 Jan 2011 07:34:11 +0100 Subject: [PATCH] Fixed #2474 (false positive: Member variable 'A::m_SemVar' is not initialised in the constructor.) --- lib/checkclass.cpp | 21 +++++++++++++++++ lib/checkclass.h | 2 ++ test/testconstructors.cpp | 47 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c95ddc43a..c85acc311 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -133,6 +133,10 @@ void CheckClass::constructors() continue; } + // Check if type can't be copied + if (var->type && canNotCopy(var->type)) + continue; + // It's non-static and it's not initialized => error if (func->type == Function::eOperatorEqual) { @@ -162,6 +166,23 @@ void CheckClass::constructors() } } +bool CheckClass::canNotCopy(const Scope *scope) const +{ + std::list::const_iterator func; + bool privateAssign = false; + bool privateCopy = false; + + for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) + { + if (func->type == Function::eCopyConstructor && func->access == Private) + privateCopy = true; + else if (func->type == Function::eOperatorEqual && func->access == Private) + privateAssign = true; + } + + return privateAssign && privateCopy; +} + void CheckClass::assignVar(const std::string &varname, const Scope *scope, std::vector &usage) { std::list::const_iterator var; diff --git a/lib/checkclass.h b/lib/checkclass.h index 1fa99d1b9..dd5f15883 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -227,6 +227,8 @@ private: * @param usage reference to usage vector */ void initializeVarList(const Function &func, std::list &callstack, const Scope *scope, std::vector &usage); + + bool canNotCopy(const Scope *scope) const; }; /// @} //--------------------------------------------------------------------------- diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 826baff02..ba5e90b31 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -76,6 +76,7 @@ private: TEST_CASE(initvar_private_constructor); // BUG 2354171 - private constructor TEST_CASE(initvar_copy_constructor); // ticket #1611 TEST_CASE(initvar_nested_constructor); // ticket #1375 + TEST_CASE(initvar_nocopy); // ticket #2474 TEST_CASE(initvar_destructor); // No variables need to be initialized in a destructor @@ -905,6 +906,52 @@ private: "[test.cpp:24]: (warning) Member variable 'D::d' is not initialised in the constructor.\n", errout.str()); } + void initvar_nocopy() // ticket #2474 + { + check("class B\n" + "{\n" + " B (const B & Var);\n" + " B & operator= (const B & Var);\n" + "};\n" + "class A\n" + "{\n" + " B m_SemVar;\n" + "public:\n" + " A(){}\n" + " A(const A&){}\n" + " const A& operator=(const A&){return *this;}\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + check("class B\n" + "{\n" + "public:\n" + " B (const B & Var);\n" + " B & operator= (const B & Var);\n" + "};\n" + "class A\n" + "{\n" + " B m_SemVar;\n" + "public:\n" + " A(){}\n" + " A(const A&){}\n" + " const A& operator=(const A&){return *this;}\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:12]: (warning) Member variable 'A::m_SemVar' is not initialised in the constructor.\n" + "[test.cpp:13]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='\n", errout.str()); + + check("class A\n" + "{\n" + " B m_SemVar;\n" + "public:\n" + " A(){}\n" + " A(const A&){}\n" + " const A& operator=(const A&){return *this;}\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:6]: (warning) Member variable 'A::m_SemVar' is not initialised in the constructor.\n" + "[test.cpp:7]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='\n", errout.str()); + } + void initvar_destructor() { check("class Fred\n"