Class: Show inconclusive warnings about unknown types that are not initialized in copy constructors. Ticket: #3611

This commit is contained in:
Daniel Marjamäki 2012-09-20 19:16:26 +02:00
parent 07db469c06
commit de8e592d00
3 changed files with 55 additions and 18 deletions

View File

@ -107,6 +107,8 @@ void CheckClass::constructors()
std::list<Variable>::const_iterator var;
unsigned int count = 0;
for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var, ++count) {
bool inconclusive = false;
if (usage[count].assign || usage[count].init || var->isStatic())
continue;
@ -131,13 +133,19 @@ void CheckClass::constructors()
// 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->isClass() && (func->type == Function::eCopyConstructor || func->type == Function::eOperatorEqual)) {
if (!var->isPointer() &&
!(var->type() && var->type()->needInitialization != Scope::True) &&
(func->type == Function::eCopyConstructor || func->type == Function::eOperatorEqual)) {
bool stdtype = false;
for (const Token *type = var->typeStartToken(); type && type->isName(); type = type->next())
stdtype |= type->isStandardType();
if (!stdtype)
if (!stdtype) {
if (_settings->inconclusive)
inconclusive = true;
else
continue;
}
}
// It's non-static and it's not initialized => error
if (func->type == Function::eOperatorEqual) {
@ -152,11 +160,11 @@ void CheckClass::constructors()
}
if (classNameUsed)
operatorEqVarError(func->token, scope->className, var->name());
operatorEqVarError(func->token, scope->className, var->name(), inconclusive);
} else if (func->access != Private) {
const Scope *varType = var->type();
if (!varType || varType->type != Scope::eUnion)
uninitVarError(func->token, scope->className, var->name());
uninitVarError(func->token, scope->className, var->name(), inconclusive);
}
}
}
@ -593,14 +601,14 @@ void CheckClass::noConstructorError(const Token *tok, const std::string &classna
"instanciated. That may cause bugs or undefined behavior.");
}
void CheckClass::uninitVarError(const Token *tok, const std::string &classname, const std::string &varname)
void CheckClass::uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive)
{
reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.");
reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", inconclusive);
}
void CheckClass::operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname)
void CheckClass::operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive)
{
reportError(tok, Severity::warning, "operatorEqVarError", "Member variable '" + classname + "::" + varname + "' is not assigned a value in '" + classname + "::operator='.");
reportError(tok, Severity::warning, "operatorEqVarError", "Member variable '" + classname + "::" + varname + "' is not assigned a value in '" + classname + "::operator='.", inconclusive);
}
//---------------------------------------------------------------------------

View File

@ -126,8 +126,8 @@ private:
//void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name);
void copyConstructorShallowCopyError(const Token *tok, const std::string& varname);
void noCopyConstructorError(const Token *tok, const std::string &classname, bool isStruct);
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname);
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive);
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive);
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname);
void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type);
void operatorEqReturnError(const Token *tok, const std::string &className);
@ -146,8 +146,8 @@ private:
//c.copyConstructorMallocError(0, 0, "var");
c.copyConstructorShallowCopyError(0, "var");
c.noCopyConstructorError(0, "class", false);
c.uninitVarError(0, "classname", "varname");
c.operatorEqVarError(0, "classname", "");
c.uninitVarError(0, "classname", "varname", false);
c.operatorEqVarError(0, "classname", "", false);
c.unusedPrivateFunctionError(0, "classname", "funcname");
c.memsetError(0, "memfunc", "classname", "class");
c.operatorEqReturnError(0, "class");

View File

@ -77,6 +77,7 @@ private:
TEST_CASE(initvar_nested_constructor); // ticket #1375
TEST_CASE(initvar_nocopy1); // ticket #2474
TEST_CASE(initvar_nocopy2); // ticket #2484
TEST_CASE(initvar_nocopy3); // ticket #3611
TEST_CASE(initvar_destructor); // No variables need to be initialized in a destructor
@ -677,7 +678,7 @@ private:
" Fred() { };\n"
" Fred(const Fred &) { };\n"
"};");
ASSERT_EQUALS("[test.cpp:7]: (warning) Member variable 'Fred::var' is not initialized in the constructor.\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("class Fred\n"
"{\n"
@ -689,7 +690,29 @@ private:
"};\n"
"Fred::Fred() { };\n"
"Fred::Fred(const Fred &) { };\n");
ASSERT_EQUALS("[test.cpp:10]: (warning) Member variable 'Fred::var' is not initialized in the constructor.\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("class Fred\n"
"{\n"
"private:\n"
" std::string var;\n"
"public:\n"
" Fred() { };\n"
" Fred(const Fred &) { };\n"
"};", true);
ASSERT_EQUALS("[test.cpp:7]: (warning, inconclusive) Member variable 'Fred::var' is not initialized in the constructor.\n", errout.str());
check("class Fred\n"
"{\n"
"private:\n"
" std::string var;\n"
"public:\n"
" Fred();\n"
" Fred(const Fred &);\n"
"};\n"
"Fred::Fred() { };\n"
"Fred::Fred(const Fred &) { };\n", true);
ASSERT_EQUALS("[test.cpp:10]: (warning, inconclusive) Member variable 'Fred::var' is not initialized in the constructor.\n", errout.str());
}
void initvar_nested_constructor() { // ticket #1375
@ -823,8 +846,7 @@ private:
" 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 initialized in the constructor.\n"
"[test.cpp:7]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='.\n", errout.str());
ASSERT_EQUALS("", errout.str());
}
void initvar_nocopy2() { // ticket #2484
@ -868,6 +890,13 @@ private:
" A(const A& rhs) {}\n"
"};");
ASSERT_EQUALS("", errout.str());
check("struct A {\n"
" B b;\n"
" A() {}\n"
" A(const A& rhs) {}\n"
"};", true);
ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Member variable 'A::b' is not initialized in the constructor.\n", errout.str());
}
void initvar_destructor() {
@ -897,7 +926,7 @@ private:
"\n"
"void Fred::operator=(const Fred &f)\n"
"{ }", true);
ASSERT_EQUALS("[test.cpp:13]: (warning) Member variable 'Fred::ints' is not assigned a value in 'Fred::operator='.\n", errout.str());
ASSERT_EQUALS("[test.cpp:13]: (warning, inconclusive) Member variable 'Fred::ints' is not assigned a value in 'Fred::operator='.\n", errout.str());
}
void uninitVar1() {