mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
ExpressionStatements can only be FunctionCalls.
This commit is contained in:
parent
41f5036507
commit
9c61060eff
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -87,7 +87,7 @@ protected:
|
||||
ElementaryOperation parseElementaryOperation();
|
||||
VariableDeclaration parseVariableDeclaration();
|
||||
FunctionDefinition parseFunctionDefinition();
|
||||
Expression parseCall(ElementaryOperation&& _initialOp);
|
||||
FunctionCall parseCall(ElementaryOperation&& _initialOp);
|
||||
TypedName parseTypedName();
|
||||
YulString expectAsmIdentifier();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user