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];
|
||||
std::set<unsigned> aliased;
|
||||
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% ;"))
|
||||
aliased.insert(tok->tokAt(2)->varId());
|
||||
|
@ -2372,7 +2375,35 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
|||
}
|
||||
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
||||
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;
|
||||
} else if (tok->str() == "!") {
|
||||
vartok = tok->astOperand1();
|
||||
|
@ -2390,6 +2421,13 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
|||
continue;
|
||||
}
|
||||
|
||||
if(numtok && !numtok->hasKnownIntValue())
|
||||
continue;
|
||||
if(lowertok && !lowertok->hasKnownIntValue())
|
||||
continue;
|
||||
if(uppertok && !uppertok->hasKnownIntValue())
|
||||
continue;
|
||||
|
||||
const unsigned int varid = vartok->varId();
|
||||
if (varid == 0U)
|
||||
continue;
|
||||
|
@ -2402,7 +2440,21 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
|||
continue;
|
||||
}
|
||||
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%|&&")) {
|
||||
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?
|
||||
int codeblock = 0;
|
||||
if (Token::Match(tok, "==|>=|<=|!"))
|
||||
if (Token::Match(tok, "==|>=|<=|!|>|<"))
|
||||
codeblock = 1;
|
||||
else if (Token::Match(tok, "%name%|!="))
|
||||
codeblock = 2;
|
||||
|
|
|
@ -1732,6 +1732,40 @@ private:
|
|||
"}";
|
||||
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
|
||||
code = "void f(int x) {\n"
|
||||
" if (x == 123) {}\n"
|
||||
|
|
Loading…
Reference in New Issue