===================================================================
@@ -57,12 +57,19 @@ extern void rest_of_type_decl_compilatio
/* Start a new statement group chained to the previous group. */
extern void start_stmt_group (void);
-/* Add GNU_STMT to the current BLOCK_STMT node. */
+/* Add GNU_STMT to the current statement group. If it is an expression with
+ no effects, it is ignored. */
extern void add_stmt (tree gnu_stmt);
-/* Similar, but set the location of GNU_STMT to that of GNAT_NODE. */
+/* Similar, but the statement is always added, regardless of side-effects. */
+extern void add_stmt_force (tree gnu_stmt);
+
+/* Like add_stmt, but set the location of GNU_STMT to that of GNAT_NODE. */
extern void add_stmt_with_node (tree gnu_stmt, Node_Id gnat_node);
+/* Similar, but the statement is always added, regardless of side-effects. */
+extern void add_stmt_with_node_force (tree gnu_stmt, Node_Id gnat_node);
+
/* Return code corresponding to the current code group. It is normally
a STATEMENT_LIST, but may also be a BIND_EXPR or TRY_FINALLY_EXPR if
BLOCK or cleanups were set. */
===================================================================
@@ -1739,12 +1739,13 @@ Attribute_to_gnu (Node_Id gnat_node, tre
/* Cache the expression we have just computed. Since we want to do it
at run time, we force the use of a SAVE_EXPR and let the gimplifier
- create the temporary. */
+ create the temporary in the outermost binding level. We will make
+ sure in Subprogram_Body_to_gnu that it is evaluated on all possible
+ paths by forcing its evaluation on entry of the function. */
if (pa)
{
gnu_result
= build1 (SAVE_EXPR, TREE_TYPE (gnu_result), gnu_result);
- TREE_SIDE_EFFECTS (gnu_result) = 1;
if (attribute == Attr_First)
pa->first = gnu_result;
else if (attribute == Attr_Last)
@@ -2634,8 +2635,9 @@ Subprogram_Body_to_gnu (Node_Id gnat_nod
VEC_pop (tree, gnu_return_label_stack);
- /* If we populated the parameter attributes cache, we need to make sure
- that the cached expressions are evaluated on all possible paths. */
+ /* If we populated the parameter attributes cache, we need to make sure that
+ the cached expressions are evaluated on all the possible paths leading to
+ their uses. So we force their evaluation on entry of the function. */
cache = DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language->parm_attr_cache;
if (cache)
{
@@ -2647,11 +2649,11 @@ Subprogram_Body_to_gnu (Node_Id gnat_nod
FOR_EACH_VEC_ELT (parm_attr, cache, i, pa)
{
if (pa->first)
- add_stmt_with_node (pa->first, gnat_node);
+ add_stmt_with_node_force (pa->first, gnat_node);
if (pa->last)
- add_stmt_with_node (pa->last, gnat_node);
+ add_stmt_with_node_force (pa->last, gnat_node);
if (pa->length)
- add_stmt_with_node (pa->length, gnat_node);
+ add_stmt_with_node_force (pa->length, gnat_node);
}
add_stmt (gnu_result);
@@ -5969,7 +5971,8 @@ start_stmt_group (void)
current_stmt_group = group;
}
-/* Add GNU_STMT to the current statement group. */
+/* Add GNU_STMT to the current statement group. If it is an expression with
+ no effects, it is ignored. */
void
add_stmt (tree gnu_stmt)
@@ -5977,7 +5980,15 @@ add_stmt (tree gnu_stmt)
append_to_statement_list (gnu_stmt, ¤t_stmt_group->stmt_list);
}
-/* Similar, but set the location of GNU_STMT to that of GNAT_NODE. */
+/* Similar, but the statement is always added, regardless of side-effects. */
+
+void
+add_stmt_force (tree gnu_stmt)
+{
+ append_to_statement_list_force (gnu_stmt, ¤t_stmt_group->stmt_list);
+}
+
+/* Like add_stmt, but set the location of GNU_STMT to that of GNAT_NODE. */
void
add_stmt_with_node (tree gnu_stmt, Node_Id gnat_node)
@@ -5987,6 +5998,16 @@ add_stmt_with_node (tree gnu_stmt, Node_
add_stmt (gnu_stmt);
}
+/* Similar, but the statement is always added, regardless of side-effects. */
+
+void
+add_stmt_with_node_force (tree gnu_stmt, Node_Id gnat_node)
+{
+ if (Present (gnat_node))
+ set_expr_location_from_node (gnu_stmt, gnat_node);
+ add_stmt_force (gnu_stmt);
+}
+
/* Add a declaration statement for GNU_DECL to the current statement group.
Get SLOC from Entity_Id. */