Commit da9e9f08 by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (expand_builtin_strncmp, [...]): New functions.

	* builtins.c (expand_builtin_strncmp, expand_builtin_strncpy): New
	functions.
	(expand_builtin): Handle BUILT_IN_STRNCPY and BUILT_IN_STRNCMP.

	* builtins.def (BUILT_IN_STRNCPY, BUILT_IN_STRNCMP): New entries.

	* c-common.c (c_common_nodes_and_builtins): Declare builtin
	strncpy and strncmp.

	* extend.texi (strncmp, strncpy): Document new builtins.

testsuite:
	* gcc.c-torture/execute/string-opt-7.c: New test.
	* gcc.c-torture/execute/string-opt-8.c: Likewise.

From-SVN: r37777
parent 231db5f4
2000-11-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (expand_builtin_strncmp, expand_builtin_strncpy): New
functions.
(expand_builtin): Handle BUILT_IN_STRNCPY and BUILT_IN_STRNCMP.
* builtins.def (BUILT_IN_STRNCPY, BUILT_IN_STRNCMP): New entries.
* c-common.c (c_common_nodes_and_builtins): Declare builtin
strncpy and strncmp.
* extend.texi (strncmp, strncpy): Document new builtins.
2000-11-26 Mark Mitchell <mark@codesourcery.com> 2000-11-26 Mark Mitchell <mark@codesourcery.com>
* config/elfos.h (ASM_OUTPUT_SECTION_NAME): Use a hash table, not * config/elfos.h (ASM_OUTPUT_SECTION_NAME): Use a hash table, not
......
...@@ -104,8 +104,12 @@ static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx)); ...@@ -104,8 +104,12 @@ static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx));
#endif #endif
static rtx expand_builtin_strcmp PARAMS ((tree, rtx, static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_memcpy PARAMS ((tree)); static rtx expand_builtin_memcpy PARAMS ((tree));
static rtx expand_builtin_strcpy PARAMS ((tree)); static rtx expand_builtin_strcpy PARAMS ((tree));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_memset PARAMS ((tree)); static rtx expand_builtin_memset PARAMS ((tree));
static rtx expand_builtin_bzero PARAMS ((tree)); static rtx expand_builtin_bzero PARAMS ((tree));
static rtx expand_builtin_strlen PARAMS ((tree, rtx)); static rtx expand_builtin_strlen PARAMS ((tree, rtx));
...@@ -1770,6 +1774,63 @@ expand_builtin_strcpy (exp) ...@@ -1770,6 +1774,63 @@ expand_builtin_strcpy (exp)
return result; return result;
} }
/* Expand expression EXP, which is a call to the strncpy builtin. Return 0
if we failed the caller should emit a normal call. */
static rtx
expand_builtin_strncpy (arglist, target, mode)
tree arglist;
rtx target;
enum machine_mode mode;
{
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 slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
/* We must be passed a constant len parameter. */
if (TREE_CODE (len) != INTEGER_CST)
return 0;
/* If the len parameter is zero, return the dst parameter. */
if (compare_tree_int (len, 0) == 0)
{
/* Evaluate and ignore the src argument in case it has
side-effects. */
expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
VOIDmode, EXPAND_NORMAL);
/* Return the dst parameter. */
return expand_expr (TREE_VALUE (arglist), target, mode,
EXPAND_NORMAL);
}
/* Now, we must be passed a constant src ptr parameter. */
if (slen == 0)
return 0;
slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
/* We're required to pad with trailing zeros if the requested
len is greater than strlen(s2)+1, so in that case punt. */
if (tree_int_cst_lt (slen, len))
return 0;
/* OK transform into builtin memcpy. */
return expand_builtin_memcpy (arglist);
}
}
/* Expand expression EXP, which is a call to the memset builtin. Return 0 /* Expand expression EXP, which is a call to the memset builtin. Return 0
if we failed the caller should emit a normal call. */ if we failed the caller should emit a normal call. */
...@@ -2051,6 +2112,83 @@ expand_builtin_strcmp (exp, target, mode) ...@@ -2051,6 +2112,83 @@ expand_builtin_strcmp (exp, target, mode)
#endif #endif
} }
/* Expand expression EXP, which is a call to the strncmp 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_strncmp (exp, target, mode)
tree exp;
rtx target;
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
tree arg1, arg2, arg3;
const char *p1, *p2;
/* 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;
arg1 = TREE_VALUE (arglist);
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
/* We must be passed a constant len parameter. */
if (TREE_CODE (arg3) != INTEGER_CST)
return 0;
/* If the len parameter is zero, return zero. */
if (compare_tree_int (arg3, 0) == 0)
{
/* Evaluate and ignore arg1 and arg2 in case they have
side-effects. */
expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
return const0_rtx;
}
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
/* If all arguments are constant, evaluate at compile-time. */
if (p1 && p2)
{
const int r = strncmp (p1, p2, TREE_INT_CST_LOW (arg3));
return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
}
/* If either string parameter is constant and its strlen is strictly
less than the length parameter, call expand_builtin_strcmp(). */
if ((p1 && compare_tree_int (arg3, strlen (p1)) > 0)
|| (p2 && compare_tree_int (arg3, strlen (p2)) > 0))
{
tree newarglist =
tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2));
rtx result;
/* Call expand_builtin_strcmp with the modified newarglist. If
the expansion does not occur, do not allow strncmp to expand to
strcmp since strcmp requires that both strings be NULL
terminated whereas strncmp does not. */
TREE_OPERAND (exp, 1) = newarglist;
result = expand_builtin_strcmp (exp, target, mode);
/* Always restore the original arguments. */
TREE_OPERAND (exp, 1) = arglist;
return result;
}
return 0;
}
/* Expand a call to __builtin_saveregs, generating the result in TARGET, /* Expand a call to __builtin_saveregs, generating the result in TARGET,
if that's convenient. */ if that's convenient. */
...@@ -2752,6 +2890,7 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -2752,6 +2890,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|| fcode == BUILT_IN_INDEX || fcode == BUILT_IN_RINDEX || fcode == BUILT_IN_INDEX || fcode == BUILT_IN_RINDEX
|| fcode == BUILT_IN_STRCHR || fcode == BUILT_IN_STRRCHR || fcode == BUILT_IN_STRCHR || fcode == BUILT_IN_STRRCHR
|| fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY || 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_STRSTR || fcode == BUILT_IN_STRPBRK
|| fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
|| fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
...@@ -2881,6 +3020,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -2881,6 +3020,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target; return target;
break; break;
case BUILT_IN_STRNCPY:
target = expand_builtin_strncpy (arglist, target, mode);
if (target)
return target;
break;
case BUILT_IN_STRSTR: case BUILT_IN_STRSTR:
target = expand_builtin_strstr (arglist, target, mode); target = expand_builtin_strstr (arglist, target, mode);
if (target) if (target)
...@@ -2931,6 +3076,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -2931,6 +3076,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target; return target;
break; break;
case BUILT_IN_STRNCMP:
target = expand_builtin_strncmp (exp, target, mode);
if (target)
return target;
break;
/* These comparison functions need an instruction that returns an actual /* These comparison functions need an instruction that returns an actual
index. An ordinary compare that just sets the condition codes index. An ordinary compare that just sets the condition codes
is not enough. */ is not enough. */
......
...@@ -39,7 +39,9 @@ DEF_BUILTIN(BUILT_IN_BCMP) ...@@ -39,7 +39,9 @@ DEF_BUILTIN(BUILT_IN_BCMP)
DEF_BUILTIN(BUILT_IN_INDEX) DEF_BUILTIN(BUILT_IN_INDEX)
DEF_BUILTIN(BUILT_IN_RINDEX) DEF_BUILTIN(BUILT_IN_RINDEX)
DEF_BUILTIN(BUILT_IN_STRCPY) DEF_BUILTIN(BUILT_IN_STRCPY)
DEF_BUILTIN(BUILT_IN_STRNCPY)
DEF_BUILTIN(BUILT_IN_STRCMP) DEF_BUILTIN(BUILT_IN_STRCMP)
DEF_BUILTIN(BUILT_IN_STRNCMP)
DEF_BUILTIN(BUILT_IN_STRLEN) DEF_BUILTIN(BUILT_IN_STRLEN)
DEF_BUILTIN(BUILT_IN_STRSTR) DEF_BUILTIN(BUILT_IN_STRSTR)
DEF_BUILTIN(BUILT_IN_STRPBRK) DEF_BUILTIN(BUILT_IN_STRPBRK)
......
...@@ -4887,6 +4887,7 @@ c_common_nodes_and_builtins () ...@@ -4887,6 +4887,7 @@ c_common_nodes_and_builtins ()
tree int_ftype_cptr_cptr_sizet; tree int_ftype_cptr_cptr_sizet;
tree int_ftype_string_string, string_ftype_ptr_ptr; tree int_ftype_string_string, string_ftype_ptr_ptr;
tree string_ftype_string_int, string_ftype_string_string; tree string_ftype_string_int, string_ftype_string_string;
tree string_ftype_string_cstring_sizet, int_ftype_cstring_cstring_sizet;
tree long_ftype_long; tree long_ftype_long;
tree longlong_ftype_longlong; tree longlong_ftype_longlong;
/* Either char* or void*. */ /* Either char* or void*. */
...@@ -4987,6 +4988,14 @@ c_common_nodes_and_builtins () ...@@ -4987,6 +4988,14 @@ c_common_nodes_and_builtins ()
const_string_type_node, const_string_type_node,
endlink))); endlink)));
/* Prototype for strncpy. */
string_ftype_string_cstring_sizet
= build_function_type (string_type_node,
tree_cons (NULL_TREE, string_type_node,
tree_cons (NULL_TREE,
const_string_type_node,
sizetype_endlink)));
traditional_len_type_node = ((flag_traditional && traditional_len_type_node = ((flag_traditional &&
c_language != clk_cplusplus) c_language != clk_cplusplus)
? integer_type_node : sizetype); ? integer_type_node : sizetype);
...@@ -5001,6 +5010,14 @@ c_common_nodes_and_builtins () ...@@ -5001,6 +5010,14 @@ c_common_nodes_and_builtins ()
const_string_type_node, const_string_type_node,
endlink))); endlink)));
/* Prototype for strncmp. */
int_ftype_cstring_cstring_sizet
= build_function_type (integer_type_node,
tree_cons (NULL_TREE, const_string_type_node,
tree_cons (NULL_TREE,
const_string_type_node,
sizetype_endlink)));
/* Prototype for strstr, strpbrk, etc. */ /* Prototype for strstr, strpbrk, etc. */
string_ftype_string_string string_ftype_string_string
= build_function_type (string_type_node, = build_function_type (string_type_node,
...@@ -5246,8 +5263,11 @@ c_common_nodes_and_builtins () ...@@ -5246,8 +5263,11 @@ c_common_nodes_and_builtins ()
BUILT_IN_INDEX, BUILT_IN_NORMAL, "index"); BUILT_IN_INDEX, BUILT_IN_NORMAL, "index");
builtin_function ("__builtin_rindex", string_ftype_string_int, builtin_function ("__builtin_rindex", string_ftype_string_int,
BUILT_IN_RINDEX, BUILT_IN_NORMAL, "rindex"); BUILT_IN_RINDEX, BUILT_IN_NORMAL, "rindex");
builtin_function ("__builtin_strcmp", int_ftype_string_string, built_in_decls[BUILT_IN_STRCMP] =
BUILT_IN_STRCMP, BUILT_IN_NORMAL, "strcmp"); builtin_function ("__builtin_strcmp", int_ftype_string_string,
BUILT_IN_STRCMP, BUILT_IN_NORMAL, "strcmp");
builtin_function ("__builtin_strncmp", int_ftype_cstring_cstring_sizet,
BUILT_IN_STRNCMP, BUILT_IN_NORMAL, "strncmp");
builtin_function ("__builtin_strstr", string_ftype_string_string, builtin_function ("__builtin_strstr", string_ftype_string_string,
BUILT_IN_STRSTR, BUILT_IN_NORMAL, "strstr"); BUILT_IN_STRSTR, BUILT_IN_NORMAL, "strstr");
builtin_function ("__builtin_strpbrk", string_ftype_string_string, builtin_function ("__builtin_strpbrk", string_ftype_string_string,
...@@ -5259,6 +5279,8 @@ c_common_nodes_and_builtins () ...@@ -5259,6 +5279,8 @@ c_common_nodes_and_builtins ()
BUILT_IN_STRRCHR, BUILT_IN_NORMAL, "strrchr"); BUILT_IN_STRRCHR, BUILT_IN_NORMAL, "strrchr");
builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
BUILT_IN_STRCPY, BUILT_IN_NORMAL, "strcpy"); 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, builtin_function ("__builtin_strlen", strlen_ftype,
BUILT_IN_STRLEN, BUILT_IN_NORMAL, "strlen"); BUILT_IN_STRLEN, BUILT_IN_NORMAL, "strlen");
builtin_function ("__builtin_sqrtf", float_ftype_float, builtin_function ("__builtin_sqrtf", float_ftype_float,
...@@ -5325,6 +5347,8 @@ c_common_nodes_and_builtins () ...@@ -5325,6 +5347,8 @@ c_common_nodes_and_builtins ()
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strncmp", int_ftype_cstring_cstring_sizet,
BUILT_IN_STRNCMP, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strstr", string_ftype_string_string, BUILT_IN_STRSTR, builtin_function ("strstr", string_ftype_string_string, BUILT_IN_STRSTR,
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strchr", string_ftype_string_int, BUILT_IN_STRCHR, builtin_function ("strchr", string_ftype_string_int, BUILT_IN_STRCHR,
...@@ -5335,6 +5359,8 @@ c_common_nodes_and_builtins () ...@@ -5335,6 +5359,8 @@ c_common_nodes_and_builtins ()
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strncpy", string_ftype_string_cstring_sizet,
BUILT_IN_STRNCPY, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN,
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT,
......
...@@ -3294,6 +3294,8 @@ function as well. ...@@ -3294,6 +3294,8 @@ function as well.
@findex strcmp @findex strcmp
@findex strcpy @findex strcpy
@findex strlen @findex strlen
@findex strncmp
@findex strncpy
@findex strpbrk @findex strpbrk
@findex strrchr @findex strrchr
@findex strstr @findex strstr
...@@ -3338,10 +3340,11 @@ The following ISO C89 functions are recognized as builtins unless ...@@ -3338,10 +3340,11 @@ The following ISO C89 functions are recognized as builtins unless
@samp{-fno-builtin} is specified: @code{abs}, @code{cos}, @code{fabs}, @samp{-fno-builtin} is specified: @code{abs}, @code{cos}, @code{fabs},
@code{fputs}, @code{labs}, @code{memcmp}, @code{memcpy}, @code{memset}, @code{fputs}, @code{labs}, @code{memcmp}, @code{memcpy}, @code{memset},
@code{printf}, @code{sin}, @code{sqrt}, @code{strchr}, @code{strcmp}, @code{printf}, @code{sin}, @code{sqrt}, @code{strchr}, @code{strcmp},
@code{strcpy}, @code{strlen}, @code{strpbrk}, @code{strrchr}, and @code{strcpy}, @code{strlen}, @code{strncmp}, @code{strncpy},
@code{strstr}. All of these functions have corresponding versions @code{strpbrk}, @code{strrchr}, and @code{strstr}. All of these
prefixed with @code{__builtin_}, except that the version for @code{sqrt} functions have corresponding versions prefixed with @code{__builtin_},
is called @code{__builtin_fsqrt}. except that the version for @code{sqrt} is called
@code{__builtin_fsqrt}.
GNU CC provides builtin versions of the ISO C99 floating point GNU CC provides builtin versions of the ISO C99 floating point
comparison macros (that avoid raising exceptions for unordered comparison macros (that avoid raising exceptions for unordered
......
/* Copyright (C) 2000 Free Software Foundation.
Ensure all expected transformations of builtin strncpy occur and
perform correctly.
Written by Kaveh R. Ghazi, 11/25/2000. */
extern void abort (void);
typedef __SIZE_TYPE__ size_t;
extern char *strncpy (char *, const char *, size_t);
extern int strcmp (const char *, const char *);
extern int strncmp (const char *, const char *, size_t);
extern void *memset (void *, int, size_t);
int main ()
{
const char *const src = "hello world";
const char *src2;
char dst[64], *dst2;
memset (dst, 0, sizeof (dst));
if (strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
abort();
memset (dst, 0, sizeof (dst));
if (strncpy (dst+16, src, 4) != dst+16 || strncmp (dst+16, src, 4))
abort();
memset (dst, 0, sizeof (dst));
if (strncpy (dst+32, src+5, 4) != dst+32 || strncmp (dst+32, src+5, 4))
abort();
memset (dst, 0, sizeof (dst));
dst2 = dst;
if (strncpy (++dst2, src+5, 4) != dst+1 || strncmp (dst2, src+5, 4)
|| dst2 != dst+1)
abort();
memset (dst, 0, sizeof (dst));
if (strncpy (dst, src, 0) != dst || strcmp (dst, ""))
abort();
memset (dst, 0, sizeof (dst));
dst2 = dst; src2 = src;
if (strncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "")
|| dst2 != dst+1 || src2 != src+1)
abort();
memset (dst, 0, sizeof (dst));
dst2 = dst; src2 = src;
if (strncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "")
|| dst2 != dst+1 || src2 != src+1)
abort();
memset (dst, 0, sizeof (dst));
if (strncpy (dst, src, 12) != dst || strcmp (dst, src))
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 *
strncpy(char *s1, const char *s2, size_t n)
{
abort();
}
#endif
/* Copyright (C) 2000 Free Software Foundation.
Ensure all expected transformations of builtin strncmp occur and
perform correctly.
Written by Kaveh R. Ghazi, 11/26/2000. */
extern void abort (void);
typedef __SIZE_TYPE__ size_t;
extern int strncmp (const char *, const char *, size_t);
int main ()
{
const char *const s1 = "hello world";
const char *s2, *s3;
if (strncmp (s1, "hello world", 12) != 0)
abort();
if (strncmp ("hello world", s1, 12) != 0)
abort();
if (strncmp ("hello", "hello", 6) != 0)
abort();
if (strncmp ("hello", "hello", 2) != 0)
abort();
if (strncmp ("hello", "hello", 100) != 0)
abort();
if (strncmp (s1+10, "d", 100) != 0)
abort();
if (strncmp (10+s1, "d", 100) != 0)
abort();
if (strncmp ("d", s1+10, 1) != 0)
abort();
if (strncmp ("d", 10+s1, 1) != 0)
abort();
if (strncmp ("hello", "aaaaa", 100) <= 0)
abort();
if (strncmp ("aaaaa", "hello", 100) >= 0)
abort();
if (strncmp ("hello", "aaaaa", 1) <= 0)
abort();
if (strncmp ("aaaaa", "hello", 1) >= 0)
abort();
s2 = s1; s3 = s1+4;
if (strncmp (++s2, ++s3, 0) != 0 || s2 != s1+1 || s3 != s1+5)
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 *
strncmp(const char *s1, const char *s2, size_t n)
{
abort();
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment