summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.c-torture/execute/builtins
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.c-torture/execute/builtins')
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1-lib.c50
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.c30
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-1-lib.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.x2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-2-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-2.c106
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-3-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/abs-3.c102
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp54
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/chk.h89
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/complex-1-lib.c70
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/complex-1.c102
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/fprintf-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.c61
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.x7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/fputs-lib.c24
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/fputs.c65
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/abs.c41
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/bfill.c16
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/bzero.c16
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c478
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/fprintf.c37
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/main.c25
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/memchr.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/memcmp.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/memmove.c32
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/mempcpy.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/memset.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/printf.c38
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/sprintf.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/stpcpy.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcat.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strchr.c28
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcmp.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcpy.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcspn.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strlen.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncat.c29
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncmp.c27
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncpy.c21
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strpbrk.c21
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strrchr.c32
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strspn.c25
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/lib/strstr.c29
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memchr-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memchr.c38
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memcmp-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memcmp.c41
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.c479
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2-lib.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2.c36
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.c579
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memmove-lib.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memmove.c90
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c97
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c51
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2.c153
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.c487
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy.c68
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.c721
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memset-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memset.c36
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c27
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c44
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.c67
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/printf-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/printf.c52
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.c220
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.c197
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/sprintf.c71
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.c265
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.c204
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcat-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcat.c81
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strchr-lib.c8
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strchr.c36
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcmp-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcmp.c48
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c47
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.c234
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcpy.c41
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcspn-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strcspn.c54
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2.c41
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3.c70
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strlen-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strlen.c71
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.c229
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncat-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncat.c82
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c173
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncmp.c73
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.c227
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncpy.c75
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk.c42
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2.c45
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy.c60
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strrchr-lib.c8
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strrchr.c49
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strspn-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strspn.c54
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm-lib.c37
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c45
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strstr-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strstr.c33
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.c321
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk-lib.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.c290
135 files changed, 8576 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1-lib.c
new file mode 100644
index 000000000..5f6a7487f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1-lib.c
@@ -0,0 +1,50 @@
+/* Verify that structure return doesn't invoke memcpy on
+ overlapping objects. */
+
+extern void abort (void);
+extern int inside_main;
+typedef __SIZE_TYPE__ size_t;
+
+struct S {
+ char stuff[1024];
+};
+
+union U {
+ struct {
+ int space;
+ struct S s;
+ } a;
+ struct {
+ struct S s;
+ int space;
+ } b;
+};
+
+struct S f(struct S *p)
+{
+ return *p;
+}
+
+void g(union U *p)
+{
+}
+
+void *memcpy(void *a, const void *b, size_t len)
+{
+ if (inside_main)
+ {
+ if (a < b && a+len > b)
+ abort ();
+ if (b < a && b+len > a)
+ abort ();
+ return a;
+ }
+ else
+ {
+ char *dst = (char *) a;
+ const char *src = (const char *) b;
+ while (len--)
+ *dst++ = *src++;
+ return a;
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.c b/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.c
new file mode 100644
index 000000000..816287344
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.c
@@ -0,0 +1,30 @@
+/* Verify that structure return doesn't invoke memcpy on
+ overlapping objects. */
+
+extern void abort (void);
+
+struct S {
+ char stuff[1024];
+};
+
+union U {
+ struct {
+ int space;
+ struct S s;
+ } a;
+ struct {
+ struct S s;
+ int space;
+ } b;
+};
+
+struct S f(struct S *);
+void g(union U *);
+
+void main_test(void)
+{
+ union U u;
+ u.b.s = f(&u.a.s);
+ u.a.s = f(&u.b.s);
+ g(&u);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1-lib.c
new file mode 100644
index 000000000..57446b263
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1-lib.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+extern int abs_called;
+extern int inside_main;
+
+/* The labs call should have been optimized, but the abs call
+ shouldn't have been. */
+
+int
+abs (int x)
+{
+ if (inside_main)
+ abs_called = 1;
+ return (x < 0 ? -x : x);
+}
+
+long
+labs (long x)
+{
+ if (inside_main)
+ abort ();
+ return (x < 0 ? -x : x);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.c b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.c
new file mode 100644
index 000000000..6ca246d39
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.c
@@ -0,0 +1,22 @@
+/* Test for -fno-builtin-FUNCTION. */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk>. */
+/* GCC normally handles abs and labs as built-in functions even without
+ optimization. So test that with -fno-builtin-abs, labs is so handled
+ but abs isn't. */
+
+int abs_called = 0;
+
+extern int abs (int);
+extern long labs (long);
+extern void abort (void);
+
+void
+main_test (void)
+{
+ if (labs (0) != 0)
+ abort ();
+ if (abs (0) != 0)
+ abort ();
+ if (!abs_called)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.x b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.x
new file mode 100644
index 000000000..80d76c528
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-1.x
@@ -0,0 +1,2 @@
+set additional_flags -fno-builtin-abs
+return 0
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-2-lib.c
new file mode 100644
index 000000000..494e5390e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-2-lib.c
@@ -0,0 +1 @@
+#include "lib/abs.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-2.c
new file mode 100644
index 000000000..c13c4556e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-2.c
@@ -0,0 +1,106 @@
+/* Test for builtin abs, labs, llabs, imaxabs. */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+
+#include <limits.h>
+typedef __INTMAX_TYPE__ intmax_t;
+#define INTMAX_MAX __INTMAX_MAX__
+
+extern int abs (int);
+extern long labs (long);
+extern long long llabs (long long);
+extern intmax_t imaxabs (intmax_t);
+extern void abort (void);
+extern void link_error (void);
+
+void
+main_test (void)
+{
+ /* For each type, test both runtime and compile time (constant folding)
+ optimization. */
+ volatile int i0 = 0, i1 = 1, im1 = -1, imin = -INT_MAX, imax = INT_MAX;
+ volatile long l0 = 0L, l1 = 1L, lm1 = -1L, lmin = -LONG_MAX, lmax = LONG_MAX;
+ volatile long long ll0 = 0LL, ll1 = 1LL, llm1 = -1LL;
+ volatile long long llmin = -__LONG_LONG_MAX__, llmax = __LONG_LONG_MAX__;
+ volatile intmax_t imax0 = 0, imax1 = 1, imaxm1 = -1;
+ volatile intmax_t imaxmin = -INTMAX_MAX, imaxmax = INTMAX_MAX;
+ if (abs (i0) != 0)
+ abort ();
+ if (abs (0) != 0)
+ link_error ();
+ if (abs (i1) != 1)
+ abort ();
+ if (abs (1) != 1)
+ link_error ();
+ if (abs (im1) != 1)
+ abort ();
+ if (abs (-1) != 1)
+ link_error ();
+ if (abs (imin) != INT_MAX)
+ abort ();
+ if (abs (-INT_MAX) != INT_MAX)
+ link_error ();
+ if (abs (imax) != INT_MAX)
+ abort ();
+ if (abs (INT_MAX) != INT_MAX)
+ link_error ();
+ if (labs (l0) != 0L)
+ abort ();
+ if (labs (0L) != 0L)
+ link_error ();
+ if (labs (l1) != 1L)
+ abort ();
+ if (labs (1L) != 1L)
+ link_error ();
+ if (labs (lm1) != 1L)
+ abort ();
+ if (labs (-1L) != 1L)
+ link_error ();
+ if (labs (lmin) != LONG_MAX)
+ abort ();
+ if (labs (-LONG_MAX) != LONG_MAX)
+ link_error ();
+ if (labs (lmax) != LONG_MAX)
+ abort ();
+ if (labs (LONG_MAX) != LONG_MAX)
+ link_error ();
+ if (llabs (ll0) != 0LL)
+ abort ();
+ if (llabs (0LL) != 0LL)
+ link_error ();
+ if (llabs (ll1) != 1LL)
+ abort ();
+ if (llabs (1LL) != 1LL)
+ link_error ();
+ if (llabs (llm1) != 1LL)
+ abort ();
+ if (llabs (-1LL) != 1LL)
+ link_error ();
+ if (llabs (llmin) != __LONG_LONG_MAX__)
+ abort ();
+ if (llabs (-__LONG_LONG_MAX__) != __LONG_LONG_MAX__)
+ link_error ();
+ if (llabs (llmax) != __LONG_LONG_MAX__)
+ abort ();
+ if (llabs (__LONG_LONG_MAX__) != __LONG_LONG_MAX__)
+ link_error ();
+ if (imaxabs (imax0) != 0)
+ abort ();
+ if (imaxabs (0) != 0)
+ link_error ();
+ if (imaxabs (imax1) != 1)
+ abort ();
+ if (imaxabs (1) != 1)
+ link_error ();
+ if (imaxabs (imaxm1) != 1)
+ abort ();
+ if (imaxabs (-1) != 1)
+ link_error ();
+ if (imaxabs (imaxmin) != INTMAX_MAX)
+ abort ();
+ if (imaxabs (-INTMAX_MAX) != INTMAX_MAX)
+ link_error ();
+ if (imaxabs (imaxmax) != INTMAX_MAX)
+ abort ();
+ if (imaxabs (INTMAX_MAX) != INTMAX_MAX)
+ link_error ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-3-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-3-lib.c
new file mode 100644
index 000000000..494e5390e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-3-lib.c
@@ -0,0 +1 @@
+#include "lib/abs.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/abs-3.c b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-3.c
new file mode 100644
index 000000000..cb0d89eb0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/abs-3.c
@@ -0,0 +1,102 @@
+/* Test for builtin abs, labs, llabs, imaxabs. Test for __builtin versions. */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+
+#include <limits.h>
+typedef __INTMAX_TYPE__ intmax_t;
+#define INTMAX_MAX __INTMAX_MAX__
+
+extern void abort (void);
+extern void link_error (void);
+
+void
+main_test (void)
+{
+ /* For each type, test both runtime and compile time (constant folding)
+ optimization. */
+ volatile int i0 = 0, i1 = 1, im1 = -1, imin = -INT_MAX, imax = INT_MAX;
+ volatile long l0 = 0L, l1 = 1L, lm1 = -1L, lmin = -LONG_MAX, lmax = LONG_MAX;
+ volatile long long ll0 = 0LL, ll1 = 1LL, llm1 = -1LL;
+ volatile long long llmin = -__LONG_LONG_MAX__, llmax = __LONG_LONG_MAX__;
+ volatile intmax_t imax0 = 0, imax1 = 1, imaxm1 = -1;
+ volatile intmax_t imaxmin = -INTMAX_MAX, imaxmax = INTMAX_MAX;
+ if (__builtin_abs (i0) != 0)
+ abort ();
+ if (__builtin_abs (0) != 0)
+ link_error ();
+ if (__builtin_abs (i1) != 1)
+ abort ();
+ if (__builtin_abs (1) != 1)
+ link_error ();
+ if (__builtin_abs (im1) != 1)
+ abort ();
+ if (__builtin_abs (-1) != 1)
+ link_error ();
+ if (__builtin_abs (imin) != INT_MAX)
+ abort ();
+ if (__builtin_abs (-INT_MAX) != INT_MAX)
+ link_error ();
+ if (__builtin_abs (imax) != INT_MAX)
+ abort ();
+ if (__builtin_abs (INT_MAX) != INT_MAX)
+ link_error ();
+ if (__builtin_labs (l0) != 0L)
+ abort ();
+ if (__builtin_labs (0L) != 0L)
+ link_error ();
+ if (__builtin_labs (l1) != 1L)
+ abort ();
+ if (__builtin_labs (1L) != 1L)
+ link_error ();
+ if (__builtin_labs (lm1) != 1L)
+ abort ();
+ if (__builtin_labs (-1L) != 1L)
+ link_error ();
+ if (__builtin_labs (lmin) != LONG_MAX)
+ abort ();
+ if (__builtin_labs (-LONG_MAX) != LONG_MAX)
+ link_error ();
+ if (__builtin_labs (lmax) != LONG_MAX)
+ abort ();
+ if (__builtin_labs (LONG_MAX) != LONG_MAX)
+ link_error ();
+ if (__builtin_llabs (ll0) != 0LL)
+ abort ();
+ if (__builtin_llabs (0LL) != 0LL)
+ link_error ();
+ if (__builtin_llabs (ll1) != 1LL)
+ abort ();
+ if (__builtin_llabs (1LL) != 1LL)
+ link_error ();
+ if (__builtin_llabs (llm1) != 1LL)
+ abort ();
+ if (__builtin_llabs (-1LL) != 1LL)
+ link_error ();
+ if (__builtin_llabs (llmin) != __LONG_LONG_MAX__)
+ abort ();
+ if (__builtin_llabs (-__LONG_LONG_MAX__) != __LONG_LONG_MAX__)
+ link_error ();
+ if (__builtin_llabs (llmax) != __LONG_LONG_MAX__)
+ abort ();
+ if (__builtin_llabs (__LONG_LONG_MAX__) != __LONG_LONG_MAX__)
+ link_error ();
+ if (__builtin_imaxabs (imax0) != 0)
+ abort ();
+ if (__builtin_imaxabs (0) != 0)
+ link_error ();
+ if (__builtin_imaxabs (imax1) != 1)
+ abort ();
+ if (__builtin_imaxabs (1) != 1)
+ link_error ();
+ if (__builtin_imaxabs (imaxm1) != 1)
+ abort ();
+ if (__builtin_imaxabs (-1) != 1)
+ link_error ();
+ if (__builtin_imaxabs (imaxmin) != INTMAX_MAX)
+ abort ();
+ if (__builtin_imaxabs (-INTMAX_MAX) != INTMAX_MAX)
+ link_error ();
+ if (__builtin_imaxabs (imaxmax) != INTMAX_MAX)
+ abort ();
+ if (__builtin_imaxabs (INTMAX_MAX) != INTMAX_MAX)
+ link_error ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
new file mode 100644
index 000000000..a54f3c1b5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
@@ -0,0 +1,54 @@
+# Copyright (C) 2003, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This harness is for testing builtin support. Each test has two files:
+#
+# - foo.c defines the main testing function, main_test().
+# - foo-lib.c implements the library functions that foo.c is testing.
+#
+# The functions in foo-lib.c will often want to abort on certain inputs.
+# They can use the global variable inside_main to see whether they are
+# being called from the test program or part of the common runtime.
+#
+# In many cases, the library functions will behave as normal at -O0
+# and abort when optimisation is enabled. Such implementations should
+# go into the lib/ directory so that they can be included by any test
+# that needs them. They shouldn't call any external functions in case
+# those functions were overridden too.
+
+load_lib torture-options.exp
+load_lib c-torture.exp
+
+torture-init
+set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS
+
+set additional_flags ""
+if [istarget "powerpc-*-darwin*"] {
+ lappend additional_flags "-Wl,-multiply_defined,suppress"
+}
+
+foreach src [lsort [find $srcdir/$subdir *.c]] {
+ if {![string match *-lib.c $src] && [runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ [file root $src]-lib.c \
+ $srcdir/$subdir/lib/main.c] \
+ $additional_flags
+ }
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/chk.h b/gcc/testsuite/gcc.c-torture/execute/builtins/chk.h
new file mode 100644
index 000000000..625fdef09
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/chk.h
@@ -0,0 +1,89 @@
+#ifndef os
+# define os(ptr) __builtin_object_size (ptr, 0)
+#endif
+
+/* This is one of the alternatives for object size checking.
+ If dst has side-effects, size checking will never be done. */
+#undef memcpy
+#define memcpy(dst, src, len) \
+ __builtin___memcpy_chk (dst, src, len, os (dst))
+#undef mempcpy
+#define mempcpy(dst, src, len) \
+ __builtin___mempcpy_chk (dst, src, len, os (dst))
+#undef memmove
+#define memmove(dst, src, len) \
+ __builtin___memmove_chk (dst, src, len, os (dst))
+#undef memset
+#define memset(dst, val, len) \
+ __builtin___memset_chk (dst, val, len, os (dst))
+#undef strcpy
+#define strcpy(dst, src) \
+ __builtin___strcpy_chk (dst, src, os (dst))
+#undef stpcpy
+#define stpcpy(dst, src) \
+ __builtin___stpcpy_chk (dst, src, os (dst))
+#undef strcat
+#define strcat(dst, src) \
+ __builtin___strcat_chk (dst, src, os (dst))
+#undef strncpy
+#define strncpy(dst, src, len) \
+ __builtin___strncpy_chk (dst, src, len, os (dst))
+#undef strncat
+#define strncat(dst, src, len) \
+ __builtin___strncat_chk (dst, src, len, os (dst))
+#undef sprintf
+#define sprintf(dst, ...) \
+ __builtin___sprintf_chk (dst, 0, os (dst), __VA_ARGS__)
+#undef vsprintf
+#define vsprintf(dst, fmt, ap) \
+ __builtin___vsprintf_chk (dst, 0, os (dst), fmt, ap)
+#undef snprintf
+#define snprintf(dst, len, ...) \
+ __builtin___snprintf_chk (dst, len, 0, os (dst), __VA_ARGS__)
+#undef vsnprintf
+#define vsnprintf(dst, len, fmt, ap) \
+ __builtin___vsnprintf_chk (dst, len, 0, os (dst), fmt, ap)
+
+/* Now "redefine" even builtins for the purpose of testing. */
+#undef __builtin_memcpy
+#define __builtin_memcpy(dst, src, len) memcpy (dst, src, len)
+#undef __builtin_mempcpy
+#define __builtin_mempcpy(dst, src, len) mempcpy (dst, src, len)
+#undef __builtin_memmove
+#define __builtin_memmove(dst, src, len) memmove (dst, src, len)
+#undef __builtin_memset
+#define __builtin_memset(dst, val, len) memset (dst, val, len)
+#undef __builtin_strcpy
+#define __builtin_strcpy(dst, src) strcpy (dst, src)
+#undef __builtin_stpcpy
+#define __builtin_stpcpy(dst, src) stpcpy (dst, src)
+#undef __builtin_strcat
+#define __builtin_strcat(dst, src) strcat (dst, src)
+#undef __builtin_strncpy
+#define __builtin_strncpy(dst, src, len) strncpy (dst, src, len)
+#undef __builtin_strncat
+#define __builtin_strncat(dst, src, len) strncat (dst, src, len)
+#undef __builtin_sprintf
+#define __builtin_sprintf(dst, ...) sprintf (dst, __VA_ARGS__)
+#undef __builtin_vsprintf
+#define __builtin_vsprintf(dst, fmt, ap) vsprintf (dst, fmt, ap)
+#undef __builtin_snprintf
+#define __builtin_snprintf(dst, len, ...) snprintf (dst, len, __VA_ARGS__)
+#undef __builtin_vsnprintf
+#define __builtin_vsnprintf(dst, len, fmt, ap) vsnprintf (dst, len, fmt, ap)
+
+extern void *chk_fail_buf[];
+extern volatile int chk_fail_allowed, chk_calls;
+extern volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
+extern volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
+extern volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed;
+extern volatile int sprintf_disallowed, vsprintf_disallowed;
+extern volatile int snprintf_disallowed, vsnprintf_disallowed;
+
+/* A storage class that ensures that declarations bind locally. We want
+ to test non-static declarations where we know it is safe to do so. */
+#if __PIC__ && !__PIE__
+#define LOCAL static
+#else
+#define LOCAL
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/complex-1-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/complex-1-lib.c
new file mode 100644
index 000000000..22d7db180
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/complex-1-lib.c
@@ -0,0 +1,70 @@
+extern int inside_main;
+extern void abort (void);
+#ifdef __OPTIMIZE__
+#define ABORT_INSIDE_MAIN do { if (inside_main) abort (); } while (0)
+#else
+#define ABORT_INSIDE_MAIN do { } while (0)
+#endif
+
+static float _Complex
+conjf (float _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return ~z;
+}
+
+static double _Complex
+conj (double _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return ~z;
+}
+
+static long double _Complex
+conjl (long double _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return ~z;
+}
+
+static float
+crealf (float _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return __real__ z;
+}
+
+static double
+creal (double _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return __real__ z;
+}
+
+static long double
+creall (long double _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return __real__ z;
+}
+
+static float
+cimagf (float _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return __imag__ z;
+}
+
+static double
+cimag (double _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return __imag__ z;
+}
+
+static long double
+cimagl (long double _Complex z)
+{
+ ABORT_INSIDE_MAIN;
+ return __imag__ z;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/complex-1.c b/gcc/testsuite/gcc.c-torture/execute/builtins/complex-1.c
new file mode 100644
index 000000000..362a0e41e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/complex-1.c
@@ -0,0 +1,102 @@
+/* Test for builtin conj, creal, cimag. */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+
+extern float _Complex conjf (float _Complex);
+extern double _Complex conj (double _Complex);
+extern long double _Complex conjl (long double _Complex);
+
+extern float crealf (float _Complex);
+extern double creal (double _Complex);
+extern long double creall (long double _Complex);
+
+extern float cimagf (float _Complex);
+extern double cimag (double _Complex);
+extern long double cimagl (long double _Complex);
+
+extern void abort (void);
+extern void link_error (void);
+
+void
+main_test (void)
+{
+ /* For each type, test both runtime and compile time (constant folding)
+ optimization. */
+ volatile float _Complex fc = 1.0F + 2.0iF;
+ volatile double _Complex dc = 1.0 + 2.0i;
+ volatile long double _Complex ldc = 1.0L + 2.0iL;
+ /* Test floats. */
+ if (conjf (fc) != 1.0F - 2.0iF)
+ abort ();
+ if (__builtin_conjf (fc) != 1.0F - 2.0iF)
+ abort ();
+ if (conjf (1.0F + 2.0iF) != 1.0F - 2.0iF)
+ link_error ();
+ if (__builtin_conjf (1.0F + 2.0iF) != 1.0F - 2.0iF)
+ link_error ();
+ if (crealf (fc) != 1.0F)
+ abort ();
+ if (__builtin_crealf (fc) != 1.0F)
+ abort ();
+ if (crealf (1.0F + 2.0iF) != 1.0F)
+ link_error ();
+ if (__builtin_crealf (1.0F + 2.0iF) != 1.0F)
+ link_error ();
+ if (cimagf (fc) != 2.0F)
+ abort ();
+ if (__builtin_cimagf (fc) != 2.0F)
+ abort ();
+ if (cimagf (1.0F + 2.0iF) != 2.0F)
+ link_error ();
+ if (__builtin_cimagf (1.0F + 2.0iF) != 2.0F)
+ link_error ();
+ /* Test doubles. */
+ if (conj (dc) != 1.0 - 2.0i)
+ abort ();
+ if (__builtin_conj (dc) != 1.0 - 2.0i)
+ abort ();
+ if (conj (1.0 + 2.0i) != 1.0 - 2.0i)
+ link_error ();
+ if (__builtin_conj (1.0 + 2.0i) != 1.0 - 2.0i)
+ link_error ();
+ if (creal (dc) != 1.0)
+ abort ();
+ if (__builtin_creal (dc) != 1.0)
+ abort ();
+ if (creal (1.0 + 2.0i) != 1.0)
+ link_error ();
+ if (__builtin_creal (1.0 + 2.0i) != 1.0)
+ link_error ();
+ if (cimag (dc) != 2.0)
+ abort ();
+ if (__builtin_cimag (dc) != 2.0)
+ abort ();
+ if (cimag (1.0 + 2.0i) != 2.0)
+ link_error ();
+ if (__builtin_cimag (1.0 + 2.0i) != 2.0)
+ link_error ();
+ /* Test long doubles. */
+ if (conjl (ldc) != 1.0L - 2.0iL)
+ abort ();
+ if (__builtin_conjl (ldc) != 1.0L - 2.0iL)
+ abort ();
+ if (conjl (1.0L + 2.0iL) != 1.0L - 2.0iL)
+ link_error ();
+ if (__builtin_conjl (1.0L + 2.0iL) != 1.0L - 2.0iL)
+ link_error ();
+ if (creall (ldc) != 1.0L)
+ abort ();
+ if (__builtin_creall (ldc) != 1.0L)
+ abort ();
+ if (creall (1.0L + 2.0iL) != 1.0L)
+ link_error ();
+ if (__builtin_creall (1.0L + 2.0iL) != 1.0L)
+ link_error ();
+ if (cimagl (ldc) != 2.0L)
+ abort ();
+ if (__builtin_cimagl (ldc) != 2.0L)
+ abort ();
+ if (cimagl (1.0L + 2.0iL) != 2.0L)
+ link_error ();
+ if (__builtin_cimagl (1.0L + 2.0iL) != 2.0L)
+ link_error ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf-lib.c
new file mode 100644
index 000000000..b6a1e913d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf-lib.c
@@ -0,0 +1 @@
+#include "lib/fprintf.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.c b/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.c
new file mode 100644
index 000000000..f7db2e061
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2001 Free Software Foundation.
+
+ Ensure all expected transformations of builtin fprintf occur and
+ that we honor side effects in the arguments.
+
+ Written by Kaveh R. Ghazi, 1/7/2001. */
+
+#include <stdio.h>
+extern int fprintf_unlocked (FILE *, const char *, ...);
+extern void abort(void);
+
+void
+main_test (void)
+{
+ FILE *s_array[] = {stdout, NULL}, **s_ptr = s_array;
+ const char *const s1 = "hello world";
+ const char *const s2[] = { s1, 0 }, *const*s3;
+
+ fprintf (*s_ptr, "");
+ fprintf (*s_ptr, "%s", "");
+ fprintf (*s_ptr, "%s", "hello");
+ fprintf (*s_ptr, "%s", "\n");
+ fprintf (*s_ptr, "%s", *s2);
+ s3 = s2;
+ fprintf (*s_ptr, "%s", *s3++);
+ if (s3 != s2+1 || *s3 != 0)
+ abort();
+ s3 = s2;
+ fprintf (*s_ptr++, "%s", *s3++);
+ if (s3 != s2+1 || *s3 != 0 || s_ptr != s_array+1 || *s_ptr != 0)
+ abort();
+
+ s_ptr = s_array;
+ fprintf (*s_ptr, "%c", '\n');
+ fprintf (*s_ptr, "%c", **s2);
+ s3 = s2;
+ fprintf (*s_ptr, "%c", **s3++);
+ if (s3 != s2+1 || *s3 != 0)
+ abort();
+ s3 = s2;
+ fprintf (*s_ptr++, "%c", **s3++);
+ if (s3 != s2+1 || *s3 != 0 || s_ptr != s_array+1 || *s_ptr != 0)
+ abort();
+
+ s_ptr = s_array;
+ fprintf (*s_ptr++, "hello world");
+ if (s_ptr != s_array+1 || *s_ptr != 0)
+ abort();
+ s_ptr = s_array;
+ fprintf (*s_ptr, "\n");
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ __builtin_fprintf (*s_ptr, "%s", "hello world\n");
+ /* Check the unlocked style, these evaluate to nothing to avoid
+ problems on systems without the unlocked functions. */
+ fprintf_unlocked (*s_ptr, "");
+ __builtin_fprintf_unlocked (*s_ptr, "");
+ fprintf_unlocked (*s_ptr, "%s", "");
+ __builtin_fprintf_unlocked (*s_ptr, "%s", "");
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.x b/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.x
new file mode 100644
index 000000000..c8fdaf5b2
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/fprintf.x
@@ -0,0 +1,7 @@
+load_lib target-supports.exp
+
+if { [check_effective_target_freestanding] } {
+ return 1;
+}
+
+return 0;
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/fputs-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/fputs-lib.c
new file mode 100644
index 000000000..c2292a781
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/fputs-lib.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stddef.h>
+extern void abort (void);
+extern int inside_main;
+extern size_t strlen(const char *);
+int
+fputs(const char *string, FILE *stream)
+{
+ size_t n = strlen(string);
+ size_t r;
+#if defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__
+ if (inside_main)
+ abort();
+#endif
+ r = fwrite (string, 1, n, stream);
+ return n > r ? EOF : 0;
+}
+
+/* Locking stdio doesn't matter for the purposes of this test. */
+int
+fputs_unlocked(const char *string, FILE *stream)
+{
+ return fputs (string, stream);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/fputs.c b/gcc/testsuite/gcc.c-torture/execute/builtins/fputs.c
new file mode 100644
index 000000000..93fa97364
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/fputs.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2000, 2001 Free Software Foundation.
+
+ Ensure all expected transformations of builtin fputs occur and that
+ we honor side effects in the stream argument.
+
+ Written by Kaveh R. Ghazi, 10/30/2000. */
+
+#include <stdio.h>
+extern void abort(void);
+
+int i;
+
+void
+main_test(void)
+{
+ FILE *s_array[] = {stdout, NULL}, **s_ptr = s_array;
+ const char *const s1 = "hello world";
+
+ fputs ("", *s_ptr);
+ fputs ("\n", *s_ptr);
+ fputs ("bye", *s_ptr);
+ fputs (s1, *s_ptr);
+ fputs (s1+5, *s_ptr);
+ fputs (s1+10, *s_ptr);
+ fputs (s1+11, *s_ptr);
+
+ /* Check side-effects when transforming fputs -> NOP. */
+ fputs ("", *s_ptr++);
+ if (s_ptr != s_array+1 || *s_ptr != 0)
+ abort();
+
+ /* Check side-effects when transforming fputs -> fputc. */
+ s_ptr = s_array;
+ fputs ("\n", *s_ptr++);
+ if (s_ptr != s_array+1 || *s_ptr != 0)
+ abort();
+
+ /* Check side-effects when transforming fputs -> fwrite. */
+ s_ptr = s_array;
+ fputs ("hello\n", *s_ptr++);
+ if (s_ptr != s_array+1 || *s_ptr != 0)
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ s_ptr = s_array;
+ __builtin_fputs ("", *s_ptr);
+ /* These builtin stubs are called by __builtin_fputs, ensure their
+ prototypes are set correctly too. */
+ __builtin_fputc ('\n', *s_ptr);
+ __builtin_fwrite ("hello\n", 1, 6, *s_ptr);
+ /* Check the unlocked style, these evaluate to nothing to avoid
+ problems on systems without the unlocked functions. */
+ fputs_unlocked ("", *s_ptr);
+ __builtin_fputs_unlocked ("", *s_ptr);
+
+ /* Check side-effects in conditional expression. */
+ s_ptr = s_array;
+ fputs (i++ ? "f" : "x", *s_ptr++);
+ if (s_ptr != s_array+1 || *s_ptr != 0 || i != 1)
+ abort();
+ fputs (--i ? "\n" : "\n", *--s_ptr);
+ if (s_ptr != s_array || i != 0)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/abs.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/abs.c
new file mode 100644
index 000000000..1e0857f73
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/abs.c
@@ -0,0 +1,41 @@
+extern int inside_main;
+extern void abort (void);
+#ifdef __OPTIMIZE__
+#define ABORT_INSIDE_MAIN do { if (inside_main) abort (); } while (0)
+#else
+#define ABORT_INSIDE_MAIN do { } while (0)
+#endif
+
+typedef __INTMAX_TYPE__ intmax_t;
+
+__attribute__ ((__noinline__))
+int
+abs (int x)
+{
+ ABORT_INSIDE_MAIN;
+ return x < 0 ? -x : x;
+}
+
+__attribute__ ((__noinline__))
+long
+labs (long x)
+{
+ ABORT_INSIDE_MAIN;
+ return x < 0 ? -x : x;
+}
+
+__attribute__ ((__noinline__))
+long long
+llabs (long long x)
+{
+ ABORT_INSIDE_MAIN;
+ return x < 0 ? -x : x;
+}
+
+__attribute__ ((__noinline__))
+intmax_t
+imaxabs (intmax_t x)
+{
+ ABORT_INSIDE_MAIN;
+ return x < 0 ? -x : x;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/bfill.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/bfill.c
new file mode 100644
index 000000000..deb6cf522
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/bfill.c
@@ -0,0 +1,16 @@
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+void
+bfill (void *s, __SIZE_TYPE__ n, int ch)
+{
+ char *p;
+
+ for (p = s; n-- > 0; p++)
+ *p = ch;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/bzero.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/bzero.c
new file mode 100644
index 000000000..a02b5358b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/bzero.c
@@ -0,0 +1,16 @@
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+void
+bzero (void *s, __SIZE_TYPE__ n)
+{
+ char *p;
+
+ for (p = s; n-- > 0; p++)
+ *p = 0;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c
new file mode 100644
index 000000000..e5197902b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/chk.c
@@ -0,0 +1,478 @@
+#include <stdarg.h>
+#ifdef __unix__
+#include <sys/types.h>
+#endif
+
+extern void abort (void);
+
+extern int inside_main;
+void *chk_fail_buf[256] __attribute__((aligned (16)));
+volatile int chk_fail_allowed, chk_calls;
+volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
+volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
+volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed;
+volatile int sprintf_disallowed, vsprintf_disallowed;
+volatile int snprintf_disallowed, vsnprintf_disallowed;
+extern __SIZE_TYPE__ strlen (const char *);
+extern int vsprintf (char *, const char *, va_list);
+
+void __attribute__((noreturn))
+__chk_fail (void)
+{
+ if (chk_fail_allowed)
+ __builtin_longjmp (chk_fail_buf, 1);
+ abort ();
+}
+
+void *
+memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+#ifdef __OPTIMIZE__
+ if (memcpy_disallowed && inside_main)
+ abort ();
+#endif
+
+ srcp = src;
+ dstp = dst;
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dst;
+}
+
+void *
+__memcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into memcpy. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (n > size)
+ __chk_fail ();
+ return memcpy (dst, src, n);
+}
+
+void *
+mempcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+#ifdef __OPTIMIZE__
+ if (mempcpy_disallowed && inside_main)
+ abort ();
+#endif
+
+ srcp = src;
+ dstp = dst;
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dstp;
+}
+
+void *
+__mempcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into mempcpy. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (n > size)
+ __chk_fail ();
+ return mempcpy (dst, src, n);
+}
+
+void *
+memmove (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+#ifdef __OPTIMIZE__
+ if (memmove_disallowed && inside_main)
+ abort ();
+#endif
+
+ srcp = src;
+ dstp = dst;
+ if (srcp < dstp)
+ while (n-- != 0)
+ dstp[n] = srcp[n];
+ else
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dst;
+}
+
+void *
+__memmove_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into memmove. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (n > size)
+ __chk_fail ();
+ return memmove (dst, src, n);
+}
+
+void *
+memset (void *dst, int c, __SIZE_TYPE__ n)
+{
+ /* Single-byte memsets should be done inline when optimisation
+ is enabled. */
+#ifdef __OPTIMIZE__
+ if (memset_disallowed && inside_main && n < 2)
+ abort ();
+#endif
+
+ while (n-- != 0)
+ n[(char *) dst] = c;
+
+ return dst;
+}
+
+void *
+__memset_chk (void *dst, int c, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into memset. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (n > size)
+ __chk_fail ();
+ return memset (dst, c, n);
+}
+
+char *
+strcpy (char *d, const char *s)
+{
+ char *r = d;
+#ifdef __OPTIMIZE__
+ if (strcpy_disallowed && inside_main)
+ abort ();
+#endif
+ while ((*d++ = *s++));
+ return r;
+}
+
+char *
+__strcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into strcpy. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (strlen (s) >= size)
+ __chk_fail ();
+ return strcpy (d, s);
+}
+
+char *
+stpcpy (char *dst, const char *src)
+{
+#ifdef __OPTIMIZE__
+ if (stpcpy_disallowed && inside_main)
+ abort ();
+#endif
+
+ while (*src != 0)
+ *dst++ = *src++;
+
+ *dst = 0;
+ return dst;
+}
+
+char *
+__stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into stpcpy. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (strlen (s) >= size)
+ __chk_fail ();
+ return stpcpy (d, s);
+}
+
+char *
+strncpy (char *s1, const char *s2, __SIZE_TYPE__ n)
+{
+ char *dest = s1;
+#ifdef __OPTIMIZE__
+ if (strncpy_disallowed && inside_main)
+ abort();
+#endif
+ for (; *s2 && n; n--)
+ *s1++ = *s2++;
+ while (n--)
+ *s1++ = 0;
+ return dest;
+}
+
+char *
+__strncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into strncpy. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (n > size)
+ __chk_fail ();
+ return strncpy (s1, s2, n);
+}
+
+char *
+strcat (char *dst, const char *src)
+{
+ char *p = dst;
+
+#ifdef __OPTIMIZE__
+ if (strcat_disallowed && inside_main)
+ abort ();
+#endif
+
+ while (*p)
+ p++;
+ while ((*p++ = *src++))
+ ;
+ return dst;
+}
+
+char *
+__strcat_chk (char *d, const char *s, __SIZE_TYPE__ size)
+{
+ /* If size is -1, GCC should always optimize the call into strcat. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ if (strlen (d) + strlen (s) >= size)
+ __chk_fail ();
+ return strcat (d, s);
+}
+
+char *
+strncat (char *s1, const char *s2, __SIZE_TYPE__ n)
+{
+ char *dest = s1;
+ char c;
+#ifdef __OPTIMIZE__
+ if (strncat_disallowed && inside_main)
+ abort();
+#endif
+ while (*s1) s1++;
+ c = '\0';
+ while (n > 0)
+ {
+ c = *s2++;
+ *s1++ = c;
+ if (c == '\0')
+ return dest;
+ n--;
+ }
+ if (c != '\0')
+ *s1 = '\0';
+ return dest;
+}
+
+char *
+__strncat_chk (char *d, const char *s, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
+{
+ __SIZE_TYPE__ len = strlen (d), n1 = n;
+ const char *s1 = s;
+
+ /* If size is -1, GCC should always optimize the call into strncat. */
+ if (size == (__SIZE_TYPE__) -1)
+ abort ();
+ ++chk_calls;
+ while (len < size && n1 > 0)
+ {
+ if (*s1++ == '\0')
+ break;
+ ++len;
+ --n1;
+ }
+
+ if (len >= size)
+ __chk_fail ();
+ return strncat (d, s, n);
+}
+
+/* No chk test in GCC testsuite needs more bytes than this.
+ As we can't expect vsnprintf to be available on the target,
+ assume 4096 bytes is enough. */
+static char chk_sprintf_buf[4096];
+
+int
+__sprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ /* If size is -1 and flag 0, GCC should always optimize the call into
+ sprintf. */
+ if (size == (__SIZE_TYPE__) -1 && flag == 0)
+ abort ();
+ ++chk_calls;
+#ifdef __OPTIMIZE__
+ if (sprintf_disallowed && inside_main)
+ abort();
+#endif
+ va_start (ap, fmt);
+ ret = vsprintf (chk_sprintf_buf, fmt, ap);
+ va_end (ap);
+ if (ret >= 0)
+ {
+ if (ret >= size)
+ __chk_fail ();
+ memcpy (str, chk_sprintf_buf, ret + 1);
+ }
+ return ret;
+}
+
+int
+__vsprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt,
+ va_list ap)
+{
+ int ret;
+
+ /* If size is -1 and flag 0, GCC should always optimize the call into
+ vsprintf. */
+ if (size == (__SIZE_TYPE__) -1 && flag == 0)
+ abort ();
+ ++chk_calls;
+#ifdef __OPTIMIZE__
+ if (vsprintf_disallowed && inside_main)
+ abort();
+#endif
+ ret = vsprintf (chk_sprintf_buf, fmt, ap);
+ if (ret >= 0)
+ {
+ if (ret >= size)
+ __chk_fail ();
+ memcpy (str, chk_sprintf_buf, ret + 1);
+ }
+ return ret;
+}
+
+int
+__snprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
+ const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ /* If size is -1 and flag 0, GCC should always optimize the call into
+ snprintf. */
+ if (size == (__SIZE_TYPE__) -1 && flag == 0)
+ abort ();
+ ++chk_calls;
+ if (size < len)
+ __chk_fail ();
+#ifdef __OPTIMIZE__
+ if (snprintf_disallowed && inside_main)
+ abort();
+#endif
+ va_start (ap, fmt);
+ ret = vsprintf (chk_sprintf_buf, fmt, ap);
+ va_end (ap);
+ if (ret >= 0)
+ {
+ if (ret < len)
+ memcpy (str, chk_sprintf_buf, ret + 1);
+ else
+ {
+ memcpy (str, chk_sprintf_buf, len - 1);
+ str[len - 1] = '\0';
+ }
+ }
+ return ret;
+}
+
+int
+__vsnprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
+ const char *fmt, va_list ap)
+{
+ int ret;
+
+ /* If size is -1 and flag 0, GCC should always optimize the call into
+ vsnprintf. */
+ if (size == (__SIZE_TYPE__) -1 && flag == 0)
+ abort ();
+ ++chk_calls;
+ if (size < len)
+ __chk_fail ();
+#ifdef __OPTIMIZE__
+ if (vsnprintf_disallowed && inside_main)
+ abort();
+#endif
+ ret = vsprintf (chk_sprintf_buf, fmt, ap);
+ if (ret >= 0)
+ {
+ if (ret < len)
+ memcpy (str, chk_sprintf_buf, ret + 1);
+ else
+ {
+ memcpy (str, chk_sprintf_buf, len - 1);
+ str[len - 1] = '\0';
+ }
+ }
+ return ret;
+}
+
+int
+snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+#ifdef __OPTIMIZE__
+ if (snprintf_disallowed && inside_main)
+ abort();
+#endif
+ va_start (ap, fmt);
+ ret = vsprintf (chk_sprintf_buf, fmt, ap);
+ va_end (ap);
+ if (ret >= 0)
+ {
+ if (ret < len)
+ memcpy (str, chk_sprintf_buf, ret + 1);
+ else if (len)
+ {
+ memcpy (str, chk_sprintf_buf, len - 1);
+ str[len - 1] = '\0';
+ }
+ }
+ return ret;
+}
+
+/* uClibc's vsprintf calls vsnprintf. */
+#ifndef __UCLIBC__
+int
+vsnprintf (char *str, __SIZE_TYPE__ len, const char *fmt, va_list ap)
+{
+ int ret;
+
+#ifdef __OPTIMIZE__
+ if (vsnprintf_disallowed && inside_main)
+ abort();
+#endif
+ ret = vsprintf (chk_sprintf_buf, fmt, ap);
+ if (ret >= 0)
+ {
+ if (ret < len)
+ memcpy (str, chk_sprintf_buf, ret + 1);
+ else if (len)
+ {
+ memcpy (str, chk_sprintf_buf, len - 1);
+ str[len - 1] = '\0';
+ }
+ }
+ return ret;
+}
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/fprintf.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/fprintf.c
new file mode 100644
index 000000000..853a705e8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/fprintf.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdarg.h>
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+int
+fprintf (FILE *fp, const char *string, ...)
+{
+ va_list ap;
+ int r;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+ va_start (ap, string);
+ r = vfprintf (fp, string, ap);
+ va_end (ap);
+ return r;
+}
+
+/* Locking stdio doesn't matter for the purposes of this test. */
+__attribute__ ((__noinline__))
+int
+fprintf_unlocked (FILE *fp, const char *string, ...)
+{
+ va_list ap;
+ int r;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+ va_start (ap, string);
+ r = vfprintf (fp, string, ap);
+ va_end (ap);
+ return r;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/main.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/main.c
new file mode 100644
index 000000000..a9bb6c6b8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/main.c
@@ -0,0 +1,25 @@
+extern void abort(void);
+extern void main_test (void);
+extern void abort (void);
+int inside_main;
+
+int
+main ()
+{
+ inside_main = 1;
+ main_test ();
+ inside_main = 0;
+ return 0;
+}
+
+/* When optimizing, all the constant cases should have been
+ constant folded, so no calls to link_error should remain.
+ In any case, link_error should not be called. */
+
+#ifndef __OPTIMIZE__
+void
+link_error (void)
+{
+ abort ();
+}
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memchr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memchr.c
new file mode 100644
index 000000000..2f15c57a7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memchr.c
@@ -0,0 +1,22 @@
+extern void abort(void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+void *
+memchr (const void *s, int c, __SIZE_TYPE__ n)
+{
+ const unsigned char uc = c;
+ const unsigned char *sp;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ sp = s;
+ for (; n != 0; ++sp, --n)
+ if (*sp == uc)
+ return (void *) sp;
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memcmp.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memcmp.c
new file mode 100644
index 000000000..fd6556d22
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memcmp.c
@@ -0,0 +1,23 @@
+extern void abort(void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+int
+memcmp (const void *s1, const void *s2, __SIZE_TYPE__ len)
+{
+ const unsigned char *sp1, *sp2;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ sp1 = s1;
+ sp2 = s2;
+ while (len != 0 && *sp1 == *sp2)
+ sp1++, sp2++, len--;
+
+ if (len == 0)
+ return 0;
+ return *sp1 - *sp2;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memmove.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memmove.c
new file mode 100644
index 000000000..08fcd0801
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memmove.c
@@ -0,0 +1,32 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+void *
+memmove (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ char *dstp;
+ const char *srcp;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ srcp = src;
+ dstp = dst;
+ if (srcp < dstp)
+ while (n-- != 0)
+ dstp[n] = srcp[n];
+ else
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dst;
+}
+
+void
+bcopy (const void *src, void *dst, __SIZE_TYPE__ n)
+{
+ memmove (dst, src, n);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/mempcpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/mempcpy.c
new file mode 100644
index 000000000..bc16da536
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/mempcpy.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+void *
+mempcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ srcp = src;
+ dstp = dst;
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dstp;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memset.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memset.c
new file mode 100644
index 000000000..90545abbf
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/memset.c
@@ -0,0 +1,20 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+void *
+memset (void *dst, int c, __SIZE_TYPE__ n)
+{
+ while (n-- != 0)
+ n[(char *) dst] = c;
+
+ /* Single-byte memsets should be done inline when optimisation
+ is enabled. Do this after the copy in case we're being called to
+ initialize bss. */
+#ifdef __OPTIMIZE__
+ if (inside_main && n < 2)
+ abort ();
+#endif
+
+ return dst;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/printf.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/printf.c
new file mode 100644
index 000000000..4be7578d1
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/printf.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdarg.h>
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+int
+printf (const char *string, ...)
+{
+ va_list ap;
+ int r;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+ va_start (ap, string);
+ r = vprintf (string, ap);
+ va_end (ap);
+ return r;
+}
+
+
+/* Locking stdio doesn't matter for the purposes of this test. */
+__attribute__ ((__noinline__))
+int
+printf_unlocked (const char *string, ...)
+{
+ va_list ap;
+ int r;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+ va_start (ap, string);
+ r = vprintf (string, ap);
+ va_end (ap);
+ return r;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/sprintf.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/sprintf.c
new file mode 100644
index 000000000..3ac447b11
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/sprintf.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdarg.h>
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+int
+(sprintf) (char *buf, const char *fmt, ...)
+{
+ va_list ap;
+ int r;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+ va_start (ap, fmt);
+ r = vsprintf (buf, fmt, ap);
+ va_end (ap);
+ return r;
+}
+
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/stpcpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/stpcpy.c
new file mode 100644
index 000000000..2c7c8178b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/stpcpy.c
@@ -0,0 +1,18 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+char *
+stpcpy (char *dst, const char *src)
+{
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ while (*src != 0)
+ *dst++ = *src++;
+
+ *dst = 0;
+ return dst;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcat.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcat.c
new file mode 100644
index 000000000..d592087a9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcat.c
@@ -0,0 +1,20 @@
+extern int inside_main;
+extern void abort(void);
+
+__attribute__ ((__noinline__))
+char *
+strcat (char *dst, const char *src)
+{
+ char *p = dst;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ while (*p)
+ p++;
+ while ((*p++ = *src++))
+ ;
+ return dst;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strchr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strchr.c
new file mode 100644
index 000000000..bee3d3203
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strchr.c
@@ -0,0 +1,28 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+char *
+strchr (const char *s, int c)
+{
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ for (;;)
+ {
+ if (*s == c)
+ return (char *) s;
+ if (*s == 0)
+ return 0;
+ s++;
+ }
+}
+
+__attribute__ ((__noinline__))
+char *
+index (const char *s, int c)
+{
+ return strchr (s, c);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcmp.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcmp.c
new file mode 100644
index 000000000..82284546f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcmp.c
@@ -0,0 +1,19 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+int
+strcmp (const char *s1, const char *s2)
+{
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ while (*s1 != 0 && *s1 == *s2)
+ s1++, s2++;
+
+ if (*s1 == 0 || *s2 == 0)
+ return (unsigned char) *s1 - (unsigned char) *s2;
+ return *s1 - *s2;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcpy.c
new file mode 100644
index 000000000..916446623
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcpy.c
@@ -0,0 +1,15 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+char *
+strcpy (char *d, const char *s)
+{
+ char *r = d;
+#if defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__
+ if (inside_main)
+ abort ();
+#endif
+ while ((*d++ = *s++));
+ return r;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcspn.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcspn.c
new file mode 100644
index 000000000..827099637
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strcspn.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+__SIZE_TYPE__
+strcspn (const char *s1, const char *s2)
+{
+ const char *p, *q;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+
+ for (p = s1; *p; p++)
+ for (q = s2; *q; q++)
+ if (*p == *q)
+ goto found;
+
+ found:
+ return p - s1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strlen.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strlen.c
new file mode 100644
index 000000000..7f81c115b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strlen.c
@@ -0,0 +1,20 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+__SIZE_TYPE__
+strlen (const char *s)
+{
+ __SIZE_TYPE__ i;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ i = 0;
+ while (s[i] != 0)
+ i++;
+
+ return i;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncat.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncat.c
new file mode 100644
index 000000000..7fd334cb4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncat.c
@@ -0,0 +1,29 @@
+extern void abort(void);
+extern int inside_main;
+
+typedef __SIZE_TYPE__ size_t;
+
+__attribute__ ((__noinline__))
+char *
+strncat (char *s1, const char *s2, size_t n)
+{
+ char *dest = s1;
+ char c = '\0';
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+ while (*s1) s1++;
+ c = '\0';
+ while (n > 0)
+ {
+ c = *s2++;
+ *s1++ = c;
+ if (c == '\0')
+ return dest;
+ n--;
+ }
+ if (c != '\0')
+ *s1 = '\0';
+ return dest;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncmp.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncmp.c
new file mode 100644
index 000000000..7a8eb6fd2
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncmp.c
@@ -0,0 +1,27 @@
+extern void abort (void);
+extern int inside_main;
+
+typedef __SIZE_TYPE__ size_t;
+
+__attribute__ ((__noinline__))
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+ const unsigned char *u1 = (const unsigned char *)s1;
+ const unsigned char *u2 = (const unsigned char *)s2;
+ unsigned char c1, c2;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+
+ while (n > 0)
+ {
+ c1 = *u1++, c2 = *u2++;
+ if (c1 == '\0' || c1 != c2)
+ return c1 - c2;
+ n--;
+ }
+ return c1 - c2;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncpy.c
new file mode 100644
index 000000000..a6ec98b05
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strncpy.c
@@ -0,0 +1,21 @@
+extern void abort(void);
+extern int inside_main;
+
+typedef __SIZE_TYPE__ size_t;
+
+__attribute__ ((__noinline__))
+char *
+strncpy(char *s1, const char *s2, size_t n)
+{
+ char *dest = s1;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+ for (; *s2 && n; n--)
+ *s1++ = *s2++;
+ while (n--)
+ *s1++ = 0;
+ return dest;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strpbrk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strpbrk.c
new file mode 100644
index 000000000..0c049272c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strpbrk.c
@@ -0,0 +1,21 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+char *
+strpbrk(const char *s1, const char *s2)
+{
+ const char *p;
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+ while (*s1)
+ {
+ for (p = s2; *p; p++)
+ if (*s1 == *p)
+ return (char *)s1;
+ s1++;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strrchr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strrchr.c
new file mode 100644
index 000000000..9a45af3c8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strrchr.c
@@ -0,0 +1,32 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+char *
+strrchr (const char *s, int c)
+{
+ __SIZE_TYPE__ i;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ i = 0;
+ while (s[i] != 0)
+ i++;
+
+ do
+ if (s[i] == c)
+ return (char *) s + i;
+ while (i-- != 0);
+
+ return 0;
+}
+
+__attribute__ ((__noinline__))
+char *
+rindex (const char *s, int c)
+{
+ return strrchr (s, c);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strspn.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strspn.c
new file mode 100644
index 000000000..622aac6ab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strspn.c
@@ -0,0 +1,25 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+__SIZE_TYPE__
+strcspn (const char *s1, const char *s2)
+{
+ const char *p, *q;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort();
+#endif
+
+ for (p = s1; *p; p++)
+ {
+ for (q = s2; *q; q++)
+ if (*p == *q)
+ goto proceed;
+ break;
+
+ proceed:;
+ }
+ return p - s1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strstr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strstr.c
new file mode 100644
index 000000000..7d3544506
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/lib/strstr.c
@@ -0,0 +1,29 @@
+extern void abort (void);
+extern int inside_main;
+
+__attribute__ ((__noinline__))
+char *
+strstr(const char *s1, const char *s2)
+{
+ const char *p, *q;
+
+#ifdef __OPTIMIZE__
+ if (inside_main)
+ abort ();
+#endif
+
+ /* deliberately dumb algorithm */
+ for (; *s1; s1++)
+ {
+ p = s1, q = s2;
+ while (*q && *p)
+ {
+ if (*q != *p)
+ break;
+ p++, q++;
+ }
+ if (*q == 0)
+ return (char *)s1;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memchr-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memchr-lib.c
new file mode 100644
index 000000000..ccea6ba7d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memchr-lib.c
@@ -0,0 +1 @@
+#include "lib/memchr.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memchr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memchr.c
new file mode 100644
index 000000000..88e731128
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memchr.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2007 Free Software Foundation.
+
+ Ensure all expected transformations of builtin memchr occur
+ and perform correctly.
+
+ Written by Paolo Carlini, 10/5/2007. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern void *memchr (const void *, int, size_t);
+
+void
+main_test (void)
+{
+ const char* const foo1 = "hello world";
+
+ if (memchr (foo1, 'x', 11))
+ abort ();
+ if (memchr (foo1, 'o', 11) != foo1 + 4)
+ abort ();
+ if (memchr (foo1, 'w', 2))
+ abort ();
+ if (memchr (foo1 + 5, 'o', 6) != foo1 + 7)
+ abort ();
+ if (memchr (foo1, 'd', 11) != foo1 + 10)
+ abort ();
+ if (memchr (foo1, 'd', 10))
+ abort ();
+ if (memchr (foo1, '\0', 11))
+ abort ();
+ if (memchr (foo1, '\0', 12) != foo1 + 11)
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_memchr (foo1, 'r', 11) != foo1 + 8)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memcmp-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memcmp-lib.c
new file mode 100644
index 000000000..029a92e77
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memcmp-lib.c
@@ -0,0 +1 @@
+#include "lib/memcmp.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memcmp.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memcmp.c
new file mode 100644
index 000000000..5489048f5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memcmp.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2001 Free Software Foundation.
+
+ Ensure that short builtin memcmp are optimized and perform correctly.
+ On architectures with a cmpstrsi instruction, this test doesn't determine
+ which optimization is being performed, but it does check for correctness.
+
+ Written by Roger Sayle, 12/02/2001.
+ Additional tests by Roger Sayle after PR 3508, 12/26/2001. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern int memcmp (const void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern void link_error (void);
+
+void
+main_test (void)
+{
+ char str[8];
+
+ strcpy (str, "3141");
+
+ if ( memcmp (str, str+2, 0) != 0 )
+ abort ();
+ if ( memcmp (str+1, str+3, 0) != 0 )
+ abort ();
+
+ if ( memcmp (str+1, str+3, 1) != 0 )
+ abort ();
+ if ( memcmp (str, str+2, 1) >= 0 )
+ abort ();
+ if ( memcmp (str+2, str, 1) <= 0 )
+ abort ();
+
+ if (memcmp ("abcd", "efgh", 4) >= 0)
+ link_error ();
+ if (memcmp ("abcd", "abcd", 4) != 0)
+ link_error ();
+ if (memcmp ("efgh", "abcd", 4) <= 0)
+ link_error ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.c
new file mode 100644
index 000000000..5b245e58e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.c
@@ -0,0 +1,479 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __memcpy_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ int i;
+
+#if defined __i386__ || defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ memcpy_disallowed = 1;
+#endif
+
+ /* All the memcpy calls in this routine except last have fixed length, so
+ object size checking should be done at compile time if optimizing. */
+ chk_calls = 0;
+
+ if (memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
+ abort ();
+ if (memcpy (p + 16, "VWX" + 1, 2) != p + 16
+ || memcmp (p + 16, "WX\0\0", 5))
+ abort ();
+ if (memcpy (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6))
+ abort ();
+ if (memcpy (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHI", 8))
+ abort ();
+
+ i = 8;
+ memcpy (p + 20, "qrstu", 6);
+ memcpy (p + 25, "QRSTU", 6);
+ if (memcpy (p + 25 + 1, s1, 3) != p + 25 + 1
+ || memcmp (p + 25, "Q123U", 6))
+ abort ();
+
+ if (memcpy (memcpy (p, "abcdEFG", 4) + 4, "efg", 4) != p + 4
+ || memcmp (p, "abcdefg", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
+ abort ();
+
+ memcpy (p + 5, s3, 1);
+ if (memcmp (p, "ABCDEFg", 8))
+ abort ();
+
+ memcpy_disallowed = 0;
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+
+ memcpy (p + 6, s1 + 1, l1);
+ if (memcmp (p, "ABCDEF2", 8))
+ abort ();
+
+ /* The above memcpy copies into an object with known size, but
+ unknown length, so it should be a __memcpy_chk call. */
+ if (chk_calls != 1)
+ abort ();
+}
+
+long buf1[64];
+char *buf2 = (char *) (buf1 + 32);
+long buf5[20];
+char buf7[20];
+
+void
+__attribute__((noinline))
+test2_sub (long *buf3, char *buf4, char *buf6, int n)
+{
+ int i = 0;
+
+ /* All the memcpy/__builtin_memcpy/__builtin___memcpy_chk
+ calls in this routine are either fixed length, or have
+ side-effects in __builtin_object_size arguments, or
+ dst doesn't point into a known object. */
+ chk_calls = 0;
+
+ /* These should probably be handled by store_by_pieces on most arches. */
+ if (memcpy (buf1, "ABCDEFGHI", 9) != (char *) buf1
+ || memcmp (buf1, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (memcpy (buf1, "abcdefghijklmnopq", 17) != (char *) buf1
+ || memcmp (buf1, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memcpy (buf3, "ABCDEF", 6) != (char *) buf1
+ || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memcpy (buf3, "a", 1) != (char *) buf1
+ || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (memcpy ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 2
+ || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
+ || i != 1)
+ abort ();
+
+ /* These should probably be handled by move_by_pieces on most arches. */
+ if (memcpy ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 4
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
+ != (char *) buf1 + 10
+ || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ if (memcpy ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 14
+ || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ if (memcpy (buf3, buf5, 8) != (char *) buf1
+ || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
+ abort ();
+
+ if (memcpy (buf3, buf5, 17) != (char *) buf1
+ || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
+ abort ();
+
+ __builtin_memcpy (buf3, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or memcpy
+ call. */
+
+ /* buf3 points to an unknown object, so __memcpy_chk should not be done. */
+ if (memcpy ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 4
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* This call has side-effects in dst, therefore no checking. */
+ if (__builtin___memcpy_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1,
+ n + 1, os ((char *) buf1 + ++i + 8))
+ != (char *) buf1 + 11
+ || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (memcpy ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 14
+ || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ i = 1;
+
+ /* These might be handled by store_by_pieces. */
+ if (memcpy (buf2, "ABCDEFGHI", 9) != buf2
+ || memcmp (buf2, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (memcpy (buf2, "abcdefghijklmnopq", 17) != buf2
+ || memcmp (buf2, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memcpy (buf4, "ABCDEF", 6) != buf2
+ || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memcpy (buf4, "a", 1) != buf2
+ || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (memcpy (buf4 + 2, "bcd" + i++, 2) != buf2 + 2
+ || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ /* These might be handled by move_by_pieces. */
+ if (memcpy (buf4 + 4, buf7, 6) != buf2 + 4
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* Side effect. */
+ if (__builtin___memcpy_chk (buf2 + i++ + 8, buf7 + 1, 1,
+ os (buf2 + i++ + 8))
+ != buf2 + 10
+ || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (memcpy (buf4 + 14, buf6, 2) != buf2 + 14
+ || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ __builtin_memcpy (buf4, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or memcpy
+ call. */
+ if (memcpy (buf4 + 4, buf7, n + 6) != buf2 + 4
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* Side effect. */
+ if (__builtin___memcpy_chk (buf2 + i++ + 8, buf7 + 1, n + 1,
+ os (buf2 + i++ + 8))
+ != buf2 + 11
+ || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 4)
+ abort ();
+
+ if (memcpy (buf4 + 14, buf6, n + 2) != buf2 + 14
+ || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test2 (void)
+{
+ long *x;
+ char *y;
+ int z;
+ __builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
+ __builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
+ __asm ("" : "=r" (x) : "0" (buf1));
+ __asm ("" : "=r" (y) : "0" (buf2));
+ __asm ("" : "=r" (z) : "0" (0));
+ test2_sub (x, y, "rstuvwxyz", z);
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ size_t l;
+
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ chk_calls = 0;
+ memcpy (a.buf1 + 2, s3, l1);
+ memcpy (r, s3, l1 + 1);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memcpy (r, s2, l1 + 2);
+ memcpy (r + 2, s3, l1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ memcpy (r, s2, l1);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ memcpy (a.buf1 + 2, s3, 1);
+ memcpy (r, s3, 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memcpy (r, s2, 3);
+ r = buf3;
+ l = 4;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = 2;
+ else if (i == l1)
+ r = &a.buf2[7], l = 3;
+ else if (i == l1 + 1)
+ r = &buf3[5], l = 4;
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = 1;
+ }
+ memcpy (r, s2, 1);
+ /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
+ is 4, so this doesn't need runtime checking. */
+ memcpy (&buf3[16], s2, l);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test4 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memcpy (&a.buf2[9], s2, l1 + 1);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memcpy (&a.buf2[7], s3, strlen (s3) + 1);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memcpy (&buf3[19], "ab", 2);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+#ifndef MAX_OFFSET
+#define MAX_OFFSET (sizeof (long long))
+#endif
+
+#ifndef MAX_COPY
+#define MAX_COPY (10 * sizeof (long long))
+#endif
+
+#ifndef MAX_EXTRA
+#define MAX_EXTRA (sizeof (long long))
+#endif
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
+
+/* Use a sequence length that is not divisible by two, to make it more
+ likely to detect when words are mixed up. */
+#define SEQUENCE_LENGTH 31
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u1, u2;
+
+void
+__attribute__((noinline))
+test5 (void)
+{
+ int off1, off2, len, i;
+ char *p, *q, c;
+
+ for (off1 = 0; off1 < MAX_OFFSET; off1++)
+ for (off2 = 0; off2 < MAX_OFFSET; off2++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+
+ p = memcpy (u1.buf + off1, u2.buf + off2, len);
+ if (p != u1.buf + off1)
+ abort ();
+
+ q = u1.buf;
+ for (i = 0; i < off1; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
+ {
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ if (*q != c)
+ abort ();
+ }
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+}
+
+#define TESTSIZE 80
+
+char srcb[TESTSIZE] __attribute__ ((aligned));
+char dstb[TESTSIZE] __attribute__ ((aligned));
+
+void
+__attribute__((noinline))
+check (char *test, char *match, int n)
+{
+ if (memcmp (test, match, n))
+ abort ();
+}
+
+#define TN(n) \
+{ memset (dstb, 0, n); memcpy (dstb, srcb, n); check (dstb, srcb, n); }
+#define T(n) \
+TN (n) \
+TN ((n) + 1) \
+TN ((n) + 2) \
+TN ((n) + 3)
+
+void
+__attribute__((noinline))
+test6 (void)
+{
+ int i;
+
+ chk_calls = 0;
+
+ for (i = 0; i < sizeof (srcb); ++i)
+ srcb[i] = 'a' + i % 26;
+
+ T (0);
+ T (4);
+ T (8);
+ T (12);
+ T (16);
+ T (20);
+ T (24);
+ T (28);
+ T (32);
+ T (36);
+ T (40);
+ T (44);
+ T (48);
+ T (52);
+ T (56);
+ T (60);
+ T (64);
+ T (68);
+ T (72);
+ T (76);
+
+ /* All memcpy calls in this routine have constant arguments. */
+ if (chk_calls)
+ abort ();
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+ test2 ();
+ test3 ();
+ test4 ();
+ test5 ();
+ test6 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2-lib.c
new file mode 100644
index 000000000..e2293ffc0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2-lib.c
@@ -0,0 +1,7 @@
+#include "lib/memmove.c"
+#ifdef __vxworks
+/* The RTP C library uses bzero and bfill, both of which are defined
+ in the same file as bcopy. */
+#include "lib/bzero.c"
+#include "lib/bfill.c"
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2.c
new file mode 100644
index 000000000..3afe34313
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-2.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+ Check builtin memmove and bcopy optimization when length is 1.
+
+ Written by Jakub Jelinek, 9/14/2004. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern void *memmove (void *, const void *, size_t);
+extern void bcopy (const void *, void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+char p[32] = "abcdefg";
+char *q = p + 4;
+
+void
+main_test (void)
+{
+ /* memmove with length 1 can be optimized into memcpy if it can be
+ expanded inline. */
+ if (memmove (p + 2, p + 3, 1) != p + 2 || memcmp (p, "abddefg", 8))
+ abort ();
+ if (memmove (p + 1, p + 1, 1) != p + 1 || memcmp (p, "abddefg", 8))
+ abort ();
+ if (memmove (q, p + 4, 1) != p + 4 || memcmp (p, "abddefg", 8))
+ abort ();
+ bcopy (p + 5, p + 6, 1);
+ if (memcmp (p, "abddeff", 8))
+ abort ();
+ bcopy (p + 1, p + 1, 1);
+ if (memcmp (p, "abddeff", 8))
+ abort ();
+ bcopy (q, p + 4, 1);
+ if (memcmp (p, "abddeff", 8))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.c
new file mode 100644
index 000000000..73b35883e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.c
@@ -0,0 +1,579 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __memcpy_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *memmove (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ int i;
+
+#if defined __i386__ || defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ memmove_disallowed = 1;
+ memcpy_disallowed = 1;
+#endif
+
+ /* All the memmove calls in this routine except last have fixed length, so
+ object size checking should be done at compile time if optimizing. */
+ chk_calls = 0;
+
+ if (memmove (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
+ abort ();
+ if (memmove (p + 16, "VWX" + 1, 2) != p + 16
+ || memcmp (p + 16, "WX\0\0", 5))
+ abort ();
+ if (memmove (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6))
+ abort ();
+ if (memmove (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHI", 8))
+ abort ();
+
+ i = 8;
+ memmove (p + 20, "qrstu", 6);
+ memmove (p + 25, "QRSTU", 6);
+ if (memmove (p + 25 + 1, s1, 3) != p + 25 + 1
+ || memcmp (p + 25, "Q123U", 6))
+ abort ();
+
+ if (memmove (memmove (p, "abcdEFG", 4) + 4, "efg", 4) != p + 4
+ || memcmp (p, "abcdefg", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_memmove (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
+ abort ();
+
+ memmove (p + 5, s3, 1);
+ if (memcmp (p, "ABCDEFg", 8))
+ abort ();
+
+ memmove_disallowed = 0;
+ memcpy_disallowed = 0;
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+
+ memmove (p + 6, s1 + 1, l1);
+ if (memcmp (p, "ABCDEF2", 8))
+ abort ();
+
+ /* The above memmove copies into an object with known size, but
+ unknown length, so it should be a __memmove_chk call. */
+ if (chk_calls != 1)
+ abort ();
+}
+
+long buf1[64];
+char *buf2 = (char *) (buf1 + 32);
+long buf5[20];
+char buf7[20];
+
+void
+__attribute__((noinline))
+test2_sub (long *buf3, char *buf4, char *buf6, int n)
+{
+ int i = 0;
+
+ /* All the memmove/__builtin_memmove/__builtin___memmove_chk
+ calls in this routine are either fixed length, or have
+ side-effects in __builtin_object_size arguments, or
+ dst doesn't point into a known object. */
+ chk_calls = 0;
+
+ /* These should probably be handled by store_by_pieces on most arches. */
+ if (memmove (buf1, "ABCDEFGHI", 9) != (char *) buf1
+ || memcmp (buf1, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (memmove (buf1, "abcdefghijklmnopq", 17) != (char *) buf1
+ || memcmp (buf1, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memmove (buf3, "ABCDEF", 6) != (char *) buf1
+ || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memmove (buf3, "a", 1) != (char *) buf1
+ || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (memmove ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 2
+ || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
+ || i != 1)
+ abort ();
+
+ /* These should probably be handled by move_by_pieces on most arches. */
+ if (memmove ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 4
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memmove ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
+ != (char *) buf1 + 10
+ || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ if (memmove ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 14
+ || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ if (memmove (buf3, buf5, 8) != (char *) buf1
+ || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
+ abort ();
+
+ if (memmove (buf3, buf5, 17) != (char *) buf1
+ || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
+ abort ();
+
+ __builtin_memmove (buf3, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or memmove
+ call. */
+
+ /* buf3 points to an unknown object, so __memmove_chk should not be done. */
+ if (memmove ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 4
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* This call has side-effects in dst, therefore no checking. */
+ if (__builtin___memmove_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1,
+ n + 1, os ((char *) buf1 + ++i + 8))
+ != (char *) buf1 + 11
+ || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (memmove ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 14
+ || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ i = 1;
+
+ /* These might be handled by store_by_pieces. */
+ if (memmove (buf2, "ABCDEFGHI", 9) != buf2
+ || memcmp (buf2, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (memmove (buf2, "abcdefghijklmnopq", 17) != buf2
+ || memcmp (buf2, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memmove (buf4, "ABCDEF", 6) != buf2
+ || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_memmove (buf4, "a", 1) != buf2
+ || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (memmove (buf4 + 2, "bcd" + i++, 2) != buf2 + 2
+ || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ /* These might be handled by move_by_pieces. */
+ if (memmove (buf4 + 4, buf7, 6) != buf2 + 4
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* Side effect. */
+ if (__builtin___memmove_chk (buf2 + i++ + 8, buf7 + 1, 1,
+ os (buf2 + i++ + 8))
+ != buf2 + 10
+ || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (memmove (buf4 + 14, buf6, 2) != buf2 + 14
+ || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ __builtin_memmove (buf4, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or memmove
+ call. */
+ if (memmove (buf4 + 4, buf7, n + 6) != buf2 + 4
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* Side effect. */
+ if (__builtin___memmove_chk (buf2 + i++ + 8, buf7 + 1, n + 1,
+ os (buf2 + i++ + 8))
+ != buf2 + 11
+ || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 4)
+ abort ();
+
+ if (memmove (buf4 + 14, buf6, n + 2) != buf2 + 14
+ || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test2 (void)
+{
+ long *x;
+ char *y;
+ int z;
+ __builtin_memmove (buf5, "RSTUVWXYZ0123456789", 20);
+ __builtin_memmove (buf7, "RSTUVWXYZ0123456789", 20);
+ __asm ("" : "=r" (x) : "0" (buf1));
+ __asm ("" : "=r" (y) : "0" (buf2));
+ __asm ("" : "=r" (z) : "0" (0));
+ test2_sub (x, y, "rstuvwxyz", z);
+}
+
+static const struct foo
+{
+ char *s;
+ double d;
+ long l;
+} foo[] =
+{
+ { "hello world1", 3.14159, 101L },
+ { "hello world2", 3.14159, 102L },
+ { "hello world3", 3.14159, 103L },
+ { "hello world4", 3.14159, 104L },
+ { "hello world5", 3.14159, 105L },
+ { "hello world6", 3.14159, 106L }
+};
+
+static const struct bar
+{
+ char *s;
+ const struct foo f[3];
+} bar[] =
+{
+ {
+ "hello world10",
+ {
+ { "hello1", 3.14159, 201L },
+ { "hello2", 3.14159, 202L },
+ { "hello3", 3.14159, 203L },
+ }
+ },
+ {
+ "hello world11",
+ {
+ { "hello4", 3.14159, 204L },
+ { "hello5", 3.14159, 205L },
+ { "hello6", 3.14159, 206L },
+ }
+ }
+};
+
+static const int baz[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+void
+__attribute__((noinline))
+test3 (void)
+{
+ const char *s;
+ struct foo f1[sizeof foo/sizeof*foo];
+ struct bar b1[sizeof bar/sizeof*bar];
+ int bz[sizeof baz/sizeof*baz];
+
+ /* All the memmove/__builtin_memmove calls in this routine have fixed
+ length. */
+ chk_calls = 0;
+
+ /* All the *memmove calls below have src in read-only memory, so all
+ of them should be optimized into memcpy. */
+ memmove_disallowed = 1;
+ if (memmove (f1, foo, sizeof (foo)) != f1 || memcmp (f1, foo, sizeof (foo)))
+ abort ();
+ if (memmove (b1, bar, sizeof (bar)) != b1 || memcmp (b1, bar, sizeof (bar)))
+ abort ();
+ memmove (bz, baz, sizeof (baz));
+ if (memcmp (bz, baz, sizeof (baz)))
+ abort ();
+
+ if (memmove (p, "abcde", 6) != p || memcmp (p, "abcde", 6))
+ abort ();
+ s = s1;
+ if (memmove (p + 2, ++s, 0) != p + 2 || memcmp (p, "abcde", 6) || s != s1 + 1)
+ abort ();
+ if (__builtin_memmove (p + 3, "", 1) != p + 3 || memcmp (p, "abc\0e", 6))
+ abort ();
+ memmove (p + 2, "fghijk", 4);
+ if (memcmp (p, "abfghi", 7))
+ abort ();
+ s = s1 + 1;
+ memmove (p + 1, s++, 0);
+ if (memcmp (p, "abfghi", 7) || s != s1 + 2)
+ abort ();
+ __builtin_memmove (p + 4, "ABCDE", 1);
+ if (memcmp (p, "abfgAi", 7))
+ abort ();
+
+ /* memmove with length 1 can be optimized into memcpy if it can be
+ expanded inline. */
+ if (memmove (p + 2, p + 3, 1) != p + 2)
+ abort ();
+ if (memcmp (p, "abggAi", 7))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+ memmove_disallowed = 0;
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test4 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ size_t l;
+
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ chk_calls = 0;
+ memmove (a.buf1 + 2, s3, l1);
+ memmove (r, s3, l1 + 1);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memmove (r, s2, l1 + 2);
+ memmove (r + 2, s3, l1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ memmove (r, s2, l1);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ memmove (a.buf1 + 2, s3, 1);
+ memmove (r, s3, 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memmove (r, s2, 3);
+ r = buf3;
+ l = 4;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = 2;
+ else if (i == l1)
+ r = &a.buf2[7], l = 3;
+ else if (i == l1 + 1)
+ r = &buf3[5], l = 4;
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = 1;
+ }
+ memmove (r, s2, 1);
+ /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
+ is 4, so this doesn't need runtime checking. */
+ memmove (&buf3[16], s2, l);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test5 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memmove (&a.buf2[9], s2, l1 + 1);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memmove (&a.buf2[7], s3, strlen (s3) + 1);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memmove (&buf3[19], "ab", 2);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+#ifndef MAX_OFFSET
+#define MAX_OFFSET (sizeof (long long))
+#endif
+
+#ifndef MAX_COPY
+#define MAX_COPY (10 * sizeof (long long))
+#endif
+
+#ifndef MAX_EXTRA
+#define MAX_EXTRA (sizeof (long long))
+#endif
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
+
+/* Use a sequence length that is not divisible by two, to make it more
+ likely to detect when words are mixed up. */
+#define SEQUENCE_LENGTH 31
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u1, u2;
+
+void
+__attribute__((noinline))
+test6 (void)
+{
+ int off1, off2, len, i;
+ char *p, *q, c;
+
+ for (off1 = 0; off1 < MAX_OFFSET; off1++)
+ for (off2 = 0; off2 < MAX_OFFSET; off2++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+
+ p = memmove (u1.buf + off1, u2.buf + off2, len);
+ if (p != u1.buf + off1)
+ abort ();
+
+ q = u1.buf;
+ for (i = 0; i < off1; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
+ {
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ if (*q != c)
+ abort ();
+ }
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+}
+
+#define TESTSIZE 80
+
+char srcb[TESTSIZE] __attribute__ ((aligned));
+char dstb[TESTSIZE] __attribute__ ((aligned));
+
+void
+__attribute__((noinline))
+check (char *test, char *match, int n)
+{
+ if (memcmp (test, match, n))
+ abort ();
+}
+
+#define TN(n) \
+{ memset (dstb, 0, n); memmove (dstb, srcb, n); check (dstb, srcb, n); }
+#define T(n) \
+TN (n) \
+TN ((n) + 1) \
+TN ((n) + 2) \
+TN ((n) + 3)
+
+void
+__attribute__((noinline))
+test7 (void)
+{
+ int i;
+
+ chk_calls = 0;
+
+ for (i = 0; i < sizeof (srcb); ++i)
+ srcb[i] = 'a' + i % 26;
+
+ T (0);
+ T (4);
+ T (8);
+ T (12);
+ T (16);
+ T (20);
+ T (24);
+ T (28);
+ T (32);
+ T (36);
+ T (40);
+ T (44);
+ T (48);
+ T (52);
+ T (56);
+ T (60);
+ T (64);
+ T (68);
+ T (72);
+ T (76);
+
+ /* All memmove calls in this routine have constant arguments. */
+ if (chk_calls)
+ abort ();
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+ test2 ();
+ __builtin_memset (p, '\0', sizeof (p));
+ test3 ();
+ test4 ();
+ test5 ();
+ test6 ();
+ test7 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-lib.c
new file mode 100644
index 000000000..e2293ffc0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-lib.c
@@ -0,0 +1,7 @@
+#include "lib/memmove.c"
+#ifdef __vxworks
+/* The RTP C library uses bzero and bfill, both of which are defined
+ in the same file as bcopy. */
+#include "lib/bzero.c"
+#include "lib/bfill.c"
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove.c
new file mode 100644
index 000000000..f52332c6c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation.
+
+ Ensure builtin memmove and bcopy perform correctly.
+
+ Written by Jakub Jelinek, 4/26/2003. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern void *memmove (void *, const void *, size_t);
+extern void bcopy (const void *, void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+const char s1[] = "123";
+char p[32] = "";
+
+static const struct foo
+{
+ char *s;
+ double d;
+ long l;
+} foo[] =
+{
+ { "hello world1", 3.14159, 101L },
+ { "hello world2", 3.14159, 102L },
+ { "hello world3", 3.14159, 103L },
+ { "hello world4", 3.14159, 104L },
+ { "hello world5", 3.14159, 105L },
+ { "hello world6", 3.14159, 106L }
+};
+
+static const struct bar
+{
+ char *s;
+ const struct foo f[3];
+} bar[] =
+{
+ {
+ "hello world10",
+ {
+ { "hello1", 3.14159, 201L },
+ { "hello2", 3.14159, 202L },
+ { "hello3", 3.14159, 203L },
+ }
+ },
+ {
+ "hello world11",
+ {
+ { "hello4", 3.14159, 204L },
+ { "hello5", 3.14159, 205L },
+ { "hello6", 3.14159, 206L },
+ }
+ }
+};
+
+static const int baz[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+void
+main_test (void)
+{
+ const char *s;
+ struct foo f1[sizeof foo/sizeof*foo];
+ struct bar b1[sizeof bar/sizeof*bar];
+ int bz[sizeof baz/sizeof*baz];
+
+ if (memmove (f1, foo, sizeof (foo)) != f1 || memcmp (f1, foo, sizeof (foo)))
+ abort ();
+ if (memmove (b1, bar, sizeof (bar)) != b1 || memcmp (b1, bar, sizeof (bar)))
+ abort ();
+ bcopy (baz, bz, sizeof (baz));
+ if (memcmp (bz, baz, sizeof (baz)))
+ abort ();
+
+ if (memmove (p, "abcde", 6) != p || memcmp (p, "abcde", 6))
+ abort ();
+ s = s1;
+ if (memmove (p + 2, ++s, 0) != p + 2 || memcmp (p, "abcde", 6) || s != s1 + 1)
+ abort ();
+ if (__builtin_memmove (p + 3, "", 1) != p + 3 || memcmp (p, "abc\0e", 6))
+ abort ();
+ bcopy ("fghijk", p + 2, 4);
+ if (memcmp (p, "abfghi", 7))
+ abort ();
+ s = s1 + 1;
+ bcopy (s++, p + 1, 0);
+ if (memcmp (p, "abfghi", 7) || s != s1 + 2)
+ abort ();
+ __builtin_bcopy ("ABCDE", p + 4, 1);
+ if (memcmp (p, "abfgAi", 7))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c
new file mode 100644
index 000000000..00005298d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c
@@ -0,0 +1,97 @@
+extern void abort (void);
+extern int inside_main;
+typedef __SIZE_TYPE__ size_t;
+
+#define TEST_ABORT if (inside_main) abort()
+
+/* LTO code is at the present to able to track that asm alias my_bcopy on builtin
+ actually refers to this function. See PR47181. */
+__attribute__ ((used))
+void *
+my_memcpy (void *d, const void *s, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ while (n--)
+ *dst++ = *src++;
+ return (char *) d;
+}
+
+/* LTO code is at the present to able to track that asm alias my_bcopy on builtin
+ actually refers to this function. See PR47181. */
+__attribute__ ((used))
+void
+my_bcopy (const void *s, void *d, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ if (src >= dst)
+ while (n--)
+ *dst++ = *src++;
+ else
+ {
+ dst += n;
+ src += n;
+ while (n--)
+ *--dst = *--src;
+ }
+}
+
+/* LTO code is at the present to able to track that asm alias my_bcopy on builtin
+ actually refers to this function. See PR47181. */
+__attribute__ ((used))
+void *
+my_memset (void *d, int c, size_t n)
+{
+ char *dst = (char *) d;
+ while (n--)
+ *dst++ = c;
+ return (char *) d;
+}
+
+/* LTO code is at the present to able to track that asm alias my_bcopy on builtin
+ actually refers to this function. See PR47181. */
+__attribute__ ((used))
+void
+my_bzero (void *d, size_t n)
+{
+ char *dst = (char *) d;
+ while (n--)
+ *dst++ = '\0';
+}
+
+void *
+memcpy (void *d, const void *s, size_t n)
+{
+ void *result = my_memcpy (d, s, n);
+ TEST_ABORT;
+ return result;
+}
+
+void
+bcopy (const void *s, void *d, size_t n)
+{
+ my_bcopy (s, d, n);
+ TEST_ABORT;
+}
+
+void *
+memset (void *d, int c, size_t n)
+{
+ void *result = my_memset (d, c, n);
+ TEST_ABORT;
+ return result;
+}
+
+void
+bzero (void *d, size_t n)
+{
+ my_bzero (d, n);
+ TEST_ABORT;
+}
+
+#ifdef __vxworks
+/* The RTP C library uses bfill, which is defined in the same file as
+ bzero and bcopy. */
+#include "lib/bfill.c"
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c
new file mode 100644
index 000000000..ed2b06cf0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Test memcpy and memset in presence of redirect. */
+
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void *memcpy (void *, const void *, size_t)
+ __asm (ASMNAME ("my_memcpy"));
+extern void bcopy (const void *, void *, size_t)
+ __asm (ASMNAME ("my_bcopy"));
+extern void *memset (void *, int, size_t)
+ __asm (ASMNAME ("my_memset"));
+extern void bzero (void *, size_t)
+ __asm (ASMNAME ("my_bzero"));
+extern int memcmp (const void *, const void *, size_t);
+
+struct A { char c[32]; } a = { "foobar" };
+char x[64] = "foobar", y[64];
+int i = 39, j = 6, k = 4;
+
+extern int inside_main;
+
+void
+main_test (void)
+{
+ struct A b = a;
+ struct A c = { { 'x' } };
+
+ inside_main = 1;
+
+ if (memcmp (b.c, x, 32) || c.c[0] != 'x' || memcmp (c.c + 1, x + 32, 31))
+ abort ();
+ if (__builtin_memcpy (y, x, i) != y || memcmp (x, y, 64))
+ abort ();
+ if (memcpy (y + 6, x, j) != y + 6
+ || memcmp (x, y, 6) || memcmp (x, y + 6, 58))
+ abort ();
+ if (__builtin_memset (y + 2, 'X', k) != y + 2
+ || memcmp (y, "foXXXXfoobar", 13))
+ abort ();
+ bcopy (y + 1, y + 2, 6);
+ if (memcmp (y, "fooXXXXfobar", 13))
+ abort ();
+ __builtin_bzero (y + 4, 2);
+ if (memcmp (y, "fooX\0\0Xfobar", 13))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2-lib.c
new file mode 100644
index 000000000..cf3178c83
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2-lib.c
@@ -0,0 +1 @@
+#include "lib/mempcpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2.c
new file mode 100644
index 000000000..3b7767acb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-2.c
@@ -0,0 +1,153 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Ensure that builtin mempcpy and stpcpy perform correctly.
+
+ Written by Jakub Jelinek, 21/05/2003. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern void *mempcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern int inside_main;
+
+long buf1[64];
+char *buf2 = (char *) (buf1 + 32);
+long buf5[20];
+char buf7[20];
+
+void
+__attribute__((noinline))
+test (long *buf3, char *buf4, char *buf6, int n)
+{
+ int i = 0;
+
+ /* These should probably be handled by store_by_pieces on most arches. */
+ if (mempcpy (buf1, "ABCDEFGHI", 9) != (char *) buf1 + 9
+ || memcmp (buf1, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (mempcpy (buf1, "abcdefghijklmnopq", 17) != (char *) buf1 + 17
+ || memcmp (buf1, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf3, "ABCDEF", 6) != (char *) buf1 + 6
+ || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf3, "a", 1) != (char *) buf1 + 1
+ || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (mempcpy ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 4
+ || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
+ || i != 1)
+ abort ();
+
+ /* These should probably be handled by move_by_pieces on most arches. */
+ if (mempcpy ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 10
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
+ != (char *) buf1 + 11
+ || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ if (mempcpy ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 16
+ || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ if (mempcpy (buf3, buf5, 8) != (char *) buf1 + 8
+ || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
+ abort ();
+
+ if (mempcpy (buf3, buf5, 17) != (char *) buf1 + 17
+ || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
+ abort ();
+
+ __builtin_memcpy (buf3, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or mempcpy
+ call. */
+ if (mempcpy ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 10
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, n + 1)
+ != (char *) buf1 + 12
+ || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (mempcpy ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 16
+ || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ i = 1;
+
+ /* These might be handled by store_by_pieces. */
+ if (mempcpy (buf2, "ABCDEFGHI", 9) != buf2 + 9
+ || memcmp (buf2, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (mempcpy (buf2, "abcdefghijklmnopq", 17) != buf2 + 17
+ || memcmp (buf2, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf4, "ABCDEF", 6) != buf2 + 6
+ || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf4, "a", 1) != buf2 + 1
+ || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (mempcpy (buf4 + 2, "bcd" + i++, 2) != buf2 + 4
+ || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ /* These might be handled by move_by_pieces. */
+ if (mempcpy (buf4 + 4, buf7, 6) != buf2 + 10
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf2 + i++ + 8, buf7 + 1, 1)
+ != buf2 + 11
+ || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (mempcpy (buf4 + 14, buf6, 2) != buf2 + 16
+ || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ __builtin_memcpy (buf4, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or mempcpy
+ call. */
+ if (mempcpy (buf4 + 4, buf7, n + 6) != buf2 + 10
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf2 + i++ + 8, buf7 + 1, n + 1)
+ != buf2 + 12
+ || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 4)
+ abort ();
+
+ if (mempcpy (buf4 + 14, buf6, n + 2) != buf2 + 16
+ || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+}
+
+void
+main_test (void)
+{
+ /* All these tests are allowed to call mempcpy/stpcpy. */
+ inside_main = 0;
+ __builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
+ __builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
+ test (buf1, buf2, "rstuvwxyz", 0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.c
new file mode 100644
index 000000000..7a1737c4a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.c
@@ -0,0 +1,487 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __mempcpy_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *mempcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ int i;
+
+#if defined __i386__ || defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ mempcpy_disallowed = 1;
+#endif
+
+ /* All the mempcpy calls in this routine except last have fixed length, so
+ object size checking should be done at compile time if optimizing. */
+ chk_calls = 0;
+
+ if (mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+ abort ();
+ if (mempcpy (p + 16, "VWX" + 1, 2) != p + 16 + 2
+ || memcmp (p + 16, "WX\0\0", 5))
+ abort ();
+ if (mempcpy (p + 1, "", 1) != p + 1 + 1 || memcmp (p, "A\0CDE", 6))
+ abort ();
+ if (mempcpy (p + 3, "FGHI", 4) != p + 3 + 4 || memcmp (p, "A\0CFGHI", 8))
+ abort ();
+
+ i = 8;
+ memcpy (p + 20, "qrstu", 6);
+ memcpy (p + 25, "QRSTU", 6);
+ if (mempcpy (p + 25 + 1, s1, 3) != (p + 25 + 1 + 3)
+ || memcmp (p + 25, "Q123U", 6))
+ abort ();
+
+ if (mempcpy (mempcpy (p, "abcdEFG", 4), "efg", 4) != p + 8
+ || memcmp (p, "abcdefg", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+ abort ();
+
+ /* If the result of mempcpy is ignored, gcc should use memcpy.
+ This should be optimized always, so disallow mempcpy calls. */
+ mempcpy_disallowed = 1;
+ mempcpy (p + 5, s3, 1);
+ if (memcmp (p, "ABCDEFg", 8))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+
+ mempcpy (p + 6, s1 + 1, l1);
+ if (memcmp (p, "ABCDEF2", 8))
+ abort ();
+
+ /* The above mempcpy copies into an object with known size, but
+ unknown length and with result ignored, so it should be a
+ __memcpy_chk call. */
+ if (chk_calls != 1)
+ abort ();
+
+ mempcpy_disallowed = 0;
+}
+
+long buf1[64];
+char *buf2 = (char *) (buf1 + 32);
+long buf5[20];
+char buf7[20];
+
+void
+__attribute__((noinline))
+test2_sub (long *buf3, char *buf4, char *buf6, int n)
+{
+ int i = 0;
+
+ /* All the mempcpy/__builtin_mempcpy/__builtin___mempcpy_chk
+ calls in this routine are either fixed length, or have
+ side-effects in __builtin_object_size arguments, or
+ dst doesn't point into a known object. */
+ chk_calls = 0;
+
+ /* These should probably be handled by store_by_pieces on most arches. */
+ if (mempcpy (buf1, "ABCDEFGHI", 9) != (char *) buf1 + 9
+ || memcmp (buf1, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (mempcpy (buf1, "abcdefghijklmnopq", 17) != (char *) buf1 + 17
+ || memcmp (buf1, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf3, "ABCDEF", 6) != (char *) buf1 + 6
+ || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf3, "a", 1) != (char *) buf1 + 1
+ || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (mempcpy ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 4
+ || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
+ || i != 1)
+ abort ();
+
+ /* These should probably be handled by move_by_pieces on most arches. */
+ if (mempcpy ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 10
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
+ != (char *) buf1 + 11
+ || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ if (mempcpy ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 16
+ || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ if (mempcpy (buf3, buf5, 8) != (char *) buf1 + 8
+ || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
+ abort ();
+
+ if (mempcpy (buf3, buf5, 17) != (char *) buf1 + 17
+ || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
+ abort ();
+
+ __builtin_memcpy (buf3, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or mempcpy
+ call. */
+
+ /* buf3 points to an unknown object, so __mempcpy_chk should not be done. */
+ if (mempcpy ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 10
+ || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* This call has side-effects in dst, therefore no checking. */
+ if (__builtin___mempcpy_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1,
+ n + 1, os ((char *) buf1 + ++i + 8))
+ != (char *) buf1 + 12
+ || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (mempcpy ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 16
+ || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ i = 1;
+
+ /* These might be handled by store_by_pieces. */
+ if (mempcpy (buf2, "ABCDEFGHI", 9) != buf2 + 9
+ || memcmp (buf2, "ABCDEFGHI\0", 11))
+ abort ();
+
+ if (mempcpy (buf2, "abcdefghijklmnopq", 17) != buf2 + 17
+ || memcmp (buf2, "abcdefghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf4, "ABCDEF", 6) != buf2 + 6
+ || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (__builtin_mempcpy (buf4, "a", 1) != buf2 + 1
+ || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
+ abort ();
+
+ if (mempcpy (buf4 + 2, "bcd" + i++, 2) != buf2 + 4
+ || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
+ || i != 2)
+ abort ();
+
+ /* These might be handled by move_by_pieces. */
+ if (mempcpy (buf4 + 4, buf7, 6) != buf2 + 10
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* Side effect. */
+ if (__builtin___mempcpy_chk (buf2 + i++ + 8, buf7 + 1, 1,
+ os (buf2 + i++ + 8))
+ != buf2 + 11
+ || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
+ || i != 3)
+ abort ();
+
+ if (mempcpy (buf4 + 14, buf6, 2) != buf2 + 16
+ || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
+ abort ();
+
+ __builtin_memcpy (buf4, "aBcdEFghijklmnopq\0", 19);
+
+ /* These should be handled either by movmemendM or mempcpy
+ call. */
+ if (mempcpy (buf4 + 4, buf7, n + 6) != buf2 + 10
+ || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
+ abort ();
+
+ /* Side effect. */
+ if (__builtin___mempcpy_chk (buf2 + i++ + 8, buf7 + 1,
+ n + 1, os (buf2 + i++ + 8))
+ != buf2 + 12
+ || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
+ || i != 4)
+ abort ();
+
+ if (mempcpy (buf4 + 14, buf6, n + 2) != buf2 + 16
+ || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test2 (void)
+{
+ long *x;
+ char *y;
+ int z;
+ __builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
+ __builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
+ __asm ("" : "=r" (x) : "0" (buf1));
+ __asm ("" : "=r" (y) : "0" (buf2));
+ __asm ("" : "=r" (z) : "0" (0));
+ test2_sub (x, y, "rstuvwxyz", z);
+}
+
+volatile void *vx;
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ size_t l;
+
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ chk_calls = 0;
+ vx = mempcpy (a.buf1 + 2, s3, l1);
+ vx = mempcpy (r, s3, l1 + 1);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vx = mempcpy (r, s2, l1 + 2);
+ vx = mempcpy (r + 2, s3, l1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ vx = mempcpy (r, s2, l1);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ vx = mempcpy (a.buf1 + 2, s3, 1);
+ vx = mempcpy (r, s3, 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vx = mempcpy (r, s2, 3);
+ r = buf3;
+ l = 4;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = 2;
+ else if (i == l1)
+ r = &a.buf2[7], l = 3;
+ else if (i == l1 + 1)
+ r = &buf3[5], l = 4;
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = 1;
+ }
+ vx = mempcpy (r, s2, 1);
+ /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
+ is 4, so this doesn't need runtime checking. */
+ vx = mempcpy (&buf3[16], s2, l);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test4 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ vx = mempcpy (&a.buf2[9], s2, l1 + 1);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ vx = mempcpy (&a.buf2[7], s3, strlen (s3) + 1);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ vx = mempcpy (&buf3[19], "ab", 2);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+#ifndef MAX_OFFSET
+#define MAX_OFFSET (sizeof (long long))
+#endif
+
+#ifndef MAX_COPY
+#define MAX_COPY (10 * sizeof (long long))
+#endif
+
+#ifndef MAX_EXTRA
+#define MAX_EXTRA (sizeof (long long))
+#endif
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
+
+/* Use a sequence length that is not divisible by two, to make it more
+ likely to detect when words are mixed up. */
+#define SEQUENCE_LENGTH 31
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u1, u2;
+
+void
+__attribute__((noinline))
+test5 (void)
+{
+ int off1, off2, len, i;
+ char *p, *q, c;
+
+ for (off1 = 0; off1 < MAX_OFFSET; off1++)
+ for (off2 = 0; off2 < MAX_OFFSET; off2++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+
+ p = mempcpy (u1.buf + off1, u2.buf + off2, len);
+ if (p != u1.buf + off1 + len)
+ abort ();
+
+ q = u1.buf;
+ for (i = 0; i < off1; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
+ {
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ if (*q != c)
+ abort ();
+ }
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+}
+
+#define TESTSIZE 80
+
+char srcb[TESTSIZE] __attribute__ ((aligned));
+char dstb[TESTSIZE] __attribute__ ((aligned));
+
+void
+__attribute__((noinline))
+check (char *test, char *match, int n)
+{
+ if (memcmp (test, match, n))
+ abort ();
+}
+
+#define TN(n) \
+{ memset (dstb, 0, n); vx = mempcpy (dstb, srcb, n); check (dstb, srcb, n); }
+#define T(n) \
+TN (n) \
+TN ((n) + 1) \
+TN ((n) + 2) \
+TN ((n) + 3)
+
+void
+__attribute__((noinline))
+test6 (void)
+{
+ int i;
+
+ chk_calls = 0;
+
+ for (i = 0; i < sizeof (srcb); ++i)
+ srcb[i] = 'a' + i % 26;
+
+ T (0);
+ T (4);
+ T (8);
+ T (12);
+ T (16);
+ T (20);
+ T (24);
+ T (28);
+ T (32);
+ T (36);
+ T (40);
+ T (44);
+ T (48);
+ T (52);
+ T (56);
+ T (60);
+ T (64);
+ T (68);
+ T (72);
+ T (76);
+
+ /* All mempcpy calls in this routine have constant arguments. */
+ if (chk_calls)
+ abort ();
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+ test2 ();
+ test3 ();
+ test4 ();
+ test5 ();
+ test6 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-lib.c
new file mode 100644
index 000000000..cf3178c83
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-lib.c
@@ -0,0 +1 @@
+#include "lib/mempcpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy.c
new file mode 100644
index 000000000..d82e2232d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Ensure builtin mempcpy performs correctly.
+
+ Written by Kaveh Ghazi, 4/11/2003. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *mempcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern int inside_main;
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+size_t l1 = 1;
+
+void
+main_test (void)
+{
+ int i;
+
+#if !defined __i386__ && !defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ inside_main = 0;
+#endif
+
+ if (mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+ abort ();
+ if (mempcpy (p + 16, "VWX" + 1, 2) != p + 16 + 2
+ || memcmp (p + 16, "WX\0\0", 5))
+ abort ();
+ if (mempcpy (p + 1, "", 1) != p + 1 + 1 || memcmp (p, "A\0CDE", 6))
+ abort ();
+ if (mempcpy (p + 3, "FGHI", 4) != p + 3 + 4 || memcmp (p, "A\0CFGHI", 8))
+ abort ();
+
+ i = 8;
+ memcpy (p + 20, "qrstu", 6);
+ memcpy (p + 25, "QRSTU", 6);
+ if (mempcpy (p + 25 + 1, s1, 3) != (p + 25 + 1 + 3)
+ || memcmp (p + 25, "Q123U", 6))
+ abort ();
+
+ if (mempcpy (mempcpy (p, "abcdEFG", 4), "efg", 4) != p + 8
+ || memcmp (p, "abcdefg", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+ abort ();
+
+ /* If the result of mempcpy is ignored, gcc should use memcpy.
+ This should be optimized always, so set inside_main again. */
+ inside_main = 1;
+ mempcpy (p + 5, s3, 1);
+ if (memcmp (p, "ABCDEFg", 8))
+ abort ();
+ mempcpy (p + 6, s1 + 1, l1);
+ if (memcmp (p, "ABCDEF2", 8))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.c
new file mode 100644
index 000000000..902a88503
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.c
@@ -0,0 +1,721 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __memset_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *memset (void *, int, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+char buffer[32];
+int argc = 1;
+volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
+volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
+char *s4;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ memset_disallowed = 1;
+ chk_calls = 0;
+ memset (buffer, argc, 0);
+ memset (buffer, argc, 1);
+ memset (buffer, argc, 2);
+ memset (buffer, argc, 3);
+ memset (buffer, argc, 4);
+ memset (buffer, argc, 5);
+ memset (buffer, argc, 6);
+ memset (buffer, argc, 7);
+ memset (buffer, argc, 8);
+ memset (buffer, argc, 9);
+ memset (buffer, argc, 10);
+ memset (buffer, argc, 11);
+ memset (buffer, argc, 12);
+ memset (buffer, argc, 13);
+ memset (buffer, argc, 14);
+ memset (buffer, argc, 15);
+ memset (buffer, argc, 16);
+ memset (buffer, argc, 17);
+ memset_disallowed = 0;
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ size_t l;
+
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ chk_calls = 0;
+ memset (a.buf1 + 2, 'a', l1);
+ memset (r, '\0', l1 + 1);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memset (r, argc, l1 + 2);
+ memset (r + 2, 'Q', l1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ memset (r, '\0', l1);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ memset (a.buf1 + 2, '\0', 1);
+ memset (r, argc, 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memset (r, 'N', 3);
+ r = buf3;
+ l = 4;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = 2;
+ else if (i == l1)
+ r = &a.buf2[7], l = 3;
+ else if (i == l1 + 1)
+ r = &buf3[5], l = 4;
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = 1;
+ }
+ memset (r, 'H', 1);
+ /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
+ is 4, so this doesn't need runtime checking. */
+ memset (&buf3[16], 'd', l);
+ /* Neither length nor destination known. Doesn't need runtime checking. */
+ memset (s4, 'a', l1);
+ memset (s4 + 2, '\0', l1 + 2);
+ /* Destination unknown. */
+ memset (s4 + 4, 'b', 2);
+ memset (s4 + 6, '\0', 4);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memset (&a.buf2[9], '\0', l1 + 1);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memset (&a.buf2[7], 'T', strlen (s3) + 1);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ memset (&buf3[19], 'b', 2);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+#ifndef MAX_OFFSET
+#define MAX_OFFSET (sizeof (long long))
+#endif
+
+#ifndef MAX_COPY
+#define MAX_COPY (10 * sizeof (long long))
+#define MAX_COPY2 15
+#else
+#define MAX_COPY2 MAX_COPY
+#endif
+
+#ifndef MAX_EXTRA
+#define MAX_EXTRA (sizeof (long long))
+#endif
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
+#define MAX_LENGTH2 (MAX_OFFSET + MAX_COPY2 + MAX_EXTRA)
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u;
+
+char A = 'A';
+
+void
+__attribute__((noinline))
+test4 (void)
+{
+ int off, len, i;
+ char *p, *q;
+
+ for (off = 0; off < MAX_OFFSET; off++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0; i < MAX_LENGTH; i++)
+ u.buf[i] = 'a';
+
+ p = memset (u.buf + off, '\0', len);
+ if (p != u.buf + off)
+ abort ();
+
+ q = u.buf;
+ for (i = 0; i < off; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0; i < len; i++, q++)
+ if (*q != '\0')
+ abort ();
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ p = memset (u.buf + off, A, len);
+ if (p != u.buf + off)
+ abort ();
+
+ q = u.buf;
+ for (i = 0; i < off; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0; i < len; i++, q++)
+ if (*q != 'A')
+ abort ();
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ p = memset (u.buf + off, 'B', len);
+ if (p != u.buf + off)
+ abort ();
+
+ q = u.buf;
+ for (i = 0; i < off; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0; i < len; i++, q++)
+ if (*q != 'B')
+ abort ();
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+}
+
+static union {
+ char buf[MAX_LENGTH2];
+ long long align_int;
+ long double align_fp;
+} u2;
+
+void reset ()
+{
+ int i;
+
+ for (i = 0; i < MAX_LENGTH2; i++)
+ u2.buf[i] = 'a';
+}
+
+void check (int off, int len, int ch)
+{
+ char *q;
+ int i;
+
+ q = u2.buf;
+ for (i = 0; i < off; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0; i < len; i++, q++)
+ if (*q != ch)
+ abort ();
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test5 (void)
+{
+ int off;
+ char *p;
+
+ /* len == 1 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 1);
+ if (p != u2.buf + off) abort ();
+ check (off, 1, '\0');
+
+ p = memset (u2.buf + off, A, 1);
+ if (p != u2.buf + off) abort ();
+ check (off, 1, 'A');
+
+ p = memset (u2.buf + off, 'B', 1);
+ if (p != u2.buf + off) abort ();
+ check (off, 1, 'B');
+ }
+
+ /* len == 2 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 2);
+ if (p != u2.buf + off) abort ();
+ check (off, 2, '\0');
+
+ p = memset (u2.buf + off, A, 2);
+ if (p != u2.buf + off) abort ();
+ check (off, 2, 'A');
+
+ p = memset (u2.buf + off, 'B', 2);
+ if (p != u2.buf + off) abort ();
+ check (off, 2, 'B');
+ }
+
+ /* len == 3 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 3);
+ if (p != u2.buf + off) abort ();
+ check (off, 3, '\0');
+
+ p = memset (u2.buf + off, A, 3);
+ if (p != u2.buf + off) abort ();
+ check (off, 3, 'A');
+
+ p = memset (u2.buf + off, 'B', 3);
+ if (p != u2.buf + off) abort ();
+ check (off, 3, 'B');
+ }
+
+ /* len == 4 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 4);
+ if (p != u2.buf + off) abort ();
+ check (off, 4, '\0');
+
+ p = memset (u2.buf + off, A, 4);
+ if (p != u2.buf + off) abort ();
+ check (off, 4, 'A');
+
+ p = memset (u2.buf + off, 'B', 4);
+ if (p != u2.buf + off) abort ();
+ check (off, 4, 'B');
+ }
+
+ /* len == 5 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 5);
+ if (p != u2.buf + off) abort ();
+ check (off, 5, '\0');
+
+ p = memset (u2.buf + off, A, 5);
+ if (p != u2.buf + off) abort ();
+ check (off, 5, 'A');
+
+ p = memset (u2.buf + off, 'B', 5);
+ if (p != u2.buf + off) abort ();
+ check (off, 5, 'B');
+ }
+
+ /* len == 6 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 6);
+ if (p != u2.buf + off) abort ();
+ check (off, 6, '\0');
+
+ p = memset (u2.buf + off, A, 6);
+ if (p != u2.buf + off) abort ();
+ check (off, 6, 'A');
+
+ p = memset (u2.buf + off, 'B', 6);
+ if (p != u2.buf + off) abort ();
+ check (off, 6, 'B');
+ }
+
+ /* len == 7 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 7);
+ if (p != u2.buf + off) abort ();
+ check (off, 7, '\0');
+
+ p = memset (u2.buf + off, A, 7);
+ if (p != u2.buf + off) abort ();
+ check (off, 7, 'A');
+
+ p = memset (u2.buf + off, 'B', 7);
+ if (p != u2.buf + off) abort ();
+ check (off, 7, 'B');
+ }
+
+ /* len == 8 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 8);
+ if (p != u2.buf + off) abort ();
+ check (off, 8, '\0');
+
+ p = memset (u2.buf + off, A, 8);
+ if (p != u2.buf + off) abort ();
+ check (off, 8, 'A');
+
+ p = memset (u2.buf + off, 'B', 8);
+ if (p != u2.buf + off) abort ();
+ check (off, 8, 'B');
+ }
+
+ /* len == 9 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 9);
+ if (p != u2.buf + off) abort ();
+ check (off, 9, '\0');
+
+ p = memset (u2.buf + off, A, 9);
+ if (p != u2.buf + off) abort ();
+ check (off, 9, 'A');
+
+ p = memset (u2.buf + off, 'B', 9);
+ if (p != u2.buf + off) abort ();
+ check (off, 9, 'B');
+ }
+
+ /* len == 10 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 10);
+ if (p != u2.buf + off) abort ();
+ check (off, 10, '\0');
+
+ p = memset (u2.buf + off, A, 10);
+ if (p != u2.buf + off) abort ();
+ check (off, 10, 'A');
+
+ p = memset (u2.buf + off, 'B', 10);
+ if (p != u2.buf + off) abort ();
+ check (off, 10, 'B');
+ }
+
+ /* len == 11 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 11);
+ if (p != u2.buf + off) abort ();
+ check (off, 11, '\0');
+
+ p = memset (u2.buf + off, A, 11);
+ if (p != u2.buf + off) abort ();
+ check (off, 11, 'A');
+
+ p = memset (u2.buf + off, 'B', 11);
+ if (p != u2.buf + off) abort ();
+ check (off, 11, 'B');
+ }
+
+ /* len == 12 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 12);
+ if (p != u2.buf + off) abort ();
+ check (off, 12, '\0');
+
+ p = memset (u2.buf + off, A, 12);
+ if (p != u2.buf + off) abort ();
+ check (off, 12, 'A');
+
+ p = memset (u2.buf + off, 'B', 12);
+ if (p != u2.buf + off) abort ();
+ check (off, 12, 'B');
+ }
+
+ /* len == 13 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 13);
+ if (p != u2.buf + off) abort ();
+ check (off, 13, '\0');
+
+ p = memset (u2.buf + off, A, 13);
+ if (p != u2.buf + off) abort ();
+ check (off, 13, 'A');
+
+ p = memset (u2.buf + off, 'B', 13);
+ if (p != u2.buf + off) abort ();
+ check (off, 13, 'B');
+ }
+
+ /* len == 14 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 14);
+ if (p != u2.buf + off) abort ();
+ check (off, 14, '\0');
+
+ p = memset (u2.buf + off, A, 14);
+ if (p != u2.buf + off) abort ();
+ check (off, 14, 'A');
+
+ p = memset (u2.buf + off, 'B', 14);
+ if (p != u2.buf + off) abort ();
+ check (off, 14, 'B');
+ }
+
+ /* len == 15 */
+ for (off = 0; off < MAX_OFFSET; off++)
+ {
+ reset ();
+
+ p = memset (u2.buf + off, '\0', 15);
+ if (p != u2.buf + off) abort ();
+ check (off, 15, '\0');
+
+ p = memset (u2.buf + off, A, 15);
+ if (p != u2.buf + off) abort ();
+ check (off, 15, 'A');
+
+ p = memset (u2.buf + off, 'B', 15);
+ if (p != u2.buf + off) abort ();
+ check (off, 15, 'B');
+ }
+}
+
+void
+__attribute__((noinline))
+test6 (void)
+{
+ int len;
+ char *p;
+
+ /* off == 0 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf, '\0', len);
+ if (p != u2.buf) abort ();
+ check (0, len, '\0');
+
+ p = memset (u2.buf, A, len);
+ if (p != u2.buf) abort ();
+ check (0, len, 'A');
+
+ p = memset (u2.buf, 'B', len);
+ if (p != u2.buf) abort ();
+ check (0, len, 'B');
+ }
+
+ /* off == 1 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+1, '\0', len);
+ if (p != u2.buf+1) abort ();
+ check (1, len, '\0');
+
+ p = memset (u2.buf+1, A, len);
+ if (p != u2.buf+1) abort ();
+ check (1, len, 'A');
+
+ p = memset (u2.buf+1, 'B', len);
+ if (p != u2.buf+1) abort ();
+ check (1, len, 'B');
+ }
+
+ /* off == 2 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+2, '\0', len);
+ if (p != u2.buf+2) abort ();
+ check (2, len, '\0');
+
+ p = memset (u2.buf+2, A, len);
+ if (p != u2.buf+2) abort ();
+ check (2, len, 'A');
+
+ p = memset (u2.buf+2, 'B', len);
+ if (p != u2.buf+2) abort ();
+ check (2, len, 'B');
+ }
+
+ /* off == 3 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+3, '\0', len);
+ if (p != u2.buf+3) abort ();
+ check (3, len, '\0');
+
+ p = memset (u2.buf+3, A, len);
+ if (p != u2.buf+3) abort ();
+ check (3, len, 'A');
+
+ p = memset (u2.buf+3, 'B', len);
+ if (p != u2.buf+3) abort ();
+ check (3, len, 'B');
+ }
+
+ /* off == 4 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+4, '\0', len);
+ if (p != u2.buf+4) abort ();
+ check (4, len, '\0');
+
+ p = memset (u2.buf+4, A, len);
+ if (p != u2.buf+4) abort ();
+ check (4, len, 'A');
+
+ p = memset (u2.buf+4, 'B', len);
+ if (p != u2.buf+4) abort ();
+ check (4, len, 'B');
+ }
+
+ /* off == 5 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+5, '\0', len);
+ if (p != u2.buf+5) abort ();
+ check (5, len, '\0');
+
+ p = memset (u2.buf+5, A, len);
+ if (p != u2.buf+5) abort ();
+ check (5, len, 'A');
+
+ p = memset (u2.buf+5, 'B', len);
+ if (p != u2.buf+5) abort ();
+ check (5, len, 'B');
+ }
+
+ /* off == 6 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+6, '\0', len);
+ if (p != u2.buf+6) abort ();
+ check (6, len, '\0');
+
+ p = memset (u2.buf+6, A, len);
+ if (p != u2.buf+6) abort ();
+ check (6, len, 'A');
+
+ p = memset (u2.buf+6, 'B', len);
+ if (p != u2.buf+6) abort ();
+ check (6, len, 'B');
+ }
+
+ /* off == 7 */
+ for (len = 0; len < MAX_COPY2; len++)
+ {
+ reset ();
+
+ p = memset (u2.buf+7, '\0', len);
+ if (p != u2.buf+7) abort ();
+ check (7, len, '\0');
+
+ p = memset (u2.buf+7, A, len);
+ if (p != u2.buf+7) abort ();
+ check (7, len, 'A');
+
+ p = memset (u2.buf+7, 'B', len);
+ if (p != u2.buf+7) abort ();
+ check (7, len, 'B');
+ }
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = buffer;
+ test1 ();
+ test2 ();
+ test3 ();
+ test4 ();
+ test5 ();
+ test6 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memset-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-lib.c
new file mode 100644
index 000000000..2eeff38be
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-lib.c
@@ -0,0 +1 @@
+#include "lib/memset.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memset.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memset.c
new file mode 100644
index 000000000..cf7c1e303
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memset.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation.
+
+ Ensure that builtin memset operations for constant length and
+ non-constant assigned value don't cause compiler problems.
+
+ Written by Roger Sayle, 21 April 2002. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern void *memset (void *, int, size_t);
+
+char buffer[32];
+int argc = 1;
+
+void
+main_test (void)
+{
+ memset (buffer, argc, 0);
+ memset (buffer, argc, 1);
+ memset (buffer, argc, 2);
+ memset (buffer, argc, 3);
+ memset (buffer, argc, 4);
+ memset (buffer, argc, 5);
+ memset (buffer, argc, 6);
+ memset (buffer, argc, 7);
+ memset (buffer, argc, 8);
+ memset (buffer, argc, 9);
+ memset (buffer, argc, 10);
+ memset (buffer, argc, 11);
+ memset (buffer, argc, 12);
+ memset (buffer, argc, 13);
+ memset (buffer, argc, 14);
+ memset (buffer, argc, 15);
+ memset (buffer, argc, 16);
+ memset (buffer, argc, 17);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
new file mode 100644
index 000000000..440323574
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
@@ -0,0 +1,27 @@
+extern void abort (void);
+
+void *
+memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+ srcp = src;
+ dstp = dst;
+
+ if (dst < src)
+ {
+ if (dst + n > src)
+ abort ();
+ }
+ else
+ {
+ if (src + n > dst)
+ abort ();
+ }
+
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dst;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
new file mode 100644
index 000000000..957a47c0f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
@@ -0,0 +1,44 @@
+extern void abort (void);
+extern void exit (int);
+struct s { unsigned char a[256]; };
+union u { struct { struct s b; int c; } d; struct { int c; struct s b; } e; };
+static union u v;
+static union u v0;
+static struct s *p = &v.d.b;
+static struct s *q = &v.e.b;
+
+static inline struct s rp (void) { return *p; }
+static inline struct s rq (void) { return *q; }
+static void pq (void) { *p = rq(); }
+static void qp (void) { *q = rp(); }
+
+static void
+init (struct s *sp)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ sp->a[i] = i;
+}
+
+static void
+check (struct s *sp)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (sp->a[i] != i)
+ abort ();
+}
+
+void
+main_test (void)
+{
+ v = v0;
+ init (p);
+ qp ();
+ check (q);
+ v = v0;
+ init (q);
+ pq ();
+ check (p);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.c
new file mode 100644
index 000000000..446fb6c2f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.c
@@ -0,0 +1,67 @@
+/* PR middle-end/23484 */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen (const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *mempcpy (void *, const void *, size_t);
+extern void *memmove (void *, const void *, size_t);
+extern int snprintf (char *, size_t, const char *, ...);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+static char data[8] = "ABCDEFG";
+
+int l1;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ char buf[8];
+
+ /* All the checking calls in this routine have a maximum length, so
+ object size checking should be done at compile time if optimizing. */
+ chk_calls = 0;
+
+ memset (buf, 'I', sizeof (buf));
+ if (memcpy (buf, data, l1 ? sizeof (buf) : 4) != buf
+ || memcmp (buf, "ABCDIIII", 8))
+ abort ();
+
+ memset (buf, 'J', sizeof (buf));
+ if (mempcpy (buf, data, l1 ? sizeof (buf) : 4) != buf + 4
+ || memcmp (buf, "ABCDJJJJ", 8))
+ abort ();
+
+ memset (buf, 'K', sizeof (buf));
+ if (memmove (buf, data, l1 ? sizeof (buf) : 4) != buf
+ || memcmp (buf, "ABCDKKKK", 8))
+ abort ();
+
+ memset (buf, 'L', sizeof (buf));
+#if(__SIZEOF_INT__ >= 4)
+ if (snprintf (buf, l1 ? sizeof (buf) : 4, "%d", l1 + 65536) != 5
+ || memcmp (buf, "655\0LLLL", 8))
+ abort ();
+#else
+ if (snprintf (buf, l1 ? sizeof (buf) : 4, "%d", l1 + 32700) != 5
+ || memcmp (buf, "327\0LLLL", 8))
+ abort ();
+#endif
+
+ if (chk_calls)
+ abort ();
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/printf-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/printf-lib.c
new file mode 100644
index 000000000..45ed7ec37
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/printf-lib.c
@@ -0,0 +1 @@
+#include "lib/printf.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/printf.c b/gcc/testsuite/gcc.c-torture/execute/builtins/printf.c
new file mode 100644
index 000000000..e493f90b7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/printf.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2000 Free Software Foundation.
+
+ Ensure all expected transformations of builtin printf occur and
+ that we honor side effects in the arguments.
+
+ Written by Kaveh R. Ghazi, 12/4/2000. */
+
+extern int printf (const char *, ...);
+extern int printf_unlocked (const char *, ...);
+extern void abort(void);
+
+void
+main_test (void)
+{
+ const char *const s1 = "hello world";
+ const char *const s2[] = { s1, 0 }, *const*s3;
+
+ printf ("%s\n", "hello");
+ printf ("%s\n", *s2);
+ s3 = s2;
+ printf ("%s\n", *s3++);
+ if (s3 != s2+1 || *s3 != 0)
+ abort();
+
+ printf ("%c", '\n');
+ printf ("%c", **s2);
+ s3 = s2;
+ printf ("%c", **s3++);
+ if (s3 != s2+1 || *s3 != 0)
+ abort();
+
+ printf ("");
+ printf ("%s", "");
+ printf ("\n");
+ printf ("%s", "\n");
+ printf ("hello world\n");
+ printf ("%s", "hello world\n");
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ __builtin_printf ("%s\n", "hello");
+ /* These builtin stubs are called by __builtin_printf, ensure their
+ prototypes are set correctly too. */
+ __builtin_putchar ('\n');
+ __builtin_puts ("hello");
+ /* Check the unlocked style, these evaluate to nothing to avoid
+ problems on systems without the unlocked functions. */
+ printf_unlocked ("");
+ __builtin_printf_unlocked ("");
+ printf_unlocked ("%s", "");
+ __builtin_printf_unlocked ("%s", "");
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.c
new file mode 100644
index 000000000..b244f8925
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __snprintf_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+extern void *memset (void *, int, size_t);
+extern int sprintf (char *, const char *, ...);
+extern int snprintf (char *, size_t, const char *, ...);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+static char buffer[32];
+char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ chk_calls = 0;
+ /* snprintf_disallowed = 1; */
+
+ memset (buffer, 'A', 32);
+ snprintf (buffer, 4, "foo");
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (snprintf (buffer, 4, "foo bar") != 7)
+ abort ();
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ snprintf (buffer, 32, "%s", "bar");
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (snprintf (buffer, 21, "%s", "bar") != 3)
+ abort ();
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ snprintf_disallowed = 0;
+
+ memset (buffer, 'A', 32);
+ if (snprintf (buffer, 4, "%d%d%d", (int) l1, (int) l1 + 1, (int) l1 + 12)
+ != 4)
+ abort ();
+ if (memcmp (buffer, "121", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (snprintf (buffer, 32, "%d%d%d", (int) l1, (int) l1 + 1, (int) l1 + 12)
+ != 4)
+ abort ();
+ if (memcmp (buffer, "1213", 5) || buffer[5] != 'A')
+ abort ();
+
+ if (chk_calls)
+ abort ();
+
+ memset (buffer, 'A', 32);
+ snprintf (buffer, strlen (ptr) + 1, "%s", ptr);
+ if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ snprintf (buffer, l1 + 31, "%d - %c", (int) l1 + 27, *ptr);
+ if (memcmp (buffer, "28 - b\0AAAAA", 12))
+ abort ();
+
+ if (chk_calls != 2)
+ abort ();
+ chk_calls = 0;
+
+ memset (s4, 'A', 32);
+ snprintf (s4, l1 + 6, "%d - %c", (int) l1 - 17, ptr[1]);
+ if (memcmp (s4, "-16 - \0AAA", 10))
+ abort ();
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ chk_calls = 0;
+ snprintf (a.buf1 + 2, l1, "%s", s3 + 3);
+ snprintf (r, l1 + 4, "%s%c", s3 + 3, s3[3]);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ snprintf (r, strlen (s2) - 2, "%c %s", s2[2], s2 + 4);
+ snprintf (r + 2, l1, s3 + 3);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ snprintf (r, l1, s2 + 4);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known source length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ /* snprintf_disallowed = 1; */
+ snprintf (a.buf1 + 2, 4, "");
+ snprintf (r, 1, "a");
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ snprintf (r, 3, "%s", s1 + 1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ snprintf (r, 1, "%s", "");
+ snprintf (r, 0, "%s", "");
+ snprintf_disallowed = 0;
+ /* Unknown destination and source, no checking. */
+ snprintf (s4, l1 + 31, "%s %d", s3, 0);
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ snprintf (&a.buf2[9], l1 + 1, "%c%s", s2[3], s2 + 4);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ snprintf (&a.buf2[7], l1 + 30, "%s%c", s3 + strlen (s3) - 2, *s3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ snprintf (&a.buf2[7], l1 + 3, "%d", (int) l1 + 9999);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ snprintf (&buf3[19], 2, "a");
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ snprintf (&buf3[17], 4, "a");
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ snprintf (&buf3[17], 4, "%s", "abc");
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = p;
+ test1 ();
+ test2 ();
+ test3 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.c
new file mode 100644
index 000000000..8a283626d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.c
@@ -0,0 +1,197 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __sprintf_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+extern void *memset (void *, int, size_t);
+extern int sprintf (char *, const char *, ...);
+
+#include "chk.h"
+
+LOCAL const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+static char buffer[32];
+char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ chk_calls = 0;
+ sprintf_disallowed = 1;
+
+ memset (buffer, 'A', 32);
+ sprintf (buffer, "foo");
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (sprintf (buffer, "foo") != 3)
+ abort ();
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ sprintf (buffer, "%s", "bar");
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (sprintf (buffer, "%s", "bar") != 3)
+ abort ();
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ if (chk_calls)
+ abort ();
+ sprintf_disallowed = 0;
+
+ memset (buffer, 'A', 32);
+ sprintf (buffer, "%s", ptr);
+ if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ sprintf (buffer, "%d - %c", (int) l1 + 27, *ptr);
+ if (memcmp (buffer, "28 - b\0AAAAA", 12))
+ abort ();
+
+ if (chk_calls != 2)
+ abort ();
+ chk_calls = 0;
+
+ sprintf (s4, "%d - %c", (int) l1 - 17, ptr[1]);
+ if (memcmp (s4, "-16 - a", 8))
+ abort ();
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ chk_calls = 0;
+ sprintf (a.buf1 + 2, "%s", s3 + 3);
+ sprintf (r, "%s%c", s3 + 3, s3[3]);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ sprintf (r, "%c %s", s2[2], s2 + 4);
+ sprintf (r + 2, s3 + 3);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ sprintf (r, s2 + 4);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known source length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ sprintf_disallowed = 1;
+ sprintf (a.buf1 + 2, "");
+ sprintf (r, "a");
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ sprintf (r, "%s", s1 + 1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ sprintf (r, "%s", "");
+ sprintf_disallowed = 0;
+ /* Unknown destination and source, no checking. */
+ sprintf (s4, "%s %d", s3, 0);
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ sprintf (&a.buf2[9], "%c%s", s2[3], s2 + 4);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ sprintf (&a.buf2[7], "%s%c", s3 + strlen (s3) - 2, *s3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ sprintf (&a.buf2[7], "%d", (int) l1 + 9999);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ sprintf (&buf3[19], "a");
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ sprintf (&buf3[17], "%s", "abc");
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = p;
+ test1 ();
+ test2 ();
+ test3 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-lib.c
new file mode 100644
index 000000000..3a4fe34c0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-lib.c
@@ -0,0 +1 @@
+#include "lib/sprintf.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf.c b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf.c
new file mode 100644
index 000000000..b45926469
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Test sprintf optimizations don't break anything and return the
+ correct results.
+
+ Written by Roger Sayle, June 22, 2003. */
+
+static char buffer[32];
+
+extern void abort ();
+typedef __SIZE_TYPE__ size_t;
+extern int sprintf(char*, const char*, ...);
+extern void *memset(void*, int, size_t);
+extern int memcmp(const void*, const void*, size_t);
+
+void test1()
+{
+ sprintf(buffer,"foo");
+}
+
+int test2()
+{
+ return sprintf(buffer,"foo");
+}
+
+void test3()
+{
+ sprintf(buffer,"%s","bar");
+}
+
+int test4()
+{
+ return sprintf(buffer,"%s","bar");
+}
+
+void test5(char *ptr)
+{
+ sprintf(buffer,"%s",ptr);
+}
+
+
+void
+main_test (void)
+{
+ memset (buffer, 'A', 32);
+ test1 ();
+ if (memcmp(buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test2 () != 3)
+ abort ();
+ if (memcmp(buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ test3 ();
+ if (memcmp(buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test4 () != 3)
+ abort ();
+ if (memcmp(buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ test5 ("barf");
+ if (memcmp(buffer, "barf", 5) || buffer[5] != 'A')
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.c
new file mode 100644
index 000000000..6091f1293
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.c
@@ -0,0 +1,265 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __stpcpy_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *stpcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+LOCAL const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ int i = 8;
+
+#if defined __i386__ || defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ stpcpy_disallowed = 1;
+#endif
+ if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+ abort ();
+ if (stpcpy (p + 16, "vwxyz" + 1) != p + 16 + 4 || memcmp (p + 16, "wxyz", 5))
+ abort ();
+ if (stpcpy (p + 1, "") != p + 1 + 0 || memcmp (p, "a\0cde", 6))
+ abort ();
+ if (stpcpy (p + 3, "fghij") != p + 3 + 5 || memcmp (p, "a\0cfghij", 9))
+ abort ();
+
+ if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2)
+ || i != 9 || memcmp (p + 19, "z\0""23\0", 5))
+ abort ();
+
+ if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+ abort ();
+
+ /* If return value of stpcpy is ignored, it should be optimized into
+ strcpy call. */
+ stpcpy_disallowed = 1;
+ stpcpy (p + 1, "abcd");
+ stpcpy_disallowed = 0;
+ if (memcmp (p, "aabcd", 6))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+
+ chk_calls = 0;
+ strcpy_disallowed = 1;
+ if (stpcpy (p, s2) != p + 4 || memcmp (p, "defg\0", 6))
+ abort ();
+ strcpy_disallowed = 0;
+ stpcpy_disallowed = 1;
+ stpcpy (p + 2, s3);
+ stpcpy_disallowed = 0;
+ if (memcmp (p, "deFGH", 6))
+ abort ();
+ if (chk_calls != 2)
+ abort ();
+}
+
+#ifndef MAX_OFFSET
+#define MAX_OFFSET (sizeof (long long))
+#endif
+
+#ifndef MAX_COPY
+#define MAX_COPY (10 * sizeof (long long))
+#endif
+
+#ifndef MAX_EXTRA
+#define MAX_EXTRA (sizeof (long long))
+#endif
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + 1 + MAX_EXTRA)
+
+/* Use a sequence length that is not divisible by two, to make it more
+ likely to detect when words are mixed up. */
+#define SEQUENCE_LENGTH 31
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u1, u2;
+
+volatile char *vx;
+
+void
+__attribute__((noinline))
+test2 (void)
+{
+ int off1, off2, len, i;
+ char *p, *q, c;
+
+ for (off1 = 0; off1 < MAX_OFFSET; off1++)
+ for (off2 = 0; off2 < MAX_OFFSET; off2++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+ u2.buf[off2 + len] = '\0';
+
+ p = stpcpy (u1.buf + off1, u2.buf + off2);
+ if (p != u1.buf + off1 + len)
+ abort ();
+
+ q = u1.buf;
+ for (i = 0; i < off1; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
+ {
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ if (*q != c)
+ abort ();
+ }
+
+ if (*q++ != '\0')
+ abort ();
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ const char *l;
+
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ chk_calls = 0;
+ vx = stpcpy (a.buf1 + 2, s3 + 3);
+ vx = stpcpy (r, s3 + 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vx = stpcpy (r, s2 + 2);
+ vx = stpcpy (r + 2, s3 + 3);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ vx = stpcpy (r, s2 + 4);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known source length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ vx = stpcpy (a.buf1 + 2, "");
+ vx = stpcpy (r, "a");
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vx = stpcpy (r, s1 + 1);
+ r = buf3;
+ l = "abc";
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = "e";
+ else if (i == l1)
+ r = &a.buf2[7], l = "gh";
+ else if (i == l1 + 1)
+ r = &buf3[5], l = "jkl";
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = "";
+ }
+ vx = stpcpy (r, "");
+ /* Here, strlen (l) + 1 is known to be at most 4 and
+ __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
+ runtime checking. */
+ vx = stpcpy (&buf3[16], l);
+ /* Unknown destination and source, no checking. */
+ vx = stpcpy (s4, s3);
+ stpcpy (s4 + 4, s3);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test4 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ vx = stpcpy (&a.buf2[9], s2 + 3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ vx = stpcpy (&a.buf2[7], s3 + strlen (s3) - 3);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ vx = stpcpy (&buf3[19], "a");
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+ s4 = p;
+ test2 ();
+ test3 ();
+ test4 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.c
new file mode 100644
index 000000000..fea3184e8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.c
@@ -0,0 +1,204 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __strcat_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcat (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int strcmp (const char *, const char *);
+extern void *memset (void *, int, size_t);
+#define RESET_DST_WITH(FILLER) \
+ do { memset (dst, 'X', sizeof (dst)); strcpy (dst, (FILLER)); } while (0)
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+char *s5;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ const char *const x1 = "hello world";
+ const char *const x2 = "";
+ char dst[64], *d2;
+
+ chk_calls = 0;
+ strcat_disallowed = 1;
+ /* Following strcat calls should be optimized out at compile time. */
+ RESET_DST_WITH (x1);
+ if (strcat (dst, "") != dst || strcmp (dst, x1))
+ abort ();
+ RESET_DST_WITH (x1);
+ if (strcat (dst, x2) != dst || strcmp (dst, x1))
+ abort ();
+ RESET_DST_WITH (x1); d2 = dst;
+ if (strcat (++d2, x2) != dst+1 || d2 != dst+1 || strcmp (dst, x1))
+ abort ();
+ RESET_DST_WITH (x1); d2 = dst;
+ if (strcat (++d2+5, x2) != dst+6 || d2 != dst+1 || strcmp (dst, x1))
+ abort ();
+ RESET_DST_WITH (x1); d2 = dst;
+ if (strcat (++d2+5, x1+11) != dst+6 || d2 != dst+1 || strcmp (dst, x1))
+ abort ();
+ if (chk_calls)
+ abort ();
+ strcat_disallowed = 0;
+
+ RESET_DST_WITH (x1);
+ if (strcat (dst, " 1111") != dst
+ || memcmp (dst, "hello world 1111\0XXX", 20))
+ abort ();
+
+ RESET_DST_WITH (x1);
+ if (strcat (dst+5, " 2222") != dst+5
+ || memcmp (dst, "hello world 2222\0XXX", 20))
+ abort ();
+
+ RESET_DST_WITH (x1); d2 = dst;
+ if (strcat (++d2+5, " 3333") != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world 3333\0XXX", 20))
+ abort ();
+
+ RESET_DST_WITH (x1);
+ strcat (strcat (strcat (strcat (strcat (strcat (dst, ": this "), ""),
+ "is "), "a "), "test"), ".");
+ if (memcmp (dst, "hello world: this is a test.\0X", 30))
+ abort ();
+
+ chk_calls = 0;
+ strcat_disallowed = 1;
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ RESET_DST_WITH (x1);
+ if (__builtin_strcat (dst, "") != dst || strcmp (dst, x1))
+ abort ();
+ if (chk_calls)
+ abort ();
+ strcat_disallowed = 0;
+}
+
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ memset (&a, '\0', sizeof (a));
+ s5 = (char *) &a;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ chk_calls = 0;
+ strcat (a.buf1 + 2, s3 + 3);
+ strcat (r, s3 + 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memset (r, '\0', 3);
+ __asm __volatile ("" : : "r" (r) : "memory");
+ strcat (r, s2 + 2);
+ strcat (r + 2, s3 + 3);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ strcat (r, s2 + 4);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known source length,
+ but we don't know the length of dest string, so runtime checking
+ is needed too. */
+ memset (&a, '\0', sizeof (a));
+ chk_calls = 0;
+ s5 = (char *) &a;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ strcat (a.buf1 + 2, "a");
+ strcat (r, "");
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memset (r, '\0', 3);
+ __asm __volatile ("" : : "r" (r) : "memory");
+ strcat (r, s1 + 1);
+ if (chk_calls != 2)
+ abort ();
+ chk_calls = 0;
+ /* Unknown destination and source, no checking. */
+ strcat (s4, s3);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ memset (&a, '\0', sizeof (a));
+ memset (buf3, '\0', sizeof (buf3));
+ s5 = (char *) &a;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ s5 = buf3;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strcat (&a.buf2[9], s2 + 3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strcat (&a.buf2[7], s3 + strlen (s3) - 3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strcat (&buf3[19], "a");
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = p;
+ test1 ();
+ memset (p, '\0', sizeof (p));
+ test2 ();
+ test3 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-lib.c
new file mode 100644
index 000000000..0a0bbb886
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-lib.c
@@ -0,0 +1 @@
+#include "lib/strcat.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcat.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat.c
new file mode 100644
index 000000000..0fb1ba1c4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2000, 2003 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strcat occur and
+ perform correctly.
+
+ Written by Kaveh R. Ghazi, 11/27/2000. */
+
+extern int inside_main;
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern char *strcat (char *, const char *);
+extern char *strcpy (char *, const char *);
+extern void *memset (void *, int, size_t);
+extern int memcmp (const void *, const void *, size_t);
+#define RESET_DST_WITH(FILLER) \
+ do { memset (dst, 'X', sizeof (dst)); strcpy (dst, (FILLER)); } while (0)
+
+void main_test (void)
+{
+ const char *const s1 = "hello world";
+ const char *const s2 = "";
+ char dst[64], *d2;
+
+ RESET_DST_WITH (s1);
+ if (strcat (dst, "") != dst || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1);
+ if (strcat (dst, s2) != dst || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strcat (++d2, s2) != dst+1 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strcat (++d2+5, s2) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strcat (++d2+5, s1+11) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+
+#ifndef __OPTIMIZE_SIZE__
+# if !defined __i386__ && !defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ inside_main = 0;
+# endif
+
+ RESET_DST_WITH (s1);
+ if (strcat (dst, " 1111") != dst
+ || memcmp (dst, "hello world 1111\0XXX", 20))
+ abort();
+
+ RESET_DST_WITH (s1);
+ if (strcat (dst+5, " 2222") != dst+5
+ || memcmp (dst, "hello world 2222\0XXX", 20))
+ abort();
+
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strcat (++d2+5, " 3333") != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world 3333\0XXX", 20))
+ abort();
+
+ RESET_DST_WITH (s1);
+ strcat (strcat (strcat (strcat (strcat (strcat (dst, ": this "), ""),
+ "is "), "a "), "test"), ".");
+ if (memcmp (dst, "hello world: this is a test.\0X", 30))
+ abort();
+
+ /* Set inside_main again. */
+ inside_main = 1;
+#endif
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ RESET_DST_WITH (s1);
+ if (__builtin_strcat (dst, "") != dst || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strchr-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strchr-lib.c
new file mode 100644
index 000000000..b3f0bd237
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strchr-lib.c
@@ -0,0 +1,8 @@
+#include "lib/strchr.c"
+#ifdef __vxworks
+/* The RTP C library uses bzero, bfill and bcopy, all of which are defined
+ in the same file as index. */
+#include "lib/bzero.c"
+#include "lib/bfill.c"
+#include "lib/memmove.c"
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strchr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strchr.c
new file mode 100644
index 000000000..08e87c63d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strchr.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2000, 2003 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strchr and index
+ occur and perform correctly.
+
+ Written by Jakub Jelinek, 11/7/2000. */
+
+extern void abort (void);
+extern char *strchr (const char *, int);
+extern char *index (const char *, int);
+
+void
+main_test (void)
+{
+ const char *const foo = "hello world";
+
+ if (strchr (foo, 'x'))
+ abort ();
+ if (strchr (foo, 'o') != foo + 4)
+ abort ();
+ if (strchr (foo + 5, 'o') != foo + 7)
+ abort ();
+ if (strchr (foo, '\0') != foo + 11)
+ abort ();
+ /* Test only one instance of index since the code path is the same
+ as that of strchr. */
+ if (index ("hello", 'z') != 0)
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strchr (foo, 'o') != foo + 4)
+ abort ();
+ if (__builtin_index (foo, 'o') != foo + 4)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcmp-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcmp-lib.c
new file mode 100644
index 000000000..99c421486
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcmp-lib.c
@@ -0,0 +1 @@
+#include "lib/strcmp.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcmp.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcmp.c
new file mode 100644
index 000000000..08a7658ea
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcmp.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2000, 2003, 2004 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strcmp
+ occur and perform correctly.
+
+ Written by Jakub Jelinek, 11/7/2000. */
+
+extern void abort (void);
+extern int strcmp (const char *, const char *);
+
+int x = 7;
+char *bar = "hi world";
+
+void
+main_test (void)
+{
+ const char *const foo = "hello world";
+
+ if (strcmp (foo, "hello") <= 0)
+ abort ();
+ if (strcmp (foo + 2, "llo") <= 0)
+ abort ();
+ if (strcmp (foo, foo) != 0)
+ abort ();
+ if (strcmp (foo, "hello world ") >= 0)
+ abort ();
+ if (strcmp (foo + 10, "dx") >= 0)
+ abort ();
+ if (strcmp (10 + foo, "dx") >= 0)
+ abort ();
+ if (strcmp (bar, "") <= 0)
+ abort ();
+ if (strcmp ("", bar) >= 0)
+ abort ();
+ if (strcmp (bar+8, "") != 0)
+ abort ();
+ if (strcmp ("", bar+8) != 0)
+ abort ();
+ if (strcmp (bar+(--x), "") <= 0 || x != 6)
+ abort ();
+ if (strcmp ("", bar+(++x)) >= 0 || x != 7)
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strcmp (foo, "hello") <= 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c
new file mode 100644
index 000000000..b10dfcb0d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c
@@ -0,0 +1 @@
+#include "lib/strcpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c
new file mode 100644
index 000000000..c3cb6d0e5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+ Ensure builtin strcpy is optimized into memcpy
+ even when there is more than one possible string literal
+ passed to it, but all string literals passed to it
+ have equal length.
+
+ Written by Jakub Jelinek, 9/15/2004. */
+
+extern void abort (void);
+extern char *strcpy (char *, const char *);
+typedef __SIZE_TYPE__ size_t;
+extern void *memcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+char buf[32], *p;
+int i;
+
+char *
+__attribute__((noinline))
+test (void)
+{
+ int j;
+ const char *q = "abcdefg";
+ for (j = 0; j < 3; ++j)
+ {
+ if (j == i)
+ q = "bcdefgh";
+ else if (j == i + 1)
+ q = "cdefghi";
+ else if (j == i + 2)
+ q = "defghij";
+ }
+ p = strcpy (buf, q);
+ return strcpy (buf + 16, q);
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE_SIZE__
+ /* For -Os, strcpy above is not replaced with
+ memcpy (buf, q, 8);, as that is larger. */
+ if (test () != buf + 16 || p != buf)
+ abort ();
+#endif
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.c
new file mode 100644
index 000000000..b3c1a3899
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __strcpy_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+LOCAL const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ chk_calls = 0;
+#ifndef __OPTIMIZE_SIZE__
+ strcpy_disallowed = 1;
+#else
+ strcpy_disallowed = 0;
+#endif
+
+ if (strcpy (p, "abcde") != p || memcmp (p, "abcde", 6))
+ abort ();
+ if (strcpy (p + 16, "vwxyz" + 1) != p + 16 || memcmp (p + 16, "wxyz", 5))
+ abort ();
+ if (strcpy (p + 1, "") != p + 1 || memcmp (p, "a\0cde", 6))
+ abort ();
+ if (strcpy (p + 3, "fghij") != p + 3 || memcmp (p, "a\0cfghij", 9))
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strcpy (p, "abcde") != p || memcmp (p, "abcde", 6))
+ abort ();
+
+ strcpy_disallowed = 0;
+ if (chk_calls)
+ abort ();
+}
+
+#ifndef MAX_OFFSET
+#define MAX_OFFSET (sizeof (long long))
+#endif
+
+#ifndef MAX_COPY
+#define MAX_COPY (10 * sizeof (long long))
+#endif
+
+#ifndef MAX_EXTRA
+#define MAX_EXTRA (sizeof (long long))
+#endif
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + 1 + MAX_EXTRA)
+
+/* Use a sequence length that is not divisible by two, to make it more
+ likely to detect when words are mixed up. */
+#define SEQUENCE_LENGTH 31
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u1, u2;
+
+void
+__attribute__((noinline))
+test2 (void)
+{
+ int off1, off2, len, i;
+ char *p, *q, c;
+
+ for (off1 = 0; off1 < MAX_OFFSET; off1++)
+ for (off2 = 0; off2 < MAX_OFFSET; off2++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+ u2.buf[off2 + len] = '\0';
+
+ p = strcpy (u1.buf + off1, u2.buf + off2);
+ if (p != u1.buf + off1)
+ abort ();
+
+ q = u1.buf;
+ for (i = 0; i < off1; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
+ {
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ if (*q != c)
+ abort ();
+ }
+
+ if (*q++ != '\0')
+ abort ();
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ const char *l;
+
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ chk_calls = 0;
+ strcpy (a.buf1 + 2, s3 + 3);
+ strcpy (r, s3 + 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ strcpy (r, s2 + 2);
+ strcpy (r + 2, s3 + 3);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ strcpy (r, s2 + 4);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known source length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ strcpy (a.buf1 + 2, "");
+ strcpy (r, "a");
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ strcpy (r, s1 + 1);
+ r = buf3;
+ l = "abc";
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = "e";
+ else if (i == l1)
+ r = &a.buf2[7], l = "gh";
+ else if (i == l1 + 1)
+ r = &buf3[5], l = "jkl";
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = "";
+ }
+ strcpy (r, "");
+ /* Here, strlen (l) + 1 is known to be at most 4 and
+ __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
+ runtime checking. */
+ strcpy (&buf3[16], l);
+ /* Unknown destination and source, no checking. */
+ strcpy (s4, s3);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test4 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strcpy (&a.buf2[9], s2 + 3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strcpy (&a.buf2[7], s3 + strlen (s3) - 3);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strcpy (&buf3[19], "a");
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+ test2 ();
+ s4 = p;
+ test3 ();
+ test4 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-lib.c
new file mode 100644
index 000000000..b10dfcb0d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-lib.c
@@ -0,0 +1 @@
+#include "lib/strcpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy.c
new file mode 100644
index 000000000..0ca62b3a2
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2000 Free Software Foundation.
+
+ Ensure builtin memcpy and strcpy perform correctly.
+
+ Written by Jakub Jelinek, 11/24/2000. */
+
+extern void abort (void);
+extern char *strcpy (char *, const char *);
+typedef __SIZE_TYPE__ size_t;
+extern void *memcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+char p[32] = "";
+
+void
+main_test (void)
+{
+ if (strcpy (p, "abcde") != p || memcmp (p, "abcde", 6))
+ abort ();
+ if (strcpy (p + 16, "vwxyz" + 1) != p + 16 || memcmp (p + 16, "wxyz", 5))
+ abort ();
+ if (strcpy (p + 1, "") != p + 1 || memcmp (p, "a\0cde", 6))
+ abort ();
+ if (strcpy (p + 3, "fghij") != p + 3 || memcmp (p, "a\0cfghij", 9))
+ abort ();
+ if (memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
+ abort ();
+ if (memcpy (p + 16, "VWX" + 1, 2) != p + 16 || memcmp (p + 16, "WXyz", 5))
+ abort ();
+ if (memcpy (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6))
+ abort ();
+ if (memcpy (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHIj", 9))
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strcpy (p, "abcde") != p || memcmp (p, "abcde", 6))
+ abort ();
+ if (__builtin_memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcspn-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcspn-lib.c
new file mode 100644
index 000000000..8b1cfea01
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcspn-lib.c
@@ -0,0 +1 @@
+#include "lib/strcspn.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcspn.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strcspn.c
new file mode 100644
index 000000000..be392546a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcspn.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2000, 2004 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 *);
+
+void
+main_test (void)
+{
+ 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();
+ if (strcspn ("", s1) != 0)
+ abort();
+ strcpy (dst, s1);
+ if (strcspn ("", dst) != 0)
+ abort();
+ strcpy (dst, s1); d2 = dst;
+ if (strcspn ("", ++d2) != 0 || d2 != dst+1)
+ abort();
+ strcpy (dst, s1); d2 = dst;
+ if (strcspn ("", ++d2+5) != 0 || d2 != dst+1)
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strcspn (s1, "z") != 11)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2-lib.c
new file mode 100644
index 000000000..9753c2498
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2-lib.c
@@ -0,0 +1 @@
+#include "lib/strlen.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2.c
new file mode 100644
index 000000000..e15ad6636
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-2.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Test strlen optimizations on conditional expressions.
+
+ Written by Jakub Jelinek, June 23, 2003. */
+
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen (const char *);
+extern char *strcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+extern void abort (void);
+extern int inside_main;
+
+size_t g, h, i, j, k, l;
+
+size_t
+foo (void)
+{
+ if (l)
+ abort ();
+ return ++l;
+}
+
+void
+main_test (void)
+{
+ if (strlen (i ? "foo" + 1 : j ? "bar" + 1 : "baz" + 1) != 2)
+ abort ();
+ if (strlen (g++ ? "foo" : "bar") != 3 || g != 1)
+ abort ();
+ if (strlen (h++ ? "xfoo" + 1 : "bar") != 3 || h != 1)
+ abort ();
+ if (strlen ((i++, "baz")) != 3 || i != 1)
+ abort ();
+ /* The following calls might not optimize strlen call away. */
+ inside_main = 0;
+ if (strlen (j ? "foo" + k++ : "bar" + k++) != 3 || k != 1)
+ abort ();
+ if (strlen (foo () ? "foo" : "bar") != 3 || l != 1)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3-lib.c
new file mode 100644
index 000000000..9753c2498
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3-lib.c
@@ -0,0 +1 @@
+#include "lib/strlen.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3.c
new file mode 100644
index 000000000..666ca21b9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+ Test strlen on const variables initialized to string literals.
+
+ Written by Jakub Jelinek, 9/14/2004. */
+
+extern void abort (void);
+extern __SIZE_TYPE__ strlen (const char *);
+extern char *strcpy (char *, const char *);
+static const char bar[] = "Hello, World!";
+static const char baz[] = "hello, world?";
+static const char larger[20] = "short string";
+extern int inside_main;
+
+int l1 = 1;
+int x = 6;
+
+void
+main_test(void)
+{
+#ifdef __OPTIMIZE__
+ const char *foo;
+ int i;
+#endif
+
+ if (strlen (bar) != 13)
+ abort ();
+
+ if (strlen (bar + 3) != 10)
+ abort ();
+
+ if (strlen (&bar[6]) != 7)
+ abort ();
+
+ if (strlen (bar + (x++ & 7)) != 7)
+ abort ();
+ if (x != 7)
+ abort ();
+
+#ifdef __OPTIMIZE__
+ foo = bar;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ foo = "HELLO, WORLD!";
+ else if (i == l1)
+ foo = bar;
+ else if (i == l1 + 1)
+ foo = "hello, world!";
+ else
+ foo = baz;
+ }
+ if (strlen (foo) != 13)
+ abort ();
+#endif
+
+ if (strlen (larger) != 12)
+ abort ();
+ if (strlen (&larger[10]) != 2)
+ abort ();
+
+ inside_main = 0;
+ /* This will result in strlen call, because larger
+ array is bigger than its initializer. */
+ if (strlen (larger + (x++ & 7)) != 5)
+ abort ();
+ if (x != 8)
+ abort ();
+ inside_main = 1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-lib.c
new file mode 100644
index 000000000..9753c2498
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen-lib.c
@@ -0,0 +1 @@
+#include "lib/strlen.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strlen.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen.c
new file mode 100644
index 000000000..0a9681770
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strlen.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strlen
+ occur and perform correctly.
+
+ Written by Jakub Jelinek, 11/7/2000.
+
+ Additional tests written by Roger Sayle, 11/02/2001:
+ Ensure all builtin strlen comparisons against zero are optimized
+ and perform correctly. The multiple calls to strcpy are to prevent
+ the potentially "pure" strlen calls from being removed by CSE.
+
+ Modified by Ben Elliston, 2006-10-25:
+ The multiple calls to strcpy that Roger mentions above are
+ problematic on systems where strcpy is implemented using strlen
+ (which this test overrides to call abort). So, rather than use
+ strcpy, we perform the identical operations using array indexing
+ and char assignments. */
+
+extern void abort (void);
+extern __SIZE_TYPE__ strlen (const char *);
+extern char *strcpy (char *, const char *);
+
+int x = 6;
+
+void
+main_test(void)
+{
+ const char *const foo = "hello world";
+ char str[8];
+ char *ptr;
+
+ if (strlen (foo) != 11)
+ abort ();
+ if (strlen (foo + 4) != 7)
+ abort ();
+ if (strlen (foo + (x++ & 7)) != 5)
+ abort ();
+ if (x != 7)
+ abort ();
+
+ ptr = str;
+ ptr[0] = 'n'; ptr[1] = 't'; ptr[2] = 's'; ptr[3] = '\0';
+ if (strlen (ptr) == 0)
+ abort ();
+
+ ptr[0] = 'n'; ptr[1] = 't'; ptr[2] = 's'; ptr[3] = '\0';
+ if (strlen (ptr) < 1)
+ abort ();
+
+ ptr[0] = 'n'; ptr[1] = 't'; ptr[2] = 's'; ptr[3] = '\0';
+ if (strlen (ptr) <= 0)
+ abort ();
+
+ ptr[0] = 'n'; ptr[1] = 't'; ptr[2] = 's'; ptr[3] = '\0';
+ if (strlen (ptr+3) != 0)
+ abort ();
+
+ ptr[0] = 'n'; ptr[1] = 't'; ptr[2] = 's'; ptr[3] = '\0';
+ if (strlen (ptr+3) > 0)
+ abort ();
+
+ ptr[0] = 'n'; ptr[1] = 't'; ptr[2] = 's'; ptr[3] = '\0';
+ if (strlen (str+3) >= 1)
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strlen (foo) != 11)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.c
new file mode 100644
index 000000000..8904df14a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.c
@@ -0,0 +1,229 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __strncat_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen (const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcat (char *, const char *);
+extern char *strncat (char *, const char *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int strcmp (const char *, const char *);
+extern void *memset (void *, int, size_t);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+char *s5;
+int x = 123;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ const char *const s1 = "hello world";
+ const char *const s2 = "";
+ const char *s3;
+ char dst[64], *d2;
+
+ /* Following strncat calls should be all optimized out. */
+ chk_calls = 0;
+ strncat_disallowed = 1;
+ strcat_disallowed = 1;
+ 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; s3 = s1;
+ if (strncat (++d2+5, ++s3, 0) != dst+6 || d2 != dst+1 || strcmp (dst, s1)
+ || s3 != s1 + 1)
+ abort ();
+ strcpy (dst, s1); d2 = dst;
+ if (strncat (++d2+5, "", ++x) != dst+6 || d2 != dst+1 || x != 124
+ || strcmp (dst, s1))
+ abort ();
+ if (chk_calls)
+ abort ();
+ strcat_disallowed = 0;
+
+ /* These __strncat_chk calls should be optimized into __strcat_chk,
+ as strlen (src) <= len. */
+ 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 ();
+ if (chk_calls != 3)
+ abort ();
+
+ chk_calls = 0;
+ /* The following calls have side-effects in dest, so are not checked. */
+ strcpy (dst, s1); d2 = dst;
+ if (__builtin___strncat_chk (++d2, s1, 100, os (++d2)) != dst+1
+ || d2 != dst+1 || strcmp (dst, "hello worldhello world"))
+ abort ();
+ strcpy (dst, s1); d2 = dst;
+ if (__builtin___strncat_chk (++d2+5, s1, 100, os (++d2+5)) != dst+6
+ || d2 != dst+1 || strcmp (dst, "hello worldhello world"))
+ abort ();
+ strcpy (dst, s1); d2 = dst;
+ if (__builtin___strncat_chk (++d2+5, s1+5, 100, os (++d2+5)) != dst+6
+ || d2 != dst+1 || strcmp (dst, "hello world world"))
+ abort ();
+ if (chk_calls)
+ abort ();
+
+ chk_calls = 0;
+ strcat_disallowed = 1;
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ strcpy (dst, s1);
+ if (__builtin_strncat (dst, "", 100) != dst || strcmp (dst, s1))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+ strncat_disallowed = 0;
+ strcat_disallowed = 0;
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+
+ /* The following calls should do runtime checking. */
+ memset (&a, '\0', sizeof (a));
+ s5 = (char *) &a;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ chk_calls = 0;
+ strncat (a.buf1 + 2, s3 + 3, l1 - 1);
+ strncat (r, s3 + 2, l1);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memset (r, '\0', 3);
+ __asm __volatile ("" : : "r" (r) : "memory");
+ strncat (r, s2 + 2, l1 + 1);
+ strncat (r + 2, s3 + 3, l1 - 1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ strncat (r, s2 + 4, l1);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known source length,
+ but we don't know the length of dest string, so runtime checking
+ is needed too. */
+ memset (&a, '\0', sizeof (a));
+ chk_calls = 0;
+ s5 = (char *) &a;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ strncat (a.buf1 + 2, "a", 5);
+ strncat (r, "def", 0);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ memset (r, '\0', 3);
+ __asm __volatile ("" : : "r" (r) : "memory");
+ strncat (r, s1 + 1, 2);
+ if (chk_calls != 2)
+ abort ();
+ chk_calls = 0;
+ strcat_disallowed = 1;
+ /* Unknown destination and source, no checking. */
+ strncat (s4, s3, l1 + 1);
+ strcat_disallowed = 0;
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ memset (&a, '\0', sizeof (a));
+ memset (buf3, '\0', sizeof (buf3));
+ s5 = (char *) &a;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ s5 = buf3;
+ __asm __volatile ("" : : "r" (s5) : "memory");
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncat (&a.buf2[9], s2 + 3, 4);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncat (&a.buf2[7], s3 + strlen (s3) - 3, 3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncat (&buf3[19], "abcde", 1);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = p;
+ test1 ();
+ memset (p, '\0', sizeof (p));
+ test2 ();
+ test3 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-lib.c
new file mode 100644
index 000000000..1405a48f4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-lib.c
@@ -0,0 +1 @@
+#include "lib/strncat.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncat.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat.c
new file mode 100644
index 000000000..1a093baf7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2000, 2003 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 void *memset (void *, int, size_t);
+extern int memcmp (const void *, const void *, size_t);
+int x = 123;
+
+/* Reset the destination buffer to a known state. */
+#define RESET_DST_WITH(FILLER) \
+ do { memset (dst, 'X', sizeof (dst)); strcpy (dst, (FILLER)); } while (0)
+
+void
+main_test (void)
+{
+ const char *const s1 = "hello world";
+ const char *const s2 = "";
+ char dst[64], *d2;
+
+ RESET_DST_WITH (s1);
+ if (strncat (dst, "", 100) != dst || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1);
+ if (strncat (dst, s2, 100) != dst || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2, s2, 100) != dst+1 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2+5, s2, 100) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2+5, s1+11, 100) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2+5, s1, 0) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2+5, "", ++x) != dst+6 || d2 != dst+1 || x != 124
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+
+ RESET_DST_WITH (s1);
+ if (strncat (dst, "foo", 3) != dst || memcmp (dst, "hello worldfoo\0XXX", 18))
+ abort();
+ RESET_DST_WITH (s1);
+ if (strncat (dst, "foo", 100) != dst || memcmp (dst, "hello worldfoo\0XXX", 18))
+ abort();
+ RESET_DST_WITH (s1);
+ if (strncat (dst, s1, 100) != dst || memcmp (dst, "hello worldhello world\0XXX", 26))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2, s1, 100) != dst+1 || d2 != dst+1
+ || memcmp (dst, "hello worldhello world\0XXX", 26))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2+5, s1, 100) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello worldhello world\0XXX", 26))
+ abort();
+ RESET_DST_WITH (s1); d2 = dst;
+ if (strncat (++d2+5, s1+5, 100) != dst+6 || d2 != dst+1
+ || memcmp (dst, "hello world world\0XXX", 21))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ RESET_DST_WITH (s1);
+ if (__builtin_strncat (dst, "", 100) != dst
+ || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2-lib.c
new file mode 100644
index 000000000..266c4a49b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2-lib.c
@@ -0,0 +1 @@
+#include "lib/strncmp.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c
new file mode 100644
index 000000000..fe3462724
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 2000, 2001, 2003, 2005 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);
+
+void
+main_test (void)
+{
+#if !defined(__OPTIMIZE__) || ((defined(__i386__) || defined (__x86_64__)) && !defined(__OPTIMIZE_SIZE__))
+ /* These tests work on platforms which support cmpstrsi. We test it
+ at -O0 on all platforms to ensure the strncmp logic is correct. */
+ const char *const s1 = "hello world";
+ const char *s2;
+ int n = 6, x;
+
+ s2 = s1;
+ if (strncmp (++s2, "ello", 3) != 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("ello", ++s2, 3) != 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "ello", 4) != 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("ello", ++s2, 4) != 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "ello", 5) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("ello", ++s2, 5) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "ello", 6) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("ello", ++s2, 6) >= 0 || s2 != s1+1)
+ abort();
+
+ s2 = s1;
+ if (strncmp (++s2, "zllo", 3) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("zllo", ++s2, 3) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "zllo", 4) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("zllo", ++s2, 4) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "zllo", 5) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("zllo", ++s2, 5) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "zllo", 6) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("zllo", ++s2, 6) <= 0 || s2 != s1+1)
+ abort();
+
+ s2 = s1;
+ if (strncmp (++s2, "allo", 3) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("allo", ++s2, 3) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "allo", 4) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("allo", ++s2, 4) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "allo", 5) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("allo", ++s2, 5) >= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp (++s2, "allo", 6) <= 0 || s2 != s1+1)
+ abort();
+ s2 = s1;
+ if (strncmp ("allo", ++s2, 6) >= 0 || s2 != s1+1)
+ abort();
+
+ s2 = s1; n = 2; x = 1;
+ if (strncmp (++s2, s1+(x&3), ++n) != 0 || s2 != s1+1 || n != 3)
+ abort();
+ s2 = s1; n = 2; x = 1;
+ if (strncmp (s1+(x&3), ++s2, ++n) != 0 || s2 != s1+1 || n != 3)
+ abort();
+ s2 = s1; n = 3; x = 1;
+ if (strncmp (++s2, s1+(x&3), ++n) != 0 || s2 != s1+1 || n != 4)
+ abort();
+ s2 = s1; n = 3; x = 1;
+ if (strncmp (s1+(x&3), ++s2, ++n) != 0 || s2 != s1+1 || n != 4)
+ abort();
+ s2 = s1; n = 4; x = 1;
+ if (strncmp (++s2, s1+(x&3), ++n) != 0 || s2 != s1+1 || n != 5)
+ abort();
+ s2 = s1; n = 4; x = 1;
+ if (strncmp (s1+(x&3), ++s2, ++n) != 0 || s2 != s1+1 || n != 5)
+ abort();
+ s2 = s1; n = 5; x = 1;
+ if (strncmp (++s2, s1+(x&3), ++n) != 0 || s2 != s1+1 || n != 6)
+ abort();
+ s2 = s1; n = 5; x = 1;
+ if (strncmp (s1+(x&3), ++s2, ++n) != 0 || s2 != s1+1 || n != 6)
+ abort();
+
+ s2 = s1; n = 2;
+ if (strncmp (++s2, "zllo", ++n) >= 0 || s2 != s1+1 || n != 3)
+ abort();
+ s2 = s1; n = 2; x = 1;
+ if (strncmp ("zllo", ++s2, ++n) <= 0 || s2 != s1+1 || n != 3)
+ abort();
+ s2 = s1; n = 3; x = 1;
+ if (strncmp (++s2, "zllo", ++n) >= 0 || s2 != s1+1 || n != 4)
+ abort();
+ s2 = s1; n = 3; x = 1;
+ if (strncmp ("zllo", ++s2, ++n) <= 0 || s2 != s1+1 || n != 4)
+ abort();
+ s2 = s1; n = 4; x = 1;
+ if (strncmp (++s2, "zllo", ++n) >= 0 || s2 != s1+1 || n != 5)
+ abort();
+ s2 = s1; n = 4; x = 1;
+ if (strncmp ("zllo", ++s2, ++n) <= 0 || s2 != s1+1 || n != 5)
+ abort();
+ s2 = s1; n = 5; x = 1;
+ if (strncmp (++s2, "zllo", ++n) >= 0 || s2 != s1+1 || n != 6)
+ abort();
+ s2 = s1; n = 5; x = 1;
+ if (strncmp ("zllo", ++s2, ++n) <= 0 || s2 != s1+1 || n != 6)
+ abort();
+
+ s2 = s1; n = 2;
+ if (strncmp (++s2, "allo", ++n) <= 0 || s2 != s1+1 || n != 3)
+ abort();
+ s2 = s1; n = 2; x = 1;
+ if (strncmp ("allo", ++s2, ++n) >= 0 || s2 != s1+1 || n != 3)
+ abort();
+ s2 = s1; n = 3; x = 1;
+ if (strncmp (++s2, "allo", ++n) <= 0 || s2 != s1+1 || n != 4)
+ abort();
+ s2 = s1; n = 3; x = 1;
+ if (strncmp ("allo", ++s2, ++n) >= 0 || s2 != s1+1 || n != 4)
+ abort();
+ s2 = s1; n = 4; x = 1;
+ if (strncmp (++s2, "allo", ++n) <= 0 || s2 != s1+1 || n != 5)
+ abort();
+ s2 = s1; n = 4; x = 1;
+ if (strncmp ("allo", ++s2, ++n) >= 0 || s2 != s1+1 || n != 5)
+ abort();
+ s2 = s1; n = 5; x = 1;
+ if (strncmp (++s2, "allo", ++n) <= 0 || s2 != s1+1 || n != 6)
+ abort();
+ s2 = s1; n = 5; x = 1;
+ if (strncmp ("allo", ++s2, ++n) >= 0 || s2 != s1+1 || n != 6)
+ abort();
+
+#endif
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-lib.c
new file mode 100644
index 000000000..266c4a49b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-lib.c
@@ -0,0 +1 @@
+#include "lib/strncmp.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp.c
new file mode 100644
index 000000000..2c22b7d01
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 2000, 2001, 2003 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);
+
+void
+main_test (void)
+{
+ 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();
+ s2 = s1;
+ if (strncmp (++s2, "", 1) <= 0 || s2 != s1+1)
+ abort();
+ if (strncmp ("", ++s2, 1) >= 0 || s2 != s1+2)
+ abort();
+ if (strncmp (++s2, "", 100) <= 0 || s2 != s1+3)
+ abort();
+ if (strncmp ("", ++s2, 100) >= 0 || s2 != s1+4)
+ abort();
+ if (strncmp (++s2+6, "", 100) != 0 || s2 != s1+5)
+ abort();
+ if (strncmp ("", ++s2+5, 100) != 0 || s2 != s1+6)
+ abort();
+ if (strncmp ("ozz", ++s2, 1) != 0 || s2 != s1+7)
+ abort();
+ if (strncmp (++s2, "rzz", 1) != 0 || s2 != s1+8)
+ abort();
+ s2 = s1; s3 = s1+4;
+ if (strncmp (++s2, ++s3+2, 1) >= 0 || s2 != s1+1 || s3 != s1+5)
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strncmp ("hello", "a", 100) <= 0)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.c
new file mode 100644
index 000000000..9e10dba1b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.c
@@ -0,0 +1,227 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __strncpy_chk performs correctly. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strncpy (char *, const char *, size_t);
+extern int memcmp (const void *, const void *, 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);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+char * volatile s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
+char * volatile s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
+char *s4;
+volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
+int i;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ const char *const src = "hello world";
+ const char *src2;
+ char dst[64], *dst2;
+
+ strncpy_disallowed = 1;
+ chk_calls = 0;
+
+ 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();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ memset (dst, 0, sizeof (dst));
+ if (__builtin_strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
+ abort();
+
+ memset (dst, 0, sizeof (dst));
+ if (strncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst
+ || strcmp (dst, "bar")
+ || i != 1)
+ abort ();
+
+ if (chk_calls)
+ abort ();
+ strncpy_disallowed = 0;
+}
+
+void
+__attribute__((noinline))
+test2 (void)
+{
+ chk_calls = 0;
+ /* No runtime checking should be done here, both destination
+ and length are unknown. */
+ strncpy (s4, "abcd", l1 + 1);
+ if (chk_calls)
+ abort ();
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int i;
+ const char *l;
+ size_t l2;
+
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ chk_calls = 0;
+ strncpy (a.buf1 + 2, s3 + 3, l1);
+ strncpy (r, s3 + 2, l1 + 2);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ strncpy (r, s2 + 2, l1 + 2);
+ strncpy (r + 2, s3 + 3, l1);
+ r = buf3;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1];
+ else if (i == l1)
+ r = &a.buf2[7];
+ else if (i == l1 + 1)
+ r = &buf3[5];
+ else if (i == l1 + 2)
+ r = &a.buf1[9];
+ }
+ strncpy (r, s2 + 4, l1);
+ if (chk_calls != 5)
+ abort ();
+
+ /* Following have known destination and known length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ strncpy (a.buf1 + 2, "", 3);
+ strncpy (a.buf1 + 2, "", 0);
+ strncpy (r, "a", 1);
+ strncpy (r, "a", 3);
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ strncpy (r, s1 + 1, 3);
+ strncpy (r, s1 + 1, 2);
+ r = buf3;
+ l = "abc";
+ l2 = 4;
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == l1 - 1)
+ r = &a.buf1[1], l = "e", l2 = 2;
+ else if (i == l1)
+ r = &a.buf2[7], l = "gh", l2 = 3;
+ else if (i == l1 + 1)
+ r = &buf3[5], l = "jkl", l2 = 4;
+ else if (i == l1 + 2)
+ r = &a.buf1[9], l = "", l2 = 1;
+ }
+ strncpy (r, "", 1);
+ /* Here, strlen (l) + 1 is known to be at most 4 and
+ __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
+ runtime checking. */
+ strncpy (&buf3[16], l, l2);
+ strncpy (&buf3[15], "abc", l2);
+ strncpy (&buf3[10], "fghij", l2);
+ if (chk_calls)
+ abort ();
+ chk_calls = 0;
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test4 (void)
+{
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncpy (&a.buf2[9], s2 + 4, l1 + 1);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncpy (&a.buf2[7], s3, l1 + 4);
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncpy (&buf3[19], "abc", 2);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ strncpy (&buf3[18], "", 3);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+ s4 = p;
+ test2 ();
+ test3 ();
+ test4 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-lib.c
new file mode 100644
index 000000000..784f72d03
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-lib.c
@@ -0,0 +1 @@
+#include "lib/strncpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy.c
new file mode 100644
index 000000000..9918cdf6a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2000, 2005 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 memcmp (const void *, const void *, size_t);
+extern void *memset (void *, int, size_t);
+
+/* Reset the destination buffer to a known state. */
+#define RESET_DST memset(dst, 'X', sizeof(dst))
+
+int i;
+
+void
+main_test (void)
+{
+ const char *const src = "hello world";
+ const char *src2;
+ char dst[64], *dst2;
+
+ RESET_DST;
+ if (strncpy (dst, src, 4) != dst || memcmp (dst, "hellXXX", 7))
+ abort();
+
+ RESET_DST;
+ if (strncpy (dst+16, src, 4) != dst+16 || memcmp (dst+16, "hellXXX", 7))
+ abort();
+
+ RESET_DST;
+ if (strncpy (dst+32, src+5, 4) != dst+32 || memcmp (dst+32, " worXXX", 7))
+ abort();
+
+ RESET_DST;
+ dst2 = dst;
+ if (strncpy (++dst2, src+5, 4) != dst+1 || memcmp (dst2, " worXXX", 7)
+ || dst2 != dst+1)
+ abort();
+
+ RESET_DST;
+ if (strncpy (dst, src, 0) != dst || memcmp (dst, "XXX", 3))
+ abort();
+
+ RESET_DST;
+ dst2 = dst; src2 = src;
+ if (strncpy (++dst2, ++src2, 0) != dst+1 || memcmp (dst2, "XXX", 3)
+ || dst2 != dst+1 || src2 != src+1)
+ abort();
+
+ RESET_DST;
+ dst2 = dst; src2 = src;
+ if (strncpy (++dst2+5, ++src2+5, 0) != dst+6 || memcmp (dst2+5, "XXX", 3)
+ || dst2 != dst+1 || src2 != src+1)
+ abort();
+
+ RESET_DST;
+ if (strncpy (dst, src, 12) != dst || memcmp (dst, "hello world\0XXX", 15))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ RESET_DST;
+ if (__builtin_strncpy (dst, src, 4) != dst || memcmp (dst, "hellXXX", 7))
+ abort();
+
+ RESET_DST;
+ if (strncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst
+ || memcmp (dst, "bar\0XXX", 7)
+ || i != 1)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk-lib.c
new file mode 100644
index 000000000..66bf8be7c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk-lib.c
@@ -0,0 +1 @@
+#include "lib/strpbrk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk.c
new file mode 100644
index 000000000..cc963a9af
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strpbrk.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 2000 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strpbrk occur and
+ perform correctly.
+
+ Written by Kaveh R. Ghazi, 11/6/2000. */
+
+extern void abort(void);
+extern char *strpbrk (const char *, const char *);
+extern int strcmp (const char *, const char *);
+
+void fn (const char *foo, const char *const *bar)
+{
+ if (strcmp(strpbrk ("hello world", "lrooo"), "llo world") != 0)
+ abort();
+ if (strpbrk (foo, "") != 0)
+ abort();
+ if (strpbrk (foo + 4, "") != 0)
+ abort();
+ if (strpbrk (*bar--, "") != 0)
+ abort();
+ if (strpbrk (*bar, "h") != foo)
+ abort();
+ if (strpbrk (foo, "h") != foo)
+ abort();
+ if (strpbrk (foo, "w") != foo + 6)
+ abort();
+ if (strpbrk (foo + 6, "o") != foo + 7)
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strpbrk (foo + 6, "o") != foo + 7)
+ abort();
+}
+
+void
+main_test (void)
+{
+ const char *const foo[] = { "hello world", "bye bye world" };
+ fn (foo[0], foo + 1);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2-lib.c
new file mode 100644
index 000000000..b31cdf4f5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2-lib.c
@@ -0,0 +1 @@
+#include "lib/stpcpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2.c
new file mode 100644
index 000000000..eb275c422
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-2.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Ensure that builtin stpcpy performs correctly.
+
+ Written by Jakub Jelinek, 21/05/2003. */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern int memcmp (const void *, const void *, size_t);
+extern char *stpcpy (char *, const char *);
+extern int inside_main;
+
+long buf1[64];
+char *buf2 = (char *) (buf1 + 32);
+long buf5[20];
+char buf7[20];
+
+void
+__attribute__((noinline))
+test (long *buf3, char *buf4, char *buf6, int n)
+{
+ int i = 4;
+
+ if (stpcpy ((char *) buf3, "abcdefghijklmnop") != (char *) buf1 + 16
+ || memcmp (buf1, "abcdefghijklmnop", 17))
+ abort ();
+
+ if (__builtin_stpcpy ((char *) buf3, "ABCDEFG") != (char *) buf1 + 7
+ || memcmp (buf1, "ABCDEFG\0ijklmnop", 17))
+ abort ();
+
+ if (stpcpy ((char *) buf3 + i++, "x") != (char *) buf1 + 5
+ || memcmp (buf1, "ABCDx\0G\0ijklmnop", 17))
+ abort ();
+}
+
+void
+main_test (void)
+{
+ /* All these tests are allowed to call mempcpy/stpcpy. */
+ inside_main = 0;
+ __builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
+ __builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
+ test (buf1, buf2, "rstuvwxyz", 0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-lib.c
new file mode 100644
index 000000000..b31cdf4f5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy-lib.c
@@ -0,0 +1 @@
+#include "lib/stpcpy.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy.c
new file mode 100644
index 000000000..737bfaa80
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strpcpy.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation.
+
+ Ensure builtin stpcpy performs correctly.
+
+ Written by Kaveh Ghazi, 4/11/2003. */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void abort (void);
+extern char *strcpy (char *, const char *);
+extern char *stpcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+
+extern int inside_main;
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+size_t l1 = 1;
+
+void
+main_test (void)
+{
+ int i = 8;
+
+#if !defined __i386__ && !defined __x86_64__
+ /* The functions below might not be optimized into direct stores on all
+ arches. It depends on how many instructions would be generated and
+ what limits the architecture chooses in STORE_BY_PIECES_P. */
+ inside_main = 0;
+#endif
+ if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+ abort ();
+ if (stpcpy (p + 16, "vwxyz" + 1) != p + 16 + 4 || memcmp (p + 16, "wxyz", 5))
+ abort ();
+ if (stpcpy (p + 1, "") != p + 1 + 0 || memcmp (p, "a\0cde", 6))
+ abort ();
+ if (stpcpy (p + 3, "fghij") != p + 3 + 5 || memcmp (p, "a\0cfghij", 9))
+ abort ();
+
+ if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2)
+ || i != 9 || memcmp (p + 19, "z\0""23\0", 5))
+ abort ();
+
+ if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+ abort ();
+
+ /* If the result of stpcpy is ignored, gcc should use strcpy.
+ This should be optimized always, so set inside_main again. */
+ inside_main = 1;
+ stpcpy (p + 3, s3);
+ if (memcmp (p, "abcFGH", 6))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strrchr-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strrchr-lib.c
new file mode 100644
index 000000000..9194c555f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strrchr-lib.c
@@ -0,0 +1,8 @@
+#include "lib/strrchr.c"
+#ifdef __vxworks
+/* The RTP C library uses bzero, bfill and bcopy, all of which are defined
+ in the same file as rindex. */
+#include "lib/bzero.c"
+#include "lib/bfill.c"
+#include "lib/memmove.c"
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strrchr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strrchr.c
new file mode 100644
index 000000000..3cc8faa2e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strrchr.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2000, 2003, 2004 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strrchr and rindex
+ occur and perform correctly.
+
+ Written by Jakub Jelinek, 11/7/2000. */
+
+extern void abort (void);
+extern char *strrchr (const char *, int);
+extern char *rindex (const char *, int);
+
+char *bar = "hi world";
+int x = 7;
+
+void
+main_test (void)
+{
+ const char *const foo = "hello world";
+
+ if (strrchr (foo, 'x'))
+ abort ();
+ if (strrchr (foo, 'o') != foo + 7)
+ abort ();
+ if (strrchr (foo, 'e') != foo + 1)
+ abort ();
+ if (strrchr (foo + 3, 'e'))
+ abort ();
+ if (strrchr (foo, '\0') != foo + 11)
+ abort ();
+ if (strrchr (bar, '\0') != bar + 8)
+ abort ();
+ if (strrchr (bar + 4, '\0') != bar + 8)
+ abort ();
+ if (strrchr (bar + (x++ & 3), '\0') != bar + 8)
+ abort ();
+ if (x != 8)
+ abort ();
+ /* Test only one instance of rindex since the code path is the same
+ as that of strrchr. */
+ if (rindex ("hello", 'z') != 0)
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strrchr (foo, 'o') != foo + 7)
+ abort ();
+ if (__builtin_rindex (foo, 'o') != foo + 7)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strspn-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strspn-lib.c
new file mode 100644
index 000000000..9e044d793
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strspn-lib.c
@@ -0,0 +1 @@
+#include "lib/strspn.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strspn.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strspn.c
new file mode 100644
index 000000000..4f2782a58
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strspn.c
@@ -0,0 +1,54 @@
+/* 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 *);
+
+void
+main_test (void)
+{
+ 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();
+ 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();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strspn (s1, "hello") != 5)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm-lib.c
new file mode 100644
index 000000000..a031a56a9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm-lib.c
@@ -0,0 +1,37 @@
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern char *strchr(const char *, int);
+extern int strcmp(const char *, const char *);
+extern int strncmp(const char *, const char *, size_t);
+extern int inside_main;
+extern const char *p;
+
+char *
+my_strstr (const char *s1, const char *s2)
+{
+ const size_t len = strlen (s2);
+
+#ifdef __OPTIMIZE__
+ /* If optimizing, we should be called only in the strstr (foo + 2, p)
+ case. All other cases should be optimized. */
+ if (inside_main)
+ if (s2 != p || strcmp (s1, "hello world" + 2) != 0)
+ abort ();
+#endif
+ if (len == 0)
+ return (char *) s1;
+ for (s1 = strchr (s1, *s2); s1; s1 = strchr (s1 + 1, *s2))
+ if (strncmp (s1, s2, len) == 0)
+ return (char *) s1;
+ return (char *) 0;
+}
+
+char *
+strstr (const char *s1, const char *s2)
+{
+ if (inside_main)
+ abort ();
+
+ return my_strstr (s1, s2);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c
new file mode 100644
index 000000000..3c3e45dfa
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2000, 2003 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strstr occur and
+ perform correctly in presence of redirect. */
+
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern char *strstr (const char *, const char *)
+ __asm (ASMNAME ("my_strstr"));
+
+const char *p = "rld", *q = "hello world";
+
+void
+main_test (void)
+{
+ const char *const foo = "hello world";
+
+ if (strstr (foo, "") != foo)
+ abort ();
+ if (strstr (foo + 4, "") != foo + 4)
+ abort ();
+ if (strstr (foo, "h") != foo)
+ abort ();
+ if (strstr (foo, "w") != foo + 6)
+ abort ();
+ if (strstr (foo + 6, "o") != foo + 7)
+ abort ();
+ if (strstr (foo + 1, "world") != foo + 6)
+ abort ();
+ if (strstr (foo + 2, p) != foo + 8)
+ abort ();
+ if (strstr (q, "") != q)
+ abort ();
+ if (strstr (q + 1, "o") != q + 4)
+ abort ();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strstr (foo + 1, "world") != foo + 6)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-lib.c
new file mode 100644
index 000000000..591058de4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-lib.c
@@ -0,0 +1 @@
+#include "lib/strstr.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strstr.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr.c
new file mode 100644
index 000000000..ae503aa43
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2000 Free Software Foundation.
+
+ Ensure all expected transformations of builtin strstr occur and
+ perform correctly.
+
+ Written by Kaveh R. Ghazi, 11/6/2000. */
+
+extern void abort(void);
+extern char *strstr (const char *, const char *);
+
+void
+main_test (void)
+{
+ const char *const foo = "hello world";
+
+ if (strstr (foo, "") != foo)
+ abort();
+ if (strstr (foo + 4, "") != foo + 4)
+ abort();
+ if (strstr (foo, "h") != foo)
+ abort();
+ if (strstr (foo, "w") != foo + 6)
+ abort();
+ if (strstr (foo + 6, "o") != foo + 7)
+ abort();
+ if (strstr (foo + 1, "world") != foo + 6)
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_strstr (foo + 1, "world") != foo + 6)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.c
new file mode 100644
index 000000000..8a3f37203
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.c
@@ -0,0 +1,321 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __vsnprintf_chk performs correctly. */
+
+#include <stdarg.h>
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+extern void *memset (void *, int, size_t);
+extern int vsnprintf (char *, size_t, const char *, va_list);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+static char buffer[32];
+char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+int
+__attribute__((noinline))
+test1_sub (int i, ...)
+{
+ int ret = 0;
+ va_list ap;
+ va_start (ap, i);
+ switch (i)
+ {
+ case 0:
+ vsnprintf (buffer, 4, "foo", ap);
+ break;
+ case 1:
+ ret = vsnprintf (buffer, 4, "foo bar", ap);
+ break;
+ case 2:
+ vsnprintf (buffer, 32, "%s", ap);
+ break;
+ case 3:
+ ret = vsnprintf (buffer, 21, "%s", ap);
+ break;
+ case 4:
+ ret = vsnprintf (buffer, 4, "%d%d%d", ap);
+ break;
+ case 5:
+ ret = vsnprintf (buffer, 32, "%d%d%d", ap);
+ break;
+ case 6:
+ ret = vsnprintf (buffer, strlen (ptr) + 1, "%s", ap);
+ break;
+ case 7:
+ vsnprintf (buffer, l1 + 31, "%d - %c", ap);
+ break;
+ case 8:
+ vsnprintf (s4, l1 + 6, "%d - %c", ap);
+ break;
+ }
+ va_end (ap);
+ return ret;
+}
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ chk_calls = 0;
+ /* vsnprintf_disallowed = 1; */
+
+ memset (buffer, 'A', 32);
+ test1_sub (0);
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test1_sub (1) != 7)
+ abort ();
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ vsnprintf_disallowed = 0;
+
+ memset (buffer, 'A', 32);
+ test1_sub (2, "bar");
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test1_sub (3, "bar") != 3)
+ abort ();
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test1_sub (4, (int) l1, (int) l1 + 1, (int) l1 + 12) != 4)
+ abort ();
+ if (memcmp (buffer, "121", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test1_sub (5, (int) l1, (int) l1 + 1, (int) l1 + 12) != 4)
+ abort ();
+ if (memcmp (buffer, "1213", 5) || buffer[5] != 'A')
+ abort ();
+
+ if (chk_calls)
+ abort ();
+
+ memset (buffer, 'A', 32);
+ test1_sub (6, ptr);
+ if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ test1_sub (7, (int) l1 + 27, *ptr);
+ if (memcmp (buffer, "28 - b\0AAAAA", 12))
+ abort ();
+
+ if (chk_calls != 2)
+ abort ();
+ chk_calls = 0;
+
+ memset (s4, 'A', 32);
+ test1_sub (8, (int) l1 - 17, ptr[1]);
+ if (memcmp (s4, "-16 - \0AAA", 10))
+ abort ();
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test2_sub (int i, ...)
+{
+ va_list ap;
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int j;
+
+ va_start (ap, i);
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ switch (i)
+ {
+ case 0:
+ vsnprintf (a.buf1 + 2, l1, "%s", ap);
+ break;
+ case 1:
+ vsnprintf (r, l1 + 4, "%s%c", ap);
+ break;
+ case 2:
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vsnprintf (r, strlen (s2) - 2, "%c %s", ap);
+ break;
+ case 3:
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vsnprintf (r + 2, l1, s3 + 3, ap);
+ break;
+ case 4:
+ case 7:
+ r = buf3;
+ for (j = 0; j < 4; ++j)
+ {
+ if (j == l1 - 1)
+ r = &a.buf1[1];
+ else if (j == l1)
+ r = &a.buf2[7];
+ else if (j == l1 + 1)
+ r = &buf3[5];
+ else if (j == l1 + 2)
+ r = &a.buf1[9];
+ }
+ if (i == 4)
+ vsnprintf (r, l1, s2 + 4, ap);
+ else
+ vsnprintf (r, 1, "a", ap);
+ break;
+ case 5:
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vsnprintf (r, l1 + 3, "%s", ap);
+ break;
+ case 6:
+ vsnprintf (a.buf1 + 2, 4, "", ap);
+ break;
+ case 8:
+ vsnprintf (s4, 3, "%s %d", ap);
+ break;
+ }
+ va_end (ap);
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ /* The following calls should do runtime checking
+ - length is not known, but destination is. */
+ chk_calls = 0;
+ test2_sub (0, s3 + 3);
+ test2_sub (1, s3 + 3, s3[3]);
+ test2_sub (2, s2[2], s2 + 4);
+ test2_sub (3);
+ test2_sub (4);
+ test2_sub (5, s1 + 1);
+ if (chk_calls != 6)
+ abort ();
+
+ /* Following have known destination and known source length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ /* vsnprintf_disallowed = 1; */
+ test2_sub (6);
+ test2_sub (7);
+ vsnprintf_disallowed = 0;
+ /* Unknown destination and source, no checking. */
+ test2_sub (8, s3, 0);
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test3_sub (int i, ...)
+{
+ va_list ap;
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ va_start (ap, i);
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ switch (i)
+ {
+ case 0:
+ vsnprintf (&a.buf2[9], l1 + 1, "%c%s", ap);
+ break;
+ case 1:
+ vsnprintf (&a.buf2[7], l1 + 30, "%s%c", ap);
+ break;
+ case 2:
+ vsnprintf (&a.buf2[7], l1 + 3, "%d", ap);
+ break;
+ case 3:
+ vsnprintf (&buf3[17], l1 + 3, "%s", ap);
+ break;
+ case 4:
+ vsnprintf (&buf3[19], 2, "a", ap);
+ break;
+ case 5:
+ vsnprintf (&buf3[16], 5, "a", ap);
+ break;
+ }
+ va_end (ap);
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (0, s2[3], s2 + 4);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (1, s3 + strlen (s3) - 2, *s3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (2, (int) l1 + 9999);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (3, "abc");
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (4);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (5);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = p;
+ test1 ();
+ test2 ();
+ test3 ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk-lib.c
new file mode 100644
index 000000000..9daf13e82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk-lib.c
@@ -0,0 +1 @@
+#include "lib/chk.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.c b/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.c
new file mode 100644
index 000000000..5649b9e90
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.c
@@ -0,0 +1,290 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation.
+
+ Ensure builtin __vsprintf_chk performs correctly. */
+
+#include <stdarg.h>
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern char *strcpy (char *, const char *);
+extern int memcmp (const void *, const void *, size_t);
+extern void *memset (void *, int, size_t);
+extern int vsprintf (char *, const char *, va_list);
+
+#include "chk.h"
+
+const char s1[] = "123";
+char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+char *s4;
+size_t l1 = 1;
+static char buffer[32];
+char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
+
+int
+__attribute__((noinline))
+test1_sub (int i, ...)
+{
+ int ret = 0;
+ va_list ap;
+ va_start (ap, i);
+ switch (i)
+ {
+ case 0:
+ vsprintf (buffer, "foo", ap);
+ break;
+ case 1:
+ ret = vsprintf (buffer, "foo", ap);
+ break;
+ case 2:
+ vsprintf (buffer, "%s", ap);
+ break;
+ case 3:
+ ret = vsprintf (buffer, "%s", ap);
+ break;
+ case 4:
+ vsprintf (buffer, "%d - %c", ap);
+ break;
+ case 5:
+ vsprintf (s4, "%d - %c", ap);
+ break;
+ }
+ va_end (ap);
+ return ret;
+}
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ chk_calls = 0;
+ vsprintf_disallowed = 1;
+
+ memset (buffer, 'A', 32);
+ test1_sub (0);
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test1_sub (1) != 3)
+ abort ();
+ if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
+ abort ();
+
+ if (chk_calls)
+ abort ();
+ vsprintf_disallowed = 0;
+
+ memset (buffer, 'A', 32);
+ test1_sub (2, "bar");
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ if (test1_sub (3, "bar") != 3)
+ abort ();
+ if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ test1_sub (2, ptr);
+ if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
+ abort ();
+
+ memset (buffer, 'A', 32);
+ test1_sub (4, (int) l1 + 27, *ptr);
+ if (memcmp (buffer, "28 - b\0AAAAA", 12))
+ abort ();
+
+ if (chk_calls != 4)
+ abort ();
+ chk_calls = 0;
+
+ test1_sub (5, (int) l1 - 17, ptr[1]);
+ if (memcmp (s4, "-16 - a", 8))
+ abort ();
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test2_sub (int i, ...)
+{
+ va_list ap;
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
+ char buf3[20];
+ int j;
+
+ va_start (ap, i);
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ switch (i)
+ {
+ case 0:
+ vsprintf (a.buf1 + 2, "%s", ap);
+ break;
+ case 1:
+ vsprintf (r, "%s%c", ap);
+ break;
+ case 2:
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vsprintf (r, "%c %s", ap);
+ break;
+ case 3:
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vsprintf (r + 2, s3 + 3, ap);
+ break;
+ case 4:
+ case 7:
+ r = buf3;
+ for (j = 0; j < 4; ++j)
+ {
+ if (j == l1 - 1)
+ r = &a.buf1[1];
+ else if (j == l1)
+ r = &a.buf2[7];
+ else if (j == l1 + 1)
+ r = &buf3[5];
+ else if (j == l1 + 2)
+ r = &a.buf1[9];
+ }
+ if (i == 4)
+ vsprintf (r, s2 + 4, ap);
+ else
+ vsprintf (r, "a", ap);
+ break;
+ case 5:
+ r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
+ vsprintf (r, "%s", ap);
+ break;
+ case 6:
+ vsprintf (a.buf1 + 2, "", ap);
+ break;
+ case 8:
+ vsprintf (s4, "%s %d", ap);
+ break;
+ }
+ va_end (ap);
+}
+
+/* Test whether compile time checking is done where it should
+ and so is runtime object size checking. */
+void
+__attribute__((noinline))
+test2 (void)
+{
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ chk_calls = 0;
+ test2_sub (0, s3 + 3);
+ test2_sub (1, s3 + 3, s3[3]);
+ test2_sub (2, s2[2], s2 + 4);
+ test2_sub (3);
+ test2_sub (4);
+ test2_sub (5, s1 + 1);
+ if (chk_calls != 6)
+ abort ();
+
+ /* Following have known destination and known source length,
+ so if optimizing certainly shouldn't result in the checking
+ variants. */
+ chk_calls = 0;
+ vsprintf_disallowed = 1;
+ test2_sub (6);
+ test2_sub (7);
+ vsprintf_disallowed = 0;
+ /* Unknown destination and source, no checking. */
+ test2_sub (8, s3, 0);
+ if (chk_calls)
+ abort ();
+}
+
+void
+__attribute__((noinline))
+test3_sub (int i, ...)
+{
+ va_list ap;
+ struct A { char buf1[10]; char buf2[10]; } a;
+ char buf3[20];
+
+ va_start (ap, i);
+ /* The following calls should do runtime checking
+ - source length is not known, but destination is. */
+ switch (i)
+ {
+ case 0:
+ vsprintf (&a.buf2[9], "%c%s", ap);
+ break;
+ case 1:
+ vsprintf (&a.buf2[7], "%s%c", ap);
+ break;
+ case 2:
+ vsprintf (&a.buf2[7], "%d", ap);
+ break;
+ case 3:
+ vsprintf (&buf3[17], "%s", ap);
+ break;
+ case 4:
+ vsprintf (&buf3[19], "a", ap);
+ break;
+ }
+ va_end (ap);
+}
+
+/* Test whether runtime and/or compile time checking catches
+ buffer overflows. */
+void
+__attribute__((noinline))
+test3 (void)
+{
+ chk_fail_allowed = 1;
+ /* Runtime checks. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (0, s2[3], s2 + 4);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (1, s3 + strlen (s3) - 2, *s3);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (2, (int) l1 + 9999);
+ abort ();
+ }
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (3, "abc");
+ abort ();
+ }
+ /* This should be detectable at compile time already. */
+ if (__builtin_setjmp (chk_fail_buf) == 0)
+ {
+ test3_sub (4);
+ abort ();
+ }
+ chk_fail_allowed = 0;
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (s2) : "0" (s2));
+ __asm ("" : "=r" (s3) : "0" (s3));
+ __asm ("" : "=r" (l1) : "0" (l1));
+ s4 = p;
+ test1 ();
+ test2 ();
+ test3 ();
+}