/* Generate code for assignment of scalar variables. Includes character
strings and derived types with allocatable components.
- If you know that the LHS has no allocations, set dealloc to false. */
+ If you know that the LHS has no allocations, set dealloc to false.
+
+ DEEP_COPY has no effect if the typespec TS is not a derived type with
+ allocatable components. Otherwise, if it is set, an explicit copy of each
+ allocatable component is made. This is necessary as a simple copy of the
+ whole object would copy array descriptors as is, so that the lhs's
+ allocatable components would point to the rhs's after the assignment.
+ Typically, setting DEEP_COPY is necessary if the rhs is a variable, and not
+ necessary if the rhs is a non-pointer function, as the allocatable components
+ are not accessible by other means than the function's result after the
+ function has returned. It is even more subtle when temporaries are involved,
+ as the two following examples show:
+ 1. When we evaluate an array constructor, a temporary is created. Thus
+ there is theoretically no alias possible. However, no deep copy is
+ made for this temporary, so that if the constructor is made of one or
+ more variable with allocatable components, those components still point
+ to the variable's: DEEP_COPY should be set for the assignment from the
+ temporary to the lhs in that case.
+ 2. When assigning a scalar to an array, we evaluate the scalar value out
+ of the loop, store it into a temporary variable, and assign from that.
+ In that case, deep copying when assigning to the temporary would be a
+ waste of resources; however deep copies should happen when assigning from
+ the temporary to each array element: again DEEP_COPY should be set for
+ the assignment from the temporary to the lhs. */
tree
gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
- bool l_is_temp, bool r_is_var, bool dealloc)
+ bool l_is_temp, bool deep_copy, bool dealloc)
{
stmtblock_t block;
tree tmp;
else if (ts.type == BT_DERIVED && ts.u.derived->attr.alloc_comp)
{
cond = NULL_TREE;
-
+
/* Are the rhs and the lhs the same? */
- if (r_is_var)
+ if (deep_copy)
{
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
gfc_build_addr_expr (NULL_TREE, lse->expr),
{
tmp = gfc_evaluate_now (lse->expr, &lse->pre);
tmp = gfc_deallocate_alloc_comp (ts.u.derived, tmp, 0);
- if (r_is_var)
+ if (deep_copy)
tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
tmp);
gfc_add_expr_to_block (&lse->post, tmp);
/* Do a deep copy if the rhs is a variable, if it is not the
same as the lhs. */
- if (r_is_var)
+ if (deep_copy)
{
tmp = gfc_copy_alloc_comp (ts.u.derived, rse->expr, lse->expr, 0);
tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),