ExprEngine: Better handling of conditions
This commit is contained in:
parent
38dec6a9ac
commit
6c59957109
|
@ -115,27 +115,64 @@ namespace {
|
||||||
const Settings * const settings;
|
const Settings * const settings;
|
||||||
const std::vector<ExprEngine::Callback> &callbacks;
|
const std::vector<ExprEngine::Callback> &callbacks;
|
||||||
|
|
||||||
Data getData(const Token *cond, bool trueData) {
|
std::vector<Data> getData(const Token *cond, bool trueData) {
|
||||||
Data ret(symbolValueIndex, tokenizer, settings, callbacks, mTrackExecution);
|
std::vector<Data> ret;
|
||||||
|
ret.push_back(Data(symbolValueIndex, tokenizer, settings, callbacks, mTrackExecution));
|
||||||
for (Memory::const_iterator mem = memory.cbegin(); mem != memory.cend(); ++mem) {
|
for (Memory::const_iterator mem = memory.cbegin(); mem != memory.cend(); ++mem) {
|
||||||
ret.memory[mem->first] = mem->second;
|
for (Data &data : ret)
|
||||||
|
data.memory[mem->first] = mem->second;
|
||||||
|
|
||||||
if (cond->isComparisonOp() && cond->astOperand1()->varId() == mem->first && cond->astOperand2()->isNumber()) {
|
if (cond->isComparisonOp() && cond->astOperand1()->varId() == mem->first && cond->astOperand2()->isNumber()) {
|
||||||
const int128_t rhsValue = MathLib::toLongNumber(cond->astOperand2()->str());
|
const int128_t rhsValue = MathLib::toLongNumber(cond->astOperand2()->str());
|
||||||
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(mem->second)) {
|
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(mem->second)) {
|
||||||
if (cond->str() == ">") {
|
if (cond->str() == ">") {
|
||||||
if (trueData && intRange->minValue <= rhsValue) {
|
if (trueData) {
|
||||||
|
if (intRange->maxValue <= rhsValue)
|
||||||
|
return std::vector<Data>();
|
||||||
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), rhsValue + 1, intRange->maxValue);
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), rhsValue + 1, intRange->maxValue);
|
||||||
ret.trackAssignment(cond, val);
|
trackAssignment(cond, val);
|
||||||
ret.memory[mem->first] = val;
|
ret[0].memory[mem->first] = val;
|
||||||
} else if (!trueData && intRange->maxValue > rhsValue) {
|
} else { /* if (!trueData) */
|
||||||
|
if (intRange->maxValue <= rhsValue)
|
||||||
|
return std::vector<Data>();
|
||||||
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), intRange->minValue, rhsValue);
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), intRange->minValue, rhsValue);
|
||||||
ret.trackAssignment(cond, val);
|
trackAssignment(cond, val);
|
||||||
ret.memory[mem->first] = val;
|
ret[0].memory[mem->first] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (cond->varId() == mem->first) {
|
||||||
|
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(mem->second)) {
|
||||||
|
if (trueData) {
|
||||||
|
if (intRange->minValue == 0 && intRange->maxValue == 0)
|
||||||
|
return std::vector<Data>();
|
||||||
|
if (intRange->minValue < 0) {
|
||||||
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), intRange->minValue, -1);
|
||||||
|
trackAssignment(cond, val);
|
||||||
|
ret[0].memory[mem->first] = val;
|
||||||
|
}
|
||||||
|
if (intRange->maxValue > 0) {
|
||||||
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), 1, intRange->maxValue);
|
||||||
|
trackAssignment(cond, val);
|
||||||
|
if (intRange->minValue < 0) {
|
||||||
|
// create additional intrange..
|
||||||
|
ret.push_back(Data(symbolValueIndex, tokenizer, settings, callbacks, mTrackExecution));
|
||||||
|
ret.back().memory = ret[0].memory;
|
||||||
|
}
|
||||||
|
ret[0].memory[mem->first] = val;
|
||||||
|
}
|
||||||
|
} else { /* if (!trueData) */
|
||||||
|
if (intRange->maxValue < 0 || intRange->minValue > 0)
|
||||||
|
return std::vector<Data>();
|
||||||
|
|
||||||
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), 0, 0);
|
||||||
|
trackAssignment(cond, val);
|
||||||
|
ret[0].memory[mem->first] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +216,9 @@ namespace {
|
||||||
for (auto mem : memory) {
|
for (auto mem : memory) {
|
||||||
ExprEngine::ValuePtr value = mem.second;
|
ExprEngine::ValuePtr value = mem.second;
|
||||||
s << " " << symbolDatabase->getVariableFromVarId(mem.first)->name() << "=";
|
s << " " << symbolDatabase->getVariableFromVarId(mem.first)->name() << "=";
|
||||||
if (value->name[0] == '$')
|
if (!value)
|
||||||
|
s << "(null)";
|
||||||
|
else if (value->name[0] == '$')
|
||||||
s << "(" << value->name << "," << value->getRange() << ")";
|
s << "(" << value->name << "," << value->getRange() << ")";
|
||||||
else
|
else
|
||||||
s << value->name;
|
s << value->name;
|
||||||
|
@ -522,16 +561,19 @@ static void execute(const Token *start, const Token *end, Data &data)
|
||||||
if (Token::simpleMatch(tok, "if (")) {
|
if (Token::simpleMatch(tok, "if (")) {
|
||||||
const Token *cond = tok->next()->astOperand2();
|
const Token *cond = tok->next()->astOperand2();
|
||||||
/*const ExprEngine::ValuePtr condValue =*/ executeExpression(cond,data);
|
/*const ExprEngine::ValuePtr condValue =*/ executeExpression(cond,data);
|
||||||
Data trueData = data.getData(cond, true);
|
std::vector<Data> trueData = data.getData(cond, true);
|
||||||
Data falseData = data.getData(cond, false);
|
std::vector<Data> falseData = data.getData(cond, false);
|
||||||
const Token *thenStart = tok->linkAt(1)->next();
|
const Token *thenStart = tok->linkAt(1)->next();
|
||||||
const Token *thenEnd = thenStart->link();
|
const Token *thenEnd = thenStart->link();
|
||||||
execute(thenStart->next(), end, trueData);
|
for (Data &d : trueData)
|
||||||
|
execute(thenStart->next(), end, d);
|
||||||
if (Token::simpleMatch(thenEnd, "} else {")) {
|
if (Token::simpleMatch(thenEnd, "} else {")) {
|
||||||
const Token *elseStart = thenEnd->tokAt(2);
|
const Token *elseStart = thenEnd->tokAt(2);
|
||||||
execute(elseStart->next(), end, falseData);
|
for (Data &d : falseData)
|
||||||
|
execute(elseStart->next(), end, d);
|
||||||
} else {
|
} else {
|
||||||
execute(thenEnd->next(), end, falseData);
|
for (Data &d : falseData)
|
||||||
|
execute(thenEnd->next(), end, d);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -553,6 +595,8 @@ static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data)
|
||||||
|
|
||||||
static ExprEngine::ValuePtr createStructVal(const Scope *structScope, Data &data)
|
static ExprEngine::ValuePtr createStructVal(const Scope *structScope, Data &data)
|
||||||
{
|
{
|
||||||
|
if (!structScope)
|
||||||
|
return ExprEngine::ValuePtr();
|
||||||
std::shared_ptr<ExprEngine::StructValue> structValue = std::make_shared<ExprEngine::StructValue>(data.getNewSymbolName());
|
std::shared_ptr<ExprEngine::StructValue> structValue = std::make_shared<ExprEngine::StructValue>(data.getNewSymbolName());
|
||||||
for (const Variable &member : structScope->varlist) {
|
for (const Variable &member : structScope->varlist) {
|
||||||
ExprEngine::ValuePtr memberValue = createVariableValue(member, data);
|
ExprEngine::ValuePtr memberValue = createVariableValue(member, data);
|
||||||
|
|
|
@ -43,6 +43,8 @@ private:
|
||||||
TEST_CASE(if1);
|
TEST_CASE(if1);
|
||||||
TEST_CASE(if2);
|
TEST_CASE(if2);
|
||||||
TEST_CASE(if3);
|
TEST_CASE(if3);
|
||||||
|
TEST_CASE(if4);
|
||||||
|
TEST_CASE(if5);
|
||||||
|
|
||||||
TEST_CASE(ifelse1);
|
TEST_CASE(ifelse1);
|
||||||
|
|
||||||
|
@ -119,6 +121,14 @@ private:
|
||||||
ASSERT_EQUALS("[1:1][-2147483648:2147483647][-2147483648:2147483647]", getRange("void f() { int x; if (a) { if (b) x=1; } a=x; }", "a=x"));
|
ASSERT_EQUALS("[1:1][-2147483648:2147483647][-2147483648:2147483647]", getRange("void f() { int x; if (a) { if (b) x=1; } a=x; }", "a=x"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if4() {
|
||||||
|
ASSERT_EQUALS("[1:2147483647][-2147483648:-1]", getRange("int x; void f() { if (x) { a=x; }}", "a=x"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void if5() {
|
||||||
|
ASSERT_EQUALS("[0:0]", getRange("int x; void f() { if (x) {} else { a=x; }}", "a=x"));
|
||||||
|
}
|
||||||
|
|
||||||
void ifelse1() {
|
void ifelse1() {
|
||||||
ASSERT_EQUALS("[-32767:6]", getRange("inf f(short x) { if (x > 5) ; else a = x + 1; }", "x+1"));
|
ASSERT_EQUALS("[-32767:6]", getRange("inf f(short x) { if (x > 5) ; else a = x + 1; }", "x+1"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue