tree i, el, exit_label, cond, tmp;
/* For a simple char type, we can call memset(). */
- /* TODO: This code does work and is potentially more efficient, but
- causes spurious -Wstringop-overflow warnings.
if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
return build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMSET),
build_int_cst (gfc_get_int_type (gfc_c_int_kind),
lang_hooks.to_target_charset (' ')),
fold_convert (size_type_node, size));
- */
/* Otherwise, we use a loop:
for (el = start, i = size; i > 0; el--, i+= TYPE_SIZE_UNIT (type))
/* 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);
- }
+ if (destlen > 0)
+ {
+ if (srclen < destlen)
+ {
+ memmove (dest, src, srclen);
+ // Pad with spaces.
+ memset (&dest[srclen], ' ', destlen - srclen);
+ }
+ else
+ {
+ // Truncate if too long.
+ memmove (dest, src, destlen);
+ }
+ }
*/
/* Do nothing if the destination length is zero. */
else
src = gfc_build_addr_expr (pvoid_type_node, src);
- /* 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,
- fold_convert (size_type_node, tmp2));
- stmtblock_t tmpblock2;
- gfc_init_block (&tmpblock2);
- gfc_add_expr_to_block (&tmpblock2, tmp2);
-
- /* If the destination is longer, fill the end with spaces. */
+ /* Truncate string if source is too long. */
cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, slen,
dlen);
+ /* Copy and pad with spaces. */
+ tmp3 = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_MEMMOVE),
+ 3, dest, src,
+ fold_convert (size_type_node, slen));
+
/* Wstringop-overflow appears at -O3 even though this warning is not
explicitly available in fortran nor can it be switched off. If the
source length is a constant, its negative appears as a very large
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 truncated memmove if the slen >= dlen. */
+ tmp2 = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_MEMMOVE),
+ 3, dest, src,
+ fold_convert (size_type_node, dlen));
+
/* The whole copy_string function is there. */
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2,
- tmp3, build_empty_stmt (input_location));
- gfc_add_expr_to_block (&tmpblock2, tmp);
- tmp = gfc_finish_block (&tmpblock2);
+ tmp3, tmp2);
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);