Fix struct with array of struct with field that points to first struct.
authorIan Lance Taylor <ian@gcc.gnu.org>
Sat, 19 Feb 2011 03:23:22 +0000 (03:23 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 19 Feb 2011 03:23:22 +0000 (03:23 +0000)
Don't crash converting an untyped complex constant to an integer type.
Don't crash on unsafe.Sizeof of erroneous type.
Don't crash on method expression of erroneous type.
Don't crash when sink and global var are initialized from type guard.
Don't crash initializing erroneous slice.
Don't crash on erroneous method of type seen before definition.

From-SVN: r170301

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

index 940d418bcaf8427ae4046df96051933d8b9f0f34..e1d59bef798bb132a5fb25a15a8e0111ab173be8 100644 (file)
@@ -716,7 +716,11 @@ Expression::float_constant_tree(mpfr_t val, tree type)
 tree
 Expression::complex_constant_tree(mpfr_t real, mpfr_t imag, tree type)
 {
-  if (TREE_CODE(type) == COMPLEX_TYPE)
+  if (type == error_mark_node)
+    return error_mark_node;
+  else if (TREE_CODE(type) == INTEGER_TYPE || TREE_CODE(type) == REAL_TYPE)
+    return Expression::float_constant_tree(real, type);
+  else if (TREE_CODE(type) == COMPLEX_TYPE)
     {
       REAL_VALUE_TYPE r1;
       real_from_mpfr(&r1, real, TREE_TYPE(type), GMP_RNDN);
@@ -6960,6 +6964,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
       if (arg_type->is_abstract())
        return false;
       tree arg_type_tree = arg_type->get_tree(this->gogo_);
+      if (arg_type_tree == error_mark_node)
+       return false;
       unsigned long val_long;
       if (this->code_ == BUILTIN_SIZEOF)
        {
@@ -10325,7 +10331,11 @@ Selector_expression::lower_method_expression(Gogo* gogo)
   gcc_assert(vno != NULL);
   Expression* ve = Expression::make_var_reference(vno, location);
   Expression* bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
-  gcc_assert(bm != NULL && !bm->is_error_expression());
+
+  // Even though we found the method above, if it has an error type we
+  // may see an error here.
+  if (bm->is_error_expression())
+    return bm;
 
   Expression_list* args;
   if (method_parameters == NULL)
index 45ff33df3d8406bba9246beacddd5c34dc1bdd7f..fc8771c639cb22bb6acbfb9b636d166876cd8648 100644 (file)
@@ -1865,6 +1865,8 @@ Named_object*
 Parse::create_dummy_global(Type* type, Expression* init,
                           source_location location)
 {
+  if (type == NULL && init == NULL)
+    type = Type::lookup_bool_type();
   Variable* var = new Variable(type, init, true, false, false, location);
   static int count;
   char buf[30];
index 0d17ab4773fb5c9338adc8d6b35706b7a6d31101..2d7312b60940ad7e87c0e1e94e95c1b08ec65055 100644 (file)
@@ -4473,6 +4473,8 @@ Array_type::fill_in_tree(Gogo* gogo, tree struct_type)
   gcc_assert(this->length_ == NULL);
 
   tree element_type_tree = this->element_type_->get_tree(gogo);
+  if (element_type_tree == error_mark_node)
+    return error_mark_node;
   tree field = TYPE_FIELDS(struct_type);
   gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__values") == 0);
   gcc_assert(POINTER_TYPE_P(TREE_TYPE(field))
@@ -6923,12 +6925,12 @@ Named_type::do_verify()
     }
 
   // If this is a struct, then if any of the fields of the struct
-  // themselves have struct type, then this struct must be converted
-  // to the backend representation before the field's type is
-  // converted.  That may seem backward, but it works because if the
-  // field's type refers to this one, e.g., via a pointer, then the
-  // conversion process will pick up the half-built struct and do the
-  // right thing.
+  // themselves have struct type, or array of struct type, then this
+  // struct must be converted to the backend representation before the
+  // field's type is converted.  That may seem backward, but it works
+  // because if the field's type refers to this one, e.g., via a
+  // pointer, then the conversion process will pick up the half-built
+  // struct and do the right thing.
   if (this->struct_type() != NULL)
     {
       const Struct_field_list* fields = this->struct_type()->fields();
@@ -6939,6 +6941,16 @@ Named_type::do_verify()
          Struct_type* st = p->type()->struct_type();
          if (st != NULL)
            st->add_prerequisite(this);
+         else
+           {
+             Array_type* at = p->type()->array_type();
+             if (at != NULL && !at->is_open_array_type())
+               {
+                 st = at->element_type()->struct_type();
+                 if (st != NULL)
+                   st->add_prerequisite(this);
+               }
+           }
        }
     }
 
@@ -7488,7 +7500,13 @@ Type::add_interface_methods_for_type(const Type* type,
        ++pm)
     {
       Function_type* fntype = pm->type()->function_type();
-      gcc_assert(fntype != NULL && !fntype->is_method());
+      if (fntype == NULL)
+       {
+         // This is an error, but it should be reported elsewhere
+         // when we look at the methods for IT.
+         continue;
+       }
+      gcc_assert(!fntype->is_method());
       fntype = fntype->copy_with_receiver(const_cast<Type*>(type));
       Method* m = new Interface_method(pm->name(), pm->location(), fntype,
                                       field_indexes, depth);