compiler: Don't crash with self-referential types.
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 1 Dec 2014 01:29:45 +0000 (01:29 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 1 Dec 2014 01:29:45 +0000 (01:29 +0000)
Fixes issue 6637.

From-SVN: r218199

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index dba5ea0f9c94812d80ecc737bcf28581e45ff396..024b2c4b2ee0df932a535d3597fa080ee0a87821 100644 (file)
@@ -8735,7 +8735,11 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
   // Add temporary variables for all arguments that require type
   // conversion.
   Function_type* fntype = this->get_function_type();
-  go_assert(fntype != NULL);
+  if (fntype == NULL)
+    {
+      go_assert(saw_errors());
+      return this;
+    }
   if (this->args_ != NULL && !this->args_->empty()
       && fntype->parameters() != NULL && !fntype->parameters()->empty())
     {
@@ -10901,9 +10905,8 @@ Interface_field_reference_expression::do_traverse(Traverse* traverse)
 // interface.  So introduce a temporary variable if necessary.
 
 Expression*
-Interface_field_reference_expression::do_lower(Gogo*, Named_object*,
-                                              Statement_inserter* inserter,
-                                              int)
+Interface_field_reference_expression::do_flatten(Gogo*, Named_object*,
+                                                Statement_inserter* inserter)
 {
   if (!this->expr_->is_variable())
     {
index b7e1806040d967b59705382a1b844b6a56ae4e25..d96df28bbc13e40a75f543107d212545fd770258 100644 (file)
@@ -2397,7 +2397,7 @@ class Interface_field_reference_expression : public Expression
   do_traverse(Traverse* traverse);
 
   Expression*
-  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
+  do_flatten(Gogo*, Named_object*, Statement_inserter*);
 
   Type*
   do_type();
index c85c72cb91b554a825e92de2280fa7753aa08b6b..7035524033a4b465530aaa855ba3309d16f21a42 100644 (file)
@@ -6361,7 +6361,13 @@ Array_type::do_reflection(Gogo* gogo, std::string* ret) const
       unsigned long val;
       if (!this->length_->numeric_constant_value(&nc)
          || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
-       error_at(this->length_->location(), "invalid array length");
+       {
+         if (!this->issued_length_error_)
+           {
+             error_at(this->length_->location(), "invalid array length");
+             this->issued_length_error_ = true;
+           }
+       }
       else
        {
          char buf[50];
@@ -6488,7 +6494,13 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
       unsigned long val;
       if (!this->length_->numeric_constant_value(&nc)
          || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
-       error_at(this->length_->location(), "invalid array length");
+       {
+         if (!this->issued_length_error_)
+           {
+             error_at(this->length_->location(), "invalid array length");
+             this->issued_length_error_ = true;
+           }
+       }
       else
        {
          char buf[50];
@@ -10221,7 +10233,12 @@ Type*
 Forward_declaration_type::real_type()
 {
   if (this->is_defined())
-    return this->named_object()->type_value();
+    {
+      Named_type* nt = this->named_object()->type_value();
+      if (!nt->is_valid())
+       return Type::make_error_type();
+      return this->named_object()->type_value();
+    }
   else
     {
       this->warn();
@@ -10233,7 +10250,12 @@ const Type*
 Forward_declaration_type::real_type() const
 {
   if (this->is_defined())
-    return this->named_object()->type_value();
+    {
+      const Named_type* nt = this->named_object()->type_value();
+      if (!nt->is_valid())
+       return Type::make_error_type();
+      return this->named_object()->type_value();
+    }
   else
     {
       this->warn();
index 60de22e1fe148818821cc1e3a83e30f95322fbdd..4f000b12717146b1de6f43bb2f7e20f2376deee0 100644 (file)
@@ -2360,7 +2360,8 @@ class Array_type : public Type
  public:
   Array_type(Type* element_type, Expression* length)
     : Type(TYPE_ARRAY),
-      element_type_(element_type), length_(length), blength_(NULL)
+      element_type_(element_type), length_(length), blength_(NULL),
+      issued_length_error_(false)
   { }
 
   // Return the element type.
@@ -2479,6 +2480,9 @@ class Array_type : public Type
   // The backend representation of the length.
   // We only want to compute this once.
   Bexpression* blength_;
+  // Whether or not an invalid length error has been issued for this type,
+  // to avoid knock-on errors.
+  mutable bool issued_length_error_;
 };
 
 // The type of a map.
@@ -2926,6 +2930,11 @@ class Named_type : public Type
   bool
   is_alias() const;
 
+  // Whether this named type is valid.  A recursive named type is invalid.
+  bool
+  is_valid() const
+  { return !this->is_error_; }
+
   // Whether this is a circular type: a pointer or function type that
   // refers to itself, which is not possible in C.
   bool