aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2017-01-02 22:00:18 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2017-01-02 22:00:18 +0200
commit096308ba6c4b48af66c8cc3dc689f2760c024e2f (patch)
tree6098f1ffe583ce60a2d838f34ba3f577cda89e63
parenta94d23fc69de8d286f507b497e1af626771a447c (diff)
downloadgcc-096308ba6c4b48af66c8cc3dc689f2760c024e2f.zip
gcc-096308ba6c4b48af66c8cc3dc689f2760c024e2f.tar.gz
gcc-096308ba6c4b48af66c8cc3dc689f2760c024e2f.tar.bz2
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
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/fortran/trans-expr.c55
2 files changed, 28 insertions, 33 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 8788ef9..ec209b2 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -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>
Update copyright years.
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 0012a29..b9c134a 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6450,33 +6450,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
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. */
cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, dlen,
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
length by the base type size. */
chartype = gfc_get_char_type (dkind);
@@ -6499,17 +6485,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
else
src = gfc_build_addr_expr (pvoid_type_node, src);
- /* Truncate string if source is too long. */
- cond2 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, slen,
- dlen);
+ /* First do the memmove. */
+ tmp2 = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (dlen), dlen,
+ slen);
tmp2 = build_call_expr_loc (input_location,
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. */
- tmp3 = build_call_expr_loc (input_location,
- builtin_decl_explicit (BUILT_IN_MEMMOVE),
- 3, dest, src, slen);
+ /* If the destination is longer, fill the end with spaces. */
+ cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node, slen,
+ dlen);
/* Wstringop-overflow appears at -O3 even though this warning is not
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);
gfc_init_block (&tempblock);
- gfc_add_expr_to_block (&tempblock, tmp3);
gfc_add_expr_to_block (&tempblock, tmp4);
tmp3 = gfc_finish_block (&tempblock);
/* The whole copy_string function is there. */
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,
build_empty_stmt (input_location));
gfc_add_expr_to_block (block, tmp);