[SMTChecker] Support tuples with multiple var decls

This commit is contained in:
Leonardo Alt 2019-04-30 16:02:01 +02:00
parent 133fd18223
commit 3c7540ceb2
10 changed files with 83 additions and 12 deletions

View File

@ -6,7 +6,7 @@ Language Features:
Compiler Features:
* SMTChecker: Support inherited state variables.
* SMTChecker: Support tuple assignments and function calls with multiple return values.
* SMTChecker: Support tuples and function calls with multiple return values.
* SMTChecker: Support ``delete``.

View File

@ -330,20 +330,35 @@ bool SMTChecker::visit(ForStatement const& _node)
void SMTChecker::endVisit(VariableDeclarationStatement const& _varDecl)
{
if (_varDecl.declarations().size() != 1)
m_errorReporter.warning(
_varDecl.location(),
"Assertion checker does not yet support such variable declarations."
);
else if (knownVariable(*_varDecl.declarations()[0]))
{
if (auto init = _varDecl.initialValue())
{
auto symbTuple = dynamic_pointer_cast<SymbolicTupleVariable>(m_expressions[init]);
/// symbTuple == nullptr if it is the return of a non-inlined function call.
if (symbTuple)
{
auto const& components = symbTuple->components();
auto const& declarations = _varDecl.declarations();
for (unsigned i = 0; i < declarations.size(); ++i)
{
solAssert(components.at(i), "");
if (declarations.at(i) && knownVariable(*declarations.at(i)))
assignment(*declarations.at(i), components.at(i)->currentValue(), declarations.at(i)->location());
}
}
}
}
else if (knownVariable(*_varDecl.declarations().front()))
{
if (_varDecl.initialValue())
assignment(*_varDecl.declarations()[0], *_varDecl.initialValue(), _varDecl.location());
assignment(*_varDecl.declarations().front(), *_varDecl.initialValue(), _varDecl.location());
}
else
m_errorReporter.warning(
_varDecl.location(),
"Assertion checker does not yet implement such variable declarations."
);
}
void SMTChecker::endVisit(Assignment const& _assignment)

View File

@ -19,5 +19,4 @@ contract C
// EVMVersion: >spuriousDragon
// ----
// Warning: (224-240): Unused local variable.
// Warning: (209-256): Assertion checker does not yet support such variable declarations.
// Warning: (260-275): Assertion violation happens here

View File

@ -19,5 +19,4 @@ contract C
// EVMVersion: >spuriousDragon
// ----
// Warning: (224-240): Unused local variable.
// Warning: (209-264): Assertion checker does not yet support such variable declarations.
// Warning: (268-283): Assertion violation happens here

View File

@ -19,5 +19,4 @@ contract C
// EVMVersion: >spuriousDragon
// ----
// Warning: (224-240): Unused local variable.
// Warning: (209-262): Assertion checker does not yet support such variable declarations.
// Warning: (266-281): Assertion violation happens here

View File

@ -9,5 +9,3 @@ contract C
}
}
// ----
// Warning: (76-101): Assertion checker does not yet support such variable declarations.
// Warning: (105-119): Assertion violation happens here

View File

@ -0,0 +1,9 @@
pragma experimental SMTChecker;
contract C
{
function g() public pure {
(uint x, ) = (2, 4);
assert(x == 2);
}
}

View File

@ -0,0 +1,17 @@
pragma experimental SMTChecker;
contract C
{
function f() internal pure returns (uint, bool, uint) {
uint x = 3;
bool b = true;
uint y = 999;
return (x, b, y);
}
function g() public pure {
(uint x, bool b, uint y) = f();
assert(x == 3);
assert(b);
assert(y == 999);
}
}

View File

@ -0,0 +1,18 @@
pragma experimental SMTChecker;
contract C
{
function f(uint x) internal pure returns (uint, bool, uint) {
bool b = true;
uint y = 999;
return (x * 2, b, y);
}
function g() public pure {
(uint x, bool b, uint y) = f(7);
assert(x == 14);
assert(b);
assert(y == 999);
}
}
// ----
// Warning: (152-157): Overflow (resulting value larger than 2**256 - 1) happens here

View File

@ -0,0 +1,17 @@
pragma experimental SMTChecker;
contract C
{
function f() internal pure returns (uint, bool, uint) {
uint x = 3;
bool b = true;
uint y = 999;
return (x, b, y);
}
function g() public pure {
(, bool b,) = f();
assert(!b);
}
}
// ----
// Warning: (224-234): Assertion violation happens here