Move variables-in-interfaces checker to PostTypeChecker

refs #7566
This commit is contained in:
Mathias Baumann 2019-12-17 16:58:53 +00:00 committed by chriseth
parent 21844aa545
commit 2179562785
4 changed files with 64 additions and 16 deletions

View File

@ -82,6 +82,16 @@ bool PostTypeChecker::visit(Identifier const& _identifier)
return callVisit(_identifier);
}
bool PostTypeChecker::visit(StructDefinition const& _struct)
{
return callVisit(_struct);
}
void PostTypeChecker::endVisit(StructDefinition const& _struct)
{
callEndVisit(_struct);
}
bool PostTypeChecker::visit(ModifierInvocation const& _modifierInvocation)
{
return callVisit(_modifierInvocation);
@ -282,6 +292,55 @@ private:
bool m_insideEmitStatement = false;
};
struct NoVariablesInInterfaceChecker: public PostTypeChecker::Checker
{
NoVariablesInInterfaceChecker(ErrorReporter& _errorReporter):
Checker(_errorReporter)
{}
bool visit(VariableDeclaration const& _variable) override
{
// Forbid any variable declarations inside interfaces unless they are part of
// * a function's input/output parameters,
// * or inside of a struct definition.
if (
m_scope && m_scope->isInterface()
&& !_variable.isCallableOrCatchParameter()
&& !m_insideStruct
)
m_errorReporter.typeError(_variable.location(), "Variables cannot be declared in interfaces.");
return true;
}
bool visit(ContractDefinition const& _contract) override
{
m_scope = &_contract;
return true;
}
void endVisit(ContractDefinition const&) override
{
m_scope = nullptr;
}
bool visit(StructDefinition const&) override
{
solAssert(m_insideStruct >= 0, "");
m_insideStruct++;
return true;
}
void endVisit(StructDefinition const&) override
{
m_insideStruct--;
solAssert(m_insideStruct >= 0, "");
}
private:
ContractDefinition const* m_scope = nullptr;
/// Flag indicating whether we are currently inside a StructDefinition.
int m_insideStruct = 0;
};
}
PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter)
@ -290,4 +349,5 @@ PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_err
m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter));
m_checkers.push_back(make_shared<ModifierContextChecker>(_errorReporter));
m_checkers.push_back(make_shared<EventOutsideEmitChecker>(_errorReporter));
m_checkers.push_back(make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
}

View File

@ -38,6 +38,7 @@ namespace solidity::frontend
* - whether override specifiers are actually contracts
* - whether a modifier is in a function header
* - whether an event is used outside of an emit statement
* - whether a variable is declared in a interface
*
* When adding a new checker, make sure a visitor that forwards calls that your
* checker uses exists in PostTypeChecker. Add missing ones.
@ -76,6 +77,9 @@ private:
bool visit(Identifier const& _identifier) override;
bool visit(StructDefinition const& _struct) override;
void endVisit(StructDefinition const& _struct) override;
bool visit(ModifierInvocation const& _modifierInvocation) override;
void endVisit(ModifierInvocation const& _modifierInvocation) override;

View File

@ -317,10 +317,7 @@ bool TypeChecker::visit(StructDefinition const& _struct)
if (CycleDetector<StructDefinition>(visitor).run(_struct) != nullptr)
m_errorReporter.fatalTypeError(_struct.location(), "Recursive struct definition.");
bool insideStruct = true;
swap(insideStruct, m_insideStruct);
ASTNode::listAccept(_struct.members(), *this);
m_insideStruct = insideStruct;
return false;
}
@ -451,16 +448,6 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
bool TypeChecker::visit(VariableDeclaration const& _variable)
{
// Forbid any variable declarations inside interfaces unless they are part of
// * a function's input/output parameters,
// * or inside of a struct definition.
if (
m_scope->isInterface()
&& !_variable.isCallableOrCatchParameter()
&& !m_insideStruct
)
m_errorReporter.typeError(_variable.location(), "Variables cannot be declared in interfaces.");
if (_variable.typeName())
_variable.typeName()->accept(*this);

View File

@ -163,9 +163,6 @@ private:
langutil::EVMVersion m_evmVersion;
/// Flag indicating whether we are currently inside a StructDefinition.
bool m_insideStruct = false;
langutil::ErrorReporter& m_errorReporter;
};