Fixed #5022 (Improve check: Division by zero or useless condition, function call)
This commit is contained in:
parent
19745bbb7d
commit
3de9431507
|
@ -2165,7 +2165,7 @@ void CheckOther::checkZeroDivisionOrUselessCondition()
|
|||
for (std::size_t functionIndex = 0; functionIndex < numberOfFunctions; ++functionIndex) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[functionIndex];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[/%] %var% !!.")) {
|
||||
if (Token::Match(tok, "[/%] %var% !!.") || Token::Match(tok, "[(,] %var% [,)]")) {
|
||||
const unsigned int varid = tok->next()->varId();
|
||||
const Variable *var = tok->next()->variable();
|
||||
if (!var)
|
||||
|
@ -2177,8 +2177,61 @@ void CheckOther::checkZeroDivisionOrUselessCondition()
|
|||
break;
|
||||
}
|
||||
}
|
||||
const Token *tok2;
|
||||
|
||||
const Token *divtok = tok;
|
||||
|
||||
// Check if variable is divided by function..
|
||||
if (Token::Match(tok, "[(,]")) {
|
||||
const Token *ftok = tok;
|
||||
unsigned int parnum = 0U;
|
||||
while (ftok && ftok->str() != "(") {
|
||||
if (ftok->str() == ")")
|
||||
ftok = ftok->link();
|
||||
else if (ftok->str() == ",")
|
||||
parnum++;
|
||||
ftok = ftok ? ftok->previous() : NULL;
|
||||
}
|
||||
ftok = ftok ? ftok->previous() : NULL;
|
||||
if (!Token::Match(ftok, "%var% (") && ftok->function())
|
||||
continue;
|
||||
|
||||
const Function * const function = ftok->function();
|
||||
const Variable * const arg = function ? function->getArgumentVar(parnum) : NULL;
|
||||
const Token *argtok = arg ? arg->typeStartToken() : NULL;
|
||||
|
||||
if (!argtok)
|
||||
continue;
|
||||
|
||||
if (argtok->str() == "const")
|
||||
argtok = argtok->next();
|
||||
|
||||
if (!Token::Match(argtok,"%type% %var% ,|)"))
|
||||
continue;
|
||||
|
||||
const Scope * const functionScope = function ? function->functionScope : NULL;
|
||||
if (!functionScope)
|
||||
continue;
|
||||
|
||||
const unsigned int varid2 = argtok->next()->varId();
|
||||
divtok = NULL;
|
||||
bool use = false;
|
||||
for (const Token *tok2 = functionScope->classStart->next(); tok2 != functionScope->classEnd; tok2 = tok2->next()) {
|
||||
if (Token::Match(tok2, "[%/] %varid%", varid2)) {
|
||||
divtok = tok2;
|
||||
tok2 = tok2->next();
|
||||
} else if (tok2->str() != "&" && Token::Match(tok2, "%cop% %varid%",varid2)) {
|
||||
tok2 = tok2->next();
|
||||
} else if (tok2->varId() == varid2 || tok2->str() == "{") {
|
||||
use = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!divtok || use)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for if condition
|
||||
const Token *tok2;
|
||||
for (tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) {
|
||||
if (tok2->varId() == varid)
|
||||
break;
|
||||
|
@ -2193,11 +2246,11 @@ void CheckOther::checkZeroDivisionOrUselessCondition()
|
|||
if (tok2->str() == "{")
|
||||
break;
|
||||
if (isVarUnsigned && Token::Match(tok2, "(|%oror%|&& 0 < %varid% &&|%oror%|)", varid))
|
||||
zerodivcondError(tok2,tok);
|
||||
zerodivcondError(tok2,divtok);
|
||||
else if (isVarUnsigned && Token::Match(tok2, "(|%oror%|&& 1 <= %varid% &&|%oror%|)", varid))
|
||||
zerodivcondError(tok2,tok);
|
||||
zerodivcondError(tok2,divtok);
|
||||
else if (Token::Match(tok2, "(|%oror%|&& !| %varid% &&|%oror%|)", varid))
|
||||
zerodivcondError(tok2,tok);
|
||||
zerodivcondError(tok2,divtok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -456,6 +456,14 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x!=0' is useless or there is division by zero at line 2.\n", errout.str());
|
||||
|
||||
// function call
|
||||
check("void f1(int x, int y) { c=x/y; }\n"
|
||||
"void f2(unsigned int y) {\n"
|
||||
" f1(123,y);\n"
|
||||
" if (y>0){}\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Either the condition 'y>0' is useless or there is division by zero at line 1.\n", errout.str());
|
||||
|
||||
// avoid false positives when variable is changed after division
|
||||
check("void f() {\n"
|
||||
" unsigned int x = do_something();\n"
|
||||
|
|
Loading…
Reference in New Issue