aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp27
-rw-r--r--libsolidity/inlineasm/AsmParser.h2
2 files changed, 18 insertions, 11 deletions
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index 9336e620..20c7b2a5 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -123,7 +123,7 @@ assembly::Statement Parser::parseStatement()
// Simple instruction (might turn into functional),
// literal,
// identifier (might turn into label or functional assignment)
- ElementaryOperation elementary(parseElementaryOperation(false));
+ ElementaryOperation elementary(parseElementaryOperation());
switch (currentToken())
{
case Token::LParen:
@@ -145,7 +145,7 @@ assembly::Statement Parser::parseStatement()
do
{
expectToken(Token::Comma);
- elementary = parseElementaryOperation(false);
+ elementary = parseElementaryOperation();
if (elementary.type() != typeid(assembly::Identifier))
fatalParserError("Variable name expected in multiple assignemnt.");
assignment.variableNames.emplace_back(boost::get<assembly::Identifier>(elementary));
@@ -247,10 +247,11 @@ assembly::ForLoop Parser::parseForLoop()
assembly::Expression Parser::parseExpression()
{
RecursionGuard recursionGuard(*this);
- ElementaryOperation operation = parseElementaryOperation(true);
+ ElementaryOperation operation = parseElementaryOperation();
if (operation.type() == typeid(Instruction))
{
Instruction const& instr = boost::get<Instruction>(operation);
+ // Enforce functional notation for instructions requiring multiple arguments.
int args = instructionInfo(instr.instruction).args;
if (args > 0 && currentToken() != Token::LParen)
fatalParserError(string(
@@ -260,11 +261,23 @@ assembly::Expression Parser::parseExpression()
boost::lexical_cast<string>(args) +
" arguments)"
));
+ // Disallow instructions returning multiple values (and DUP/SWAP) as expression.
+ if (
+ instructionInfo(instr.instruction).ret != 1 ||
+ isDupInstruction(instr.instruction) ||
+ isSwapInstruction(instr.instruction)
+ )
+ fatalParserError(
+ "Instruction \"" +
+ instructionNames().at(instr.instruction) +
+ "\" not allowed in this context."
+ );
}
if (currentToken() == Token::LParen)
return parseCall(std::move(operation));
else if (operation.type() == typeid(Instruction))
{
+ // Instructions not taking arguments are allowed as expressions.
Instruction& instr = boost::get<Instruction>(operation);
return FunctionalInstruction{std::move(instr.location), instr.instruction, {}};
}
@@ -317,7 +330,7 @@ std::map<dev::solidity::Instruction, string> const& Parser::instructionNames()
return s_instructionNames;
}
-Parser::ElementaryOperation Parser::parseElementaryOperation(bool _onlySinglePusher)
+Parser::ElementaryOperation Parser::parseElementaryOperation()
{
RecursionGuard recursionGuard(*this);
ElementaryOperation ret;
@@ -341,12 +354,6 @@ Parser::ElementaryOperation Parser::parseElementaryOperation(bool _onlySinglePus
if (!m_julia && instructions().count(literal))
{
dev::solidity::Instruction const& instr = instructions().at(literal);
- if (_onlySinglePusher)
- {
- InstructionInfo info = dev::solidity::instructionInfo(instr);
- if (info.ret != 1)
- fatalParserError("Instruction \"" + literal + "\" not allowed in this context.");
- }
ret = Instruction{location(), instr};
}
else
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index 44889a13..bd90bb43 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -70,7 +70,7 @@ protected:
assembly::Expression parseExpression();
static std::map<std::string, dev::solidity::Instruction> const& instructions();
static std::map<dev::solidity::Instruction, std::string> const& instructionNames();
- ElementaryOperation parseElementaryOperation(bool _onlySinglePusher = false);
+ ElementaryOperation parseElementaryOperation();
VariableDeclaration parseVariableDeclaration();
FunctionDefinition parseFunctionDefinition();
assembly::Expression parseCall(ElementaryOperation&& _initialOp);