mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
fixing try/catch encoding for BMC, refactoring
This commit is contained in:
parent
064e9a5de6
commit
dd43ce1578
@ -352,23 +352,29 @@ bool BMC::visit(TryStatement const& _tryStatement)
|
|||||||
|
|
||||||
externalCall->accept(*this);
|
externalCall->accept(*this);
|
||||||
auto callExpr = expr(*externalCall);
|
auto callExpr = expr(*externalCall);
|
||||||
smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + to_string(m_context.newUniqueId()), smtutil::SortProvider::uintSort);
|
if (_tryStatement.successClause()->parameters())
|
||||||
|
tryCatchAssignment(
|
||||||
|
_tryStatement.successClause()->parameters()->parameters(), *m_context.expression(*externalCall));
|
||||||
|
|
||||||
|
smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + to_string(m_context.newUniqueId()), smtutil::SortProvider::uintSort);
|
||||||
auto const& clauses = _tryStatement.clauses();
|
auto const& clauses = _tryStatement.clauses();
|
||||||
|
m_context.addAssertion(clauseId >= 0 && clauseId < clauses.size());
|
||||||
solAssert(clauses[0].get() == _tryStatement.successClause(), "First clause of TryStatement should be the success clause");
|
solAssert(clauses[0].get() == _tryStatement.successClause(), "First clause of TryStatement should be the success clause");
|
||||||
vector<set<VariableDeclaration const*>> touchedVars;
|
vector<set<VariableDeclaration const*>> touchedVars;
|
||||||
vector<pair<VariableIndices, smtutil::Expression>> clausesVisitResults;
|
vector<pair<VariableIndices, smtutil::Expression>> clausesVisitResults;
|
||||||
for (size_t i = 0; i < clauses.size(); ++i)
|
for (size_t i = 0; i < clauses.size(); ++i)
|
||||||
{
|
{
|
||||||
clausesVisitResults.push_back(visitBranch(clauses[i].get(), clauseId == i));
|
clausesVisitResults.push_back(visitBranch(clauses[i].get()));
|
||||||
touchedVars.push_back(touchedVariables(*clauses[i]));
|
touchedVars.push_back(touchedVariables(*clauses[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge the information from all clauses
|
// merge the information from all clauses
|
||||||
smtutil::Expression pathCondition = clausesVisitResults.front().second;
|
smtutil::Expression pathCondition = clausesVisitResults.front().second;
|
||||||
|
auto currentIndices = clausesVisitResults[0].first;
|
||||||
for (size_t i = 1; i < clauses.size(); ++i)
|
for (size_t i = 1; i < clauses.size(); ++i)
|
||||||
{
|
{
|
||||||
mergeVariables(touchedVars[i - 1] + touchedVars[i], clauseId == (i - 1), clausesVisitResults[i - 1].first, clausesVisitResults[i].first);
|
mergeVariables(touchedVars[i - 1] + touchedVars[i], clauseId == i, clausesVisitResults[i].first, currentIndices);
|
||||||
|
currentIndices = copyVariableIndices();
|
||||||
pathCondition = pathCondition || clausesVisitResults[i].second;
|
pathCondition = pathCondition || clausesVisitResults[i].second;
|
||||||
}
|
}
|
||||||
setPathCondition(pathCondition);
|
setPathCondition(pathCondition);
|
||||||
|
@ -563,25 +563,8 @@ bool CHC::visit(TryStatement const& _tryStatement)
|
|||||||
endVisit(*externalCall);
|
endVisit(*externalCall);
|
||||||
|
|
||||||
if (_tryStatement.successClause()->parameters())
|
if (_tryStatement.successClause()->parameters())
|
||||||
{
|
tryCatchAssignment(
|
||||||
auto const& params = _tryStatement.successClause()->parameters()->parameters();
|
_tryStatement.successClause()->parameters()->parameters(), *m_context.expression(*externalCall));
|
||||||
if (params.size() > 1)
|
|
||||||
{
|
|
||||||
auto const& symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(*externalCall));
|
|
||||||
solAssert(symbTuple, "");
|
|
||||||
auto const& symbComponents = symbTuple->components();
|
|
||||||
solAssert(symbComponents.size() == params.size(), "");
|
|
||||||
for (unsigned i = 0; i < symbComponents.size(); ++i)
|
|
||||||
{
|
|
||||||
auto param = params.at(i);
|
|
||||||
solAssert(param, "");
|
|
||||||
solAssert(m_context.knownVariable(*param), "");
|
|
||||||
assignment(*param, symbTuple->component(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (params.size() == 1)
|
|
||||||
assignment(*params.front(), expr(*externalCall));
|
|
||||||
}
|
|
||||||
|
|
||||||
connectBlocks(m_currentBlock, predicate(*tryAfterCallSuccessBlock));
|
connectBlocks(m_currentBlock, predicate(*tryAfterCallSuccessBlock));
|
||||||
|
|
||||||
|
@ -2107,6 +2107,26 @@ smtutil::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment
|
|||||||
return values.first;
|
return values.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMTEncoder::tryCatchAssignment(vector<shared_ptr<VariableDeclaration>> const& _variables, smt::SymbolicVariable const& _rhs)
|
||||||
|
{
|
||||||
|
if (_variables.size() > 1)
|
||||||
|
{
|
||||||
|
auto const* symbTuple = dynamic_cast<smt::SymbolicTupleVariable const*>(&_rhs);
|
||||||
|
solAssert(symbTuple, "");
|
||||||
|
auto const& symbComponents = symbTuple->components();
|
||||||
|
solAssert(symbComponents.size() == _variables.size(), "");
|
||||||
|
for (unsigned i = 0; i < symbComponents.size(); ++i)
|
||||||
|
{
|
||||||
|
auto param = _variables.at(i);
|
||||||
|
solAssert(param, "");
|
||||||
|
solAssert(m_context.knownVariable(*param), "");
|
||||||
|
assignment(*param, symbTuple->component(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_variables.size() == 1)
|
||||||
|
assignment(*_variables.front(), _rhs.currentValue());
|
||||||
|
}
|
||||||
|
|
||||||
void SMTEncoder::assignment(VariableDeclaration const& _variable, Expression const& _value)
|
void SMTEncoder::assignment(VariableDeclaration const& _variable, Expression const& _value)
|
||||||
{
|
{
|
||||||
// In general, at this point, the SMT sorts of _variable and _value are the same,
|
// In general, at this point, the SMT sorts of _variable and _value are the same,
|
||||||
|
@ -238,6 +238,8 @@ protected:
|
|||||||
void tupleAssignment(Expression const& _left, Expression const& _right);
|
void tupleAssignment(Expression const& _left, Expression const& _right);
|
||||||
/// Computes the right hand side of a compound assignment.
|
/// Computes the right hand side of a compound assignment.
|
||||||
smtutil::Expression compoundAssignment(Assignment const& _assignment);
|
smtutil::Expression compoundAssignment(Assignment const& _assignment);
|
||||||
|
/// Handles assignment of the result of external call in try statement to the parameters of success clause
|
||||||
|
void tryCatchAssignment(std::vector<std::shared_ptr<VariableDeclaration>> const& _variables, smt::SymbolicVariable const& rhs);
|
||||||
|
|
||||||
/// Maps a variable to an SSA index.
|
/// Maps a variable to an SSA index.
|
||||||
using VariableIndices = std::unordered_map<VariableDeclaration const*, int>;
|
using VariableIndices = std::unordered_map<VariableDeclaration const*, int>;
|
||||||
|
Loading…
Reference in New Issue
Block a user