diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 90789f49359..f06e8a6ef66 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2003-06-26 Roger Sayle + Jakub Jelinek + + * builtins.c (expand_builtin_sprintf): Use c_getstr and strlen to + obtain the format string instead of using TREE_STRING_POINTER and + TREE_STRING_LENGTH. Only optimize sprintf(dst,"%s",src) when the + return value is unused or the length of src is a known constant. + 2003-06-26 Richard Henderson * config/ia64/ia64.h (REGISTER_NAMES): R0 is really AP. diff --git a/gcc/builtins.c b/gcc/builtins.c index 3872fd56c50..44ecbdedcf2 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4492,8 +4492,8 @@ expand_builtin_cabs (tree arglist, rtx target) static rtx expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) { - tree dest, fmt, stripped; - tree orig_arglist; + tree orig_arglist, dest, fmt; + const char *fmt_str; orig_arglist = arglist; @@ -4512,36 +4512,33 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) arglist = TREE_CHAIN (arglist); /* Check whether the format is a literal string constant. */ - stripped = fmt; - STRIP_NOPS (stripped); - if (stripped && TREE_CODE (stripped) == ADDR_EXPR) - stripped = TREE_OPERAND (stripped, 0); - if (TREE_CODE (stripped) != STRING_CST) + fmt_str = c_getstr (fmt); + if (fmt_str == NULL) return 0; /* If the format doesn't contain % args or %%, use strcpy. */ - if (strchr (TREE_STRING_POINTER (stripped), '%') == 0) + if (strchr (fmt_str, '%') == 0) { tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; tree exp; - if (arglist || !fn) + if (arglist || ! fn) return 0; expand_expr (build_function_call_expr (fn, orig_arglist), const0_rtx, VOIDmode, EXPAND_NORMAL); if (target == const0_rtx) return const0_rtx; - exp = build_int_2 (TREE_STRING_LENGTH (stripped) - 1, 0); + exp = build_int_2 (strlen (fmt_str), 0); exp = fold (build1 (NOP_EXPR, integer_type_node, exp)); return expand_expr (exp, target, mode, EXPAND_NORMAL); } - /* If the format is "%s", use strcpy and possibly strlen. */ - else if (strcmp (TREE_STRING_POINTER (stripped), "%s") == 0) + /* If the format is "%s", use strcpy if the result isn't used. */ + else if (strcmp (fmt_str, "%s") == 0) { - tree strcpy_fn, strlen_fn, exp, arg; - strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY]; + tree fn, arg, len; + fn = implicit_built_in_decls[BUILT_IN_STRCPY]; - if (! strcpy_fn) + if (! fn) return 0; if (! arglist || TREE_CHAIN (arglist)) @@ -4552,25 +4549,21 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) if (target != const0_rtx) { - strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN]; - if (! strlen_fn) + len = c_strlen (arg); + if (! len || TREE_CODE (len) != INTEGER_CST) return 0; - arg = save_expr (arg); } else - strlen_fn = 0; + len = NULL_TREE; arglist = build_tree_list (NULL_TREE, arg); arglist = tree_cons (NULL_TREE, dest, arglist); - expand_expr (build_function_call_expr (strcpy_fn, arglist), + expand_expr (build_function_call_expr (fn, arglist), const0_rtx, VOIDmode, EXPAND_NORMAL); if (target == const0_rtx) return const0_rtx; - - exp = build_function_call_expr (strlen_fn, TREE_CHAIN (arglist)); - exp = fold (build1 (NOP_EXPR, integer_type_node, exp)); - return expand_expr (exp, target, mode, EXPAND_NORMAL); + return expand_expr (len, target, mode, EXPAND_NORMAL); } return 0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index df08e070e65..51bed0425d6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2003-06-26 Roger Sayle + Jakub Jelinek + + * gcc.c-torture/execute/string-opt-16.c: Remove test for disabled + sprintf(dst,"%s",src) optimization. + * gcc.c-torture/execute/20030626-1.c: New test case. + * gcc.c-torture/execute/20030626-2.c: New test case. + 2003-06-26 J"orn Rennecke * gcc.c-torture/execute/multi-ix.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/20030626-1.c b/gcc/testsuite/gcc.c-torture/execute/20030626-1.c new file mode 100644 index 00000000000..8b985f03530 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20030626-1.c @@ -0,0 +1,13 @@ +char buf[10]; + +extern void abort (void); +extern int sprintf (char*, const char*, ...); + +int main() +{ + int l = sprintf (buf, "foo\0bar"); + if (l != 3) + abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/20030626-2.c b/gcc/testsuite/gcc.c-torture/execute/20030626-2.c new file mode 100644 index 00000000000..5483d0cba54 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20030626-2.c @@ -0,0 +1,14 @@ +char buf[40]; + +extern int sprintf (char*, const char*, ...); +extern void abort (void); + +int main() +{ + int i = 0; + int l = sprintf (buf, "%s", i++ ? "string" : "other string"); + if (l != sizeof ("other string") - 1 || i != 1) + abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c index 82f3c418cd0..8556b8f6517 100644 --- a/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c @@ -38,10 +38,6 @@ void test5(char *ptr) sprintf(buffer,"%s",ptr); } -int test6(char *ptr) -{ - return sprintf(buffer,"%s",ptr); -} int main() { @@ -72,12 +68,6 @@ int main() if (memcmp(buffer, "barf", 5) || buffer[5] != 'A') abort (); - memset (buffer, 'A', 32); - if (test6 ("barf") != 4) - abort (); - if (memcmp(buffer, "barf", 5) || buffer[5] != 'A') - abort (); - return 0; }