mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-20 12:19:27 +08:00
builtins.c (expand_builtin_strcat, [...]): New functions.
* 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. testsuite: * 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. From-SVN: r37964
This commit is contained in:
parent
ca8034a0ea
commit
d118937d79
@ -1,3 +1,20 @@
|
||||
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
|
||||
|
234
gcc/builtins.c
234
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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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}.
|
||||
|
@ -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>
|
||||
|
||||
|
78
gcc/testsuite/gcc.c-torture/execute/string-opt-10.c
Normal file
78
gcc/testsuite/gcc.c-torture/execute/string-opt-10.c
Normal file
@ -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
|
50
gcc/testsuite/gcc.c-torture/execute/string-opt-11.c
Normal file
50
gcc/testsuite/gcc.c-torture/execute/string-opt-11.c
Normal file
@ -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
|
50
gcc/testsuite/gcc.c-torture/execute/string-opt-12.c
Normal file
50
gcc/testsuite/gcc.c-torture/execute/string-opt-12.c
Normal file
@ -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
|
48
gcc/testsuite/gcc.c-torture/execute/string-opt-9.c
Normal file
48
gcc/testsuite/gcc.c-torture/execute/string-opt-9.c
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user