Re: [patch] Fix crash on function returning variable-sized array

2012-01-11 Thread Eric Botcazou
 The new void *data pointer could use a comment on what it is and how it's
 used.

Yes; as a matter of fact, it needs to be documented for mostly_copy_tree_r 
first, and probably just referred to for copy_if_shared_r and copy_if_shared.

-- 
Eric Botcazou


[patch] Fix crash on function returning variable-sized array

2012-01-10 Thread Eric Botcazou
This is a regression present on the mainline.  The compiler crashes during the 
function unnesting pass because of an out-of-context temporary, but the root 
cause of the problem is incorrect sharing of a tree node.  The problem has 
probably been latent since gimplification was devised: while the DECL_SIZE and 
DECL_SIZE_UNIT trees of VAR_DECLs are visited by walk_tree (via BIND_EXPR), 
this isn't the case for RESULT_DECL.  As a result, if it has variable size 
(this now happens much more often in Ada), its subtrees aren't unshared and 
this is problematic.

The proposed fix is to unshared them manually in unshare_body.  To implement 
this, the awkward interface to gimplify_body/unshare_body, where you pass both 
a pointer to the body and the decl itself and later need to test whether they 
are related, is simplified as the 2 calls of gimplify_body are idiomatic.

Tested on i586-suse-linux, OK for the mainline?


2012-01-10  Eric Botcazou  ebotca...@adacore.com

* gimple.h (gimplify_body): Remove first argument.
* gimplify.c (copy_if_shared): Add DATA argument.  Do not create the
pointer set here, instead just pass DATA to walk_tree.
(unshare_body): Remove BODY_P argument and adjust.  Create the pointer
set here and invoke copy_if_shared on the size trees of DECL_RESULT.
(unvisit_body): Likewise, but with unmark_visited.
(gimplify_body): Remove BODY_P argument and adjust.
(gimplify_function_tree): Adjust call to gimplify_body.
* omp-low.c (finalize_task_copyfn): Likewise.


2012-01-10  Eric Botcazou  ebotca...@adacore.com

* gnat.dg/array19.ad[sb]: New test.


-- 
Eric Botcazou
Index: gimple.h
===
--- gimple.h	(revision 182780)
+++ gimple.h	(working copy)
@@ -1099,7 +1099,7 @@ extern enum gimplify_status gimplify_exp
 extern void gimplify_type_sizes (tree, gimple_seq *);
 extern void gimplify_one_sizepos (tree *, gimple_seq *);
 extern bool gimplify_stmt (tree *, gimple_seq *);
-extern gimple gimplify_body (tree *, tree, bool);
+extern gimple gimplify_body (tree, bool);
 extern void push_gimplify_context (struct gimplify_ctx *);
 extern void pop_gimplify_context (gimple);
 extern void gimplify_and_add (tree, gimple_seq *);
Index: gimplify.c
===
--- gimplify.c	(revision 182780)
+++ gimplify.c	(working copy)
@@ -951,31 +951,33 @@ copy_if_shared_r (tree *tp, int *walk_su
 /* Unshare most of the shared trees rooted at *TP. */
 
 static inline void
-copy_if_shared (tree *tp)
+copy_if_shared (tree *tp, void *data)
 {
-  /* If the language requires deep unsharing, we need a pointer set to make
- sure we don't repeatedly unshare subtrees of unshareable nodes.  */
-  struct pointer_set_t *visited
-= lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
-  walk_tree (tp, copy_if_shared_r, visited, NULL);
-  if (visited)
-pointer_set_destroy (visited);
+  walk_tree (tp, copy_if_shared_r, data, NULL);
 }
 
-/* Unshare all the trees in BODY_P, a pointer into the body of FNDECL, and the
-   bodies of any nested functions if we are unsharing the entire body of
-   FNDECL.  */
+/* Unshare all the trees in the body of FNDECL, as well as in the bodies of
+   any nested functions.  */
 
 static void
-unshare_body (tree *body_p, tree fndecl)
+unshare_body (tree fndecl)
 {
   struct cgraph_node *cgn = cgraph_get_node (fndecl);
+  /* If the language requires deep unsharing, we need a pointer set to make
+ sure we don't repeatedly unshare subtrees of unshareable nodes.  */
+  struct pointer_set_t *visited
+= lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
 
-  copy_if_shared (body_p);
+  copy_if_shared (DECL_SAVED_TREE (fndecl), visited);
+  copy_if_shared (DECL_SIZE (DECL_RESULT (fndecl)), visited);
+  copy_if_shared (DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
+
+  if (visited)
+pointer_set_destroy (visited);
 
-  if (cgn  body_p == DECL_SAVED_TREE (fndecl))
+  if (cgn)
 for (cgn = cgn-nested; cgn; cgn = cgn-next_nested)
-  unshare_body (DECL_SAVED_TREE (cgn-decl), cgn-decl);
+  unshare_body (cgn-decl);
 }
 
 /* Callback for walk_tree to unmark the visited trees rooted at *TP.
@@ -1008,15 +1010,17 @@ unmark_visited (tree *tp)
 /* Likewise, but mark all trees as not visited.  */
 
 static void
-unvisit_body (tree *body_p, tree fndecl)
+unvisit_body (tree fndecl)
 {
   struct cgraph_node *cgn = cgraph_get_node (fndecl);
 
-  unmark_visited (body_p);
+  unmark_visited (DECL_SAVED_TREE (fndecl));
+  unmark_visited (DECL_SIZE (DECL_RESULT (fndecl)));
+  unmark_visited (DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
 
-  if (cgn  body_p == DECL_SAVED_TREE (fndecl))
+  if (cgn)
 for (cgn = cgn-nested; cgn; cgn = cgn-next_nested)
-  unvisit_body (DECL_SAVED_TREE (cgn-decl), cgn-decl);
+  unvisit_body (cgn-decl);
 }
 
 /* Unconditionally make an unshared copy of EXPR.  

Re: [patch] Fix crash on function returning variable-sized array

2012-01-10 Thread Richard Henderson
On 01/11/2012 06:28 AM, Eric Botcazou wrote:
 2012-01-10  Eric Botcazou  ebotca...@adacore.com
 
   * gimple.h (gimplify_body): Remove first argument.
   * gimplify.c (copy_if_shared): Add DATA argument.  Do not create the
   pointer set here, instead just pass DATA to walk_tree.
   (unshare_body): Remove BODY_P argument and adjust.  Create the pointer
   set here and invoke copy_if_shared on the size trees of DECL_RESULT.
   (unvisit_body): Likewise, but with unmark_visited.
   (gimplify_body): Remove BODY_P argument and adjust.
   (gimplify_function_tree): Adjust call to gimplify_body.
   * omp-low.c (finalize_task_copyfn): Likewise.

Ok.

Nice cleanup.


r~


Re: [patch] Fix crash on function returning variable-sized array

2012-01-10 Thread Geert Bosch

On Jan 10, 2012, at 14:28, Eric Botcazou wrote:

 2012-01-10  Eric Botcazou  ebotca...@adacore.com
 
   * gimple.h (gimplify_body): Remove first argument.
   * gimplify.c (copy_if_shared): Add DATA argument.  Do not create the
   pointer set here, instead just pass DATA to walk_tree.

The new void *data pointer could use a comment on what it is and how it's used.

  -Geert