Merge pull request #7874 from ghallak/assembly_constant_refs

Support referencing another constants in inline assembly
This commit is contained in:
chriseth 2019-12-05 13:52:49 +01:00 committed by GitHub
commit d2e3933dc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 119 additions and 3 deletions

View File

@ -3,6 +3,7 @@
Language Features:
* Allow to obtain the selector of public or external library functions via a member ``.selector``.
* Parser: Allow splitting string and hexadecimal string literals into multiple parts.
* Inline Assembly: Support referencing other constants.
Compiler Features:

View File

@ -41,6 +41,8 @@ set(sources
ast/ASTJsonConverter.h
ast/ASTPrinter.cpp
ast/ASTPrinter.h
ast/ASTUtils.cpp
ast/ASTUtils.h
ast/ASTVisitor.h
ast/ExperimentalFeatures.h
ast/Types.cpp

View File

@ -22,6 +22,7 @@
#include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ASTUtils.h>
#include <libsolidity/ast/TypeProvider.h>
#include <libyul/AsmAnalysis.h>
@ -641,6 +642,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
solAssert(var->type(), "Expected variable type!");
if (var->isConstant())
{
var = rootVariableDeclaration(*var);
if (!var->value())
{
m_errorReporter.typeError(_identifier.location, "Constant has no value.");
@ -651,7 +654,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
type(*var->value())->category() != Type::Category::RationalNumber
))
{
m_errorReporter.typeError(_identifier.location, "Only direct number constants are supported by inline assembly.");
m_errorReporter.typeError(_identifier.location, "Only direct number constants and references to such constants are supported by inline assembly.");
return size_t(-1);
}
else if (_context == yul::IdentifierContext::LValue)

View File

@ -0,0 +1,42 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ASTUtils.h>
namespace dev
{
namespace solidity
{
VariableDeclaration const* rootVariableDeclaration(VariableDeclaration const& _varDecl)
{
solAssert(_varDecl.isConstant(), "Constant variable expected");
VariableDeclaration const* rootDecl = &_varDecl;
Identifier const* identifier;
while ((identifier = dynamic_cast<Identifier const*>(rootDecl->value().get())))
{
auto referencedVarDecl = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration);
solAssert(referencedVarDecl && referencedVarDecl->isConstant(), "Identifier is not referencing a variable declaration");
rootDecl = referencedVarDecl;
}
return rootDecl;
}
}
}

View File

@ -0,0 +1,30 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace dev
{
namespace solidity
{
/// Find the topmost referenced variable declaration when the given variable
/// declaration value is an identifier. Works only for constant variable declarations.
VariableDeclaration const* rootVariableDeclaration(VariableDeclaration const& _varDecl);
}
}

View File

@ -21,6 +21,7 @@
*/
#include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ASTUtils.h>
#include <libsolidity/ast/TypeProvider.h>
#include <libsolidity/codegen/CompilerUtils.h>
#include <libsolidity/codegen/ContractCompiler.h>
@ -631,6 +632,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{
if (variable->isConstant())
{
variable = rootVariableDeclaration(*variable);
u256 value;
if (variable->value()->annotation().type->category() == Type::Category::RationalNumber)
{

View File

@ -0,0 +1,26 @@
contract C {
uint constant a = 2;
uint constant aa = a;
uint constant aaa = aa;
bytes2 constant b = 0xabcd;
bytes2 constant bb = b;
bytes3 constant c = "abc";
bytes3 constant cc = c;
bytes3 constant ccc = cc;
bytes3 constant cccc = ccc;
bool constant d = true;
bool constant dd = d;
address payable constant e = 0x1212121212121212121212121212121212121212;
address payable constant ee = e;
function f() public pure returns (uint w, bytes2 x, bytes3 y, bool z, address t) {
assembly {
w := aaa
x := bb
y := cccc
z := dd
t := ee
}
}
}
// ----
// f() -> 2, left(0xabcd), left(0x616263), true, 0x1212121212121212121212121212121212121212

View File

@ -7,4 +7,4 @@ contract C {
}
}
// ----
// TypeError: (115-116): Only direct number constants are supported by inline assembly.
// TypeError: (115-116): Only direct number constants and references to such constants are supported by inline assembly.

View File

@ -0,0 +1,11 @@
contract C {
bytes32 constant x = keccak256("abc");
bytes32 constant y = x;
function f() public pure returns (uint t) {
assembly {
t := y
}
}
}
// ----
// TypeError: (168-169): Only direct number constants and references to such constants are supported by inline assembly.

View File

@ -8,4 +8,3 @@ contract C {
}
}
// ----
// TypeError: (134-135): Only direct number constants are supported by inline assembly.