http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49324

Tobias Burnus <burnus at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Wrong result with           |Deep copy missing for array
                   |constructor of derived      |constructors of DT w/
                   |types w/ allocatable        |allocatable components
                   |components                  |

--- Comment #4 from Tobias Burnus <burnus at gcc dot gnu.org> 2011-06-09 
07:26:41 UTC ---
Paul: As you (with Erik) have implemented alloc components: Do you know the
purpose of the "if (r_is_var)"? (See bottom of this comment.) I wouldn't mind
if you could work on this PR as I would like to concentrate on other gfortran
and in particular urgent non-gfortran issues...

 * * *

The cause of the failure is not really surprising; the issue is related to the
missing deep copy of the arguments:

       D.1604 = (struct t[0:] * restrict) z.data;
       (*(struct t[2] * restrict) atmp.8.data)[0] = x;
       (*(struct t[2] * restrict) atmp.8.data)[1] = y;
       (*D.1604)[(S.11 + D.1613) + D.1605]
             = (*(struct t[2] * restrict) atmp.8.data)[S.11];

The code is OK if there are no allocatable components. However, with
allocatable components, one cannot simply assign the structure, but one needs
to deep copy the (allocatable) components. For ALLOCATE (..., SOURCE=...) and
for intrinsic assignment, a similar issue exists (and is mostly solved, except
for polymorphic variables, cf. PR46174).


If one looks at gfc_trans_scalar_assign, which is called in
gfc_trans_assignment_1, one finds:

5308 else if (ts.type == BT_DERIVED && ts.u.derived->attr.alloc_comp)
...
5341   /* Do a deep copy if the rhs is a variable, if it is not the
5342      same as the lhs.  */
5343   if (r_is_var)
5344     {
5345       tmp = gfc_copy_alloc_comp (ts.u.derived, rse->expr, lse->expr, 0);
5346       tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
5347                       tmp);
5348       gfc_add_expr_to_block (&block, tmp);
5349     }

The "r_is_var" is given by (cf. trans-expr.c:6156):
  expr_is_variable (expr2) || scalar_to_array
and as expr2 is an EXPR_ARRAY and not a variable ...

(For non-variables, the check "Are the rhs and the lhs the same?" does not make
sense, cf. trans-expr.c:5312-5319.)

Reply via email to