This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, fortran] PR18022 - assignments of the kind x(:)%i = f(y(:))- revision
- From: Paul Thomas <paulthomas2 at wanadoo dot fr>
- To: Paul Thomas <paulthomas2 at wanadoo dot fr>
- Cc: Tobias Schlüter <tobias dot schlueter at physik dot uni-muenchen dot de>,"'fortran at gcc dot gnu dot org'" <fortran at gcc dot gnu dot org>,patch <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 16 Oct 2005 09:59:59 +0200
- Subject: Re: [Patch, fortran] PR18022 - assignments of the kind x(:)%i = f(y(:))- revision
- References: <434D8D18.7000201@wanadoo.fr>
:ADDPATCH fortran:
Thanks to Richard Sandiford for a good suggestion: The condition has
been moved to join others in gfc_trans_arrayfunc_assign and this now
returns null if the lvalue is a component reference within an array
reference.
Bubblestrapped and regtested on FC3/i686: OK for mainline and 4.0?
Paul T
This PR involved assignments of the for y = f(x), where the lvalue is
a component of an array of derived types and the function outputs an
array of the same type as the component. This kind of assignment
evades the scalarizer by going to gfc_trans_arrayfunc_assign. This
would be fine if the description of arrays was up to any arbitrary
spacing between elements. In the absence of this greatly required
feature, such assignments produce nonsense.
The patch functions by skipping past the call to
gfc_trans_arrayfunc_assign, if the lvalue expression has any component
references after an array reference has been seen. That is to say,
the likes of x(:)%i = f(y(:)) will go to the scalarizer. This is a
much improved version of the original proposed patch:
http://gcc.gnu.org/ml/fortran/2005-07/msg00098.html
2005-10-12 Paul Thomas <pault@gcc.gnu.org>
PR fortran/18022
* trans-expr.c (gfc_trans_arrayfunc_assign): Return NULL
if there is a component ref during an array ref.
2005-10-12 Paul Thomas <pault@gcc.gnu.org>
PR fortran/18022
gfortran.dg/assign_func_dtcomp_1.f90: New test.
Index: gcc/gcc/fortran/trans-expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans-expr.c,v
retrieving revision 1.65
diff -c -p -r1.65 trans-expr.c
*** gcc/gcc/fortran/trans-expr.c 3 Oct 2005 07:22:18 -0000 1.65
--- gcc/gcc/fortran/trans-expr.c 16 Oct 2005 06:05:12 -0000
*************** gfc_trans_arrayfunc_assign (gfc_expr * e
*** 2591,2596 ****
--- 2591,2598 ----
{
gfc_se se;
gfc_ss *ss;
+ gfc_ref * ref;
+ bool seen_array_ref;
/* The caller has already checked rank>0 and expr_type == EXPR_FUNCTION. */
if (expr2->value.function.isym && !gfc_is_intrinsic_libcall (expr2))
*************** gfc_trans_arrayfunc_assign (gfc_expr * e
*** 2605,2610 ****
--- 2607,2624 ----
if (gfc_ref_needs_temporary_p (expr1->ref))
return NULL;
+ /* Check that no component references appear during an array
+ reference. This is needed because we do not have the means to
+ span any arbitrary stride with an array descriptor. */
+ seen_array_ref = false;
+ for (ref = expr1->ref; ref; ref = ref->next)
+ {
+ if (ref->type == REF_ARRAY)
+ seen_array_ref= true;
+ else if (ref->type == REF_COMPONENT && seen_array_ref)
+ return NULL;
+ }
+
/* Check for a dependency. */
if (gfc_check_fncall_dependency (expr1, expr2))
return NULL;
------------------------assign_func_dtcomp_1.f90-------------------------
! { dg-do run }
! { dg-options "-O0" }
!
! Test fix for PR18022.
!
! Contributed by Paul Thomas <pault@gcc.gnu.org>
!
program assign_func_dtcomp
implicit none
type :: mytype
real :: x
real :: y
end type mytype
type (mytype), dimension (4) :: z
type :: thytype
real :: x(4)
end type thytype
type (thytype) :: w
real, dimension (4) :: a = (/1.,2.,3.,4./)
real, dimension (4) :: b = (/5.,6.,7.,8./)
! Test the original problem is fixed.
z(:)%x = foo (a)
z(:)%y = foo (b)
if (any(z%x.ne.a).or.any(z%y.ne.b)) call abort ()
! Make sure we did not break anything on the way.
w%x(:) = foo (b)
a = foo (b)
if (any(w%x.ne.b).or.any(a.ne.b)) call abort ()
contains
function foo (v) result (ans)
real, dimension (:), intent(in) :: v
real, dimension (size(v)) :: ans
ans = v
end function foo
end program assign_func_dtcomp