@@ -2348,6 +2348,10 @@
name() const
{ return this->constant_->name(); }
+ // Check that the initializer does not refer to the constant itself.
+ void
+ check_for_init_loop();
+
protected:
Expression*
do_lower(Gogo*, Named_object*, int);
@@ -2610,24 +2614,50 @@
}
}
-// Check types of a const reference.
+// Check for a loop in which the initializer of a constant refers to
+// the constant itself.
void
-Const_expression::do_check_types(Gogo*)
+Const_expression::check_for_init_loop()
{
if (this->type_ != NULL && this->type_->is_error_type())
return;
- Expression* init = this->constant_->const_value()->expr();
- Find_named_object find_named_object(this->constant_);
- Expression::traverse(&init, &find_named_object);
- if (find_named_object.found())
+ if (this->seen_)
{
this->report_error(_("constant refers to itself"));
this->type_ = Type::make_error_type();
return;
}
+ Expression* init = this->constant_->const_value()->expr();
+ Find_named_object find_named_object(this->constant_);
+
+ this->seen_ = true;
+ Expression::traverse(&init, &find_named_object);
+ this->seen_ = false;
+
+ if (find_named_object.found())
+ {
+ if (this->type_ == NULL || !this->type_->is_error_type())
+ {
+ this->report_error(_("constant refers to itself"));
+ this->type_ = Type::make_error_type();
+ }
+ 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())
return;
@@ -2754,9 +2784,19 @@
switch ((*pexpr)->classification())
{
case Expression::EXPRESSION_CONST_REFERENCE:
- if (static_cast<Const_expression*>(*pexpr)->named_object() == this->no_)
- break;
- return TRAVERSE_CONTINUE;
+ {
+ Const_expression* ce = static_cast<Const_expression*>(*pexpr);
+ 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:
if ((*pexpr)->var_expression()->named_object() == this->no_)
break;