Merge pull request #6555 from sifmelcara/break-for-loop

[Yul] Disallow function definitions inside for loop init blocks
This commit is contained in:
chriseth
2019-04-25 11:20:44 +02:00
committed by GitHub
6 changed files with 183 additions and 46 deletions
+52 -33
View File
@@ -126,31 +126,19 @@ Statement Parser::parseStatement()
case Token::For:
return parseForLoop();
case Token::Break:
if (m_insideForLoopBody)
{
auto stmt = Statement{ createWithLocation<Break>() };
m_scanner->next();
return stmt;
}
else
{
m_errorReporter.syntaxError(location(), "Keyword break outside for-loop body is not allowed.");
m_scanner->next();
return {};
}
{
Statement stmt{createWithLocation<Break>()};
checkBreakContinuePosition("break");
m_scanner->next();
return stmt;
}
case Token::Continue:
if (m_insideForLoopBody)
{
auto stmt = Statement{ createWithLocation<Continue>() };
m_scanner->next();
return stmt;
}
else
{
m_errorReporter.syntaxError(location(), "Keyword continue outside for-loop body is not allowed.");
m_scanner->next();
return {};
}
{
Statement stmt{createWithLocation<Continue>()};
checkBreakContinuePosition("continue");
m_scanner->next();
return stmt;
}
case Token::Assign:
{
if (m_dialect->flavour != AsmFlavour::Loose)
@@ -290,20 +278,24 @@ Case Parser::parseCase()
ForLoop Parser::parseForLoop()
{
bool outerForLoopBody = m_insideForLoopBody;
m_insideForLoopBody = false;
RecursionGuard recursionGuard(*this);
ForLoopComponent outerForLoopComponent = m_currentForLoopComponent;
ForLoop forLoop = createWithLocation<ForLoop>();
expectToken(Token::For);
m_currentForLoopComponent = ForLoopComponent::ForLoopPre;
forLoop.pre = parseBlock();
m_currentForLoopComponent = ForLoopComponent::None;
forLoop.condition = make_unique<Expression>(parseExpression());
m_currentForLoopComponent = ForLoopComponent::ForLoopPost;
forLoop.post = parseBlock();
m_insideForLoopBody = true;
m_currentForLoopComponent = ForLoopComponent::ForLoopBody;
forLoop.body = parseBlock();
m_insideForLoopBody = outerForLoopBody;
forLoop.location.end = forLoop.body.location.end;
m_currentForLoopComponent = outerForLoopComponent;
return forLoop;
}
@@ -487,9 +479,16 @@ VariableDeclaration Parser::parseVariableDeclaration()
FunctionDefinition Parser::parseFunctionDefinition()
{
RecursionGuard recursionGuard(*this);
auto outerForLoopBody = m_insideForLoopBody;
m_insideForLoopBody = false;
ScopeGuard restoreInsideForLoopBody{[&]() { m_insideForLoopBody = outerForLoopBody; }};
if (m_currentForLoopComponent == ForLoopComponent::ForLoopPre)
m_errorReporter.syntaxError(
location(),
"Functions cannot be defined inside a for-loop init block."
);
ForLoopComponent outerForLoopComponent = m_currentForLoopComponent;
m_currentForLoopComponent = ForLoopComponent::None;
FunctionDefinition funDef = createWithLocation<FunctionDefinition>();
expectToken(Token::Function);
funDef.name = expectAsmIdentifier();
@@ -516,6 +515,8 @@ FunctionDefinition Parser::parseFunctionDefinition()
}
funDef.body = parseBlock();
funDef.location.end = funDef.body.location.end;
m_currentForLoopComponent = outerForLoopComponent;
return funDef;
}
@@ -642,6 +643,24 @@ YulString Parser::expectAsmIdentifier()
return name;
}
void Parser::checkBreakContinuePosition(string const& _which)
{
switch (m_currentForLoopComponent)
{
case ForLoopComponent::None:
m_errorReporter.syntaxError(location(), "Keyword \"" + _which + "\" needs to be inside a for-loop body.");
break;
case ForLoopComponent::ForLoopPre:
m_errorReporter.syntaxError(location(), "Keyword \"" + _which + "\" in for-loop init block is not allowed.");
break;
case ForLoopComponent::ForLoopPost:
m_errorReporter.syntaxError(location(), "Keyword \"" + _which + "\" in for-loop post block is not allowed.");
break;
case ForLoopComponent::ForLoopBody:
break;
}
}
bool Parser::isValidNumberLiteral(string const& _literal)
{
try