Move modifier context check to PostTypeChecker

refs #7566
This commit is contained in:
Mathias Baumann 2019-12-17 15:18:58 +00:00 committed by chriseth
parent 5ad590cf0b
commit 9f8d49e358
4 changed files with 52 additions and 18 deletions

View File

@ -67,6 +67,15 @@ bool PostTypeChecker::visit(Identifier const& _identifier)
return callVisit(_identifier); return callVisit(_identifier);
} }
bool PostTypeChecker::visit(ModifierInvocation const& _modifierInvocation)
{
return callVisit(_modifierInvocation);
}
void PostTypeChecker::endVisit(ModifierInvocation const& _modifierInvocation)
{
callEndVisit(_modifierInvocation);
}
namespace namespace
{ {
@ -183,11 +192,48 @@ struct OverrideSpecifierChecker: public PostTypeChecker::Checker
} }
} }
}; };
struct ModifierContextChecker: public PostTypeChecker::Checker
{
ModifierContextChecker(ErrorReporter& _errorReporter):
Checker(_errorReporter) {}
bool visit(ModifierInvocation const&) override
{
m_insideModifierInvocation = true;
return true;
} }
void endVisit(ModifierInvocation const&) override
{
m_insideModifierInvocation = false;
}
bool visit(Identifier const& _identifier) override
{
if (m_insideModifierInvocation)
return true;
if (ModifierType const* type = dynamic_cast<decltype(type)>(_identifier.annotation().type))
{
m_errorReporter.typeError(
_identifier.location(),
"Modifier can only be referenced in function headers."
);
}
return false;
}
private:
/// Flag indicating whether we are currently inside the invocation of a modifier
bool m_insideModifierInvocation = false;
};
}
PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter)
{ {
m_checkers.push_back(make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter)); m_checkers.push_back(make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter)); m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter));
m_checkers.push_back(make_shared<ModifierContextChecker>(_errorReporter));
} }

View File

@ -36,6 +36,7 @@ namespace solidity::frontend
* This module performs analyses on the AST that are done after type checking and assignments of types: * This module performs analyses on the AST that are done after type checking and assignments of types:
* - whether there are circular references in constant state variables * - whether there are circular references in constant state variables
* - whether override specifiers are actually contracts * - whether override specifiers are actually contracts
* - whether a modifier is in a function header
* *
* When adding a new checker, make sure a visitor that forwards calls that your * When adding a new checker, make sure a visitor that forwards calls that your
* checker uses exists in PostTypeChecker. Add missing ones. * checker uses exists in PostTypeChecker. Add missing ones.
@ -69,6 +70,9 @@ private:
bool visit(Identifier const& _identifier) override; bool visit(Identifier const& _identifier) override;
bool visit(ModifierInvocation const& _modifierInvocation) override;
void endVisit(ModifierInvocation const& _modifierInvocation) override;
template <class T> template <class T>
bool callVisit(T const& _node) bool callVisit(T const& _node)
{ {

View File

@ -547,11 +547,7 @@ void TypeChecker::visitManually(
for (ASTPointer<Expression> const& argument: arguments) for (ASTPointer<Expression> const& argument: arguments)
argument->accept(*this); argument->accept(*this);
{
m_insideModifierInvocation = true;
ScopeGuard resetFlag{[&] () { m_insideModifierInvocation = false; }};
_modifier.name()->accept(*this); _modifier.name()->accept(*this);
}
auto const* declaration = &dereference(*_modifier.name()); auto const* declaration = &dereference(*_modifier.name());
vector<ASTPointer<VariableDeclaration>> emptyParameterList; vector<ASTPointer<VariableDeclaration>> emptyParameterList;
@ -2704,15 +2700,6 @@ bool TypeChecker::visit(Identifier const& _identifier)
); );
} }
if (!m_insideModifierInvocation)
if (ModifierType const* type = dynamic_cast<decltype(type)>(_identifier.annotation().type))
{
m_errorReporter.typeError(
_identifier.location(),
"Modifier can only be referenced in function headers."
);
}
return false; return false;
} }

View File

@ -170,9 +170,6 @@ private:
/// Flag indicating whether we are currently inside a StructDefinition. /// Flag indicating whether we are currently inside a StructDefinition.
bool m_insideStruct = false; bool m_insideStruct = false;
/// Flag indicating whether we are currently inside the invocation of a modifier
bool m_insideModifierInvocation = false;
langutil::ErrorReporter& m_errorReporter; langutil::ErrorReporter& m_errorReporter;
}; };