diff options
author | Martin Sebor <msebor@redhat.com> | 2020-02-05 16:55:26 -0700 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-02-05 16:55:26 -0700 |
commit | e7868dc6a79daec4f46552fa5c99f88e4eb8de4c (patch) | |
tree | 0fad493958df5c30eebb8192fd46c5f287379396 /gcc/testsuite | |
parent | f6bef09771cf93e695cf719fb43db8c43e31acf5 (diff) | |
download | gcc-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/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/strlenopt-1.C | 42 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/strlenopt-2.C | 56 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Warray-bounds-58.c | 81 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wrestrict-20.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstring-compare.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strcmpopt_10.c | 130 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strcmpopt_11.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strcmpopt_2.c | 67 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strcmpopt_4.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-69.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-92.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-93.c | 71 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr92056.c | 11 |
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 *); |