diff options
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/builtins.c | 234 | ||||
-rw-r--r-- | gcc/builtins.def | 4 | ||||
-rw-r--r-- | gcc/c-common.c | 44 | ||||
-rw-r--r-- | gcc/extend.texi | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-10.c | 78 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-11.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-12.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-9.c | 48 |
10 files changed, 531 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f6383eb..61ac69e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2000-12-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + * builtins.c (expand_builtin_strcat, expand_builtin_strncat, + expand_builtin_strspn, expand_builtin_strcspn): New functions. + (expand_builtin): Handle BUILT_IN_STRCAT, BUILT_IN_STRNCAT, + BUILT_IN_STRSPN and BUILT_IN_STRCSPN. + + * builtins.def (BUILT_IN_STRCAT, BUILT_IN_STRNCAT, + BUILT_IN_STRSPN, BUILT_IN_STRCSPN): New entries. + + * c-common.c (c_common_nodes_and_builtins): Declare builtin + strcat, strncat, strspn and strcspn. + (string_ftype_string_cstring): Renamed from `string_ftype_ptr_ptr'. + + * extend.texi (strcat, strcspn, strncat, strspn): Document new + builtins. + +2000-12-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + * builtins.c (expand_builtin_strcmp): Use const*_rtx when expanding strcmp at compile-time. Add another transformation. (expand_builtin_strncmp): Add more transformations. Call diff --git a/gcc/builtins.c b/gcc/builtins.c index 0ed4707..7994f63 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -111,6 +111,14 @@ static rtx expand_builtin_strncmp PARAMS ((tree, rtx, enum machine_mode)); static rtx builtin_memcpy_read_str PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode)); +static rtx expand_builtin_strcat PARAMS ((tree, rtx, + enum machine_mode)); +static rtx expand_builtin_strncat PARAMS ((tree, rtx, + enum machine_mode)); +static rtx expand_builtin_strspn PARAMS ((tree, rtx, + enum machine_mode)); +static rtx expand_builtin_strcspn PARAMS ((tree, rtx, + enum machine_mode)); static rtx expand_builtin_memcpy PARAMS ((tree)); static rtx expand_builtin_strcpy PARAMS ((tree)); static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT, @@ -2423,6 +2431,206 @@ expand_builtin_strncmp (exp, target, mode) return 0; } +/* Expand expression EXP, which is a call to the strcat builtin. + Return 0 if we failed the caller should emit a normal call, + otherwise try to get the result in TARGET, if convenient. */ +static rtx +expand_builtin_strcat (arglist, target, mode) + tree arglist; + rtx target; + enum machine_mode mode; +{ + /* If we need to check memory accesses, call the library function. */ + if (current_function_check_memory_usage) + return 0; + + if (arglist == 0 + /* Arg could be non-pointer if user redeclared this fcn wrong. */ + || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE + || TREE_CHAIN (arglist) == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) + != POINTER_TYPE)) + return 0; + else + { + tree dst = TREE_VALUE (arglist), + src = TREE_VALUE (TREE_CHAIN (arglist)); + const char *p = c_getstr (src); + + /* If the string length is zero, return the dst parameter. */ + if (p && *p == '\0') + return expand_expr (dst, target, mode, EXPAND_NORMAL); + + return 0; + } +} + +/* Expand expression EXP, which is a call to the strncat builtin. + Return 0 if we failed the caller should emit a normal call, + otherwise try to get the result in TARGET, if convenient. */ +static rtx +expand_builtin_strncat (arglist, target, mode) + tree arglist; + rtx target; + enum machine_mode mode; +{ + /* If we need to check memory accesses, call the library function. */ + if (current_function_check_memory_usage) + return 0; + + if (arglist == 0 + /* Arg could be non-pointer if user redeclared this fcn wrong. */ + || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE + || TREE_CHAIN (arglist) == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) + != POINTER_TYPE) + || TREE_CHAIN (TREE_CHAIN (arglist)) == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE + (TREE_CHAIN (TREE_CHAIN (arglist))))) + != INTEGER_TYPE)) + return 0; + else + { + tree dst = TREE_VALUE (arglist), + src = TREE_VALUE (TREE_CHAIN (arglist)), + len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + const char *p = c_getstr (src); + + /* If the requested length is zero, or the src parameter string + length is zero, return the dst parameter. */ + if ((TREE_CODE (len) == INTEGER_CST && compare_tree_int (len, 0) == 0) + || (p && *p == '\0')) + { + /* Evaluate and ignore the src and len parameters in case + they have side-effects. */ + expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL); + expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL); + return expand_expr (dst, target, mode, EXPAND_NORMAL); + } + + /* If the requested len is greater than or equal to the string + length, call strcat. */ + if (TREE_CODE (len) == INTEGER_CST && p + && compare_tree_int (len, strlen (p)) >= 0) + { + tree call_expr, newarglist = + tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)), + fn = built_in_decls[BUILT_IN_STRCAT]; + + /* If the replacement _DECL isn't initialized, don't do the + transformation. */ + if (!fn) + return 0; + + call_expr = build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (fn)), fn); + call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + call_expr, newarglist, NULL_TREE); + TREE_SIDE_EFFECTS (call_expr) = 1; + return expand_expr (call_expr, target, mode, EXPAND_NORMAL); + } + return 0; + } +} + +/* Expand expression EXP, which is a call to the strspn builtin. + Return 0 if we failed the caller should emit a normal call, + otherwise try to get the result in TARGET, if convenient. */ +static rtx +expand_builtin_strspn (arglist, target, mode) + tree arglist; + rtx target; + enum machine_mode mode; +{ + /* If we need to check memory accesses, call the library function. */ + if (current_function_check_memory_usage) + return 0; + + if (arglist == 0 + /* Arg could be non-pointer if user redeclared this fcn wrong. */ + || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE + || TREE_CHAIN (arglist) == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) + != POINTER_TYPE)) + return 0; + else + { + tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); + const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); + + /* If both arguments are constants, evaluate at compile-time. */ + if (p1 && p2) + { + const size_t r = strspn (p1, p2); + return expand_expr (size_int (r), target, mode, EXPAND_NORMAL); + } + + /* If the second argument is "", return 0. */ + if (p2 && *p2 == '\0') + { + /* Evaluate and ignore argument s1 in case it has + side-effects. */ + expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL); + return const0_rtx; + } + return 0; + } +} + +/* Expand expression EXP, which is a call to the strcspn builtin. + Return 0 if we failed the caller should emit a normal call, + otherwise try to get the result in TARGET, if convenient. */ +static rtx +expand_builtin_strcspn (arglist, target, mode) + tree arglist; + rtx target; + enum machine_mode mode; +{ + /* If we need to check memory accesses, call the library function. */ + if (current_function_check_memory_usage) + return 0; + + if (arglist == 0 + /* Arg could be non-pointer if user redeclared this fcn wrong. */ + || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE + || TREE_CHAIN (arglist) == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) + != POINTER_TYPE)) + return 0; + else + { + tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist)); + const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); + + /* If both arguments are constants, evaluate at compile-time. */ + if (p1 && p2) + { + const size_t r = strcspn (p1, p2); + return expand_expr (size_int (r), target, mode, EXPAND_NORMAL); + } + + /* If the second argument is "", return __builtin_strlen(s1). */ + if (p2 && *p2 == '\0') + { + tree call_expr, newarglist = build_tree_list (NULL_TREE, s1), + fn = built_in_decls[BUILT_IN_STRLEN]; + + /* If the replacement _DECL isn't initialized, don't do the + transformation. */ + if (!fn) + return 0; + + call_expr = build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (fn)), fn); + call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + call_expr, newarglist, NULL_TREE); + TREE_SIDE_EFFECTS (call_expr) = 1; + return expand_expr (call_expr, target, mode, EXPAND_NORMAL); + } + return 0; + } +} + /* Expand a call to __builtin_saveregs, generating the result in TARGET, if that's convenient. */ @@ -3127,6 +3335,8 @@ expand_builtin (exp, target, subtarget, mode, ignore) || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY || fcode == BUILT_IN_STRNCPY || fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRPBRK + || fcode == BUILT_IN_STRCAT || fcode == BUILT_IN_STRNCAT + || fcode == BUILT_IN_STRSPN || fcode == BUILT_IN_STRCSPN || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS || fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC @@ -3262,6 +3472,30 @@ expand_builtin (exp, target, subtarget, mode, ignore) return target; break; + case BUILT_IN_STRCAT: + target = expand_builtin_strcat (arglist, target, mode); + if (target) + return target; + break; + + case BUILT_IN_STRNCAT: + target = expand_builtin_strncat (arglist, target, mode); + if (target) + return target; + break; + + case BUILT_IN_STRSPN: + target = expand_builtin_strspn (arglist, target, mode); + if (target) + return target; + break; + + case BUILT_IN_STRCSPN: + target = expand_builtin_strcspn (arglist, target, mode); + if (target) + return target; + break; + case BUILT_IN_STRSTR: target = expand_builtin_strstr (arglist, target, mode); if (target) diff --git a/gcc/builtins.def b/gcc/builtins.def index 9d2884e..fba269b 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -39,6 +39,8 @@ DEF_BUILTIN(BUILT_IN_BZERO) DEF_BUILTIN(BUILT_IN_BCMP) DEF_BUILTIN(BUILT_IN_INDEX) DEF_BUILTIN(BUILT_IN_RINDEX) +DEF_BUILTIN(BUILT_IN_STRCAT) +DEF_BUILTIN(BUILT_IN_STRNCAT) DEF_BUILTIN(BUILT_IN_STRCPY) DEF_BUILTIN(BUILT_IN_STRNCPY) DEF_BUILTIN(BUILT_IN_STRCMP) @@ -46,6 +48,8 @@ DEF_BUILTIN(BUILT_IN_STRNCMP) DEF_BUILTIN(BUILT_IN_STRLEN) DEF_BUILTIN(BUILT_IN_STRSTR) DEF_BUILTIN(BUILT_IN_STRPBRK) +DEF_BUILTIN(BUILT_IN_STRSPN) +DEF_BUILTIN(BUILT_IN_STRCSPN) DEF_BUILTIN(BUILT_IN_STRCHR) DEF_BUILTIN(BUILT_IN_STRRCHR) DEF_BUILTIN(BUILT_IN_FSQRT) diff --git a/gcc/c-common.c b/gcc/c-common.c index 6e33945..cdbc8aa 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4939,8 +4939,8 @@ c_common_nodes_and_builtins () tree void_ftype_any, void_ftype_int, int_ftype_any, sizet_ftype_any; tree double_ftype_double, double_ftype_double_double; tree float_ftype_float, ldouble_ftype_ldouble; - tree int_ftype_cptr_cptr_sizet; - tree int_ftype_string_string, string_ftype_ptr_ptr; + tree int_ftype_cptr_cptr_sizet, sizet_ftype_cstring_cstring; + tree int_ftype_string_string, string_ftype_string_cstring; tree string_ftype_string_int, string_ftype_string_string; tree string_ftype_string_cstring_sizet, int_ftype_cstring_cstring_sizet; tree long_ftype_long; @@ -5058,15 +5058,15 @@ c_common_nodes_and_builtins () void_zero_node = build_int_2 (0, 0); TREE_TYPE (void_zero_node) = void_type_node; - /* Prototype for strcpy. */ - string_ftype_ptr_ptr + /* Prototype for strcpy/strcat. */ + string_ftype_string_cstring = build_function_type (string_type_node, tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, const_string_type_node, endlink))); - /* Prototype for strncpy. */ + /* Prototype for strncpy/strncat. */ string_ftype_string_cstring_sizet = build_function_type (string_type_node, tree_cons (NULL_TREE, string_type_node, @@ -5088,6 +5088,14 @@ c_common_nodes_and_builtins () const_string_type_node, endlink))); + /* Prototype for strspn/strcspn. */ + sizet_ftype_cstring_cstring + = build_function_type (c_size_type_node, + tree_cons (NULL_TREE, const_string_type_node, + tree_cons (NULL_TREE, + const_string_type_node, + endlink))); + /* Prototype for strncmp. */ int_ftype_cstring_cstring_sizet = build_function_type (integer_type_node, @@ -5357,12 +5365,22 @@ c_common_nodes_and_builtins () BUILT_IN_STRCHR, BUILT_IN_NORMAL, "strchr"); builtin_function ("__builtin_strrchr", string_ftype_string_int, BUILT_IN_STRRCHR, BUILT_IN_NORMAL, "strrchr"); - builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, + builtin_function ("__builtin_strcpy", string_ftype_string_cstring, BUILT_IN_STRCPY, BUILT_IN_NORMAL, "strcpy"); builtin_function ("__builtin_strncpy", string_ftype_string_cstring_sizet, BUILT_IN_STRNCPY, BUILT_IN_NORMAL, "strncpy"); - builtin_function ("__builtin_strlen", strlen_ftype, - BUILT_IN_STRLEN, BUILT_IN_NORMAL, "strlen"); + built_in_decls[BUILT_IN_STRCAT] = + builtin_function ("__builtin_strcat", string_ftype_string_cstring, + BUILT_IN_STRCAT, BUILT_IN_NORMAL, "strcat"); + builtin_function ("__builtin_strncat", string_ftype_string_cstring_sizet, + BUILT_IN_STRNCAT, BUILT_IN_NORMAL, "strncat"); + builtin_function ("__builtin_strspn", string_ftype_string_cstring, + BUILT_IN_STRSPN, BUILT_IN_NORMAL, "strspn"); + builtin_function ("__builtin_strcspn", string_ftype_string_cstring_sizet, + BUILT_IN_STRCSPN, BUILT_IN_NORMAL, "strcspn"); + built_in_decls[BUILT_IN_STRLEN] = + builtin_function ("__builtin_strlen", strlen_ftype, + BUILT_IN_STRLEN, BUILT_IN_NORMAL, "strlen"); builtin_function ("__builtin_sqrtf", float_ftype_float, BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf"); builtin_function ("__builtin_fsqrt", double_ftype_double, @@ -5441,10 +5459,18 @@ c_common_nodes_and_builtins () BUILT_IN_NORMAL, NULL_PTR); builtin_function ("strpbrk", string_ftype_string_string, BUILT_IN_STRPBRK, BUILT_IN_NORMAL, NULL_PTR); - builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, + builtin_function ("strcpy", string_ftype_string_cstring, BUILT_IN_STRCPY, BUILT_IN_NORMAL, NULL_PTR); builtin_function ("strncpy", string_ftype_string_cstring_sizet, BUILT_IN_STRNCPY, BUILT_IN_NORMAL, NULL_PTR); + builtin_function ("strcat", string_ftype_string_cstring, BUILT_IN_STRCAT, + BUILT_IN_NORMAL, NULL_PTR); + builtin_function ("strncat", string_ftype_string_cstring_sizet, + BUILT_IN_STRNCAT, BUILT_IN_NORMAL, NULL_PTR); + builtin_function ("strspn", sizet_ftype_cstring_cstring, BUILT_IN_STRSPN, + BUILT_IN_NORMAL, NULL_PTR); + builtin_function ("strcspn", sizet_ftype_cstring_cstring, + BUILT_IN_STRCSPN, BUILT_IN_NORMAL, NULL_PTR); builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, BUILT_IN_NORMAL, NULL_PTR); builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, diff --git a/gcc/extend.texi b/gcc/extend.texi index bf60bca..bfb9da5 100644 --- a/gcc/extend.texi +++ b/gcc/extend.texi @@ -3311,14 +3311,18 @@ function as well. @findex sqrt @findex sqrtf @findex sqrtl +@findex strcat @findex strchr @findex strcmp @findex strcpy +@findex strcspn @findex strlen +@findex strncat @findex strncmp @findex strncpy @findex strpbrk @findex strrchr +@findex strspn @findex strstr GNU CC provides a large number of built-in functions other than the ones @@ -3361,9 +3365,10 @@ corresponding versions prefixed with @code{__builtin_}. The following ISO C89 functions are recognized as builtins unless @samp{-fno-builtin} is specified: @code{abs}, @code{cos}, @code{fabs}, @code{fputs}, @code{labs}, @code{memcmp}, @code{memcpy}, @code{memset}, -@code{printf}, @code{sin}, @code{sqrt}, @code{strchr}, @code{strcmp}, -@code{strcpy}, @code{strlen}, @code{strncmp}, @code{strncpy}, -@code{strpbrk}, @code{strrchr}, and @code{strstr}. All of these +@code{printf}, @code{sin}, @code{sqrt}, @code{strcat}, @code{strchr}, +@code{strcmp}, @code{strcpy}, @code{strcspn}, @code{strlen}, +@code{strncat}, @code{strncmp}, @code{strncpy}, @code{strpbrk}, +@code{strrchr}, @code{strspn}, and @code{strstr}. All of these functions have corresponding versions prefixed with @code{__builtin_}, except that the version for @code{sqrt} is called @code{__builtin_fsqrt}. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 073697d..b205469 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,7 +1,12 @@ 2000-12-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> - gcc.c-torture/execute/string-opt-3.c: Add more strcmp checks. - gcc.c-torture/execute/string-opt-8.c: Add more strncmp checks. + * gcc.c-torture/execute/string-opt-9.c: New test. + * gcc.c-torture/execute/string-opt-10.c: Likewise. + * gcc.c-torture/execute/string-opt-11.c: Likewise. + * gcc.c-torture/execute/string-opt-12.c: Likewise. + + * gcc.c-torture/execute/string-opt-3.c: Add more strcmp checks. + * gcc.c-torture/execute/string-opt-8.c: Add more strncmp checks. 2000-12-02 Geoffrey Keating <geoffk@redhat.com> diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-10.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-10.c new file mode 100644 index 0000000..3949bb8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-10.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2000 Free Software Foundation. + + Ensure all expected transformations of builtin strncat occur and + perform correctly. + + Written by Kaveh R. Ghazi, 11/27/2000. */ + +extern void abort (void); +typedef __SIZE_TYPE__ size_t; +extern char *strncat (char *, const char *, size_t); +extern char *strcpy (char *, const char *); +extern char *strcmp (const char *, const char *); +int x = 123; + +int main () +{ + const char *const s1 = "hello world"; + const char *const s2 = ""; + char dst[64], *d2; + + strcpy (dst, s1); + if (strncat (dst, "", 100) != dst || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); + if (strncat (dst, s2, 100) != dst || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2, s2, 100) != dst+1 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2+5, s2, 100) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2+5, s1+11, 100) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2+5, s1, 0) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2+5, "", ++x) != dst+6 || d2 != dst+1 || x != 124 + || strcmp (dst, s1)) + abort(); + + strcpy (dst, s1); + if (strncat (dst, "foo", 3) != dst || strcmp (dst, "hello worldfoo")) + abort(); + strcpy (dst, s1); + if (strncat (dst, "foo", 100) != dst || strcmp (dst, "hello worldfoo")) + abort(); + strcpy (dst, s1); + if (strncat (dst, s1, 100) != dst || strcmp (dst, "hello worldhello world")) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2, s1, 100) != dst+1 || d2 != dst+1 + || strcmp (dst, "hello worldhello world")) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2+5, s1, 100) != dst+6 || d2 != dst+1 + || strcmp (dst, "hello worldhello world")) + abort(); + strcpy (dst, s1); d2 = dst; + if (strncat (++d2+5, s1+5, 100) != dst+6 || d2 != dst+1 + || strcmp (dst, "hello world world")) + abort(); + + return 0; +} + +#ifdef __OPTIMIZE__ +/* When optimizing, all the above cases should be transformed into + something else. So any remaining calls to the original function + should abort. */ +static char * +strncat (char *s1, const char *s2, size_t n) +{ + abort(); +} +#endif diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-11.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-11.c new file mode 100644 index 0000000..9d043c9 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-11.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2000 Free Software Foundation. + + Ensure all expected transformations of builtin strspn occur and + perform correctly. + + Written by Kaveh R. Ghazi, 11/27/2000. */ + +extern void abort (void); +typedef __SIZE_TYPE__ size_t; +extern size_t strspn (const char *, const char *); +extern char *strcpy (char *, const char *); + +int main () +{ + const char *const s1 = "hello world"; + char dst[64], *d2; + + if (strspn (s1, "hello") != 5) + abort(); + if (strspn (s1+4, "hello") != 1) + abort(); + if (strspn (s1, "z") != 0) + abort(); + if (strspn (s1, "hello world") != 11) + abort(); + if (strspn (s1, "") != 0) + abort(); + strcpy (dst, s1); + if (strspn (dst, "") != 0) + abort(); + strcpy (dst, s1); d2 = dst; + if (strspn (++d2, "") != 0 || d2 != dst+1) + abort(); + strcpy (dst, s1); d2 = dst; + if (strspn (++d2+5, "") != 0 || d2 != dst+1) + abort(); + + return 0; +} + +#ifdef __OPTIMIZE__ +/* When optimizing, all the above cases should be transformed into + something else. So any remaining calls to the original function + should abort. */ +static size_t +strspn (const char *s1, const char *s2) +{ + abort(); +} +#endif diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-12.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-12.c new file mode 100644 index 0000000..0126b85 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-12.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2000 Free Software Foundation. + + Ensure all expected transformations of builtin strcspn occur and + perform correctly. + + Written by Kaveh R. Ghazi, 11/27/2000. */ + +extern void abort (void); +typedef __SIZE_TYPE__ size_t; +extern size_t strcspn (const char *, const char *); +extern char *strcpy (char *, const char *); + +int main () +{ + const char *const s1 = "hello world"; + char dst[64], *d2; + + if (strcspn (s1, "hello") != 0) + abort(); + if (strcspn (s1, "z") != 11) + abort(); + if (strcspn (s1+4, "z") != 7) + abort(); + if (strcspn (s1, "hello world") != 0) + abort(); + if (strcspn (s1, "") != 11) + abort(); + strcpy (dst, s1); + if (strcspn (dst, "") != 11) + abort(); + strcpy (dst, s1); d2 = dst; + if (strcspn (++d2, "") != 10 || d2 != dst+1) + abort(); + strcpy (dst, s1); d2 = dst; + if (strcspn (++d2+5, "") != 5 || d2 != dst+1) + abort(); + + return 0; +} + +#ifdef __OPTIMIZE__ +/* When optimizing, all the above cases should be transformed into + something else. So any remaining calls to the original function + should abort. */ +static size_t +strcspn (const char *s1, const char *s2) +{ + abort(); +} +#endif diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c new file mode 100644 index 0000000..c1174d9 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2000 Free Software Foundation. + + Ensure all expected transformations of builtin strcat occur and + perform correctly. + + Written by Kaveh R. Ghazi, 11/27/2000. */ + +extern void abort (void); +typedef __SIZE_TYPE__ size_t; +extern char *strcat (char *, const char *); +extern char *strcpy (char *, const char *); +extern char *strcmp (const char *, const char *); + +int main () +{ + const char *const s1 = "hello world"; + const char *const s2 = ""; + char dst[64], *d2; + + strcpy (dst, s1); + if (strcat (dst, "") != dst || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); + if (strcat (dst, s2) != dst || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strcat (++d2, s2) != dst+1 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strcat (++d2+5, s2) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + strcpy (dst, s1); d2 = dst; + if (strcat (++d2+5, s1+11) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) + abort(); + + return 0; +} + +#ifdef __OPTIMIZE__ +/* When optimizing, all the above cases should be transformed into + something else. So any remaining calls to the original function + should abort. */ +static char * +strcat (char *s1, const char *s2) +{ + abort(); +} +#endif |