Refactor: ConditionHandler cleanup (#3394)
This commit is contained in:
parent
e626e3065d
commit
69eaa9dfd9
|
@ -4526,29 +4526,22 @@ struct ConditionHandler {
|
||||||
|
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const = 0;
|
virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const = 0;
|
||||||
|
|
||||||
void traverseCondition(
|
void traverseCondition(TokenList* tokenlist,
|
||||||
TokenList* tokenlist,
|
|
||||||
SymbolDatabase* symboldatabase,
|
SymbolDatabase* symboldatabase,
|
||||||
ErrorLogger* errorLogger,
|
const std::function<void(const Condition& cond, Token* tok, const Scope* scope)>& f) const
|
||||||
const Settings* settings,
|
{
|
||||||
const std::function<
|
|
||||||
void(const Condition& cond, Token* tok, const Scope* scope, const std::vector<const Variable*>& vars)>& f) const {
|
|
||||||
for (const Scope *scope : symboldatabase->functionScopes) {
|
for (const Scope *scope : symboldatabase->functionScopes) {
|
||||||
std::set<nonneg int> aliased;
|
|
||||||
for (Token *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (Token *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "if|while|for ("))
|
if (Token::Match(tok, "if|while|for ("))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Token::Match(tok, "= & %var% ;"))
|
|
||||||
aliased.insert(tok->tokAt(2)->varId());
|
|
||||||
const Token* top = tok->astTop();
|
const Token* top = tok->astTop();
|
||||||
if (!top)
|
if (!top)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?"))
|
if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?"))
|
||||||
continue;
|
continue;
|
||||||
// *INDENT-OFF*
|
for (const Condition& cond : parse(tok, tokenlist->getSettings())) {
|
||||||
for (const Condition& cond : parse(tok, settings)) {
|
|
||||||
if (!cond.vartok)
|
if (!cond.vartok)
|
||||||
continue;
|
continue;
|
||||||
if (cond.vartok->exprId() == 0)
|
if (cond.vartok->exprId() == 0)
|
||||||
|
@ -4557,28 +4550,11 @@ struct ConditionHandler {
|
||||||
continue;
|
continue;
|
||||||
if (cond.true_values.empty() || cond.false_values.empty())
|
if (cond.true_values.empty() || cond.false_values.empty())
|
||||||
continue;
|
continue;
|
||||||
if (!isConstExpression(cond.vartok, settings->library, true, tokenlist->isCPP()))
|
if (!isConstExpression(cond.vartok, tokenlist->getSettings()->library, true, tokenlist->isCPP()))
|
||||||
continue;
|
|
||||||
std::vector<const Variable*> vars =
|
|
||||||
getExprVariables(cond.vartok, tokenlist, symboldatabase, settings);
|
|
||||||
if (std::any_of(vars.begin(), vars.end(), [](const Variable* var) { return !var; }))
|
|
||||||
continue;
|
|
||||||
if (!vars.empty() && (vars.front())) {
|
|
||||||
if (std::any_of(vars.begin(), vars.end(), [&](const Variable* var) {
|
|
||||||
return var && aliased.find(var->declarationId()) != aliased.end();
|
|
||||||
})) {
|
|
||||||
if (settings->debugwarnings)
|
|
||||||
bailout(tokenlist,
|
|
||||||
errorLogger,
|
|
||||||
cond.vartok,
|
|
||||||
"variable is aliased so we just skip all valueflow after condition");
|
|
||||||
continue;
|
continue;
|
||||||
|
f(cond, tok, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f(cond, tok, scope, vars);
|
|
||||||
}
|
|
||||||
// *INDENT-ON*
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4586,12 +4562,7 @@ struct ConditionHandler {
|
||||||
SymbolDatabase* symboldatabase,
|
SymbolDatabase* symboldatabase,
|
||||||
ErrorLogger* errorLogger,
|
ErrorLogger* errorLogger,
|
||||||
const Settings* settings) const {
|
const Settings* settings) const {
|
||||||
traverseCondition(
|
traverseCondition(tokenlist, symboldatabase, [&](const Condition& cond, Token* tok, const Scope*) {
|
||||||
tokenlist,
|
|
||||||
symboldatabase,
|
|
||||||
errorLogger,
|
|
||||||
settings,
|
|
||||||
[&](const Condition& cond, Token* tok, const Scope*, const std::vector<const Variable*>&) {
|
|
||||||
if (cond.vartok->exprId() == 0)
|
if (cond.vartok->exprId() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -4699,12 +4670,7 @@ struct ConditionHandler {
|
||||||
SymbolDatabase* symboldatabase,
|
SymbolDatabase* symboldatabase,
|
||||||
ErrorLogger* errorLogger,
|
ErrorLogger* errorLogger,
|
||||||
const Settings* settings) const {
|
const Settings* settings) const {
|
||||||
traverseCondition(
|
traverseCondition(tokenlist, symboldatabase, [&](const Condition& cond, Token* tok, const Scope* scope) {
|
||||||
tokenlist,
|
|
||||||
symboldatabase,
|
|
||||||
errorLogger,
|
|
||||||
settings,
|
|
||||||
[&](const Condition& cond, Token* tok, const Scope* scope, const std::vector<const Variable*>& vars) {
|
|
||||||
if (Token::simpleMatch(tok->astParent(), "?"))
|
if (Token::simpleMatch(tok->astParent(), "?"))
|
||||||
return;
|
return;
|
||||||
const Token* top = tok->astTop();
|
const Token* top = tok->astTop();
|
||||||
|
@ -4750,19 +4716,19 @@ struct ConditionHandler {
|
||||||
values = elseValues;
|
values = elseValues;
|
||||||
if (Token::Match(tok, "==|!=") || (tok == cond.vartok && astIsBool(tok)))
|
if (Token::Match(tok, "==|!=") || (tok == cond.vartok && astIsBool(tok)))
|
||||||
changePossibleToKnown(values);
|
changePossibleToKnown(values);
|
||||||
// *INDENT-OFF*
|
|
||||||
if (astIsFloat(cond.vartok, false) ||
|
if (astIsFloat(cond.vartok, false) ||
|
||||||
(!cond.vartok->valueType() &&
|
(!cond.vartok->valueType() &&
|
||||||
std::all_of(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
std::all_of(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
||||||
return v.isIntValue() || v.isFloatValue();
|
return v.isIntValue() || v.isFloatValue();
|
||||||
})))
|
})))
|
||||||
values.remove_if([&](const ValueFlow::Value& v) { return v.isImpossible(); });
|
values.remove_if([&](const ValueFlow::Value& v) {
|
||||||
|
return v.isImpossible();
|
||||||
|
});
|
||||||
for (Token* start:nextExprs) {
|
for (Token* start:nextExprs) {
|
||||||
Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, settings);
|
Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, settings);
|
||||||
if (r.terminate != Analyzer::Terminate::None)
|
if (r.terminate != Analyzer::Terminate::None)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// *INDENT-ON*
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4792,14 +4758,6 @@ struct ConditionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
|
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
|
||||||
// does condition reassign variable?
|
|
||||||
if (tok != top->astOperand2() && Token::Match(top->astOperand2(), "%oror%|&&") &&
|
|
||||||
isVariablesChanged(top, top->link(), 0, vars, settings, tokenlist->isCPP())) {
|
|
||||||
if (settings->debugwarnings)
|
|
||||||
bailout(tokenlist, errorLogger, tok, "assignment in condition");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if astParent is "!" we need to invert codeblock
|
// if astParent is "!" we need to invert codeblock
|
||||||
{
|
{
|
||||||
const Token* tok2 = tok;
|
const Token* tok2 = tok;
|
||||||
|
@ -7178,10 +7136,9 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
||||||
valueFlowSymbolicInfer(tokenlist, symboldatabase);
|
valueFlowSymbolicInfer(tokenlist, symboldatabase);
|
||||||
valueFlowArrayBool(tokenlist);
|
valueFlowArrayBool(tokenlist);
|
||||||
valueFlowRightShift(tokenlist, settings);
|
valueFlowRightShift(tokenlist, settings);
|
||||||
valueFlowAfterMove(tokenlist, symboldatabase, settings);
|
valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowInferCondition(tokenlist, settings);
|
valueFlowInferCondition(tokenlist, settings);
|
||||||
valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings);
|
|
||||||
valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
|
@ -7191,6 +7148,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
||||||
valueFlowUninit(tokenlist, symboldatabase, settings);
|
valueFlowUninit(tokenlist, symboldatabase, settings);
|
||||||
valueFlowUninitPointerAliasDeref(tokenlist);
|
valueFlowUninitPointerAliasDeref(tokenlist);
|
||||||
if (tokenlist->isCPP()) {
|
if (tokenlist->isCPP()) {
|
||||||
|
valueFlowAfterMove(tokenlist, symboldatabase, settings);
|
||||||
valueFlowSmartPointer(tokenlist, errorLogger, settings);
|
valueFlowSmartPointer(tokenlist, errorLogger, settings);
|
||||||
valueFlowIterators(tokenlist, settings);
|
valueFlowIterators(tokenlist, settings);
|
||||||
valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
|
valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
|
||||||
|
|
|
@ -1171,7 +1171,7 @@ private:
|
||||||
" p = q;\n"
|
" p = q;\n"
|
||||||
" if (p || *p) { }\n"
|
" if (p || *p) { }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:5]: (warning) Possible null pointer dereference: p\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ticket #8831 - FP triggered by if/return/else sequence
|
// ticket #8831 - FP triggered by if/return/else sequence
|
||||||
|
|
Loading…
Reference in New Issue