Merge pull request #9321 from ethereum/multiYulAssign

Disallow the same yul variable occurring multiple times on the LHS of an assignment.
This commit is contained in:
chriseth 2020-07-07 11:07:05 +02:00 committed by GitHub
commit d72aae20aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 0 deletions

View File

@ -23,6 +23,7 @@ Bugfixes:
* Wasm backend: Fix code generation for for-loops with pre statements. * Wasm backend: Fix code generation for for-loops with pre statements.
* Wasm backend: Properly support both ``i32.drop`` and ``i64.drop``, and remove ``drop``. * Wasm backend: Properly support both ``i32.drop`` and ``i64.drop``, and remove ``drop``.
* Yul: Fix source location of variable multi-assignment. * Yul: Fix source location of variable multi-assignment.
* Yul: Disallow the same variable to occur multiple times on the left-hand side of an assignment.
### 0.6.10 (2020-06-11) ### 0.6.10 (2020-06-11)

View File

@ -288,6 +288,8 @@ variables at the same time. For this, the number and types of the
values have to match. values have to match.
If you want to assign the values returned from a function that has If you want to assign the values returned from a function that has
multiple return parameters, you have to provide multiple variables. multiple return parameters, you have to provide multiple variables.
The same variable may not occur multiple times on the left-hand side of
an assignment, e.g. ``x, x := f()`` is invalid.
.. code-block:: yul .. code-block:: yul
@ -506,6 +508,8 @@ In variable declarations and assignments, the right-hand-side expression
variables on the left-hand-side. variables on the left-hand-side.
This is the only situation where an expression evaluating This is the only situation where an expression evaluating
to more than one value is allowed. to more than one value is allowed.
The same variable name cannot occur more than once in the left-hand-side of
an assignment or variable declaration.
Expressions that are also statements (i.e. at the block level) have to Expressions that are also statements (i.e. at the block level) have to
evaluate to zero values. evaluate to zero values.

View File

@ -167,6 +167,17 @@ void AsmAnalyzer::operator()(Assignment const& _assignment)
size_t const numVariables = _assignment.variableNames.size(); size_t const numVariables = _assignment.variableNames.size();
yulAssert(numVariables >= 1, ""); yulAssert(numVariables >= 1, "");
set<YulString> variables;
for (auto const& _variableName: _assignment.variableNames)
if (!variables.insert(_variableName.name).second)
m_errorReporter.declarationError(
9005_error,
_assignment.location,
"Variable " +
_variableName.name.str() +
" occurs multiple times on the left-hand side of the assignment."
);
vector<YulString> types = std::visit(*this, *_assignment.value); vector<YulString> types = std::visit(*this, *_assignment.value);
if (types.size() != numVariables) if (types.size() != numVariables)

View File

@ -0,0 +1,10 @@
{
function f() -> a, b {}
function g() -> a, b, c {}
let x, y
x, x := f()
y, x, y := g()
}
// ----
// DeclarationError 9005: (70-81): Variable x occurs multiple times on the left-hand side of the assignment.
// DeclarationError 9005: (84-98): Variable y occurs multiple times on the left-hand side of the assignment.

View File

@ -0,0 +1,6 @@
{
function f() -> a, b {}
let x, x := f()
}
// ----
// DeclarationError 1395: (30-45): Variable name x already taken in this scope.