Fixed #4620 (False positive: Uninitialized variable in constructor (1.58))

This commit is contained in:
Robert Reif 2013-02-27 06:59:04 +01:00 committed by Daniel Marjamäki
parent c07576e07e
commit 509061afff
4 changed files with 47 additions and 16 deletions

View File

@ -364,10 +364,8 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
// Class constructor.. initializing variables like this
// clKalle::clKalle() : var(value) { }
if (initList) {
if (level == 0 && Token::Match(ftok, "%var% (")) {
if (ftok->str() != func.name()) {
initVar(ftok->str(), scope, usage);
} else { // c++11 delegate constructor
if (level == 0 && Token::Match(ftok, "%type% (")) {
if (ftok->str() == func.name()) { // c++11 delegate constructor
const Function *member = scope->findFunction(ftok);
// member function found
if (member) {
@ -392,7 +390,10 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
assignAllVar(usage);
}
}
} else { // base class constructor
}
} else if (level == 0 && Token::Match(ftok, "%var% (")) {
initVar(ftok->str(), scope, usage);
} else if (level == 0 && Token::Match(ftok, "%var% {") && ftok->str() != "const" && Token::Match(ftok->next()->link()->next(), ",|{|%type%")) {
initVar(ftok->str(), scope, usage);
ftok = ftok->linkAt(1);
@ -496,9 +497,8 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
// Calling member function?
else if (Token::simpleMatch(ftok, "operator= (") &&
ftok->previous()->str() != "::") {
const Function *member = scope->findFunction(ftok);
// member function found
if (member) {
if (ftok->function() && ftok->function()->nestedIn == scope) {
const Function *member = ftok->function();
// recursive call
// assume that all variables are initialized
if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
@ -538,10 +538,10 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
}
// check if member function
const Function *member = scope->findFunction(ftok);
if (ftok->function() && ftok->function()->nestedIn == scope &&
ftok->function()->type != Function::eConstructor) {
const Function *member = ftok->function();
// member function found
if (member && member->type != Function::eConstructor) {
// recursive call
// assume that all variables are initialized
if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
@ -801,7 +801,7 @@ void CheckClass::unusedPrivateFunctionError(const Token *tok, const std::string
// ClassCheck: Check that memset is not used on classes
//---------------------------------------------------------------------------
const Scope* findFunctionOf(const Scope* scope)
static const Scope* findFunctionOf(const Scope* scope)
{
while (scope) {
if (scope->type == Scope::eFunction)

View File

@ -1885,7 +1885,6 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
// skip default values
if (tok->str() == "=") {
initArgCount++;
while (tok->str() != "," && tok->str() != ")") {
if (tok->link() && Token::Match(tok, "[{[(<]"))
tok = tok->link();
@ -1898,6 +1897,12 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
if (tok->str() == ")")
break;
}
// count deafult arguments
for (const Token* tok = argDef->next(); tok && tok != argDef->link(); tok = tok->next()) {
if (tok->str() == "=")
initArgCount++;
}
}
}
@ -2378,7 +2383,7 @@ const Scope *SymbolDatabase::findVariableType(const Scope *start, const Token *t
//---------------------------------------------------------------------------
/** @todo This function only counts the number of arguments in the function call.
It does not take into account functions with default arguments.
It does not take into account function constantness.
It does not take into account argument types. This can be difficult because of promotion and conversion operators and casts and because the argument can also be a function call.
*/
const Function* Scope::findFunction(const Token *tok) const
@ -2388,7 +2393,7 @@ const Function* Scope::findFunction(const Token *tok) const
const Function *func = &*i;
if (tok->strAt(1) == "(" && tok->tokAt(2)) {
// check if function has no arguments
if (tok->strAt(2) == ")" && (func->argCount() == 0 || func->argCount() == func->initializedArgCount()))
if (tok->strAt(2) == ")" && (func->argCount() == 0 || func->minArgCount() == 0))
return func;
// check the arguments
@ -2396,12 +2401,13 @@ const Function* Scope::findFunction(const Token *tok) const
const Token *arg = tok->tokAt(2);
while (arg && arg->str() != ")") {
/** @todo check argument type for match */
/** @todo check for default arguments */
args++;
arg = arg->nextArgument();
}
if (args == func->argCount())
// check for argument count match or default arguments
if (args == func->argCount() ||
(args < func->argCount() && args >= func->minArgCount()))
return func;
}
}

View File

@ -403,6 +403,9 @@ public:
std::size_t argCount() const {
return argumentList.size();
}
std::size_t minArgCount() const {
return argumentList.size() - initArgCount;
}
const Variable* getArgumentVar(unsigned int num) const;
unsigned int initializedArgCount() const {
return initArgCount;

View File

@ -64,6 +64,7 @@ private:
TEST_CASE(simple9); // ticket #4574
TEST_CASE(simple10); // ticket #4388
TEST_CASE(simple11); // ticket #4536
TEST_CASE(simple12); // ticket #4620
TEST_CASE(initvar_with_this); // BUG 2190300
TEST_CASE(initvar_if); // BUG 2190290
@ -353,6 +354,27 @@ private:
ASSERT_EQUALS("", errout.str());
}
void simple12() { // ticket #4620
check("class Fred {\n"
" int x;\n"
"public:\n"
" Fred() { Init(); }\n"
" void Init(int i = 0);\n"
"};\n"
"void Fred::Init(int i) { x = i; }\n");
ASSERT_EQUALS("", errout.str());
check("class Fred {\n"
" int x;\n"
" int y;\n"
"public:\n"
" Fred() { Init(0); }\n"
" void Init(int i, int j = 0);\n"
"};\n"
"void Fred::Init(int i, int j) { x = i; y = j; }\n");
ASSERT_EQUALS("", errout.str());
}
void initvar_with_this() {
check("struct Fred\n"
"{\n"