Class: Show inconclusive warnings about unknown types that are not initialized in copy constructors. Ticket: #3611
This commit is contained in:
parent
07db469c06
commit
de8e592d00
|
@ -107,6 +107,8 @@ void CheckClass::constructors()
|
||||||
std::list<Variable>::const_iterator var;
|
std::list<Variable>::const_iterator var;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var, ++count) {
|
for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var, ++count) {
|
||||||
|
bool inconclusive = false;
|
||||||
|
|
||||||
if (usage[count].assign || usage[count].init || var->isStatic())
|
if (usage[count].assign || usage[count].init || var->isStatic())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -131,12 +133,18 @@ void CheckClass::constructors()
|
||||||
|
|
||||||
// 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() && !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;
|
bool stdtype = false;
|
||||||
for (const Token *type = var->typeStartToken(); type && type->isName(); type = type->next())
|
for (const Token *type = var->typeStartToken(); type && type->isName(); type = type->next())
|
||||||
stdtype |= type->isStandardType();
|
stdtype |= type->isStandardType();
|
||||||
if (!stdtype)
|
if (!stdtype) {
|
||||||
continue;
|
if (_settings->inconclusive)
|
||||||
|
inconclusive = true;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's non-static and it's not initialized => error
|
// It's non-static and it's not initialized => error
|
||||||
|
@ -152,11 +160,11 @@ void CheckClass::constructors()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classNameUsed)
|
if (classNameUsed)
|
||||||
operatorEqVarError(func->token, scope->className, var->name());
|
operatorEqVarError(func->token, scope->className, var->name(), inconclusive);
|
||||||
} else if (func->access != Private) {
|
} else if (func->access != Private) {
|
||||||
const Scope *varType = var->type();
|
const Scope *varType = var->type();
|
||||||
if (!varType || varType->type != Scope::eUnion)
|
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.");
|
"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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -126,8 +126,8 @@ private:
|
||||||
//void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name);
|
//void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name);
|
||||||
void copyConstructorShallowCopyError(const Token *tok, const std::string& varname);
|
void copyConstructorShallowCopyError(const Token *tok, const std::string& varname);
|
||||||
void noCopyConstructorError(const Token *tok, const std::string &classname, bool isStruct);
|
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 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);
|
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 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 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);
|
void operatorEqReturnError(const Token *tok, const std::string &className);
|
||||||
|
@ -146,8 +146,8 @@ private:
|
||||||
//c.copyConstructorMallocError(0, 0, "var");
|
//c.copyConstructorMallocError(0, 0, "var");
|
||||||
c.copyConstructorShallowCopyError(0, "var");
|
c.copyConstructorShallowCopyError(0, "var");
|
||||||
c.noCopyConstructorError(0, "class", false);
|
c.noCopyConstructorError(0, "class", false);
|
||||||
c.uninitVarError(0, "classname", "varname");
|
c.uninitVarError(0, "classname", "varname", false);
|
||||||
c.operatorEqVarError(0, "classname", "");
|
c.operatorEqVarError(0, "classname", "", false);
|
||||||
c.unusedPrivateFunctionError(0, "classname", "funcname");
|
c.unusedPrivateFunctionError(0, "classname", "funcname");
|
||||||
c.memsetError(0, "memfunc", "classname", "class");
|
c.memsetError(0, "memfunc", "classname", "class");
|
||||||
c.operatorEqReturnError(0, "class");
|
c.operatorEqReturnError(0, "class");
|
||||||
|
|
|
@ -77,6 +77,7 @@ private:
|
||||||
TEST_CASE(initvar_nested_constructor); // ticket #1375
|
TEST_CASE(initvar_nested_constructor); // ticket #1375
|
||||||
TEST_CASE(initvar_nocopy1); // ticket #2474
|
TEST_CASE(initvar_nocopy1); // ticket #2474
|
||||||
TEST_CASE(initvar_nocopy2); // ticket #2484
|
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
|
TEST_CASE(initvar_destructor); // No variables need to be initialized in a destructor
|
||||||
|
|
||||||
|
@ -677,7 +678,7 @@ private:
|
||||||
" Fred() { };\n"
|
" Fred() { };\n"
|
||||||
" Fred(const 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"
|
check("class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -689,7 +690,29 @@ private:
|
||||||
"};\n"
|
"};\n"
|
||||||
"Fred::Fred() { };\n"
|
"Fred::Fred() { };\n"
|
||||||
"Fred::Fred(const 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
|
void initvar_nested_constructor() { // ticket #1375
|
||||||
|
@ -823,8 +846,7 @@ private:
|
||||||
" A(const A&){}\n"
|
" A(const A&){}\n"
|
||||||
" const A& operator=(const A&){return *this;}\n"
|
" const A& operator=(const A&){return *this;}\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (warning) Member variable 'A::m_SemVar' is not initialized in the constructor.\n"
|
ASSERT_EQUALS("", errout.str());
|
||||||
"[test.cpp:7]: (warning) Member variable 'A::m_SemVar' is not assigned a value in 'A::operator='.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_nocopy2() { // ticket #2484
|
void initvar_nocopy2() { // ticket #2484
|
||||||
|
@ -868,6 +890,13 @@ private:
|
||||||
" A(const A& rhs) {}\n"
|
" A(const A& rhs) {}\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void initvar_destructor() {
|
||||||
|
@ -897,7 +926,7 @@ private:
|
||||||
"\n"
|
"\n"
|
||||||
"void Fred::operator=(const Fred &f)\n"
|
"void Fred::operator=(const Fred &f)\n"
|
||||||
"{ }", true);
|
"{ }", 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() {
|
void uninitVar1() {
|
||||||
|
|
Loading…
Reference in New Issue