trans-expr.c (gfc_trans_scalar_assign): Rename argument, extend comment.
authorMikael Morin <mikael@gcc.gnu.org>
Tue, 14 Aug 2012 16:35:09 +0000 (16:35 +0000)
committerMikael Morin <mikael@gcc.gnu.org>
Tue, 14 Aug 2012 16:35:09 +0000 (16:35 +0000)
fortran/
* trans-expr.c (gfc_trans_scalar_assign): Rename argument,
extend comment.

From-SVN: r190392

gcc/fortran/ChangeLog
gcc/fortran/trans-expr.c

index 6309b5a25f36b19bc2d31702b5aa51ff066bde82..587a010318fbf0174f47f5d7f3464c5b7204f230 100644 (file)
@@ -1,3 +1,8 @@
+2012-08-14  Mikael Morin  <mikael@gcc.gnu.org>
+
+       * trans-expr.c (gfc_trans_scalar_assign): Rename argument,
+       extend comment.
+
 2012-08-14  Mikael Morin  <mikael@gcc.gnu.org>
 
        * gfortran.h (gfc_get_proc_ptr_comp): New prototype.
index 12a75d0d156a47f5eb66c940919d4625fbe8d3a8..53fdf45c400f69f4d338527a0b3509750d674496 100644 (file)
@@ -6307,11 +6307,34 @@ gfc_conv_string_parameter (gfc_se * se)
 
 /* 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;
@@ -6345,9 +6368,9 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
   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),
@@ -6363,7 +6386,7 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
        {
          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);
@@ -6377,7 +6400,7 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
 
       /* 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),