mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
a94d23fc69
commit
096308ba6c
|
|
@ -1,3 +1,9 @@
|
||||||
|
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,
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue