Patchwork [gccgo] More recursive type patches

login
register
mail settings
Submitter Ian Taylor
Date Sept. 8, 2010, 6:11 p.m.
Message ID <mcr4oe0hzqa.fsf@google.com>
Download mbox | patch
Permalink /patch/64190/
State New
Headers show

Comments

Ian Taylor - Sept. 8, 2010, 6:11 p.m.
Here are some more patches for recursive types in gccgo.  For a
recursive pointer or function type, the recursion just uses
ptr_type_node.  This patch checks for that when doing a pointer
indirection or function call, and insert a cast as needed so that
GENERIC/GIMPLE see the right type.  This patch also makes sure that we
do not record the recursively found ptr_type_node when handling a
forwarding type.  Committed to gccgo branch.

Ian

Patch

diff -r 0442a71e2d75 go/expressions.cc
--- a/go/expressions.cc	Tue Sep 07 17:12:33 2010 -0700
+++ b/go/expressions.cc	Wed Sep 08 11:08:53 2010 -0700
@@ -4002,6 +4002,15 @@ 
 				   expr);
 	  }
 
+	// If the type of EXPR is a recursive pointer type, then we
+	// need to insert a cast before indirecting.
+	if (TREE_TYPE(TREE_TYPE(expr)) == ptr_type_node)
+	  {
+	    Type* pt = this->expr_->type()->points_to();
+	    tree ind = pt->get_tree(context->gogo());
+	    expr = fold_convert_loc(loc, build_pointer_type(ind), expr);
+	  }
+
 	return build_fold_indirect_ref_loc(loc, expr);
       }
 
@@ -8382,6 +8391,16 @@ 
 	CALL_EXPR_STATIC_CHAIN(ret) = closure_tree;
     }
 
+  // If this is a recursive function type which returns itself, as in
+  //   type F func() F
+  // we have used ptr_type_node for the return type.  Add a cast here
+  // to the correct type.
+  if (TREE_TYPE(ret) == ptr_type_node)
+    {
+      tree t = this->type()->get_tree(gogo);
+      ret = fold_convert_loc(location, t, ret);
+    }
+
   if (excess_type != NULL_TREE)
     {
       // Calling convert here can undo our excess precision change.
diff -r 0442a71e2d75 go/types.cc
--- a/go/types.cc	Tue Sep 07 17:12:33 2010 -0700
+++ b/go/types.cc	Wed Sep 08 11:08:53 2010 -0700
@@ -781,9 +781,19 @@ 
 {
   if (this->tree_ == NULL)
     {
-      this->tree_ = this->do_get_tree(gogo);
-      go_preserve_from_gc(this->tree_);
-    }
+      tree t = this->do_get_tree(gogo);
+
+      // For a recursive function or pointer type, we will temporarily
+      // return ptr_type_node during the recursion.  We don't want to
+      // record that for a forwarding type, as it may confuse us
+      // later.
+      if (t == ptr_type_node && this->forward_declaration_type() != NULL)
+	return t;
+
+      this->tree_ = t;
+      go_preserve_from_gc(t);
+    }
+
   return this->tree_;
 }