diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bc8e97a023dff86a0fe7f761f3c1c184b32b0df4..16bcd96fcd92d0ad2036fd69754f79ea04018d9c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2012-01-11 Eric Botcazou <ebotcazou@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-11 Eric Botcazou <ebotcazou@adacore.com> * tree.h (build_function_decl_skip_args): Add boolean parameter. diff --git a/gcc/gimple.h b/gcc/gimple.h index 5283ca2e2d6b809bc85479284ac15bc41d0922e3..ec32f2577a36832702bfb5c3727635851f77153f 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1097,7 +1097,7 @@ extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *, 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 *); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index b3b047a75618bca18859d3128ba6befc6359011f..94b99a1182324a7c538ca1670b101cb75cfe0b16 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -867,9 +867,10 @@ annotate_all_with_location (gimple_seq stmt_p, location_t location) way to go. */ /* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes. - These nodes model computations that should only be done once. If we - were to unshare something like SAVE_EXPR(i++), the gimplification - process would create wrong code. */ + These nodes model computations that must be done once. If we were to + unshare something like SAVE_EXPR(i++), the gimplification process would + create wrong code. However, if DATA is non-null, it must hold a pointer + set that is used to unshare the subtrees of these nodes. */ static tree mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data) @@ -909,9 +910,9 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } -/* Callback for walk_tree to unshare most of the shared trees rooted at - *TP. If *TP has been visited already (i.e., TREE_VISITED (*TP) == 1), - then *TP is deep copied by calling mostly_copy_tree_r. */ +/* Callback for walk_tree to unshare most of the shared trees rooted at *TP. + If *TP has been visited already, then *TP is deeply copied by calling + mostly_copy_tree_r. DATA is passed to mostly_copy_tree_r unmodified. */ static tree copy_if_shared_r (tree *tp, int *walk_subtrees, void *data) @@ -948,34 +949,37 @@ copy_if_shared_r (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } -/* Unshare most of the shared trees rooted at *TP. */ +/* Unshare most of the shared trees rooted at *TP. DATA is passed to the + copy_if_shared_r callback unmodified. */ 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 (cgn && body_p == &DECL_SAVED_TREE (fndecl)) + if (visited) + pointer_set_destroy (visited); + + 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 +1012,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. This is used when using @@ -7938,13 +7944,12 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p) } } -/* Gimplify the body of statements pointed to by BODY_P and return a - GIMPLE_BIND containing the sequence of GIMPLE statements - corresponding to BODY_P. FNDECL is the function decl containing - *BODY_P. */ +/* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node + containing the sequence of corresponding GIMPLE statements. If DO_PARMS + is true, also gimplify the parameters. */ gimple -gimplify_body (tree *body_p, tree fndecl, bool do_parms) +gimplify_body (tree fndecl, bool do_parms) { location_t saved_location = input_location; gimple_seq parm_stmts, seq; @@ -7965,8 +7970,8 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) It would seem we don't have to do this for nested functions because they are supposed to be output and then the outer function gimplified first, but the g++ front end doesn't always do it that way. */ - unshare_body (body_p, fndecl); - unvisit_body (body_p, fndecl); + unshare_body (fndecl); + unvisit_body (fndecl); cgn = cgraph_get_node (fndecl); if (cgn && cgn->origin) @@ -7977,11 +7982,11 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) /* Resolve callee-copies. This has to be done before processing the body so that DECL_VALUE_EXPR gets processed correctly. */ - parm_stmts = (do_parms) ? gimplify_parameters () : NULL; + parm_stmts = do_parms ? gimplify_parameters () : NULL; /* Gimplify the function's body. */ seq = NULL; - gimplify_stmt (body_p, &seq); + gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq); outer_bind = gimple_seq_first_stmt (seq); if (!outer_bind) { @@ -7997,7 +8002,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) else outer_bind = gimple_build_bind (NULL_TREE, seq, NULL); - *body_p = NULL_TREE; + DECL_SAVED_TREE (fndecl) = NULL_TREE; /* If we had callee-copies statements, insert them at the beginning of the function and clear DECL_VALUE_EXPR_P on the parameters. */ @@ -8115,7 +8120,7 @@ gimplify_function_tree (tree fndecl) && !needs_to_live_in_memory (ret)) DECL_GIMPLE_REG_P (ret) = 1; - bind = gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true); + bind = gimplify_body (fndecl, true); /* The tree body of the function is no longer needed, replace it with the new GIMPLE body. */ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 4e1c2badae35738faf55fc631abf952174cea743..8ab689d015271e8cf9ce48339c902679769e1be3 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1248,7 +1248,7 @@ finalize_task_copyfn (gimple task_stmt) old_fn = current_function_decl; push_cfun (child_cfun); current_function_decl = child_fn; - bind = gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false); + bind = gimplify_body (child_fn, false); seq = gimple_seq_alloc (); gimple_seq_add_stmt (&seq, bind); new_seq = maybe_catch_exception (seq); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9724f759a67585ecf55e6eebd614c95ca18b0a35..f49cdd90ed476b7b192d75f16b87d60c67486efc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-01-11 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/array19.ad[sb]: New test. + 2012-01-11 Eric Botcazou <ebotcazou@adacore.com> * gnat.dg/opt23.ad[sb]: New test. diff --git a/gcc/testsuite/gnat.dg/array19.adb b/gcc/testsuite/gnat.dg/array19.adb new file mode 100644 index 0000000000000000000000000000000000000000..56b05d6490b6f20fcc450a67efc282aba1b14880 --- /dev/null +++ b/gcc/testsuite/gnat.dg/array19.adb @@ -0,0 +1,34 @@ +-- { dg-do compile } + +package body Array19 is + + function N return Integer is + begin + return 1; + end; + + type Array_Type is array (1 .. N) of Float; + + type Enum is (One, Two); + + type Rec (D : Enum := Enum'First) is record + case D is + when One => null; + when Two => A : Array_Type; + end case; + end record; + + procedure Proc is + + R : Rec; + + function F return Array_Type is + begin + return (others => 0.0); + end F; + + begin + R.A := F; + end; + +end Array19; diff --git a/gcc/testsuite/gnat.dg/array19.ads b/gcc/testsuite/gnat.dg/array19.ads new file mode 100644 index 0000000000000000000000000000000000000000..48947f590fa6d50d0fa56eb59752c76c4fb2839e --- /dev/null +++ b/gcc/testsuite/gnat.dg/array19.ads @@ -0,0 +1,5 @@ +package Array19 is + + procedure Proc; + +end Array19;