Go patch committed: Use VIEW_CONVERT_EXPR where needed

Ian Lance Taylor iant@golang.org
Wed Jan 31 08:55:00 GMT 2018


This patch to the Go frontend's GCC interface uses VIEW_CONVERT_EXPR
where needed.  The code was using fold_convert_loc in
constructor_expression and temporary_variable, which almost always
worked.  However, it failed in https://golang.org/issue/23606.  This
patch fixes the problem.  Bootstrapped and ran Go testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian


2018-01-30  Ian Lance Taylor  <iant@golang.org>

* go-gcc.cc (Gcc_backend::convert_tree): New private method.
(Gcc_backend::constructor_expression): Call it.
(Gcc_backend::assignment_statement): Likewise.
(Gcc_backend::temporary_variable): Likewise.
-------------- next part --------------
Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 256593)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -541,6 +541,9 @@ class Gcc_backend : public Backend
   tree
   non_zero_size_type(tree);
 
+  tree
+  convert_tree(tree, tree, Location);
+
 private:
   void
   define_builtin(built_in_function bcode, const char* name, const char* libname,
@@ -1785,8 +1788,7 @@ Gcc_backend::constructor_expression(Btyp
       constructor_elt empty = {NULL, NULL};
       constructor_elt* elt = init->quick_push(empty);
       elt->index = field;
-      elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
-                                    val);
+      elt->value = this->convert_tree(TREE_TYPE(field), val, location);
       if (!TREE_CONSTANT(elt->value))
 	is_constant = false;
     }
@@ -2055,29 +2057,7 @@ Gcc_backend::assignment_statement(Bfunct
     return this->compound_statement(this->expression_statement(bfn, lhs),
 				    this->expression_statement(bfn, rhs));
 
-  // Sometimes the same unnamed Go type can be created multiple times
-  // and thus have multiple tree representations.  Make sure this does
-  // not confuse the middle-end.
-  if (TREE_TYPE(lhs_tree) != TREE_TYPE(rhs_tree))
-    {
-      tree lhs_type_tree = TREE_TYPE(lhs_tree);
-      gcc_assert(TREE_CODE(lhs_type_tree) == TREE_CODE(TREE_TYPE(rhs_tree)));
-      if (POINTER_TYPE_P(lhs_type_tree)
-	  || INTEGRAL_TYPE_P(lhs_type_tree)
-	  || SCALAR_FLOAT_TYPE_P(lhs_type_tree)
-	  || COMPLEX_FLOAT_TYPE_P(lhs_type_tree))
-	rhs_tree = fold_convert_loc(location.gcc_location(), lhs_type_tree,
-				    rhs_tree);
-      else if (TREE_CODE(lhs_type_tree) == RECORD_TYPE
-	       || TREE_CODE(lhs_type_tree) == ARRAY_TYPE)
-	{
-	  gcc_assert(int_size_in_bytes(lhs_type_tree)
-		     == int_size_in_bytes(TREE_TYPE(rhs_tree)));
-	  rhs_tree = fold_build1_loc(location.gcc_location(),
-				     VIEW_CONVERT_EXPR,
-				     lhs_type_tree, rhs_tree);
-	}
-    }
+  rhs_tree = this->convert_tree(TREE_TYPE(lhs_tree), rhs_tree, location);
 
   return this->make_statement(fold_build2_loc(location.gcc_location(),
                                               MODIFY_EXPR,
@@ -2507,6 +2487,43 @@ Gcc_backend::non_zero_size_type(tree typ
   gcc_unreachable();
 }
 
+// Convert EXPR_TREE to TYPE_TREE.  Sometimes the same unnamed Go type
+// can be created multiple times and thus have multiple tree
+// representations.  Make sure this does not confuse the middle-end.
+
+tree
+Gcc_backend::convert_tree(tree type_tree, tree expr_tree, Location location)
+{
+  if (type_tree == TREE_TYPE(expr_tree))
+    return expr_tree;
+
+  if (type_tree == error_mark_node
+      || expr_tree == error_mark_node
+      || TREE_TYPE(expr_tree) == error_mark_node)
+    return error_mark_node;
+
+  gcc_assert(TREE_CODE(type_tree) == TREE_CODE(TREE_TYPE(expr_tree)));
+  if (POINTER_TYPE_P(type_tree)
+      || INTEGRAL_TYPE_P(type_tree)
+      || SCALAR_FLOAT_TYPE_P(type_tree)
+      || COMPLEX_FLOAT_TYPE_P(type_tree))
+    return fold_convert_loc(location.gcc_location(), type_tree, expr_tree);
+  else if (TREE_CODE(type_tree) == RECORD_TYPE
+	   || TREE_CODE(type_tree) == ARRAY_TYPE)
+    {
+      gcc_assert(int_size_in_bytes(type_tree)
+		 == int_size_in_bytes(TREE_TYPE(expr_tree)));
+      if (TYPE_MAIN_VARIANT(type_tree)
+	  == TYPE_MAIN_VARIANT(TREE_TYPE(expr_tree)))
+	return fold_build1_loc(location.gcc_location(), NOP_EXPR,
+			       type_tree, expr_tree);
+      return fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR,
+			     type_tree, expr_tree);
+    }
+
+  gcc_unreachable();
+}
+
 // Make a global variable.
 
 Bvariable*
@@ -2717,8 +2734,7 @@ Gcc_backend::temporary_variable(Bfunctio
     }
 
   if (this->type_size(btype) != 0 && init_tree != NULL_TREE)
-    DECL_INITIAL(var) = fold_convert_loc(location.gcc_location(), type_tree,
-                                         init_tree);
+    DECL_INITIAL(var) = this->convert_tree(type_tree, init_tree, location);
 
   if (is_address_taken)
     TREE_ADDRESSABLE(var) = 1;


More information about the Gcc-patches mailing list