This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[PATCH] Fix fortran/29951, transfer vs arrays to scalars
- From: Andrew Pinski <pinskia at gmail dot com>
- To: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Sat, 25 Nov 2006 00:23:59 -0800
- Subject: [PATCH] Fix fortran/29951, transfer vs arrays to scalars
- Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:subject:to:content-type:date:message-id:mime-version:x-mailer:from; b=Ft/S96DFkg/4QvAsGTGYGIISxZIA8j2b5Y2dw/3KDp3HuGPUoOMCIrJh1gXkktz2jA9uQrNBIK0g34ISKYr5Yd5mnzut/HqxtJXcS8TU1Iu1mlJG8xVFrdZsAu+c4ZuRO2FJ4wqfgWckMK5uOYCwDEaoe50Wu5x2QrP6kOXr5aM=
The problem here is that dereferencing an array for the
VIEW_CONVERT_EXPR causes us to just use the first element of the array.
This patch fixes the problem by using memcpy instead of let the
optimizers optimize it down to a VIEW_CONVERT_EXPR if they can, they do
with the testcase I was trying to fix before.
OK? Bootstrapped and tested on i686-linux-gnu with no regressions.
Thanks,
Andrew Pinski
ChangeLog:
* trans-intrinsic.c (gfc_conv_intrinsic_transfer): Change to
call memcpy instead of creating a VIEW_CONVERT_EXRP.
* gfortran.fortran-torture/execute/transfer2.f90: New test.
Index: testsuite/gfortran.fortran-torture/execute/transfer2.f90
===================================================================
--- testsuite/gfortran.fortran-torture/execute/transfer2.f90 (revision 0)
+++ testsuite/gfortran.fortran-torture/execute/transfer2.f90 (revision 0)
@@ -0,0 +1,19 @@
+program test_convert
+
+ implicit none
+ character(len=4) :: byte_string
+ character(len=1),dimension(4) :: byte_array
+ integer*4 :: value,value1,n,i
+
+ byte_string(1:1) = char(157)
+ byte_string(2:2) = char(127)
+ byte_string(3:3) = char(100)
+ byte_string(4:4) = char(0)
+
+ byte_array(1:4) = (/char(157),char(127),char(100),char(0)/)
+
+ value = transfer(byte_string(1:4),value)
+ value1 = transfer(byte_array(1:4),value1)
+
+ if (value .ne. value1) call abort()
+end program test_convert
Index: fortran/trans-intrinsic.c
===================================================================
--- fortran/trans-intrinsic.c (revision 119148)
+++ fortran/trans-intrinsic.c (working copy)
@@ -2989,7 +2989,7 @@ gfc_conv_intrinsic_array_transfer (gfc_s
/* Scalar transfer statement.
- TRANSFER (source, mold) = VIEW_CONVERT_EXPR<typeof<mold> >source. */
+ TRANSFER (source, mold) = memcpy(&tmpdecl, &source, size), tmpdecl. */
static void
gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
@@ -2999,6 +2999,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se
tree type;
tree ptr;
gfc_ss *ss;
+ tree tmpdecl, tmp, args;
/* Get a pointer to the source. */
arg = expr->value.function.actual;
@@ -3014,6 +3015,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se
arg = arg->next;
type = gfc_typenode_for_spec (&expr->ts);
+
if (expr->ts.type == BT_CHARACTER)
{
ptr = convert (build_pointer_type (type), ptr);
@@ -3026,8 +3028,22 @@ gfc_conv_intrinsic_transfer (gfc_se * se
}
else
{
- tree tmp = build_fold_indirect_ref (ptr);
- se->expr = fold_build1 (VIEW_CONVERT_EXPR, type, tmp);
+ tree moldsize;
+ tmpdecl = gfc_create_var (type, "transfer");
+ moldsize = size_in_bytes (type);
+
+ /* Use memcpy to do the transfer. */
+ tmp = build1 (ADDR_EXPR, build_pointer_type (type), tmpdecl);
+ tmp = fold_convert (pvoid_type_node, tmp);
+ args = gfc_chainon_list (NULL_TREE, tmp);
+ tmp = fold_convert (pvoid_type_node, ptr);
+ args = gfc_chainon_list (args, tmp);
+ args = gfc_chainon_list (args, moldsize);
+ tmp = built_in_decls[BUILT_IN_MEMCPY];
+ tmp = build_function_call_expr (tmp, args);
+ gfc_add_expr_to_block (&se->pre, tmp);
+
+ se->expr = tmpdecl;
}
}