mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Check for circular constants across contracts.
This commit is contained in:
parent
c4d8b4fa0e
commit
21dee1c8ba
@ -38,6 +38,13 @@ bool PostTypeChecker::check(ASTNode const& _astRoot)
|
|||||||
return Error::containsOnlyWarnings(m_errorReporter.errors());
|
return Error::containsOnlyWarnings(m_errorReporter.errors());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PostTypeChecker::finalize()
|
||||||
|
{
|
||||||
|
for (auto& checker: m_checkers)
|
||||||
|
checker->finalize();
|
||||||
|
return Error::containsOnlyWarnings(m_errorReporter.errors());
|
||||||
|
}
|
||||||
|
|
||||||
bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition)
|
bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition)
|
||||||
{
|
{
|
||||||
return callVisit(_contractDefinition);
|
return callVisit(_contractDefinition);
|
||||||
@ -83,6 +90,11 @@ bool PostTypeChecker::visit(Identifier const& _identifier)
|
|||||||
return callVisit(_identifier);
|
return callVisit(_identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PostTypeChecker::visit(MemberAccess const& _memberAccess)
|
||||||
|
{
|
||||||
|
return callVisit(_memberAccess);
|
||||||
|
}
|
||||||
|
|
||||||
bool PostTypeChecker::visit(StructDefinition const& _struct)
|
bool PostTypeChecker::visit(StructDefinition const& _struct)
|
||||||
{
|
{
|
||||||
return callVisit(_struct);
|
return callVisit(_struct);
|
||||||
@ -110,14 +122,7 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker
|
|||||||
ConstStateVarCircularReferenceChecker(ErrorReporter& _errorReporter):
|
ConstStateVarCircularReferenceChecker(ErrorReporter& _errorReporter):
|
||||||
Checker(_errorReporter) {}
|
Checker(_errorReporter) {}
|
||||||
|
|
||||||
bool visit(ContractDefinition const&) override
|
void finalize() override
|
||||||
{
|
|
||||||
solAssert(!m_currentConstVariable, "");
|
|
||||||
solAssert(m_constVariableDependencies.empty(), "");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void endVisit(ContractDefinition const&) override
|
|
||||||
{
|
{
|
||||||
solAssert(!m_currentConstVariable, "");
|
solAssert(!m_currentConstVariable, "");
|
||||||
for (auto declaration: m_constVariables)
|
for (auto declaration: m_constVariables)
|
||||||
@ -128,9 +133,12 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker
|
|||||||
"The value of the constant " + declaration->name() +
|
"The value of the constant " + declaration->name() +
|
||||||
" has a cyclic dependency via " + identifier->name() + "."
|
" has a cyclic dependency via " + identifier->name() + "."
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
m_constVariables.clear();
|
bool visit(ContractDefinition const&) override
|
||||||
m_constVariableDependencies.clear();
|
{
|
||||||
|
solAssert(!m_currentConstVariable, "");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visit(VariableDeclaration const& _variable) override
|
bool visit(VariableDeclaration const& _variable) override
|
||||||
@ -162,6 +170,15 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool visit(MemberAccess const& _memberAccess) override
|
||||||
|
{
|
||||||
|
if (m_currentConstVariable)
|
||||||
|
if (auto var = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
|
||||||
|
if (var->isConstant())
|
||||||
|
m_constVariableDependencies[m_currentConstVariable].insert(var);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
VariableDeclaration const* findCycle(VariableDeclaration const& _startingFrom)
|
VariableDeclaration const* findCycle(VariableDeclaration const& _startingFrom)
|
||||||
{
|
{
|
||||||
auto visitor = [&](VariableDeclaration const& _variable, util::CycleDetector<VariableDeclaration>& _cycleDetector, size_t _depth)
|
auto visitor = [&](VariableDeclaration const& _variable, util::CycleDetector<VariableDeclaration>& _cycleDetector, size_t _depth)
|
||||||
|
@ -54,6 +54,9 @@ public:
|
|||||||
{
|
{
|
||||||
Checker(langutil::ErrorReporter& _errorReporter):
|
Checker(langutil::ErrorReporter& _errorReporter):
|
||||||
m_errorReporter(_errorReporter) {}
|
m_errorReporter(_errorReporter) {}
|
||||||
|
|
||||||
|
/// Called after all source units have been visited.
|
||||||
|
virtual void finalize() {}
|
||||||
protected:
|
protected:
|
||||||
langutil::ErrorReporter& m_errorReporter;
|
langutil::ErrorReporter& m_errorReporter;
|
||||||
};
|
};
|
||||||
@ -63,6 +66,9 @@ public:
|
|||||||
|
|
||||||
bool check(ASTNode const& _astRoot);
|
bool check(ASTNode const& _astRoot);
|
||||||
|
|
||||||
|
/// Called after all source units have been visited.
|
||||||
|
bool finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool visit(ContractDefinition const& _contract) override;
|
bool visit(ContractDefinition const& _contract) override;
|
||||||
void endVisit(ContractDefinition const& _contract) override;
|
void endVisit(ContractDefinition const& _contract) override;
|
||||||
@ -77,6 +83,7 @@ private:
|
|||||||
bool visit(FunctionCall const& _functionCall) override;
|
bool visit(FunctionCall const& _functionCall) override;
|
||||||
|
|
||||||
bool visit(Identifier const& _identifier) override;
|
bool visit(Identifier const& _identifier) override;
|
||||||
|
bool visit(MemberAccess const& _identifier) override;
|
||||||
|
|
||||||
bool visit(StructDefinition const& _struct) override;
|
bool visit(StructDefinition const& _struct) override;
|
||||||
void endVisit(StructDefinition const& _struct) override;
|
void endVisit(StructDefinition const& _struct) override;
|
||||||
|
@ -387,6 +387,8 @@ bool CompilerStack::analyze()
|
|||||||
for (Source const* source: m_sourceOrder)
|
for (Source const* source: m_sourceOrder)
|
||||||
if (source->ast && !postTypeChecker.check(*source->ast))
|
if (source->ast && !postTypeChecker.check(*source->ast))
|
||||||
noErrors = false;
|
noErrors = false;
|
||||||
|
if (!postTypeChecker.finalize())
|
||||||
|
noErrors = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that immutable variables are never read in c'tors and assigned
|
// Check that immutable variables are never read in c'tors and assigned
|
||||||
|
Loading…
Reference in New Issue
Block a user