Detect cyclic constant definitions

This commit is contained in:
Balajiganapathi S 2017-11-17 22:25:07 +05:30 committed by Alex Beregszaszi
parent c0b4969451
commit d102deaec9
3 changed files with 44 additions and 9 deletions

View File

@ -77,18 +77,22 @@ void ConstantEvaluator::endVisit(Literal const& _literal)
void ConstantEvaluator::endVisit(Identifier const& _identifier)
{
VariableDeclaration const *variableDeclaration = dynamic_cast<VariableDeclaration const *>(_identifier.annotation().referencedDeclaration);
VariableDeclaration const* variableDeclaration = dynamic_cast<VariableDeclaration const*>(_identifier.annotation().referencedDeclaration);
if (!variableDeclaration)
return;
if (!variableDeclaration->isConstant())
m_errorReporter.fatalTypeError(_identifier.location(), "Identifier must be declared constant.");
ASTPointer<Expression> value = variableDeclaration->value();
if (value)
{
if (!value->annotation().type)
ConstantEvaluator e(*value, m_errorReporter);
if (!value)
m_errorReporter.fatalTypeError(_identifier.location(), "Constant identifier declaration must have a constant value.");
_identifier.annotation().type = value->annotation().type;
if (!value->annotation().type)
{
if (m_depth > 32)
m_errorReporter.fatalTypeError(_identifier.location(), "Cyclic constant definition.");
ConstantEvaluator e(*value, m_errorReporter, m_depth + 1);
}
_identifier.annotation().type = value->annotation().type;
}

View File

@ -38,8 +38,9 @@ class TypeChecker;
class ConstantEvaluator: private ASTConstVisitor
{
public:
ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter):
m_errorReporter(_errorReporter)
ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter, size_t _newDepth = 0):
m_errorReporter(_errorReporter),
m_depth(_newDepth)
{
_expr.accept(*this);
}
@ -51,6 +52,8 @@ private:
virtual void endVisit(Identifier const& _identifier);
ErrorReporter& m_errorReporter;
/// Current recursion depth.
size_t m_depth;
};
}

View File

@ -7366,7 +7366,35 @@ BOOST_AUTO_TEST_CASE(array_length_cannot_be_constant_function_parameter)
}
}
)";
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal.");
CHECK_ERROR(text, TypeError, "Constant identifier declaration must have a constant value.");
}
BOOST_AUTO_TEST_CASE(array_length_with_cyclic_constant)
{
char const* text = R"(
contract C {
uint constant LEN = LEN;
function f() {
uint[LEN] a;
}
}
)";
CHECK_ERROR(text, TypeError, "Cyclic constant definition.");
}
BOOST_AUTO_TEST_CASE(array_length_with_complex_cyclic_constant)
{
char const* text = R"(
contract C {
uint constant L2 = LEN - 10;
uint constant L1 = L2 / 10;
uint constant LEN = 10 + L1 * 5;
function f() {
uint[LEN] a;
}
}
)";
CHECK_ERROR(text, TypeError, "Cyclic constant definition.");
}
BOOST_AUTO_TEST_CASE(array_length_with_pure_functions)