aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-02-05 16:55:26 -0700
committerMartin Sebor <msebor@redhat.com>2020-02-05 16:55:26 -0700
commite7868dc6a79daec4f46552fa5c99f88e4eb8de4c (patch)
tree0fad493958df5c30eebb8192fd46c5f287379396 /gcc/testsuite
parentf6bef09771cf93e695cf719fb43db8c43e31acf5 (diff)
downloadgcc-e7868dc6a79daec4f46552fa5c99f88e4eb8de4c.zip
gcc-e7868dc6a79daec4f46552fa5c99f88e4eb8de4c.tar.gz
gcc-e7868dc6a79daec4f46552fa5c99f88e4eb8de4c.tar.bz2
PR tree-optimization/92765 - wrong code for strcmp of a union member
gcc/ChangeLog: PR tree-optimization/92765 * gimple-fold.c (get_range_strlen_tree): Handle MEM_REF and PARM_DECL. * tree-ssa-strlen.c (compute_string_length): Remove. (determine_min_objsize): Remove. (get_len_or_size): Add an argument. Call get_range_strlen_dynamic. Avoid using type size as the upper bound on string length. (handle_builtin_string_cmp): Add an argument. Adjust. (strlen_check_and_optimize_call): Pass additional argument to handle_builtin_string_cmp. gcc/testsuite/ChangeLog: PR tree-optimization/92765 * g++.dg/tree-ssa/strlenopt-1.C: New test. * g++.dg/tree-ssa/strlenopt-2.C: New test. * gcc.dg/Warray-bounds-58.c: New test. * gcc.dg/Wrestrict-20.c: Avoid a valid -Wformat-overflow. * gcc.dg/Wstring-compare.c: Xfail a test. * gcc.dg/strcmpopt_2.c: Disable tests. * gcc.dg/strcmpopt_4.c: Adjust tests. * gcc.dg/strcmpopt_10.c: New test. * gcc.dg/strcmpopt_11.c: New test. * gcc.dg/strlenopt-69.c: Disable tests. * gcc.dg/strlenopt-92.c: New test. * gcc.dg/strlenopt-93.c: New test. * gcc.dg/strlenopt.h: Declare calloc. * gcc.dg/tree-ssa/pr92056.c: Xfail tests until pr93518 is resolved. * gcc.dg/tree-ssa/builtin-sprintf-warn-23.c: Correct test (pr93517).
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/ChangeLog19
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/strlenopt-1.C42
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/strlenopt-2.C56
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-58.c81
-rw-r--r--gcc/testsuite/gcc.dg/Wrestrict-20.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wstring-compare.c3
-rw-r--r--gcc/testsuite/gcc.dg/strcmpopt_10.c130
-rw-r--r--gcc/testsuite/gcc.dg/strcmpopt_11.c16
-rw-r--r--gcc/testsuite/gcc.dg/strcmpopt_2.c67
-rw-r--r--gcc/testsuite/gcc.dg/strcmpopt_4.c25
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-69.c3
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-92.c58
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-93.c71
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt.h1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr92056.c11
16 files changed, 553 insertions, 50 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ca1d083..5802f0d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,22 @@
+2020-02-05 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/92765
+ * g++.dg/tree-ssa/strlenopt-1.C: New test.
+ * g++.dg/tree-ssa/strlenopt-2.C: New test.
+ * gcc.dg/Warray-bounds-58.c: New test.
+ * gcc.dg/Wrestrict-20.c: Avoid a valid -Wformat-overflow.
+ * gcc.dg/Wstring-compare.c: Xfail a test.
+ * gcc.dg/strcmpopt_2.c: Disable tests.
+ * gcc.dg/strcmpopt_4.c: Adjust tests.
+ * gcc.dg/strcmpopt_10.c: New test.
+ * gcc.dg/strcmpopt_11.c: New test.
+ * gcc.dg/strlenopt-69.c: Disable tests.
+ * gcc.dg/strlenopt-92.c: New test.
+ * gcc.dg/strlenopt-93.c: New test.
+ * gcc.dg/strlenopt.h: Declare calloc.
+ * gcc.dg/tree-ssa/pr92056.c: Xfail tests until pr93518 is resolved.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-23.c: Correct test (pr93517).
+
2020-02-05 Marek Polacek <polacek@redhat.com>
PR c++/93559 - ICE with CONSTRUCTOR flags verification.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/strlenopt-1.C b/gcc/testsuite/g++.dg/tree-ssa/strlenopt-1.C
new file mode 100644
index 0000000..b6adfac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/strlenopt-1.C
@@ -0,0 +1,42 @@
+/* PR tree-optimization/92765 - wrong code for strcmp of a union member
+ { dg-do run }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+inline void* operator new (size_t, void *p)
+{
+ return p;
+}
+
+struct A { char a2[2]; };
+struct B { char a4[4]; };
+
+__attribute__((noipa)) void
+sink (void*) { }
+
+__attribute__((noipa)) void
+copy (char *d, const char *s)
+{
+ while ((*d++ = *s++));
+}
+
+__attribute__((noipa)) void
+store_and_compare (void *p)
+{
+ A *a = new (p) A;
+ sink (a->a2);
+
+ B *b = new (p) B;
+ char *q = (char *) b->a4;
+ copy (q, "abc");
+
+ if (__builtin_strcmp (q, "abc"))
+ __builtin_abort ();
+}
+
+int main ()
+{
+ char a [sizeof (A) > sizeof (B) ? sizeof (A) : sizeof (B)];
+ store_and_compare (a);
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/strlenopt-2.C b/gcc/testsuite/g++.dg/tree-ssa/strlenopt-2.C
new file mode 100644
index 0000000..60f8205
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/strlenopt-2.C
@@ -0,0 +1,56 @@
+/* PR tree-optimization/92765 - wrong code for strcmp of a union member
+ { dg-do run }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+inline void* operator new (size_t, void *p)
+{
+ return p;
+}
+
+struct A
+{
+ char a[2]; char b[2]; char c[2];
+ A () { a[0] = 0; b[0] = 0; c[0] = 0; };
+ ~A () { }
+};
+
+struct B
+{
+ char d[6];
+ B () { d[0] = 0; d[2] = 0; }
+ ~B () { }
+};
+
+__attribute__((noipa)) void
+sink (void *) { }
+
+__attribute__((noipa)) void
+copy (char *d, const char *s)
+{
+ while ((*d++ = *s++));
+}
+
+__attribute__((noipa)) void
+store_and_compare (void *p)
+{
+ A *a = new (p) A ();
+ sink (&a->b);
+ a->~A ();
+
+ B *b = new (p) B ();
+ char *q = &b->d[2];
+ copy (q, "abc");
+
+ if (__builtin_strcmp (q, "abc"))
+ __builtin_abort ();
+ b->~B ();
+}
+
+int main ()
+{
+ char a [sizeof (A) > sizeof (B) ? sizeof (A) : sizeof (B)];
+ store_and_compare (a);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-58.c b/gcc/testsuite/gcc.dg/Warray-bounds-58.c
new file mode 100644
index 0000000..7bd6df2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-58.c
@@ -0,0 +1,81 @@
+/* { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern size_t strlen (const char*);
+
+void sink (size_t);
+
+struct A0 { char i, a[0]; };
+
+extern struct A0 ea0;
+
+void fa0_extern (void)
+{
+ sink (strlen (ea0.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
+ sink (strlen (ea0.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ea0.a)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ea0.a + 1)); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static struct A0 sa0 = { 0 };
+
+void fa0_static (void)
+{
+ sink (strlen (sa0.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
+ sink (strlen (sa0.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (sa0.a)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (sa0.a + 1)); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+struct Ax { char i, a[]; };
+
+extern struct Ax ax;
+
+void fax_extern (void)
+{
+ sink (strlen (ax.a - 2)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax.a));
+ sink (strlen (ax.a + 123));
+}
+
+static struct Ax ax0 = { 0, { 0 } };
+static struct Ax ax1 = { 1, { 1, 0 } };
+static struct Ax ax2 = { 2, { 2, 1, 0 } };
+static struct Ax ax3 = { 3, { 3, 2, 1, 0 } };
+
+void fax_static (void)
+{
+ sink (strlen (ax0.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
+ sink (strlen (ax0.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax0.a));
+ sink (strlen (ax0.a + 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax0.a + 2)); // { dg-warning "\\\[-Warray-bounds" }
+
+ sink (strlen (ax1.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
+ sink (strlen (ax1.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax1.a));
+ sink (strlen (ax1.a + 1));
+ sink (strlen (ax1.a + 2)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax1.a + 3)); // { dg-warning "\\\[-Warray-bounds" }
+
+ sink (strlen (ax2.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
+ sink (strlen (ax2.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax2.a));
+ sink (strlen (ax2.a + 1));
+ sink (strlen (ax2.a + 2));
+ sink (strlen (ax2.a + 3)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax2.a + 4)); // { dg-warning "\\\[-Warray-bounds" }
+
+ sink (strlen (ax3.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
+ sink (strlen (ax3.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax3.a));
+ sink (strlen (ax3.a + 1));
+ sink (strlen (ax3.a + 2));
+ sink (strlen (ax3.a + 3));
+ sink (strlen (ax3.a + 4)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+ sink (strlen (ax3.a + 5)); // { dg-warning "\\\[-Warray-bounds" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-20.c b/gcc/testsuite/gcc.dg/Wrestrict-20.c
index 9826e7f..a2d2988 100644
--- a/gcc/testsuite/gcc.dg/Wrestrict-20.c
+++ b/gcc/testsuite/gcc.dg/Wrestrict-20.c
@@ -15,7 +15,7 @@ void test_warn (char *p)
sprintf (a, "a=%s", a); /* { dg-warning "-Wrestrict" } */
p = a;
- char *q = p + 1;
+ char *q = p + 3;
sprintf (p, "a=%s", q); /* { dg-warning "-Wrestrict" } */
}
@@ -31,7 +31,7 @@ void test_nowarn_front_end (char *d)
void test_nowarn_sprintf_pass (char *d)
{
char *q = d;
-
+
sprintf (d, "p=%p", q);
snprintf (d, 32, "p=%p", q);
diff --git a/gcc/testsuite/gcc.dg/Wstring-compare.c b/gcc/testsuite/gcc.dg/Wstring-compare.c
index 0ca492d..d1534bf 100644
--- a/gcc/testsuite/gcc.dg/Wstring-compare.c
+++ b/gcc/testsuite/gcc.dg/Wstring-compare.c
@@ -120,7 +120,8 @@ void strcmp_array_copy (void)
void strcmp_member_array_lit (const struct S *p)
{
- T (p->a4, "1234"); // { dg-warning "length 4 and an array of size 4 " }
+ // Not handled due to the fix for PR 92756.
+ T (p->a4, "1234"); // { dg-warning "length 4 and an array of size 4 " "pr92765" { xfail *-*-* } }
}
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_10.c b/gcc/testsuite/gcc.dg/strcmpopt_10.c
new file mode 100644
index 0000000..94fda59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strcmpopt_10.c
@@ -0,0 +1,130 @@
+/* Verify that strncmp equalities aren't eliminated when the trailing array
+ type referenced by a member pointer is smaller than the string in cases
+ when the pointer pointed to by the enclosing object references an object
+ sufficiently large to store a string of equal length.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wextra -fdump-tree-optimized" } */
+
+void init (void*);
+
+struct A1 { char i, a[1]; };
+
+void f1_arr (void)
+{
+ char a[9];
+ init (a);
+
+ struct A1 *p = (struct A1*)a;
+
+ if (__builtin_strncmp (p->a, "01234567", 8) == 0)
+ {
+ extern void array_test (void);
+ array_test ();
+ }
+}
+
+void f1_ptr (void)
+{
+ void *p;
+ init (&p);
+
+ struct A1 *q = (struct A1*)p;
+
+ if (__builtin_strncmp (q->a, "0123456789", 10) == 0)
+ {
+ extern void pointer_test (void);
+ pointer_test ();
+ }
+}
+
+void f1_struct (void)
+{
+ struct { char a[9]; } b;
+ init (&b);
+
+ struct A1 *p = (struct A1*)&b;
+
+ if (__builtin_strncmp (p->a, "01234567", 8) == 0)
+ {
+ extern void struct_test (void);
+ struct_test ();
+ }
+}
+
+void f1_memptr (void)
+{
+ struct { void *p; } b;
+ init (&b);
+
+ struct A1 *p = (struct A1*)b.p;
+
+ if (__builtin_strncmp (p->a, "0123456789", 10) == 0)
+ {
+ extern void memptr_test (void);
+ memptr_test ();
+ }
+}
+
+
+struct A2 { char i, a[2]; };
+
+void f2_arr (void)
+{
+ char a[8];
+ init (a);
+
+ struct A2 *p = (struct A2*)a;
+
+ if (__builtin_strncmp (p->a, "0123456", 7) == 0)
+ {
+ extern void array_test (void);
+ array_test ();
+ }
+}
+
+void f2_ptr (void)
+{
+ void *p;
+ init (&p);
+
+ struct A2 *q = (struct A2*)p;
+
+ if (__builtin_strncmp (q->a, "0123456789", 10) == 0)
+ {
+ extern void pointer_test (void);
+ pointer_test ();
+ }
+}
+
+void f2_struct (void)
+{
+ struct { char a[8]; } b;
+ init (&b);
+
+ struct A2 *p = (struct A2*)&b;
+
+ if (__builtin_strncmp (p->a, "0123456", 7) == 0)
+ {
+ extern void struct_test (void);
+ struct_test ();
+ }
+}
+
+void f2_memptr (void)
+{
+ struct { void *p; } b;
+ init (&b);
+
+ struct A2 *p = (struct A2*)b.p;
+
+ if (__builtin_strncmp (p->a, "0123456789", 10) == 0)
+ {
+ extern void memptr_test (void);
+ memptr_test ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "array_test" 2 "optimized" } }
+ { dg-final { scan-tree-dump-times "pointer_test" 2 "optimized" } }
+ { dg-final { scan-tree-dump-times "struct_test" 2 "optimized" } }
+ { dg-final { scan-tree-dump-times "memptr_test" 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_11.c b/gcc/testsuite/gcc.dg/strcmpopt_11.c
new file mode 100644
index 0000000..945e083
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strcmpopt_11.c
@@ -0,0 +1,16 @@
+/* Verify that strcmp doesn't make assumptions about the size of a weak
+ symbol.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+/* An ordinary definition of A with more elements might be provided
+ in another translation unit. Even though that would be undefined
+ (the type of the actual definition must be the same as the type
+ of the weak declaration) this test verifies that GCC doesn't rely
+ on the size of this A for optimization (as a matter of QoI). */
+__attribute__ ((weak)) char a[3];
+
+int cmp_a3_x (void)
+{
+ return __builtin_strcmp (a, "1234567") == 0;
+}
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_2.c b/gcc/testsuite/gcc.dg/strcmpopt_2.c
index 57d8f65..f31761b 100644
--- a/gcc/testsuite/gcc.dg/strcmpopt_2.c
+++ b/gcc/testsuite/gcc.dg/strcmpopt_2.c
@@ -4,52 +4,53 @@
char s[100] = {'a','b','c','d'};
typedef struct { char s[8]; int x; } S;
-__attribute__ ((noinline)) int
-f1 (S *s)
-{
- return __builtin_strcmp (s->s, "abc") != 0;
+__attribute__ ((noinline)) int
+f1 (S *s)
+{
+ /* Member arrays not handled due to the fix for PR 92765. */
+ return 0; // __builtin_strcmp (s->s, "abc") != 0;
}
-__attribute__ ((noinline)) int
-f2 (void)
-{
- return __builtin_strcmp (s, "abc") != 0;
+__attribute__ ((noinline)) int
+f2 (void)
+{
+ return __builtin_strcmp (s, "abc") != 0;
}
-__attribute__ ((noinline)) int
-f3 (S *s)
-{
- return __builtin_strcmp ("abc", s->s) != 0;
+__attribute__ ((noinline)) int
+f3 (S *s)
+{
+ return 0; // __builtin_strcmp ("abc", s->s) != 0;
}
-__attribute__ ((noinline)) int
-f4 (void)
-{
- return __builtin_strcmp ("abc", s) != 0;
+__attribute__ ((noinline)) int
+f4 (void)
+{
+ return __builtin_strcmp ("abc", s) != 0;
}
-__attribute__ ((noinline)) int
-f5 (S *s)
-{
- return __builtin_strncmp (s->s, "abc", 3) != 0;
+__attribute__ ((noinline)) int
+f5 (S *s)
+{
+ return 0; // __builtin_strncmp (s->s, "abc", 3) != 0;
}
-__attribute__ ((noinline)) int
-f6 (void)
-{
- return __builtin_strncmp (s, "abc", 2) != 0;
+__attribute__ ((noinline)) int
+f6 (void)
+{
+ return __builtin_strncmp (s, "abc", 2) != 0;
}
-__attribute__ ((noinline)) int
-f7 (S *s)
-{
- return __builtin_strncmp ("abc", s->s, 3) != 0;
+__attribute__ ((noinline)) int
+f7 (S *s)
+{
+ return 0; // __builtin_strncmp ("abc", s->s, 3) != 0;
}
-__attribute__ ((noinline)) int
-f8 (void)
-{
- return __builtin_strncmp ("abc", s, 2) != 0;
+__attribute__ ((noinline)) int
+f8 (void)
+{
+ return __builtin_strncmp ("abc", s, 2) != 0;
}
int main (void)
@@ -64,4 +65,4 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 8 "strlen1" } } */
+/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 4 "strlen1" } } */
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_4.c b/gcc/testsuite/gcc.dg/strcmpopt_4.c
index 4e26522..b07fbb6 100644
--- a/gcc/testsuite/gcc.dg/strcmpopt_4.c
+++ b/gcc/testsuite/gcc.dg/strcmpopt_4.c
@@ -2,15 +2,26 @@
/* { dg-options "-O2 -fdump-tree-strlen" } */
typedef struct { char s[8]; int x; } S;
+
extern int max_i;
-int
-f1 (S * s)
-{
- int result, i;
- for (i = 0; i < max_i; i++)
- result += __builtin_strcmp (s->s, "abc") != 0 ? 2 : 1;
+int f_param (S s)
+{
+ int result = 0;
+ for (int i = 0; i < max_i; i++)
+ result += __builtin_strcmp (s.s, "abc") != 0 ? 2 : 1;
+ return result;
+}
+
+
+S s;
+
+int f_object (void)
+{
+ int result = 0;
+ for (int i = 0; i < max_i; i++)
+ result += __builtin_strcmp (s.s, "abc") != 0 ? 2 : 1;
return result;
}
-/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 1 "strlen1" } } */
+/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 2 "strlen1" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-69.c b/gcc/testsuite/gcc.dg/strlenopt-69.c
index 9ad8e2e..9df6eec 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-69.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-69.c
@@ -35,6 +35,8 @@ void test_array_lit (void)
void test_memarray_lit (struct S *p)
{
+#if 0
+ /* Member arrays not handled due to the fix for PR 92765. */
A (strcmp (p->a4, "1234"));
A (strcmp (p->a4, "12345"));
A (strcmp (p->a4, "123456"));
@@ -42,6 +44,7 @@ void test_memarray_lit (struct S *p)
A (strcmp ("1234", p->a4));
A (strcmp ("12345", p->a4));
A (strcmp ("123456", p->a4));
+#endif
}
/* Verify that the equality of empty strings is folded. */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-92.c b/gcc/testsuite/gcc.dg/strlenopt-92.c
new file mode 100644
index 0000000..a9383e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-92.c
@@ -0,0 +1,58 @@
+/* PR tree-optimization/92765 - wrong code for strcmp of a union member
+ { dg-do run }
+ { dg-options "-O2 -Wall" } */
+
+#include "strlenopt.h"
+
+__attribute__((noipa)) int
+copy (char *x, int y)
+{
+ if (y == 0)
+ strcpy (x, "abcd");
+ return y;
+}
+
+__attribute__((noipa)) char *
+alloc_2_copy_compare (int x)
+{
+ char *p;
+ if (x)
+ p = malloc (4);
+ else
+ p = calloc (16, 1);
+
+ char *q = p + 2;
+ if (copy (q, x))
+ return p;
+
+ if (strcmp (q, "abcd") != 0)
+ abort ();
+
+ return p;
+}
+
+char a5[5], a6[6], a7[7];
+
+__attribute__((noipa)) char *
+decl_3_copy_compare (int x)
+{
+ char *p = x < 0 ? a5 : 0 < x ? a6 : a7;
+ char *q = p + 1;
+ if (copy (q, x))
+ return p;
+
+ if (strcmp (q, "abcd") != 0)
+ abort ();
+
+ return p;
+}
+
+int main ()
+{
+ free (alloc_2_copy_compare (0));
+ free (alloc_2_copy_compare (1));
+
+ decl_3_copy_compare (-1);
+ decl_3_copy_compare (0);
+ decl_3_copy_compare (1);
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-93.c b/gcc/testsuite/gcc.dg/strlenopt-93.c
new file mode 100644
index 0000000..dc5f12d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-93.c
@@ -0,0 +1,71 @@
+/* Verify that strlen doesn't (inadvertently) use the size of an array
+ of char pointers to put an upper bound on the length of the strings
+ they point to.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+void eaa_test (void)
+{
+ extern char eaa[4][4];
+
+ char (*p)[4] = eaa;
+
+ if (!*p)
+ return;
+
+ /* The longest string stored in EAA is 15 characters. */
+ if (__builtin_strlen (*p) > 14)
+ {
+ extern void eaa_ok (void);
+ eaa_ok ();
+ }
+
+ if (__builtin_strlen (*p) > 15)
+ {
+ extern void eaa_fail (void);
+ eaa_fail ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "eaa_ok" 1 "optimized" } }
+ { dg-final { scan-tree-dump-not "eaa_fail" "optimized" } } */
+
+
+void epa_test (void)
+{
+ extern char* epa[4];
+ char **p = epa;
+
+ if (*p && __builtin_strlen (*p) > 123)
+ {
+ extern void epa_ok (void);
+ epa_ok ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "epa_ok" 1 "optimized" } } */
+
+
+static char* spa[4];
+
+void spa_test (void)
+{
+ char **p = spa;
+
+ if (*p && __builtin_strlen (*p) > 123)
+ {
+ extern void spa_ok ();
+ spa_ok ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "spa_ok" 1 "optimized" } } */
+
+
+void sink (void*, ...);
+
+void init (void)
+{
+ /* Make believe even the static array SA may be non-zero. */
+ sink (spa);
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt.h b/gcc/testsuite/gcc.dg/strlenopt.h
index 518d0cf..a3ca951 100644
--- a/gcc/testsuite/gcc.dg/strlenopt.h
+++ b/gcc/testsuite/gcc.dg/strlenopt.h
@@ -5,6 +5,7 @@
#define NULL ((void *) 0)
typedef __SIZE_TYPE__ size_t;
extern void abort (void);
+void *calloc (size_t, size_t);
void *malloc (size_t);
void free (void *);
char *strdup (const char *);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c
index 98dfa1d..7fb9651 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c
@@ -642,10 +642,22 @@ void test_multiple_overlap (int i)
}
{
- char a[4]; /* { dg-message "declared here" } */
+ char a[4];
+
+ /* There is no overlap here because the length of a3 is at most 1
+ and a4 is necessarily the empty string. */
+ char *d = a;
+ char *a3 = a + 2;
+ char *a4 = a + 3;
+
+ T (d, "%s%s", a3, a4);
+ }
+
+ {
+ char a[5]; /* { dg-message "declared here" } */
/* a3 and a4 may overlap the output. They will only not overlap
- it when a3 is empty, and a4 is at most chaeracter byte long. */
+ it when a3 is empty, and a4 is at most 1 character long. */
char *d = a;
char *a3 = a + 2;
char *a4 = a + 3;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr92056.c b/gcc/testsuite/gcc.dg/tree-ssa/pr92056.c
index e43d0c0..73b1f2a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr92056.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr92056.c
@@ -1,8 +1,9 @@
-/* PR tree-optimization/92056 */
-/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
-/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */
-/* { dg-final { scan-tree-dump-not "strcmp \\(" "optimized" } } */
+/* PR tree-optimization/92056
+ { dg-do compile }
+ { dg-options "-O2 -fdump-tree-optimized" }
+ Xfailed until pr93518 is resolved.
+ { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" { xfail *-*-* } } }
+ { dg-final { scan-tree-dump-not "strcmp \\(" "optimized" { xfail *-*-* } } } */
void bar (int, char *);