Patchwork Go patch committed: Don't crash on undefined anonymous field

login
register
mail settings
Submitter Ian Taylor
Date Dec. 15, 2010, 6:16 a.m.
Message ID <mcr39pz5zne.fsf@google.com>
Download mbox | patch
Permalink /patch/75607/
State New
Headers show

Comments

Ian Taylor - Dec. 15, 2010, 6:16 a.m.
This patch fixes the Go frontend to not crash when a struct uses an
anonymous field whose type is never defined.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

Patch

diff -r 44d82240e42d go/types.cc
--- a/go/types.cc	Tue Dec 14 17:44:29 2010 -0800
+++ b/go/types.cc	Tue Dec 14 22:13:21 2010 -0800
@@ -3375,6 +3375,7 @@ 
   Struct_field_list* fields = this->fields_;
   if (fields == NULL)
     return true;
+  bool ret = true;
   for (Struct_field_list::iterator p = fields->begin();
        p != fields->end();
        ++p)
@@ -3384,7 +3385,7 @@ 
 	{
 	  error_at(p->location(), "struct field type is incomplete");
 	  p->set_type(Type::make_error_type());
-	  return false;
+	  ret = false;
 	}
       else if (p->is_anonymous())
 	{
@@ -3396,7 +3397,7 @@ 
 	    }
 	}
     }
-  return true;
+  return ret;
 }
 
 // Whether this contains a pointer.
@@ -3758,13 +3759,16 @@ 
   bool any_fields_set = false;
   VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc,
 					    this->fields_->size());
-  Struct_field_list::const_iterator p = this->fields_->begin();
-  for (tree field = TYPE_FIELDS(type_tree);
-       field != NULL_TREE;
-       field = DECL_CHAIN(field), ++p)
-    {
-      gcc_assert(p != this->fields_->end());
+
+  tree field = TYPE_FIELDS(type_tree);
+  for (Struct_field_list::const_iterator p = this->fields_->begin();
+       p != this->fields_->end();
+       ++p, field = DECL_CHAIN(field))
+    {
       tree value = p->type()->get_init_tree(gogo, is_clear);
+      if (value == error_mark_node)
+	return error_mark_node;
+      gcc_assert(field != NULL_TREE);
       if (value != NULL)
 	{
 	  constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
@@ -3775,7 +3779,7 @@ 
 	    is_constant = false;
 	}
     }
-  gcc_assert(p == this->fields_->end());
+  gcc_assert(field == NULL_TREE);
 
   if (!any_fields_set)
     {
@@ -6891,7 +6895,9 @@ 
 	return this->named_tree_;
       t = make_node(RECORD_TYPE);
       this->named_tree_ = t;
-      this->type_->struct_type()->fill_in_tree(gogo, t);
+      t = this->type_->struct_type()->fill_in_tree(gogo, t);
+      if (t == error_mark_node)
+	return error_mark_node;
       break;
 
     case TYPE_ARRAY:
@@ -7728,6 +7734,9 @@ 
       if (!pf->is_anonymous())
 	continue;
 
+      if (pf->type()->is_error_type() || pf->type()->is_undefined())
+	continue;
+
       Named_type* fnt = pf->type()->deref()->named_type();
       gcc_assert(fnt != NULL);
 
@@ -7845,7 +7854,8 @@ 
        pf != fields->end();
        ++pf)
     {
-      if (pf->is_anonymous())
+      if (pf->is_anonymous()
+	  && (!pf->type()->is_error_type() && !pf->type()->is_undefined()))
 	{
 	  Named_type* subtype = pf->type()->deref()->named_type();
 	  gcc_assert(subtype != NULL);