Tweak the CheckClass::constructors() check
This commit is contained in:
parent
79664abf2a
commit
61c56eda44
|
@ -65,6 +65,11 @@ static const char * getFunctionTypeName(Function::Type type)
|
||||||
return "";
|
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)
|
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())
|
if (usage[count].assign || usage[count].init || var.isStatic())
|
||||||
continue;
|
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
|
if (var.isConst() && func.isOperator()) // We can't set const members in assignment operator
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -185,16 +193,11 @@ void CheckClass::constructors()
|
||||||
bool inconclusive = false;
|
bool inconclusive = false;
|
||||||
// Don't warn about unknown types in copy constructors since we
|
// Don't warn about unknown types in copy constructors since we
|
||||||
// don't know if they can be copied or not..
|
// don't know if they can be copied or not..
|
||||||
if (!var.isPointer() &&
|
if ((func.type == Function::eCopyConstructor || func.type == Function::eOperatorEqual) && !isVariableCopyNeeded(var))
|
||||||
!(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;
|
inconclusive = true;
|
||||||
else
|
|
||||||
|
if (!printInconclusive && inconclusive)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's non-static and it's not initialized => error
|
// It's non-static and it's not initialized => error
|
||||||
if (func.type == Function::eOperatorEqual) {
|
if (func.type == Function::eOperatorEqual) {
|
||||||
|
|
|
@ -88,6 +88,7 @@ private:
|
||||||
TEST_CASE(initvar_operator_eq3);
|
TEST_CASE(initvar_operator_eq3);
|
||||||
TEST_CASE(initvar_operator_eq4); // ticket #2204
|
TEST_CASE(initvar_operator_eq4); // ticket #2204
|
||||||
TEST_CASE(initvar_operator_eq5); // ticket #4119
|
TEST_CASE(initvar_operator_eq5); // ticket #4119
|
||||||
|
TEST_CASE(initvar_operator_eq6);
|
||||||
TEST_CASE(initvar_same_classname); // BUG 2208157
|
TEST_CASE(initvar_same_classname); // BUG 2208157
|
||||||
TEST_CASE(initvar_chained_assign); // BUG 2270433
|
TEST_CASE(initvar_chained_assign); // BUG 2270433
|
||||||
TEST_CASE(initvar_2constructors); // BUG 2270353
|
TEST_CASE(initvar_2constructors); // BUG 2270353
|
||||||
|
@ -764,6 +765,32 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void initvar_same_classname() {
|
||||||
// Bug 2208157 - False positive: Uninitialized variable, same class name
|
// Bug 2208157 - False positive: Uninitialized variable, same class name
|
||||||
|
|
||||||
|
@ -1327,14 +1354,13 @@ private:
|
||||||
" A(A &&){}\n"
|
" A(A &&){}\n"
|
||||||
" const A& operator=(const A&){return *this;}\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"
|
ASSERT_EQUALS("", errout.str());
|
||||||
"[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());
|
|
||||||
|
|
||||||
check("class B\n"
|
check("class B\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" B (B && Var);\n"
|
" B (B && Var);\n"
|
||||||
|
" int data;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1345,13 +1371,14 @@ private:
|
||||||
" A(A &&){}\n"
|
" A(A &&){}\n"
|
||||||
" const A& operator=(const A&){return *this;}\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"
|
check("class B\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" B ();\n"
|
" B ();\n"
|
||||||
" B & operator= (const B & Var);\n"
|
" B & operator= (const B & Var);\n"
|
||||||
|
" int data;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1362,9 +1389,7 @@ private:
|
||||||
" A(A &&){}\n"
|
" A(A &&){}\n"
|
||||||
" const A& operator=(const A&){return *this;}\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"
|
ASSERT_EQUALS("", 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());
|
|
||||||
|
|
||||||
check("class A\n"
|
check("class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1382,6 +1407,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" B (B & Var);\n"
|
" B (B & Var);\n"
|
||||||
" B & operator= (const B & Var);\n"
|
" B & operator= (const B & Var);\n"
|
||||||
|
" int data;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1390,7 +1416,7 @@ private:
|
||||||
" A(){}\n"
|
" A(){}\n"
|
||||||
" A(const A&){}\n"
|
" A(const A&){}\n"
|
||||||
" const A& operator=(const A&){return *this;}\n"
|
" const A& operator=(const A&){return *this;}\n"
|
||||||
"};");
|
"};", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("class B\n"
|
check("class B\n"
|
||||||
|
@ -1398,6 +1424,7 @@ private:
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" B (B & Var);\n"
|
" B (B & Var);\n"
|
||||||
" B & operator= (const B & Var);\n"
|
" B & operator= (const B & Var);\n"
|
||||||
|
" int data;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1406,9 +1433,10 @@ private:
|
||||||
" A(){}\n"
|
" A(){}\n"
|
||||||
" A(const A&){}\n"
|
" A(const A&){}\n"
|
||||||
" const A& operator=(const A&){return *this;}\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"
|
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
|
void initvar_nocopy3() { // #3611 - unknown type is non-copyable
|
||||||
|
|
Loading…
Reference in New Issue