mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
parent
5ad590cf0b
commit
9f8d49e358
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user