Improve valeflow analysis with comparison operators (#1131)
* Improve valeflow analysis with comparison operators * Use simple match * Dont add 0 on comparisons * Check reverse comparisons * Use nullptr * Remove duplicate code tests
This commit is contained in:
parent
54de7b48c9
commit
b871c85b67
|
@ -2354,7 +2354,10 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
const Scope * scope = symboldatabase->functionScopes[i];
|
const Scope * scope = symboldatabase->functionScopes[i];
|
||||||
std::set<unsigned> aliased;
|
std::set<unsigned> aliased;
|
||||||
for (Token* tok = const_cast<Token*>(scope->classStart); tok != scope->classEnd; tok = tok->next()) {
|
for (Token* tok = const_cast<Token*>(scope->classStart); tok != scope->classEnd; tok = tok->next()) {
|
||||||
const Token *vartok, *numtok;
|
const Token * vartok = nullptr;
|
||||||
|
const Token * numtok = nullptr;
|
||||||
|
const Token * lowertok = nullptr;
|
||||||
|
const Token * uppertok = nullptr;
|
||||||
|
|
||||||
if (Token::Match(tok, "= & %var% ;"))
|
if (Token::Match(tok, "= & %var% ;"))
|
||||||
aliased.insert(tok->tokAt(2)->varId());
|
aliased.insert(tok->tokAt(2)->varId());
|
||||||
|
@ -2372,7 +2375,35 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
}
|
}
|
||||||
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
||||||
vartok = vartok->astOperand1();
|
vartok = vartok->astOperand1();
|
||||||
if (!vartok->isName() || !numtok->hasKnownIntValue())
|
if (!vartok->isName())
|
||||||
|
continue;
|
||||||
|
} else if (Token::simpleMatch(tok, ">")) {
|
||||||
|
if (!tok->astOperand1() || !tok->astOperand2())
|
||||||
|
continue;
|
||||||
|
if (tok->astOperand1()->hasKnownIntValue()) {
|
||||||
|
uppertok = tok->astOperand1();
|
||||||
|
vartok = tok->astOperand2();
|
||||||
|
} else {
|
||||||
|
lowertok = tok->astOperand2();
|
||||||
|
vartok = tok->astOperand1();
|
||||||
|
}
|
||||||
|
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
||||||
|
vartok = vartok->astOperand1();
|
||||||
|
if (!vartok->isName())
|
||||||
|
continue;
|
||||||
|
} else if (Token::simpleMatch(tok, "<")) {
|
||||||
|
if (!tok->astOperand1() || !tok->astOperand2())
|
||||||
|
continue;
|
||||||
|
if (tok->astOperand1()->hasKnownIntValue()) {
|
||||||
|
lowertok = tok->astOperand1();
|
||||||
|
vartok = tok->astOperand2();
|
||||||
|
} else {
|
||||||
|
uppertok = tok->astOperand2();
|
||||||
|
vartok = tok->astOperand1();
|
||||||
|
}
|
||||||
|
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
||||||
|
vartok = vartok->astOperand1();
|
||||||
|
if (!vartok->isName())
|
||||||
continue;
|
continue;
|
||||||
} else if (tok->str() == "!") {
|
} else if (tok->str() == "!") {
|
||||||
vartok = tok->astOperand1();
|
vartok = tok->astOperand1();
|
||||||
|
@ -2390,6 +2421,13 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(numtok && !numtok->hasKnownIntValue())
|
||||||
|
continue;
|
||||||
|
if(lowertok && !lowertok->hasKnownIntValue())
|
||||||
|
continue;
|
||||||
|
if(uppertok && !uppertok->hasKnownIntValue())
|
||||||
|
continue;
|
||||||
|
|
||||||
const unsigned int varid = vartok->varId();
|
const unsigned int varid = vartok->varId();
|
||||||
if (varid == 0U)
|
if (varid == 0U)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2402,7 +2440,21 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
values.push_back(ValueFlow::Value(tok, numtok ? numtok->values().front().intvalue : 0LL));
|
// TODO: We should add all known values
|
||||||
|
if(numtok) {
|
||||||
|
values.push_back(ValueFlow::Value(tok, numtok->values().front().intvalue));
|
||||||
|
} else if(lowertok) {
|
||||||
|
long long v = lowertok->values().front().intvalue;
|
||||||
|
values.push_back(ValueFlow::Value(tok, v+1));
|
||||||
|
|
||||||
|
} else if(uppertok) {
|
||||||
|
long long v = uppertok->values().front().intvalue;
|
||||||
|
values.push_back(ValueFlow::Value(tok, v-1));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
values.push_back(ValueFlow::Value(tok, 0LL));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
||||||
Token *parent = const_cast<Token*>(tok->astParent());
|
Token *parent = const_cast<Token*>(tok->astParent());
|
||||||
|
@ -2453,7 +2505,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
|
|
||||||
// based on the comparison, should we check the if or while?
|
// based on the comparison, should we check the if or while?
|
||||||
int codeblock = 0;
|
int codeblock = 0;
|
||||||
if (Token::Match(tok, "==|>=|<=|!"))
|
if (Token::Match(tok, "==|>=|<=|!|>|<"))
|
||||||
codeblock = 1;
|
codeblock = 1;
|
||||||
else if (Token::Match(tok, "%name%|!="))
|
else if (Token::Match(tok, "%name%|!="))
|
||||||
codeblock = 2;
|
codeblock = 2;
|
||||||
|
|
|
@ -1732,6 +1732,40 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" if (x > 123) {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 124));
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" if (x < 123) {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 122));
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
|
||||||
|
|
||||||
|
// ----
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" if (123 < x) {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 124));
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
|
||||||
|
|
||||||
|
code = "void f(int x) {\n"
|
||||||
|
" if (123 > x) {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 122));
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 123));
|
||||||
|
|
||||||
// in else
|
// in else
|
||||||
code = "void f(int x) {\n"
|
code = "void f(int x) {\n"
|
||||||
" if (x == 123) {}\n"
|
" if (x == 123) {}\n"
|
||||||
|
|
Loading…
Reference in New Issue