This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[Patch, fortran] PR34396 - Length of substrings defined by expressions not correctly computed in constructors
- From: "Paul Richard Thomas" <paul dot richard dot thomas at gmail dot com>
- To: "fortran at gcc dot gnu dot org" <fortran at gcc dot gnu dot org>
- Date: Thu, 10 Jan 2008 00:41:42 +0100
- Subject: [Patch, fortran] PR34396 - Length of substrings defined by expressions not correctly computed in constructors
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; bh=JcXGgGib1C5kTC5NqwFhFlf81Hj3vHohARongOSr+so=; b=wiZJqpbOnLRrX14h+3lnvezj7DrIVnX8XjWTiLEJKDVAztBwYEXbe8DA2Y/aOKRboqIgXc89HGmkE/cras4O/TxtYF+yPEjcz0Qz8mm51lxrxXM3rmXL8FLk7jVaEqa8cL+0IBQr8mV5OG1F/OPU73mheeMFw4zgklyslqpTqWg=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:mime-version:content-type; b=rO+FpW5cUxAPZnLlWFFLJtseD6bA/hY6JHGfzIq4GXRQipClyiYxDi4EF0wHjNWvqKGwga/SDKqMxzIVf/HnowA8Ea2ur2YajDZfL9h9M7fa8TQoFtH9GwE6utALpzg5MY7EN0J5hAi1MSgzzY6Ocgakg08pZDsJxfO6/s1zMuE=
:ADDPATCH fortran:
This one consisted of two bugs:
(i) The assignment from the constructor to the array elements did not
pad out the result with spaces. This was cured by borrowing
gfc_trans_string_copy from trans-expr.c.
(ii) The bounds checking was not working correctly. This was fixed by
moving it to gfc_trans_array_ctor_element, where the string length
must be calculate for each element.
The testcase is essentially the reporter's.
Bootstrapped and regtested on x86_ia64/FC8 - OK for trunk?
Paul
2008-01-09 Paul Thomas <pault@gcc.gnu.org>
PR fortran/34396
* trans-array.c (gfc_trans_array_ctor_element): Use gfc_trans_string_copy
to assign strings and perform bounds checks on the string length.
(get_array_ctor_strlen): Remove bounds checking.
(gfc_trans_array_constructor): Initialize string length checking.
* trans-array.h : Add prototype for gfc_trans_string_copy.
2008-01-09 Paul Thomas <pault@gcc.gnu.org>
PR fortran/34396
* gfortran.dg/bounds_check_12.f90: New test.
Index: gcc/fortran/trans-array.c
===================================================================
*** gcc/fortran/trans-array.c (revision 131363)
--- gcc/fortran/trans-array.c (working copy)
*************** gfc_put_offset_into_var (stmtblock_t * p
*** 951,968 ****
--- 951,975 ----
/* Assign an element of an array constructor. */
+ static bool first_len;
+ static tree first_len_val;
static void
gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
tree offset, gfc_se * se, gfc_expr * expr)
{
tree tmp;
+ tree esize;
gfc_conv_expr (se, expr);
/* Store the value. */
tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
tmp = gfc_build_array_ref (tmp, offset, NULL);
+
+ esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
+ esize = fold_convert (gfc_charlen_type_node, esize);
+
if (expr->ts.type == BT_CHARACTER)
{
gfc_conv_string_parameter (se);
*************** gfc_trans_array_ctor_element (stmtblock_
*** 978,986 ****
tmp = gfc_build_addr_expr (pchar_type_node, tmp);
/* We know the temporary and the value will be the same length,
so can use memcpy. */
! tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
! tmp, se->expr, se->string_length);
! gfc_add_expr_to_block (&se->pre, tmp);
}
}
else
--- 985,1014 ----
tmp = gfc_build_addr_expr (pchar_type_node, tmp);
/* We know the temporary and the value will be the same length,
so can use memcpy. */
! gfc_trans_string_copy (&se->pre, esize, tmp,
! se->string_length,
! se->expr);
! }
! if (flag_bounds_check)
! {
! if (first_len)
! {
! gfc_add_modify_expr (&se->pre, first_len_val,
! se->string_length);
! first_len = false;
! }
! else
! {
! /* Verify that all constructor elements are of the same
! length. */
! tree cond = fold_build2 (NE_EXPR, boolean_type_node,
! first_len_val, se->string_length);
! gfc_trans_runtime_check
! (cond, &se->pre, &expr->where,
! "Different CHARACTER lengths (%ld/%ld) in array constructor",
! fold_convert (long_integer_type_node, first_len_val),
! fold_convert (long_integer_type_node, se->string_length));
! }
}
}
else
*************** bool
*** 1425,1431 ****
get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
{
bool is_const;
- tree first_len = NULL_TREE;
is_const = TRUE;
--- 1453,1458 ----
*************** get_array_ctor_strlen (stmtblock_t *bloc
*** 1460,1482 ****
get_array_ctor_all_strlen (block, c->expr, len);
break;
}
- if (flag_bounds_check)
- {
- if (!first_len)
- first_len = *len;
- else
- {
- /* Verify that all constructor elements are of the same
- length. */
- tree cond = fold_build2 (NE_EXPR, boolean_type_node,
- first_len, *len);
- gfc_trans_runtime_check
- (cond, block, &c->expr->where,
- "Different CHARACTER lengths (%ld/%ld) in array constructor",
- fold_convert (long_integer_type_node, first_len),
- fold_convert (long_integer_type_node, *len));
- }
- }
}
return is_const;
--- 1487,1492 ----
*************** gfc_trans_array_constructor (gfc_loopinf
*** 1660,1665 ****
--- 1670,1681 ----
tree type;
bool dynamic;
+ if (flag_bounds_check && ss->expr->ts.type == BT_CHARACTER)
+ {
+ first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
+ first_len = true;
+ }
+
ss->data.info.dimen = loop->dimen;
c = ss->expr->value.constructor;
Index: gcc/fortran/trans-array.h
===================================================================
*** gcc/fortran/trans-array.h (revision 131363)
--- gcc/fortran/trans-array.h (working copy)
*************** void gfc_add_intrinsic_ss_code (gfc_loop
*** 137,139 ****
--- 137,142 ----
/* Functions for constant array constructor processing. */
unsigned HOST_WIDE_INT gfc_constant_array_constructor_p (gfc_constructor *);
tree gfc_build_constant_array_constructor (gfc_expr *, tree);
+
+ /* Copy a string from src to dest. */
+ void gfc_trans_string_copy (stmtblock_t *, tree, tree, tree, tree);
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c (revision 131363)
--- gcc/fortran/trans-expr.c (working copy)
*************** gfc_conv_function_call (gfc_se * se, gfc
*** 2803,2809 ****
/* Generate code to copy a string. */
! static void
gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
tree slength, tree src)
{
--- 2803,2809 ----
/* Generate code to copy a string. */
! void
gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
tree slength, tree src)
{
Index: gcc/testsuite/gfortran.dg/bounds_check_12.f90
===================================================================
*** gcc/testsuite/gfortran.dg/bounds_check_12.f90 (revision 0)
--- gcc/testsuite/gfortran.dg/bounds_check_12.f90 (revision 0)
***************
*** 0 ****
--- 1,28 ----
+ ! { dg-do run }
+ ! { dg-options "-fbounds-check" }
+ ! { dg-shouldfail "Different CHARACTER lengths" }
+ ! Tests the fix for PR34396, where the non-constant string lengths in the
+ ! array constructor were being ignored and the bounds checking was not
+ ! being done correctly.
+ !
+ ! Contributed by Dominique d'Humieres <dominiq@lps.ens.fr>
+ !
+ program array_char
+ implicit none
+ integer :: i, j(5)
+ character (len=5) :: x, y
+ character (len=5) :: z(2)
+ x = "ab"
+ y = "cd"
+ z = ""
+ z = (/y(1: len (trim(y))), x(1: len (trim(x)))/)
+ j = ichar ([(z(1)(i:i), i=1,5)])
+ if (any (j .ne. (/99,100,32,32,32/))) call abort ()
+ j = ichar ([(z(2)(i:i), i=1,5)])
+ if (any (j .ne. (/97,98,32,32,32/))) call abort ()
+ x = "a "
+ z = (/y(1: len (trim(y))), x(1: len (trim(x)))/)
+ end program array_char
+
+ ! { dg-output "At line 24 of file .*" }
+ ! { dg-output "Different CHARACTER lengths .2/1. in array constructor" }