re PR ada/21937 (Member record alignment triggers an ICE)
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 21 Oct 2005 15:46:19 +0000 (15:46 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 21 Oct 2005 15:46:19 +0000 (15:46 +0000)
PR ada/21937
PR ada/22328
PR ada/22381
PR ada/22383
PR ada/22419
PR ada/22420
* utils2.c (build_return_expr): New helper function.
* gigi.h (build_return_expr): Declare it.
* trans.c (Subprogram_Body_to_gnu): Use build_return_expr instead
of manually building the RETURN_EXPR tree.
(call_to_gnu): Pass MODIFY_EXPR through build_binary_op.
(gnat_to_gnu) <N_Return_Statement>: Pass MODIFY_EXPR through
build_binary_op for the "target pointer" case. �Use build_return_expr
instead of manually building the RETURN_EXPR tree.

From-SVN: r105741

gcc/ada/ChangeLog
gcc/ada/gigi.h
gcc/ada/trans.c
gcc/ada/utils2.c

index 2a992754006c307e42d603b51dda654f30b2e858..877d6b7dfe41400efe90648645db58de96117783 100644 (file)
@@ -1,3 +1,20 @@
+2005-10-21  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR ada/21937
+       PR ada/22328
+       PR ada/22381
+       PR ada/22383
+       PR ada/22419
+       PR ada/22420
+       * utils2.c (build_return_expr): New helper function.
+       * gigi.h (build_return_expr): Declare it.
+       * trans.c (Subprogram_Body_to_gnu): Use build_return_expr instead
+       of manually building the RETURN_EXPR tree.
+       (call_to_gnu): Pass MODIFY_EXPR through build_binary_op.
+       (gnat_to_gnu) <N_Return_Statement>: Pass MODIFY_EXPR through
+       build_binary_op for the "target pointer" case.  Use build_return_expr
+       instead of manually building the RETURN_EXPR tree.
+
 2005-09-16  Laurent GUERBY  <laurent@guerby.net>
 
        PR ada/23788
index 0adf64445ff02cd2d9a394685b7eefa14c6dd1c6..9dba805530d817fdfb076c5f1481ed0b99581976 100644 (file)
@@ -678,6 +678,9 @@ extern tree build_unary_op (enum tree_code op_code, tree result_type,
 extern tree build_cond_expr (tree result_type, tree condition_operand,
                              tree true_operand, tree false_operand);
 
+/* Similar, but for RETURN_EXPR.  */
+extern tree build_return_expr (tree result_decl, tree ret_val);
+
 /* Build a CALL_EXPR to call FUNDECL with one argument, ARG.  Return
    the CALL_EXPR.  */
 extern tree build_call_1_expr (tree fundecl, tree arg);
index fb741a3e03081409cfc78c80de97f7e8d79c0592..0e05b6d473144824fed2bf3197bfbabe572b6305 100644 (file)
@@ -1456,9 +1456,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
        gnu_retval = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_retval);
 
       add_stmt_with_node
-       (build1 (RETURN_EXPR, void_type_node,
-                build2 (MODIFY_EXPR, TREE_TYPE (gnu_retval),
-                        DECL_RESULT (current_function_decl), gnu_retval)),
+       (build_return_expr (DECL_RESULT (current_function_decl), gnu_retval),
         gnat_node);
       gnat_poplevel ();
       gnu_result = end_stmt_group ();
@@ -1685,8 +1683,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                }
 
              /* Set up to move the copy back to the original.  */
-             gnu_temp = build2 (MODIFY_EXPR, TREE_TYPE (gnu_copy),
-                                gnu_copy, gnu_actual);
+             gnu_temp = build_binary_op (MODIFY_EXPR, NULL_TREE,
+                                         gnu_copy, gnu_actual);
              annotate_with_node (gnu_temp, gnat_actual);
              append_to_statement_list (gnu_temp, &gnu_after_list);
            }
@@ -3519,8 +3517,6 @@ gnat_to_gnu (Node_Id gnat_node)
        tree gnu_ret_val = NULL_TREE;
        /* The place to put the return value.  */
        tree gnu_lhs;
-       /* Avoid passing error_mark_node to RETURN_EXPR.  */
-       gnu_result = NULL_TREE;
 
        /* If we are dealing with a "return;" from an Ada procedure with
           parameters passed by copy in copy out, we need to return a record
@@ -3626,18 +3622,20 @@ gnat_to_gnu (Node_Id gnat_node)
                  }
              }
          }
-
-       if (gnu_ret_val)
-         gnu_result = build2 (MODIFY_EXPR, TREE_TYPE (gnu_ret_val),
-                              gnu_lhs, gnu_ret_val);
+       else
+         /* If the Ada subprogram is a regular procedure, just return.  */
+         gnu_lhs = NULL_TREE;
 
        if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
          {
+           if (gnu_ret_val)
+             gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE,
+                                           gnu_lhs, gnu_ret_val);
            add_stmt_with_node (gnu_result, gnat_node);
-           gnu_result = NULL_TREE;
+           gnu_lhs = NULL_TREE;
          }
 
-       gnu_result = build1 (RETURN_EXPR, void_type_node, gnu_result);
+       gnu_result = build_return_expr (gnu_lhs, gnu_ret_val);
       }
       break;
 
index 5847910d2e6745e07c7b5d0197cea47b9e2faaad..21a3f61f7615bd08ba98176c30280edb394abd1c 100644 (file)
@@ -1378,8 +1378,50 @@ build_cond_expr (tree result_type, tree condition_operand,
 
   return result;
 }
-\f
 
+/* Similar, but for RETURN_EXPR.  If RESULT_DECL is non-zero, build
+   a RETURN_EXPR around the assignment of RET_VAL to RESULT_DECL.
+   If RESULT_DECL is zero, build a bare RETURN_EXPR.  */
+
+tree
+build_return_expr (tree result_decl, tree ret_val)
+{
+  tree result_expr;
+
+  if (result_decl)
+    {
+      /* The gimplifier explicitly enforces the following invariant:
+
+           RETURN_EXPR
+               |
+           MODIFY_EXPR
+           /        \
+          /          \
+      RESULT_DECL    ...
+
+      As a consequence, type-homogeneity dictates that we use the type
+      of the RESULT_DECL as the operation type.  */
+
+      tree operation_type = TREE_TYPE (result_decl);
+
+      /* Convert the right operand to the operation type.  Note that
+         it's the same transformation as in the MODIFY_EXPR case of
+         build_binary_op with the additional guarantee that the type
+         cannot involve a placeholder, since otherwise the function
+         would use the "target pointer" return mechanism.  */
+       
+      if (operation_type != TREE_TYPE (ret_val))
+       ret_val = convert (operation_type, ret_val);
+
+      result_expr
+       = build2 (MODIFY_EXPR, operation_type, result_decl, ret_val);
+    }
+  else
+    result_expr = NULL_TREE;
+
+  return build1 (RETURN_EXPR, void_type_node, result_expr);
+}
+\f
 /* Build a CALL_EXPR to call FUNDECL with one argument, ARG.  Return
    the CALL_EXPR.  */