Skip to content

Commit 11dd874

Browse files
author
Leonardo Alt
committed
[SMTChecker] Support tuples with multiple var decls
1 parent dea486a commit 11dd874

10 files changed

+83
-12
lines changed

Changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Language Features:
55

66
Compiler Features:
77
* SMTChecker: Support inherited state variables.
8-
* SMTChecker: Support tuple assignments and function calls with multiple return values.
8+
* SMTChecker: Support tuples and function calls with multiple return values.
99

1010

1111
Bugfixes:

libsolidity/formal/SMTChecker.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,20 +330,35 @@ bool SMTChecker::visit(ForStatement const& _node)
330330
void SMTChecker::endVisit(VariableDeclarationStatement const& _varDecl)
331331
{
332332
if (_varDecl.declarations().size() != 1)
333-
m_errorReporter.warning(
334-
_varDecl.location(),
335-
"Assertion checker does not yet support such variable declarations."
336-
);
337-
else if (knownVariable(*_varDecl.declarations()[0]))
333+
{
334+
if (auto init = _varDecl.initialValue())
335+
{
336+
auto const& symbTuple = dynamic_pointer_cast<SymbolicTupleVariable>(m_expressions[init]);
337+
/// symbTuple == nullptr if it is the return of a non-inlined function call.
338+
if (symbTuple)
339+
{
340+
auto const& components = symbTuple->components();
341+
auto const& declarations = _varDecl.declarations();
342+
for (unsigned i = 0; i < declarations.size(); ++i)
343+
{
344+
solAssert(components.at(i), "");
345+
if (declarations.at(i) && knownVariable(*declarations.at(i)))
346+
assignment(*declarations.at(i), components.at(i)->currentValue(), declarations.at(i)->location());
347+
}
348+
}
349+
}
350+
}
351+
else if (knownVariable(*_varDecl.declarations().front()))
338352
{
339353
if (_varDecl.initialValue())
340-
assignment(*_varDecl.declarations()[0], *_varDecl.initialValue(), _varDecl.location());
354+
assignment(*_varDecl.declarations().front(), *_varDecl.initialValue(), _varDecl.location());
341355
}
342356
else
343357
m_errorReporter.warning(
344358
_varDecl.location(),
345359
"Assertion checker does not yet implement such variable declarations."
346360
);
361+
347362
}
348363

349364
void SMTChecker::endVisit(Assignment const& _assignment)

test/libsolidity/smtCheckerTests/types/address_call.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ contract C
1919
// EVMVersion: >spuriousDragon
2020
// ----
2121
// Warning: (224-240): Unused local variable.
22-
// Warning: (209-256): Assertion checker does not yet support such variable declarations.
2322
// Warning: (260-275): Assertion violation happens here

test/libsolidity/smtCheckerTests/types/address_delegatecall.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ contract C
1919
// EVMVersion: >spuriousDragon
2020
// ----
2121
// Warning: (224-240): Unused local variable.
22-
// Warning: (209-264): Assertion checker does not yet support such variable declarations.
2322
// Warning: (268-283): Assertion violation happens here

test/libsolidity/smtCheckerTests/types/address_staticcall.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ contract C
1919
// EVMVersion: >spuriousDragon
2020
// ----
2121
// Warning: (224-240): Unused local variable.
22-
// Warning: (209-262): Assertion checker does not yet support such variable declarations.
2322
// Warning: (266-281): Assertion violation happens here

test/libsolidity/smtCheckerTests/types/tuple_declarations.sol

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,3 @@ contract C
99
}
1010
}
1111
// ----
12-
// Warning: (76-101): Assertion checker does not yet support such variable declarations.
13-
// Warning: (105-119): Assertion violation happens here
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pragma experimental SMTChecker;
2+
3+
contract C
4+
{
5+
function g() public pure {
6+
(uint x, ) = (2, 4);
7+
assert(x == 2);
8+
}
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pragma experimental SMTChecker;
2+
3+
contract C
4+
{
5+
function f() internal pure returns (uint, bool, uint) {
6+
uint x = 3;
7+
bool b = true;
8+
uint y = 999;
9+
return (x, b, y);
10+
}
11+
function g() public pure {
12+
(uint x, bool b, uint y) = f();
13+
assert(x == 3);
14+
assert(b);
15+
assert(y == 999);
16+
}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pragma experimental SMTChecker;
2+
3+
contract C
4+
{
5+
function f(uint x) internal pure returns (uint, bool, uint) {
6+
bool b = true;
7+
uint y = 999;
8+
return (x * 2, b, y);
9+
}
10+
function g() public pure {
11+
(uint x, bool b, uint y) = f(7);
12+
assert(x == 14);
13+
assert(b);
14+
assert(y == 999);
15+
}
16+
}
17+
// ----
18+
// Warning: (152-157): Overflow (resulting value larger than 2**256 - 1) happens here
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pragma experimental SMTChecker;
2+
3+
contract C
4+
{
5+
function f() internal pure returns (uint, bool, uint) {
6+
uint x = 3;
7+
bool b = true;
8+
uint y = 999;
9+
return (x, b, y);
10+
}
11+
function g() public pure {
12+
(, bool b,) = f();
13+
assert(!b);
14+
}
15+
}
16+
// ----
17+
// Warning: (224-234): Assertion violation happens here

0 commit comments

Comments
 (0)