OSDN Git Service

Improve check for const initializer loop.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Jan 2011 16:55:24 +0000 (16:55 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Jan 2011 16:55:24 +0000 (16:55 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@169003 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/expressions.cc

index 5afe163..2171564 100644 (file)
@@ -2348,6 +2348,10 @@ class Const_expression : public Expression
   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,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
-Const_expression::do_check_types(Gogo*)
+Const_expression::check_for_init_loop()
 {
   if (this->type_ != NULL && this->type_->is_error_type())
     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();
   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())
     {
-      this->report_error(_("constant refers to itself"));
-      this->type_ = Type::make_error_type();
+      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 @@ Find_named_object::expression(Expression** pexpr)
   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;