ExpressionStatements can only be FunctionCalls.

This commit is contained in:
chriseth 2020-11-10 12:00:58 +01:00
parent 41f5036507
commit 9c61060eff
15 changed files with 42 additions and 67 deletions

View File

@ -49,7 +49,7 @@ public:
void operator()(yul::Identifier const&) {}
void operator()(yul::ExpressionStatement const& _expr)
{
std::visit(*this, _expr.expression);
(*this)(_expr.expression);
}
void operator()(yul::Assignment const& _assignment)
{

View File

@ -163,7 +163,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
void AsmAnalyzer::operator()(ExpressionStatement const& _statement)
{
auto watcher = m_errorReporter.errorWatcher();
vector<YulString> types = std::visit(*this, _statement.expression);
vector<YulString> types = (*this)(_statement.expression);
if (watcher.ok() && !types.empty())
m_errorReporter.typeError(
3083_error,

View File

@ -52,7 +52,7 @@ struct Identifier { langutil::SourceLocation location; YulString name; };
struct Assignment { langutil::SourceLocation location; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector<Expression> arguments; };
/// Statement that contains only a single expression
struct ExpressionStatement { langutil::SourceLocation location; Expression expression; };
struct ExpressionStatement { langutil::SourceLocation location; FunctionCall expression; };
/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::unique_ptr<Expression> value; };
/// Block that creates a scope (frees declared stack variables)

View File

@ -99,7 +99,7 @@ Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const
Json::Value AsmJsonConverter::operator()(ExpressionStatement const& _node) const
{
Json::Value ret = createAstNode(_node.location, "YulExpressionStatement");
ret["expression"] = std::visit(*this, _node.expression);
ret["expression"] = (*this)(_node.expression);
return ret;
}

View File

@ -233,7 +233,7 @@ FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node)
ExpressionStatement AsmJsonImporter::createExpressionStatement(Json::Value const& _node)
{
auto statement = createAsmNode<ExpressionStatement>(_node);
statement.expression = createExpression(member(_node, "expression"));
statement.expression = createFunctionCall(member(_node, "expression"));
return statement;
}

View File

@ -147,8 +147,8 @@ Statement Parser::parseStatement()
{
case Token::LParen:
{
Expression expr = parseCall(std::move(elementary));
return ExpressionStatement{locationOf(expr), expr};
FunctionCall expr = parseCall(std::move(elementary));
return ExpressionStatement{expr.location, std::move(expr)};
}
case Token::Comma:
case Token::AssemblyAssign:
@ -198,21 +198,8 @@ Statement Parser::parseStatement()
break;
}
if (holds_alternative<Identifier>(elementary))
{
Identifier& identifier = std::get<Identifier>(elementary);
return ExpressionStatement{identifier.location, { move(identifier) }};
}
else if (holds_alternative<Literal>(elementary))
{
Expression expr = std::get<Literal>(elementary);
return ExpressionStatement{locationOf(expr), expr};
}
else
{
yulAssert(false, "Invalid elementary operation.");
return {};
}
yulAssert(false, "Invalid elementary operation.");
return {};
}
Case Parser::parseCase()
@ -417,7 +404,7 @@ FunctionDefinition Parser::parseFunctionDefinition()
return funDef;
}
Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp)
FunctionCall Parser::parseCall(Parser::ElementaryOperation&& _initialOp)
{
RecursionGuard recursionGuard(*this);

View File

@ -87,7 +87,7 @@ protected:
ElementaryOperation parseElementaryOperation();
VariableDeclaration parseVariableDeclaration();
FunctionDefinition parseFunctionDefinition();
Expression parseCall(ElementaryOperation&& _initialOp);
FunctionCall parseCall(ElementaryOperation&& _initialOp);
TypedName parseTypedName();
YulString expectAsmIdentifier();

View File

@ -67,7 +67,7 @@ string AsmPrinter::operator()(Identifier const& _identifier) const
string AsmPrinter::operator()(ExpressionStatement const& _statement) const
{
return std::visit(*this, _statement.expression);
return (*this)(_statement.expression);
}
string AsmPrinter::operator()(Assignment const& _assignment) const

View File

@ -47,7 +47,7 @@ ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter):
bool ScopeFiller::operator()(ExpressionStatement const& _expr)
{
return std::visit(*this, _expr.expression);
return (*this)(_expr.expression);
}
bool ScopeFiller::operator()(VariableDeclaration const& _varDecl)

View File

@ -254,7 +254,7 @@ void CodeTransform::operator()(Assignment const& _assignment)
void CodeTransform::operator()(ExpressionStatement const& _statement)
{
m_assembly.setSourceLocation(_statement.location);
std::visit(*this, _statement.expression);
(*this)(_statement.expression);
}
void CodeTransform::operator()(FunctionCall const& _call)

View File

@ -34,7 +34,8 @@ using namespace solidity::util;
Statement ASTCopier::operator()(ExpressionStatement const& _statement)
{
return ExpressionStatement{ _statement.location, translate(_statement.expression) };
Expression expr = (*this)(_statement.expression);
return ExpressionStatement{ _statement.location, std::get<FunctionCall>(std::move(expr)) };
}
Statement ASTCopier::operator()(VariableDeclaration const& _varDecl)

View File

@ -107,7 +107,7 @@ void ASTModifier::operator()(FunctionCall& _funCall)
void ASTModifier::operator()(ExpressionStatement& _statement)
{
visit(_statement.expression);
(*this)(_statement.expression);
}
void ASTModifier::operator()(Assignment& _assignment)

View File

@ -397,22 +397,19 @@ std::optional<pair<YulString, YulString>> DataFlowAnalyzer::isSimpleStore(
_store == evmasm::Instruction::SSTORE,
""
);
if (holds_alternative<FunctionCall>(_statement.expression))
{
FunctionCall const& funCall = std::get<FunctionCall>(_statement.expression);
if (EVMDialect const* dialect = dynamic_cast<EVMDialect const*>(&m_dialect))
if (auto const* builtin = dialect->builtin(funCall.functionName.name))
if (builtin->instruction == _store)
if (
holds_alternative<Identifier>(funCall.arguments.at(0)) &&
holds_alternative<Identifier>(funCall.arguments.at(1))
)
{
YulString key = std::get<Identifier>(funCall.arguments.at(0)).name;
YulString value = std::get<Identifier>(funCall.arguments.at(1)).name;
return make_pair(key, value);
}
}
FunctionCall const& funCall = _statement.expression;
if (EVMDialect const* dialect = dynamic_cast<EVMDialect const*>(&m_dialect))
if (auto const* builtin = dialect->builtin(funCall.functionName.name))
if (builtin->instruction == _store)
if (
holds_alternative<Identifier>(funCall.arguments.at(0)) &&
holds_alternative<Identifier>(funCall.arguments.at(1))
)
{
YulString key = std::get<Identifier>(funCall.arguments.at(0)).name;
YulString value = std::get<Identifier>(funCall.arguments.at(1)).name;
return make_pair(key, value);
}
return {};
}

View File

@ -233,24 +233,15 @@ void InlineModifier::operator()(Block& _block)
std::optional<vector<Statement>> InlineModifier::tryInlineStatement(Statement& _statement)
{
// Only inline for expression statements, assignments and variable declarations.
Expression* e = std::visit(util::GenericVisitor{
util::VisitorFallback<Expression*>{},
[](ExpressionStatement& _s) { return &_s.expression; },
[](Assignment& _s) { return _s.value.get(); },
[](VariableDeclaration& _s) { return _s.value.get(); }
// Only inline direct function cfor expression statements, assignments and variable declarations.
FunctionCall* funCall = std::visit(util::GenericVisitor{
util::VisitorFallback<FunctionCall*>{},
[](ExpressionStatement& _s) { return &_s.expression; }
}, _statement);
if (e)
{
// Only inline direct function calls.
FunctionCall* funCall = std::visit(util::GenericVisitor{
util::VisitorFallback<FunctionCall*>{},
[](FunctionCall& _e) { return &_e; }
}, *e);
if (funCall && m_driver.shallInline(*funCall, m_currentFunction))
return performInline(_statement, *funCall);
}
return {};
if (funCall && m_driver.shallInline(*funCall, m_currentFunction))
return performInline(_statement, *funCall);
else
return {};
}
vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall)

View File

@ -194,10 +194,9 @@ TerminationFinder::ControlFlow TerminationFinder::controlFlowKind(Statement cons
bool TerminationFinder::isTerminatingBuiltin(ExpressionStatement const& _exprStmnt)
{
if (holds_alternative<FunctionCall>(_exprStmnt.expression))
if (auto const* dialect = dynamic_cast<EVMDialect const*>(&m_dialect))
if (auto const* builtin = dialect->builtin(std::get<FunctionCall>(_exprStmnt.expression).functionName.name))
if (builtin->instruction)
return evmasm::SemanticInformation::terminatesControlFlow(*builtin->instruction);
if (auto const* dialect = dynamic_cast<EVMDialect const*>(&m_dialect))
if (auto const* builtin = dialect->builtin(_exprStmnt.expression.functionName.name))
if (builtin->instruction)
return evmasm::SemanticInformation::terminatesControlFlow(*builtin->instruction);
return false;
}