Commit 036c8f37 by Ian Lance Taylor

Improve check for const initializer loop.

From-SVN: r169003
parent e3e19050
...@@ -2348,6 +2348,10 @@ class Const_expression : public Expression ...@@ -2348,6 +2348,10 @@ class Const_expression : public Expression
name() const name() const
{ return this->constant_->name(); } { return this->constant_->name(); }
// Check that the initializer does not refer to the constant itself.
void
check_for_init_loop();
protected: protected:
Expression* Expression*
do_lower(Gogo*, Named_object*, int); do_lower(Gogo*, Named_object*, int);
...@@ -2610,23 +2614,49 @@ Const_expression::do_determine_type(const Type_context* context) ...@@ -2610,23 +2614,49 @@ Const_expression::do_determine_type(const Type_context* context)
} }
} }
// Check types of a const reference. // Check for a loop in which the initializer of a constant refers to
// the constant itself.
void void
Const_expression::do_check_types(Gogo*) Const_expression::check_for_init_loop()
{ {
if (this->type_ != NULL && this->type_->is_error_type()) if (this->type_ != NULL && this->type_->is_error_type())
return; return;
if (this->seen_)
{
this->report_error(_("constant refers to itself"));
this->type_ = Type::make_error_type();
return;
}
Expression* init = this->constant_->const_value()->expr(); Expression* init = this->constant_->const_value()->expr();
Find_named_object find_named_object(this->constant_); Find_named_object find_named_object(this->constant_);
this->seen_ = true;
Expression::traverse(&init, &find_named_object); Expression::traverse(&init, &find_named_object);
this->seen_ = false;
if (find_named_object.found()) if (find_named_object.found())
{ {
this->report_error(_("constant refers to itself")); if (this->type_ == NULL || !this->type_->is_error_type())
this->type_ = Type::make_error_type(); {
this->report_error(_("constant refers to itself"));
this->type_ = Type::make_error_type();
}
return; return;
} }
}
// Check types of a const reference.
void
Const_expression::do_check_types(Gogo*)
{
if (this->type_ != NULL && this->type_->is_error_type())
return;
this->check_for_init_loop();
if (this->type_ == NULL || this->type_->is_abstract()) if (this->type_ == NULL || this->type_->is_abstract())
return; return;
...@@ -2754,9 +2784,19 @@ Find_named_object::expression(Expression** pexpr) ...@@ -2754,9 +2784,19 @@ Find_named_object::expression(Expression** pexpr)
switch ((*pexpr)->classification()) switch ((*pexpr)->classification())
{ {
case Expression::EXPRESSION_CONST_REFERENCE: case Expression::EXPRESSION_CONST_REFERENCE:
if (static_cast<Const_expression*>(*pexpr)->named_object() == this->no_) {
break; Const_expression* ce = static_cast<Const_expression*>(*pexpr);
return TRAVERSE_CONTINUE; if (ce->named_object() == this->no_)
break;
// We need to check a constant initializer explicitly, as
// loops here will not be caught by the loop checking for
// variable initializers.
ce->check_for_init_loop();
return TRAVERSE_CONTINUE;
}
case Expression::EXPRESSION_VAR_REFERENCE: case Expression::EXPRESSION_VAR_REFERENCE:
if ((*pexpr)->var_expression()->named_object() == this->no_) if ((*pexpr)->var_expression()->named_object() == this->no_)
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment