Fixed #4620 (False positive: Uninitialized variable in constructor (1.58))
This commit is contained in:
parent
c07576e07e
commit
509061afff
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue