value flow: improved calculations that depends on variable

This commit is contained in:
Daniel Marjamäki 2014-01-20 21:45:30 +01:00
parent 79a1244a54
commit bb3cc67aaa
3 changed files with 29 additions and 9 deletions

View File

@ -170,11 +170,13 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
std::list<ValueFlow::Value>::const_iterator value1, value2; std::list<ValueFlow::Value>::const_iterator value1, value2;
for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) { for (value1 = parent->astOperand1()->values.begin(); value1 != parent->astOperand1()->values.end(); ++value1) {
for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) { for (value2 = parent->astOperand2()->values.begin(); value2 != parent->astOperand2()->values.end(); ++value2) {
if (value1->varId == 0U || value2->varId == 0U || value1->varId == value2->varId) { if (value1->varId == 0U || value2->varId == 0U ||
(value1->varId == value2->varId && value1->varvalue == value2->varvalue)) {
ValueFlow::Value result(0); ValueFlow::Value result(0);
result.condition = value1->condition ? value1->condition : value2->condition; result.condition = value1->condition ? value1->condition : value2->condition;
result.inconclusive = value1->inconclusive | value2->inconclusive; result.inconclusive = value1->inconclusive | value2->inconclusive;
result.varId = (value1->varId != 0U) ? value1->varId : value2->varId; result.varId = (value1->varId != 0U) ? value1->varId : value2->varId;
result.varvalue = (result.varId == value1->varId) ? value1->intvalue : value2->intvalue;
switch (parent->str()[0]) { switch (parent->str()[0]) {
case '+': case '+':
result.intvalue = value1->intvalue + value2->intvalue; result.intvalue = value1->intvalue + value2->intvalue;

View File

@ -29,9 +29,9 @@ class Settings;
namespace ValueFlow { namespace ValueFlow {
class Value { class Value {
public: public:
Value() : condition(0), intvalue(0), inconclusive(false), varId(0U) {} Value() : condition(0), intvalue(0), inconclusive(false), varId(0U), varvalue(0) {}
Value(long long val) : condition(0), intvalue(val), inconclusive(false), varId(0U) {} Value(long long val) : condition(0), intvalue(val), inconclusive(false), varId(0U), varvalue(val) {}
Value(const Token *c, long long val) : condition(c), intvalue(val), inconclusive(false), varId(0U) {} Value(const Token *c, long long val) : condition(c), intvalue(val), inconclusive(false), varId(0U), varvalue(val) {}
/** Condition that this value depends on (TODO: replace with a 'callstack') */ /** Condition that this value depends on (TODO: replace with a 'callstack') */
const Token *condition; const Token *condition;
@ -44,6 +44,9 @@ namespace ValueFlow {
/** For calculated values - varId that calculated value depends on */ /** For calculated values - varId that calculated value depends on */
unsigned int varId; unsigned int varId;
/** For calculated values - variable value that calculated value depends on */
long long varvalue;
}; };
void setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings); void setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings);

View File

@ -95,14 +95,19 @@ private:
tokenizer.tokenize(istr, "test.cpp"); tokenizer.tokenize(istr, "test.cpp");
} }
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) { std::list<ValueFlow::Value> tokenValues(const char code[], const char tokstr[]) {
const Settings settings; const Settings settings;
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
std::istringstream istr(code); std::istringstream istr(code);
errout.str(""); errout.str("");
tokenizer.tokenize(istr, "test.cpp"); tokenizer.tokenize(istr, "test.cpp");
const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr); const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr);
return (tok && tok->values.size()==1U) ? tok->values.front() : ValueFlow::Value(); return tok ? tok->values : std::list<ValueFlow::Value>();
}
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
return values.size() == 1U ? values.front() : ValueFlow::Value();
} }
void valueFlowNumber() { void valueFlowNumber() {
@ -128,6 +133,12 @@ private:
"}"; "}";
ASSERT_EQUALS(579, valueOfTok(code, "+").intvalue); ASSERT_EQUALS(579, valueOfTok(code, "+").intvalue);
code = "void f(int x, int y) {\n"
" a = x+y;\n"
" if (x==123 || y==456) {}"
"}";
ASSERT_EQUALS(0, valueOfTok(code, "+").intvalue);
code = "void f(int x) {\n" code = "void f(int x) {\n"
" a = x+x;\n" " a = x+x;\n"
" if (x==123) {}" " if (x==123) {}"
@ -135,10 +146,14 @@ private:
ASSERT_EQUALS(246, valueOfTok(code, "+").intvalue); ASSERT_EQUALS(246, valueOfTok(code, "+").intvalue);
code = "void f(int x, int y) {\n" code = "void f(int x, int y) {\n"
" a = x+y;\n" " a = x*x;\n"
" if (x==123 || y==456) {}" " if (x==2) {}\n"
" if (x==4) {}\n"
"}"; "}";
ASSERT_EQUALS(0, valueOfTok(code, "+").intvalue); std::list<ValueFlow::Value> values = tokenValues(code,"*");
ASSERT_EQUALS(2U, values.size());
ASSERT_EQUALS(4, values.front().intvalue);
ASSERT_EQUALS(16, values.back().intvalue);
} }
void valueFlowBeforeCondition() { void valueFlowBeforeCondition() {