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) 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) if (!variableDeclaration)
return; return;
if (!variableDeclaration->isConstant()) if (!variableDeclaration->isConstant())
m_errorReporter.fatalTypeError(_identifier.location(), "Identifier must be declared constant."); m_errorReporter.fatalTypeError(_identifier.location(), "Identifier must be declared constant.");
ASTPointer<Expression> value = variableDeclaration->value(); ASTPointer<Expression> value = variableDeclaration->value();
if (value) if (!value)
{ m_errorReporter.fatalTypeError(_identifier.location(), "Constant identifier declaration must have a constant value.");
if (!value->annotation().type)
ConstantEvaluator e(*value, m_errorReporter);
_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 class ConstantEvaluator: private ASTConstVisitor
{ {
public: public:
ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter): ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter, size_t _newDepth = 0):
m_errorReporter(_errorReporter) m_errorReporter(_errorReporter),
m_depth(_newDepth)
{ {
_expr.accept(*this); _expr.accept(*this);
} }
@ -51,6 +52,8 @@ private:
virtual void endVisit(Identifier const& _identifier); virtual void endVisit(Identifier const& _identifier);
ErrorReporter& m_errorReporter; 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) BOOST_AUTO_TEST_CASE(array_length_with_pure_functions)