ValueFlow: Improved analysis of assignments

This commit is contained in:
Daniel Marjamäki 2014-08-05 08:28:46 +02:00
parent a2f776b1b7
commit 9eb28cb8af
2 changed files with 8 additions and 4 deletions

View File

@ -641,6 +641,7 @@ static bool valueFlowForward(Token * const startToken,
unsigned int number_of_if = 0; unsigned int number_of_if = 0;
int varusagelevel = -1; int varusagelevel = -1;
bool returnStatement = false; // current statement is a return, stop analysis at the ";" bool returnStatement = false; // current statement is a return, stop analysis at the ";"
bool read = false; // is variable value read?
for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) { for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
if (indentlevel >= 0 && tok2->str() == "{") if (indentlevel >= 0 && tok2->str() == "{")
@ -692,6 +693,9 @@ static bool valueFlowForward(Token * const startToken,
bool varusage = (indentlevel >= 0 && constValue && number_of_if == 0U) ? bool varusage = (indentlevel >= 0 && constValue && number_of_if == 0U) ?
isVariableChanged(start,end,varid) : isVariableChanged(start,end,varid) :
(nullptr != Token::findmatch(start, "%varid%", end, varid)); (nullptr != Token::findmatch(start, "%varid%", end, varid));
if (!read) {
read = bool(nullptr != Token::findmatch(tok2, "%varid% !!=", end, varid));
}
if (varusage) { if (varusage) {
varusagelevel = indentlevel; varusagelevel = indentlevel;
@ -699,7 +703,7 @@ static bool valueFlowForward(Token * const startToken,
return false; return false;
// TODO: don't check noreturn scopes // TODO: don't check noreturn scopes
if (number_of_if > 0U || Token::findmatch(tok2, "%varid%", start, varid)) { if (read && (number_of_if > 0U || Token::findmatch(tok2, "%varid%", start, varid))) {
if (settings->debugwarnings) if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok2, "variable " + var->nameToken()->str() + " is assigned in conditional code"); bailout(tokenlist, errorLogger, tok2, "variable " + var->nameToken()->str() + " is assigned in conditional code");
return false; return false;
@ -731,7 +735,7 @@ static bool valueFlowForward(Token * const startToken,
} }
if (isVariableChanged(start, end, varid)) { if (isVariableChanged(start, end, varid)) {
if (number_of_if == 0 && if ((!read || number_of_if == 0) &&
Token::simpleMatch(tok2, "if (") && Token::simpleMatch(tok2, "if (") &&
!(Token::simpleMatch(end, "} else {") && !(Token::simpleMatch(end, "} else {") &&
(Token::findmatch(end, "%varid%", end->linkAt(2), varid) || (Token::findmatch(end, "%varid%", end->linkAt(2), varid) ||

View File

@ -678,9 +678,9 @@ private:
" int x = 123;\n" " int x = 123;\n"
" if (condition1) x = 456;\n" " if (condition1) x = 456;\n"
" if (condition2) x = 789;\n" " if (condition2) x = 789;\n"
" a = 2 + x;\n" " a = 2 + x;\n" // <- either assignment "x=123" is redundant or x can be 123 here.
"}"; "}";
ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); ASSERT_EQUALS(true, testValueOfX(code, 5U, 123));
code = "void f(int a) {\n" code = "void f(int a) {\n"
" int x = 123;\n" " int x = 123;\n"