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]

[PATCH] Fix PR60746


Code generation without 'cfun' is tricky (and should be generally
avoided).  The following patch fixes one case that clearly has
zero test coverage until now as the various uncovered issues show ;)

Bootstrap & regtest running on x86_64-unknown-linux-gnu, will apply
to trunk and the tree-ssanames.c hunk to the branch(es).

Richard.

2014-04-04  Richard Biener  <rguenther@suse.de>

	PR ipa/60746
	* tree-ssanames.c (make_ssa_name_fn): Fix assert.
	* gimple.c (gimple_set_bb): Avoid ICEing for NULL cfun for
	non-GIMPLE_LABELs.
	* gimplify.h (gimple_add_tmp_var_fn): Declare.
	* gimplify.c (gimple_add_tmp_var_fn): New function.
	* gimple-expr.h (create_tmp_reg_fn): Declare.
	* gimple-expr.c (create_tmp_reg_fn): New function.
	* gimple-low.c (record_vars_into): Don't change cfun.
	* cgraph.c (cgraph_redirect_edge_call_stmt_to_callee): Fix
	code generation without cfun.

	* g++.dg/torture/pr60746.C: New testcase.

Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c	(revision 209059)
+++ gcc/tree-ssanames.c	(working copy)
@@ -144,7 +144,7 @@ make_ssa_name_fn (struct function *fn, t
 
       /* The node was cleared out when we put it on the free list, so
 	 there is no need to do so again here.  */
-      gcc_assert (ssa_name (SSA_NAME_VERSION (t)) == NULL);
+      gcc_assert ((*SSANAMES (fn))[SSA_NAME_VERSION (t)] == NULL);
       (*SSANAMES (fn))[SSA_NAME_VERSION (t)] = t;
     }
   else
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c	(revision 209059)
+++ gcc/gimple.c	(working copy)
@@ -1464,9 +1464,12 @@ gimple_set_bb (gimple stmt, basic_block
 {
   stmt->bb = bb;
 
+  if (gimple_code (stmt) != GIMPLE_LABEL)
+    return;
+
   /* If the statement is a label, add the label to block-to-labels map
      so that we can speed up edge creation for GIMPLE_GOTOs.  */
-  if (cfun->cfg && gimple_code (stmt) == GIMPLE_LABEL)
+  if (cfun->cfg)
     {
       tree t;
       int uid;
Index: gcc/gimplify.h
===================================================================
--- gcc/gimplify.h	(revision 209059)
+++ gcc/gimplify.h	(working copy)
@@ -60,6 +60,7 @@ extern tree get_formal_tmp_var (tree, gi
 extern tree get_initialized_tmp_var (tree, gimple_seq *, gimple_seq *);
 extern void declare_vars (tree, gimple, bool);
 extern void gimple_add_tmp_var (tree);
+extern void gimple_add_tmp_var_fn (struct function *, tree);
 extern tree unshare_expr (tree);
 extern tree unshare_expr_without_location (tree);
 extern tree voidify_wrapper_expr (tree, tree);
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(revision 209059)
+++ gcc/gimplify.c	(working copy)
@@ -627,6 +627,26 @@ force_constant_size (tree var)
 /* Push the temporary variable TMP into the current binding.  */
 
 void
+gimple_add_tmp_var_fn (struct function *fn, tree tmp)
+{
+  gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp)
+	      && !gimplify_ctxp);
+
+  /* Later processing assumes that the object size is constant, which might
+     not be true at this point.  Force the use of a constant upper bound in
+     this case.  */
+  if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (tmp)))
+    force_constant_size (tmp);
+
+  DECL_CONTEXT (tmp) = fn->decl;
+  DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
+
+  record_vars_into (tmp, fn->decl);
+}
+
+/* Push the temporary variable TMP into the current binding.  */
+
+void
 gimple_add_tmp_var (tree tmp)
 {
   gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
Index: gcc/gimple-expr.h
===================================================================
--- gcc/gimple-expr.h	(revision 209059)
+++ gcc/gimple-expr.h	(working copy)
@@ -33,6 +33,7 @@ extern tree create_tmp_var_name (const c
 extern tree create_tmp_var_raw (tree, const char *);
 extern tree create_tmp_var (tree, const char *);
 extern tree create_tmp_reg (tree, const char *);
+extern tree create_tmp_reg_fn (struct function *, tree, const char *);
 
 
 extern void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *,
Index: gcc/gimple-expr.c
===================================================================
--- gcc/gimple-expr.c	(revision 209059)
+++ gcc/gimple-expr.c	(working copy)
@@ -527,6 +527,24 @@ create_tmp_reg (tree type, const char *p
   return tmp;
 }
 
+/* Create a new temporary variable declaration of type TYPE by calling
+   create_tmp_var and if TYPE is a vector or a complex number, mark the new
+   temporary as gimple register.  */
+
+tree
+create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
+{
+  tree tmp;
+
+  tmp = create_tmp_var_raw (type, prefix);
+  gimple_add_tmp_var_fn (fn, tmp);
+  if (TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
+
+  return tmp;
+}
+
 
 /* ----- Expression related -----  */
 
Index: gcc/gimple-low.c
===================================================================
--- gcc/gimple-low.c	(revision 209059)
+++ gcc/gimple-low.c	(working copy)
@@ -841,11 +841,6 @@ lower_builtin_posix_memalign (gimple_stm
 void
 record_vars_into (tree vars, tree fn)
 {
-  bool change_cfun = fn != current_function_decl;
-
-  if (change_cfun)
-    push_cfun (DECL_STRUCT_FUNCTION (fn));
-
   for (; vars; vars = DECL_CHAIN (vars))
     {
       tree var = vars;
@@ -860,11 +855,8 @@ record_vars_into (tree vars, tree fn)
 	continue;
 
       /* Record the variable.  */
-      add_local_decl (cfun, var);
+      add_local_decl (DECL_STRUCT_FUNCTION (fn), var);
     }
-
-  if (change_cfun)
-    pop_cfun ();
 }
 
 
Index: gcc/cgraph.c
===================================================================
--- gcc/cgraph.c	(revision 209059)
+++ gcc/cgraph.c	(working copy)
@@ -1479,13 +1479,14 @@ cgraph_redirect_edge_call_stmt_to_callee
     {
       if (TREE_CODE (lhs) == SSA_NAME)
 	{
+	  tree var = create_tmp_reg_fn (DECL_STRUCT_FUNCTION (e->caller->decl),
+					TREE_TYPE (lhs), NULL);
+	  var = get_or_create_ssa_default_def
+		  (DECL_STRUCT_FUNCTION (e->caller->decl), var);
+	  gimple set_stmt = gimple_build_assign (lhs, var);
           gsi = gsi_for_stmt (new_stmt);
-
-	  tree var = create_tmp_var (TREE_TYPE (lhs), NULL);
-	  tree def = get_or_create_ssa_default_def
-		      (DECL_STRUCT_FUNCTION (e->caller->decl), var);
-	  gimple set_stmt = gimple_build_assign (lhs, def);
-	  gsi_insert_before (&gsi, set_stmt, GSI_SAME_STMT);
+	  gsi_insert_before_without_update (&gsi, set_stmt, GSI_SAME_STMT);
+	  update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), set_stmt);
 	}
       gimple_call_set_lhs (new_stmt, NULL_TREE);
       update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt);
Index: gcc/testsuite/g++.dg/torture/pr60746.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr60746.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr60746.C	(working copy)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+
+class One
+{
+public:
+  virtual unsigned long getSize () const;
+};
+
+class Two
+{
+  virtual int run ();
+};
+
+int
+Two::run ()
+{
+  One list_arry[5][2];
+  int orig = 0;
+  if (list_arry[3][orig].getSize () > 0
+      || list_arry[4][orig].getSize () > 0)
+    {
+    }
+}


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