]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Don't crash on recursive consts.
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 16 Dec 2010 04:47:18 +0000 (04:47 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 16 Dec 2010 04:47:18 +0000 (04:47 +0000)
From-SVN: r167899

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc

index 8187e6da415fc083937a669fdf18a12f79e76326..553e6d662c31531504b79a445641784114962f2e 100644 (file)
@@ -2292,7 +2292,7 @@ class Const_expression : public Expression
  public:
   Const_expression(Named_object* constant, source_location location)
     : Expression(EXPRESSION_CONST_REFERENCE, location),
-      constant_(constant), type_(NULL)
+      constant_(constant), type_(NULL), seen_(false)
   { }
 
   const std::string&
@@ -2350,6 +2350,9 @@ class Const_expression : public Expression
   // The type of this reference.  This is used if the constant has an
   // abstract type.
   Type* type_;
+  // Used to prevent infinite recursion when a constant incorrectly
+  // refers to itself.
+  mutable bool seen_;
 };
 
 // Lower a constant expression.  This is where we convert the
@@ -2387,6 +2390,9 @@ bool
 Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val,
                                            Type** ptype) const
 {
+  if (this->seen_)
+    return false;
+
   Type* ctype;
   if (this->type_ != NULL)
     ctype = this->type_;
@@ -2396,9 +2402,14 @@ Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val,
     return false;
 
   Expression* e = this->constant_->const_value()->expr();
+
+  this->seen_ = true;
+
   Type* t;
   bool r = e->integer_constant_value(iota_is_constant, val, &t);
 
+  this->seen_ = false;
+
   if (r
       && ctype != NULL
       && !Integer_expression::check_constant(val, ctype, this->location()))
@@ -2413,6 +2424,9 @@ Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val,
 bool
 Const_expression::do_float_constant_value(mpfr_t val, Type** ptype) const
 {
+  if (this->seen_)
+    return false;
+
   Type* ctype;
   if (this->type_ != NULL)
     ctype = this->type_;
@@ -2421,9 +2435,14 @@ Const_expression::do_float_constant_value(mpfr_t val, Type** ptype) const
   if (ctype != NULL && ctype->float_type() == NULL)
     return false;
 
+  this->seen_ = true;
+
   Type* t;
   bool r = this->constant_->const_value()->expr()->float_constant_value(val,
                                                                        &t);
+
+  this->seen_ = false;
+
   if (r && ctype != NULL)
     {
       if (!Float_expression::check_constant(val, ctype, this->location()))
@@ -2440,6 +2459,9 @@ bool
 Const_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
                                            Type **ptype) const
 {
+  if (this->seen_)
+    return false;
+
   Type* ctype;
   if (this->type_ != NULL)
     ctype = this->type_;
@@ -2448,10 +2470,15 @@ Const_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
   if (ctype != NULL && ctype->complex_type() == NULL)
     return false;
 
+  this->seen_ = true;
+
   Type *t;
   bool r = this->constant_->const_value()->expr()->complex_constant_value(real,
                                                                          imag,
                                                                          &t);
+
+  this->seen_ = false;
+
   if (r && ctype != NULL)
     {
       if (!Complex_expression::check_constant(real, imag, ctype,
@@ -2470,13 +2497,32 @@ Const_expression::do_type()
 {
   if (this->type_ != NULL)
     return this->type_;
+
+  if (this->seen_)
+    {
+      this->report_error(_("constant refers to itself"));
+      this->type_ = Type::make_error_type();
+      return this->type_;
+    }
+
+  this->seen_ = true;
+
   Named_constant* nc = this->constant_->const_value();
   Type* ret = nc->type();
+
   if (ret != NULL)
-    return ret;
+    {
+      this->seen_ = false;
+      return ret;
+    }
+
   // During parsing, a named constant may have a NULL type, but we
   // must not return a NULL type here.
-  return nc->expr()->type();
+  ret = nc->expr()->type();
+
+  this->seen_ = false;
+
+  return ret;
 }
 
 // Set the type of the const reference.
index b27871132e33b7ac0ef7d83bf3776c3fa7659cbc..29462998836d3065b0b065437974bbe646e57059 100644 (file)
@@ -1472,7 +1472,8 @@ Check_types_traverse::constant(Named_object* named_object, bool)
       && !ctype->is_boolean_type()
       && !ctype->is_string_type())
     {
-      error_at(constant->location(), "invalid constant type");
+      if (!ctype->is_error_type())
+       error_at(constant->location(), "invalid constant type");
       constant->set_error();
     }
   else if (!constant->expr()->is_constant())