This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: Fix various crashes


This patch fixes several different crashes.  I wrote the patch on the
plane so it combines several fixes at once, rather than my usual
practice of committing each fix separately.

  * If a struct has a field whose type is an array of struct, and the
    latter struct has a field whose type is a pointer to the first
    struct, then if the structs were converted to GENERIC in the wrong
    order the size of the array might be computed using an incomplete
    struct.  I fixed this using the existing prerequisite mechanism.

  * Avoid a crash if an untyped complex constant is converted to an
    integer or floating point type.

  * Avoid a crash when using unsafe.Sizeof with an erroneous type.

  * Avoid a crash when using a method expression of an erroneous type,
    in which the method might appear in the list of all methods of the
    type but might itself be erroneous.

  * Avoid a crash when a sink variable and a global variable are
    initialized from a type guard, when there is no explicitly specified
    type for the global variable.

  * Avoid a crash when initializing a value for a slice whose element
    type is erroneous.

  * Avoid crashing when an erroneous method is defined for a type before
    the actual definition of the type is seen.

Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

diff -r 8c0f3339bc97 go/expressions.cc
--- a/go/expressions.cc	Tue Feb 15 14:35:42 2011 -0800
+++ b/go/expressions.cc	Fri Feb 18 19:01:03 2011 -0800
@@ -716,7 +716,11 @@
 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 @@
       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 @@
   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)
diff -r 8c0f3339bc97 go/parse.cc
--- a/go/parse.cc	Tue Feb 15 14:35:42 2011 -0800
+++ b/go/parse.cc	Fri Feb 18 19:01:03 2011 -0800
@@ -1865,6 +1865,8 @@
 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];
diff -r 8c0f3339bc97 go/types.cc
--- a/go/types.cc	Tue Feb 15 14:35:42 2011 -0800
+++ b/go/types.cc	Fri Feb 18 19:01:03 2011 -0800
@@ -4473,6 +4473,8 @@
   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 @@
     }
 
   // 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 @@
 	  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 @@
        ++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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]