mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6649 from ethereum/smt_tuple_asgn
[SMTChecker] Support tuple assignment
This commit is contained in:
commit
5bd3ed97bd
@ -6,7 +6,7 @@ Language Features:
|
||||
|
||||
Compiler Features:
|
||||
* SMTChecker: Support inherited state variables.
|
||||
* SMTChecker: Support tuple declarations.
|
||||
* SMTChecker: Support tuple assignments.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
@ -368,13 +368,29 @@ void SMTChecker::endVisit(Assignment const& _assignment)
|
||||
);
|
||||
else
|
||||
{
|
||||
auto rightHandSide = compoundOps.count(op) ?
|
||||
compoundAssignment(_assignment) :
|
||||
expr(_assignment.rightHandSide());
|
||||
defineExpr(_assignment, rightHandSide);
|
||||
vector<smt::Expression> rightArguments;
|
||||
if (_assignment.rightHandSide().annotation().type->category() == Type::Category::Tuple)
|
||||
{
|
||||
auto const& symbTuple = dynamic_pointer_cast<SymbolicTupleVariable>(m_expressions[&_assignment.rightHandSide()]);
|
||||
solAssert(symbTuple, "");
|
||||
for (auto const& component: symbTuple->components())
|
||||
{
|
||||
/// Right hand side tuple component cannot be empty.
|
||||
solAssert(component, "");
|
||||
rightArguments.push_back(component->currentValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rightHandSide = compoundOps.count(op) ?
|
||||
compoundAssignment(_assignment) :
|
||||
expr(_assignment.rightHandSide());
|
||||
defineExpr(_assignment, rightHandSide);
|
||||
rightArguments.push_back(expr(_assignment));
|
||||
}
|
||||
assignment(
|
||||
_assignment.leftHandSide(),
|
||||
expr(_assignment),
|
||||
rightArguments,
|
||||
_assignment.annotation().type,
|
||||
_assignment.location()
|
||||
);
|
||||
@ -1250,7 +1266,7 @@ smt::Expression SMTChecker::division(smt::Expression _left, smt::Expression _rig
|
||||
|
||||
void SMTChecker::assignment(
|
||||
Expression const& _left,
|
||||
smt::Expression const& _right,
|
||||
vector<smt::Expression> const& _right,
|
||||
TypePointer const& _type,
|
||||
langutil::SourceLocation const& _location
|
||||
)
|
||||
@ -1261,9 +1277,23 @@ void SMTChecker::assignment(
|
||||
"Assertion checker does not yet implement type " + _type->toString()
|
||||
);
|
||||
else if (auto varDecl = identifierToVariable(_left))
|
||||
assignment(*varDecl, _right, _location);
|
||||
{
|
||||
solAssert(_right.size() == 1, "");
|
||||
assignment(*varDecl, _right.front(), _location);
|
||||
}
|
||||
else if (dynamic_cast<IndexAccess const*>(&_left))
|
||||
arrayIndexAssignment(_left, _right);
|
||||
{
|
||||
solAssert(_right.size() == 1, "");
|
||||
arrayIndexAssignment(_left, _right.front());
|
||||
}
|
||||
else if (auto tuple = dynamic_cast<TupleExpression const*>(&_left))
|
||||
{
|
||||
auto const& components = tuple->components();
|
||||
solAssert(_right.size() == components.size(), "");
|
||||
for (unsigned i = 0; i < _right.size(); ++i)
|
||||
if (auto component = components.at(i))
|
||||
assignment(*component, {_right.at(i)}, component->annotation().type, component->location());
|
||||
}
|
||||
else
|
||||
m_errorReporter.warning(
|
||||
_location,
|
||||
|
@ -141,7 +141,7 @@ private:
|
||||
/// Will also be used for assignments of tuple components.
|
||||
void assignment(
|
||||
Expression const& _left,
|
||||
smt::Expression const& _right,
|
||||
std::vector<smt::Expression> const& _right,
|
||||
TypePointer const& _type,
|
||||
langutil::SourceLocation const& _location
|
||||
);
|
||||
|
12
test/libsolidity/smtCheckerTests/types/tuple_assignment.sol
Normal file
12
test/libsolidity/smtCheckerTests/types/tuple_assignment.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C
|
||||
{
|
||||
function g() public pure {
|
||||
uint x;
|
||||
uint y;
|
||||
(x, y) = (2, 4);
|
||||
assert(x == 2);
|
||||
assert(y == 4);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C
|
||||
{
|
||||
uint[] a;
|
||||
function g(uint x, uint y) public {
|
||||
require(x != y);
|
||||
(a[x], a[y]) = (2, 4);
|
||||
assert(a[x] == 2);
|
||||
assert(a[y] == 4);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C
|
||||
{
|
||||
uint[] a;
|
||||
function g(uint x, uint y) public {
|
||||
require(x != y);
|
||||
(, a[y]) = (2, 4);
|
||||
assert(a[x] == 2);
|
||||
assert(a[y] == 4);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (136-153): Assertion violation happens here
|
@ -0,0 +1,14 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C
|
||||
{
|
||||
function g() public pure {
|
||||
uint x;
|
||||
uint y;
|
||||
(x, ) = (2, 4);
|
||||
assert(x == 2);
|
||||
assert(y == 4);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (132-146): Assertion violation happens here
|
@ -0,0 +1,13 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C
|
||||
{
|
||||
function g() public pure {
|
||||
(uint x, uint y) = (2, 4);
|
||||
assert(x == 2);
|
||||
assert(y == 4);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (76-101): Assertion checker does not yet support such variable declarations.
|
||||
// Warning: (105-119): Assertion violation happens here
|
Loading…
Reference in New Issue
Block a user