Commit 096308ba by Janne Blomqvist

PR 78534 Modify string copy to avoid -Wstringop-overflow warning

When the character length is changed from int to size_t the existing
algorithm causes a -Wstringop-overflow warning with -O1 on the
gfortran.dg/allocate_deferred_char_scalar_1.f03 testcase. This change
is committed separately from the character length size change in order
to make bisecting potential performance issues easier.

2017-01-02  Janne Blomqvist  <jb@gcc.gnu.org>

        PR fortran/78534
	* trans-expr.c (gfc_trans_string_copy): Rework string copy
	algorithm to avoid -Wstringop-overflow warning.

From-SVN: r244003
parent a94d23fc
2017-01-02 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/78534
* trans-expr.c (gfc_trans_string_copy): Rework string copy
algorithm to avoid -Wstringop-overflow warning.
2017-01-01 Jakub Jelinek <jakub@redhat.com> 2017-01-01 Jakub Jelinek <jakub@redhat.com>
Update copyright years. Update copyright years.
......
...@@ -6450,33 +6450,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest, ...@@ -6450,33 +6450,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
return; return;
} }
/* The string copy algorithm below generates code like
if (dlen > 0) {
memmove (dest, src, min(dlen, slen));
if (slen < dlen)
memset(&dest[slen], ' ', dlen - slen);
}
*/
/* Do nothing if the destination length is zero. */ /* Do nothing if the destination length is zero. */
cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, dlen, cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, dlen,
build_int_cst (size_type_node, 0)); build_int_cst (size_type_node, 0));
/* The following code was previously in _gfortran_copy_string:
// The two strings may overlap so we use memmove.
void
copy_string (GFC_INTEGER_4 destlen, char * dest,
GFC_INTEGER_4 srclen, const char * src)
{
if (srclen >= destlen)
{
// This will truncate if too long.
memmove (dest, src, destlen);
}
else
{
memmove (dest, src, srclen);
// Pad with spaces.
memset (&dest[srclen], ' ', destlen - srclen);
}
}
We're now doing it here for better optimization, but the logic
is the same. */
/* For non-default character kinds, we have to multiply the string /* For non-default character kinds, we have to multiply the string
length by the base type size. */ length by the base type size. */
chartype = gfc_get_char_type (dkind); chartype = gfc_get_char_type (dkind);
...@@ -6499,17 +6485,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest, ...@@ -6499,17 +6485,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
else else
src = gfc_build_addr_expr (pvoid_type_node, src); src = gfc_build_addr_expr (pvoid_type_node, src);
/* Truncate string if source is too long. */ /* First do the memmove. */
cond2 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, slen, tmp2 = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (dlen), dlen,
dlen); slen);
tmp2 = build_call_expr_loc (input_location, tmp2 = build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMMOVE), builtin_decl_explicit (BUILT_IN_MEMMOVE),
3, dest, src, dlen); 3, dest, src, tmp2);
stmtblock_t tmpblock2;
gfc_init_block (&tmpblock2);
gfc_add_expr_to_block (&tmpblock2, tmp2);
/* Else copy and pad with spaces. */ /* If the destination is longer, fill the end with spaces. */
tmp3 = build_call_expr_loc (input_location, cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, slen,
builtin_decl_explicit (BUILT_IN_MEMMOVE), dlen);
3, dest, src, slen);
/* Wstringop-overflow appears at -O3 even though this warning is not /* Wstringop-overflow appears at -O3 even though this warning is not
explicitly available in fortran nor can it be switched off. If the explicitly available in fortran nor can it be switched off. If the
...@@ -6525,13 +6513,14 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest, ...@@ -6525,13 +6513,14 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
tmp4 = fill_with_spaces (tmp4, chartype, tmp); tmp4 = fill_with_spaces (tmp4, chartype, tmp);
gfc_init_block (&tempblock); gfc_init_block (&tempblock);
gfc_add_expr_to_block (&tempblock, tmp3);
gfc_add_expr_to_block (&tempblock, tmp4); gfc_add_expr_to_block (&tempblock, tmp4);
tmp3 = gfc_finish_block (&tempblock); tmp3 = gfc_finish_block (&tempblock);
/* The whole copy_string function is there. */ /* The whole copy_string function is there. */
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2, tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2,
tmp2, tmp3); tmp3, build_empty_stmt (input_location));
gfc_add_expr_to_block (&tmpblock2, tmp);
tmp = gfc_finish_block (&tmpblock2);
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp, tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
build_empty_stmt (input_location)); build_empty_stmt (input_location));
gfc_add_expr_to_block (block, tmp); gfc_add_expr_to_block (block, tmp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment