ValueFlow: only set values in conditional code in subfunctions when sure

This commit is contained in:
Daniel Marjamäki 2016-12-20 11:06:20 +01:00
parent 807b653739
commit e14e86c103
2 changed files with 25 additions and 8 deletions

View File

@ -1242,6 +1242,7 @@ static bool valueFlowForward(Token * const startToken,
const unsigned int varid, const unsigned int varid,
std::list<ValueFlow::Value> values, std::list<ValueFlow::Value> values,
const bool constValue, const bool constValue,
const bool subFunction,
TokenList * const tokenlist, TokenList * const tokenlist,
ErrorLogger * const errorLogger, ErrorLogger * const errorLogger,
const Settings * const settings) const Settings * const settings)
@ -1363,7 +1364,11 @@ static bool valueFlowForward(Token * const startToken,
// Should scope be skipped because variable value is checked? // Should scope be skipped because variable value is checked?
std::list<ValueFlow::Value> truevalues; std::list<ValueFlow::Value> truevalues;
for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) { for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
if (condAlwaysTrue || !conditionIsFalse(condTok, getProgramMemory(tok2, varid, *it))) if (condAlwaysTrue)
truevalues.push_back(*it);
else if (subFunction && conditionIsTrue(condTok, getProgramMemory(tok2, varid, *it)))
truevalues.push_back(*it);
else if (!subFunction && !conditionIsFalse(condTok, getProgramMemory(tok2, varid, *it)))
truevalues.push_back(*it); truevalues.push_back(*it);
} }
if (truevalues.size() != values.size() || condAlwaysTrue) { if (truevalues.size() != values.size() || condAlwaysTrue) {
@ -1376,6 +1381,7 @@ static bool valueFlowForward(Token * const startToken,
varid, varid,
truevalues, truevalues,
constValue, constValue,
subFunction,
tokenlist, tokenlist,
errorLogger, errorLogger,
settings); settings);
@ -1872,7 +1878,7 @@ static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatab
const unsigned int varId = varTok->varId(); const unsigned int varId = varTok->varId();
const Token * const endOfVarScope = var->typeStartToken()->scope()->classEnd; const Token * const endOfVarScope = var->typeStartToken()->scope()->classEnd;
setTokenValue(varTok, value, settings); setTokenValue(varTok, value, settings);
valueFlowForward(varTok->next(), endOfVarScope, var, varId, values, false, tokenlist, errorLogger, settings); valueFlowForward(varTok->next(), endOfVarScope, var, varId, values, false, false, tokenlist, errorLogger, settings);
continue; continue;
} }
ValueFlow::Value::MoveKind moveKind; ValueFlow::Value::MoveKind moveKind;
@ -1904,7 +1910,7 @@ static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatab
const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok); const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok);
const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove); const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
if (endOfFunctionCall) if (endOfFunctionCall)
valueFlowForward(const_cast<Token *>(endOfFunctionCall), endOfVarScope, var, varId, values, false, tokenlist, errorLogger, settings); valueFlowForward(const_cast<Token *>(endOfFunctionCall), endOfVarScope, var, varId, values, false, false, tokenlist, errorLogger, settings);
} }
} }
} }
@ -1965,7 +1971,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
// Skip RHS // Skip RHS
const Token * nextExpression = nextAfterAstRightmostLeaf(tok); const Token * nextExpression = nextAfterAstRightmostLeaf(tok);
valueFlowForward(const_cast<Token *>(nextExpression), endOfVarScope, var, varid, values, constValue, tokenlist, errorLogger, settings); valueFlowForward(const_cast<Token *>(nextExpression), endOfVarScope, var, varid, values, constValue, false, tokenlist, errorLogger, settings);
} }
} }
} }
@ -2089,7 +2095,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
} }
if (startToken) { if (startToken) {
if (!valueFlowForward(startToken->next(), startToken->link(), var, varid, values, true, tokenlist, errorLogger, settings)) if (!valueFlowForward(startToken->next(), startToken->link(), var, varid, values, true, false, tokenlist, errorLogger, settings))
continue; continue;
if (isVariableChanged(startToken, startToken->link(), varid, settings)) { if (isVariableChanged(startToken, startToken->link(), varid, settings)) {
// TODO: The endToken should not be startToken->link() in the valueFlowForward call // TODO: The endToken should not be startToken->link() in the valueFlowForward call
@ -2125,7 +2131,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
// TODO: constValue could be true if there are no assignments in the conditional blocks and // TODO: constValue could be true if there are no assignments in the conditional blocks and
// perhaps if there are no && and no || in the condition // perhaps if there are no && and no || in the condition
bool constValue = false; bool constValue = false;
valueFlowForward(after->next(), top->scope()->classEnd, var, varid, values, constValue, tokenlist, errorLogger, settings); valueFlowForward(after->next(), top->scope()->classEnd, var, varid, values, constValue, false, tokenlist, errorLogger, settings);
} }
} }
} }
@ -2503,6 +2509,7 @@ static void valueFlowForLoopSimplifyAfter(Token *fortok, unsigned int varid, con
varid, varid,
values, values,
false, false,
false,
tokenlist, tokenlist,
errorLogger, errorLogger,
settings); settings);
@ -2566,7 +2573,7 @@ static void valueFlowInjectParameter(TokenList* tokenlist, ErrorLogger* errorLog
if (!varid2) if (!varid2)
return; return;
valueFlowForward(const_cast<Token*>(functionScope->classStart->next()), functionScope->classEnd, arg, varid2, argvalues, false, tokenlist, errorLogger, settings); valueFlowForward(const_cast<Token*>(functionScope->classStart->next()), functionScope->classEnd, arg, varid2, argvalues, false, true, tokenlist, errorLogger, settings);
} }
static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
@ -2614,7 +2621,7 @@ static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symbol
settings); settings);
} }
if (vartok->variable()->scope()) // #7257 if (vartok->variable()->scope()) // #7257
valueFlowForward(tok, vartok->variable()->scope()->classEnd, vartok->variable(), vartok->varId(), values, false, tokenlist, errorLogger, settings); valueFlowForward(tok, vartok->variable()->scope()->classEnd, vartok->variable(), vartok->varId(), values, false, false, tokenlist, errorLogger, settings);
} }
} }
} }

View File

@ -1974,6 +1974,16 @@ private:
"};"; "};";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
code = "void foo(int x, int y) {\n"
" if (y == 1) {\n"
" a = x;\n" // <- x is not 1
" }\n"
"}\n"
"\n"
"void bar() {\n"
" foo(1, 10);\n"
"}";
ASSERT_EQUALS(false, testValueOfX(code, 3U, 1));
} }
void valueFlowFunctionReturn() { void valueFlowFunctionReturn() {