Use opportunistic visiting order for modifiers.

This commit is contained in:
chriseth 2020-08-04 10:38:31 +02:00
parent cf5aa450bd
commit 8d92fd1c04
2 changed files with 24 additions and 22 deletions

View File

@ -128,12 +128,6 @@ private:
bool ViewPureChecker::check() bool ViewPureChecker::check()
{ {
// Process modifiers first to infer their state mutability.
m_checkModifiers = true;
for (auto const& source: m_ast)
source->accept(*this);
m_checkModifiers = false;
for (auto const& source: m_ast) for (auto const& source: m_ast)
source->accept(*this); source->accept(*this);
@ -142,9 +136,6 @@ bool ViewPureChecker::check()
bool ViewPureChecker::visit(FunctionDefinition const& _funDef) bool ViewPureChecker::visit(FunctionDefinition const& _funDef)
{ {
if (m_checkModifiers)
return false;
solAssert(!m_currentFunction, ""); solAssert(!m_currentFunction, "");
m_currentFunction = &_funDef; m_currentFunction = &_funDef;
m_bestMutabilityAndLocation = {StateMutability::Pure, _funDef.location()}; m_bestMutabilityAndLocation = {StateMutability::Pure, _funDef.location()};
@ -153,9 +144,6 @@ bool ViewPureChecker::visit(FunctionDefinition const& _funDef)
void ViewPureChecker::endVisit(FunctionDefinition const& _funDef) void ViewPureChecker::endVisit(FunctionDefinition const& _funDef)
{ {
if (m_checkModifiers)
return;
solAssert(m_currentFunction == &_funDef, ""); solAssert(m_currentFunction == &_funDef, "");
if ( if (
m_bestMutabilityAndLocation.mutability < _funDef.stateMutability() && m_bestMutabilityAndLocation.mutability < _funDef.stateMutability() &&
@ -177,9 +165,6 @@ void ViewPureChecker::endVisit(FunctionDefinition const& _funDef)
bool ViewPureChecker::visit(ModifierDefinition const& _modifier) bool ViewPureChecker::visit(ModifierDefinition const& _modifier)
{ {
if (!m_checkModifiers)
return false;
solAssert(m_currentFunction == nullptr, ""); solAssert(m_currentFunction == nullptr, "");
m_bestMutabilityAndLocation = {StateMutability::Pure, _modifier.location()}; m_bestMutabilityAndLocation = {StateMutability::Pure, _modifier.location()};
return true; return true;
@ -187,9 +172,6 @@ bool ViewPureChecker::visit(ModifierDefinition const& _modifier)
void ViewPureChecker::endVisit(ModifierDefinition const& _modifierDef) void ViewPureChecker::endVisit(ModifierDefinition const& _modifierDef)
{ {
if (!m_checkModifiers)
return;
solAssert(m_currentFunction == nullptr, ""); solAssert(m_currentFunction == nullptr, "");
m_inferredMutability[&_modifierDef] = std::move(m_bestMutabilityAndLocation); m_inferredMutability[&_modifierDef] = std::move(m_bestMutabilityAndLocation);
} }
@ -306,7 +288,26 @@ void ViewPureChecker::reportMutability(
m_currentFunction->stateMutability() == StateMutability::Pure || m_currentFunction->stateMutability() == StateMutability::Pure ||
m_currentFunction->stateMutability() == StateMutability::NonPayable, m_currentFunction->stateMutability() == StateMutability::NonPayable,
"" ""
); );
}
ViewPureChecker::MutabilityAndLocation const& ViewPureChecker::modifierMutability(
ModifierDefinition const& _modifier
)
{
if (!m_inferredMutability.count(&_modifier))
{
MutabilityAndLocation bestMutabilityAndLocation{};
FunctionDefinition const* currentFunction = nullptr;
swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
swap(currentFunction, m_currentFunction);
_modifier.accept(*this);
swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
swap(currentFunction, m_currentFunction);
}
return m_inferredMutability.at(&_modifier);
} }
void ViewPureChecker::endVisit(FunctionCall const& _functionCall) void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
@ -431,8 +432,7 @@ void ViewPureChecker::endVisit(ModifierInvocation const& _modifier)
solAssert(_modifier.name(), ""); solAssert(_modifier.name(), "");
if (ModifierDefinition const* mod = dynamic_cast<decltype(mod)>(_modifier.name()->annotation().referencedDeclaration)) if (ModifierDefinition const* mod = dynamic_cast<decltype(mod)>(_modifier.name()->annotation().referencedDeclaration))
{ {
solAssert(m_inferredMutability.count(mod), ""); MutabilityAndLocation const& mutAndLocation = modifierMutability(*mod);
auto const& mutAndLocation = m_inferredMutability.at(mod);
reportMutability(mutAndLocation.mutability, _modifier.location(), mutAndLocation.location); reportMutability(mutAndLocation.mutability, _modifier.location(), mutAndLocation.location);
} }
else else

View File

@ -71,11 +71,13 @@ private:
std::optional<langutil::SourceLocation> const& _nestedLocation = {} std::optional<langutil::SourceLocation> const& _nestedLocation = {}
); );
/// Determines the mutability of modifier if not already cached.
MutabilityAndLocation const& modifierMutability(ModifierDefinition const& _modifier);
std::vector<std::shared_ptr<ASTNode>> const& m_ast; std::vector<std::shared_ptr<ASTNode>> const& m_ast;
langutil::ErrorReporter& m_errorReporter; langutil::ErrorReporter& m_errorReporter;
bool m_errors = false; bool m_errors = false;
bool m_checkModifiers = false;
MutabilityAndLocation m_bestMutabilityAndLocation = MutabilityAndLocation{StateMutability::Payable, langutil::SourceLocation()}; MutabilityAndLocation m_bestMutabilityAndLocation = MutabilityAndLocation{StateMutability::Payable, langutil::SourceLocation()};
FunctionDefinition const* m_currentFunction = nullptr; FunctionDefinition const* m_currentFunction = nullptr;
std::map<ModifierDefinition const*, MutabilityAndLocation> m_inferredMutability; std::map<ModifierDefinition const*, MutabilityAndLocation> m_inferredMutability;