builtins.c (expand_builtin_strcat, [...]): New functions.
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>
Sun, 3 Dec 2000 03:46:03 +0000 (03:46 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Sun, 3 Dec 2000 03:46:03 +0000 (03:46 +0000)
* 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

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/c-common.c
gcc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/string-opt-10.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/string-opt-11.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/string-opt-12.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/string-opt-9.c [new file with mode: 0644]

index f6383eb68b805233c964ff4e6bba48b11a4e226c..61ac69e7f84cd0c2d0673c2913d9211c505f64a3 100644 (file)
@@ -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
index 0ed47078799d63bd9def84790970650b70938fff..7994f63dcada45d2b8ef046715cfd44eb7401597 100644 (file)
@@ -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)
index 9d2884e072a162defc6f7bc863c9648252faba52..fba269b5c5e4e6874c0ed2b93651382c9c3fea06 100644 (file)
@@ -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)
index 6e3394539a1fdfa1ee8880c30a67db7ba25f1f03..cdbc8aabdc426a91f3e8207dea8f03fecbfd119d 100644 (file)
@@ -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,
index bf60bca726d989813bf596a8e3de0f0707900452..bfb9da5cecd1bb4c228240f955aa537e6889b136 100644 (file)
@@ -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}.
index 073697d4faf8fd963a8fb48a6f4f76bb433bde07..b205469de54770f8d0eef256d90b69022d0a5e66 100644 (file)
@@ -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 (file)
index 0000000..3949bb8
--- /dev/null
@@ -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 (file)
index 0000000..9d043c9
--- /dev/null
@@ -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 (file)
index 0000000..0126b85
--- /dev/null
@@ -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 (file)
index 0000000..c1174d9
--- /dev/null
@@ -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