Support referencing other constants in inline assembly

This commit is contained in:
Gaith Hallak
2019-12-05 13:27:17 +03:00
parent 2a1b6f55af
commit 4d90180e24
10 changed files with 119 additions and 3 deletions
+2
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
+4 -1
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)
+42
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;
}
}
}
+30
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);
}
}
+2
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)
{