mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul] Ensures DataFlowAnalyzer works fine with break/continue statements just like without.
This commit is contained in:
@@ -117,6 +117,9 @@ void DataFlowAnalyzer::operator()(ForLoop& _for)
|
||||
for (auto& statement: _for.pre.statements)
|
||||
visit(statement);
|
||||
|
||||
AssignmentsSinceContinue assignmentsSinceCont;
|
||||
assignmentsSinceCont(_for.body);
|
||||
|
||||
Assignments assignments;
|
||||
assignments(_for.body);
|
||||
assignments(_for.post);
|
||||
@@ -124,22 +127,13 @@ void DataFlowAnalyzer::operator()(ForLoop& _for)
|
||||
|
||||
visit(*_for.condition);
|
||||
(*this)(_for.body);
|
||||
clearValues(assignmentsSinceCont.names());
|
||||
(*this)(_for.post);
|
||||
|
||||
clearValues(assignments.names());
|
||||
|
||||
popScope();
|
||||
}
|
||||
|
||||
void DataFlowAnalyzer::operator()(Break&)
|
||||
{
|
||||
yulAssert(false, "Not implemented yet.");
|
||||
}
|
||||
|
||||
void DataFlowAnalyzer::operator()(Continue&)
|
||||
{
|
||||
yulAssert(false, "Not implemented yet.");
|
||||
}
|
||||
|
||||
void DataFlowAnalyzer::operator()(Block& _block)
|
||||
{
|
||||
size_t numScopes = m_variableScopes.size();
|
||||
|
||||
@@ -53,8 +53,6 @@ public:
|
||||
void operator()(Switch& _switch) override;
|
||||
void operator()(FunctionDefinition&) override;
|
||||
void operator()(ForLoop&) override;
|
||||
void operator()(Break& _continue) override;
|
||||
void operator()(Continue& _continue) override;
|
||||
void operator()(Block& _block) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -79,3 +79,29 @@ void Assignments::operator()(Assignment const& _assignment)
|
||||
for (auto const& var: _assignment.variableNames)
|
||||
m_names.emplace(var.name);
|
||||
}
|
||||
|
||||
|
||||
void AssignmentsSinceContinue::operator()(ForLoop const& _forLoop)
|
||||
{
|
||||
m_forLoopDepth++;
|
||||
ASTWalker::operator()(_forLoop);
|
||||
m_forLoopDepth--;
|
||||
}
|
||||
|
||||
void AssignmentsSinceContinue::operator()(Continue const&)
|
||||
{
|
||||
if (m_forLoopDepth == 0)
|
||||
m_continueFound = true;
|
||||
}
|
||||
|
||||
void AssignmentsSinceContinue::operator()(Assignment const& _assignment)
|
||||
{
|
||||
if (m_continueFound)
|
||||
for (auto const& var: _assignment.variableNames)
|
||||
m_names.emplace(var.name);
|
||||
}
|
||||
|
||||
void AssignmentsSinceContinue::operator()(FunctionDefinition const&)
|
||||
{
|
||||
yulAssert(false, "");
|
||||
}
|
||||
|
||||
@@ -81,4 +81,29 @@ private:
|
||||
std::set<YulString> m_names;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collects all names from a given continue statement on onwards.
|
||||
*
|
||||
* It makes only sense to be invoked from within a body of an outer for loop, that is,
|
||||
* it will only collect all names from the beginning of the first continue statement
|
||||
* of the outer-most ForLoop.
|
||||
*/
|
||||
class AssignmentsSinceContinue: public ASTWalker
|
||||
{
|
||||
public:
|
||||
using ASTWalker::operator();
|
||||
void operator()(ForLoop const& _forLoop) override;
|
||||
void operator()(Continue const&) override;
|
||||
void operator()(Assignment const& _assignment) override;
|
||||
void operator()(FunctionDefinition const& _funDef) override;
|
||||
|
||||
std::set<YulString> const& names() const { return m_names; }
|
||||
bool empty() const noexcept { return m_names.empty(); }
|
||||
|
||||
private:
|
||||
size_t m_forLoopDepth = 0;
|
||||
bool m_continueFound = false;
|
||||
std::set<YulString> m_names;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user