Tweak the CheckClass::constructors() check

This commit is contained in:
Daniel Marjamäki 2018-06-27 14:02:57 +02:00
parent 79664abf2a
commit 61c56eda44
2 changed files with 51 additions and 20 deletions

View File

@ -65,6 +65,11 @@ static const char * getFunctionTypeName(Function::Type type)
return "";
}
static bool isVariableCopyNeeded(const Variable &var)
{
return var.isPointer() || (var.type() && var.type()->needInitialization == Type::True) || (var.valueType()->type >= ValueType::Type::CHAR);
}
//---------------------------------------------------------------------------
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
@ -156,6 +161,9 @@ void CheckClass::constructors()
if (usage[count].assign || usage[count].init || var.isStatic())
continue;
if (var.valueType()->pointer == 0 && var.type() && var.type()->needInitialization == Type::False)
continue;
if (var.isConst() && func.isOperator()) // We can't set const members in assignment operator
continue;
@ -185,16 +193,11 @@ void CheckClass::constructors()
bool inconclusive = false;
// Don't warn about unknown types in copy constructors since we
// don't know if they can be copied or not..
if (!var.isPointer() &&
!(var.type() && var.type()->needInitialization != Type::True) &&
(func.type == Function::eCopyConstructor || func.type == Function::eOperatorEqual)) {
if (var.valueType()->type <= ValueType::Type::RECORD) {
if (printInconclusive)
inconclusive = true;
else
continue;
}
}
if ((func.type == Function::eCopyConstructor || func.type == Function::eOperatorEqual) && !isVariableCopyNeeded(var))
inconclusive = true;
if (!printInconclusive && inconclusive)
continue;
// It's non-static and it's not initialized => error
if (func.type == Function::eOperatorEqual) {

View File

@ -88,6 +88,7 @@ private:
TEST_CASE(initvar_operator_eq3);
TEST_CASE(initvar_operator_eq4); // ticket #2204
TEST_CASE(initvar_operator_eq5); // ticket #4119
TEST_CASE(initvar_operator_eq6);
TEST_CASE(initvar_same_classname); // BUG 2208157
TEST_CASE(initvar_chained_assign); // BUG 2270433
TEST_CASE(initvar_2constructors); // BUG 2270353
@ -764,6 +765,32 @@ private:
ASSERT_EQUALS("", errout.str());
}
void initvar_operator_eq6() { // std::vector
check("struct Fred {\n"
" uint8_t data;\n"
" Fred & operator=(const Fred &rhs) {\n"
" return *this;\n"
" }\n"
"};",true);
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Member variable 'Fred::data' is not assigned a value in 'Fred::operator='.\n", errout.str());
check("struct Fred {\n"
" std::vector<int> ints;\n"
" Fred & operator=(const Fred &rhs) {\n"
" return *this;\n"
" }\n"
"};",true);
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Member variable 'Fred::ints' is not assigned a value in 'Fred::operator='.\n", errout.str());
check("struct Fred {\n"
" Data data;\n"
" Fred & operator=(const Fred &rhs) {\n"
" return *this;\n"
" }\n"
"};",true);
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Member variable 'Fred::data' is not assigned a value in 'Fred::operator='.\n", errout.str());
}
void initvar_same_classname() {
// Bug 2208157 - False positive: Uninitialized variable, same class name
@ -1327,14 +1354,13 @@ private:
" A(A &&){}\n"
" const A& operator=(const A&){return *this;}\n"
"};");
ASSERT_EQUALS("[test.cpp:11]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
"[test.cpp:12]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
"[test.cpp:13]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='.\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("class B\n"
"{\n"
"public:\n"
" B (B && Var);\n"
" int data;\n"
"};\n"
"class A\n"
"{\n"
@ -1345,13 +1371,14 @@ private:
" A(A &&){}\n"
" const A& operator=(const A&){return *this;}\n"
"};");
ASSERT_EQUALS("[test.cpp:12]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n", errout.str());
ASSERT_EQUALS("[test.cpp:13]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n", errout.str());
check("class B\n"
"{\n"
"public:\n"
" B ();\n"
" B & operator= (const B & Var);\n"
" int data;\n"
"};\n"
"class A\n"
"{\n"
@ -1362,9 +1389,7 @@ private:
" A(A &&){}\n"
" const A& operator=(const A&){return *this;}\n"
"};");
ASSERT_EQUALS("[test.cpp:12]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
"[test.cpp:13]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
"[test.cpp:14]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='.\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("class A\n"
"{\n"
@ -1382,6 +1407,7 @@ private:
"{\n"
" B (B & Var);\n"
" B & operator= (const B & Var);\n"
" int data;\n"
"};\n"
"class A\n"
"{\n"
@ -1390,7 +1416,7 @@ private:
" A(){}\n"
" A(const A&){}\n"
" const A& operator=(const A&){return *this;}\n"
"};");
"};", true);
ASSERT_EQUALS("", errout.str());
check("class B\n"
@ -1398,6 +1424,7 @@ private:
"public:\n"
" B (B & Var);\n"
" B & operator= (const B & Var);\n"
" int data;\n"
"};\n"
"class A\n"
"{\n"
@ -1406,9 +1433,10 @@ private:
" A(){}\n"
" A(const A&){}\n"
" const A& operator=(const A&){return *this;}\n"
"};");
"};", true);
ASSERT_EQUALS("[test.cpp:12]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
"[test.cpp:13]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='.\n", errout.str());
"[test.cpp:13]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
"[test.cpp:14]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='.\n", errout.str());
}
void initvar_nocopy3() { // #3611 - unknown type is non-copyable