value flow: improved calculations that depends on variable
This commit is contained in:
parent
79a1244a54
commit
bb3cc67aaa
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue