diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-10-12 09:46:38 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-10-12 09:46:38 -0700 |
commit | 9cd320ea6572c577cdf17ce1f9ea5230b166af6d (patch) | |
tree | d1c8e7c2e09a91ed75f0e5476c648c2e745aa2de /gcc/testsuite/gcc.dg | |
parent | 4854d721be78358e59367982bdd94461b4be3c5a (diff) | |
parent | 3175d40fc52fb8eb3c3b18cc343d773da24434fb (diff) | |
download | gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.zip gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.tar.gz gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.tar.bz2 |
Merge from trunk revision 3175d40fc52fb8eb3c3b18cc343d773da24434fb.
Diffstat (limited to 'gcc/testsuite/gcc.dg')
605 files changed, 16014 insertions, 941 deletions
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-30.c b/gcc/testsuite/gcc.dg/Warray-bounds-30.c index b996568..048a95d 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-30.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-30.c @@ -73,8 +73,7 @@ void test_global_int_array (void) T (&p[min]); /* { dg-warning "subscript -\[0-9\]+ is \(below|outside\) array bounds of .int\\\[1]." } */ T (&p[-1]); /* { dg-warning "subscript -1 is \(below|outside\) array bounds of .int\\\[1]." } */ - T (&p[0]); - T (&p[1]); + T (&p[0], &p[1]); T (&p[2]); /* { dg-warning "subscript 2 is \(above|outside\) array bounds of .int\\\[1]." } */ T (&p[max]); /* { dg-warning "subscript \[0-9\]+ is \(above|outside\) array bounds of .int\\\[1]." } */ diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-39.c b/gcc/testsuite/gcc.dg/Warray-bounds-39.c index f10ffac..8317656 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-39.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-39.c @@ -21,65 +21,65 @@ char d[4]; void* test_memcpy_s0_1 (void *d) { - return memcpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s0_2 (void *d) { - return memcpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s0_0_1 (void *d) { - return memcpy (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s0_0_2 (void *d) { - return memcpy (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s0_1_1 (void *d) { - return memcpy (d, s0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s0_1_2 (void *d) { - return memcpy (d, s0_1, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s0_1, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s1_0_1 (void *d) { - return memcpy (d, s1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_s1_0_2 (void *d) { - return memcpy (d, s1_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, s1_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memmove_s0_1 (void *d) { - return memmove (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memmove (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memmove_s0_2 (void *d) { - return memmove (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memmove (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memmove_s0_0_1 (void *d) { - return memmove (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memmove (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memmove_s0_0_2 (void *d) { - return memmove (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memmove (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } @@ -92,57 +92,57 @@ const struct Empty e1_0[1][0] = { }; void* test_memcpy_e_1 (void *d) { - return memcpy (d, &e, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, &e, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_e0_1 (void *d) { - return memcpy (d, e0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, e0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_e0_0_1 (void *d) { - return memcpy (d, e0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, e0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_e0_1_1 (void *d) { - return memcpy (d, e0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, e0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } void* test_memcpy_e1_0_1 (void *d) { - return memcpy (d, e1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return memcpy (d, e1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } char* test_strcpy_s0 (char *d) { - return strcpy (d, s0); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return strcpy (d, s0); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } char* test_strcpy_s0_0 (char *d) { - return strcpy (d, s0_0[0]); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return strcpy (d, s0_0[0]); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } char* test_strncpy_s0_1 (char *d) { - return strncpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return strncpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } char* test_strncpy_s0_2 (char *d) { - return strncpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return strncpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } char* test_strncpy_s0_0_1 (char *d) { - return strncpy (d, s0_0[0], 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return strncpy (d, s0_0[0], 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } char* test_strncpy_s0_0_2 (char *d) { - return strncpy (d, s0_0[0], 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */ + return strncpy (d, s0_0[0], 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */ } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-40.c b/gcc/testsuite/gcc.dg/Warray-bounds-40.c index aabc283..c389d96 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-40.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-40.c @@ -3,7 +3,7 @@ functions when -Wstringop-overflow is disabled is -Warray-bounds with the right wording. { dg-do compile } - { dg-options "-O2 -Wall -Wno-stringop-overflow" } */ + { dg-options "-O2 -Wall -Wno-stringop-overflow -Wno-stringop-overread" } */ #define PTRDIFF_MAX __PTRDIFF_MAX__ #define SIZE_MAX __SIZE_MAX__ diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-46.c b/gcc/testsuite/gcc.dg/Warray-bounds-46.c index 3f1c6c7..4effe5c 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-46.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-46.c @@ -3,7 +3,8 @@ Test to verify that past-the-end accesses by string functions to member arrays by-reference objects are diagnosed. { dg-do compile } - { dg-options "-O2 -Wall -Wno-unused-local-typedefs -Wno-stringop-overflow -ftrack-macro-expansion=0" } */ + { dg-options "-O2 -Wall -Wno-unused-local-typedefs -Wno-stringop-overflow -ftrack-macro-expansion=0" } + { dg-require-effective-target alloca } */ #define SA(expr) typedef int StaticAssert [2 * !!(expr) - 1] diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48.c b/gcc/testsuite/gcc.dg/Warray-bounds-48.c index d6a327e..13373d1 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-48.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48.c @@ -1,7 +1,8 @@ /* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array of a declared object { dg-do "compile" } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ typedef __INT16_TYPE__ int16_t; typedef __INT32_TYPE__ int32_t; diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-50.c b/gcc/testsuite/gcc.dg/Warray-bounds-50.c index d6edfac..05c89b2 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-50.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-50.c @@ -1,6 +1,7 @@ /* PR middle-end/92349 - ICE in -Warray-bounds on a VLA member { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-58.c b/gcc/testsuite/gcc.dg/Warray-bounds-58.c index 7bd6df2..849457e5 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-58.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-58.c @@ -1,5 +1,5 @@ /* { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall -Wno-stringop-overread" } */ typedef __SIZE_TYPE__ size_t; @@ -15,8 +15,8 @@ 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" } + sink (strlen (ea0.a)); // valid just-past-the-end offset + sink (strlen (ea0.a + 1)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } } static struct A0 sa0 = { 0 }; @@ -25,8 +25,8 @@ 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" } + sink (strlen (sa0.a)); // valid just-past-the-end offset + sink (strlen (sa0.a + 1)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } } @@ -52,23 +52,23 @@ 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 (ax0.a + 1)); // valid just-past-the-end offset + sink (strlen (ax0.a + 2)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } 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 (ax1.a + 2)); // valid just-past-the-end offset + sink (strlen (ax1.a + 3)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } 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 (ax2.a + 3)); // valid just-past-the-end offset + sink (strlen (ax2.a + 4)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } sink (strlen (ax3.a - 2)); // { dg-warning "\\\[-Warray-bounds" } sink (strlen (ax3.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } } @@ -76,6 +76,6 @@ void fax_static (void) 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" } + sink (strlen (ax3.a + 4)); // valid just-past-the-end offset + sink (strlen (ax3.a + 5)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-62.c b/gcc/testsuite/gcc.dg/Warray-bounds-62.c new file mode 100644 index 0000000..c2421aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-62.c @@ -0,0 +1,130 @@ +/* PR tree-optimization/84079 - missing -Warray-bounds taking the address + of past-the-end element of a multidimensional array + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +void sink (int, ...); + +#define T(type, dims, inxs) \ + do { \ + type a dims; \ + sink (__LINE__, &a inxs); \ + } while (0) + + +void test_char_1_1 (int i0, int i1, int i2) +{ +#undef DIMS +#define DIMS [1][1] + + T (char, DIMS, [0]); + T (char, DIMS, [1]); + T (char, DIMS, [2]); // { dg-warning "subscript 2 is above array bounds of 'char\\\[1]\\\[1]'" } + + T (char, DIMS, [0][0]); + T (char, DIMS, [0][1]); + T (char, DIMS, [0][2]); // { dg-warning "subscript 2 is above array bounds of 'char\\\[1]'" } + + T (char, DIMS, [1][0]); // { dg-warning "subscript 1 is above array bounds of 'char\\\[1]\\\[1]'" } + T (char, DIMS, [1][1]); // { dg-warning "subscript 1 is above array bounds of 'char\\\[1]\\\[1]'" } + T (char, DIMS, [1][2]); // { dg-warning "subscript 2 is above array bounds of 'char\\\[1]'" } + + // Exercise ranges. + if (i0 < 0) i0 = 0; + if (i1 < 1) i1 = 1; + if (i2 < 2) i2 = 2; + + T (char, DIMS, [i0]); + T (char, DIMS, [i1]); + T (char, DIMS, [i2]); // { dg-warning "subscript 2 is above array bounds of 'char\\\[1]\\\[1]" } + + T (char, DIMS, [i0][i0]); + T (char, DIMS, [i0][i1]); + T (char, DIMS, [i1][i0]); // { dg-warning "subscript 1 is above array bounds of 'char\\\[1]\\\[1]'" } + T (char, DIMS, [i1][i1]); // { dg-warning "subscript 1 is above array bounds of 'char\\\[1]\\\[1]'" } + T (char, DIMS, [i1][i2]); // { dg-warning "subscript 2 is above array bounds of 'char\\\[1]'" } +} + + +void test_int_3_5 (int i0, int i1, int i2, int i3, int i4, int i5, int i6) +{ +#undef DIMS +#define DIMS [3][5] + + T (int, DIMS, [0]); + T (int, DIMS, [3]); + T (int, DIMS, [4]); // { dg-warning "subscript 4 is above array bounds of 'int\\\[3]\\\[5]'" } + + T (int, DIMS, [0][0]); + T (int, DIMS, [0][5]); + T (int, DIMS, [0][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [1][0]); + T (int, DIMS, [1][5]); + T (int, DIMS, [1][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [3][0]); // { dg-warning "subscript 3 is above array bounds of 'int\\\[3]\\\[5]'" } + T (int, DIMS, [3][5]); // { dg-warning "subscript 3 is above array bounds of 'int\\\[3]\\\[5]'" } + T (int, DIMS, [3][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + // Exercise ranges. + if (i0 < 0) i0 = 0; + if (i1 < 1) i1 = 1; + if (i2 < 2) i2 = 2; + if (i3 < 3) i3 = 3; + if (i4 < 4) i4 = 4; + if (i5 < 5) i5 = 5; + if (i6 < 6) i6 = 6; + + T (int, DIMS, [i0]); + T (int, DIMS, [i3]); + T (int, DIMS, [i4]); // { dg-warning "subscript 4 is above array bounds of 'int\\\[3]\\\[5]" } + + T (int, DIMS, [i0][i0]); + T (int, DIMS, [i0][i5]); + T (int, DIMS, [i0][i6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [i1][i0]); + T (int, DIMS, [i1][i5]); + T (int, DIMS, [i1][i6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [i3][i0]); // { dg-warning "subscript 3 is above array bounds of 'int\\\[3]\\\[5]'" } + T (int, DIMS, [i3][i5]); // { dg-warning "subscript 3 is above array bounds of 'int\\\[3]\\\[5]'" } + T (int, DIMS, [i3][i6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } +} + + +void test_int_2_3_4_5 (void) +{ +#undef DIMS +#define DIMS [2][3][4][5] + + T (int, DIMS, [0]); + T (int, DIMS, [2]); + T (int, DIMS, [3]); // { dg-warning "subscript 3 is above array bounds of 'int\\\[2]\\\[3]\\\[4]\\\[5]'" } + + T (int, DIMS, [0][0]); + T (int, DIMS, [0][3]); + T (int, DIMS, [0][4]); // { dg-warning "subscript 4 is above array bounds of 'int\\\[3]\\\[4]\\\[5]'" } + T (int, DIMS, [0][9]); // { dg-warning "subscript 9 is above array bounds of 'int\\\[3]\\\[4]\\\[5]'" } + + T (int, DIMS, [0][0][0]); + T (int, DIMS, [0][0][4]); + T (int, DIMS, [0][0][5]); // { dg-warning "subscript 5 is above array bounds of 'int\\\[4]\\\[5]'" } + + T (int, DIMS, [0][0][0][0]); + T (int, DIMS, [0][0][0][5]); + T (int, DIMS, [0][0][0][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [0][0][1][0]); + T (int, DIMS, [0][0][1][5]); + T (int, DIMS, [0][0][1][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [0][0][3][0]); + T (int, DIMS, [0][0][3][5]); + T (int, DIMS, [0][0][3][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } + + T (int, DIMS, [0][0][1][0]); + T (int, DIMS, [0][0][1][5]); + T (int, DIMS, [0][0][1][6]); // { dg-warning "subscript 6 is above array bounds of 'int\\\[5]'" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-63.c b/gcc/testsuite/gcc.dg/Warray-bounds-63.c new file mode 100644 index 0000000..a3fc918 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-63.c @@ -0,0 +1,54 @@ +/* PR middle-end/94195 - missing warning reading a smaller object via + an lvalue of a larger type + { dg-do compile } + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ + +typedef __INT16_TYPE__ int16_t; +typedef __SIZE_TYPE__ size_t; + +void* alloca (size_t); + +void sink (void*); + + +void byte_store_to_decl (void) +{ + struct S6 { char a[6]; } s; // { dg-message "referencing 's'" } + + char *p = (char*)&s; + + p[0] = 0; p[1] = 1; p[2] = 2; p[3] = 3; p[4] = 4; p[5] = 5; + p[6] = 6; // { dg-warning "array subscript 6 is outside array bounds of 'struct S6\\\[1]" } + + sink (&s); +} + + +void word_store_to_decl (void) +{ + struct S6 { char a[6]; } s; // { dg-message "referencing 's'" } + + char *p = (char*)&s; + + int16_t *q = (int16_t*)(p + 1); + + q[0] = 0; q[1] = 1; + q[2] = 2; // { dg-warning "array subscript 'int16_t {aka short int}\\\[2]' is partly outside array bounds of 'struct S6\\\[1]'" } + + sink (&s); +} + + +void word_store_to_alloc (void) +{ + struct S6 { char a[6]; } *p; + p = alloca (sizeof *p); // { dg-message "referencing an object of size 6 allocated by 'alloca'" } + + int16_t *q = (int16_t*)((char*)p + 1); + + q[0] = 0; q[1] = 1; + q[2] = 2; // { dg-warning "array subscript 'int16_t {aka short int}\\\[2]' is partly outside array bounds of 'unsigned char\\\[6]'" } + + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-64.c b/gcc/testsuite/gcc.dg/Warray-bounds-64.c new file mode 100644 index 0000000..88b88de --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-64.c @@ -0,0 +1,60 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + + Verify that out-of-bounds accesses to array arguments are diagnosed, + both to ordinary array parameters with constant bounds and to array + parameters declared static. This is the converse of what PR 50584 + asks for. + + { dg-do compile } + { dg-options "-O2 -Wall -Warray-parameter -Wno-vla-paramater" } */ + +#define NOIPA __attribute__ ((noipa)) + +void sink (void*, ...); + +#define T(...) sink (0, __VA_ARGS__) + + +NOIPA void fca1 (char a[1]) +{ + T (a[0]); + T (a[1]); // { dg-warning "-Warray-bounds" } +} + +NOIPA void fcas1 (char a[static 1]) +{ + T (a[0]); + T (a[1]); // { dg-warning "-Warray-bounds" } +} + +NOIPA void fca2 (char a[2]) +{ + T (a[0]); T (a[1]); + T (a[2]); // { dg-warning "-Warray-bounds" } +} + +NOIPA void fcas2 (char a[static 2]) +{ + T (a[0]); T (a[1]); + T (a[2]); // { dg-warning "-Warray-bounds" } +} + +NOIPA void fca3 (char a[3]) +{ + T (a[0]); T (a[1]); T (a[2]); + T (a[3]); // { dg-warning "-Warray-bounds" } +} + +NOIPA void fcas3 (char a[static 3]) +{ + T (a[0]); T (a[1]); T (a[2]); + T (a[3]); // { dg-warning "-Warray-bounds" } +} + + +NOIPA void fca1_1 (char a[1][1]) +{ + T (a[0][0]); + T (a[0][1]); // { dg-warning "-Warray-bounds" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-65.c b/gcc/testsuite/gcc.dg/Warray-bounds-65.c new file mode 100644 index 0000000..6bd50d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-65.c @@ -0,0 +1,202 @@ +/* PR middle-end/84051 - missing -Warray-bounds on an out-of-bounds access + via an array pointer + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +void sink (void*, ...); +#define T(x) sink (0, x) + +void +test_note (int (*pia3)[3]) // { dg-message "while referencing 'pia3'" } +{ + int i = 0; + T ((*pia3)[i++]); + T ((*pia3)[i++]); + T ((*pia3)[i++]); + T ((*pia3)[i++]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]'" } + T ((*pia3)[i++]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'int\\\[3]'" } + + { + /* Regrettably, the following isn't diagnosed because it's represented + the same as the possibly valid access below: + MEM[(int *)a_1(D) + 36B] = 0; */ + int *p0 = pia3[0]; + T (p0[3]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]'" "pr?????" { xfail *-*-* } } + + int *p1 = pia3[3]; + T (p1[0]); // okay + } +} + +void test_a1_cst (_Bool (*pba0)[0], char (*pca1)[1], + short (*psa2)[2], int (*pia3)[3]) +{ + T ((*pba0)[-1]); // { dg-warning "array subscript -1 is (above|outside) array bounds of '_Bool\\\[0]'" } + T ((*pba0)[0]); // { dg-warning "array subscript 0 is (above|outside) array bounds of '_Bool\\\[0]'" } + T ((*pba0)[1]); // { dg-warning "array subscript 1 is (above|outside) array bounds of '_Bool\\\[0]'" } + T ((*pba0)[2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of '_Bool\\\[0]'" } + T ((*pba0)[12]); // { dg-warning "array subscript 12 is (above|outside) array bounds of '_Bool\\\[0]'" } + + T ((*pca1)[-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of 'char\\\[1]'" } + T ((*pca1)[0]); + T ((*pca1)[1]); // { dg-warning "array subscript 1 is (above|outside) array bounds of 'char\\\[1]'" } + T ((*pca1)[2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'char\\\[1]'" } + T ((*pca1)[123]); // { dg-warning "array subscript 123 is (above|outside) array bounds of 'char\\\[1]'" } + + T ((*psa2)[-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of 'short int\\\[2]'" } + T ((*psa2)[0]); + T ((*psa2)[1]); + T ((*psa2)[2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'short int\\\[2]'" } + T ((*psa2)[1234]); // { dg-warning "array subscript 1234 is (above|outside) array bounds of 'short int\\\[2]'" } + + T ((*pia3)[-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of 'int\\\[3]'" } + T ((*pia3)[0]); + T ((*pia3)[1]); + T ((*pia3)[2]); + T ((*pia3)[3]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]'" } + T ((*pia3)[12345]); // { dg-warning "array subscript 12345 is (above|outside) array bounds of 'int\\\[3]'" } +} + + +void test_a2_cst (_Bool (*pba0_1)[0][1], char (*pca1_2)[1][2], + short (*psa2_3)[2][3], int (*pia3_4)[3][4]) +{ + T ((*pba0_1)[-1][-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[-1][0]); // { dg-warning "array subscript -1 is (above|outside) array bounds of '_Bool\\\[0]\\\[1]'" } + + T ((*pba0_1)[0][-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[0][0]); // { dg-warning "array subscript 0 is (above|outside) array bounds of '_Bool\\\[0]\\\[1]'" } + T ((*pba0_1)[0][1]); // { dg-warning "array subscript 1 is (above|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[0][2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[0][12]); // { dg-warning "array subscript 12 is (above|outside) array bounds of '_Bool\\\[1]'" } + + T ((*pba0_1)[1][-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[1][0]); // { dg-warning "array subscript 1 is (above|outside) array bounds of '_Bool\\\[0]\\\[1]'" } + T ((*pba0_1)[1][1]); // { dg-warning "array subscript 1 is (above|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[1][2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of '_Bool\\\[1]'" } + T ((*pba0_1)[1][12]); // { dg-warning "array subscript 12 is (above|outside) array bounds of '_Bool\\\[1]'" } + + + T ((*pca1_2)[0][0]); + T ((*pca1_2)[0][1]); + T ((*pca1_2)[0][2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'char\\\[2]'" } + + T ((*pca1_2)[1][0]); // { dg-warning "array subscript 1 is (above|outside) array bounds of 'char\\\[1]\\\[2]'" } + T ((*pca1_2)[1][1]); // { dg-warning "array subscript 1 is (above|outside) array bounds of 'char\\\[1]\\\[2]'" } + T ((*pca1_2)[1][2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'char\\\[2]'" } + + + T ((*psa2_3)[0][0]); + T ((*psa2_3)[0][1]); + T ((*psa2_3)[0][2]); + T ((*psa2_3)[0][3]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'short int\\\[3]'" } + + T ((*psa2_3)[1][0]); + T ((*psa2_3)[1][1]); + T ((*psa2_3)[1][2]); + T ((*psa2_3)[1][3]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'short int\\\[3]'" } + + T ((*psa2_3)[2][0]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'short int\\\[2]\\\[3]'" } + T ((*psa2_3)[2][1]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'short int\\\[2]\\\[3]'" } + T ((*psa2_3)[2][2]); // { dg-warning "array subscript 2 is (above|outside) array bounds of 'short int\\\[2]\\\[3]'" } + T ((*psa2_3)[2][3]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'short int\\\[3]'" } + + + T ((*pia3_4)[0][0]); + T ((*pia3_4)[0][1]); + T ((*pia3_4)[0][2]); + T ((*pia3_4)[0][3]); + T ((*pia3_4)[0][4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'int\\\[4]'" } + + T ((*pia3_4)[1][0]); + T ((*pia3_4)[1][1]); + T ((*pia3_4)[1][2]); + T ((*pia3_4)[1][3]); + T ((*pia3_4)[1][4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'int\\\[4]'" } + + T ((*pia3_4)[2][0]); + T ((*pia3_4)[2][1]); + T ((*pia3_4)[2][2]); + T ((*pia3_4)[2][3]); + T ((*pia3_4)[2][4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'int\\\[4]'" } + + T ((*pia3_4)[3][0]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]\\\[4]'" } + T ((*pia3_4)[3][1]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]\\\[4]'" } + T ((*pia3_4)[3][2]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]\\\[4]'" } + T ((*pia3_4)[3][3]); // { dg-warning "array subscript 3 is (above|outside) array bounds of 'int\\\[3]\\\[4]'" } + T ((*pia3_4)[3][4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'int\\\[4]'" } +} + + +typedef int IA4[4]; +typedef IA4 IA3_4[3]; + +void test_a2_var (IA3_4 *pia3_4) +{ + { + IA4 *pia4 = &(*pia3_4)[0]; + + T ((*pia4)[-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of 'IA4'" } + T ((*pia4)[0]); + T ((*pia4)[1]); + T ((*pia4)[2]); + T ((*pia4)[3]); + T ((*pia4)[4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'IA4'" } + } + + { + IA4 *pia4 = &(*pia3_4)[1]; + + T ((*pia4)[-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of 'IA4'" } + T ((*pia4)[0]); + T ((*pia4)[1]); + T ((*pia4)[2]); + T ((*pia4)[3]); + T ((*pia4)[4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'IA4'" } + } + + { + IA4 *pia4 = &(*pia3_4)[2]; + + T ((*pia4)[-1]); // { dg-warning "array subscript -1 is (below|outside) array bounds of 'IA4'" } + T ((*pia4)[0]); + T ((*pia4)[1]); + T ((*pia4)[2]); + T ((*pia4)[3]); + T ((*pia4)[4]); // { dg-warning "array subscript 4 is (above|outside) array bounds of 'IA4'" } + } + + { + IA4 *pia4 = &(*pia3_4)[3]; + + T ((*pia4)[-1]); // { dg-warning "\\\[-Warray-bounds" } + /* The following aren't diagnosed unless N itself is out of bounds + because thanks to the MEM_REF they're indistinguishable from + possibly valid accesses: + MEM[(int[4] *)pia3_4_2(D) + 48B][N]; */ + T ((*pia4)[0]); // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + T ((*pia4)[1]); // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + T ((*pia4)[2]); // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + T ((*pia4)[3]); // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } } + T ((*pia4)[4]); // { dg-warning "\\\[-Warray-bounds" } + } +} + + +struct S { IA3_4 *pia3_4; }; +typedef struct S S5[5]; +typedef S5 S5_7[7]; + +void test_s5_7 (S5_7 *ps5_7) +{ + { + S5 *ps5 = &(*ps5_7)[0]; + T ((*ps5)[0]); + T ((*(*ps5)[0].pia3_4)[0][0]); + T ((*(*ps5)[0].pia3_4)[2][3]); + T ((*(*ps5)[0].pia3_4)[2][4]); // { dg-warning "array subscript 4 is above array bounds of 'IA4'" } + + T ((*(*ps5)[1].pia3_4)[2][3]); + T ((*(*ps5)[5].pia3_4)[2][3]); // { dg-warning "array subscript 5 is above array bounds of 'S5'" } + } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-66.c b/gcc/testsuite/gcc.dg/Warray-bounds-66.c new file mode 100644 index 0000000..c61891f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-66.c @@ -0,0 +1,257 @@ +/* PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index + { dg-do compile } + { dg-options "-O2 -Wall -Wno-uninitialized -ftrack-macro-expansion=0" } + { dg-require-effective-target alloca } */ + +#include "range.h" + +typedef __INT16_TYPE__ int16_t; + +#define alloca(n) __builtin_alloca (n) + +void* calloc (size_t, size_t); +void* malloc (size_t); + +void sink (void*, ...); +#define sink(...) sink (0, __VA_ARGS__) + +#define T(x) (sink (x)) + +__attribute__ ((alloc_size (1))) void* alloc (size_t); + + +void test_alloca_cst (void) +{ + { + char *p = alloca (1); + sink (p); + T (p[0]); + T (p[1]); // { dg-warning "subscript 1 is outside array bounds of 'char\\\[1\\\]'" } + } + + { + char *p = alloca (2); + sink (p); + T (p[0]), T (p[1]); + T (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'char\\\[2\\\]'" } + } + + { + char *p = alloca (3); + sink (p); + T (p[0]), T (p[1]), T (p[2]); + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" } + } +} + + +void test_alloca_char_range (int i, unsigned n, size_t sz) +{ + { + // Be sure to exercise signed as well as unsigned arguments. + char *p = alloca (i); + sink (p); + T (p[0]), T (p[1]), T (p[12345]); + T (p[-1]); // { dg-warning "subscript -1 is outside array bounds of 'char\\\[" } + } + + { + char *p = alloca (n); + sink (p); + T (p[0]), T (p[1]), T (p[12345]); + T (p[-1]); // { dg-warning "subscript -1 is outside array bounds of 'char\\\[" } + } + + { + char *p = alloca (sz); + sink (p); + T (p[0]), T (p[1]), T (p[23456]); + T (p[-1]); // { dg-warning "subscript -1 is outside array bounds of 'char\\\[" } + } + + { + char *p = alloca (UR (0, 1)); + sink (p); + T (p[0]); + T (p[1]); // { dg-warning "subscript 1 is outside array bounds of 'char\\\[1\\\]'" } + } + + { + char *p = alloca (UR (0, 2)); + sink (p); + sink (p[0], p[1]); + sink (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'char\\\[2\\\]'" } + } + + { + char *p = alloca (UR (0, 3)); + sink (p); + T (p[0]), T (p[1]), T (p[2]); + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" } + } + + { + char *p = alloca (UR (1, 3)); + sink (p); + T (p[0]), T (p[1]), T (p[2]); + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" } + } + + { + char *p = alloca (UR (2, 3)); + sink (p); + T (p[0]), T (p[1]), T (p[2]); + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" } + } +} + + +void test_alloca_int16_range (unsigned n) +{ + int16_t *p; + { + p = alloca (n); // { dg-message "allocated by " } + sink (p); + T (p[0]), T (p[1]), T (p[12345]); + T (p[-1]); // { dg-warning "subscript -1 is outside array bounds of 'int16_t\\\[" } + } + + { + p = alloca (UR (0, 1)); // { dg-message "object of size between 0 and 1 allocated by '__builtin_alloca'" } + sink (p); + T (p[0]); // { dg-warning "subscript 'int16_t {aka short int}\\\[0\\\]' is partly outside array bounds of 'unsigned char\\\[1]'" } + T (p[1]); // { dg-warning "subscript 1 is outside array bounds of 'int16_t\\\[0]'" } + } + + { + p = alloca (UR (0, 2)); // { dg-message "object of size between 0 and 2 allocated by '__builtin_alloca'" } + sink (p); + sink (p[0]); + sink (p[1]); // { dg-warning "subscript 1 is outside array bounds of 'int16_t\\\[1]'" } + sink (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'int16_t\\\[1\\\]'" } + } + + { + p = alloca (UR (0, 3)); // { dg-message "object of size between 0 and 3 allocated by '__builtin_alloca'" } + sink (p); + T (p[0]); + T (p[1]); // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" } + T (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'int16_t\\\[1\\\]'" } + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'int16_t\\\[1\\\]'" } + } + + { + p = alloca (UR (1, 3)); // { dg-message "object of size between 1 and 3 allocated by '__builtin_alloca'" } + sink (p); + T (p[0]); + T (p[1]); // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" } + T (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'int16_t\\\[1\\\]'" } + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'int16_t\\\[1\\\]'" } + } + + { + p = alloca (UR (2, 3)); // { dg-message "object of size between 2 and 3 allocated by '__builtin_alloca'" } + sink (p); + T (p[0]); + T (p[1]); // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" } + T (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'int16_t\\\[1\\\]'" } + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'int16_t\\\[1\\\]'" } + } + + { + p = alloca (UR (3, 4)); // { dg-message "object of size between 3 and 4 allocated by '__builtin_alloca'" } + sink (p); + T (p[0]); + T (p[1]); + T (p[2]); // { dg-warning "subscript 2 is outside array bounds of 'int16_t\\\[2\\\]'" } + T (p[3]); // { dg-warning "subscript 3 is outside array bounds of 'int16_t\\\[2\\\]'" } + } +} + + +void test_vla_cst (void) +{ + int n = 1; + { + char a[n]; + sink (a); + T (a[0]); + T (a[1]); // { dg-warning "subscript 1 is (above|outside) array bounds " } + } + + { + n = 2; + char a[n]; + sink (a); + T (a[0]), T (a[1]); + T (a[2]); // { dg-warning "subscript 2 is (above|outside) array bounds " } + } + + { + n = 3; + char a[n], *p = a; + sink (p); + T (p[0]), T (p[1]), T (p[2]); + T (p[3]); // { dg-warning "subscript 3 is (above|outside) array bounds " } + } +} + + +void test_vla_char_range (int i, unsigned n, size_t sz) +{ + { + char a[i]; + sink (a); + T (a[0]), T (a[1]), T (a[12345]); + T (a[-1]); // { dg-warning "subscript -1 is (below|outside) array bounds of 'char\\\[" } + } + + { + char a[n]; + sink (a); + T (a[0]), T (a[1]), T (a[12345]); + T (a[-1]); // { dg-warning "subscript -1 is (below|outside) array bounds of 'char\\\[" } + } + + { + char a[sz]; + sink (a); + T (a[0]), T (a[1]), T (a[23456]); + T (a[-1]); // { dg-warning "subscript -1 is (below|outside) array bounds of 'char\\\[" } + } + + { + char a[UR (0, 1)]; + sink (a); + T (a[0]); + T (a[1]); // { dg-warning "subscript 1 is outside array bounds of 'char\\\[1\\\]'" "pr82608" { xfail *-*-* } } + } + + { + char a[UR (0, 2)]; + sink (a); + sink (a[0], a[1]); + sink (a[2]); // { dg-warning "subscript 2 is outside array bounds of 'char\\\[2\\\]'" "pr82608" { xfail *-*-* } } + } + + { + char a[UR (0, 3)]; + sink (a); + T (a[0]), T (a[1]), T (a[2]); + T (a[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" "pr82608" { xfail *-*-* } } + } + + { + char a[UR (1, 3)]; + sink (a); + T (a[0]), T (a[1]), T (a[2]); + T (a[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" "pr82608" { xfail *-*-* } } + } + + { + char a[UR (2, 3)]; + sink (a); + T (a[0]), T (a[1]), T (a[2]); + T (a[3]); // { dg-warning "subscript 3 is outside array bounds of 'char\\\[3\\\]'" "pr82608" { xfail *-*-* } } + } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-67.c b/gcc/testsuite/gcc.dg/Warray-bounds-67.c new file mode 100644 index 0000000..a9b9ff7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-67.c @@ -0,0 +1,36 @@ +/* Verify warnings fpr accesses to trailing one-element array members + of a struct that's a member of either a struct or a union. Both + are obviously undefined but GCC relies on these hacks so the test + verifies that -Warray-bounds doesn't trigger for it. + { do-do compile } + { dg-options "-O2 -Wall" } */ + + +typedef union tree_node *tree; + +struct tree_exp { int i; tree operands[1]; }; + +union tree_node +{ + struct tree_exp exp; +}; + +tree test_nowarn (tree t) +{ + return t->exp.operands[3]; // { dg-bogus "\\\[-Warray-bounds" } +} + + +typedef struct shrub_node *shrub; + +struct shrub_exp { int i; shrub operands[1]; }; + +struct shrub_node +{ + struct shrub_exp exp; +}; + +shrub test_warn (shrub s) +{ + return s->exp.operands[3]; // { dg-warning "\\\[-Warray-bounds" "pr96346" { xfail *-*-* } } +} diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-2.c b/gcc/testsuite/gcc.dg/Warray-parameter-2.c new file mode 100644 index 0000000..88f20e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-2.c @@ -0,0 +1,45 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + { dg-do compile } + { dg-options "-Wall" } */ + +// Reduced from Glibc. + +typedef struct FILE FILE; + +int vfprintf (FILE*, const char*, __builtin_va_list); +int vfprintf (FILE*, const char*, __builtin_va_list); // { dg-bogus "-Warray-parameter" } +int vfprintf (FILE*, const char*, __builtin_va_list); + +int vfscanf (FILE*, const char*, __builtin_va_list); +int vfscanf (FILE*, const char*, __builtin_va_list); // { dg-bogus "-Warray-parameter" } +int vfscanf (FILE*, const char*, __builtin_va_list); + + +/* Verify that mismatches in array/to pointer to va_list are still + diagnosed. */ + +int fva (__builtin_va_list); +int fva (__builtin_va_list); + +int fpva_a1 (__builtin_va_list*); +int fpva_a1 (__builtin_va_list[1]); // { dg-warning "\\\[-Warray-parameter" } + +int fpva_a_ (__builtin_va_list*); +int fpva_a_ (__builtin_va_list[]); +int fpva_a_ (__builtin_va_list*); +int fpva_a_ (__builtin_va_list[]); + +/* Also verify that a mismatch between a pointer and a one-element + array are diagnosed. This is pervasive in Glibc headers but + making an exception for it would leave no way to express + the requirement that a function take at least one argument + by reference. */ + +struct __jmp_buf_tag; +int __sigsetjmp (struct __jmp_buf_tag*, int); + +struct __jmp_buf_tag { }; +typedef struct __jmp_buf_tag jmp_buf[1]; + +int __sigsetjmp (struct __jmp_buf_tag[1], int); // { dg-warning "\\\[-Warray-parameter" } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3.c b/gcc/testsuite/gcc.dg/Warray-parameter-3.c new file mode 100644 index 0000000..cbf3e93 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3.c @@ -0,0 +1,89 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + { dg-do compile } + { dg-options "-Wall -Warray-parameter=1" } */ + +/* Verify that at level 1 mismatches in the bounds of ordinary array + parameters don't trigger -Warray-parameter. */ +void fax (int[]); +void fax (int[0]); +void fax (int[1]); +void fax (int[2]); +void fax (int[3]); + +/* Same as above but starting with an array with a specified bound. */ +void gax (int[3]); +void gax (int[2]); +void gax (int[1]); +void gax (int[0]); +void gax (int[]); + +/* Same for multidimensional arrays. */ +void fax_y (int[][3]); +void fax_y (int[0][3]); +void fax_y (int[1][3]); +void fax_y (int[2][3]); +void fax_y (int[3][3]); + +/* Same as above but starting with an array with a specified bound. */ +void gax_y (int[3][5]); +void gax_y (int[2][5]); +void gax_y (int[1][5]); +void gax_y (int[0][5]); +void gax_y (int[][5]); + +/* Exercise VLAs with a mismatch in the bound for an ordinary array. */ +void fvlax_y (int n, int[][n]); +void fvlax_y (int n, int[0][n]); +void fvlax_y (int n, int[1][n]); +void fvlax_y (int n, int[2][n]); +void fvlax_y (int n, int[3][n]); + +void fvlaxn_y (int n, int[][n]); +void fvlaxn_y (int n, int[0][n]); +void fvlaxn_y (int n, int[1][n]); +void fvlaxn_y (int n, int[2][n]); +void fvlaxn_y (int n, int[3][n]); + +void fvlaxx_y (int[][*]); +void fvlaxx_y (int[0][*]); +void fvlaxx_y (int[1][*]); +void fvlaxx_y (int[2][*]); +void fvlaxx_y (int[3][*]); + +/* Verify that mismatches in the bounds of array parameters declared + static do trigger -Warray-parameter. */ +void fas1 (int[static 1]); // { dg-message "previously declared as 'int\\\[static 1]'" } +void fas1 (int[static 2]); // { dg-warning "\\\[-Warray-parameter=" } + + +/* Also verify that -Warray-bounds doesn't trigger for ordinary array + parameters... */ +#pragma GCC optimize "2" + +__attribute__ ((noipa)) void +gca3 (char a[3]) +{ + a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3; +} + +__attribute__ ((noipa)) void +gia3 (int a[3]) +{ + a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3; +} + +/* ...but does for static arrays. */ +__attribute__ ((noipa)) void +gcas3 (char a[static 3]) +{ + a[0] = 0; a[1] = 1; a[2] = 2; + a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } +} + +__attribute__ ((noipa)) void +gias3 (int a[static 3]) +{ + a[0] = 0; a[1] = 1; a[2] = 2; + a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-4.c b/gcc/testsuite/gcc.dg/Warray-parameter-4.c new file mode 100644 index 0000000..b702d73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-4.c @@ -0,0 +1,119 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify warnings for multidimensional arrays, including mismatches + in bounds of arrays of VLAs. (Mismatches in variable bounds are + diagnosed by -Wvla-parameter.) + { dg-do compile } + { dg-options "-Wall -Warray-parameter=2" } */ + +// Verify that equivalent forms don't tigger a warning. + +typedef int IA1[1]; +typedef int IA1x_[][1]; +typedef int IA1x0[0][1]; + +void fia_x1 (int[][1]); +void fia_x1 (IA1[0]); +void fia_x1 (IA1x_); +void fia_x1 (IA1x0); +void fia_x1 (int[0][1]); +void fia_x1 (int[static 0][1]); + +// Same as above one more time. +void fia_x1 (int[][1]); +void fia_x1 (IA1[0]); +void fia_x1 (IA1x_); +void fia_x1 (IA1x0); +void fia_x1 (int[0][1]); +void fia_x1 (int[static 0][1]); + + +void fia1x1 (int[1][1]); +void fia1x1 (int[1][1]); +void fia1x1 (int[static 1][1]); + +void fia2x1 (int[2][1]); +void fia2x1 (int[2][1]); +void fia2x1 (int[static 2][1]); + +void fia1x2 (int[1][2]); +void fia1x2 (int[1][2]); +void fia1x2 (int[static 1][2]); + +void fia1x1_2x1 (int[1][1]); // { dg-message "previously declared as 'int\\\[1]\\\[1]'" } +void fia1x1_2x1 (int[2][1]); // { dg-warning "\\\[-Warray-parameter" } +void fia1x1_2x1 (int[static 1][1]); +void fia1x1_2x1 (int[static 2][1]); // { dg-warning "\\\[-Warray-parameter" } + + +void fia2x1_1x1 (int[2][1]); // { dg-message "previously declared as 'int\\\[2]\\\[1]'" } +void fia2x1_1x1 (int[1][1]); // { dg-warning "\\\[-Warray-parameter" } +void fia2x1_1x1 (int[2][1]); +void fia2x1_1x1 (int[static 1][1]); // { dg-warning "\\\[-Warray-parameter" } +void fia2x1_1x1 (int[static 2][1]); + + +extern int n1, n2; + +void fca_xn1 (char[][n1]); +void fca_xn1 (char[0][n1]); +void fca_xn1 (char[static 0][n1]); + +void fca1xn1_2xn1 (char[1][n1]); +void fca1xn1_2xn1 (char[2][n1]); // { dg-warning "\\\[-Warray-parameter" } +void fca1xn1_2xn1 (char[1][n1]); +void fca1xn1_2xn1 (char[static 1][n1]); +void fca1xn1_2xn1 (char[static 2][n1]); // { dg-warning "\\\[-Warray-parameter" } + + +/* Exercise VLAs with a mismatch in the bound for an ordinary array. */ +void fvlax_y (int n, int[][n]); +void fvlax_y (int n, int[0][n]); +void fvlax_y (int n, int[1][n]); // { dg-warning "argument 2 of type 'int\\\[1]\\\[n]' with mismatched bound" } +void fvlax_y (int n, int[2][n]); // { dg-warning "argument 2 of type 'int\\\[2]\\\[n]' with mismatched bound" } +void fvlax_y (int n, int[3][n]); // { dg-warning "argument 2 of type 'int\\\[3]\\\[n]' with mismatched bound" } + +void fvlaxn_y (int n, int[][n]); +void fvlaxn_y (int n, int[0][n]); +void fvlaxn_y (int n, int[1][n]); // { dg-warning "\\\[-Warray-parameter" } +void fvlaxn_y (int n, int[2][n]); // { dg-warning "\\\[-Warray-parameter" } +void fvlaxn_y (int n, int[3][n]); // { dg-warning "\\\[-Warray-parameter" } + +void fvlaxx_y (int[][*]); +void fvlaxx_y (int[0][*]); +void fvlaxx_y (int[1][*]); // { dg-warning "\\\[-Warray-parameter" } +void fvlaxx_y (int[2][*]); // { dg-warning "\\\[-Warray-parameter" } +void fvlaxx_y (int[3][*]); // { dg-warning "\\\[-Warray-parameter" } + + +// Verify an array of pointers to an array of function pointers. + +void ffpa7_5 (void (* (* (* [7])[5])(void))(void)); +// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[7]\\\)\\\[5]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "note" { target *-*-* } .-1 } +void ffpa7_5 (void (* (* (* [6])[5])(void))(void)); +// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[6]\\\)\\\[5]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-1 } +void ffpa7_5 (void (* (* (* [])[5])(void))(void)); +// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[]\\\)\\\[5]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-1 } +void ffpa7_5 (void (* (* (* (*))[5])(void))(void)); +// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\*\\\)\\\[5]\\\)\\\(void\\\)\\\)\\\(void\\\)' declared as a pointer" "" { target *-*-* } .-1 } + +// Same as above but with array of pointers to a VLA of function pointers. +void ffpa7_n1 (void (* (* (* [7])[n1])(void))(void)); +// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[7]\\\)\\\[n1]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "note" { target *-*-* } .-1 } +void ffpa7_n1 (void (* (* (* [8])[n1])(void))(void)); +// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[n1]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-1 } + +void ffpa9_x (void (* (* (* [9])[*])(void))(void)); +// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[9]\\\)\\\[\\\*]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "pr?????" { xfail *-*-* } .-1 } +// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[9]\\\)\\\[0]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "" { target *-*-* } .-2 } +void ffpa9_x (void (* (* (* [8])[*])(void))(void)); +// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[\\\*]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "pr?????" { xfail *-*-* } .-1 } +// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[0]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-2 } + +/* Verify a three-dimensional array of pointers to two-dimensional arrays + of pointers to function pointers. */ + +void ffpa7_5_3 (void (* (* (* (* [7])[5])[3])(void))(void)); +// { dg-message "previously declared as 'void ?\\\(\\\* ?\\\(\\\* ?\\\(\\\* ?\\\(\\\* ?\\\[7]\\\)\\\[5]\\\)\\\[3]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "note" { target *-*-* } .-1 } +void ffpa7_5_3 (void (* (* (* (* [1])[5])[3])(void))(void)); +// { dg-warning "argument 1 of type 'void ?\\\(\\\* ?\\\(\\\* ?\\\(\\\* ?\\\(\\\* ?\\\[1]\\\)\\\[5]\\\)\\\[3]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-5.c b/gcc/testsuite/gcc.dg/Warray-parameter-5.c new file mode 100644 index 0000000..6e89bf0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-5.c @@ -0,0 +1,14 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify that -Warray-parameter diagnoses mismatches in bounds of + arrays between redeclarations of the same function and with pointer + parameters pointing to those arrays. + { dg-do compile } + { dg-options "-Wall -Warray-parameter" } */ + +void fa_x (int (*)[]); // { dg-message "previously declared as 'int \\\(\\\*\\\)\\\[]'" } +void fa_x (int (*)[2]); // { dg-warning "\\\[-Warray-parameter" } +void fa_x (int (*)[2]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[2]'" } + +void fa_2 (int (*)[2]); // { dg-message "previously declared as 'int \\\(\\\*\\\)\\\[2]'" } +void fa_2 (int (*)[]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[]'" } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-6.c b/gcc/testsuite/gcc.dg/Warray-parameter-6.c new file mode 100644 index 0000000..609dac9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-6.c @@ -0,0 +1,9 @@ +/* PR c/97131 - ICE: Segmentation fault in warn_parm_ptrarray_mismatch + { dg-do compile } + { dg-options "-Wall" } */ + +struct bm { }; + +void ms (struct bm (*at)[1]) { } + +void ms (int f1) { } // { dg-error "conflicting types for 'ms'" } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-7.c b/gcc/testsuite/gcc.dg/Warray-parameter-7.c new file mode 100644 index 0000000..4863045 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-7.c @@ -0,0 +1,25 @@ +/* PR c/97206 - ICE in composite_type on declarations of a similar array types + { dg-do compile } + { dg-options "-Wall" } */ + +__attribute__((__access__(__write_only__, 1))) void +f1 (char* restrict); + +void f1 (char*); + +char a1[]; +char a1[] = { }; + + +void f2 (char[restrict]); +void f2 (char*); + +char a2[]; +char a2[] = { }; + + +void f3 (char*); +void f3 (char[const]); + +extern const char a3[]; +extern const char a3[1]; diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-8.c b/gcc/testsuite/gcc.dg/Warray-parameter-8.c new file mode 100644 index 0000000..b152702 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-8.c @@ -0,0 +1,36 @@ +/* Verify that combinations of array type qualifiers render correctly. + { dg-do compile } + { dg-options "-Warray-parameter" } */ + +void fatm (int[_Atomic 1]); // { dg-message "previously declared as 'int\\\[_Atomic 1]" } +void fatm (int[_Atomic 2]); // { dg-warning "argument 1 of type 'int\\\[_Atomic 2]' with mismatched bound" } + + +void fcst (int[const 2]); // { dg-message "previously declared as 'int\\\[const 2]" } +void fcst (int[const 3]); // { dg-warning "argument 1 of type 'int\\\[const 3]' with mismatched bound" } + + +void frst (int[restrict 3]); // { dg-message "previously declared as 'int\\\[restrict 3]" } +void frst (int[restrict 4]); // { dg-warning "argument 1 of type 'int\\\[restrict 4]' with mismatched bound" } + +void fvol (int[volatile 4]); // { dg-message "previously declared as 'int\\\[volatile 4]" } +void fvol (int[volatile 5]); // { dg-warning "argument 1 of type 'int\\\[volatile 5]' with mismatched bound" } + + +void fcr (int[const restrict 1]); // { dg-message "previously declared as 'int\\\[\(const restrict|restrict const\) 1]" } +void fcr (int[restrict volatile 2]); // { dg-warning "argument 1 of type 'int\\\[\(restrict volatile|volatile restrict\) 2]' with mismatched bound" } +void fcr (int[const restrict volatile 3]); // { dg-warning "argument 1 of type 'int\\\[const volatile restrict 3]' with mismatched bound" } + + +extern int n; + +void fcx_n (int [const 1][n]); // { dg-message "previously declared as 'int\\\[const 1]\\\[n]'" "note" } +void fcx_n (int [restrict 2][n]); // { dg-warning "argument 1 of type 'int\\\[restrict 2]\\\[n]' with mismatched bound" } + + +extern int n1, n2; + +/* The mismatch in the array bound should be diagnosed but the mismatch + in the VLA should not be without -Wvla-parameter. */ +void fc3_n1 (int [const 3][n1]); // { dg-message "previously declared as 'int\\\[const 3]\\\[n1]'" "note" } +void fc3_n1 (int [const 5][n2]); // { dg-warning "argument 1 of type 'int\\\[const 5]\\\[n2]' with mismatched bound" } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter.c b/gcc/testsuite/gcc.dg/Warray-parameter.c new file mode 100644 index 0000000..42be310 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter.c @@ -0,0 +1,187 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify that -Warray-parameter diagnoses mismatches in array (and + pointer) arrguments between redeclarations of the same function. + Also verify that the array/pointer argument form in a mismatched + redeclaration doesn't override the form in the initial declaration. + { dg-do compile } + { dg-options "-Wall -Warray-parameter -Wno-vla-paramater" } */ + +/* Redclarations with the same or equivalent array form should not + be dianosed. T[0] is diagnosed by -Wpedantic for being invalid + C so there's little point in also warning for the difference in + array form. */ +void f1vpp (void**); +void f1vpp (void*[]); +void f1vpp (void*[0]); + +void f1ia_ (int[]); +void f1ia_ (int[]); +void f1ia_ (int[0]); +/* Verify the unused attribute still has an effect. */ +void f1ia_ (int a[0] __attribute__ ((unused))) { } +void f1ia_ (int[]); + +void f1ia_p (int[]); +void f1ia_p (int*); +void f1ia_p (int *p __attribute__ ((unused))) { } +void f1ia_p (int[]); + +void f1p_ia (const int*); +void f1p_ia (const int[]); +void f1p_ia (const int *p __attribute__ ((unused))) { } +void f1p_ia (const int[]); + +void f1ia1 (int[1]); +void f1ia1 (int[1]); +void f1ia1 (int[2 - 1]); + +void f1ias2 (int[static 2]); +void f1ias2 (int[static 2]); +void f1ias2 (int[static 1 + 1]); +void f1ias2 (int a[static 3 - 1]) { (void)&a; } + +void f1ipa_ (int*[]); +void f1ipa_ (int*[]); +void f1ipa_ (int*[0]); + +void f1ia1_x (int[1]); // { dg-message "previously declared as 'int\\\[1]'" } +void f1ia1_x (int[]); // { dg-warning "argument 1 of type 'int\\\[]' with mismatched bound" } +void f1ia1_x (int[]); // { dg-warning "argument 1 of type 'int\\\[]' with mismatched bound" } +void f1ia1_x (int[1]); +void f1ia1_x (int[2]); // { dg-warning "argument 1 of type 'int\\\[2]' with mismatched bound" } +void f1ia1_x (int[1]); +void f1ia1_x (int[3]); // { dg-warning "argument 1 of type 'int\\\[3]' with mismatched bound" } +void f1ia1_x (int a[1] __attribute__ ((unused))) { } + + +void f1ias2_s3 (int[static 2]); // { dg-message "previously declared as 'int\\\[static 2]'" } +void f1ias2_s3 (int[static 3]); // { dg-warning "argument 1 of type 'int\\\[static 3]' with mismatched bound" } +/* Verify the unused attribute still has an effect and doesn't interfere + with the warning. */ +void f1ias2_s3 (int a[static 3] __attribute__ ((unused))) { } // { dg-warning "argument 1 of type 'int\\\[static 3]' with mismatched bound" } + + +/* Ordinary T[N] and T[static N] forms are both effectively treated + the same but strictly have different meanings so they are diagnosed. + It might be worth splitting the warning into two levels and having + only the higher level treat the ordinary form as T[static N]. */ + +void f1ia3_s4 (int[3]); // { dg-message "previously declared as 'int\\\[3]'" } +void f1ia3_s4 (int[static 4]); // { dg-warning "argument 1 of type 'int\\\[static 4]' with mismatched bound" } +void f1ia3_s4 (int[3]); + + +void f1ias4_5 (int[static 4]); // { dg-message "previously declared as 'int\\\[static 4]'" } +void f1ias4_5 (int[5]); // { dg-warning "argument 1 of type 'int\\\[5]' with mismatched bound" } +void f1ias4_5 (int[static 4]); + + +void f1ia_1 (int[]); // { dg-message "previously declared as 'int\\\[]'" } +void f1ia_1 (int[1]); // { dg-warning "argument 1 of type 'int\\\[1]' with mismatched bound" } +void f1ia_1 (int[]); + + +void f1ca_ (char[]); // { dg-message "previously declared as 'char\\\[]'" } +void f1ca_ (char[2]); // { dg-warning "argument 1 of type 'char\\\[2]' with mismatched bound" } +void f1ca_ (char[]); + + +void f1csp (const short*); // { dg-message "previously declared as 'const short int ?\\\*'" } +void f1csp (const short[3]); // { dg-warning "argument 1 of type 'const short int\\\[3]' with mismatched bound" } +void f1csp (const short*); + + +void f1ia2 (int[2]); // { dg-message "previously declared as 'int\\\[2]'" } +void f1ia2 (int[1]); // { dg-warning "argument 1 of type 'int\\\[1]' with mismatched bound" } +void f1ia2 (int[2]); + + +void f1cvla2 (const volatile long[3]); // { dg-message "previously declared as 'const volatile long int\\\[3]'" } +void f1cvla2 (const volatile long[2]); // { dg-warning "argument 1 of type 'const volatile long int\\\[2]' with mismatched bound" } +void f1cvla2 (const volatile long[3]); +void f1cvla2 (const volatile long[restrict 4]); // { dg-warning "argument 1 of type 'const volatile long int\\\[restrict 4]' with mismatched bound" } + + +void f1afa4 (_Atomic float[3]); // { dg-message "previously declared as an array '_Atomic float ?\\\[3]'" } +void f1afa4 (_Atomic float*); // { dg-warning "argument 1 of type '_Atomic float ?\\\*' declared as a pointer" } +void f1afa4 (_Atomic float[3]); + +void f1ipa1_a2 (int*[1]); // { dg-message "previously declared as 'int \\\*\\\[1]'" } +void f1ipa1_a2 (int*[2]); // { dg-warning "argument 1 of type 'int \\\*\\\[2]' with mismatched bound" } +void f1ipa1_a2 (int*[1]); + + +typedef int IAx[]; +typedef int IA1[1]; +typedef int IA2[2]; +typedef int IA3[3]; + +// The message should differentiate between the [] form and *. +void f1IAx_A1 (IAx); // { dg-message "previously declared as 'int\\\[]'" "pr?????" { xfail *-*-* } } + // { dg-message "previously declared as 'int *\\\*'" "note" { target *-*-* } .-1 } +void f1IAx_A1 (IA1); // { dg-message "argument 1 of type 'int\\\[1]' with mismatched bound" } + +void f1IA1_A2 (IA1); // { dg-message "previously declared as 'int\\\[1]'" } +void f1IA1_A2 (IA2); // { dg-warning "argument 1 of type 'int\\\[2]' with mismatched bound" } +void f1IA1_A2 (IA1); +void f1IA1_A2 (int[2]); // { dg-warning "argument 1 of type 'int\\\[2]' with mismatched bound" } + + +void f1IA1_A3 (IA1 ia1); // { dg-message "previously declared as 'int\\\[1]'" } +void f1IA1_A3 (IA3 ia3); // { dg-warning "argument 1 of type 'int\\\[3]' with mismatched bound" } +void f1IA1_A3 (IA1 ia1); + + +void f1IA2_A3 (IA2 a); // { dg-message "previously declared as 'int\\\[2]'" } +void f1IA2_A3 (IA3 a); // { dg-warning "argument 1 of type 'int\\\[3]' with mismatched bound" } +void f1IA2_A3 (IA2 a); + + +// Verify multiple array arguments. + +void f2a2_a3_3_3 (int[2], int[3]); // { dg-message "previously declared as 'int\\\[2]'" } +void f2a2_a3_3_3 (int[2], int[3]); +void f2a2_a3_3_3 (int[3], int[3]); // { dg-warning "argument 1 of type 'int\\\[3]' with mismatched bound" } + + +void f2a2_a3_2_4 (int[2], int[3]); // { dg-message "previously declared as 'int\\\[3]'" } +void f2a2_a3_2_4 (int[2], int[4]); // { dg-warning "argument 2 of type 'int\\\[4]' with mismatched bound" } + + +/* Verify that pointers to arrays and arrays of arrays are differentiated + the same way as pointers and arrays of other types. */ +typedef IA1 *PA1; + +void fpia1 (IA1*); // { dg-message "previously declared as 'int ?\\(\\\*\\)\\\[1]'" } +void fpia1 (IA1[1]); // { dg-warning "argument 1 of type 'int\\\[1]\\\[1]' with mismatched bound" } +void fpia1 (PA1); +void fpia1 (int(*)[1]); +void fpia1 (int[][1]); + +void f1vpa1 (void*[][1]); +void f1vpa1 (void*[0][1]); + +/* Verify arrays of pointers. */ +void vaip1 (int (*[3])); // { dg-message "previously declared as 'int *\\\*\\\[3]'" } +void vaip1 (int (*[5])); // { dg-warning "argument 1 of type 'int *\\\*\\\[5]' with mismatched bound" } +void vaip1 (int (*[3])); +void vaip1 (int (*[])); // { dg-warning "argument 1 of type 'int *\\\*\\\[]' with mismatched bound" } +void vaip1 (int (*[3])); + +/* Verify that attributes with arrays don't cause unwanted warnings and + don't suppress intended ones. */ + +#define ALIGN(N)__attribute__ ((aligned (__alignof__ (char[N])))) + +void fatipa2 (int (* ALIGN (3)[2])); // { dg-message "previously declared as 'int \\\*\\\[2]'" } +void fatipa2 (int (* ALIGN (4)[2])); +void fatipa2 (int (* ALIGN (5)[2])); +void fatipa2 (int (* ALIGN (7)[3])); // { dg-warning "argument 1 of type 'int \\\*\\\[3]' with mismatched bound" } + +void fatiap (int (* ALIGN (3))[2]); +void fatiap (int (* ALIGN (5))[2]); + + +void fatipa3 (int (* ALIGN (1) (* ALIGN (2))[3])); +void fatipa3 (int (* ALIGN (1) (* ALIGN (2))[3])); diff --git a/gcc/testsuite/gcc.dg/Wattributes-6.c b/gcc/testsuite/gcc.dg/Wattributes-6.c index d3dd22d..4ba59bf 100644 --- a/gcc/testsuite/gcc.dg/Wattributes-6.c +++ b/gcc/testsuite/gcc.dg/Wattributes-6.c @@ -21,7 +21,7 @@ PackedAligned { int i; }; struct ATTR ((aligned (2))) AlignedMemberPacked { - int ATTR ((packed)) i; + int ATTR ((packed)) i; // { dg-warning "attribute ignored" "" { target default_packed } } }; struct ATTR ((packed)) diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-16.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-16.c new file mode 100644 index 0000000..494fff9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-16.c @@ -0,0 +1,12 @@ +/* PR c/96596 - ICE on a declaration of a built-in with invalid array + argument + { dg-do compile } */ + +void __builtin_abort (int[foo]); /* { dg-error "'foo' undeclared" } */ +void __builtin_trap (int[__SIZE_MAX__]); /* { dg-error "size of unnamed array is too large" } */ +void __builtin_unreachable (int[][]); /* { dg-error "array type has incomplete element type" } */ + +void __builtin_exit (int, int[+]); /* { dg-error "expected expression before" } */ + +/* { dg-prune-output "\\\[-Wbuiltin-declaration-mismatch" } */ + diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c index f0c1ce3..56a827a 100644 --- a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c @@ -10,3 +10,6 @@ void a (void) "" /* { dg-warning "passing argument 2 of .sscanf. from incompatible pointer type" } */ ); } + +/* The invalid scanf call may also trigger: + { dg-prune-output "accessing 4 bytes in a region of size 1" } */ diff --git a/gcc/testsuite/gcc.dg/Wno-frame-address.c b/gcc/testsuite/gcc.dg/Wno-frame-address.c index 51f20b4..13c42b2 100644 --- a/gcc/testsuite/gcc.dg/Wno-frame-address.c +++ b/gcc/testsuite/gcc.dg/Wno-frame-address.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-skip-if "Cannot access arbitrary stack frames" { arm*-*-* amdgpu-*-* avr-*-* hppa*-*-* ia64-*-* visium-*-* csky-*-* msp430-*-* } } */ +/* { dg-skip-if "Cannot access arbitrary stack frames" { arm*-*-* amdgpu-*-* avr-*-* hppa*-*-* ia64-*-* visium-*-* csky-*-* msp430-*-* cris-*-* mmix-*-* } } */ /* { dg-options "-Werror" } */ /* { dg-additional-options "-mbackchain" { target { s390*-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/Wnonnull-4.c b/gcc/testsuite/gcc.dg/Wnonnull-4.c new file mode 100644 index 0000000..180a40d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wnonnull-4.c @@ -0,0 +1,173 @@ +/* PR middle-end/97188 - ICE passing a null VLA to a function expecting + at least one element + { dg-do compile } + { dg-options "-O -Wall -ftrack-macro-expansion=0" } */ + +#define INT_MAX __INT_MAX__ +#define INT_MIN (-INT_MAX - 1) + +/* Exercise passing nul to a one-dimensional VLA argument. */ + +void test_fca_n (int r_m1) +{ + extern void fca_n (int n, char[n]); // { dg-message "in a call to function 'fca_n'" "note" } + +#define T(n) fca_n (n, 0) + + int min = INT_MIN; + int max = INT_MAX; + if (r_m1 >= 0) + r_m1 = -1; + + // Verify negative bounds. + T (min); // { dg-warning "bound argument 1 value -\\d+ is negative for a variable length array argument 2 of type 'char\\\[n]'" } + T (r_m1); // { dg-warning "bound argument 1 value \\\[-\\d+, -1] is negative for a variable length array argument 2 of type 'char\\\[n]" } + T ( -1); // { dg-warning "bound argument 1 value -1 is negative for a variable length array argument 2 of type 'char\\\[n]" } + + T ( 0); + + // Verify positive bounds. + T ( 1); // { dg-warning "argument 1 of variable length array 'char\\\[n]' is null but the corresponding bound argument 2 value is 1" } + T ( 9); // { dg-warning "argument 1 of variable length array 'char\\\[n]' is null but the corresponding bound argument 2 value is 9" } + T (max); // { dg-warning "argument 1 of variable length array 'char\\\[n]' is null but the corresponding bound argument 2 value is \\d+" } +} + + +/* Exercise passing nul to an array with unspecified bound of VLAs. */ + +void test_fsa_x_n (int r_m1) +{ + extern void fsa_x_n (int n, short[][n]); // { dg-message "in a call to function 'fsa_x_n'" "note" } + +#undef T +#define T(n) fsa_x_n (n, 0) + + int min = INT_MIN; + int max = INT_MAX; + if (r_m1 >= 0) + r_m1 = -1; + + // Verify negative bounds. + T (min); // { dg-warning "bound argument 1 value -\\d+ is negative for a variable length array argument 2 of type 'short int\\\[]\\\[n]'" } + T (r_m1); // { dg-warning "bound argument 1 value \\\[-\\d+, -1] is negative for a variable length array argument 2 of type 'short int\\\[]\\\[n]" } + T ( -1); // { dg-warning "bound argument 1 value -1 is negative for a variable length array argument 2 of type 'short int\\\[]\\\[n]" } + + T ( 0); + + // Verify positive bounds. + T ( 1); // { dg-warning "argument 1 of variable length array 'short int\\\[]\\\[n]' is null but the corresponding bound argument 2 value is 1" } + T ( 9); // { dg-warning "argument 1 of variable length array 'short int\\\[]\\\[n]' is null but the corresponding bound argument 2 value is 9" } + T (max); // { dg-warning "argument 1 of variable length array 'short int\\\[]\\\[n]' is null but the corresponding bound argument 2 value is \\d+" } +} + + +/* Exercise passing nul to an array of a single VLA. */ + +void test_fia_1_n (int r_m1) +{ + extern void fia_1_n (int n, int[1][n]); // { dg-message "in a call to function 'fia_1_n'" "note" } + +#undef T +#define T(n) fia_1_n (n, 0) + + int min = INT_MIN; + int max = INT_MAX; + if (r_m1 >= 0) + r_m1 = -1; + + // Verify negative bounds. + T (min); // { dg-warning "bound argument 1 value -\\d+ is negative for a variable length array argument 2 of type 'int\\\[1]\\\[n]'" } + T (r_m1); // { dg-warning "bound argument 1 value \\\[-\\d+, -1] is negative for a variable length array argument 2 of type 'int\\\[1]\\\[n]" } + T ( -1); // { dg-warning "bound argument 1 value -1 is negative for a variable length array argument 2 of type 'int\\\[1]\\\[n]" } + + T ( 0); + + // Verify positive bounds. + T ( 1); // { dg-warning "argument 1 of variable length array 'int\\\[1]\\\[n]' is null but the corresponding bound argument 2 value is 1" } + T ( 9); // { dg-warning "argument 1 of variable length array 'int\\\[1]\\\[n]' is null but the corresponding bound argument 2 value is 9" } + T (max); // { dg-warning "argument 1 of variable length array 'int\\\[1]\\\[n]' is null but the corresponding bound argument 2 value is \\d+" } +} + + +/* Exercise passing nul to an array of three VLAs. */ + +void test_fla_3_n (int r_m1) +{ + extern void fla_3_n (int n, long[3][n]); // { dg-message "in a call to function 'fla_3_n'" "note" } + +#undef T +#define T(n) fla_3_n (n, 0) + + int min = INT_MIN; + int max = INT_MAX; + if (r_m1 >= 0) + r_m1 = -1; + + // Verify negative bounds. + T (min); // { dg-warning "bound argument 1 value -\\d+ is negative for a variable length array argument 2 of type 'long int\\\[3]\\\[n]'" } + T (r_m1); // { dg-warning "bound argument 1 value \\\[-\\d+, -1] is negative for a variable length array argument 2 of type 'long int\\\[3]\\\[n]" } + T ( -1); // { dg-warning "bound argument 1 value -1 is negative for a variable length array argument 2 of type 'long int\\\[3]\\\[n]" } + + T ( 0); + + // Verify positive bounds. + T ( 1); // { dg-warning "argument 1 of variable length array 'long int\\\[3]\\\[n]' is null but the corresponding bound argument 2 value is 1" } + T ( 9); // { dg-warning "argument 1 of variable length array 'long int\\\[3]\\\[n]' is null but the corresponding bound argument 2 value is 9" } + T (max); // { dg-warning "argument 1 of variable length array 'long int\\\[3]\\\[n]' is null but the corresponding bound argument 2 value is \\d+" } +} + + +/* Exercise passing nul to a VLA of five-element arrays. */ + +void test_fda_n_5 (int r_m1) +{ + extern void fda_n_5 (int n, double[n][5]);// { dg-message "in a call to function 'fda_n_5'" "note" } + +#undef T +#define T(n) fda_n_5 (n, 0) + + int min = INT_MIN; + int max = INT_MAX; + if (r_m1 >= 0) + r_m1 = -1; + + // Verify negative bounds. + T (min); // { dg-warning "bound argument 1 value -\\d+ is negative for a variable length array argument 2 of type 'double\\\[n]\\\[5]'" } + T (r_m1); // { dg-warning "bound argument 1 value \\\[-\\d+, -1] is negative for a variable length array argument 2 of type 'double\\\[n]\\\[5]" } + T ( -1); // { dg-warning "bound argument 1 value -1 is negative for a variable length array argument 2 of type 'double\\\[n]\\\[5]" } + + T ( 0); + + // Verify positive bounds. + T ( 1); // { dg-warning "argument 1 of variable length array 'double\\\[n]\\\[5]' is null but the corresponding bound argument 2 value is 1" } + T ( 9); // { dg-warning "argument 1 of variable length array 'double\\\[n]\\\[5]' is null but the corresponding bound argument 2 value is 9" } + T (max); // { dg-warning "argument 1 of variable length array 'double\\\[n]\\\[5]' is null but the corresponding bound argument 2 value is \\d+" } +} + + +/* Exercise passing nul to a two-dimensional VLA. */ + +void test_fca_n_n (int r_m1) +{ + extern void fca_n_n (int n, char[n][n]); // { dg-message "in a call to function 'fca_n_n'" "note" } + +#undef T +#define T(n) fca_n_n (n, 0) + + int min = INT_MIN; + int max = INT_MAX; + if (r_m1 >= 0) + r_m1 = -1; + + // Verify negative bounds. + T (min); // { dg-warning "bound argument 1 value -\\d+ is negative for a variable length array argument 2 of type 'char\\\[n]\\\[n]'" } + T (r_m1); // { dg-warning "bound argument 1 value \\\[-\\d+, -1] is negative for a variable length array argument 2 of type 'char\\\[n]\\\[n]" } + T ( -1); // { dg-warning "bound argument 1 value -1 is negative for a variable length array argument 2 of type 'char\\\[n]\\\[n]" } + + T ( 0); + + // Verify positive bounds. + T ( 1); // { dg-warning "argument 1 of variable length array 'char\\\[n]\\\[n]' is null but the corresponding bound argument 2 value is 1" } + T ( 9); // { dg-warning "argument 1 of variable length array 'char\\\[n]\\\[n]' is null but the corresponding bound argument 2 value is 9" } + T (max); // { dg-warning "argument 1 of variable length array 'char\\\[n]\\\[n]' is null but the corresponding bound argument 2 value is \\d+" } +} diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c index 0e3435c..9273690 100644 --- a/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c @@ -1,6 +1,7 @@ /* PR c/71924 - missing -Wreturn-local-addr returning alloca result { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ #define ATTR(...) __attribute__ ((__VA_ARGS__)) diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c index 6dad7af..e922888 100644 --- a/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c @@ -1,6 +1,7 @@ /* PR c/71924 - missing -Wreturn-local-addr returning alloca result { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ #define ATTR(...) __attribute__ ((__VA_ARGS__)) diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c index 0a451ef..4a3b07b 100644 --- a/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c @@ -1,6 +1,7 @@ /* PR c/71924 - missing -Wreturn-local-addr returning alloca result { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ #define ATTR(...) __attribute__ ((__VA_ARGS__)) diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c index 70138b3..844660f 100644 --- a/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c @@ -1,6 +1,7 @@ /* PR c/71924 - missing -Wreturn-local-addr returning alloca result { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c b/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c index 4d14de2..5aea89a 100644 --- a/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c +++ b/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c @@ -1,6 +1,6 @@ /* Test -Wsizeof-pointer-memaccess warnings. */ /* { dg-do compile } */ -/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow" } */ +/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread" } */ /* { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/Wstack-usage.c b/gcc/testsuite/gcc.dg/Wstack-usage.c index 4738b69..11e3a27 100644 --- a/gcc/testsuite/gcc.dg/Wstack-usage.c +++ b/gcc/testsuite/gcc.dg/Wstack-usage.c @@ -1,6 +1,7 @@ /* PR 90983/manual documents `-Wno-stack-usage` flag, but it is unrecognized { dg-do compile } - { dg-options "-Wall -Wstack-usage=123 -Wno-stack-usage" } */ + { dg-options "-Wall -Wstack-usage=123 -Wno-stack-usage" } + { dg-require-effective-target alloca } */ void f (void*); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-15.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-15.c index 12f8f9d..1907bac 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-15.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-15.c @@ -4,7 +4,8 @@ for either kind of VLAs (member and non-member). Diagnosing the accesses is the subject of pr82608. { dg-do compile } - { dg-options "-O2 -Wall -Wno-array-bounds" } */ + { dg-options "-O2 -Wall -Wno-array-bounds" } + { dg-require-effective-target alloca } */ void sink (void*); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-22.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-22.c index a81ab99..8eaaa71 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-22.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-22.c @@ -48,11 +48,18 @@ T (rindex, b + 4, '4'); // { dg-warning "missing terminating nul" "rindex" } T (stpcpy, d, a); // { dg-warning "missing terminating nul" "stpcpy" } T (stpncpy, d, a, 4); -T (stpncpy, d, a, 5); // { dg-warning "missing terminating nul" "stpncpy" } +T (stpncpy, d, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "stpncpy" } T (stpncpy, d, a, n); -T (stpncpy, d, a + n, 4); -T (stpncpy, d, a + n, 5); // { dg-warning "missing terminating nul" "stpncpy" } +/* When the offset into an unterminated array isn't known and the bound + is less than the size of the array it suggests the access may be + constrained just right. When the bound is exactly equal to the size + of the array, then the offset would have to be zero for the access to + be safe, so a warning is justified. Otherwise, the bound is too small + and the access is definitely unsafe. */ +T (stpncpy, d, a + n, 3); +T (stpncpy, d, a + n, 4); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "stpncpy" } +T (stpncpy, d, a + n, 5); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "stpncpy" } T (stpncpy, d, b, 4); T (stpncpy, d, b, 5); @@ -67,7 +74,7 @@ T (stpncpy, d, b + 3, 5); T (stpncpy, d, b + 3, n); T (stpncpy, d, b + 4, 1); -T (stpncpy, d, b + 4, 2); // { dg-warning "missing terminating nul" "stpncpy" } +T (stpncpy, d, b + 4, 2); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "stpncpy" } T (stpncpy, d, b + 4, n); /* The following might be worth warning about since it's only safe with n < 4. */ @@ -84,7 +91,7 @@ T (strcasecmp, b, b + 4); // { dg-warning "missing terminating nul" "strcasecm T (strcat, d, a); // { dg-warning "missing terminating nul" "strcat" } T (strncat, d, a, 4); -T (strncat, d, a, 5); // { dg-warning "missing terminating nul" "strncat" } +T (strncat, d, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncat" } T (strncat, d, a, n); T (strncat, d, b, n); @@ -93,7 +100,7 @@ T (strncat, d, b + 2, n); T (strncat, d, b + 3, n); T (strncat, d, b + 4, 0); T (strncat, d, b + 4, 1); -T (strncat, d, b + 4, 2); // { dg-warning "missing terminating nul" "strncat" } +T (strncat, d, b + 4, 2); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncat" } /* The following should probably trigger a warning since it's only safe when n < 2, makes little sense with n == 0, and not much more with n == 1. */ @@ -122,8 +129,8 @@ T (strncmp, s, a, 4); /* The warning below is not issued because GCC folds strncmp calls with the same arguments to zero before it checks for the missing nul. */ T (strncmp, a, a, 5); // { dg-warning "missing terminating nul" "pr92624" { xfail *-*-*} } -T (strncmp, a, s, 5); // { dg-warning "missing terminating nul" "strcmp" } -T (strncmp, s, a, 5); // { dg-warning "missing terminating nul" "strcmp" } +T (strncmp, a, s, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strcmp" } +T (strncmp, s, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strcmp" } T (strcpy, d, a); // { dg-warning "missing terminating nul" "strcpy" } @@ -136,10 +143,10 @@ T (strspn, s, a); // { dg-warning "missing terminating nul" "strcspn" T (strdup, a); // { dg-warning "missing terminating nul" "strdup" } T (strndup, a, 4); -T (strndup, a, 5); // { dg-warning "missing terminating nul" "strndup" } +T (strndup, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strndup" } T (strndup, b + 3, 2); T (strndup, b + 4, 1); -T (strndup, b + 4, 2); // { dg-warning "missing terminating nul" "strndup" } +T (strndup, b + 4, 2); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strndup" } T (strlen, a); // { dg-warning "missing terminating nul" "strlen" } @@ -161,11 +168,12 @@ T (__stpcpy_chk, d, a, -1); // { dg-warning "missing terminating nul" T (__stpncpy_chk, d, a, 4, -1); -T (__stpncpy_chk, d, a, 5, -1); // { dg-warning "missing terminating nul" "stpncpy_chk" } +T (__stpncpy_chk, d, a, 5, -1); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "stpncpy_chk" } T (__stpncpy_chk, d, a, n, -1); -T (__stpncpy_chk, d, a + n, 4, -1); -T (__stpncpy_chk, d, a + n, 5, -1); // { dg-warning "missing terminating nul" "stpncpy_chk" } +T (__stpncpy_chk, d, a + n, 3, -1); +T (__stpncpy_chk, d, a + n, 4, -1); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "stpncpy_chk" } +T (__stpncpy_chk, d, a + n, 5, -1); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "stpncpy_chk" } T (__stpncpy_chk, d, b, 4, -1); T (__stpncpy_chk, d, b, 5, -1); @@ -180,16 +188,17 @@ T (__stpncpy_chk, d, b + 3, 5, -1); T (__stpncpy_chk, d, b + 3, n, -1); T (__stpncpy_chk, d, b + 4, 1, -1); -T (__stpncpy_chk, d, b + 4, 2, -1); // { dg-warning "missing terminating nul" "stpncpy_chk" } +T (__stpncpy_chk, d, b + 4, 2, -1); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "stpncpy_chk" } T (__stpncpy_chk, d, b + 4, n, -1); T (__strncat_chk, d, a, 4, -1); -T (__strncat_chk, d, a, 5, -1); // { dg-warning "missing terminating nul" "strncat_chk" } +T (__strncat_chk, d, a, 5, -1); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncat_chk" } T (__strncat_chk, d, a, n, -1); -T (__strncat_chk, d, a + n, 4, -1); -T (__strncat_chk, d, a + n, 5, -1); // { dg-warning "missing terminating nul" "strncat_chk" } +T (__strncat_chk, d, a + n, 3, -1); +T (__strncat_chk, d, a + n, 4, -1); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "strncat_chk" } +T (__strncat_chk, d, a + n, 5, -1); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "strncat_chk" } T (__strncat_chk, d, b, 4, -1); T (__strncat_chk, d, b, 5, -1); @@ -204,16 +213,17 @@ T (__strncat_chk, d, b + 3, 5, -1); T (__strncat_chk, d, b + 3, n, -1); T (__strncat_chk, d, b + 4, 1, -1); -T (__strncat_chk, d, b + 4, 2, -1); // { dg-warning "missing terminating nul" "strncat_chk" } +T (__strncat_chk, d, b + 4, 2, -1); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncat_chk" } T (__strncat_chk, d, b + 4, n, -1); T (__strncpy_chk, d, a, 4, -1); -T (__strncpy_chk, d, a, 5, -1); // { dg-warning "missing terminating nul" "strncpy_chk" } +T (__strncpy_chk, d, a, 5, -1); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncpy_chk" } T (__strncpy_chk, d, a, n, -1); -T (__strncpy_chk, d, a + n, 4, -1); -T (__strncpy_chk, d, a + n, 5, -1); // { dg-warning "missing terminating nul" "strncpy_chk" } +T (__strncpy_chk, d, a + n, 3, -1); +T (__strncpy_chk, d, a + n, 4, -1); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "strncpy_chk" } +T (__strncpy_chk, d, a + n, 5, -1); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "strncpy_chk" } T (__strncpy_chk, d, b, 4, -1); T (__strncpy_chk, d, b, 5, -1); @@ -228,7 +238,7 @@ T (__strncpy_chk, d, b + 3, 5, -1); T (__strncpy_chk, d, b + 3, n, -1); T (__strncpy_chk, d, b + 4, 1, -1); -T (__strncpy_chk, d, b + 4, 2, -1); // { dg-warning "missing terminating nul" "strncpy" } +T (__strncpy_chk, d, b + 4, 2, -1); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncpy" } T (__strncpy_chk, d, b + 4, n, -1); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-23.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-23.c index 6d9fcb9..0da916a 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-23.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-23.c @@ -4,7 +4,8 @@ warnings are issued for calls to user-defined functions with attribute access and with non-constant out-of-bounds arguments. { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ #include "range.h" @@ -20,7 +21,7 @@ typedef __INT32_TYPE__ int32_t; /* Exercise null pointer detection. */ RDONLY (2, 1) void -rd2_1 (int, const void*); // { dg-message "in a call to function 'rd2_1' declared with attribute 'read_only \\\(2, 1\\\)" } +rd2_1 (int, const void*); // { dg-message "in a call to function 'rd2_1' declared with attribute 'access \\\(read_only, 2, 1\\\)" "note" } void test_rd2_1 (void) { @@ -39,12 +40,16 @@ void test_rd2_1 (void) { void *null = 0; - rd2_1 (SR (1, 2), null); // { dg-warning "argument 2 is null but the corresponding size argument 1 range is \\\[1, 2]" } + /* Ideally the message would say "range" for a range and "value" + for a singular value but using the same reduces the complexity + of the code and keeps down the number of messages that need to + be translated, withot sacrificing (too much) clarity. */ + rd2_1 (SR (1, 2), null); // { dg-warning "argument 2 is null but the corresponding size argument 1 range|value is \\\[1, 2]" } } } WRONLY (3, 1) void -wr3_1 (int, int, void*); // { dg-message "in a call to function 'wr3_1' declared with attribute 'write_only \\\(3, 1\\\)" } +wr3_1 (int, int, void*); // { dg-message "in a call to function 'wr3_1' declared with attribute 'access \\\(write_only, 3, 1\\\)" } void test_wr3_1 (void) { @@ -58,7 +63,7 @@ void test_wr3_1 (void) void *null = 0; - wr3_1 (SR (1, 2), 1, null); // { dg-warning "argument 3 is null but the corresponding size argument 1 range is \\\[1, 2]" } + wr3_1 (SR (1, 2), 1, null); // { dg-warning "argument 3 is null but the corresponding size argument 1 range|value is \\\[1, 2]" } } @@ -70,7 +75,7 @@ void test_wrd2_1 (int n) wr2_1 (0, 0); wr2_1 (SR (-1, 1), 0); wr2_1 (SR (0, 1), 0); - wr2_1 (SR (1, 2), 0); // { dg-warning "argument 2 is null but the corresponding size argument 1 range is \\\[1, 2]" } + wr2_1 (SR (1, 2), 0); // { dg-warning "argument 2 is null but the corresponding size argument 1 range|value is \\\[1, 2]" } /* This should probably be diagnosed but to avoid false positives caused by jump threading and such it would have to be done @@ -126,7 +131,7 @@ void test_rd1_3_wr2_4 (const void *s, void *d, int n1, int n2) rd1_3_wr2_4 (s, d, -1, 2); // { dg-warning "argument 3 value -1 is negative" } const int ir_min_m1 = SR (INT_MIN, -1); - rd1_3_wr2_4 (s, d, ir_min_m1, 2); // { dg-warning "argument 3 range \\\[-\[0-9\]+, -1] is negative" } + rd1_3_wr2_4 (s, d, ir_min_m1, 2); // { dg-warning "argument 3 range|value \\\[-\[0-9\]+, -1] is negative" } rd1_3_wr2_4 (s, d, SR (-1, 0), 2); rd1_3_wr2_4 (s, d, SR (INT_MIN, INT_MAX), 2); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-24.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-24.c index a21a1f1..049d1c6 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-24.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-24.c @@ -23,7 +23,7 @@ extern char d1[1], d2[2], d3[3]; the attribute without a size operand. */ RDONLY (1) void -rd1_int (const int32_t*); // { dg-message "in a call to function 'rd1_int' declared with attribute 'read_only \\\(1\\\)'" } +rd1_int (const int32_t*); // { dg-message "in a call to function 'rd1_int' declared with attribute 'access \\\(read_only, 1\\\)'" "note" } void test_rd1_int (void) { @@ -39,7 +39,7 @@ void test_rd1_int (void) the attribute and with non-zero size. */ RDONLY (2, 1) void -rd2_1 (int, const void*); // { dg-message "in a call to function 'rd2_1' declared with attribute 'read_only \\\(2, 1\\\)" } +rd2_1 (int, const void*); // { dg-message "in a call to function 'rd2_1' declared with attribute 'access \\\(read_only, 2, 1\\\)" "note" } void test_rd2_1 (void) { @@ -49,7 +49,7 @@ void test_rd2_1 (void) } WRONLY (3, 1) void -wr3_1 (int, int, void*); // { dg-message "in a call to function 'wr3_1' declared with attribute 'write_only \\\(3, 1\\\)" } +wr3_1 (int, int, void*); // { dg-message "in a call to function 'wr3_1' declared with attribute 'access \\\(write_only, 3, 1\\\)" "note" } void test_wr3_1 (void) { @@ -157,7 +157,7 @@ void test_rd6_1_wr5_2_rd4_3 (void) { rd6_1_wr5_2_rd4_3 (7, 2, 1, d1, d2, s3); // { dg-warning "reading 7 bytes from a region of size 3" } rd6_1_wr5_2_rd4_3 (3, 8, 1, d1, d2, s3); // { dg-warning "writing 8 bytes into a region of size 2" } - rd6_1_wr5_2_rd4_3 (3, 2, 9, d1, d2, s3); // { dg-warning "writing 9 bytes into a region of size 1" } + rd6_1_wr5_2_rd4_3 (3, 2, 9, d1, d2, s3); // { dg-warning "accessing 9 bytes in a region of size 1" } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-25.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-25.c index 109a1dd..bc60958 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-25.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-25.c @@ -1,6 +1,7 @@ /* PR middle-end/91582 - missing heap overflow detection for strcpy { dg-do compile } - { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */ + { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } + { dg-require-effective-target alloca } */ #include "range.h" diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c index 8e2cfe3..37c1ca2 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c @@ -2,7 +2,8 @@ PR middle-end/85484 - missing -Wstringop-overflow for strcpy with a string of non-const length { dg-do compile } - { dg-options "-O2 -Wall -Wno-array-bounds" } */ + { dg-options "-O2 -Wall -Wno-array-bounds" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-33.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-33.c index cb8aeb9..d4f7956 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-33.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-33.c @@ -7,7 +7,7 @@ void fcst (char *d) { char a[2] = "0"; - __builtin_strcpy (d, a + 3); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" } + __builtin_strcpy (d, a + 3); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" } } void frng (char *d, int i) @@ -17,14 +17,14 @@ void frng (char *d, int i) if (i < 3) i = 3; - __builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" } + __builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" } } void gcst (char *d) { char a[2] = "0"; - __builtin_strcpy (d, a + 2); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" } + __builtin_strcpy (d, a + 2); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" } } void grng (char *d, int i) @@ -34,7 +34,7 @@ void grng (char *d, int i) if (i < 2) i = 2; - __builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" } + __builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" } } /* { dg-prune-output "-Wuninitialized" } */ diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c index fd43f3a..a1b1039 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c @@ -112,7 +112,7 @@ void s2_warn_cstoff_cstidx (struct S2 *p) void s2_warn_varoff_cstdix (struct S2 *p, int i) { char *q = p->a + i; - q[2] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } } + q[2] = __LINE__; // { dg-warning "\\\[-Wstringop-overflow" } } void s2_warn_cstoff_varidx (struct S2 *p, int i) diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c index 339f904..46f8fed 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c @@ -185,6 +185,18 @@ void test_note (const char *s) } { + char a[1][1][2]; // { dg-message "at offset 2 into " } + strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " } + sink (a); + } + + { + char a[1][2][2]; // { dg-message "destination object" } + strncpy (a[0][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } + sink (a); + } + + { char a[1][2][2]; // { dg-message "at offset 2 into " } strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } sink (a); @@ -192,7 +204,13 @@ void test_note (const char *s) { char a[1][2][2]; // { dg-message "at offset 4 into " } - strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } + strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " } + sink (a); + } + + { + char a[2][1][2]; // { dg-message "at offset 2 into " } + strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 0 " } sink (a); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-39.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-39.c index f83646a..295a38d 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-39.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-39.c @@ -1,7 +1,8 @@ /* PR middle-end/95667 - unintended warning for memset writing across multiple members { dg-do compile } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ extern void sink (void*); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-40.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-40.c new file mode 100644 index 0000000..386c92d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-40.c @@ -0,0 +1,120 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + { dg-do compile } + { dg-options "-Wall" } */ + +typedef __INT16_TYPE__ int16_t; + +void fa2 (int16_t[2]); +void fxa2 (int16_t[2]) __attribute__ ((nonnull)); + +void fas2 (int16_t[static 2]); + +void fvla (unsigned n, int16_t[n]); + +void test_array_1_dim (void) +{ + int16_t a1[1]; + int16_t a2[2]; + int16_t i; + + fa2 (0); + fa2 (a2); + fa2 (a1); // { dg-warning "'fa2' accessing 4 bytes in a region of size 2 " } + fa2 (&i); // { dg-warning "'fa2' accessing 4 bytes in a region of size 2 " } + + fxa2 (0); // { dg-warning "\\\[-Wnonnull" } + fxa2 (a2); + fxa2 (a1); // { dg-warning "'fxa2' accessing 4 bytes in a region of size 2 " } + fxa2 (&i); // { dg-warning "'fxa2' accessing 4 bytes in a region of size 2 " } + + fas2 (0); // { dg-warning "\\\[-Wnonnull" } + fas2 (a2); + fas2 (a1); // { dg-warning "'fas2' accessing 4 bytes in a region of size 2 " } + fas2 (&i); // { dg-warning "'fas2' accessing 4 bytes in a region of size 2 " } + + fvla (1, 0); // { dg-warning "\\\[-Wnonnull" } + fvla (1, &i); + fvla (2, a2); + fvla (2, a1); // { dg-warning "'fvla' accessing 4 bytes in a region of size 2 " } + fvla (2, &i); // { dg-warning "'fvla' accessing 4 bytes in a region of size 2 " } +} + + +void fac2 (const int16_t[2]); +void fxac2 (const int16_t[2]) __attribute__ ((nonnull)); + +void facs2 (const int16_t[static 2]); + +void fvlac (unsigned n, const int16_t[n]); + +void test_const_array_1_dim (void) +{ + int16_t a1[1]; + int16_t a2[2]; + int16_t i; + + fac2 (0); + fac2 (a2); + fac2 (a1); // { dg-warning "'fac2' reading 4 bytes from a region of size 2 " } + fac2 (&i); // { dg-warning "'fac2' reading 4 bytes from a region of size 2 " } + + fxac2 (0); // { dg-warning "\\\[-Wnonnull" } + fxac2 (a2); + fxac2 (a1); // { dg-warning "'fxac2' reading 4 bytes from a region of size 2 " } + fxac2 (&i); // { dg-warning "'fxac2' reading 4 bytes from a region of size 2 " } + + facs2 (0); // { dg-warning "\\\[-Wnonnull" } + facs2 (a2); + facs2 (a1); // { dg-warning "'facs2' reading 4 bytes from a region of size 2 " } + facs2 (&i); // { dg-warning "'facs2' reading 4 bytes from a region of size 2 " } + + fvlac (1, 0); // { dg-warning "\\\[-Wnonnull" } + fvlac (1, &i); + fvlac (2, a2); + fvlac (2, a1); // { dg-warning "'fvlac' reading 4 bytes from a region of size 2 " } + fvlac (2, &i); // { dg-warning "'fvlac' reading 4 bytes from a region of size 2 " } +} + + +void fca3x5 (int16_t[3][5]); +void fcas5x7 (int16_t[static 5][7]); + +struct Snx5 { int16_t a3x5[3][5], a2x5[2][5], a1x5[1][5]; }; +struct Snx7 { int16_t a5x7[5][7], a4x7[4][7], a1x7[1][7]; }; +struct S0x7 { int x; int16_t a0x7[0][7]; }; + +void test_array_2_dim (struct Snx5 *px5, struct Snx7 *px7, struct S0x7 *p0x7) +{ + int16_t a0x5[0][5], a1x5[1][5], a2x5[2][5], a3x5[3][5], a4x5[4][5]; + + fca3x5 (a3x5); + fca3x5 (a4x5); + fca3x5 (a2x5); // { dg-warning "'fca3x5' accessing 30 bytes in a region of size 20" } + fca3x5 (a1x5); // { dg-warning "'fca3x5' accessing 30 bytes in a region of size 10" } + fca3x5 (a0x5); // { dg-warning "'fca3x5' accessing 30 bytes in a region of size 0" } + + fca3x5 (px5->a3x5); + fca3x5 (px5->a2x5); // { dg-warning "'fca3x5' accessing 30 bytes in a region of size 20" } + fca3x5 (px5->a1x5); // { dg-warning "'fca3x5' accessing 30 bytes in a region of size 10" "pr96346" { xfail *-*-* } } + + { + int16_t (*pa2x5)[5] = &a2x5[0]; + fca3x5 (pa2x5); // { dg-warning "'fca3x5' accessing 30 bytes in a region of size 10" } + ++pa2x5; + fca3x5 (pa2x5); // { dg-warning "'fca3x5' accessing 30 bytes " } + } + + int16_t a0x7[0][7], a1x7[1][7], a4x7[4][7], a5x7[5][7], a99x7[99][7]; + fcas5x7 (a99x7); + fcas5x7 (a5x7); + fcas5x7 (a4x7); // { dg-warning "'fcas5x7' accessing 70 bytes in a region of size 56" } + fcas5x7 (a1x7); // { dg-warning "'fcas5x7' accessing 70 bytes in a region of size 14" } + fcas5x7 (a0x7); // { dg-warning "'fcas5x7' accessing 70 bytes in a region of size 0" } + + fcas5x7 (px7->a5x7); + fcas5x7 (px7->a4x7); // { dg-warning "'fcas5x7' accessing 70 bytes in a region of size 56" } + fcas5x7 (px7->a1x7); // { dg-warning "'fcas5x7' accessing 70 bytes in a region of size 14" "pr96346" { xfail *-*-* } } + + fcas5x7 (p0x7->a0x7); // { dg-warning "'fcas5x7' accessing 70 bytes in a region of size 0" "pr96346" { xfail *-*-* } } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c new file mode 100644 index 0000000..9b2d2cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c @@ -0,0 +1,120 @@ +/* Verify that writes at excessive offsets into declared or allocated + objects of unknown size are diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +#define DIFF_MAX __PTRDIFF_MAX__ + +typedef __SIZE_TYPE__ size_t; + +void* malloc (size_t); +void* memcpy (void*, const void*, size_t); +void* memset (void*, int, size_t); + +void sink (void*); + + +void char_array_cst_off_cst_size (void) +{ + extern char caxcc[]; // { dg-message "at offset \\d+ into destination object 'caxcc'" } + + char *p = caxcc; + size_t idx = DIFF_MAX - 3; + + memset (p + idx, 0, 3); + sink (p); + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2" } + sink (p); + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 1" "pr?????" { xfail ilp32 } } + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 0" } + sink (p); +} + + +void char_array_var_off_cst_size (size_t idx) +{ + /* The offset is a range with a very large lower bound and an upper + bound of DIFF_MAX. There's not point in also mentioning the latter + (it wouldn't make the note any more meaningful) so verify it only + mentions the lower bound. */ + extern char caxvc[]; // { dg-message "at offset \\d+ into destination object 'caxvc'" "note" } + + char *p = caxvc; + + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } + sink (p); +} + + +void char_array_var_off_var_size (size_t idx, size_t n) +{ + extern char caxvv[]; // { dg-message "at offset \\d+ into destination object 'caxvv'" "note" } + + char *p = caxvv; + + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + if (n < 3 || 7 < n) + n = 3; + + memset (p + idx, 0, n); + sink (p); + + ++n; + memset (p + idx, 0, n); // { dg-warning "writing between 4 and 8 bytes into a region of size 3" } + sink (p); +} + + +void alloc_array_var_off_cst_size (size_t n, size_t idx) +{ + char *p = malloc (n); // { dg-message "at offset \\d+ into destination object" "note" } + + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } + sink (p); +} + + +void int_array_cst_off_cst_size (void) +{ + extern int iaxc[]; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'iaxc'" } + + int *p = iaxc; + size_t idx = DIFF_MAX / sizeof *iaxc; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } + sink (p); +} + + +void* nowarn_anti_range_1 (char *p, char *q) +{ + size_t n = q - p; + if (!n) return 0; + + char *d = __builtin_malloc (n + 1); + memcpy (d, p, n + 1); // { dg-bogus "-Wstringop-overflow" } + return d; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-42.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-42.c new file mode 100644 index 0000000..4bb22f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-42.c @@ -0,0 +1,62 @@ +/* Verify -Wstringop-overflow a with destination pointer pointing either + before the beginning or past the end of an object. + { dg-do compile } + { dg-options "-O -Wall -Wno-array-bounds -Wno-restrict" } */ + +typedef __SIZE_TYPE__ size_t; + +char* strcpy (char *, const char *); + + +extern char a[1]; + +volatile char *d; + +void cpy_si_1_max (int i, const char *s) +{ + if (i < 1) i = 1; + d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } +} + +void cpy_ui_1_max (unsigned i, const char *s) +{ + if (i < 1) i = 1; + d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" "" { xfail ilp32 } } +} + +void cpy_sl_1_max (long i, const char *s) +{ + if (i < 1) i = 1; + d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } +} + +void cpy_ul_1_max (unsigned long i, const char *s) +{ + if (i < 1) i = 1; + + d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + + /* Because of integer wraparound the offset's range is [1, 0] so + the overflow isn't diagnosed (yet). */ + d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" "" { xfail *-*-* } } +} + + +void cpy_si_min_m1 (int i, const char *s) +{ + if (i > -1) i = -1; + d = strcpy (a + i - 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i + 2, s); +} + +void cpy_sl_min_m1 (long i, const char *s) +{ + if (i > -1) i = -1; + d = strcpy (a + i - 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" } + d = strcpy (a + i + 2, s); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c new file mode 100644 index 0000000..14ab925 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-43.c @@ -0,0 +1,179 @@ +/* PR 96903 - bogus warning on memcpy at negative offset from array end + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */ + +#include "range.h" + +#define INT_MAX __INT_MAX__ +#define INT_MIN -(INT_MAX - 1) +#define UINT_MAX (2U * INT_MAX + 1) + +typedef __SIZE_TYPE__ size_t; + +void* memset (void *, int, size_t); + +void sink (void*, ...); + +extern char a11[11]; +struct S { char a11[11], b; }; +extern struct S sa11; + +#define T2(dst, off1, off2, n) do { \ + char *_p0 = dst; \ + char *_p1 = _p0 + (off1); \ + char *_p2 = _p1 + (off2); \ + memset (_p2, 0, n); \ + sink (dst, _p0, _p1, _p2); \ + } while (0); + +#define T1(dst, off, n) T2 (dst, off, 0, n) + + +void nowarn_memset_array_cst (void) +{ + char *p = &a11[11]; + + T1 (p, -11, 11); + T1 (p, -10, 10); + T1 (p, -9, 9); + T1 (p, -8, 8); + T1 (p, -3, 3); + T1 (p, -2, 2); + T1 (p, -1, 1); + T1 (p, 0, 0); + + T2 (p, -6, -5, 11); + T2 (p, -6, -4, 10); + T2 (p, -6, -3, 9); + T2 (p, -6, -2, 8); + T2 (p, -6, -1, 7); + T2 (p, -5, -6, 11); + T2 (p, -5, -5, 10); +} + +void nowarn_memset_array_rng_int (void) +{ + char *p = &a11[11]; + + int i11 = SR (11, INT_MAX); + int i10 = SR (10, INT_MAX); + int i9 = SR ( 9, INT_MAX); + int i3 = SR ( 3, INT_MAX); + int i2 = SR ( 2, INT_MAX); + int i1 = SR ( 1, INT_MAX); + int i0 = SR ( 0, INT_MAX); + + int m11 = SR (INT_MIN, -11); + int m10 = SR (INT_MIN, -10); + int m9 = SR (INT_MIN, -9); + int m3 = SR (INT_MIN, -3); + int m2 = SR (INT_MIN, -2); + int m1 = SR (INT_MIN, -1); + int m0 = SR (INT_MIN, -0); + + T1 (p, m11, i11); + T1 (p, m10, i10); + T1 (p, m9, i9); + T1 (p, m3, i3); + T1 (p, m2, i2); + T1 (p, m1, i1); + T1 (p, m0, i0); + + T1 (p, m11, i11); + T1 (p, m10, i10); + T1 (p, m9, i9); + T1 (p, m3, i3); + T1 (p, m2, i2); + T1 (p, m1, i1); + T1 (p, m0, i0); +} + + +void nowarn_memset_array_rng (void) +{ + char *p = &a11[11]; + + T2 (p, SR (-11, -10), SR ( -2, -1), UR (11, 12)); + T2 (p, SR (-10, -9), SR ( -1, 0), UR (11, 13)); + T2 (p, SR ( -9, -8), SR ( -2, -1), UR (11, 14)); + T2 (p, SR ( -8, -7), SR ( -3, -2), UR (11, 15)); + T2 (p, SR ( -7, -6), SR ( -4, -3), UR (11, 16)); + T2 (p, SR ( -6, -5), SR ( -5, -4), UR (11, 17)); + T2 (p, SR ( -5, -4), SR ( -6, -5), UR (11, 18)); + T2 (p, SR ( -4, -3), SR ( -7, -6), UR (11, 19)); + T2 (p, SR ( -3, -2), SR ( -8, -7), UR (11, INT_MAX)); + T2 (p, SR ( -2, -1), SR ( -9, -8), UR (11, UINT_MAX)); + T2 (p, SR ( -1, 0), SR (-10, -9), UR (11, DIFF_MAX)); + T2 (p, SR ( 0, 1), SR (-11, -10), UR (11, SIZE_MAX)); + + T2 (p, SR (DIFF_MIN, -10), SR (DIFF_MIN, -1), UR (10, 12)); + + T2 (p, SR (-11, -10), SR ( -3, -1), UR (10, 12)) + T2 (p, SR (-11, -10), SR ( -3, -1), UR (10, 12)) +} + + +void warn_memset_array_rng (void) +{ + char *p = &a11[11]; + size_t n11_12 = UR (11, 12); + size_t n10_12 = UR (10, 12); + + T2 (p, SR (-11, -10), SR ( -3, -2), n11_12); // { dg-warning "writing between 11 and 12 bytes into a region of size 0" } + T2 (p, SR (-11, -10), SR ( -3, -2), n10_12); // { dg-warning "writing between 10 and 12 bytes into a region of size 0" } +} + + +void nowarn_memset_anti_range (void) +{ + size_t n11 = UR (11, SIZE_MAX); + + char *p = &a11[11]; + + T1 (p, (int)SAR (INT_MIN, -12), n11); + T1 (p, (int)SAR ( -13, -13), n11); + T1 (p, (int)SAR ( -13, -12), n11); + T1 (p, (int)SAR ( -10, 1), n11); + T1 (p, (int)SAR ( -10, 11), n11); + T1 (p, (int)SAR ( -10, INT_MAX), n11); + T1 (p, (int)SAR ( -1, -1), n11); + T1 (p, (int)SAR ( -1, 0), n11); + T1 (p, (int)SAR ( -1, 11), n11); + T1 (p, (int)SAR ( -1, INT_MAX), n11); + + T1 (p, SAR (DIFF_MIN, -12), n11); + T1 (p, SAR ( -13, -13), n11); + T1 (p, SAR ( -13, -12), n11); + T1 (p, SAR ( -10, 1), n11); // { dg-bogus "-Wstringop-overflow" } + T1 (p, SAR ( -10, 11), n11); // { dg-bogus "-Wstringop-overflow" } + T1 (p, SAR ( -10, DIFF_MAX), n11); + T1 (p, SAR ( -1, -1), n11); // { dg-bogus "-Wstringop-overflow" } + T1 (p, SAR ( -1, 0), n11); // { dg-bogus "-Wstringop-overflow" } + T1 (p, SAR ( -1, 11), n11); // { dg-bogus "-Wstringop-overflow" } + T1 (p, SAR ( -1, DIFF_MAX), n11); +} + +void warn_memset_reversed_range (void) +{ + size_t n11 = UR (11, SIZE_MAX); + + char *p = &a11[11]; + + /* Since the offset is excessive, either starting before &a11[0] + ot just past &a[11], the region size in the warning should + probably be zero, but accept other sizes too. */ + T1 (p, SAR (INT_MIN, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" } + + /* The following are represented as ordinary ranges with reversed bounds + and those are handled. */ + T1 (p, SAR (INT_MIN, 11), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } + /* In ILP32 the offset in the following has no range info associated + with it. */ + T1 (p, SAR (INT_MIN, 1), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" "pr?????" { xfail ilp32 } } + T1 (p, SAR (INT_MIN, 0), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } + /* Also represented as a true anti-range. */ + T1 (p, SAR ( -12, -11), n11); // { dg-warning "writing 11 or more bytes into a region of size \\d+" } + T1 (p, SAR ( -12, -1), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } + T1 (p, SAR ( -11, 0), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } + T1 (p, SAR ( -11, 11), n11); // { dg-warning "writing 11 or more bytes into a region of size 0" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-44.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.c new file mode 100644 index 0000000..9e292a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.c @@ -0,0 +1,129 @@ +/* PR middle-end/97175 - ICE on an excessive strncpy bound + { dg-do compile } + { dg-options "-O -Wall" } */ + +int n; + +char *d; + +void sink (void*); + +/* Exercise calls with a destination of unknown size. */ + +void f0 (const void *s) +{ + if (n > 0) return; + __builtin_memcpy (d, s, n); // eliminated +} + +void f1 (const void *s) +{ + if (n > 0) return; + __builtin_memmove (d, s, n); // eliminated +} + +void f2 (void) +{ + if (n > 0) return; + __builtin_memset (d, 0, n); // eliminated +} + +void f3 (const char *s) +{ + if (n > 0) return; + __builtin_strncpy (d, s, n); // can be eliminated but isn't +} + +void f4 (const char *s) +{ + if (n > 0) return; + *d = 0; + __builtin_strncat (d, s, n); // can be eliminated but isn't +} + + +/* Exercise the same calls but with a declared destination object. */ + +void g0 (const void *s) +{ + if (n > 0) return; + char a[1]; + __builtin_memcpy (a, s, n); // eliminated + sink (a); +} + +void g1 (const void *s) +{ + if (n > 0) return; + char a[1]; + __builtin_memmove (a, s, n); // eliminated + sink (a); +} + +void g2 (void) +{ + if (n > 0) return; + char a[1]; + __builtin_memset (a, 0, n); // eliminated + sink (a); +} + +void g3 (const char *s) +{ + if (n > 0) return; + char a[1]; + __builtin_strncpy (a, s, n); // can be eliminated but isn't + sink (a); +} + +void g4 (const char *s) +{ + if (n > 0) return; + char a[1]; + *a = 0; + __builtin_strncat (a, s, n); // can be eliminated but isn't + sink (a); +} + + +void h0 (const void *s) +{ + if (n > 0) return; + d = __builtin_malloc (1); + __builtin_memcpy (d, s, n); // eliminated +} + +void h1 (const void *s) +{ + if (n > 0) return; + d = __builtin_malloc (1); + __builtin_memmove (d, s, n); // eliminated +} + +void h2 (void) +{ + if (n > 0) return; + d = __builtin_malloc (1); + __builtin_memset (d, 0, n); // eliminated +} + +void h3 (const char *s) +{ + if (n > 0) return; + d = __builtin_malloc (1); + __builtin_strncpy (d, s, n); // can be eliminated but isn't +} + +void h4 (const char *s) +{ + if (n > 0) return; + d = __builtin_malloc (1); + *d = 0; + __builtin_strncat (d, s, n); // can be eliminated but isn't +} + +/* The calls above that aren't eliminated trigger + warning: specified size between INT_MAX and SIZE_MAX exceed maximum + object size PTRDIFF_MAX + { dg-prune-output "-Wstringop-overflow" } + { dg-prune-output "-Wstringop-overread" } */ diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-44.s b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.s new file mode 100644 index 0000000..0fc73a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.s @@ -0,0 +1,271 @@ + .file "Wstringop-overflow-44.c" + .text + .p2align 4 + .globl f0 + .type f0, @function +f0: +.LFB0: + .cfi_startproc + ret + .cfi_endproc +.LFE0: + .size f0, .-f0 + .p2align 4 + .globl f1 + .type f1, @function +f1: +.LFB1: + .cfi_startproc + ret + .cfi_endproc +.LFE1: + .size f1, .-f1 + .p2align 4 + .globl f2 + .type f2, @function +f2: +.LFB2: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L12 +.L4: + ret + .p2align 4,,10 + .p2align 3 +.L12: + movslq %eax, %rdx + movq d(%rip), %rcx + testq %rdx, %rdx + je .L4 + xorl %eax, %eax +.L6: + movb $0, (%rcx,%rax) + addq $1, %rax + cmpq %rdx, %rax + jb .L6 + ret + .cfi_endproc +.LFE2: + .size f2, .-f2 + .p2align 4 + .globl f3 + .type f3, @function +f3: +.LFB3: + .cfi_startproc + movslq n(%rip), %rdx + testl %edx, %edx + jle .L15 + ret + .p2align 4,,10 + .p2align 3 +.L15: + movq %rdi, %rsi + movq d(%rip), %rdi + jmp strncpy + .cfi_endproc +.LFE3: + .size f3, .-f3 + .p2align 4 + .globl f4 + .type f4, @function +f4: +.LFB4: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L18 + ret + .p2align 4,,10 + .p2align 3 +.L18: + movq d(%rip), %rax + movq %rdi, %rsi + movb $0, (%rax) + movslq n(%rip), %rdx + movq d(%rip), %rdi + jmp strncat + .cfi_endproc +.LFE4: + .size f4, .-f4 + .p2align 4 + .globl g0 + .type g0, @function +g0: +.LFB5: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L25 + ret + .p2align 4,,10 + .p2align 3 +.L25: + subq $24, %rsp + .cfi_def_cfa_offset 32 + leaq 15(%rsp), %rdi + call sink + addq $24, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE5: + .size g0, .-g0 + .p2align 4 + .globl g1 + .type g1, @function +g1: +.LFB6: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L32 + ret + .p2align 4,,10 + .p2align 3 +.L32: + subq $24, %rsp + .cfi_def_cfa_offset 32 + leaq 15(%rsp), %rdi + call sink + addq $24, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE6: + .size g1, .-g1 + .p2align 4 + .globl g2 + .type g2, @function +g2: +.LFB7: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L45 + ret + .p2align 4,,10 + .p2align 3 +.L45: + movslq %eax, %rdx + subq $24, %rsp + .cfi_def_cfa_offset 32 + testq %rdx, %rdx + je .L36 + xorl %eax, %eax +.L35: + movb $0, 15(%rsp,%rax) + addq $1, %rax + cmpq %rdx, %rax + jb .L35 +.L36: + leaq 15(%rsp), %rdi + call sink + addq $24, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE7: + .size g2, .-g2 + .p2align 4 + .globl g3 + .type g3, @function +g3: +.LFB8: + .cfi_startproc + movslq n(%rip), %rdx + testl %edx, %edx + jle .L52 + ret + .p2align 4,,10 + .p2align 3 +.L52: + subq $24, %rsp + .cfi_def_cfa_offset 32 + movq %rdi, %rsi + leaq 15(%rsp), %rdi + call strncpy + leaq 15(%rsp), %rdi + call sink + addq $24, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE8: + .size g3, .-g3 + .p2align 4 + .globl g4 + .type g4, @function +g4: +.LFB9: + .cfi_startproc + movslq n(%rip), %rdx + testl %edx, %edx + jle .L59 + ret + .p2align 4,,10 + .p2align 3 +.L59: + subq $24, %rsp + .cfi_def_cfa_offset 32 + movq %rdi, %rsi + leaq 15(%rsp), %rdi + movb $0, 15(%rsp) + call strncat + leaq 15(%rsp), %rdi + call sink + addq $24, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE9: + .size g4, .-g4 + .p2align 4 + .globl h0 + .type h0, @function +h0: +.LFB10: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L66 + ret + .p2align 4,,10 + .p2align 3 +.L66: + subq $8, %rsp + .cfi_def_cfa_offset 16 + movl $1, %edi + call malloc + movq %rax, d(%rip) + addq $8, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE10: + .size h0, .-h0 + .p2align 4 + .globl h1 + .type h1, @function +h1: +.LFB16: + .cfi_startproc + movl n(%rip), %eax + testl %eax, %eax + jle .L73 + ret + .p2align 4,,10 + .p2align 3 +.L73: + subq $8, %rsp + .cfi_def_cfa_offset 16 + movl $1, %edi + call malloc + movq %rax, d(%rip) + addq $8, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE16: + .size h1, .-h1 diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-45.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-45.c new file mode 100644 index 0000000..112d79a --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-45.c @@ -0,0 +1,255 @@ +/* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy + Verify that out of bounds writes by built-ins to objects through pointers + returned by other built-ins are diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +#include "range.h" + +void* malloc (size_t); +void* memcpy (void*, const void*, size_t); +void* memmove (void*, const void*, size_t); +void* mempcpy (void*, const void*, size_t); + +void sink (void*, ...); + + +void nowarn_memcpy (const void *s) +{ + extern char cpy_a4[4]; + unsigned n = sizeof cpy_a4; + + void *p = cpy_a4; + p = memcpy (p, s, n); + sink (p); + memcpy (p, s, n); + sink (p); + + p = cpy_a4 + 1; + p = memcpy (p, s, n - 1); + sink (p); + memcpy (p, s, n - 1); + sink (p); + + p = cpy_a4 + 2; + p = memcpy (p, s, n - 2); + sink (p); + memcpy (p, s, n - 2); + sink (p); + + p = cpy_a4 + 3; + p = memcpy (p, s, n - 3); + sink (p); + memcpy (p, s, n - 3); + sink (p); + + p = cpy_a4 + 4; + p = memcpy (p, s, n - 4); + sink (p); + memcpy (p, s, n - 4); + sink (p); +} + + +void nowarn_memcpy_chain (const void *s) +{ + extern char cpy_a8[8]; + + char *p = cpy_a8; + + p = memcpy (p + 1, s, 7); + sink (p); + + p = memcpy (p + 2 , s, 5); + sink (p); + + p = memcpy (p + 3 , s, 2); + sink (p); + + p = memcpy (p + 1 , s, 1); + sink (p); + + p = memcpy (p - 7 , s, 8); + sink (p); + + memcpy (p + 1, s, 7); +} + + +void warn_memcpy (const void *s) +{ + extern char cpy_a5[5]; // { dg-message "destination object 'cpy_a5'" "note" } + + unsigned n = sizeof cpy_a5; + void *p = cpy_a5; + + p = memcpy (p, s, n); + sink (p); + memcpy (p, s, n + 1); // { dg-warning "writing 6 bytes into a region of size 5" } + sink (p); + + p = cpy_a5; + p = memcpy (p, s, n); + sink (p); + memcpy (p, s, n + 1); // { dg-warning "writing 6 bytes into a region of size 5" } + sink (p); + + p = cpy_a5 + 1; + p = memcpy (p, s, n - 1); + sink (p); + memcpy (p, s, n); // { dg-warning "writing 5 bytes into a region of size 4" } + sink (p); +} + + +void warn_memcpy_chain (const void *s) +{ + extern char cpy_a8[8]; // { dg-message "destination object 'cpy_a8'" "note" } + + char *p = cpy_a8; + + p = memcpy (p, s, 9); // { dg-warning "writing 9 bytes into a region of size 8" } + sink (p); + + p = memcpy (p + 2, s, 7); // { dg-warning "writing 7 bytes into a region of size 6" } + sink (p); + + p = memcpy (p + 3, s, 5); // { dg-warning "writing 5 bytes into a region of size 3" } + sink (p); + + p = memcpy (p + 3, s, 3); // { dg-warning "writing 3 bytes into a region of size 0" } + sink (p); +} + + +void nowarn_mempcpy (const void *s) +{ + extern char a4[4]; + unsigned n = sizeof a4; + + char *p = mempcpy (a4, s, n); + sink (p); + mempcpy (p - 4, s, n); + sink (p); + + p = mempcpy (a4 + 1, s, n - 1); + sink (p); + mempcpy (p - 4, s, n); + sink (p); + + p = mempcpy (a4 + 2, s, n - 2); + sink (p); + mempcpy (p - 4, s, n); + sink (p); + + p = mempcpy (a4 + 3, s, n - 3); + sink (p); + mempcpy (p - 4, s, n); + sink (p); + + p = mempcpy (a4 + 4, s, n - 4); + sink (p); + mempcpy (p - 4, s, n); + sink (p); +} + + +void nowarn_mempcpy_chain (const void *s) +{ + extern char pcpy_a8[8]; + + char *p = pcpy_a8; + + p = mempcpy (p + 1, s, 7); + sink (p); + + p = mempcpy (p - 7 , s, 7); + sink (p); + + p = mempcpy (p - 5 , s, 5); + sink (p); + + p = mempcpy (p - 3 , s, 3); + sink (p); + + p = mempcpy (p - 2 , s, 2); + sink (p); + + mempcpy (p - 1, s, 1); + sink (p); + + mempcpy (p - 8, s, 8); +} + + +void warn_mempcpy (const void *s) +{ + extern char pcpy_a5[5]; // { dg-message "destination object 'pcpy_a5'" "note" } + + char *p = pcpy_a5; + + p = mempcpy (p, s, 5); + sink (p); + mempcpy (p - 5, s, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } + sink (p); + + p = pcpy_a5; + p = mempcpy (p, s, 3); + sink (p); + mempcpy (p, s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } + sink (p); + + p = pcpy_a5 + 1; + p = mempcpy (p, s, 3); + sink (p); + mempcpy (p - 1, s, 5); // { dg-warning "writing 5 bytes into a region of size 2 " } + sink (p); +} + + +void warn_mempcpy_chain_3 (const void *s) +{ + char *p = malloc (5); // { dg-message "at offset \\\[3, 5] into destination object of size 5" "note" } + p = mempcpy (p, s, UR (1, 2)); + p = mempcpy (p, s, UR (2, 3)); + p = mempcpy (p, s, UR (3, 4)); // { dg-warning "writing between 3 and 4 bytes into a region of size 2 " } + + sink (p); +} + +void warn_mempcpy_offrng_chain_3 (const void *s) +{ + char *p = malloc (11); // { dg-message "at offset \\\[9, 11] into destination object of size 11 " "note" } + size_t r1_2 = UR (1, 2); + size_t r2_3 = r1_2 + 1; + size_t r3_4 = r2_3 + 1; + + p = mempcpy (p + r1_2, s, r1_2); + p = mempcpy (p + r2_3, s, r2_3); + p = mempcpy (p + r3_4, s, r3_4); // { dg-warning "writing between 3 and 4 bytes into a region of size 2 " } + + sink (p); +} + +void warn_mempcpy_chain_4 (const void *s) +{ + char *p = malloc (9); // { dg-message "at offset \\\[6, 9] into destination object of size 9 " "note" } + p = mempcpy (p, s, UR (1, 2)); + p = mempcpy (p, s, UR (2, 3)); + p = mempcpy (p, s, UR (3, 4)); + p = mempcpy (p, s, UR (4, 5)); // { dg-warning "writing between 4 and 5 bytes into a region of size 3 " } + + sink (p); +} + +void warn_mempcpy_chain_5 (const void *s) +{ + char *p = malloc (14); // { dg-message "at offset \\\[10, 14] into destination object of size 14 " "note" } + p = mempcpy (p, s, UR (1, 2)); + p = mempcpy (p, s, UR (2, 3)); + p = mempcpy (p, s, UR (3, 4)); + p = mempcpy (p, s, UR (4, 5)); + p = mempcpy (p, s, UR (5, 6)); // { dg-warning "writing between 5 and 6 bytes into a region of size 4 " } + + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c new file mode 100644 index 0000000..a4d78b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c @@ -0,0 +1,97 @@ +/* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy + Verify that out of bounds writes by built-ins to objects through pointers + returned by memchr() are diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +#include "range.h" + +void* malloc (size_t); +void* memchr (void*, int, size_t); +void* memset (void*, int, size_t); + +void sink (void*, ...); + +void nowarn_memchr_cst_memset_cst (const void *s) +{ + char *p = malloc (4); + sink (p); + + p = memchr (p, '1', 4); + memset (p, 0, 4); +} + +void nowarn_memchr_uint_memset_cst (const void *s, unsigned n) +{ + char *p = malloc (4); + sink (p); + + p = memchr (p, '1', n); + memset (p, 0, 4); +} + +void nowarn_memchr_sz_memset_cst (const void *s, size_t n) +{ + char *p = malloc (4); + sink (p); + + p = memchr (p, '1', n); + memset (p, 0, 4); +} + +void nowarn_memchr_anti_range_memset_cst (const void *s, size_t n) +{ + char *p = malloc (4); + sink (p); + + if (n == 0) + n = 1; + + p = memchr (p, '1', n); + memset (p, 0, 4); +} + +void warn_memchr_cst_memset_cst (const void *s) +{ + char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" } + sink (p); + + p = memchr (p, '1', 4); + memset (p, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } +} + +void warn_memchr_var_memset_cst (const void *s, unsigned n) +{ + char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" } + sink (p); + + p = memchr (p, '1', n); + memset (p, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } +} + +void warn_memchr_var_memset_range (const void *s, unsigned n) +{ + /* The offsets in the first two notes are bounded by the size of + the allocated object. The real upper bound of the offset in + the last note includes the upper bound f the offset of the pointer + returned from the previous memchr() call, but it ends up getting + constrained to the bounds of the allocated object so it's the same + as in the first two notes. The exact value probably isn't too + important. */ + char *p0 = malloc (UR (5, 7)); + // { dg-message "at offset \\\[0, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[1, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-2 } + // { dg-message "at offset \\\[2, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-3 } + + sink (p0); + char *p1 = memchr (p0, '1', n); + memset (p1, 0, UR (8, 9)); // { dg-warning "writing between 8 and 9 bytes into a region of size 7 " } + + sink (p0); + p1 = memchr (p0 + 1, '2', n); + memset (p1, 0, UR (7, 9)); // { dg-warning "writing between 7 and 9 bytes into a region of size 6 " } + + sink (p0); + char *p2 = memchr (p1 + 1, '3', n); + memset (p2, 0, UR (6, 9)); // { dg-warning "writing between 6 and 9 bytes into a region of size 5 " } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c new file mode 100644 index 0000000..02b14ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c @@ -0,0 +1,69 @@ +/* Verify that storing a bigger vector into smaller space is diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +typedef __INT16_TYPE__ int16_t; +typedef __attribute__ ((__vector_size__ (32))) char C32; + +typedef __attribute__ ((__vector_size__ (64))) int16_t I16_64; + +void sink (void*); + + +void nowarn_c32 (char c) +{ + extern char nowarn_a32[32]; + + void *p = nowarn_a32; + *(C32*)p = (C32){ c }; + sink (p); + + char a32[32]; + p = a32; + *(C32*)p = (C32){ c }; + sink (p); +} + +void warn_c32 (char c) +{ + extern char warn_a32[32]; // { dg-message "at offset 32 to object 'warn_a32' with size 32" } + + void *p = warn_a32 + 1; + *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" } + + /* Verify a local variable too. */ + char a32[32]; + p = a32 + 1; + *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" } + sink (p); +} + + +void nowarn_i16_64 (int16_t i) +{ + extern char nowarn_a64[64]; + + void *p = nowarn_a64; + I16_64 *q = (I16_64*)p; + *q = (I16_64){ i }; + + char a64[64]; + q = (I16_64*)a64; + *q = (I16_64){ i }; + sink (q); +} + +void warn_i16_64 (int16_t i) +{ + extern char warn_a64[64]; // { dg-message "at offset 128 to object 'warn_a64' with size 64" "pr97027" { xfail *-*-* } } + + void *p = warn_a64 + 1; + I16_64 *q = (I16_64*)p; + *q = (I16_64){ i }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" { xfail *-*-* } } + + char a64[64]; + p = a64 + 1; + q = (I16_64*)p; + *q = (I16_64){ i }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" { xfail *-*-* } } + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-49.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-49.c new file mode 100644 index 0000000..84b6c94 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-49.c @@ -0,0 +1,146 @@ +/* Verify the handling of anti-ranges/multi-ranges by allocation functions + and subsequent accesses. + { dg-do compile } + { dg-options "-O2" } */ + +typedef __SIZE_TYPE__ size_t; + +void* malloc (size_t); +void bzero (void*, size_t); +void* memset (void*, int, size_t); + + +/* Exercise size_t (via malloc and memset) and unsigned/signed int. */ + +__attribute__ ((alloc_size (1))) void* +alloc_int (int); + +__attribute__ ((access (write_only, 1, 2))) void +access_int (void*, int); + +__attribute__ ((alloc_size (1))) void* +alloc_uint (unsigned); + +__attribute__ ((access (write_only, 1, 2))) void +access_uint (void*, unsigned); + + +void* nowarn_malloc_memset_same_anti_range (size_t n) +{ + /* Set N to the anti-range ~[3, 3]. */ + if (n == 3) + n = 4; + void *p = malloc (n); + + /* Verify there is no warning for an access to N bytes at P. + This means the warning has to assume the value of N in the call + to alloc() is in the larger subrange [4, UINT_MAX], while in + the call to access() in [0, 3]. */ + return memset (p, 0, n); +} + +/* Same as above but with two valid ranges. */ + +void* nowarn_malloc_memset_anti_range (size_t n1, size_t n2) +{ + /* Set N1 to the anti-range ~[3, 3]. */ + if (n1 == 3) + n1 = 4; + void *p = malloc (n1); + + /* Set N2 to the anti-range ~[7, 7]. */ + if (n2 == 7) + n2 = 8; + + return memset (p, 0, n2); +} + + +void nowarn_alloc_access_same_anti_range_int (int n) +{ + /* Set N to the anti-range ~[3, 3]. */ + if (n == 3) + n = 4; + void *p = alloc_int (n); + + /* Verify there is no warning for an access to N bytes at P. + This means the warning has to assume the value of N in the call + to alloc() is in the larger subrange [4, UINT_MAX], while in + the call to access() in [0, 3]. */ + access_int (p, n); +} + +/* Same as above but with two valid ranges. */ + +void nowarn_alloc_access_anti_range_int (int n1, int n2) +{ + /* Set N1 to the anti-range ~[3, 3]. */ + if (n1 == 3) + n1 = 4; + void *p = alloc_int (n1); + + /* Set N2 to the anti-range ~[7, 7]. */ + if (n2 == 7) + n2 = 8; + + access_int (p, n2); +} + + +void nowarn_alloc_access_same_anti_range_uint (unsigned n) +{ + /* Set N to the anti-range ~[3, 3]. */ + if (n == 3) + n = 4; + void *p = alloc_uint (n); + + /* Verify there is no warning for an access to N bytes at P. + This means the warning has to assume the value of N in the call + to alloc() is in the larger subrange [4, UINT_MAX], while in + the call to access() in [0, 3]. */ + access_uint (p, n); +} + +/* Same as above but with two valid ranges. */ + +void nowarn_alloc_access_anti_range_uint (unsigned n1, unsigned n2) +{ + /* Set N1 to the anti-range ~[3, 3]. */ + if (n1 == 3) + n1 = 4; + void *p = alloc_uint (n1); + + /* Set N2 to the anti-range ~[7, 7]. */ + if (n2 == 7) + n2 = 8; + + access_uint (p, n2); +} + + +void* nowarn_malloc_anti_range_memset_range (size_t n1, size_t n2) +{ + /* Set N1 to the anti-range ~[3, 3]. */ + if (n1 == 3) + n1 = 4; + void *p = malloc (n1); + + /* Set N2 to the range [5, MAX]. */ + if (n2 < 5) + n2 = 5; + return memset (p, 0, n2); +} + +void* nowarn_malloc_range_bzero_anti_range (size_t n1, size_t n2) +{ + /* Set N1 to the anti-range ~[3, 3]. */ + if (n1 > 4) + n1 = 4; + void *p = malloc (n1); + + /* Set N2 to the range [5, MAX]. */ + if (n2 <= 3 || 5 <= n2) + n2 = 4; + bzero (p, n2); + return p; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c new file mode 100644 index 0000000..7df58e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c @@ -0,0 +1,125 @@ +/* Verify that writes at excessive offsets into objects of unknown size + pointed to by function arguments are diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +#define DIFF_MAX __PTRDIFF_MAX__ + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; + +void* memset (void*, int, size_t); + +void sink (void*); + +char* fcall (void); + +void char_ptr_cst_off_cst_size (char *p) + // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'p'" "note" { target *-*-* } .-1 } +{ + size_t idx = DIFF_MAX - 3; + + memset (p + idx, 0, 3); + sink (p); + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2" } + sink (p); + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 1" } + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 0" } +} + + +void char_ptr_var_difoff_cst_size (ptrdiff_t idx) +{ + char *p = fcall (); + /* The offset is a range with a very large lower bound and an upper + bound of DIFF_MAX. There's not point in also mentioning the latter + (it wouldn't make the note any more meaningful) so verify it only + mentions the lower bound. + { dg-message "at offset \\d+ into destination object of size \\\[0, \\d+] (allocated|returned) by 'fcall'" "note" { target *-*-* } .-5 } */ + + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } +} + + +void char_ptr_var_szoff_cst_size (size_t idx) +{ + extern char* gptr; + // { dg-message "at offset \\d+ into destination object 'gptr'" "note" { target *-*-* } .-1 } + + char *p = gptr; + + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" "" { xfail *-*-* } } + + if (idx > DIFF_MAX) + idx = DIFF_MAX; + + memset (p + idx, 0, 7); // { dg-warning "writing 7 bytes into a region of size 3" } +} + + +void char_ptr_var_difoff_var_size (char *p, ptrdiff_t idx, size_t n) + // { dg-message "at offset \\d+ into destination object 'p'" "note" { target *-*-* } .-1 } +{ + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + if (n < 3 || 7 < n) + n = 3; + + memset (p + idx, 0, n); + sink (p); + + ++n; + memset (p + idx, 0, n); // { dg-warning "writing between 4 and 8 bytes into a region of size 3" } +} + + +void char_ptr_var_szoff_var_size (char *p, size_t idx, size_t n) + // { dg-message "at offset \\\[\[1-9\]\[0-9\]+, \[1-9\]\[0-9\]+] into destination object 'p'" "note" { xfail *-*-* } .-1 } +{ + if (idx < DIFF_MAX - 3) + idx = DIFF_MAX - 3; + + if (n < 3 || 7 < n) + n = 3; + + memset (p + idx, 0, n); + sink (p); + + ++n; + /* With an unsigned offset large values are interpreted as negative + so the addition (p + idx) is effectively treated as subtraction, + making an overflow indistinguishable from a valid (if unlikely) + store. */ + memset (p + idx, 0, n); // { dg-warning "writing between 4 and 8 bytes into a region of size 3" "pr?????" { xfail *-*-* } } +} + + +void int_ptr_cst_off_cst_size (int *p) + // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'p'" "note" { target *-*-* } .-1 } +{ + size_t idx = DIFF_MAX / sizeof *p; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-51.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-51.c new file mode 100644 index 0000000..6f36643 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-51.c @@ -0,0 +1,34 @@ +/* Test case derived from Binutils/GDB's readline/readline/histexpand.c. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +char * +get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr) +{ + int si, i, j, k; + char *s; + + s = 0; + i = *iptr; + + for (si = i; str[si] && str[si] != delimiter; si++) + if (str[si] == '\\' && str[si + 1] == delimiter) + si++; + + if (si > i || is_rhs) + { + s = (char *)__builtin_malloc (si - i + 1); + for (j = 0, k = i; k < si; j++, k++) + { + /* Remove a backslash quoting the search string delimiter. */ + if (str[k] == '\\' && str[k + 1] == delimiter) + k++; + s[j] = str[k]; // { dg-bogus "-Wstringop-overflow" } + } + s[j] = '\0'; + if (lenptr) + *lenptr = j; + } + + return s; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-52.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-52.c new file mode 100644 index 0000000..a289655 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-52.c @@ -0,0 +1,62 @@ + +/* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy + Verify that writes by built-in functions to objects through pointers + returned by ordinary (non-built-int) function are assumed to point to + the beginning of objects. + { dg-do compile } + { dg-options "-O2" } */ + +#include "range.h" + +void* memcpy (void*, const void*, size_t); +void* memset (void*, int, size_t); + +void sink (void*, ...); + +extern char* arrptr[]; +extern char* ptr; +extern char* retptr (void); +struct S { char *p; }; +extern struct S retstruct (void); + +void nowarn_ptr (void) +{ + { + void *p = arrptr; + memset (p - 1, 0, 12345); // { dg-warning "\\\[-Wstringop-overflow" } + memset (p,0, 12345); + memset (p,0, DIFF_MAX - 1); + } + + { + char *p = arrptr[0]; + memset (p - 1, 0, 12345); + memset (p - 12345, 0, 12345); + memset (p - 1234, 0, DIFF_MAX - 1); + memset (p - DIFF_MAX + 1, 0, 12345); + } + + { + char *p = ptr; + memset (p - 1, 0, 12345); + memset (p - 12345, 0, 12345); + memset (p - 1234, 0, DIFF_MAX - 1); + memset (p - DIFF_MAX + 1, 0, 12345); + } + + { + char *p = retptr (); + memset (p - 1, 0, 12345); + memset (p - 12345, 0, 12345); + memset (p - 1234, 0, DIFF_MAX - 1); + memset (p - DIFF_MAX + 1, 0, 12345); + } + + { + char *p = retstruct ().p; + memset (p - 1, 0, 12345); + memset (p - 12345, 0, 12345); + memset (p - 1234, 0, DIFF_MAX - 1); + memset (p - DIFF_MAX + 1, 0, 12345); + } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-53.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-53.c new file mode 100644 index 0000000..cd8fa32 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-53.c @@ -0,0 +1,116 @@ +/* PR middle-end/96384 - bogus -Wstringop-overflow= storing into + multidimensional array with index in range + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define SHRT_MAX __SHRT_MAX__ +#define SHRT_MIN (-SHRT_MAX - 1) +#define INT_MAX __INT_MAX__ +#define INT_MIN (-INT_MAX - 1) +#define LONG_MAX __LONG_MAX__ +#define LONG_MIN (-LONG_MAX - 1) + +#define USHRT_MAX (SHRT_MAX * 2 + 1) +#define UINT_MAX ~0U +#define ULONG_MAX ~0LU + +char ca3_5_7[3][5][7]; + +void nowarn_ca_3_5_ssi (short i) +{ + if (i > SHRT_MAX - 1) + i = SHRT_MAX - 1; + + ca3_5_7[i][0][0] = __LINE__; + ca3_5_7[i][0][1] = __LINE__; + ca3_5_7[i][0][2] = __LINE__; + ca3_5_7[i][0][3] = __LINE__; + ca3_5_7[i][0][4] = __LINE__; + ca3_5_7[i][0][5] = __LINE__; + ca3_5_7[i][0][6] = __LINE__; + + ca3_5_7[i][1][0] = __LINE__; + ca3_5_7[i][1][1] = __LINE__; + ca3_5_7[i][1][2] = __LINE__; + ca3_5_7[i][1][3] = __LINE__; + ca3_5_7[i][1][4] = __LINE__; + ca3_5_7[i][1][5] = __LINE__; + ca3_5_7[i][1][6] = __LINE__; + + ca3_5_7[i][2][0] = __LINE__; + ca3_5_7[i][2][1] = __LINE__; + ca3_5_7[i][2][2] = __LINE__; + ca3_5_7[i][2][3] = __LINE__; + ca3_5_7[i][2][4] = __LINE__; + ca3_5_7[i][2][5] = __LINE__; + ca3_5_7[i][2][6] = __LINE__; + + ca3_5_7[i][3][0] = __LINE__; + ca3_5_7[i][3][1] = __LINE__; + ca3_5_7[i][3][2] = __LINE__; + ca3_5_7[i][3][3] = __LINE__; + ca3_5_7[i][3][4] = __LINE__; + ca3_5_7[i][3][5] = __LINE__; + ca3_5_7[i][3][6] = __LINE__; + + ca3_5_7[i][4][0] = __LINE__; + ca3_5_7[i][4][1] = __LINE__; + ca3_5_7[i][4][2] = __LINE__; + ca3_5_7[i][4][3] = __LINE__; + ca3_5_7[i][4][4] = __LINE__; + ca3_5_7[i][4][5] = __LINE__; + ca3_5_7[i][4][6] = __LINE__; + + ca3_5_7[1][i][5] = __LINE__; + ca3_5_7[2][3][i] = __LINE__; +} + +void nowarn_ca_3_5_usi (unsigned short i) +{ + if (i > USHRT_MAX - 1) + i = USHRT_MAX - 1; + + ca3_5_7[i][3][5] = __LINE__; + ca3_5_7[1][i][5] = __LINE__; + ca3_5_7[2][3][i] = __LINE__; +} + +void nowarn_ca_3_5_si (int i) +{ + if (i > INT_MAX - 1) + i = INT_MAX - 1; + + ca3_5_7[i][3][5] = __LINE__; + ca3_5_7[1][i][5] = __LINE__; + ca3_5_7[2][3][i] = __LINE__; +} + +void nowarn_ca_3_5_ui (unsigned i) +{ + if (i > UINT_MAX - 1) + i = UINT_MAX - 1; + + ca3_5_7[i][3][5] = __LINE__; + ca3_5_7[1][i][5] = __LINE__; + ca3_5_7[2][3][i] = __LINE__; +} + +void nowarn_ca_3_5_li (long i) +{ + if (i > LONG_MAX - 1) + i = LONG_MAX - 1; + + ca3_5_7[i][3][5] = __LINE__; + ca3_5_7[1][i][5] = __LINE__; + ca3_5_7[2][3][i] = __LINE__; +} + +void nowarn_ca_3_5_uli (unsigned long i) +{ + if (i > ULONG_MAX - 1) + i = ULONG_MAX - 1; + + ca3_5_7[i][3][5] = __LINE__; + ca3_5_7[1][i][5] = __LINE__; + ca3_5_7[2][3][i] = __LINE__; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c new file mode 100644 index 0000000..26568f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c @@ -0,0 +1,103 @@ +/* Verify that writes at excessive offsets into flexible array members + of extern or allocated objects of unknow size are diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +#define DIFF_MAX __PTRDIFF_MAX__ + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; + +void* memset (void*, int, size_t); + +void sink (void*); + +void char_flexarray_cst_off_cst_size (void) +{ + extern struct { char n, a[]; } + caxcc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'caxcc'" } + + char *p = caxcc.a; + size_t idx = DIFF_MAX - 4; + + memset (p + idx, 0, 3); + sink (p); + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2" } + sink (p); + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 1" } + + ++idx; + memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 0" } +} + + +void char_flexarray_var_off_cst_size (ptrdiff_t idx) +{ + extern struct { char n, a[]; } + caxvc; // { dg-message "destination object 'caxvc'" } + + char *p = caxvc.a; + + if (idx < DIFF_MAX - 4) + idx = DIFF_MAX - 4; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } +} + + +void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx) +{ + extern struct { char n, a[]; } + caxvv; // { dg-message "destination object 'caxvv'" } + + char *p = caxvv.a; + + if (idx < DIFF_MAX - 4) + idx = DIFF_MAX - 4; + + if (n < 3 || 7 < n) + n = 3; + + memset (p + idx, 0, n); + sink (p); + + ++n; + memset (p + idx, 0, n); // { dg-warning "writing between 4 and 8 bytes into a region of size 3" } +} + + +void alloc_array_var_off_cst_size (size_t n, ptrdiff_t idx) +{ + struct { char n, a[]; } + *p = __builtin_malloc (n); // { dg-message "at offset \\d+ into destination object" } + + if (idx < DIFF_MAX - 4) + idx = DIFF_MAX - 4; + + memset (p->a + idx, 0, 3); + sink (p); + + memset (p->a + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } +} + + +void int_array_cst_off_cst_size (void) +{ + extern struct { int n, a[]; } + iaxc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'iaxc'" } + + int *p = iaxc.a; + size_t idx = DIFF_MAX / sizeof *p - 1; + + memset (p + idx, 0, 3); + sink (p); + + memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c new file mode 100644 index 0000000..25f5b82 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c @@ -0,0 +1,97 @@ +/* Verify that offsets in "anti-ranges" are handled correctly. + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; + +void* memset (void*, int, size_t); + +void sink (void*, ...); +#define T(x) sink (x) + + +void int_range_add_sub_ (int i, int j) +{ + if (i < 1) i = 1; + if (j > -1) j = -1; + + char ca5[5]; // { dg-message "at offset \\\[1, 5]" "note" } + char *p0 = ca5; // offset + char *p1 = p0 + i; // 1-5 + char *p2 = p1 + i; // 2-5 + char *p3 = p2 + j; // 0-4 + char *p4 = p3 + j; // 0-3 + char *p5 = p4 + j; // 0-2 + char *p6 = p5 + j; // 0-1 + char *p7 = p6 + i; // 1-2 + + memset (p7, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4" } + + sink (p0, p1, p2, p3, p4, p5, p6, p7); +} + + +void ruint_arint_add (unsigned i, int j) +{ + i |= 1; // [1, UINT_MAX] + j |= 1; // [INT_MIN + 1, -1] U [1, INT_MAX] + + char a[5]; // { dg-message "at offset \\\[1, 5]" "note" } + char *p0 = a; // offset + char *p1 = p0 + i; // 1-5 + T (memset (p1, 0, 4)); + + char *p2 = p1 + j; // 0-5 + T (memset (p2, 0, 5)); + + char *p3 = p2 + i; // 1-5 + T (memset (p3, 0, 4)); + + char *p4 = p3 + j; // 0-5 + T (memset (p4, 0, 5)); + + char *p5 = p4 + i; // 1-5 + T (memset (p5, 0, 4)); + + char *p6 = p5 + j; // 0-5 + T (memset (p6, 0, 5)); + + char *p7 = p6 + i; // 1-5 + T (memset (p7, 0, 5)); // { dg-warning "writing 5 bytes into a region of size 4" "" } +} + + +void warn_ptrdiff_anti_range_add (ptrdiff_t i) +{ + i |= 1; + + char ca5[5]; // { dg-message "at offset \\\[1, 5]" "pr?????" { xfail *-*-* } } + char *p0 = ca5; // offset + char *p1 = p0 + i; // 1-5 + char *p2 = p1 + i; // 2-5 + char *p3 = p2 + i; // 3-5 + char *p4 = p3 + i; // 4-5 + char *p5 = p4 + i; // 5 + + memset (p5, 0, 5); // { dg-warning "writing 5 bytes into a region of size 0" "pr?????" { xfail *-*-* } } + + sink (p0, p1, p2, p3, p4, p5); +} + +void warn_int_anti_range (int i) +{ + i |= 1; + + char ca5[5]; // { dg-message "at offset \\\[1, 5]" "pr?????" { xfail *-*-* } } + char *p0 = ca5; // offset + char *p1 = p0 + i; // 1-5 + char *p2 = p1 + i; // 2-5 + char *p3 = p2 + i; // 3-5 + char *p4 = p3 + i; // 4-5 + char *p5 = p4 + i; // 5 + + memset (p5, 0, 5); // { dg-warning "writing 5 bytes into a region of size 0" "pr?????" { xfail *-*-* } } + + sink (p0, p1, p2, p3, p4, p5); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-9.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-9.c index 11db965..2df84b2 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-9.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-9.c @@ -63,10 +63,10 @@ void test_strncpy (void) char* test_strndup (void) { - return strndup (s, SIZE_MAX - 5); /* { dg-warning ".strndup. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overflow=\\\]" } */ + return strndup (s, SIZE_MAX - 5); /* { dg-warning ".strndup. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overread" } */ } size_t test_strnlen (void) { - return strnlen (s, SIZE_MAX - 6); /* { dg-warning ".strnlen. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overflow=\\\]" } */ + return strnlen (s, SIZE_MAX - 6); /* { dg-warning ".strnlen. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overread" } */ } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow.c b/gcc/testsuite/gcc.dg/Wstringop-overflow.c index 2c5f4f0..c615dae 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow.c @@ -51,8 +51,8 @@ void test_memcpy_array (const void *s) T (a7 + UR (8, 9), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */ T (a7 + UR (9, 10), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */ - T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */ - T (a7 + UR (DIFF_MAX, SIZE_MAX), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-*} } */ + T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */ + T (a7 + UR (DIFF_MAX, SIZE_MAX), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */ /* This is valid. */ char *d = a7 + 7; @@ -102,8 +102,8 @@ void test_strcpy_array (void) T (a7 + UR (8, 9), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */ T (a7 + UR (9, 10), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */ - T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */ - T (a7 + UR (DIFF_MAX, SIZE_MAX), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */ + T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */ + T (a7 + UR (DIFF_MAX, SIZE_MAX), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */ char *d = a7 + 7; @@ -127,6 +127,6 @@ void test_strncpy_memarray (struct MemArray *p, const void *s) T (p->a9 + UR (9, 10), s, 9); /* { dg-warning "writing 9 bytes into a region of size 0" } */ T (p->a9 + UR (10, 11), s, 9); /* { dg-warning "writing 9 bytes into a region of size 0" } */ - T (p->a9 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 1); /* { dg-warning "writing 1 byte into a region of size 0" "pr85350" { xfail *-*-* } } */ - T (p->a9 + UR (DIFF_MAX, SIZE_MAX), s, 3); /* { dg-warning "writing 3 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */ + T (p->a9 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 1); /* { dg-warning "writing 1 byte into a region of size 0" } */ + T (p->a9 + UR (DIFF_MAX, SIZE_MAX), s, 3); /* { dg-warning "writing 3 bytes into a region of size 0" } */ } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-2.c b/gcc/testsuite/gcc.dg/Wstringop-overread-2.c new file mode 100644 index 0000000..16dc06d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overread-2.c @@ -0,0 +1,117 @@ +/* Verify -Wstringop-overread is issued for reading more than the maximum + object size but not for writing. + { dg-do compile } + { dg-options "-O2 -Wno-stringop-overflow -ftrack-macro-expansion=0" } */ + +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define SIZE_MAX __SIZE_MAX__ + +#define NOIPA __attribute__ ((noipa)) + +typedef __SIZE_TYPE__ size_t; + +void* memchr (const void*, int, size_t); +int memcmp (const void*, const void*, size_t); +void* memcpy (const void*, const void*, size_t); + +int strncmp (const char*, const char*, size_t); +char* strncat (char*, const char*, size_t); +char* strncpy (char*, const char*, size_t); +size_t strnlen (const char*, size_t); + +void sink (int, ...); +#define sink(...) sink (0, __VA_ARGS__) +#define T(exp) sink (exp) + +NOIPA void test_memchr (const void *p, int x) +{ + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (memchr (p, x, dmax)); + + T (memchr (p, x, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" } + T (memchr (p, x, dmax * 2)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" } + T (memchr (p, x, smax)); // { dg-warning "\\\[-Wstringop-overread" } +} + + +NOIPA void test_memcmp (const void *p, const void *q) +{ + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (memcmp (p, q, dmax)); + + T (memcmp (p, q, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" } + T (memcmp (p, q, dmax * 2)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" } + T (memcmp (p, q, smax)); // { dg-warning "\\\[-Wstringop-overread" } +} + + +NOIPA void test_memcpy (void *p, const void *q) +{ + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (memcpy (p, q, dmax)); + + T (memcpy (p, q, dmax + 1)); // -Wstringop-overflow disabled + T (memcpy (p, q, dmax * 2)); // ditto + T (memcpy (p, q, smax)); // ditto +} + + +NOIPA void test_strncmp (const char *p, const char *q) +{ + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (strncmp (p, q, dmax)); + + T (strncmp (p, q, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "strncmp" } + T (strncmp (p, q, dmax * 2)); // { dg-warning "\\\[-Wstringop-overread" "strncmp" } + T (strncmp (p, q, smax)); // { dg-warning "\\\[-Wstringop-overread" "strncmp" } +} + +NOIPA void test_strncat (char *p, const char *q) +{ + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (strncat (p, q, dmax)); + + T (strncat (p, q, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" } + T (strncat (p, q, dmax * 2)); // { dg-warning "\\\[-Wstringop-overread" } + T (strncat (p, q, smax)); // { dg-warning "\\\[-Wstringop-overread" } +} + +NOIPA void test_strncpy (char *p, const char *q) +{ +#if 0 + /* Disabled: strncpy calls with an excissve bound trigger both + -Wstringop-overflow and, when the former option is disabled, + -Wstringop-overread. The latter should probably not trigger. */ + + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (strncpy (p, q, dmax)); + + T (strncpy (p, q, dmax + 1)); // -Wstringop-overflow disabled + T (strncpy (p, q, dmax * 2)); // ditto + T (strncpy (p, q, smax)); // ditto +#endif +} + +NOIPA void test_strnlen (const char *p) +{ + size_t dmax = PTRDIFF_MAX; + size_t smax = SIZE_MAX; + + T (strnlen (p, dmax)); + + T (strnlen (p, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" } + T (strnlen (p, dmax * 2)); // { dg-warning "\\\[-Wstringop-overread" } + T (strnlen (p, smax)); // { dg-warning "\\\[-Wstringop-overread" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-3.c b/gcc/testsuite/gcc.dg/Wstringop-overread-3.c new file mode 100644 index 0000000..6c2c6b6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overread-3.c @@ -0,0 +1,188 @@ +/* Verify that calling strndup and strnlen with an unknown bound isn't + diagnosed regardless of the size of the array and the type of the bound. + { dg-do compile } + { dg-options "-O -Wall" } */ + +#define NOIPA __attribute__ ((noipa)) + +typedef __SIZE_TYPE__ size_t; + +extern char* strndup (const char*, size_t); +extern size_t strnlen (const char*, size_t); + +/* TO DO: Passing a zero-length array to any function is almost certainly + a bug and should be diagnosed except perpaphs when the function also + takes a bound and its value is known to be zero. When this is + implemented this test will need to be adjusted. */ +extern char a0[0]; + +extern char a1[1]; + +NOIPA char* strndup_a0_si (short n) +{ + return strndup (a0, n); +} + +NOIPA char* strndup_a0_i (int n) +{ + return strndup (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a0_li (long n) +{ + return strndup (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a0_lli (long long n) +{ + return strndup (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + +NOIPA char* strndup_a0_usi (unsigned short n) +{ + return strndup (a0, n); +} + +NOIPA char* strndup_a0_ui (unsigned n) +{ + return strndup (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a0_uli (unsigned long n) +{ + return strndup (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a0_ulli (unsigned long long n) +{ + return strndup (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + + +NOIPA char* strndup_a1_si (short n) +{ + return strndup (a1, n); +} + +NOIPA char* strndup_a1_i (int n) +{ + return strndup (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a1_li (long n) +{ + return strndup (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a1_lli (long long n) +{ + return strndup (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + +NOIPA char* strndup_a1_usi (unsigned short n) +{ + return strndup (a1, n); +} + +NOIPA char* strndup_a1_ui (unsigned n) +{ + return strndup (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a1_uli (unsigned long n) +{ + return strndup (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA char* strndup_a1_ulli (unsigned long long n) +{ + return strndup (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + +NOIPA size_t strnlen_a0_si (short n) +{ + return strnlen (a0, n); +} + +NOIPA size_t strnlen_a0_i (int n) +{ + return strnlen (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a0_li (long n) +{ + return strnlen (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a0_lli (long long n) +{ + return strnlen (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + +NOIPA size_t strnlen_a0_usi (unsigned short n) +{ + return strnlen (a0, n); +} + +NOIPA size_t strnlen_a0_ui (unsigned n) +{ + return strnlen (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a0_uli (unsigned long n) +{ + return strnlen (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a0_ulli (unsigned long long n) +{ + return strnlen (a0, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + + +NOIPA size_t strnlen_a1_si (short n) +{ + return strnlen (a1, n); +} + +NOIPA size_t strnlen_a1_i (int n) +{ + return strnlen (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a1_li (long n) +{ + return strnlen (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a1_lli (long long n) +{ + return strnlen (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + + +NOIPA size_t strnlen_a1_usi (unsigned short n) +{ + return strnlen (a1, n); +} + +NOIPA size_t strnlen_a1_ui (unsigned n) +{ + return strnlen (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a1_uli (unsigned long n) +{ + return strnlen (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} + +NOIPA size_t strnlen_a1_ulli (unsigned long long n) +{ + return strnlen (a1, n); // { dg-bogus "\\\[-Wstringop-overread" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-4.c b/gcc/testsuite/gcc.dg/Wstringop-overread-4.c new file mode 100644 index 0000000..8248dad --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overread-4.c @@ -0,0 +1,58 @@ +/* Verify -Wstringop-overread with a source pointer pointing either + before the beginning or past the end of an object. + { dg-do compile } + { dg-options "-O -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +size_t strlen (const char *); + + +extern char a[1]; + +volatile size_t n; + +void len_si_1_max (int i) +{ + if (i < 1) i = 1; + n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" } +} + +void len_ui_1_max (unsigned i) +{ + if (i < 1) i = 1; + n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail ilp32 } } +} + +void len_sl_1_max (long i) +{ + if (i < 1) i = 1; + n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" } +} + +void len_ul_1_max (unsigned long i) +{ + if (i < 1) i = 1; + n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail *-*-* } } +} + + +void len_si_min_m1 (int i) +{ + if (i > -1) i = -1; + n = strlen (a + i - 1); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail lp64 } } + n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail *-*-* } } + n = strlen (a + i + 2); +} + +void len_sl_min_m1 (long i) +{ + if (i > -1) i = -1; + n = strlen (a + i - 1); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail *-*-* } } + n = strlen (a + i + 2); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-5.c b/gcc/testsuite/gcc.dg/Wstringop-overread-5.c new file mode 100644 index 0000000..b75002b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overread-5.c @@ -0,0 +1,76 @@ +/* Verify -Wstringop-overread with a source pointer pointing either + before the beginning or past the end of an object. + { dg-do compile } + { dg-options "-O -Wall -Wno-array-bounds" } */ + +typedef __SIZE_TYPE__ size_t; + +size_t strlen (const char *); + +void sink (void*, ...); + +void off_sz_or_1 (size_t i) +{ + i |= 1; + + /* Verify the offset in the notes only mentions the meaningful lower + bound and not a range with the excessive (and meaningless) upper + bound like [2, 9223372036854775807]. */ + extern char a[1]; + // { dg-message "at offset 1 into source object 'a'" "note" { target *-*-* } .-1 } + // { dg-message "at offset 2 " "note" { target *-*-* } .-2 } + + char *p1 = a + i; + char *p2 = p1 + 1; + char *p3 = p1 - 1; + + size_t n = 0; + n += strlen (p1); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n += strlen (p2); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n += strlen (p3); + + sink (p1, p2, p3, n); +} + + +void off_sz_or_2 (size_t i) +{ + i |= 2; + + extern char b[2]; + // { dg-message "at offset 2 " "note" { target *-*-* } .-1 } + // { dg-message "at offset 3 " "note" { target *-*-* } .-2 } + + char *p1 = b + i; + char *p2 = p1 + 1; + char *p3 = p1 - 1; + + size_t n = 0; + n += strlen (p1); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n += strlen (p2); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n += strlen (p3); + + sink (p1, p2, p3, n); +} + + +void off_sz_or_4 (size_t i) +{ + i |= 4; + + extern char c[3]; + // { dg-message "at offset 4 " "note" { target *-*-* } .-1 } + // { dg-message "at offset 5 " "note" { target *-*-* } .-2 } + // { dg-message "at offset 3 " "note" { target *-*-* } .-3 } + + char *p1 = c + i; + char *p2 = p1 + 1; + char *p3 = p1 - 1; + + size_t n = 0; + n += strlen (p1); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n += strlen (p2); // { dg-warning "reading 1 or more bytes from a region of size 0" } + n += strlen (p3); // { dg-warning "reading 1 or more bytes from a region of size 0" } + + sink (p1, p2, p3, n); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread.c b/gcc/testsuite/gcc.dg/Wstringop-overread.c new file mode 100644 index 0000000..0343e43 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overread.c @@ -0,0 +1,716 @@ +/* Verify -Wstringop-overread is issued appropriately. + { dg-do compile } + { dg-options "-O2 -ftrack-macro-expansion=0" } */ + +typedef __SIZE_TYPE__ size_t; + +// <libint.h> functions. + +char* gettext (const char *); + +// <stdio.h> functions. + +int puts (const char*); +int puts_unlocked (const char*); + +// <string.h> functions. + +char* strchr (const char*, int); + +int strcmp (const char*, const char*); +int strncmp (const char*, const char*, size_t); + +char* strcat (char*, const char*); +char* strcpy (char*, const char*); +char* strncpy (char*, const char*, size_t); +char* strdup (const char*); +char* strndup (const char*, size_t); + +char* strpbrk (char*, const char*); +size_t strcspn (const char*, const char*); +size_t strspn (const char*, const char*); +char* strstr (char*, const char*); + +size_t strlen (const char*); +size_t strnlen (const char*, size_t); + + +void sink (int, ...); +#define sink(...) sink (0, __VA_ARGS__) + +extern char *d; +extern char a0[0]; // { dg-message "source object 'a0'" } +extern char a1[1]; // { dg-message "source object 'a1'" } +extern char a2[2]; // { dg-message "source object 'a2'" } + +extern char b1[1]; +extern char b2[2]; +extern char bx[]; + +const char s0[0] = { }; // { dg-message "source object 's0'" } +const char s1[1] = ""; // { dg-message "source object 's1'" } +const char s2[2] = "1"; // { dg-message "source object 's2'" } + +#define T(x) sink (0, (x)) + + +void test_strcat_array (const char *s, int i, int i0) +{ + if (i0 < 0) + i0 = 0; + + T (strcat (d, a0)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, a0 + i)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, a0 + i + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + + T (strcat (d, a0 + i0)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + + T (strcat (d, a1)); + T (strcat (d, a1 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, a1 + i)); + T (strcat (d, a1 + i + 1)); + + T (strcat (d, a1 + i0)); + T (strcat (d, a1 + i0 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + + T (strcat (d, a2)); + T (strcat (d, a2 + 1)); + T (strcat (d, a2 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, a2 + i)); + T (strcat (d, a2 + i + 2)); + + T (strcat (d, a2 + i0)); + T (strcat (d, a2 + i0 + 1)); + T (strcat (d, a2 + i0 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + + // Repeat the above with the arguments reversed. + + T (strcat (a0, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + T (strcat (a0 + i, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + T (strcat (a0 + i + 1, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + + T (strcat (a0 + i0, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + + T (strcat (a1, s)); + T (strcat (a1 + 1, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + T (strcat (a1 + i, s)); + T (strcat (a1 + i + 1, s)); + + T (strcat (a1 + i0, s)); + T (strcat (a1 + i0 + 1, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + + T (strcat (a2, s)); + T (strcat (a2 + 1, s)); + T (strcat (a2 + 2, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } + T (strcat (a2 + i, s)); + T (strcat (a2 + i + 2, s)); + + T (strcat (a2 + i0, s)); + T (strcat (a2 + i0 + 1, s)); + T (strcat (a2 + i0 + 2, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" } +} + +void test_strcat_literal (int i) +{ + T (strcat (d, "")); + T (strcat (d, "" + 0)); + T (strcat (d, "" + i)); + + T (strcat (d, "1")); + T (strcat (d, "1" + 1)); + T (strcat (d, "1" + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, "1" + i)); + + T (strcat (d, "12")); + T (strcat (d, "12" + 1)); + T (strcat (d, "12" + 2)); + T (strcat (d, "12" + 3)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, "12" + i)); +} + +void test_strcat_string (int i) +{ + T (strcat (d, s0)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, s0 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, s0 + i)); // { dg-warning "'strcat' (reading 1 or more bytes from a region of size 0|argument missing terminating nul)" } + + T (strcat (d, s1)); + T (strcat (d, s1 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, s1 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, s1 + i)); + + T (strcat (d, s2)); + T (strcat (d, s2 + 1)); + T (strcat (d, s2 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, s2 + 3)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" } + T (strcat (d, s2 + i)); +} + + +void test_strcpy_array (int i, int i0) +{ + if (i0 < 0) + i0 = 0; + + T (strcpy (d, a0)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, a0 + i)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, a0 + i + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + + T (strcpy (d, a0 + i0)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + + T (strcpy (d, a1)); + T (strcpy (d, a1 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, a1 + i)); + T (strcpy (d, a1 + i + 1)); + + T (strcpy (d, a1 + i0)); + T (strcpy (d, a1 + i0 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + + T (strcpy (d, a2)); + T (strcpy (d, a2 + 1)); + T (strcpy (d, a2 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, a2 + i)); + T (strcpy (d, a2 + i + 2)); + + T (strcpy (d, a2 + i0)); + T (strcpy (d, a2 + i0 + 1)); + T (strcpy (d, a2 + i0 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } +} + +void test_strcpy_literal (int i) +{ + T (strcpy (d, "")); + T (strcpy (d, "" + 0)); + T (strcpy (d, "" + i)); + + T (strcpy (d, "1")); + T (strcpy (d, "1" + 1)); + T (strcpy (d, "1" + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, "1" + i)); + + T (strcpy (d, "12")); + T (strcpy (d, "12" + 1)); + T (strcpy (d, "12" + 2)); + T (strcpy (d, "12" + 3)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, "12" + i)); +} + +void test_strcpy_string (int i) +{ + T (strcpy (d, s0)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, s0 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, s0 + i)); // { dg-warning "'strcpy' (reading 1 or more bytes from a region of size 0|argument missing terminating nul)" } + + T (strcpy (d, s1)); + T (strcpy (d, s1 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, s1 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, s1 + i)); + + T (strcpy (d, s2)); + T (strcpy (d, s2 + 1)); + T (strcpy (d, s2 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, s2 + 3)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" } + T (strcpy (d, s2 + i)); +} + + +void test_strncpy_array (int i) +{ + T (strncpy (d, a0, 0)); + T (strncpy (d, a0, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" } + T (strncpy (d, a0 + i, 0)); + T (strncpy (d, a0 + i, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" } + + T (strncpy (d, a1, 0)); + T (strncpy (d, a1, 1)); + T (strncpy (d, a1 + 1, 0)); + T (strncpy (d, a1 + 1, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" } + T (strncpy (d, a1 + i, 0)); + T (strncpy (d, a1 + i, 1)); + T (strncpy (d, a1 + i, 2)); +} + + +void test_strncpy_literal (int i, int i0) +{ + if (i0 < 0) + i0 = 0; + + T (strncpy (d, "", 0)); + T (strncpy (d, "", 1)); + T (strncpy (d, "", 2)); + + T (strncpy (d, "" + i, 0)); + T (strncpy (d, "" + i, 1)); + T (strncpy (d, "" + i0, 1)); + T (strncpy (d, "" + i0, 1)); + + T (strncpy (d, "" + 1, 0)); + T (strncpy (d, "" + 1, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" } + + T (strncpy (d, "1", 0)); + T (strncpy (d, "1" + 1, 0)); + T (strncpy (d, "1" + 1, 1)); + T (strncpy (d, "1" + 1, 2)); + T (strncpy (d, "1" + i, 2)); + + T (strncpy (d, "1" + 2, 0)); + T (strncpy (d, "1" + 2, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" } +} + + +void test_strlen_array (int i, int i0) +{ + if (i0 < 0) + i0 = 0; + + T (strlen (a0)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + T (strlen (a0 + i)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + T (strlen (a0 + i + 1)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + + T (strlen (a0 + i0)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + + T (strlen (a1)); + T (strlen (a1 + 1)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + T (strlen (a1 + i)); + T (strlen (a1 + i + 1)); + + T (strlen (a1 + i0)); + T (strlen (a1 + i0 + 1)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + + T (strlen (a2)); + T (strlen (a2 + 1)); + T (strlen (a2 + 2)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } + T (strlen (a2 + i)); + T (strlen (a2 + i + 2)); + + T (strlen (a2 + i0)); + T (strlen (a2 + i0 + 1)); + T (strlen (a2 + i0 + 2)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" } +} + + +void test_strnlen_array (int i, int i0, unsigned n) +{ + if (i0 < 0) + i0 = 0; + + T (strnlen (a0, 0)); + T (strnlen (a0, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + T (strnlen (a0, i0)); + T (strnlen (a0, i0 + 1)); // { dg-warning "'strnlen' (reading between 1 and \[0-9\]+ bytes from a region of size 0|specified bound \\\[1, \[0-9\]+\\\] exceeds source size 0)" } + T (strnlen (a0, n)); + T (strnlen (a0 + i, 0)); + T (strnlen (a0 + i, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + T (strnlen (a0 + i, i0)); + T (strnlen (a0 + i, n)); + T (strnlen (a0 + i + 1, 0)); + T (strnlen (a0 + i + 1, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + + T (strnlen (a0 + i0, 0)); + T (strnlen (a0 + i0, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + T (strnlen (a0 + i0, n)); + + T (strnlen (a1, 0)); + T (strnlen (a1, 1)); + T (strnlen (a1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" { xfail *-*-* } } + T (strnlen (a1, n)); + + T (strnlen (a1 + 1, 0)); + T (strnlen (a1 + 1, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a1 + 1, i0)); + T (strnlen (a1 + 1, i0 + 1)); // { dg-warning "'strnlen' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strnlen (a1 + 1, n)); + T (strnlen (a1 + i, 0)); + T (strnlen (a1 + i, 1)); + T (strnlen (a1 + i, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" } + T (strnlen (a1 + i, n)); + T (strnlen (a1 + i + 1, 0)); + T (strnlen (a1 + i + 1, 1)); + T (strnlen (a1 + i + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" } + T (strnlen (a1 + i + 1, n)); + + T (strnlen (a1 + i0, 0)); + T (strnlen (a1 + i0, 1)); + T (strnlen (a1 + i0, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" } + T (strnlen (a1 + i0, n)); + T (strnlen (a1 + i0 + 1, 0)); + T (strnlen (a1 + i0 + 1, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a1 + i0 + 1, n)); + + T (strnlen (a2, 0)); + T (strnlen (a2, 1)); + T (strnlen (a2, 2)); + T (strnlen (a2, n)); + T (strnlen (a2 + 1, 0)); + T (strnlen (a2 + 1, 1)); + T (strnlen (a2 + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" { xfail *-*-* } } + T (strnlen (a2 + 1, n)); + T (strnlen (a2 + 2, 0)); + T (strnlen (a2 + 2, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a2 + 2, n)); + T (strnlen (a2 + i, 0)); + T (strnlen (a2 + i, 1)); + T (strnlen (a2 + i, 2)); + T (strnlen (a2 + i + 2, 0)); + T (strnlen (a2 + i + 2, 1)); + T (strnlen (a2 + i + 2, 2)); + T (strnlen (a2 + i + 2, n)); + + T (strnlen (a2 + i0, 0)); + T (strnlen (a2 + i0, 1)); + T (strnlen (a2 + i0, 2)); + T (strnlen (a2 + i0, 3)); // { dg-warning "'strnlen' specified bound 3 exceeds source size 2" } + T (strnlen (a2 + i0, n)); + + T (strnlen (a2 + i0 + 1, 0)); + T (strnlen (a2 + i0 + 1, 1)); + T (strnlen (a2 + i0 + 1, 2)); + T (strnlen (a2 + i0 + 1, n)); + + T (strnlen (a2 + i0 + 2, 0)); + T (strnlen (a2 + i0 + 2, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a2 + i0 + 2, i0)); + T (strnlen (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strnlen' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strnlen (a2 + i0 + 2, n)); +} + + +void test_strcmp_array (const char *s, int i) +{ + T (strcmp (a0, "")); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } } + + T (strcmp (a0, s)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" } + T (strcmp (a0 + i, s)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" } + + T (strcmp (a1, s)); + T (strcmp (a1 + 1, s)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" } + T (strcmp (a1 + i, s)); + T (strcmp (a1 + i + 1, s)); + + + // Repeat the above with the arguments reversed. + + T (strcmp ("", a0)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} } + + T (strcmp (s, a0)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" } + T (strcmp (s, a0 + i)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" } + + T (strcmp (s, a1)); + T (strcmp (s, a1 + 1)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" } + T (strcmp (s, a1 + i)); + T (strcmp (s, a1 + i + 1)); +} + +/* The number of characters read is considered to be bounded not just + by the third argument to strncmp but also by the length of the shorter + of the two strings. When the string length is unknowm, verify that + a warning is only issued for certain reading past the end but not + otherwise. */ + +void test_strncmp_array (const char *s, int i) +{ + T (strncmp (a0, a0, 0)); + + T (strncmp (a0, s, 0)); + T (strncmp (a0, s, 1)); // { dg-warning "'strncmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } } + + T (strncmp (a0, s, 2)); // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" } + T (strncmp (a1, s, 0)); + T (strncmp (a1, s, 1)); + T (strncmp (a1 + 1, s, 1)); // { dg-warning "'strncmp' reading 1 byte from a region of size 0" "pr?????" { xfail *-*-*} } + T (strncmp (a1, s, 1)); + T (strncmp (a1 + 1, s, 2)); // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" } + + T (strncmp (a2, s, 1)); + T (strncmp (a2, s, 2)); + T (strncmp (a2, s, 3)); + + T (strncmp (a2 + 1, s, 1)); + T (strncmp (a2 + 2, s, 2)); // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" } + + T (strncmp (a1, b1, 0)); + T (strncmp (a1, b1, 1)); + T (strncmp (a1, b1, 2)); // { dg-warning "'strncmp' specified bound 2 exceeds source size 1" } +} + + +void test_strncmp_literal (const char *s, int i) +{ + T (strncmp (a0, "", 0)); + T (strncmp (a0, "1", 0)); + T (strncmp (a0, "12", 0)); + + /* The calls with a bound in excess of the length of the literal are + folded early (most into strcmp) so the warning doesn't trigger. */ + T (strncmp (s, "", 0)); + + T (strncmp (s, "1", 0)); + T (strncmp (s, "1", 1)); + T (strncmp (s, "1", 2)); // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } } + + T (strncmp (s, "12", 0)); + T (strncmp (s, "12", 1)); + T (strncmp (s, "12", 2)); + T (strncmp (s, "12", 3)); // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } } + + T (strncmp (s, "123", 0)); + T (strncmp (s, "123", 1)); + T (strncmp (s, "123", 2)); + T (strncmp (s, "123", 3)); + T (strncmp (s, "123", 4)); // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } } +} + + +void test_strchr_array (int x, int i) +{ + T (strchr (a0, x)); // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" } + T (strchr (a0 + i, x)); // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" } + + T (strchr (a1, x)); + T (strchr (a1 + 1, x)); // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" } + T (strchr (a1 + i, x)); + T (strchr (a1 + i + 1, x)); +} + + +void test_strdup_array (int i) +{ + T (strdup (a0)); // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" } + T (strdup (a0 + i)); // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" } + + T (strdup (a1)); + T (strdup (a1 + 1)); // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" } + T (strdup (a1 + i)); + T (strdup (a1 + i + 1)); +} + + +void test_strndup_array (int i, int i0, unsigned n) +{ + if (i0 < 0) + i0 = 0; + + T (strndup (a0, 0)); + T (strndup (a0, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + T (strndup (a0, i0)); + T (strndup (a0, i0 + 1)); // { dg-warning "'strndup' (reading between 1 and \[0-9\]+ bytes from a region of size 0|specified bound \\\[1, \[0-9\]+\\\] exceeds source size 0)" } + T (strndup (a0, n)); + T (strndup (a0 + i, 0)); + T (strndup (a0 + i, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + T (strndup (a0 + i, i0)); + T (strndup (a0 + i, n)); + T (strndup (a0 + i + 1, 0)); + T (strndup (a0 + i + 1, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + + T (strndup (a0 + i0, 0)); + T (strndup (a0 + i0, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" } + T (strndup (a0 + i0, n)); + + T (strndup (a1, 0)); + T (strndup (a1, 1)); + T (strndup (a1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" } + T (strndup (a1, n)); + T (strndup (a1 + 1, 0)); + T (strndup (a1 + 1, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a1 + 1, i0)); + T (strndup (a1 + 1, i0 + 1)); // { dg-warning "'strndup' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strndup (a1 + 1, n)); + T (strndup (a1 + i, 0)); + T (strndup (a1 + i, 1)); + T (strndup (a1 + i, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" } + T (strndup (a1 + i, n)); + T (strndup (a1 + i + 1, 0)); + T (strndup (a1 + i + 1, 1)); + T (strndup (a1 + i + 1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" } + T (strndup (a1 + i + 1, n)); + + T (strndup (a1 + i0, 0)); + T (strndup (a1 + i0, 1)); + T (strndup (a1 + i0, n)); + T (strndup (a1 + i0 + 1, 0)); + T (strndup (a1 + i0 + 1, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a1 + i0 + 1, n)); + + T (strndup (a2, 0)); + T (strndup (a2, 1)); + T (strndup (a2, 2)); + T (strndup (a2, n)); + T (strndup (a2 + 1, 0)); + T (strndup (a2 + 1, 1)); + T (strndup (a2 + 1, 2)); + T (strndup (a2 + 1, n)); + T (strndup (a2 + 2, 0)); + T (strndup (a2 + 2, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a2 + 2, n)); + T (strndup (a2 + i, 0)); + T (strndup (a2 + i, 1)); + T (strndup (a2 + i, 2)); + T (strndup (a2 + i + 2, 0)); + T (strndup (a2 + i + 2, 1)); + T (strndup (a2 + i + 2, 2)); + T (strndup (a2 + i + 2, n)); + + T (strndup (a2 + i0, 0)); + T (strndup (a2 + i0, 1)); + T (strndup (a2 + i0, 2)); + T (strndup (a2 + i0, 3)); // { dg-warning "'strndup' specified bound 3 exceeds source size 2" } + T (strndup (a2 + i0, n)); + + T (strndup (a2 + i0 + 1, 0)); + T (strndup (a2 + i0 + 1, 1)); + T (strndup (a2 + i0 + 1, 2)); + T (strndup (a2 + i0 + 1, n)); + + T (strndup (a2 + i0 + 2, 0)); + T (strndup (a2 + i0 + 2, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a2 + i0 + 2, i0)); + T (strndup (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strndup' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strndup (a2 + i0 + 2, n)); +} + + +void test_strpbrk_array (char *s, int i) +{ + T (strpbrk (a0, "")); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } } + + T (strpbrk (a0, s)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + T (strpbrk (a0 + i, s)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + + T (strpbrk (a1, s)); + T (strpbrk (a1 + 1, s)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + T (strpbrk (a1 + i, s)); + T (strpbrk (a1 + i + 1, s)); + + + // Repeat the above with the arguments reversed. + + T (strpbrk ("", a0)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + + T (strpbrk (s, a0)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + T (strpbrk (s, a0 + i)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + + T (strpbrk (s, a1)); + T (strpbrk (s, a1 + 1)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" } + T (strpbrk (s, a1 + i)); + T (strpbrk (s, a1 + i + 1)); +} + + +void test_strspn_array (const char *s, int i) +{ + T (strspn (a0, "")); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } } + + T (strspn (a0, s)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" } + T (strspn (a0 + i, s)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" } + + T (strspn (a1, s)); + T (strspn (a1 + 1, s)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" } + T (strspn (a1 + i, s)); + T (strspn (a1 + i + 1, s)); + + + // Repeat the above with the arguments reversed. + + T (strspn ("", a0)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} } + + T (strspn (s, a0)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" } + T (strspn (s, a0 + i)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" } + + T (strspn (s, a1)); + T (strspn (s, a1 + 1)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" } + T (strspn (s, a1 + i)); + T (strspn (s, a1 + i + 1)); +} + + +void test_strcspn_array (const char *s, int i) +{ + /* The call below is tranformed to strlen() so the warning references + the latter function instead of strcspn. Avoid testing that aspect. */ + T (strcspn (a0, "")); // { dg-warning "reading 1 or more bytes from a region of size 0" } + + T (strcspn (a0, s)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" } + T (strcspn (a0 + i, s)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" } + + T (strcspn (a1, s)); + T (strcspn (a1 + 1, s)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" } + T (strcspn (a1 + i, s)); + T (strcspn (a1 + i + 1, s)); + + + // Repeat the above with the arguments reversed. + + T (strcspn ("", a0)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} } + + T (strcspn (s, a0)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" } + T (strcspn (s, a0 + i)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" } + + T (strcspn (s, a1)); + T (strcspn (s, a1 + 1)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" } + T (strcspn (s, a1 + i)); + T (strcspn (s, a1 + i + 1)); +} + + +void test_strstr_array (char *s, int i) +{ + T (strstr (a0, "")); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } } + + T (strstr (a0, s)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + T (strstr (a0 + i, s)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + + T (strstr (a1, s)); + T (strstr (a1 + 1, s)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + T (strstr (a1 + i, s)); + T (strstr (a1 + i + 1, s)); + + + // Repeat the above with the arguments reversed. + + T (strstr ("", a0)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + + T (strstr (s, a0)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + T (strstr (s, a0 + i)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + + T (strstr (s, a1)); + T (strstr (s, a1 + 1)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" } + T (strstr (s, a1 + i)); + T (strstr (s, a1 + i + 1)); +} + + +void test_puts_array (int i) +{ + T (puts (a0)); // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" } + T (puts (a0 + i)); // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" } + + T (puts (a1)); + T (puts (a1 + 1)); // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" } + T (puts (a1 + i)); + T (puts (a1 + i + 1)); +} + + +void test_puts_unlocked_array (int i) +{ + T (puts_unlocked (a0)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" } + T (puts_unlocked (a0 + i)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" } + + T (puts_unlocked (a1)); + T (puts_unlocked (a1 + 1)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" } + T (puts_unlocked (a1 + i)); + T (puts_unlocked (a1 + i + 1)); +} + + +void test_gettext_array (int i) +{ + T (gettext (a0)); // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" } + T (gettext (a0 + i)); // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" } + + T (gettext (a1)); + T (gettext (a1 + 1)); // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" } + T (gettext (a1 + i)); + T (gettext (a1 + i + 1)); +} diff --git a/gcc/testsuite/gcc.dg/Wunused-var-4.c b/gcc/testsuite/gcc.dg/Wunused-var-4.c new file mode 100644 index 0000000..08ddcf4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wunused-var-4.c @@ -0,0 +1,33 @@ +/* PR c/96571 */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -O2 -Wunused-but-set-variable" } */ + +enum E { V }; + +int +foo (void) +{ + enum E v; /* { dg-bogus "set but not used" } */ + return _Generic (v, enum E : 0); +} + +int +bar (void) +{ + int a = 0; /* { dg-bogus "set but not used" } */ + return _Generic (0, int : a); +} + +int +baz (void) +{ + int a; /* { dg-bogus "set but not used" } */ + return _Generic (0, long long : a, int : 0); +} + +int +qux (void) +{ + int a; /* { dg-bogus "set but not used" } */ + return _Generic (0, long long : a, default: 0); +} diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-2.c b/gcc/testsuite/gcc.dg/Wvla-parameter-2.c new file mode 100644 index 0000000..ba93241 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-2.c @@ -0,0 +1,75 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify the -Wvla-parameter warnings correctly diagnose mismatches + between multimensional array arguments with one or more variable + bounds in redeclarations of the same function. + { dg-do compile } + { dg-options "-Wall -Wvla-parameter" } */ + +void fmn_a1n_axn (int n, int[1][n]); // { dg-message "previously declared as 'int\\\[1]\\\[n]' with 1 variable bound" "note" } +void fmn_a1n_axn (int n, int[*][n]); // { dg-warning "argument 2 of type 'int\\\[\\\*]\\\[n]' declared with 2 variable bounds" } + + +void fmn_axn_a2n (int n, int[*][n]); // { dg-message "previously declared as 'int\\\[\\\*]\\\[n]' with 2 variable bounds" "note" } +void fmn_axn_a2n (int n, int[2][n]); // { dg-warning "argument 2 of type 'int\\\[2]\\\[n]' declared with 1 variable bound" } + + +void fmn_amn_axn (int m, int n, int[m][n]); // { dg-message "previously declared as 'int\\\[m]\\\[n]' with 0 unspecified variable bounds" "note" } +void fmn_amn_axn (int m, int n, int[*][n]); // { dg-warning "argument 3 of type 'int\\\[\\\*]\\\[n]' declared with 1 unspecified variable bound" } + +// Same as above but a different function name. +void gmn_amn_axn (int m, int n, int[m][n]); // { dg-message "previously declared as 'int\\\[m]\\\[n]' with 0 unspecified variable bounds" "note" } +void gmn_amn_axn (int m, int n, int[*][n]); // { dg-warning "argument 3 of type 'int\\\[\\\*]\\\[n]' declared with 1 unspecified variable bound" } + +typedef int A7[7]; + +void fm_A7_m_5 (int m, A7[m][5]); // { dg-message "previously declared as 'int\\\[m]\\\[5]\\\[7]' with bound argument 1" "note" } +void fm_A7_m_5 (int n, A7[n][5]); + +void fm_A7_m_5 (int n, A7[n + 1][5]); // { dg-warning "argument 2 of type 'int\\\[n \\\+ 1]\\\[5]\\\[7]' declared with mismatched bound 'n \\\+ 1'" } + + +int n1, n2, n3, n4, n5, n6, n7, n8, n9; +void f (int[n1][2][n3][4][n5][6][n7][8][n9]); // { dg-message "previously declared as 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' with 0 unspecified variable bounds" "note" } + // { dg-message "with 5 variable bounds" "note" { target *-*-* } .-1 } +void f (int[n1][2][n3][4][n5][6][n7][8][n9]); + +/* Due to a limitation and because [*] is represented the same as [0] + only the most significant array bound is rendered as [*]; the others + are rendered as [0]. */ +void f (int[n1][2][n3][4][n5][6][n7][8][*]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[\\\*]' declared with 1 unspecified variable bound" "pr?????" { xfail *-*-* } } +// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[0]' declared with 1 unspecified variable bound" "pr?????" { target *-*-* } .-1 } +void f (int[n1][2][n3][4][n5][6][*][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[\\\*]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr?????" { xfail *-*-* } } +// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[0]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr?????" { target *-*-* } .-1 } +void f (int[n1][2][n3][4][*][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[\\\*]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr?????" { xfail *-*-*} } +// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[0]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr?????" { target *-*-* } .-1 } +void f (int[n1][2][*][4][n5][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[\\\*]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr?????" { xfail *-*-* } } +// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[0]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr?????" { target *-*-* } .-1 } +void f (int[*][2][n3][4][n5][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[\\\*]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" } + +void f (int[n1][n2][n3][n4][n5][n6][n7][n8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[n2]\\\[n3]\\\[n4]\\\[n5]\\\[n6]\\\[n7]\\\[n8]\\\[n9]' declared with 9 variable bounds" } + +// Verify that arrays of pointers to arrays...etc are handled correctly. +void a2pampan (int (*(*(*[2])[n1])[n2])); +// { dg-message "previously declared as 'int \\\* \\\(\\\* \\\(\\\*\\\[2]\\\)\\\[n1]\\\)\\\[n2]'" "note" { target *-*-* } .-1 } +void a2pampan (int (*(*(*[2])[n1])[1])); +// { dg-warning "argument 1 of type 'int \\\* \\\(\\\* \\\(\\\*\\\[2]\\\)\\\[n1]\\\)\\\[1]' declared with 1 variable bound" "" { target *-*-* } .-1 } +void a2pampan (int (*(*(*[2])[1])[n2])); +// { dg-warning "argument 1 of type 'int \\\* \\\(\\\* \\\(\\\*\\\[2]\\\)\\\[1]\\\)\\\[n2]' declared with 1 variable bound" "" { target *-*-* } .-1 } +void a2pampan (int (*(*(*[2])[n1])[n1])); +// { dg-warning "argument 1 of type 'int \\\* \\\(\\\* \\\(\\\*\\\[2]\\\)\\\[n1]\\\)\\\[n1]' declared with mismatched bound 'n1'" "" { target *-*-* } .-1 } +void a2pampan (int (*(*(*[2])[n1])[n2])); + + +/* Verify that the presence or absence of static with VLA dooesn't cause + unwanted warnings. */ + +int f2ia1_1 (int n, int [n][n]); // { sg-message "previously declared as 'int\\\[n]\\\[n]' with bound argument 1" } +int f2ia1_1 (int n, int[static n][n]); +int f2ia1_1 (int n, int a[static n][n]) { return sizeof *a; } +int f2ia1_1 (int n, int[static n + 1][n]); // { dg-warning "argument 2 of type 'int\\\[n \\\+ 1]\\\[n]' declared with mismatched bound 'n \\\+ 1'" } + +int f2ias1_1 (int n, int [static n][n]); // { dg-message "previously declared as 'int\\\[n]\\\[n]' with bound argument 1" } +int f2ias1_1 (int n, int[n][n]); +int f2ias1_1 (int n, int a[++n][n]) // { dg-warning "argument 2 of type 'int\\\[\\\+\\\+n]\\\[n]' declared with mismatched bound ' ?\\+\\+n'" } +{ return sizeof *a; } diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-3.c b/gcc/testsuite/gcc.dg/Wvla-parameter-3.c new file mode 100644 index 0000000..51f0172 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-3.c @@ -0,0 +1,68 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify that redeclarations of functions with pointer parameters to + arrays with variable bounds are diagnosed if the bounds don't match + either in kind or in the variable expression. + { dg-do compile } + { dg-options "-Wall -Wvla-parameter" } */ + +extern int m, n; + +void pa_ (int (*)[]); // { dg-message "previously declared as 'int \\\(\\\*\\\)\\\[]'" "note" } +void pa_ (int (*)[n]); // { dg-warning "\\\[-Wvla-parameter" } +void pa_ (int (*)[n + 1]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int *\\\(\\\*\\\)\\\[n \\\+ 1\\\]'" } + +void ppa_ (int (**)[]); // { dg-message "previously declared as 'int \\\(\\\*\\\*\\\)\\\[]'" "note" } +void ppa_ (int (**)[n]); // { dg-warning "\\\[-Wvla-parameter" } +void ppa_ (int (**)[n + 1]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\*\\\)\\\[n \\\+ 1\\\]'" } + +void pa1 (int (*)[1]); // { dg-message "previously declared as 'int \\\(\\\*\\\)\\\[1]'" "note" } +void pa1 (int (*)[n]); // { dg-warning "\\\[-Wvla-parameter" } +void pa1 (int (*)[1]); +void pa1 (int (*)[n + 1]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int *\\\(\\\*\\\)\\\[n \\\+ 1\\\]'" } + +void ppax (int (**)[*]); // { dg-message "previously declared as 'int \\\(\\\*\\\*\\\)\\\[.]'" "note" } +void ppax (int (**)[n]); // { dg-warning "\\\[-Wvla-parameter" } +/* A VLA with an unspecified bound is represented the same as [0] so + so the pretty printer can't differentiate between the two forms. */ +void ppax (int (**)[1]); // { dg-bogus "\\\[-Warray-parameter" "pr?????" { xfail *-*-* } } + // { dg-warning "\\\[-Wvla-parameter" "pr?????" { xfail *-*-* } .-1 } +void ppax (int (**)[n + 1]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int *\\\(\\\*\\\*\\\)\\\[n \\\+ 1\\\]'" } + + +void pa1_n (int (*)[1][n]); +void pa1_n (int (*)[1][n]); +void pa1_n (int (*)[*][n]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[\\\*]\\\[n]'" "pr?????" { xfail *-*-*} } + // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[0]\\\[n]'" "pr?????" { target *-*-* } .-1 } + +void pa1_n_2 (int (*)[1][n][2]); +void pa1_n_2 (int (*)[1][n][*]); // { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[\\\*]'" "pr?????" { xfail *-*-* } } + // { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[0]'" "pr?????" { target *-*-* } .-1 } + + +void pa1_n_2_a1_n_2 (int (*)[1][n][2], int (*)[1][n][2]); +// { dg-message "previously declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[2]'" "note" { target *-*-* } .-1 } +void pa1_n_2_a1_n_2 (int (*)[1][n][2], int (*)[1][n][n]); +// { dg-warning "mismatch in bound 3 of argument 2 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[n]'" "" { target *-*-* } .-1 } +void pa1_n_2_a1_n_2 (int (*)[1][n][2], int (*)[1][3][2]); +// { dg-warning "mismatch in bound 2 of argument 2 declared as 'int \\\(\\\*\\\)\\\[1]\\\[3]\\\[2]'" "" { target *-*-* } .-1 } +void pa1_n_2_a1_n_2 (int (*)[1][n][2], int (*)[n][n][2]); +// { dg-warning "mismatch in bound 1 of argument 2 declared as 'int \\\(\\\*\\\)\\\[n]\\\[n]\\\[2]'" "" { target *-*-* } .-1 } +void pa1_n_2_a1_n_2 (int (*)[1][n][n], int (*)[1][n][2]); +// { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[n]'" "" { target *-*-* } .-1 } +void pa1_n_2_a1_n_2 (int (*)[n][n][2], int (*)[1][n][2]); +// { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[n]\\\[n]\\\[2]'" "" { target *-*-* } .-1 } +void pa1_n_2_a1_n_2 (int (*)[*][*][*], int (*)[*][*][2]); +// { dg-warning "mismatch in bounds 1, 2, 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[.]\\\[.]\\\[.]'" "" { target *-*-* } .-1 } +// { dg-warning "mismatch in bounds 1, 2 of argument 2 declared as 'int \\\(\\\*\\\)\\\[.]\\\[.]\\\[2]'" "" { target *-*-* } .-2 } +void pa1_n_2_a1_n_2 (int (*)[1][n][2], int (*)[1][n][2]); + +/* Verify that pointers to arrays of pointers to arrays...etc are handled + correctly. */ +void pa2pampan (int (*(*(*(*)[2])[m])[n])); +// { dg-message "previously declared as 'int \\\* \\\(\\\* \\\(\\\* \\\(\\\*\\\)\\\[2]\\\)\\\[m]\\\)\\\[n]'" "note" { target *-*-* } .-1 } +void pa2pampan (int (*(*(*(*)[2])[m])[1])); +// { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\* \\\(\\\* \\\(\\\* \\\(\\\*\\\)\\\[2]\\\)\\\[m]\\\)\\\[1]'" "" { target *-*-* } .-1 } +void pa2pampan (int (*(*(*(*)[2])[1])[n])); +// { dg-warning "mismatch in bound 2 of argument 1 declared as 'int \\\* \\\(\\\* \\\(\\\* \\\(\\\*\\\)\\\[2]\\\)\\\[1]\\\)\\\[n]'" "" { target *-*-* } .-1 } +void pa2pampan (int (*(*(*(*)[2])[m])[n])); diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-4.c b/gcc/testsuite/gcc.dg/Wvla-parameter-4.c new file mode 100644 index 0000000..599ad19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-4.c @@ -0,0 +1,99 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify warnings for redeclarations of functions with pointer parameters + to arrays with variable bounds involving typedefs. + { dg-do compile } + { dg-options "-Wall -Wvla-parameter" } */ + +extern int m, n; + +typedef int IA3[3]; + +/* Verify the warning points to the declaration with more unspecified + bounds, guiding the user to specify them rather than making them all + unspecified. */ +void* f_pIA3ax (IA3 *x[*]); // { dg-warning "argument 1 of type 'int \\\(\\\*\\\[\\\*]\\\)\\\[3]' .aka '\[^\n\r\}\]+'. declared with 1 unspecified variable bound" } +void* f_pIA3ax (IA3 *x[*]); +void* f_pIA3ax (IA3 *x[n]); // { dg-message "subsequently declared as 'int \\\(\\\*\\\[n]\\\)\\\[3]' with 0 unspecified variable bounds" "note" } +void* f_pIA3ax (IA3 *x[n]) { return x; } + + +void* f_pIA3an (IA3 *x[n]); // { dg-message "previously declared as 'int \\\(\\\*\\\[n]\\\)\\\[3]' with 0 unspecified variable bounds" "note" } +void* f_pIA3an (IA3 *x[n]); +void* f_pIA3an (IA3 *x[*]); // { dg-warning "argument 1 of type 'int \\\(\\\*\\\[\\\*]\\\)\\\[3]' .aka '\[^\n\r\}\]+'. declared with 1 unspecified variable bound" } +void* f_pIA3an (IA3 *x[n]) { return x; } + + +void nowarn_local_fndecl (void) +{ + typedef int IAm[m]; + + void* f_IAm (IAm); + void* f_IAm (int[m]); + void* f_IAm (IAm); + + void* f_iam (int[m]); + void* f_iam (IAm); + void* f_iam (int[m]); + + typedef int IA3[3]; + typedef IA3 IAn_3[n]; + typedef IAn_3 IA2_n_3[2]; + typedef IA2_n_3 IAm_2_n_3[m]; + + void f_IAm_2_n_3 (IAm_2_n_3); + void f_IAm_2_n_3 (IA2_n_3[m]); + void f_IAm_2_n_3 (IAn_3[m][2]); + void f_IAm_2_n_3 (IA3[m][2][n]); + void f_IAm_2_n_3 (int[m][2][n][3]); + + void f_iam_2_n_3 (int[m][2][n][3]); + void f_iam_2_n_3 (IA3[m][2][n]); + void f_iam_2_n_3 (IAn_3[m][2]); + void f_iam_2_n_3 (IAm_2_n_3); + + void f_IAx_m_2_n_3 (IAm_2_n_3[*]); + void f_IAx_m_2_n_3 (IA2_n_3[*][m]); + void f_IAx_m_2_n_3 (IAn_3[*][m][2]); + void f_IAx_m_2_n_3 (IA3[*][m][2][n]); + void f_IAx_m_2_n_3 (int[*][m][2][n][3]); + + void f_IA__m_2_n_3 (IAm_2_n_3[]); + void f_IA__m_2_n_3 (IA2_n_3[][m]); + void f_IA__m_2_n_3 (IAn_3[][m][2]); + void f_IA__m_2_n_3 (IA3[][m][2][n]); + void f_IA__m_2_n_3 (int[][m][2][n][3]); +} + + +void warn_local_fndecl (void) +{ + typedef int IAm[m]; + typedef int IAn[n]; + + void* g_IAm (IAm); // { dg-message "previously declared as 'int\\\[m]' with bound 'm'" } + void* g_IAm (int[n]); // { dg-warning "argument 1 of type 'int\\\[n]' declared with mismatched bound 'n'" } + void* g_IAm (IAm); + + void* g_iam (int[m]); // { dg-message "previously declared as 'int\\\[m]' with bound 'm'" } + void* g_iam (IAn); // { dg-warning "argument 1 of type 'int\\\[n]' declared with mismatched bound 'n'" } + void* g_iam (int[m]); + + + typedef int IA3[3]; + typedef IA3 IAn_3[n]; + typedef IAn_3 IA2_n_3[2]; + typedef IA2_n_3 IAm_2_n_3[m]; + + typedef IA3 IAm_3[m]; + typedef IAm_3 IA2_m_3[2]; + typedef IA2_m_3 IAm_2_m_3[m]; + + void* g_IAm_2_n_3 (IAm_2_n_3); + void* g_IAm_2_n_3 (int[m][2][m][3]); // { dg-warning "argument 1 of type 'int\\\[m]\\\[2]\\\[m]\\\[3]' declared with mismatched bound 'm'" } + void* g_IAm_2_n_3 (IAm_2_n_3); + + void* g_iam_2_n_2 (int[m][2][n][3]); + void* g_iam_2_n_2 (IAm_2_m_3); // { dg-warning "argument 1 of type 'int\\\[m]\\\[2]\\\[m]\\\[3]' declared with mismatched bound 'm'" } + void* g_iam_2_n_2 (int[m][2][n][3]); +} diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-5.c b/gcc/testsuite/gcc.dg/Wvla-parameter-5.c new file mode 100644 index 0000000..16b40d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-5.c @@ -0,0 +1,22 @@ +/* Verify that combinations of array type qualifiers render correctly. + { dg-do compile } + { dg-options "-Wvla-parameter" } */ + +extern int n1, n2; + +void fcx_n1 (int [const][n1]); // { dg-message "previously declared as 'int\\\[const]\\\[n1]' with bound 'n1'" "note" } +void fcx_n1 (int [const][n2]); // { dg-warning "argument 1 of type 'int\\\[const]\\\[n2]' declared with mismatched bound 'n2'" } + +/* The mismatch in the array bound should not be diagnosed without + -Warray-parameter but the mismatch in the VLA should still be + diagnosed. */ +void fc3_n1 (int [const 3][n1]); // { dg-message "previously declared as 'int\\\[const 3]\\\[n1]' with bound 'n1'" "note" } +void fc3_n1 (int [const 5][n2]); // { dg-warning "argument 1 of type 'int\\\[const 5]\\\[n2]' declared with mismatched bound 'n2'" } + + +void frx_n1 (int [restrict][n1]); // { dg-message "previously declared as 'int\\\[restrict]\\\[n1]' with bound 'n1'" "note" } +void frx_n1 (int [restrict][n2]); // { dg-warning "argument 1 of type 'int\\\[restrict]\\\[n2]' declared with mismatched bound 'n2'" } + + +void fvx_n2 (int [volatile][n2]); // { dg-message "previously declared as 'int\\\[volatile]\\\[n2]' with bound 'n2'" "note" } +void fvx_n2 (int [volatile][n1]); // { dg-warning "argument 1 of type 'int\\\[volatile]\\\[n1]' declared with mismatched bound 'n1'" } diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-6.c b/gcc/testsuite/gcc.dg/Wvla-parameter-6.c new file mode 100644 index 0000000..268aeec --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-6.c @@ -0,0 +1,34 @@ +/* PR middle-end/97189 - ICE on redeclaration of a function with VLA argument + and attribute access + Also verify the right arguments are underlined in the notes. + { dg-do compile } + { dg-options "-Wall -fdiagnostics-show-caret" } */ + +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) + +RW (2, 3) void f1 (int n, int[n], int); +/* { dg-warning "attribute 'access \\(read_write, 2, 3\\)' positional argument 2 conflicts with previous designation by argument 3" "warning" { target *-*-* } .-1 } + { dg-begin-multiline-output "" } + RW (2, 3) void f1 (int n, int[n], int); + ^~ + { dg-end-multiline-output "" } + { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-6 } + { dg-begin-multiline-output "" } + RW (2, 3) void f1 (int n, int[n], int); + ~~~~^ ~~~~~~ + { dg-end-multiline-output "" } */ + + +RW (2) void f2 (int, int[*], int); +/* { dg-message "previously declared as a variable length array 'int\\\[\\\*]'" "note" { target *-*-* } .-1 } + { dg-begin-multiline-output "" } + RW (2, 3) void f2 (int, int[], int); + ^~~~~ + { dg-end-multiline-output "" } */ + +RW (2, 3) void f2 (int, int[], int); +/* { dg-warning "argument 2 of type 'int\\\[]' declared as an ordinary array" "warning" { target *-*-* } .-1 } + { dg-begin-multiline-output "" } + RW (2) void f2 (int, int[*], int); + ^~~~~~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-7.c b/gcc/testsuite/gcc.dg/Wvla-parameter-7.c new file mode 100644 index 0000000..14ce75f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-7.c @@ -0,0 +1,36 @@ +/* PR middle-end/97189 - ICE on redeclaration of a function with VLA argument + and attribute access + { dg-do compile } + { dg-options "-Wall" } */ + +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) + +RW (2, 3) void f1 (int n, int[n], int); +/* { dg-warning "attribute 'access \\(read_write, 2, 3\\)' positional argument 2 conflicts with previous designation by argument 3" "warning" { target *-*-* } .-1 } + { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-2 } */ + +void call_f1 (int *p) +{ + /* Verify that a warning is issued. Ideally, it seems the VLA bound + should take precedence over the attribute and the warning would + reference argument 1 but since the conflict in the redeclarations + of the function is already diagnosed don't test that (and let it + be acceptable for this warning to reference argument 3). */ + f1 (-1, p, -1); + // { dg-warning "argument \\d value -1 is negative" "warning" { target *-*-* } .-1 } +} + +RW (2) void f2 (int, int[*], int); +// { dg-message "previously declared as a variable length array 'int\\\[\\\*]'" "note" { target *-*-* } .-1 } +RW (2, 3) void f2 (int, int[], int); +// { dg-warning "argument 2 of type 'int\\\[]' declared as an ordinary array" "warning" { target *-*-* } .-1 } + +void call_f2 (int *p) +{ + f2 (-1, p, 0); + + /* Verify that the attribute access on the redeclaration of f2() takes + precedence over the one on the first declaration. */ + f2 (0, p, -1); + // { dg-warning "argument 3 value -1 is negative" "warning" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter.c b/gcc/testsuite/gcc.dg/Wvla-parameter.c new file mode 100644 index 0000000..6e4df02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter.c @@ -0,0 +1,136 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + Verify the -Wvla-parameter warnings correctly diagnose mismatches + between one-dimensional VLA and non-VLA arguments in redeclarations + of the same function. + Also verify that the array/pointer argument form in a mismatched + redeclaration doesn't override the form in the initial declaration. + { dg-do compile } + { dg-options "-Wall -Wvla-parameter" } */ + +/* Verify that redeclaring an argument as a VLA with an unspecified + bound that was first declared as an ordinary array with an unspecified + bound triggers a warning. */ +void f1ia_x (int[]); // { dg-message "previously declared as an ordinary array 'int\\\[]'" "note" } +void f1ia_x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ia_x (int[]); +void f1ia_x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +/* Also verify that a definition of the same form as the first declaration + doesn't trigger a warning and doesn't prevent warnings for subsequent + mismatches. */ +void f1ia_x (int a[]) { (void)&a;} +void f1ia_x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } + +/* Repeat the above but starting with an ordinary array with a constant + bound. */ +void f1ia1x (int[1]); // { dg-message "previously declared as an ordinary array 'int\\\[1]'" "note" } +void f1ia1x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ia1x (int a[1]) { (void)&a; } +void f1ia1x (int[1]); +void f1ia1x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } + +void f1ipx (int*); // { dg-message "previously declared as a pointer 'int ?\\\*'" "note" } +void f1ipx (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ipx (int*); +void f1ipx (int *p) { (void)&p; } +void f1ipx (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ipx (int*); + +void f2ipx (int*, int*); // { dg-message "previously declared as a pointer 'int ?\\\*'" "note" } +void f2ipx (int*, int[*]); // { dg-warning "argument 2 of type 'int\\\[\\\*]' declared as a variable length array" } +void f2ipx (int*, int*); +void f2ipx (int*, int[*]); // { dg-warning "argument 2 of type 'int\\\[\\\*]' declared as a variable length array" } +void f2ipx (int *p, int *q) { (void)&p; (void)&q; } +void f2ipx (int*, int[*]); // { dg-warning "argument 2 of type 'int\\\[\\\*]' declared as a variable length array" } + +void f1ias2x (int[static 2]); // { dg-message "previously declared as an ordinary array 'int\\\[static 2]'" } +void f1ias2x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ias2x (int[static 2]); +void f1ias2x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ias2x (int a[static 2]) { (void)&a; } +void f1ias2x (int[*]); // { dg-warning "argument 1 of type 'int\\\[\\\*]' declared as a variable length array" } +void f1ias2x (int[static 2]); + +extern int nelts; + +void f1sa_var (short[]); // { dg-message "previously declared as an ordinary array 'short int\\\[]'" } +void f1sa_var (short[nelts]); // { dg-warning "argument 1 of type 'short int\\\[nelts]' declared as a variable length array" } +void f1sa_var (short[]); +void f1sa_var (short[nelts]); // { dg-warning "argument 1 of type 'short int\\\[nelts]' declared as a variable length array" } +void f1sa_var (short a[]) { (void)&a; } +void f1sa_var (short[nelts]); // { dg-warning "argument 1 of type 'short int\\\[nelts]' declared as a variable length array" } +void f1sa_var (short[]); + +void f1sa_expr (int[]); // { dg-message "previously declared as an ordinary array 'int\\\[]'" } +void f1sa_expr (int[nelts + 1]); // { dg-warning "argument 1 of type 'int\\\[nelts \\\+ 1]' declared as a variable length array" } +void f1sa_expr (int[]); +void f1sa_expr (int[nelts * 2]); // { dg-warning "argument 1 of type 'int\\\[nelts \\\* 2]' declared as a variable length array" } +void f1sa_expr (int a[]) { (void)&a; } +void f1sa_expr (int[nelts / 3]); // { dg-warning "argument 1 of type 'int\\\[nelts / 3]' declared as a variable length array" } +void f1sa_expr (int[]); + +extern int f (int); + +void f1ia_f (int[]); // { dg-message "previously declared as an ordinary array 'int\\\[]'" } +void f1ia_f (int[f (1)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(1\\\)]' declared as a variable length array" } +void f1ia_f (int[]); +void f1ia_f (int[f (2)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(2\\\)]' declared as a variable length array" } +void f1ia_f (int a[]) { (void)&a; } +void f1ia_f (int[f (3)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(3\\\)]' declared as a variable length array" } +void f1ia_f (int[f (4)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(4\\\)]' declared as a variable length array" } +void f1ia_f (int[]); + +void f1iaf0_f1 (int[f (0)]); // { dg-message "previously declared as 'int\\\[f *\\\(0\\\)]'" } +void f1iaf0_f1 (int[f (1)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(1\\\)]' declared with mismatched bound" } +void f1iaf0_f1 (int[f (0)]); +void f1iaf0_f1 (int[f (1)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(1\\\)]' declared with mismatched bound" } +void f1iaf0_f1 (int a[f (0)]) { (void)&a; } +void f1iaf0_f1 (int[f (1)]); // { dg-warning "argument 1 of type 'int\\\[f *\\\(1\\\)]' declared with mismatched bound" } +void f1iaf0_f1 (int[f (0)]); + +void f1la_ (long[]); // { dg-message "previously declared as an ordinary array 'long int\\\[]'" } +void f1la_ (long[nelts]); // { dg-warning "argument 1 of type 'long int\\\[nelts]' declared as a variable length array" } +void f1la_ (long[]); +void f1la_ (long a[nelts]) // { dg-warning "argument 1 of type 'long int\\\[nelts]' declared as a variable length array" } +{ (void)&a; } +void f1la_ (long[]); + +void f2ca_ (int, char[]); // { dg-message "previously declared as an ordinary array 'char\\\[]'" } +void f2ca_ (int n, char[n]); // { dg-warning "argument 2 of type 'char\\\[n]' declared as a variable length array" } +void f2ca_ (int, char[]); +void f2ca_ (int n, char a[n]) // { dg-warning "argument 2 of type 'char\\\[n]' declared as a variable length array" } +{ (void)&n; (void)&a; } + +void f2ia1_f (int n, int[n]); // { dg-message "previously declared as 'int\\\[n]' with bound argument 1" } +void f2ia1_f (int, int[f (0)]); // { dg-warning "argument 2 of type 'int\\\[f *\\\(0\\\)]' declared with mismatched bound 'f *\\\(0\\\)'" } +void f2ia1_f (int m, int[m]); +void f2ia1_f (int, int[f (1)]); // { dg-warning "argument 2 of type 'int\\\[f *\\\(1\\\)]' declared with mismatched bound 'f *\\\(1\\\)'" } +void f2ia1_f (int x, int a[x]) { (void)&x; (void)&a; } +void f2ia1_f (int, int[f (2)]); // { dg-warning "argument 2 of type 'int\\\[f *\\\(2\\\)]' declared with mismatched bound 'f *\\\(2\\\)'" } +void f2ia1_f (int y, int[y]); + +void f2iaf_1 (int, int[f (0)]); // { dg-message "previously declared as 'int\\\[f *\\\(0\\\)]'" } +void f2iaf_1 (int n, int[n]); // { dg-warning "argument 2 of type 'int\\\[n]' declared with mismatched bound argument 1" } +void f2iaf_1 (int, int[f (0)]); +void f2iaf_1 (int m, int[m]); // { dg-warning "argument 2 of type 'int\\\[m]' declared with mismatched bound argument 1" } +void f2iaf_1 (int x, int a[f (0)]) { (void)&x; (void)&a; } +void f2iaf_1 (int y, int[y]); // { dg-warning "argument 2 of type 'int\\\[y]' declared with mismatched bound argument 1" } + + +void f3ia1 (int n, int, int[n]); // { dg-message "previously declared as 'int\\\[n]' with bound argument 1" } +void f3ia1 (int, int n, int[n]); // { dg-warning "argument 3 of type 'int\\\[n]' declared with mismatched bound argument 2" } +void f3ia1 (int n, int, int[n]); + + +extern int g (int); + +void f1iaf_g (int[f (1)]); // { dg-message "previously declared as 'int\\\[f *\\\(1\\\)]'" } +void f1iaf_g (int[g (1)]); // { dg-warning "argument 1 of type 'int\\\[g *\\\(1\\\)]' declared with mismatched bound" } +void f1iaf_g (int[f (1)]); + + +void nrf1iaf_g (int[f (1)]); // { dg-message "previously declared as 'int\\\[f *\\\(1\\\)]'" } +__attribute__ ((nonnull)) +void nrf1iaf_g (int[g (1)]); // { dg-warning "argument 1 of type 'int\\\[g *\\\(1\\\)]' declared with mismatched bound" } +__attribute__ ((noreturn)) +void nrf1iaf_g (int[f (1)]); diff --git a/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue-2.c b/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue-2.c new file mode 100644 index 0000000..57fd30a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue-2.c @@ -0,0 +1,30 @@ +/* { dg-additional-options "-fanalyzer-show-duplicate-count" } */ + +#include <stdlib.h> + +typedef struct _krb5_data { + char *data; +} krb5_data; + +/* Ensure that we de-duplicate the various paths to reach here, + and only emit one diagnostic. */ + +void +recvauth_common(krb5_data common) +{ + free(common.data); + free(common.data); /* { dg-warning "double-'free' of 'common.data'" "inner warning" } */ + /* { dg-warning "double-'free' of 'inbuf_a.data' " "inbuf_a warning" { target *-*-* } .-1 } */ + /* { dg-warning "double-'free' of 'inbuf_b.data' " "inbuf_b warning" { target *-*-* } .-2 } */ + /* { dg-message "2 duplicates" "duplicates notification" { xfail *-*-* } .-3 } */ +} + +void krb5_recvauth(krb5_data inbuf_a) +{ + recvauth_common(inbuf_a); +} + +void krb5_recvauth_version(krb5_data inbuf_b) +{ + recvauth_common(inbuf_b); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue.c b/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue.c index b43148c..0fc865f 100644 --- a/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue.c +++ b/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-dedupe-issue.c @@ -14,7 +14,7 @@ recvauth_common(krb5_data inbuf) { free(inbuf.data); free(inbuf.data); /* { dg-warning "double-'free'" "warning" } */ - /* { dg-message "2 duplicates" "duplicates notification" { target *-*-* } .-1 } */ + /* { dg-message "2 duplicates" "duplicates notification" { xfail *-*-* } .-1 } */ } void krb5_recvauth(krb5_data inbuf) diff --git a/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-minimal.c b/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-minimal.c index aa9deb3..5edbdb1 100644 --- a/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-minimal.c +++ b/gcc/testsuite/gcc.dg/analyzer/CVE-2005-1689-minimal.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include "analyzer-decls.h" typedef struct _krb5_data { char *data; @@ -28,3 +29,63 @@ test_3 (krb5_data inbuf, int flag) } free((char *)inbuf.data); /* { dg-warning "double-'free' of 'inbuf.data'" } */ } + +extern void unknown_fn (void *); + +void +test_4 (krb5_data inbuf) +{ + unknown_fn (NULL); + free(inbuf.data); /* { dg-message "first 'free' here" } */ + free(inbuf.data); /* { dg-warning "double-'free' of 'inbuf.data'" } */ +} + +void +test_5 (krb5_data inbuf) +{ + unknown_fn (&inbuf); + free(inbuf.data); /* { dg-message "first 'free' here" } */ + free(inbuf.data); /* { dg-warning "double-'free' of 'inbuf.data'" "inbuf.data" } */ + /* { dg-bogus "double-'free' of 'inbuf'" "inbuf" { target *-*-* } .-1 } */ +} + +typedef struct _padded_krb5_data { + int pad; + char *data; +} padded_krb5_data; + +void +test_6 (padded_krb5_data inbuf) +{ + unknown_fn (&inbuf.data); + free((char *)inbuf.data); /* { dg-message "first 'free' here" } */ + free((char *)inbuf.data); /* { dg-warning "double-'free' of 'inbuf.data'" "inbuf.data" } */ +} + +void +test_7 (padded_krb5_data inbuf) +{ + unknown_fn (&inbuf.data); + free((char *)inbuf.data); + + unknown_fn (&inbuf.data); + free((char *)inbuf.data); +} + +void +test_8 (padded_krb5_data inbuf, int flag) +{ + if (flag) + { + unknown_fn (&inbuf.data); + free((char *)inbuf.data); + } + /* Should have two enodes, one for the explicit "freed" state, and one + for the implicit "start" state. */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + + unknown_fn (&inbuf.data); + + /* Should have just one enode, for the implicit "start" state. */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/abs-1.c b/gcc/testsuite/gcc.dg/analyzer/abs-1.c new file mode 100644 index 0000000..d6ce8d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/abs-1.c @@ -0,0 +1,22 @@ +#include "analyzer-decls.h" + +extern long int labs (long int x) + __attribute__ ((__nothrow__ , __leaf__)) + __attribute__ ((__const__)); + +long int test_1 (long int x) +{ + return labs (x); +} + +static long __attribute__((noinline)) +hide_long (long x) +{ + return x; +} + +long int test_2 (long int x) +{ + __analyzer_eval (labs (hide_long (42)) == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (labs (hide_long (-17)) == 17); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/aliasing-1.c b/gcc/testsuite/gcc.dg/analyzer/aliasing-1.c new file mode 100644 index 0000000..26050f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/aliasing-1.c @@ -0,0 +1,25 @@ +#include "analyzer-decls.h" + +int a; +void test (int *p, int x) +{ + int y; + + a = 17; + x = 42; + y = 13; + + __analyzer_eval (a == 17); /* { dg-warning "TRUE" } */ + __analyzer_eval (x == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (y == 13); /* { dg-warning "TRUE" } */ + + __analyzer_eval (p == &a); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (p == &x); /* { dg-warning "FALSE" } */ + __analyzer_eval (p == &y); /* { dg-warning "FALSE" } */ + + *p = 73; + + __analyzer_eval (a == 17); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (x == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (y == 13); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/aliasing-2.c b/gcc/testsuite/gcc.dg/analyzer/aliasing-2.c new file mode 100644 index 0000000..38ceeff --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/aliasing-2.c @@ -0,0 +1,32 @@ +#include "analyzer-decls.h" + +extern void escape (int *p); + +int a; +void test (int *p, int x) +{ + int y; + + a = 17; + x = 42; + y = 13; + + __analyzer_eval (a == 17); /* { dg-warning "TRUE" } */ + __analyzer_eval (x == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (y == 13); /* { dg-warning "TRUE" } */ + + escape (&x); + __analyzer_eval (a == 17); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (x == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (y == 13); /* { dg-warning "TRUE" } */ + + __analyzer_eval (p == &a); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (p == &x); /* { dg-warning "FALSE" } */ + __analyzer_eval (p == &y); /* { dg-warning "FALSE" } */ + + *p = 73; + + __analyzer_eval (a == 17); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (x == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (y == 13); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/alloca-leak.c b/gcc/testsuite/gcc.dg/analyzer/alloca-leak.c index 6d9fe34..9331993 100644 --- a/gcc/testsuite/gcc.dg/analyzer/alloca-leak.c +++ b/gcc/testsuite/gcc.dg/analyzer/alloca-leak.c @@ -1,3 +1,5 @@ +/* { dg-require-effective-target alloca } */ + #include <alloca.h> void *test (void) diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h b/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h index 180e873..d96b3f2 100644 --- a/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h +++ b/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h @@ -7,6 +7,11 @@ /* Trigger a breakpoint in the analyzer when reached. */ extern void __analyzer_break (void); +/* Emit a warning describing the 2nd argument (which can be of any + type), at the given verbosity level. This is for use when + debugging, and may be of use in DejaGnu tests. */ +extern void __analyzer_describe (int verbosity, ...); + /* Dump copious information about the analyzer’s state when reached. */ extern void __analyzer_dump (void); @@ -20,8 +25,6 @@ extern void __analyzer_dump (void); will also dump all of the states within those nodes. */ extern void __analyzer_dump_exploded_nodes (int); -extern void __analyzer_dump_num_heap_regions (void); - /* Emit a placeholder "note" diagnostic with a path to this call site, if the analyzer finds a feasible path to it. */ extern void __analyzer_dump_path (void); diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer.exp b/gcc/testsuite/gcc.dg/analyzer/analyzer.exp index ac9c495..d72fef3 100644 --- a/gcc/testsuite/gcc.dg/analyzer/analyzer.exp +++ b/gcc/testsuite/gcc.dg/analyzer/analyzer.exp @@ -30,7 +30,7 @@ if [info exists DEFAULT_CFLAGS] then { } # If a testcase doesn't have special options, use these. -set DEFAULT_CFLAGS "-fanalyzer -fdiagnostics-path-format=separate-events -Wanalyzer-too-complex -fanalyzer-call-summaries" +set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -fanalyzer-call-summaries" # Initialize `dg'. dg-init diff --git a/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c b/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c index e0bf1f4..70bb921 100644 --- a/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c +++ b/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c @@ -12,9 +12,10 @@ extern void bar(void *ptrA, void *ptrB, void *ptrC) /* { dg-message "argument 1 void test_1 (void *p, void *q, void *r) { foo(p, q, r); - foo(NULL, q, r); + foo(NULL, q, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */ + /* { dg-message "argument 1 NULL where non-null expected" "note" { target *-*-* } .-1 } */ foo(p, NULL, r); - foo(p, q, NULL); + foo(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" } */ } void test_1a (void *q, void *r) @@ -27,9 +28,10 @@ void test_1a (void *q, void *r) void test_2 (void *p, void *q, void *r) { bar(p, q, r); - bar(NULL, q, r); - bar(p, NULL, r); - bar(p, q, NULL); + bar(NULL, q, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */ + bar(p, NULL, r); /* { dg-warning "use of NULL where non-null expected" "warning" } */ + /* { dg-message "argument 2 NULL where non-null expected" "note" { target *-*-* } .-1 } */ + bar(p, q, NULL); /* { dg-warning "use of NULL where non-null expected" "warning" } */ } void test_3 (void *q, void *r) diff --git a/gcc/testsuite/gcc.dg/analyzer/bzero-1.c b/gcc/testsuite/gcc.dg/analyzer/bzero-1.c new file mode 100644 index 0000000..8945086 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/bzero-1.c @@ -0,0 +1,11 @@ +#include "analyzer-decls.h" + +extern void bzero(void *s, __SIZE_TYPE__ n); + +void test_1 (void) +{ + char tmp[1024]; + bzero (tmp, 1024); + __analyzer_eval (tmp[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (tmp[1023] == 0); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/bzip2-arg-parse-1.c b/gcc/testsuite/gcc.dg/analyzer/bzip2-arg-parse-1.c new file mode 100644 index 0000000..1f1d829 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/bzip2-arg-parse-1.c @@ -0,0 +1,95 @@ +/* Integration test to verify that we don't explode in this + argument-parsing logic. + Adapted from part of bzip2-1.0.8: bzip2.c: main. */ + +#include <stdlib.h> +#include <stdio.h> +#include "analyzer-decls.h" + +/* This test file has been heavily modified from the bzip2.c original, + which has the following license boilerplate. */ +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward <jseward@acm.org> + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + +typedef char Char; +typedef unsigned char Bool; +typedef int Int32; + +#define True ((Bool)1) +#define False ((Bool)0) + +typedef + struct zzzz { + Char *name; + struct zzzz *link; + } + Cell; + +Int32 verbosity; +Bool keepInputFiles, smallMode; +Bool forceOverwrite, noisy; +Int32 blockSize100k; +Int32 opMode; +Int32 srcMode; +Char *progName; + +extern void license ( void ); +extern void usage ( Char *fullProgName ); + +void test (Cell *argList) +{ + Cell *aa; + Int32 i, j; + + for (aa = argList; aa != NULL; aa = aa->link) { + if (aa->name[0] == '-' && aa->name[1] != '-') { + for (j = 1; aa->name[j] != '\0'; j++) { + switch (aa->name[j]) { + case 'c': srcMode = 2; break; + case 'd': opMode = 2; break; + case 'z': opMode = 1; break; + case 'f': forceOverwrite = True; break; + case 't': opMode = 3; break; + case 'k': keepInputFiles = True; break; + case 's': smallMode = True; break; + case 'q': noisy = False; break; + case '1': blockSize100k = 1; break; + case '2': blockSize100k = 2; break; + case '3': blockSize100k = 3; break; + case '4': blockSize100k = 4; break; + case '5': blockSize100k = 5; break; + case '6': blockSize100k = 6; break; + case '7': blockSize100k = 7; break; + case '8': blockSize100k = 8; break; + case '9': blockSize100k = 9; break; + case 'V': + case 'L': license(); break; + case 'v': verbosity++; break; + case 'h': usage ( progName ); + exit ( 0 ); + break; + default: fprintf ( stderr, "%s: Bad flag `%s'\n", + progName, aa->name ); + usage ( progName ); + exit ( 1 ); + break; + } + } + } + } + + /* The analyzer ought to be able to successfully merge all of the + above changes that can reach here into a single state. */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/casts-1.c b/gcc/testsuite/gcc.dg/analyzer/casts-1.c new file mode 100644 index 0000000..15cd85f --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/casts-1.c @@ -0,0 +1,49 @@ +#include "analyzer-decls.h" + +struct s1 +{ + char a; + char b; + char c; + char d; +}; + +struct s2 +{ + char arr[4]; +}; + +void test_1 () +{ + struct s1 x = {'A', 'B', 'C', 'D'}; + __analyzer_eval (x.a == 'A'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.b == 'B'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.c == 'C'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.d == 'D'); /* { dg-warning "TRUE" } */ + __analyzer_eval (((struct s2 *)&x)->arr[0] == 'A'); /* { dg-warning "TRUE" } */ + __analyzer_eval (((struct s2 *)&x)->arr[1] == 'B'); /* { dg-warning "TRUE" } */ + __analyzer_eval (((struct s2 *)&x)->arr[2] == 'C'); /* { dg-warning "TRUE" } */ + __analyzer_eval (((struct s2 *)&x)->arr[3] == 'D'); /* { dg-warning "TRUE" } */ + + ((struct s2 *)&x)->arr[1] = '#'; + __analyzer_eval (((struct s2 *)&x)->arr[1] == '#'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.b == '#'); /* { dg-warning "TRUE" } */ +} + +void test_2 () +{ + struct s2 x = {{'A', 'B', 'C', 'D'}}; + __analyzer_eval (x.arr[0] == 'A'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.arr[1] == 'B'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.arr[2] == 'C'); /* { dg-warning "TRUE" } */ + __analyzer_eval (x.arr[3] == 'D'); /* { dg-warning "TRUE" } */ + struct s1 *p = (struct s1 *)&x; + __analyzer_eval (p->a == 'A'); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + __analyzer_eval (p->b == 'B'); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + __analyzer_eval (p->c == 'C'); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + __analyzer_eval (p->d == 'D'); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/casts-2.c b/gcc/testsuite/gcc.dg/analyzer/casts-2.c new file mode 100644 index 0000000..3eef717 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/casts-2.c @@ -0,0 +1,15 @@ +#include "analyzer-decls.h" + +void test_1 (int i) +{ + char c1 = i; + char c2 = i; + __analyzer_eval (c1 == i); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (c1 == c2); /* { dg-warning "TRUE" } */ +} + +void test_2 (char c) +{ + int i = c; + __analyzer_eval (i == c); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-1.c b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-1.c index bb03487..0f07818 100644 --- a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-1.c @@ -40,13 +40,13 @@ void test_4 (void) struct ptr_wrapper r; r.ptr = malloc (sizeof (int)); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'r.ptr'" } */ -/* { dg-bogus "leak of '<unknown>'" "unknown leak" { xfail *-*-* } .-1 } */ +/* { dg-bogus "leak of '<unknown>'" "unknown leak" { target *-*-* } .-1 } */ static struct ptr_wrapper __attribute__((noinline)) called_by_test_5a (void) { struct ptr_wrapper r; - r.ptr = malloc (sizeof (int)); + r.ptr = malloc (sizeof (int)); /* { dg-message "allocated here" } */ return r; } @@ -54,15 +54,14 @@ void test_5a (void) { struct ptr_wrapper q = called_by_test_5a (); } /* { dg-warning "leak of 'q.ptr'" } */ -/* TODO: show the allocation point. */ static struct ptr_wrapper __attribute__((noinline)) called_by_test_5b (void) { struct ptr_wrapper r; r.ptr = malloc (sizeof (int)); - return r; /* { dg-warning "leak" } */ - /* TODO: show the allocation point. */ + return r; /* { dg-warning "leak of '<return-value>.ptr'" } */ + /* TODO: show the allocation point; improve above message. */ } void test_5b (void) diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-3.c b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-3.c index 5083faa..4925926 100644 --- a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-3.c @@ -22,4 +22,4 @@ test_2 (void) { struct union_wrapper uw2; uw2.u.ptr = malloc (1024); -} /* { dg-warning "leak of '\\(void \\*\\)uw2.u'" } */ +} /* { dg-warning "leak of 'uw2.u.ptr'" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-4.c b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-4.c new file mode 100644 index 0000000..5c0a5f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-4.c @@ -0,0 +1,28 @@ +#include "analyzer-decls.h" + +struct coord +{ + int x; + int y; +}; + +void test_1 (void) +{ + struct coord arr[16]; + + arr[2].y = 4; + arr[3].x = 5; + arr[3].y = 6; + arr[4].x = 7; + arr[6].y = 8; + arr[8].x = 9; + + arr[7] = arr[3]; + + __analyzer_eval (arr[7].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[7].y == 6); /* { dg-warning "TRUE" } */ + + /* Make sure we don't touch the neighbors. */ + __analyzer_eval (arr[6].y == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[8].x == 9); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c new file mode 100644 index 0000000..ccf8fe3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/compound-assignment-5.c @@ -0,0 +1,142 @@ +#include "analyzer-decls.h" + +struct coord +{ + int x; + int y; +}; + +/* Copying from one on-stack array to another. */ + +void test_1 (void) +{ + struct coord arr_a[16]; + struct coord arr_b[16]; + arr_a[3].x = 5; + arr_a[3].y = 6; + + arr_b[7] = arr_a[3]; + + __analyzer_eval (arr_b[7].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr_b[7].y == 6); /* { dg-warning "TRUE" } */ +} + +/* Copying from an on-stack array to a global array. */ + +struct coord glob_arr[16]; + +void test_2 (void) +{ + struct coord arr[16]; + arr[3].x = 5; + arr[3].y = 6; + + glob_arr[7] = arr[3]; + + __analyzer_eval (glob_arr[7].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (glob_arr[7].y == 6); /* { dg-warning "TRUE" } */ +} + +/* Copying from a partially initialized on-stack array to a global array. */ + +struct coord glob_arr[16]; + +void test_3 (void) +{ + struct coord arr[16]; + arr[3].y = 6; + + glob_arr[7] = arr[3]; // or should the uninit warning be here? + + __analyzer_eval (glob_arr[7].x); /* { dg-warning "uninitialized" "uninit" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + __analyzer_eval (glob_arr[7].y == 6); /* { dg-warning "TRUE" } */ +} + +/* Symbolic bindings: copying from one array to another. */ + +struct coord glob_arr[16]; + +void test_4 (int i) +{ + struct coord arr_a[16]; + struct coord arr_b[16]; + arr_a[i].x = 5; + arr_a[i].y = 6; + __analyzer_eval (arr_a[i].x == 5); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ + __analyzer_eval (arr_a[i].y == 6); /* { dg-warning "TRUE" } */ + + arr_b[i] = arr_a[i]; + + __analyzer_eval (arr_b[i].x == 5); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ + __analyzer_eval (arr_b[i].y == 6); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ +} + +/* Symbolic bindings: copying within an array: symbolic src and dest */ + +struct coord glob_arr[16]; + +void test_5a (int i, int j) +{ + struct coord arr[16]; + arr[i].x = 5; + arr[i].y = 6; + + arr[j] = arr[i]; + + __analyzer_eval (arr[j].x == 5); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ + __analyzer_eval (arr[j].y == 6); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ +} + +/* Symbolic bindings: copying within an array: symbolic src, concrete dest. */ + +struct coord glob_arr[16]; + +void test_5b (int i) +{ + struct coord arr[16]; + arr[i].x = 5; + arr[i].y = 6; + + arr[3] = arr[i]; + + __analyzer_eval (arr[3].x == 5); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ + __analyzer_eval (arr[3].y == 6); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ +} + +/* Symbolic bindings: copying within an array: concrete src, symbolic dest. */ + +struct coord glob_arr[16]; + +void test_5c (int i) +{ + struct coord arr[16]; + arr[3].x = 5; + arr[3].y = 6; + + arr[i] = arr[3]; + + __analyzer_eval (arr[i].x == 5); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ + __analyzer_eval (arr[i].y == 6); /* { dg-warning "TRUE" "TRUE" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "UNKNOWN" { xfail *-*-* } .-1 } */ +} + +/* No info on the subregion being copied, and hence + binding_cluster2::maybe_get_compound_binding should return NULL. */ + +void test_6 (void) +{ + struct coord arr[16]; + arr[7] = glob_arr[3]; + + __analyzer_eval (arr[7].x == 5); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (arr[7].y == 6); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/conditionals-notrans.c b/gcc/testsuite/gcc.dg/analyzer/conditionals-notrans.c index a00127b..b1ac541 100644 --- a/gcc/testsuite/gcc.dg/analyzer/conditionals-notrans.c +++ b/gcc/testsuite/gcc.dg/analyzer/conditionals-notrans.c @@ -7,15 +7,12 @@ void test (int i, int j) { __analyzer_eval (i > 4); /* { dg-warning "TRUE" } */ __analyzer_eval (i <= 4); /* { dg-warning "FALSE" } */ - __analyzer_eval (i > 3); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i > 3); /* { dg-warning "TRUE" } */ __analyzer_eval (i > 5); /* { dg-warning "UNKNOWN" } */ - __analyzer_eval (i != 3); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i != 3); /* { dg-warning "TRUE" } */ - __analyzer_eval (i == 3); /* { dg-warning "FALSE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i == 3); /* { dg-warning "FALSE" } */ __analyzer_eval (i != 4); /* { dg-warning "TRUE" } */ __analyzer_eval (i == 4); /* { dg-warning "FALSE" } */ @@ -43,21 +40,17 @@ void test (int i, int j) __analyzer_eval (i <= 4); /* { dg-warning "TRUE" } */ __analyzer_eval (i > 3); /* { dg-warning "UNKNOWN" } */ - __analyzer_eval (i > 5); /* { dg-warning "FALSE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i > 5); /* { dg-warning "FALSE" } */ __analyzer_eval (i != 3); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (i == 3); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (i != 4); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (i == 4); /* { dg-warning "UNKNOWN" } */ - __analyzer_eval (i == 5); /* { dg-warning "FALSE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ - __analyzer_eval (i != 5); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i == 5); /* { dg-warning "FALSE" } */ + __analyzer_eval (i != 5); /* { dg-warning "TRUE" } */ __analyzer_eval (i < 5); /* { dg-warning "TRUE" } */ - __analyzer_eval (i <= 5); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i <= 5); /* { dg-warning "TRUE" } */ } } @@ -101,8 +94,7 @@ void test_range_int_gt_lt (int i) { if (i > 3) if (i < 5) - __analyzer_eval (i == 4); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i == 4); /* { dg-warning "TRUE" } */ } void test_range_float_gt_lt (float f) @@ -116,8 +108,7 @@ void test_range_int_ge_lt (int i) { if (i >= 4) if (i < 5) - __analyzer_eval (i == 4); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i == 4); /* { dg-warning "TRUE" } */ } void test_range_float_ge_lt (float f) @@ -131,8 +122,7 @@ void test_range_int_gt_le (int i) { if (i > 3) if (i <= 4) - __analyzer_eval (i == 4); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i == 4); /* { dg-warning "TRUE" } */ } void test_range_float_gt_le (float f) @@ -146,8 +136,7 @@ void test_range_int_ge_le (int i) { if (i >= 4) if (i <= 4) - __analyzer_eval (i == 4); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (i == 4); /* { dg-warning "TRUE" } */ } void test_range_float_ge_le (float f) diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c index 1db9913..3f16a38 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c @@ -1,3 +1,5 @@ +/* { dg-require-effective-target alloca } */ + #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -179,15 +181,8 @@ int test_12d (struct coord c) { struct coord d; d = c; - __analyzer_eval (d.x == c.x); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "actual" { target *-*-* } .-1 } */ - /* TODO(xfail): c and d share the same unknown value of type "coord", but - attempts to access the fields lead to different unknown values. */ - - __analyzer_eval (d.y == c.y); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "actual" { target *-*-* } .-1 } */ - // TODO(xfail): likewise - + __analyzer_eval (d.x == c.x); /* { dg-warning "TRUE" } */ + __analyzer_eval (d.y == c.y); /* { dg-warning "TRUE" } */ __analyzer_eval (d.x == d.y); /* { dg-warning "UNKNOWN" } */ /* d and c share an unknown value of type "struct coord". But d.x and d.y should be different unknown values (although they inherit @@ -209,25 +204,21 @@ void test_13 (struct outer *o) { __analyzer_eval (o->mid.in.f == 0.f); /* { dg-warning "UNKNOWN" } */ o->mid.in.f = 0.f; - __analyzer_eval (o->mid.in.f == 0.f); /* { dg-warning "TRUE" "PR 93356" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "disabled float comparisons" { target *-*-* } .-1 } */ + __analyzer_eval (o->mid.in.f == 0.f); /* { dg-warning "TRUE" } */ } void test_14 (struct outer o) { __analyzer_eval (o.mid.in.f == 0.f); /* { dg-warning "UNKNOWN" } */ o.mid.in.f = 0.f; - __analyzer_eval (o.mid.in.f == 0.f); /* { dg-warning "TRUE" "PR 93356" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "disabled float comparisons" { target *-*-* } .-1 } */ + __analyzer_eval (o.mid.in.f == 0.f); /* { dg-warning "TRUE" } */ } void test_15 (const char *str) { char ch = str[0]; __analyzer_eval (ch == 'a'); /* { dg-warning "UNKNOWN" } */ - __analyzer_eval (ch == str[0]); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (ch == str[0]); /* { dg-warning "TRUE" } */ ch = 'a'; __analyzer_eval (ch == 'a'); /* { dg-warning "TRUE" } */ @@ -240,15 +231,15 @@ void test_16 (void) __analyzer_eval (msg != NULL); /* { dg-warning "TRUE" } */ - __analyzer_eval (msg[0] == 'h'); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (msg[0] == 'h'); /* { dg-warning "TRUE" } */ - __analyzer_eval (msg[1] == 'e'); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (msg[1] == 'e'); /* { dg-warning "TRUE" } */ __analyzer_eval (strlen (msg) == 11); /* { dg-warning "TRUE" } */ + + /* Out-of-bounds. */ + __analyzer_eval (msg[100] == 'e'); /* { dg-warning "UNKNOWN" } */ + // TODO: some kind of warning for the out-of-bounds access } static const char *__attribute__((noinline)) @@ -263,13 +254,9 @@ void test_16_alt (void) __analyzer_eval (msg != NULL); /* { dg-warning "TRUE" } */ - __analyzer_eval (msg[0] == 'h'); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (msg[0] == 'h'); /* { dg-warning "TRUE" } */ - __analyzer_eval (msg[1] == 'e'); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (msg[1] == 'e'); /* { dg-warning "TRUE" } */ __analyzer_eval (strlen (msg) == 11); /* { dg-warning "TRUE" } */ } @@ -332,9 +319,6 @@ void test_16e (int i) __analyzer_eval (j == i); /* { dg-warning "UNKNOWN" } */ } -/* TODO: and more complicated graph-like examples, where anything that's - reachable from the pointer might be modified. */ - void test_17 (int i) { int j = 42; @@ -475,13 +459,7 @@ void test_23 (struct foo *f, struct foo *g) i = f->i + g->i; j = f->i + g->i; k = f->i * g->i; - __analyzer_eval (i == j); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - /* TODO(xfail): we'd need to record that the two unknown values are both - the sum of the two unknown input values (and thus are the same); not - yet sure if we want arbitrary expression trees in the representation - (analysis termination concerns). */ - + __analyzer_eval (i == j); /* { dg-warning "TRUE" } */ __analyzer_eval (i == k); /* { dg-warning "UNKNOWN" } */ } @@ -494,9 +472,7 @@ void test_24 (struct foo *f) /* Overwriting a whole struct should invalidate our knowledge about fields within it. */ g = *f; - __analyzer_eval (g.i == 42); /* { dg-warning "UNKNOWN" "desired" { xfail *-*-* } } */ - /* { dg-warning "TRUE" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (g.i == 42); /* { dg-warning "UNKNOWN" } */ } void test_25 (struct foo *f) @@ -511,16 +487,14 @@ void test_25 (struct foo *f) source value should update our knowledge about fields within the dest value. */ g = *f; - __analyzer_eval (g.i == 43); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "FALSE" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail) + __analyzer_eval (g.i == 43); /* { dg-warning "TRUE" } */ } void test_26 (struct coord *p, struct coord *q) { p->x = 42; - q->y = 17; - __analyzer_eval (p->x == 42); /* { dg-warning "TRUE" } */ + q->y = 17; /* could clobber p->x. */ + __analyzer_eval (p->x == 42); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (p->y); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (q->x); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (q->y == 17); /* { dg-warning "TRUE" } */ @@ -529,26 +503,21 @@ void test_26 (struct coord *p, struct coord *q) source value should update our knowledge about fields within the dest value. */ *p = *q; - __analyzer_eval (p->x); /* { dg-warning "UNKNOWN" "desired" { xfail *-*-* } } */ - /* { dg-warning "TRUE" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): should have been overwritten + __analyzer_eval (p->x); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (p->y == 17); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ // TODO(xfail): should have been overwritten with q->y __analyzer_eval (q->x); /* { dg-warning "UNKNOWN" } */ - __analyzer_eval (q->y == 17); /* { dg-warning "TRUE" } */ + __analyzer_eval (q->y == 17); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ } void test_27 (struct coord *p) { memset (p, 0, sizeof (struct coord)); - __analyzer_eval (p->x == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): - __analyzer_eval (p->y == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - // TODO(xfail): + __analyzer_eval (p->x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (p->y == 0); /* { dg-warning "TRUE" } */ } void test_28 (struct coord *p) @@ -661,6 +630,8 @@ void test_29a (struct coord p[]) __analyzer_eval (q[-2].y == 107025); /* { dg-warning "TRUE" } */ q -= 2; + __analyzer_eval (q == &p[7]); /* { dg-warning "UNKNOWN" } */ + // TODO: make this be TRUE __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */ __analyzer_eval (q->y == 107025); /* { dg-warning "TRUE" } */ @@ -709,6 +680,7 @@ void test_29b (void) __analyzer_eval (q[-2].y == 107025); /* { dg-warning "TRUE" } */ q -= 2; + __analyzer_eval (q == &p[7]); /* { dg-warning "TRUE" } */ __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */ __analyzer_eval (q->y == 107025); /* { dg-warning "TRUE" } */ @@ -757,6 +729,7 @@ void test_29c (int len) __analyzer_eval (q[-2].y == 107025); /* { dg-warning "TRUE" } */ q -= 2; + __analyzer_eval (q == &p[7]); /* { dg-warning "TRUE" } */ __analyzer_eval (q->x == 107024); /* { dg-warning "TRUE" } */ __analyzer_eval (q->y == 107025); /* { dg-warning "TRUE" } */ @@ -934,12 +907,12 @@ void test_41 (void) union u u; u.i = 42; __analyzer_eval (u.i == 42); /* { dg-warning "TRUE" } */ - __analyzer_eval (u.ptr == NULL); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (u.ptr == NULL); /* { dg-warning "UNKNOWN|FALSE" } */ /* Writes to a union member should invalidate knowledge about other members. */ u.ptr = NULL; __analyzer_eval (u.ptr == NULL); /* { dg-warning "TRUE" } */ - __analyzer_eval (u.i == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (u.i == 42); /* { dg-warning "UNKNOWN|FALSE" } */ } void test_42 (void) @@ -948,8 +921,7 @@ void test_42 (void) float f; i = 42; f = i; - __analyzer_eval (f == 42.0); /* { dg-warning "TRUE" "PR 93356" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "disabled float comparisons" { target *-*-* } .-1 } */ + __analyzer_eval (f == 42.0); /* { dg-warning "TRUE" } */ } void test_43 (void) @@ -1061,10 +1033,8 @@ void test_51 (struct coord c) { struct coord d; memcpy (&d, &c, sizeof (struct coord)); - __analyzer_eval (c.x == d.x); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ - __analyzer_eval (c.y == d.y); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + __analyzer_eval (c.x == d.x); /* { dg-warning "TRUE" } */ + __analyzer_eval (c.y == d.y); /* { dg-warning "TRUE" } */ } struct big diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-13.c b/gcc/testsuite/gcc.dg/analyzer/data-model-13.c index e7cb845..31c1896 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-13.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-13.c @@ -14,8 +14,5 @@ void test_1 (void) void test_2 (void) { global_union.ptr_val = malloc (1024); /* { dg-message "allocated here" } */ - global_union.int_val = 0; -} /* { dg-warning "leak of '<unknown>' " } */ -/* TODO: something better than "<unknown>". */ -/* TODO: better location for the leak. */ - + global_union.int_val = 0; /* { dg-warning "leak of 'global_union.ptr_val' " } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-14.c b/gcc/testsuite/gcc.dg/analyzer/data-model-14.c index f9bb540..1dbcb70 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-14.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-14.c @@ -1,6 +1,3 @@ -/* FIXME: we shouldn't need this. */ -/* { dg-additional-options "-fanalyzer-fine-grained" } */ - #include <stdlib.h> void *global_ptr; @@ -8,14 +5,12 @@ void *global_ptr; void test_1 (int i) { global_ptr = malloc (1024); /* { dg-message "allocated here" } */ - *(int *)&global_ptr = i; /* { dg-warning "leak of '<unknown>'" } */ - // TODO: something better than "<unknown>" here ^^^ + *(int *)&global_ptr = i; /* { dg-warning "leak of 'global_ptr'" } */ } void test_2 (int i) { - void *p = malloc (1024); /* { dg-message "allocated here" "" { xfail *-*-* } } */ - // TODO(xfail) + void *p = malloc (1024); /* { dg-message "allocated here" } */ global_ptr = p; *(int *)&p = i; p = global_ptr; diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-16.c b/gcc/testsuite/gcc.dg/analyzer/data-model-16.c index a8acfbe..616d353 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-16.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-16.c @@ -1,3 +1,5 @@ +/* { dg-require-effective-target label_values } */ + /* Labels as values. */ #include "analyzer-decls.h" diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-18.c b/gcc/testsuite/gcc.dg/analyzer/data-model-18.c index 0a9ae9f..86e8110 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-18.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-18.c @@ -16,7 +16,5 @@ void test (int *p, int i, int j) __analyzer_eval (p[3] == 42); /* { dg-warning "UNKNOWN" } */ __analyzer_eval (p[i] == 17); /* { dg-warning "TRUE" } */ - __analyzer_eval (p[j] == 17); /* { dg-warning "UNKNOWN" "desired" { xfail *-*-* } } */ - /* { dg-bogus "TRUE" "status quo" { xfail *-*-* } .-1 } */ - // FIXME(xfails) ^^^ + __analyzer_eval (p[j] == 17); /* { dg-warning "UNKNOWN" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-20.c b/gcc/testsuite/gcc.dg/analyzer/data-model-20.c new file mode 100644 index 0000000..8fdbb6b --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-20.c @@ -0,0 +1,25 @@ +/* { dg-additional-options "-Wno-analyzer-too-complex" } */ + +#include <stdlib.h> + +struct foo { int dummy; }; + +struct foo ** +test (int n) { + struct foo **arr; + int i; + + if ((arr = (struct foo **)malloc(n * sizeof(struct foo *))) == NULL) + return NULL; + + for (i = 0; i < n; i++) { + if ((arr[i] = (struct foo *)malloc(sizeof(struct foo))) == NULL) { + for (; i >= 0; i++) { + free(arr[i]); /* { dg-bogus "double-'free'" } */ + } + free(arr); + return NULL; + } + } + return arr; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-5.c b/gcc/testsuite/gcc.dg/analyzer/data-model-5.c index 5cf3347..2135c70 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-5.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-5.c @@ -90,11 +90,20 @@ void unref (base_obj *obj) { if (--obj->ob_refcnt == 0) /* { dg-bogus "dereference of uninitialized pointer 'obj'" } */ obj->ob_type->tp_dealloc (obj); + /* { dg-warning "dereference of NULL 'obj'" "deref of NULL" { target *-*-* } .-2 } */ + /* FIXME: ideally we wouldn't issue this, as we've already issued a + warning about str_obj which is now in the "stop" state; the cast + confuses things. */ } void test_1 (const char *str) { base_obj *obj = new_string_obj (str); - //__analyzer_dump(); unref (obj); -} /* { dg-bogus "leak" } */ +} /* { dg-bogus "leak" "" { xfail *-*-* } } */ +/* XFAIL (false leak): + Given that we only know "len" symbolically, this line: + str_obj->str_buf[len] = '\0'; + is a symbolic write which could clobber the ob_type or ob_refcnt. + It reports a leak when following the path where the refcount is clobbered + to be a value that leads to the deallocator not being called. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-5b.c b/gcc/testsuite/gcc.dg/analyzer/data-model-5b.c index 76e351d..cd6a4df 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-5b.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-5b.c @@ -86,8 +86,10 @@ void test_1 (const char *str) //__analyzer_dump(); if (obj) unref (obj); -} /* { dg-bogus "leak of 'obj'" "" { xfail *-*-* } } */ -/* TODO(xfail): the false leak report involves the base_obj.ob_refcnt - being 1, but the string_obj.str_base.ob_refcnt being unknown (when - they ought to be the same region), thus allowing for a path in which - the object is allocated but not freed. */ +} /* { dg-bogus "leak" "" { xfail *-*-* } } */ +/* XFAIL (false leak): + Given that we only know "len" symbolically, this line: + str_obj->str_buf[len] = '\0'; + is a symbolic write which could clobber the ob_type or ob_refcnt. + It reports a leak when following the path where the refcount is clobbered + to be a value that leads to the deallocator not being called. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-5c.c b/gcc/testsuite/gcc.dg/analyzer/data-model-5c.c index 3aba7bd..ad4e1d2 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-5c.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-5c.c @@ -75,9 +75,10 @@ void test_1 (const char *str) string_obj *obj = new_string_obj (str); if (obj) unref (obj); -} /* { dg-bogus "leak of 'obj'" "" { xfail *-*-* } } */ -/* TODO(xfail): the false leak report involves the base_obj.ob_refcnt - being 1, but the string_obj.str_base.ob_refcnt being unknown (when - they ought to be the same region), thus allowing for a path in which - the object is allocated but not freed. */ - +} /* { dg-bogus "leak" "" { xfail *-*-* } } */ +/* XFAIL (false leak): + Given that we only know "len" symbolically, this line: + str_obj->str_buf[len] = '\0'; + is a symbolic write which could clobber the ob_type or ob_refcnt. + It reports a leak when following the path where the refcount is clobbered + to be a value that leads to the deallocator not being called. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-5d.c b/gcc/testsuite/gcc.dg/analyzer/data-model-5d.c index 8c7bfa9..b4d77a9 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-5d.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-5d.c @@ -5,34 +5,33 @@ #include <stdlib.h> #include "analyzer-decls.h" -typedef struct base_obj base_obj; -typedef struct type_obj type_obj; -typedef struct string_obj string_obj; - -struct base_obj +typedef struct base_obj { struct type_obj *ob_type; int ob_refcnt; -}; +} base_obj; -struct type_obj +typedef struct type_obj { base_obj tp_base; -}; + void (*tp_dealloc) (base_obj *); +} type_obj; -struct string_obj +typedef struct boxed_int_obj { - base_obj str_base; - size_t str_len; - char str_buf[]; -}; + base_obj int_base; + int int_val; +} boxed_int_obj; + +extern void int_del (base_obj *); type_obj type_type = { - { &type_type, 1}, + { &type_type, 1} }; -type_obj str_type = { - { &str_type, 1}, +type_obj boxed_int_type = { + { &type_type, 1}, + int_del }; base_obj *alloc_obj (type_obj *ob_type, size_t sz) @@ -45,20 +44,28 @@ base_obj *alloc_obj (type_obj *ob_type, size_t sz) return obj; } +base_obj *new_int_obj (int val) +{ + boxed_int_obj *int_obj + = (boxed_int_obj *)alloc_obj (&boxed_int_type, sizeof (boxed_int_obj)); + if (!int_obj) + return NULL; + int_obj->int_val = val; + return (base_obj *)int_obj; +} + void unref (base_obj *obj) { - //__analyzer_dump(); if (--obj->ob_refcnt == 0) - free (obj); + obj->ob_type->tp_dealloc (obj); } -void test_1 () +void test_1 (const char *str) { - base_obj *obj = alloc_obj (&str_type, sizeof (string_obj)); - if (obj) - { - __analyzer_dump_num_heap_regions (); /* { dg-warning "num heap regions: '1'" } */ - unref (obj); - __analyzer_dump_num_heap_regions (); /* { dg-warning "num heap regions: '0'" } */ - } -} + base_obj *obj = new_int_obj (42); + if (!obj) + return; + __analyzer_eval (((boxed_int_obj *)obj)->int_val == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (obj->ob_refcnt == 1); /* { dg-warning "TRUE" } */ + unref (obj); +} /* { dg-bogus "leak" "" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-6.c b/gcc/testsuite/gcc.dg/analyzer/data-model-6.c deleted file mode 100644 index 78a797e..0000000 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-6.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdlib.h> -#include "analyzer-decls.h" - -/* Verify that we don't accumulate state after a malloc/free pair. */ - -void test (void) -{ - void *ptr; - __analyzer_dump_num_heap_regions (); /* { dg-warning "num heap regions: '0'" } */ - ptr = malloc (1024); - __analyzer_dump_num_heap_regions (); /* { dg-warning "num heap regions: '1'" } */ - free (ptr); - __analyzer_dump_num_heap_regions (); /* { dg-warning "num heap regions: '0'" } */ -} diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-8.c b/gcc/testsuite/gcc.dg/analyzer/data-model-8.c index 939b4c2..3e69d0f 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-8.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-8.c @@ -21,6 +21,5 @@ void test (void) struct base *bp = (struct base *)&s; - __analyzer_eval (bp->i == 3); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + __analyzer_eval (bp->i == 3); /* { dg-warning "TRUE" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/describe-1.c b/gcc/testsuite/gcc.dg/analyzer/describe-1.c new file mode 100644 index 0000000..bc57c6e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/describe-1.c @@ -0,0 +1,11 @@ +/* Smoketest for __analyzer_describe. */ + +#include "analyzer-decls.h" + +void test (int i) +{ + __analyzer_describe (0, 42); /* { dg-warning "svalue: '\\(int\\)42'" } */ + __analyzer_describe (0, i); /* { dg-warning "svalue: 'INIT_VAL\\(i.*\\)'" } */ + __analyzer_describe (0, &i); /* { dg-warning "svalue: '&i'" } */ + /* Further cases would risk overspecifying things. */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/dot-output.c b/gcc/testsuite/gcc.dg/analyzer/dot-output.c index 7b69c62..ff418b1 100644 --- a/gcc/testsuite/gcc.dg/analyzer/dot-output.c +++ b/gcc/testsuite/gcc.dg/analyzer/dot-output.c @@ -18,8 +18,7 @@ int *test (int *buf, int n, int *out) /* A loop, to ensure we have phi nodes. */ for (i = 0; i < n; i++) - result[i] = buf[i] + i; /* { dg-warning "possibly-NULL" "" { xfail *-*-* } } */ - /* TODO(xfail): why isn't the warning appearing? */ + result[i] = buf[i] + i; /* { dg-warning "possibly-NULL" } */ /* Example of a "'" (to test quoting). */ *out = some_call (i, 'a'); diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-1.c b/gcc/testsuite/gcc.dg/analyzer/explode-1.c index 6b62e8e..9b95afd 100644 --- a/gcc/testsuite/gcc.dg/analyzer/explode-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/explode-1.c @@ -47,7 +47,7 @@ void test (void) { default: case 0: - *pp = malloc (16); + *pp = malloc (16); /* { dg-warning "leak" } */ break; case 1: free (*pp); diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-2.c b/gcc/testsuite/gcc.dg/analyzer/explode-2.c index d786aa9..70d8fec 100644 --- a/gcc/testsuite/gcc.dg/analyzer/explode-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/explode-2.c @@ -19,31 +19,31 @@ void test (void) { default: case 0: - p0 = malloc (16); + p0 = malloc (16); /* { dg-warning "leak" } */ break; case 1: - free (p0); /* { dg-warning "double-'free' of 'p0'" } */ + free (p0); /* { dg-warning "double-'free' of 'p0'" "" { xfail *-*-* } } */ break; case 2: - p1 = malloc (16); + p1 = malloc (16); /* { dg-warning "leak" } */ break; case 3: - free (p1); /* { dg-warning "double-'free' of 'p1'" } */ + free (p1); /* { dg-warning "double-'free' of 'p1'" "" { xfail *-*-* } } */ break; case 4: - p2 = malloc (16); + p2 = malloc (16); /* { dg-warning "leak" } */ break; case 5: - free (p2); /* { dg-warning "double-'free' of 'p2'" } */ + free (p2); /* { dg-warning "double-'free' of 'p2'" "" { xfail *-*-* } } */ break; case 6: - p3 = malloc (16); + p3 = malloc (16); /* { dg-warning "leak" } */ break; case 7: - free (p3); /* { dg-warning "double-'free' of 'p3'" } */ + free (p3); /* { dg-warning "double-'free' of 'p3'" "" { xfail *-*-* } } */ break; } } diff --git a/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c b/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c new file mode 100644 index 0000000..f2a8a4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c @@ -0,0 +1,62 @@ +#include "analyzer-decls.h" + +void test_1 (void) +{ + __analyzer_dump_path (); /* { dg-message "path" } */ +} + +void test_2 (int flag) +{ + if (flag) + __analyzer_dump_path (); /* { dg-message "path" } */ +} + +void test_3 (int flag) +{ + if (flag) + if (!flag) + __analyzer_dump_path (); /* { dg-bogus "path" } */ +} + +int global_for_test_4; +static void __attribute__((noinline)) called_by_test_4 () {} +void test_4 (void) +{ + /* Verify that a state change that happens in a stmt that + isn't the first within its BB can affect path feasibility. */ + global_for_test_4 = 0; + global_for_test_4 = 1; + /* Thwart the optimizer. */ + called_by_test_4 (); + if (global_for_test_4) + __analyzer_dump_path (); /* { dg-message "path" } */ +} + +/* Verify that loops don't confuse the feasibility checker. */ + +void test_5 (void) +{ + for (int i = 0; i < 1024; i++) + { + } + __analyzer_dump_path (); /* { dg-message "path" } */ +} + +/* Reproducer for an issue seen with CVE-2005-1689 (PR analyzer/96374): if we + take the shortest path and update state and check feasibility per-edge, we + can erroneously reject valid diagnostics. */ + +int test_6 (int a, int b) +{ + int problem = 0; + if (a) + problem = 1; + if (b) + { + if (!problem) + problem = 2; + __analyzer_dump_path (); /* { dg-message "path" "" { xfail *-*-* } } */ + /* XFAIL is PR analyzer/96374. */ + } + return problem; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/feasibility-2.c b/gcc/testsuite/gcc.dg/analyzer/feasibility-2.c new file mode 100644 index 0000000..9fe62d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/feasibility-2.c @@ -0,0 +1,20 @@ +/* Verify that -fno-analyzer-feasibility works. */ +/* { dg-additional-options "-fno-analyzer-feasibility" } */ + +#include "analyzer-decls.h" + +void test_1 (int flag) +{ + int a; + if (flag) + a = 1; + else + a = 2; + + if (a == 1) /* (can only be the case when "flag" was true above). */ + if (!flag) + { + __analyzer_dump_path (); /* { dg-message "note: path" "path diag" } */ + /* { dg-message "infeasible" "infeasibility event" { target *-*-* } .-1 } */ + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/first-field-1.c b/gcc/testsuite/gcc.dg/analyzer/first-field-1.c new file mode 100644 index 0000000..8b71e1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/first-field-1.c @@ -0,0 +1,24 @@ +#include "analyzer-decls.h" + +typedef struct base_obj +{ + int m_first; + int m_second; +} base_obj; + +typedef struct sub_obj +{ + base_obj base; +} sub_obj; + +void test (sub_obj *sub) +{ + sub->base.m_first = 1; + sub->base.m_second = 2; + __analyzer_eval (sub->base.m_first == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (sub->base.m_second == 2); /* { dg-warning "TRUE" } */ + + base_obj *base = (struct base_obj *)sub; + __analyzer_eval (base->m_first == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (base->m_second == 2); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/first-field-2.c b/gcc/testsuite/gcc.dg/analyzer/first-field-2.c new file mode 100644 index 0000000..2fb98d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/first-field-2.c @@ -0,0 +1,33 @@ +/* A toy re-implementation of CPython's object model. */ + +#include <stdlib.h> +#include <string.h> + +#include "analyzer-decls.h" + +typedef struct base_obj base_obj; +typedef struct string_obj string_obj; + +struct base_obj +{ + int ob_refcnt; +}; + +struct string_obj +{ + base_obj str_base; + size_t str_len; + char str_buf[]; +}; + +base_obj *alloc_obj (const char *str) +{ + size_t len = strlen (str); + base_obj *obj = (base_obj *)malloc (sizeof (string_obj) + len + 1); + if (!obj) + return NULL; + obj->ob_refcnt = 1; + string_obj *str_obj = (string_obj *)obj; + __analyzer_eval (str_obj->str_base.ob_refcnt == 1); /* { dg-warning "TRUE" } */ + return obj; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/getchar-1.c b/gcc/testsuite/gcc.dg/analyzer/getchar-1.c new file mode 100644 index 0000000..25595e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/getchar-1.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#include "analyzer-decls.h" + +int test_1 (void) +{ + int c = getchar (); + return c; +} + +int glob_2; +int test_2 (void) +{ + int c; + glob_2 = 42; + __analyzer_eval (glob_2 == 42); /* { dg-warning "TRUE" } */ + c = getchar (); + __analyzer_eval (glob_2 == 42); /* { dg-warning "TRUE" } */ + return c; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/init.c b/gcc/testsuite/gcc.dg/analyzer/init.c new file mode 100644 index 0000000..e51d88e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/init.c @@ -0,0 +1,136 @@ +/* Tests of brace-enclosed initializers + Some of these use the CONSTRUCTOR tree code, but it appears + only for a full zero-init; it appears that by the time the analyzer + runs that this initialization has been converted into field-wise + gimple assign stmts, with just "zero-init everything" CONSTRUCTORs + and "clobber" CONSTRUCTORs. */ + +#include "analyzer-decls.h" + +struct coord +{ + int x; + int y; +}; + +struct tri +{ + struct coord v[3]; +}; + +union iap +{ + int i; + void *p; +}; + +void test_1 (void) +{ + struct coord c = {3, 4}; + __analyzer_eval (c.x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c.y == 4); /* { dg-warning "TRUE" } */ +} + +void test_2 (void) +{ + struct coord c = {3}; + __analyzer_eval (c.x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c.y == 0); /* { dg-warning "TRUE" } */ +} + +void test_3 (void) +{ + struct coord c = {}; + __analyzer_eval (c.x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c.y == 0); /* { dg-warning "TRUE" } */ +} + +void test_4 (void) +{ + int c[2] = {3, 4}; + __analyzer_eval (c[0] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1] == 4); /* { dg-warning "TRUE" } */ +} + +void test_5 (void) +{ + int c[2] = {3}; + __analyzer_eval (c[0] == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1] == 0); /* { dg-warning "TRUE" } */ +} + +void test_6 (void) +{ + int c[2] = {}; + __analyzer_eval (c[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1] == 0); /* { dg-warning "TRUE" } */ +} + +void test_7 (void) +{ + struct coord c[2] = {{3, 4}, {5, 6}}; + __analyzer_eval (c[0].x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[0].y == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].y == 6); /* { dg-warning "TRUE" } */ +} + +void test_8 (void) +{ + struct coord c[2] = {{3}, {5}}; + __analyzer_eval (c[0].x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[0].y == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].y == 0); /* { dg-warning "TRUE" } */ +} + +void test_9 (void) +{ + struct coord c[2] = {{}, {}}; + __analyzer_eval (c[0].x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[0].y == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].y == 0); /* { dg-warning "TRUE" } */ +} + +void test_10 (void) +{ + struct coord c[2] = {{.y = 4, .x = 3}, {5, 6}}; + __analyzer_eval (c[0].x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[0].y == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].y == 6); /* { dg-warning "TRUE" } */ +} + +void test_11 (void) +{ + struct coord c[2] = {{.y = 4}, {5, 6}}; + __analyzer_eval (c[0].x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[0].y == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (c[1].y == 6); /* { dg-warning "TRUE" } */ +} + +void test_12 (void) +{ + struct tri t = {}; + __analyzer_eval (t.v[0].x == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (t.v[2].y == 0); /* { dg-warning "TRUE" } */ +} + +void test_13 (void) +{ + struct tri t = {3, 4, 5, 6, 7, 8}; + __analyzer_eval (t.v[0].x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (t.v[0].y == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (t.v[1].x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (t.v[1].y == 6); /* { dg-warning "TRUE" } */ + __analyzer_eval (t.v[2].x == 7); /* { dg-warning "TRUE" } */ + __analyzer_eval (t.v[2].y == 8); /* { dg-warning "TRUE" } */ +} + +void test_14 (void) +{ + union iap u = {}; + __analyzer_eval (u.i == 0); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/leak-2.c b/gcc/testsuite/gcc.dg/analyzer/leak-2.c new file mode 100644 index 0000000..bba3e81 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/leak-2.c @@ -0,0 +1,9 @@ +#include <stdlib.h> + +void *ptr; + +void *test (void) +{ + ptr = malloc (1024); + ptr = NULL; /* { dg-warning "leak of 'ptr'" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c new file mode 100644 index 0000000..2b03527 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c @@ -0,0 +1,74 @@ +#include <stdlib.h> + +#include "analyzer-decls.h" + +struct iter +{ + int start; + int end; + int step; + int val; +}; + +struct iter * __attribute__((noinline)) +iter_new (int start, int end, int step) +{ + struct iter *it = (struct iter *)malloc (sizeof (struct iter)); + if (!it) + abort (); + it->start = start; + it->end = end; + it->step = step; + it->val = start; + return it; +} + +int __attribute__((noinline)) +iter_done_p (struct iter *it) +{ + return it->val >= it->end; +} + +void __attribute__((noinline)) +iter_next (struct iter *it) +{ + it->val += it->step; +} + +/* Example of an iterator object, to see how well we cope with a well-disguised + iteration from 0 to n with a step of 1. */ + +void test(int n) +{ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + struct iter *it = iter_new (0, n, 1); + while (!iter_done_p (it)) + { + __analyzer_eval (it->val < n); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + __analyzer_eval (it->val == 0); /* { dg-warning "TRUE" "true on 1st iter" } */ + /* { dg-warning "UNKNOWN" "unknown" { target *-*-* } .-1 } */ + /* TODO: should we ought to figure out i > 0 after 1st iteration? */ + + __analyzer_eval (it->val >= 0); /* { dg-warning "TRUE" } */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + + iter_next (it); + } + + __analyzer_eval (it->val >= n); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + + __analyzer_eval (it->val == n); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256. */ + + free (it); + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + // TODO: why 2 enodes here, rather than 1 +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c new file mode 100644 index 0000000..d49ed13 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c @@ -0,0 +1,31 @@ +#include "analyzer-decls.h" + +void test(int n) +{ + int i; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (i = 0; i < n; i++) { + __analyzer_eval (i < n); /* { dg-warning "TRUE" } */ + /* (should report TRUE twice). */ + + __analyzer_eval (i == 0); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + __analyzer_eval (i >= 0); /* { dg-warning "TRUE" } */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + __analyzer_eval (i >= n); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + + __analyzer_eval (i == n); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-2a.c b/gcc/testsuite/gcc.dg/analyzer/loop-2a.c index a392ffc..16b6449 100644 --- a/gcc/testsuite/gcc.dg/analyzer/loop-2a.c +++ b/gcc/testsuite/gcc.dg/analyzer/loop-2a.c @@ -14,10 +14,7 @@ void test(void) for (u.i=0; u.i<256; u.i++) { - __analyzer_eval (u.i < 256); /* { dg-warning "TRUE" "1st" } */ - /* { dg-warning "TRUE" "2nd" { xfail *-*-* } .-1 } */ - /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-2 } */ - /* (should report TRUE twice). */ + __analyzer_eval (u.i < 256); /* { dg-warning "TRUE" } */ __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ @@ -26,11 +23,10 @@ void test(void) /* TODO(xfail^^^): we're only capturing the first iteration, so we erroneously get i == 0. */ - //__analyzer_eval (u.i >= 0); /* { d-todo-g-warning "TRUE" } */ + __analyzer_eval (u.i >= 0); /* { dg-warning "TRUE" } */ } - __analyzer_eval (u.i >= 256); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + __analyzer_eval (u.i >= 256); /* { dg-warning "TRUE" } */ __analyzer_eval (u.i == 256); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-3.c b/gcc/testsuite/gcc.dg/analyzer/loop-3.c index 1d01771..0bcf707 100644 --- a/gcc/testsuite/gcc.dg/analyzer/loop-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/loop-3.c @@ -6,11 +6,8 @@ void test(int c) char *buffer = (char*)malloc(256); for (i=0; i<255; i++) { - buffer[i] = c; /* { dg-warning "use after 'free' of 'buffer'" } */ - /* BUG: the malloc could have failed - TODO: the checker doesn't yet pick up on this, perhaps - due to the pointer arithmetic not picking up on the - state */ + buffer[i] = c; /* { dg-warning "use after 'free' of 'buffer'" "use after free" { xfail *-*-* } } */ + /* { dg-warning "possibly-NULL 'buffer'" "deref of unchecked" { target *-*-* } .-1 } */ free(buffer); /* { dg-warning "double-'free' of 'buffer'" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-4.c b/gcc/testsuite/gcc.dg/analyzer/loop-4.c index e5767de..b66a345 100644 --- a/gcc/testsuite/gcc.dg/analyzer/loop-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/loop-4.c @@ -1,6 +1,3 @@ -// FIXME: -/* { dg-additional-options "-fno-analyzer-state-purge" } */ - /* Example of nested loops. */ #include "analyzer-decls.h" @@ -13,8 +10,7 @@ void test(void) for (i=0; i<256; i++) { - __analyzer_eval (i >= 0); /* { dg-warning "TRUE" "true" } */ - /* { dg-warning "UNKNOWN" "unknown" { target *-*-* } .-1 } */ + __analyzer_eval (i >= 0); /* { dg-warning "TRUE" } */ __analyzer_eval (i < 256); /* { dg-warning "TRUE" } */ @@ -23,7 +19,9 @@ void test(void) __analyzer_eval (j >= 0); /* { dg-warning "TRUE" "true" } */ /* { dg-warning "UNKNOWN" "unknown" { target *-*-* } .-1 } */ - __analyzer_eval (j < 256); /* { dg-warning "TRUE" } */ + __analyzer_eval (j < 256); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ @@ -32,7 +30,8 @@ void test(void) __analyzer_eval (k >= 0); /* { dg-warning "TRUE" "true" } */ /* { dg-warning "UNKNOWN" "unknown" { target *-*-* } .-1 } */ - __analyzer_eval (k < 256); /* { dg-warning "TRUE" } */ + __analyzer_eval (k < 256); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 processed enodes" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c new file mode 100644 index 0000000..553cd2f --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c @@ -0,0 +1,35 @@ +#include "analyzer-decls.h" + +void test(int n) +{ + int i; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (i = n; i > 0; i--) { + __analyzer_eval (i > 0); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ + + __analyzer_eval (i == n); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + __analyzer_eval (i <= n); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "TRUE" "2nd" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i >= 0 for all iterations. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + __analyzer_eval (i <= 0); /* { dg-warning "TRUE" "true" } */ + + + __analyzer_eval (i == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c new file mode 100644 index 0000000..3513bf4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c @@ -0,0 +1,35 @@ +#include "analyzer-decls.h" + +void test(int start, int end, int step) +{ + int i; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (i = start; i > end; i --) { + __analyzer_eval (i > end); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ + + __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + __analyzer_eval (i <= start); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + __analyzer_eval (i >= end); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + + // FIXME: do we know this? What if we overshoot? + __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c new file mode 100644 index 0000000..2692c50 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c @@ -0,0 +1,30 @@ +#include "analyzer-decls.h" + +void test(int start, int end, int step) +{ + int i; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (i = start; i > end; i -= step) { + __analyzer_eval (i > end); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ + + __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + /* We don't know the direction of step. */ + __analyzer_eval (i <= start); /* { dg-warning "TRUE" "true" } */ + /* { dg-warning "UNKNOWN" "unknown" { target *-*-* } .-1 } */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + __analyzer_eval (i <= end); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c new file mode 100644 index 0000000..3fc1362 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c @@ -0,0 +1,36 @@ +#include "analyzer-decls.h" + +void test(int start, int end, int step) +{ + int i; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (i = start; i < end; i += step) { + __analyzer_eval (i < end); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ + + __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + /* We don't know the direction of step. */ + __analyzer_eval (i >= start); /* { dg-warning "TRUE" "true" } */ + /* { dg-warning "UNKNOWN" "unknown" { target *-*-* } .-1 } */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + // FIXME: do we know this? What about direction of step? + __analyzer_eval (i >= end); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + + // FIXME: do we know this? What if we overshoot? + __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c new file mode 100644 index 0000000..5e21890 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c @@ -0,0 +1,32 @@ +#include "analyzer-decls.h" + +void test(int start, int end) +{ + int i; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (i = start; i < end; i++) { + __analyzer_eval (i < end); /* { dg-warning "TRUE" "true" } */ + + __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */ + /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ + /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ + + __analyzer_eval (i >= start); /* { dg-warning "TRUE" "true" } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + /* TODO(xfail^^^): should report TRUE twice. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + __analyzer_eval (i >= end); /* { dg-warning "TRUE" "true" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "unknown" { xfail *-*-* } .-1 } */ + + __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */ + /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */ + /* TODO(xfail^^^): it only figures out i >= end, rather than i == end. */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/loop.c b/gcc/testsuite/gcc.dg/analyzer/loop.c index 37b757b..c4cfd88 100644 --- a/gcc/testsuite/gcc.dg/analyzer/loop.c +++ b/gcc/testsuite/gcc.dg/analyzer/loop.c @@ -1,5 +1,3 @@ -/* { dg-additional-options "-fno-analyzer-state-purge" } */ - #include "analyzer-decls.h" void test(void) @@ -12,15 +10,12 @@ void test(void) __analyzer_eval (i < 256); /* { dg-warning "TRUE" } */ /* (should report TRUE twice). */ - __analyzer_eval (i == 0); /* { dg-warning "TRUE" "1st" } */ + __analyzer_eval (i == 0); /* { dg-warning "TRUE" } */ /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */ /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration. */ - __analyzer_eval (i >= 0); /* { dg-warning "TRUE" "1st" } */ - /* { dg-warning "TRUE" "2nd" { xfail *-*-* } } */ - /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */ - /* TODO(xfail^^^): ideally we ought to figure out i >= 0 for all iterations. */ + __analyzer_eval (i >= 0); /* { dg-warning "TRUE" } */ __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c index 3024e546..c3e1330 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c @@ -1,3 +1,5 @@ +/* { dg-require-effective-target alloca } */ + #include <alloca.h> #include <stdlib.h> @@ -358,7 +360,7 @@ void test_30 (void) struct link tmp; tmp.m_ptr = (struct link *)malloc (sizeof (struct link)); /* { dg-message "allocated here" } */ } /* { dg-warning "leak of 'tmp.m_ptr'" } */ -/* { dg-bogus "leak of '<unknown>'" "" { xfail *-*-* } .-1 } */ +/* { dg-bogus "leak of '<unknown>'" "leak of unknown" { target *-*-* } .-1 } */ void test_31 (void) { @@ -366,7 +368,7 @@ void test_31 (void) void *ptr = malloc (sizeof (struct link)); /* { dg-message "allocated here" } */ tmp.m_ptr = (struct link *)ptr; } /* { dg-warning "leak of 'ptr'" } */ -/* { dg-bogus "leak of 'tmp.m_ptr'" "" { xfail *-*-* } .-1 } */ +/* { dg-bogus "leak of 'tmp.m_ptr'" "" { target *-*-* } .-1 } */ void test_32 (void) { @@ -505,8 +507,7 @@ void test_42c (void) void *p = malloc (1024); void *q = p + 64; free (q - 64); /* this is probably OK. */ -} /* { dg-bogus "leak of 'p'" "" { xfail *-*-* } } */ -// TODO(xfail) +} /* { dg-bogus "leak of 'p'" } */ #if 0 void test_31 (void *p) @@ -529,10 +530,8 @@ struct link global_link; void test_43 (void) { global_link.m_ptr = malloc (sizeof (struct link)); /* { dg-message "allocated here" } */ - global_link.m_ptr = NULL; -} /* { dg-warning "leak of '<unknown>'" } */ -/* TODO: should be more precise than just '<unknown>', and - ideally would be at the assigment to NULL. */ + global_link.m_ptr = NULL; /* { dg-warning "leak of 'global_link.m_ptr'" } */ +} struct link *global_ptr; @@ -589,3 +588,16 @@ void test_48 (void) int *p = NULL; /* { dg-message "'p' is NULL" } */ *p = 1; /* { dg-warning "dereference of NULL 'p'" } */ } + +/* As test_48, but where the assignment of NULL is not at the start of a BB. */ + +int test_49 (int i) +{ + int *p; + int x; + + x = i * 2; + p = NULL; /* { dg-message "'p' is NULL" } */ + *p = 1; /* { dg-warning "dereference of NULL 'p'" } */ + return x; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-4.c b/gcc/testsuite/gcc.dg/analyzer/malloc-4.c index c9c275a..908bb28 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-4.c @@ -10,11 +10,11 @@ void *hv (struct foo **tm) *tm = p; if (!p) abort (); - return p; /* { dg-warning "leak of 'tm'" } */ + return p; } void a5 (void) { struct bar *qb = NULL; hv (&qb); -} /* { dg-warning "leak of '\\(struct foo \\*\\)qb'" } */ +} /* { dg-warning "leak of 'qb'" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-in-loop.c b/gcc/testsuite/gcc.dg/analyzer/malloc-in-loop.c new file mode 100644 index 0000000..a8c85a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-in-loop.c @@ -0,0 +1,19 @@ +#include <stdlib.h> +#include "analyzer-decls.h" + +extern void foo (int *); + +void test (int n) +{ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + for (int i = 0; i < n; i++) + { + int *ptr = (int *)malloc (sizeof (int) * i); + foo (ptr); + free (ptr); + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + } + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c index f86e8ac..580862b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c @@ -1,6 +1,6 @@ /* Example of a multilevel wrapper around malloc/free, with a double-'free'. */ -/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes -fdiagnostics-show-caret" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ #include <stdlib.h> @@ -61,111 +61,133 @@ void test (int i) | | | | | (2) calling 'make_boxed_int' from 'test' | - +--> 'make_boxed_int': events 3-6 + +--> 'make_boxed_int': events 3-4 | | NN | make_boxed_int (int i) | | ^~~~~~~~~~~~~~ | | | | | (3) entry to 'make_boxed_int' - |...... + | NN | { + | NN | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); + | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | + | | (4) calling 'wrapped_malloc' from 'make_boxed_int' + | + +--> 'wrapped_malloc': events 5-6 + | + | NN | void *wrapped_malloc (size_t size) + | | ^~~~~~~~~~~~~~ + | | | + | | (5) entry to 'wrapped_malloc' + | NN | { + | NN | return malloc (size); + | | ~~~~~~~~~~~~~ + | | | + | | (6) allocated here + | + <------+ + | + 'make_boxed_int': events 7-10 + | + | NN | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); + | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | + | | (7) returning to 'make_boxed_int' from 'wrapped_malloc' | NN | if (!result) - | | ~ + | | ~ | | | - | | (4) following 'false' branch (when 'result' is non-NULL)... + | | (8) assuming 'result' is non-NULL + | | (9) following 'false' branch (when 'result' is non-NULL)... | NN | abort (); | NN | result->i = i; - | | ~~~~~~~~~~~~~ + | | ~~~~~~~~~~~~~ | | | - | | (5) ...to here - | NN | return result; - | | ~~~~~~ - | | | - | | (6) state of '<return-value>': 'start' -> 'nonnull' (origin: NULL) + | | (10) ...to here | <------+ | - 'test': events 7-8 + 'test': events 11-12 | | NN | boxed_int *obj = make_boxed_int (i); | | ^~~~~~~~~~~~~~~~~~ | | | - | | (7) returning to 'test' from 'make_boxed_int' + | | (11) returning to 'test' from 'make_boxed_int' | NN | | NN | free_boxed_int (obj); | | ~~~~~~~~~~~~~~~~~~~~ | | | - | | (8) calling 'free_boxed_int' from 'test' + | | (12) calling 'free_boxed_int' from 'test' | - +--> 'free_boxed_int': events 9-10 + +--> 'free_boxed_int': events 13-14 | | NN | free_boxed_int (boxed_int *bi) | | ^~~~~~~~~~~~~~ | | | - | | (9) entry to 'free_boxed_int' + | | (13) entry to 'free_boxed_int' | NN | { | NN | wrapped_free (bi); | | ~~~~~~~~~~~~~~~~~ | | | - | | (10) calling 'wrapped_free' from 'free_boxed_int' + | | (14) calling 'wrapped_free' from 'free_boxed_int' | - +--> 'wrapped_free': events 11-12 + +--> 'wrapped_free': events 15-16 | | NN | void wrapped_free (void *ptr) | | ^~~~~~~~~~~~ | | | - | | (11) entry to 'wrapped_free' + | | (15) entry to 'wrapped_free' | NN | { | NN | free (ptr); | | ~~~~~~~~~~ | | | - | | (12) first 'free' here (state of 'ptr': 'nonnull' -> 'freed', origin: NULL) + | | (16) first 'free' here | <------+ | - 'free_boxed_int': event 13 + 'free_boxed_int': event 17 | | NN | wrapped_free (bi); | | ^~~~~~~~~~~~~~~~~ | | | - | | (13) returning to 'free_boxed_int' from 'wrapped_free' + | | (17) returning to 'free_boxed_int' from 'wrapped_free' | <------+ | - 'test': events 14-15 + 'test': events 18-19 | | NN | free_boxed_int (obj); | | ^~~~~~~~~~~~~~~~~~~~ | | | - | | (14) returning to 'test' from 'free_boxed_int' + | | (18) returning to 'test' from 'free_boxed_int' | NN | | NN | free_boxed_int (obj); | | ~~~~~~~~~~~~~~~~~~~~ | | | - | | (15) passing freed pointer 'obj' in call to 'free_boxed_int' from 'test' + | | (19) passing freed pointer 'obj' in call to 'free_boxed_int' from 'test' | - +--> 'free_boxed_int': events 16-17 + +--> 'free_boxed_int': events 20-21 | | NN | free_boxed_int (boxed_int *bi) | | ^~~~~~~~~~~~~~ | | | - | | (16) entry to 'free_boxed_int' + | | (20) entry to 'free_boxed_int' | NN | { | NN | wrapped_free (bi); | | ~~~~~~~~~~~~~~~~~ | | | - | | (17) passing freed pointer 'bi' in call to 'wrapped_free' from 'free_boxed_int' + | | (21) passing freed pointer 'bi' in call to 'wrapped_free' from 'free_boxed_int' | - +--> 'wrapped_free': events 18-19 + +--> 'wrapped_free': events 22-23 | | NN | void wrapped_free (void *ptr) | | ^~~~~~~~~~~~ | | | - | | (18) entry to 'wrapped_free' + | | (22) entry to 'wrapped_free' | NN | { | NN | free (ptr); | | ~~~~~~~~~~ | | | - | | (19) second 'free' here; first 'free' was at (12) ('ptr' is in state 'freed') + | | (23) second 'free' here; first 'free' was at (16) | { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c index a778a29..3200447 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c @@ -1,6 +1,6 @@ /* Example of a multilevel wrapper around malloc, with an unchecked write. */ -/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret -fanalyzer-verbose-state-changes" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ #include <stdlib.h> @@ -49,7 +49,7 @@ make_boxed_int (int i) | NN | return malloc (size); | | ~~~~~~~~~~~~~ | | | - | | (4) this call could return NULL (state of '<return-value>': 'start' -> 'unchecked', origin: NULL) + | | (4) this call could return NULL | <------+ | @@ -62,6 +62,6 @@ make_boxed_int (int i) | NN | result->i = i; | | ~~~~~~~~~~~~~ | | | - | | (6) 'result' could be NULL: unchecked value from (4) ('result' is in state 'unchecked') + | | (6) 'result' could be NULL: unchecked value from (4) | { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-8.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-8.c index 10b97a0..35c9385 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-8.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-8.c @@ -1,4 +1,5 @@ /* { dg-additional-options "-fanalyzer-transitivity" } */ +/* { dg-require-effective-target alloca } */ #include <stddef.h> #include <alloca.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c index c5ff96e..a3cacc0 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c @@ -112,8 +112,7 @@ int test_3 (int x, int y) free (ptr); /* No double-'free' warning: we've already attempted to dereference it above. */ return *ptr; /* { dg-warning "use after 'free' of 'ptr'" "use-after-free" } */ - // TODO: two warnings here: one is from sm-malloc, the other from region model - /* { dg-warning "leak of 'ptr'" "leak" { target *-*-* } .-2 } */ + /* { dg-warning "leak of 'ptr'" "leak" { target *-*-* } .-1 } */ } /* "dereference of possibly-NULL 'ptr'". */ @@ -241,59 +240,3 @@ int test_3 (int x, int y) | | (7) 'ptr' leaks here; was allocated at (1) | { dg-end-multiline-output "" } */ - -/* "use after 'free' of 'ptr'". */ -/* { dg-begin-multiline-output "" } - NN | *ptr = 19; - | ~~~~~^~~~ - 'test_3': events 1-3 - | - | NN | if (x) - | | ^ - | | | - | | (1) following 'true' branch (when 'x != 0')... - | NN | free (ptr); - | | ~~~~~~~~~~ - | | | - | | (2) ...to here - | NN | - | NN | *ptr = 19; - | | ~~~~~~~~~ - | | | - | | (3) use after 'free' of 'ptr' here - | - { dg-end-multiline-output "" } */ - -/* "use after 'free' of 'ptr'". */ -/* { dg-begin-multiline-output "" } - NN | return *ptr; - | ^~~~ - 'test_3': events 1-5 - | - | NN | if (x) - | | ^ - | | | - | | (1) following 'false' branch (when 'x == 0')... - |...... - | NN | *ptr = 19; - | | ~~~~~~~~~ - | | | - | | (2) ...to here - |...... - | NN | if (y) - | | ~ - | | | - | | (3) following 'true' branch (when 'y != 0')... - | NN | free (ptr); - | | ~~~~~~~~~~ - | | | - | | (4) ...to here - | NN | to dereference it above - | NN | return *ptr; - | | ~~~~ - | | | - | | (5) use after 'free' of 'ptr' here - | - { dg-end-multiline-output "" } */ -/* TODO: this is really a duplicate; can we either eliminate it, or - improve the path? */ diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1a.c b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1a.c index d47dfa8..bf77862 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1a.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1a.c @@ -11,7 +11,7 @@ do_stuff (int *p, int n) int sum = 0; int i; for (i = 0; i < n; i++) - p[i] = i; + p[i] = i; /* { dg-warning "dereference of possibly-NULL 'p'" } */ for (i = 0; i < n; i++) sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ return sum; @@ -48,10 +48,10 @@ int test_repeated_predicate_1 (int n) result = do_stuff (ptr, n); - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ - // FIXME: why 3 here? - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ - // FIXME: why 3 here? + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + if (n > 10) free (ptr); /* { dg-bogus "not on the heap" } */ @@ -105,8 +105,8 @@ int test_explicit_flag (int n) result = do_stuff (ptr, n); - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ - // FIXME: why 3 here? + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + if (need_to_free) free (ptr); /* { dg-bogus "not on the heap" } */ @@ -131,8 +131,8 @@ int test_pointer_comparison (int n) result = do_stuff (ptr, n); - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ - // FIXME: why 3 here? + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + if (ptr != buf) free (ptr); /* { dg-bogus "not on the heap" } */ @@ -169,8 +169,8 @@ int test_initial_flag (int n) result = do_stuff (ptr, n); - __analyzer_dump_exploded_nodes (0); /* { dg-warning "5 processed enodes" } */ - // FIXME: why 5 here? + __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + // FIXME: why 3 here? if (n > 10) free (ptr); /* { dg-bogus "not on the heap" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c index 89bd511..9001fe6 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c @@ -31,13 +31,13 @@ int test_repeated_predicate_1 (int n) int sum = 0; int i; for (i = 0; i < n; i++) - p[i] = i; + p[i] = i; /* { dg-warning "dereference of possibly-NULL" } */ for (i = 0; i < n; i++) sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ result = sum; } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ if (n > 10) free (ptr); /* { dg-bogus "not on the heap" } */ @@ -65,11 +65,11 @@ int test_repeated_predicate_1a (int n) int sum = 0; int i; for (i = 0; i < n; i++) - p[i] = i; + p[i] = i; /* { dg-warning "dereference of possibly-NULL" } */ result = sum; } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ if (n > 10) free (ptr); /* { dg-bogus "not on the heap" } */ @@ -126,13 +126,13 @@ int test_explicit_flag (int n) int sum = 0; int i; for (i = 0; i < n; i++) - p[i] = i; + p[i] = i; /* { dg-warning "dereference of possibly-NULL" } */ for (i = 0; i < n; i++) sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ result = sum; } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ if (need_to_free) free (ptr); /* { dg-bogus "not on the heap" } */ @@ -160,13 +160,13 @@ int test_pointer_comparison (int n) int sum = 0; int i; for (i = 0; i < n; i++) - p[i] = i; + p[i] = i; /* { dg-warning "dereference of possibly-NULL" } */ for (i = 0; i < n; i++) sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ result = sum; } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ if (ptr != buf) free (ptr); /* { dg-bogus "not on the heap" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c index d20a275..0196389 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c @@ -30,16 +30,15 @@ int test_1 (int n) int sum = 0; int i; for (i = 0; i < n; i++) - p[i] = i; + p[i] = i; /* { dg-warning "dereference of possibly-NULL" } */ for (i = 0; i < n; i++) sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ result = sum; } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ - return result; /* { dg-message "leak of 'p'" } */ - /* FIXME: should this be 'ptr'? */ + return result; /* { dg-message "leak of 'p'|leak of 'ptr'" } */ } /* A simpler version of the above. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/memcpy-1.c b/gcc/testsuite/gcc.dg/analyzer/memcpy-1.c new file mode 100644 index 0000000..f120eac --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/memcpy-1.c @@ -0,0 +1,43 @@ +#include <string.h> +#include "analyzer-decls.h" + +void *test_1 (void *dst, void *src, size_t n) +{ + void *result = memcpy (dst, src, n); + __analyzer_eval (result == dst); /* { dg-warning "TRUE" } */ + return result; +} + +void *test_1a (void *dst, void *src, size_t n) +{ + void *result = __memcpy_chk (dst, src, n, -1); + __analyzer_eval (result == dst); /* { dg-warning "TRUE" } */ + return result; +} + +void test_2 (int i) +{ + int j; + memcpy (&j, &i, sizeof (int)); + __analyzer_eval (i == j); /* { dg-warning "TRUE" } */ +} + +void test_2a (int i) +{ + int j; + __memcpy_chk (&j, &i, sizeof (int), sizeof (int)); + __analyzer_eval (i == j); /* { dg-warning "TRUE" } */ +} + +void test_3 (void *src, size_t n) +{ + char buf[40], other[40]; + buf[0] = 'a'; + other[0] = 'b'; + __analyzer_eval (buf[0] == 'a'); /* { dg-warning "TRUE" } */ + __analyzer_eval (other[0] == 'b'); /* { dg-warning "TRUE" } */ + + memcpy (buf, src, n); + __analyzer_eval (buf[0] == 'a'); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (other[0] == 'b'); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/memset-1.c b/gcc/testsuite/gcc.dg/analyzer/memset-1.c new file mode 100644 index 0000000..5748aa1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/memset-1.c @@ -0,0 +1,114 @@ +#include <string.h> +#include "analyzer-decls.h" + +/* Zero-fill of uninitialized buffer. */ + +void test_1 (void) +{ + char buf[256]; + memset (buf, 0, 256); + __analyzer_eval (buf[42] == 0); /* { dg-warning "TRUE" } */ +} + +/* As above, but with __builtin_memset. */ + +void test_1a (void) +{ + char buf[256]; + __builtin_memset (buf, 0, 256); + __analyzer_eval (buf[42] == 0); /* { dg-warning "TRUE" } */ +} + +/* Zero-fill of partially initialized buffer. */ + +void test_2 (void) +{ + char buf[256]; + buf[42] = 'A'; + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ + memset (buf, 0, 256); + __analyzer_eval (buf[42] == '\0'); /* { dg-warning "TRUE" } */ +} + +/* A "memset" with known non-zero value. */ + +void test_3 (int val) +{ + char buf[256]; + memset (buf, 'A', 256); + /* We currently merely mark such regions as "unknown", so querying + values within them yields UNKNOWN when ideally it would be TRUE. */ + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ +} + +/* A "memset" with unknown value. */ + +void test_4 (int val) +{ + char buf[256]; + memset (buf, val, 256); + /* We currently merely mark such regions as "unknown", so querying + values within them yields UNKNOWN when ideally it would be TRUE. */ + __analyzer_eval (buf[42] == (char)val); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ +} + +/* A "memset" with unknown num bytes. */ + +void test_5 (int n) +{ + char buf[256]; + buf[42] = 'A'; + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ + memset (buf, 0, n); + + /* We can't know if buf[42] was written to or not. */ + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (buf[42] == '\0'); /* { dg-warning "UNKNOWN" } */ +} + +/* As test_5, but with "__builtin___memset_chk". */ + +void test_5a (int n) +{ + char buf[256]; + buf[42] = 'A'; + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ + __builtin___memset_chk (buf, 0, n, __builtin_object_size (buf, 0)); + + /* We can't know if buf[42] was written to or not. */ + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (buf[42] == '\0'); /* { dg-warning "UNKNOWN" } */ +} + +/* A "memset" with unknown value, but with zero size. */ + +static size_t __attribute__((noinline)) +get_zero (void) +{ + return 0; +} + +void test_6 (int val) +{ + char buf[256]; + buf[42] = 'A'; + memset (buf, 'B', get_zero ()); + __analyzer_eval (buf[42] == 'A'); /* { dg-warning "TRUE" } */ +} + +/* A "memset" of known size that's not the full buffer. */ + +void test_7 (void) +{ + char buf[256]; + buf[128] = 'A'; + memset (buf, 0, 128); + /* We currently merely mark the whole region as "unknown", so querying + values within them yields UNKNOWN. */ + __analyzer_eval (buf[127] == '\0'); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ + __analyzer_eval (buf[128] == 'A'); /* { dg-warning "TRUE" "known nonzero" { xfail *-*-* } } */ + /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-3.c b/gcc/testsuite/gcc.dg/analyzer/paths-3.c index 9bd3030..b5ab810 100644 --- a/gcc/testsuite/gcc.dg/analyzer/paths-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/paths-3.c @@ -13,7 +13,7 @@ int test_1 (int a, int b) else p = malloc (32); - __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ if (a > 5) { @@ -34,7 +34,7 @@ int test_2 (int a, int b) else p = malloc (32); - __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ if (a > 6) /* different condition */ { diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-4.c b/gcc/testsuite/gcc.dg/analyzer/paths-4.c index 2f58763..b72e658 100644 --- a/gcc/testsuite/gcc.dg/analyzer/paths-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/paths-4.c @@ -13,8 +13,8 @@ int test_1 (struct state *s) __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ while (1) { - __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ - __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ /* TODO: why does the above need an extra stmt to merge state? */ do_stuff (s, s->mode); } @@ -25,13 +25,13 @@ int test_2 (struct state *s) __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ while (1) { - __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ - __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ /* TODO: why does the above need an extra stmt to merge state? */ switch (s->mode) { case 0: - __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ do_stuff (s, 0); break; case 1: diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-6.c b/gcc/testsuite/gcc.dg/analyzer/paths-6.c index 8220b8e..ef1a4e6 100644 --- a/gcc/testsuite/gcc.dg/analyzer/paths-6.c +++ b/gcc/testsuite/gcc.dg/analyzer/paths-6.c @@ -89,7 +89,7 @@ void test_3 (int i) break; } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ __analyzer_eval (f == 3); /* { dg-warning "TRUE" } */ __analyzer_eval (g == 4); /* { dg-warning "TRUE" } */ __analyzer_eval (h == 5); /* { dg-warning "TRUE" } */ @@ -108,7 +108,7 @@ void test_4 (int flag) q = malloc (256); p = malloc (256); } - __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ free (p); free (q); } diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-7.c b/gcc/testsuite/gcc.dg/analyzer/paths-7.c index 243b963..8caaee8 100644 --- a/gcc/testsuite/gcc.dg/analyzer/paths-7.c +++ b/gcc/testsuite/gcc.dg/analyzer/paths-7.c @@ -50,8 +50,7 @@ int test_2 (int flag, int *p, int n) sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ result = sum; - __analyzer_dump_exploded_nodes (0); /* { dg-warning "5 processed enodes" } */ - // FIXME: why 5 here? + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */ return result; diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-simplified.c b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-simplified.c new file mode 100644 index 0000000..4a08f0f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-simplified.c @@ -0,0 +1,22 @@ +/* { dg-do "compile" } */ + +/* Minimal replacement of system headers. */ +#define NULL ((void *) 0) +typedef struct _IO_FILE FILE; +extern FILE *fopen(const char *__restrict __filename, + const char *__restrict __modes); +extern int fclose (FILE *__stream); + +extern void unzRepair(const char* file, const char* fileOut, const char* fileOutTmp) +{ + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + fclose(fpOutCD); + fclose(fpZip); + fclose(fpOut); + } +} /* { dg-warning "leak of FILE 'fpZip'" "leak of fpZip" } */ + /* { dg-warning "leak of FILE 'fpOut'" "leak of fpOut" { target *-*-* } .-1 } */ + /* { dg-warning "leak of FILE 'fpOutCD'" "leak of fpOutCD" { target *-*-* } .-2 } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools.c b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools.c new file mode 100644 index 0000000..88ab5bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools.c @@ -0,0 +1,331 @@ +/* Integration test to ensure we issue FILE * leak diagnostics for + this particular non-trivial case. + Adapted from zlib/contrib/minizip/mztools.c, with all #includes + removed. */ + +/* { dg-do "compile" } */ + +/* Minimal replacement of system headers. */ + +typedef __SIZE_TYPE__ size_t; +#define NULL ((void *) 0) + +typedef struct _IO_FILE FILE; +extern FILE *fopen(const char *__restrict __filename, + const char *__restrict __modes); +extern size_t fread (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream); +extern size_t fwrite (const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __s); +extern int fclose (FILE *__stream); +extern int remove (const char *__filename) + __attribute__ ((__nothrow__ , __leaf__)); + +extern void *malloc (size_t __size) + __attribute__ ((__nothrow__ , __leaf__)) + __attribute__ ((__malloc__)); +extern void free (void *__ptr) + __attribute__ ((__nothrow__ , __leaf__)); + +extern size_t strlen (const char *__s) + __attribute__ ((__nothrow__ , __leaf__)) + __attribute__ ((__pure__)) + __attribute__ ((__nonnull__ (1))); + +/* Minimal replacement of zlib headers. */ + +#define ZEXPORT +typedef unsigned long uLong; /* 32 bits or more */ +#define Z_OK 0 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_MEM_ERROR (-4) + +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[1024]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fnsize < sizeof(filename)) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (extsize < sizeof(extra)) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char header[46]; + char* comment = ""; + int comsize = (int) strlen(comment); + WRITE_32(header, 0x02014b50); + WRITE_16(header + 4, version); + WRITE_16(header + 6, version); + WRITE_16(header + 8, gpflag); + WRITE_16(header + 10, method); + WRITE_16(header + 12, filetime); + WRITE_16(header + 14, filedate); + WRITE_32(header + 16, crc); + WRITE_32(header + 20, cpsize); + WRITE_32(header + 24, uncpsize); + WRITE_16(header + 28, fnsize); + WRITE_16(header + 30, extsize); + WRITE_16(header + 32, comsize); + WRITE_16(header + 34, 0); /* disk # */ + WRITE_16(header + 36, 0); /* int attrb */ + WRITE_32(header + 38, 0); /* ext attrb */ + WRITE_32(header + 42, currentOffset); + /* Header */ + if (fwrite(header, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char header[22]; + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(header, 0x06054b50); + WRITE_16(header + 4, 0); /* disk # */ + WRITE_16(header + 6, 0); /* disk # */ + WRITE_16(header + 8, entriesZip); /* hack */ + WRITE_16(header + 10, entriesZip); /* hack */ + WRITE_32(header + 12, offsetCD); /* size of CD */ + WRITE_32(header + 16, offset); /* offset to CD */ + WRITE_16(header + 20, comsize); /* comment */ + + /* Header */ + if (fwrite(header, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; /* { dg-warning "leak of FILE 'fpZip'" "leak of fpZip" } */ + /* { dg-warning "leak of FILE 'fpOut'" "leak of fpOut" { target *-*-* } .-1 } */ + /* { dg-warning "leak of FILE 'fpOutCD'" "leak of fpOutCD" { target *-*-* } .-2 } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias-feasibility.c b/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias-feasibility.c new file mode 100644 index 0000000..0d470d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias-feasibility.c @@ -0,0 +1,79 @@ +/* Simplified version of test to ensure we issue a FILE * leak diagnostic, + reproducing a feasibility issue. + Adapted from intl/localealias.c, with all #includes removed. */ + +/* { dg-do "compile" } */ +/* { dg-additional-options "-fno-analyzer-feasibility" } */ +/* TODO: remove the need for this option. */ + +/* Handle aliases for locale names. + Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* Minimal version of system headers. */ + +typedef __SIZE_TYPE__ size_t; +#define NULL ((void *)0) + +typedef struct _IO_FILE FILE; +extern FILE *fopen (const char *__restrict __filename, + const char *__restrict __modes); +extern int fclose (FILE *__stream); + +extern int isspace (int) __attribute__((__nothrow__, __leaf__)); + +/* Cleaned-up body of localealias.c follows. */ + +size_t +read_alias_file (const char *fname, int fname_len) +{ + FILE *fp; + size_t added; + char buf[400]; + char *alias; + char *value; + char *cp; + + fp = fopen (fname, "r"); /* { dg-message "opened here" } */ + if (fp == NULL) + return 0; + + cp = buf; + + /* Ignore leading white space. */ + while (isspace ((unsigned char)cp[0])) + ++cp; + + if (cp[0] != '\0' && cp[0] != '#') + { + alias = cp++; + while (cp[0] != '\0' && !isspace ((unsigned char)cp[0])) + ++cp; + if (cp[0] != '\0') + *cp++ = '\0'; + + while (isspace ((unsigned char)cp[0])) + ++cp; + + if (cp[0] != '\0') + return 42; /* { dg-warning "leak of FILE 'fp'" } */ + } + + fclose(fp); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias-simplified.c b/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias-simplified.c new file mode 100644 index 0000000..6f65add --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias-simplified.c @@ -0,0 +1,45 @@ +/* Simplified version of test for ensuring we issue a FILE * leak diagnostic, + made trivial. + Adapted from intl/localealias.c, with all #includes removed. */ + +/* { dg-do "compile" } */ + +/* Handle aliases for locale names. + Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* Minimal version of system headers. */ +#define NULL ((void *) 0) +typedef struct _IO_FILE FILE; +extern FILE *fopen(const char *__restrict __filename, + const char *__restrict __modes); +extern int fclose(FILE *__stream); + +void +read_alias_file (int flag) +{ + FILE *fp; + + fp = fopen ("name", "r"); /* { dg-message "opened here" } */ + if (fp == NULL) + return; + + if (flag) + return; /* { dg-warning "leak of FILE 'fp'" } */ + + fclose (fp); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias.c b/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias.c new file mode 100644 index 0000000..043e45f --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93355-localealias.c @@ -0,0 +1,391 @@ +/* Integration test to ensure we issue a FILE * leak diagnostic for + this particular non-trivial case. + Adapted from intl/localealias.c, with all #includes removed. */ + +/* { dg-do "compile" } */ +/* { dg-additional-options "-Wno-analyzer-too-complex -fno-analyzer-feasibility" } */ +/* TODO: remove the need for these options. */ +/* { dg-require-effective-target alloca } */ + +/* Handle aliases for locale names. + Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* Minimal version of system headers. */ + +typedef __SIZE_TYPE__ size_t; +#define NULL ((void *) 0) + +#define PATH_SEPARATOR ':' +typedef struct _IO_FILE FILE; +extern FILE *fopen(const char *__restrict __filename, + const char *__restrict __modes); +extern int feof_unlocked(FILE *__stream) __attribute__((__nothrow__, __leaf__)); +extern char *fgets_unlocked(char *__restrict __s, int __n, + FILE *__restrict __stream); +extern int fclose(FILE *__stream); + +#define alloca __builtin_alloca + +extern char *strchr(const char *__s, int __c) + __attribute__((__nothrow__, __leaf__)) __attribute__((__pure__)) + __attribute__((__nonnull__(1))); +extern void *memcpy(void *__restrict __dest, const void *__restrict __src, + size_t __n) __attribute__((__nothrow__, __leaf__)) + __attribute__((__nonnull__(1, 2))); +extern void *mempcpy(void *__restrict __dest, const void *__restrict __src, + size_t __n) __attribute__((__nothrow__, __leaf__)) + __attribute__((__nonnull__(1, 2))); +#define HAVE_MEMPCPY 1 +extern size_t strlen(const char *__s) __attribute__((__nothrow__, __leaf__)) + __attribute__((__pure__)) __attribute__((__nonnull__(1))); + +extern int strcasecmp(const char *__s1, const char *__s2) + __attribute__((__nothrow__, __leaf__)) __attribute__((__pure__)) + __attribute__((__nonnull__(1, 2))); + +extern int isspace(int) __attribute__((__nothrow__, __leaf__)); + +extern void *realloc(void *__ptr, size_t __size) + __attribute__((__nothrow__, __leaf__)) + __attribute__((__warn_unused_result__)); + +typedef int (*__compar_fn_t)(const void *, const void *); +extern void *bsearch(const void *__key, const void *__base, size_t __nmemb, + size_t __size, __compar_fn_t __compar) + __attribute__((__nonnull__(1, 2, 5))); + +extern __inline __attribute__((__gnu_inline__)) void * +bsearch(const void *__key, const void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) { + size_t __l, __u, __idx; + const void *__p; + int __comparison; + + __l = 0; + __u = __nmemb; + while (__l < __u) { + __idx = (__l + __u) / 2; + __p = (void *)(((const char *)__base) + (__idx * __size)); + __comparison = (*__compar)(__key, __p); + if (__comparison < 0) + __u = __idx; + else if (__comparison > 0) + __l = __idx + 1; + else + return (void *)__p; + } + + return ((void *)0); +} + +extern void qsort(void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) __attribute__((__nonnull__(1, 4))); + +/* Minimal version of intl headers. */ + +#define PARAMS(args) args + +#define relocate libintl_relocate +extern const char *libintl_relocate(const char *pathname); + +#define LOCALE_ALIAS_PATH "value for LOCALE_ALIAS_PATH" + +/* Cleaned-up body of localealias.c follows. */ + +#ifndef internal_function +# define internal_function +#endif + +/* Some optimizations for glibc. */ +# define FEOF(fp) feof_unlocked (fp) +# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp) + +/* For those losing systems which don't have `alloca' we have to add + some additional code emulating it. */ +# define freea(p) /* nothing */ + +struct alias_map +{ + const char *alias; + const char *value; +}; + +# define libc_freeres_ptr(decl) decl + +libc_freeres_ptr (static char *string_space); +static size_t string_space_act; +static size_t string_space_max; +libc_freeres_ptr (static struct alias_map *map); +static size_t nmap; +static size_t maxmap; + + +/* Prototypes for local functions. */ +static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) + internal_function; +static int extend_alias_table PARAMS ((void)); +static int alias_compare PARAMS ((const struct alias_map *map1, + const struct alias_map *map2)); + + +const char * +_nl_expand_alias (name) + const char *name; +{ + static const char *locale_alias_path; + struct alias_map *retval; + const char *result = NULL; + size_t added; + +#ifdef _LIBC + __libc_lock_lock (lock); +#endif + + if (locale_alias_path == NULL) + locale_alias_path = LOCALE_ALIAS_PATH; + + do + { + struct alias_map item; + + item.alias = name; + + if (nmap > 0) + retval = (struct alias_map *) bsearch (&item, map, nmap, + sizeof (struct alias_map), + (int (*) PARAMS ((const void *, + const void *)) + ) alias_compare); + else + retval = NULL; + + /* We really found an alias. Return the value. */ + if (retval != NULL) + { + result = retval->value; + break; + } + + /* Perhaps we can find another alias file. */ + added = 0; + while (added == 0 && locale_alias_path[0] != '\0') + { + const char *start; + + while (locale_alias_path[0] == PATH_SEPARATOR) + ++locale_alias_path; + start = locale_alias_path; + + while (locale_alias_path[0] != '\0' + && locale_alias_path[0] != PATH_SEPARATOR) + ++locale_alias_path; + + if (start < locale_alias_path) + added = read_alias_file (start, locale_alias_path - start); + } + } + while (added != 0); + +#ifdef _LIBC + __libc_lock_unlock (lock); +#endif + + return result; +} + + +static size_t +internal_function +read_alias_file (fname, fname_len) + const char *fname; + int fname_len; +{ + FILE *fp; + char *full_fname; + size_t added; + static const char aliasfile[] = "/locale.alias"; + + full_fname = (char *) alloca (fname_len + sizeof aliasfile); +#ifdef HAVE_MEMPCPY + mempcpy (mempcpy (full_fname, fname, fname_len), + aliasfile, sizeof aliasfile); +#else + memcpy (full_fname, fname, fname_len); + memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); +#endif + + fp = fopen (relocate (full_fname), "r"); /* { dg-message "opened here" } */ + freea (full_fname); + if (fp == NULL) + return 0; + +#ifdef HAVE___FSETLOCKING + /* No threads present. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); +#endif + + added = 0; + while (!FEOF (fp)) + { + /* It is a reasonable approach to use a fix buffer here because + a) we are only interested in the first two fields + b) these fields must be usable as file names and so must not + be that long + We avoid a multi-kilobyte buffer here since this would use up + stack space which we might not have if the program ran out of + memory. */ + char buf[400]; + char *alias; + char *value; + char *cp; + + if (FGETS (buf, sizeof buf, fp) == NULL) + /* EOF reached. */ + break; + + cp = buf; + /* Ignore leading white space. */ + while (isspace ((unsigned char) cp[0])) + ++cp; + + /* A leading '#' signals a comment line. */ + if (cp[0] != '\0' && cp[0] != '#') + { + alias = cp++; + while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) + ++cp; + /* Terminate alias name. */ + if (cp[0] != '\0') + *cp++ = '\0'; + + /* Now look for the beginning of the value. */ + while (isspace ((unsigned char) cp[0])) + ++cp; + + if (cp[0] != '\0') + { + size_t alias_len; + size_t value_len; + + value = cp++; + while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) + ++cp; + /* Terminate value. */ + if (cp[0] == '\n') + { + /* This has to be done to make the following test + for the end of line possible. We are looking for + the terminating '\n' which do not overwrite here. */ + *cp++ = '\0'; + *cp = '\n'; + } + else if (cp[0] != '\0') + *cp++ = '\0'; + + if (nmap >= maxmap) + if (__builtin_expect (extend_alias_table (), 0)) + return added; /* { dg-warning "leak of FILE 'fp'" } */ + + alias_len = strlen (alias) + 1; + value_len = strlen (value) + 1; + + if (string_space_act + alias_len + value_len > string_space_max) + { + /* Increase size of memory pool. */ + size_t new_size = (string_space_max + + (alias_len + value_len > 1024 + ? alias_len + value_len : 1024)); + char *new_pool = (char *) realloc (string_space, new_size); + if (new_pool == NULL) + return added; + + if (__builtin_expect (string_space != new_pool, 0)) + { + size_t i; + + for (i = 0; i < nmap; i++) + { + map[i].alias += new_pool - string_space; + map[i].value += new_pool - string_space; + } + } + + string_space = new_pool; + string_space_max = new_size; + } + + map[nmap].alias = memcpy (&string_space[string_space_act], + alias, alias_len); + string_space_act += alias_len; + + map[nmap].value = memcpy (&string_space[string_space_act], + value, value_len); + string_space_act += value_len; + + ++nmap; + ++added; + } + } + + /* Possibly not the whole line fits into the buffer. Ignore + the rest of the line. */ + while (strchr (buf, '\n') == NULL) + if (FGETS (buf, sizeof buf, fp) == NULL) + /* Make sure the inner loop will be left. The outer loop + will exit at the `feof' test. */ + break; + } + + /* Should we test for ferror()? I think we have to silently ignore + errors. --drepper */ + fclose (fp); + + if (added > 0) + qsort (map, nmap, sizeof (struct alias_map), + (int (*) PARAMS ((const void *, const void *))) alias_compare); + + return added; +} + + +static int +extend_alias_table () +{ + size_t new_size; + struct alias_map *new_map; + + new_size = maxmap == 0 ? 100 : 2 * maxmap; + new_map = (struct alias_map *) realloc (map, (new_size + * sizeof (struct alias_map))); + if (new_map == NULL) + /* Simply don't extend: we don't have any more core. */ + return -1; + + map = new_map; + maxmap = new_size; + return 0; +} + + +static int +alias_compare (map1, map2) + const struct alias_map *map1; + const struct alias_map *map2; +{ + return strcasecmp (map1->alias, map2->alias); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93382.c b/gcc/testsuite/gcc.dg/analyzer/pr93382.c index c55696d..210b97d 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr93382.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr93382.c @@ -13,8 +13,8 @@ ql (void) { int n1[1]; - fread (n1, sizeof (n1[0]), 1, fp); /* { dg-message "'n1' gets an unchecked value here" } */ - idx = n1[0]; /* { dg-message "'idx' has an unchecked value here \\\(from 'n1'\\\)" } */ + fread (n1, sizeof (n1[0]), 1, fp); /* { dg-message "'n1' gets an unchecked value here" "" { xfail *-*-* } } */ + idx = n1[0]; /* { dg-message "'idx' has an unchecked value here \\\(from 'n1'\\\)" "" { xfail *-*-* } } */ } int arr[10]; @@ -23,5 +23,5 @@ int pl (void) { ql (); - return arr[idx]; /* { dg-warning "use of tainted value 'idx' in array lookup without bounds checking" } */ + return arr[idx]; /* { dg-warning "use of tainted value 'idx' in array lookup without bounds checking" "" { xfail *-*-* } } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93546.c b/gcc/testsuite/gcc.dg/analyzer/pr93546.c index 432a643..66f6805 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr93546.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr93546.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target label_values } */ void ch (int x1) diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93938.c b/gcc/testsuite/gcc.dg/analyzer/pr93938.c new file mode 100644 index 0000000..81d9983 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93938.c @@ -0,0 +1,13 @@ +/* Taken from gcc.dg/pr70022.c, adding -O1 to the options + (and -fanalyzer, implicitly). */ + +/* { dg-do compile } */ +/* { dg-options "-w -Wno-psabi -O1" } */ + +typedef int v4si __attribute__ ((vector_size (16))); + +int +foo (v4si v) +{ + return v[~0UL]; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94099.c b/gcc/testsuite/gcc.dg/analyzer/pr94099.c index a116c49..1d7a5d7 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr94099.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr94099.c @@ -21,7 +21,8 @@ pl (void) for (sc = 0; sc < 1; ++sc) { th.gk.hk = 0; - th.gk.bg[sc] = 0; /* { dg-warning "uninitialized" "uninit-warning-removed" { xfail *-*-* } } */ + th.gk.bg[sc] = 0; /* { dg-warning "dereference of NULL '0'" } */ + // TODO: above message could be improved l3 (&th); } } diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94399.c b/gcc/testsuite/gcc.dg/analyzer/pr94399.c new file mode 100644 index 0000000..e897c04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94399.c @@ -0,0 +1,13 @@ +#include <stdlib.h> + +#define _cleanup_(f) __attribute__((cleanup(f))) + +static inline void freep(void **p) { + free(*p); +} + +void test(void) { + _cleanup_(freep) void *ptr; + + ptr = malloc(3); +} /* { dg-bogus "leak" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94447.c b/gcc/testsuite/gcc.dg/analyzer/pr94447.c index 1aecebb..7c61a20 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr94447.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr94447.c @@ -6,5 +6,5 @@ struct foo int test (void) { struct foo f = {}; - return *f.v; + return *f.v; /* { dg-warning "dereference of NULL" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94458.c b/gcc/testsuite/gcc.dg/analyzer/pr94458.c new file mode 100644 index 0000000..ad9bfc9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94458.c @@ -0,0 +1,23 @@ +#include <stdlib.h> + +struct ret +{ + int **array; +}; + +struct ret *allocate_stuff(void) +{ + struct ret *ret; + + ret = calloc(1, sizeof (struct ret)); + if (!ret) { + abort(); + } + + ret->array = calloc (10, sizeof(int *)); + if (!ret->array) { + abort(); + } + + return ret; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94640.c b/gcc/testsuite/gcc.dg/analyzer/pr94640.c new file mode 100644 index 0000000..9722a17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94640.c @@ -0,0 +1,17 @@ +#include <stdio.h> + +int debug; + +int opencfgfile(const char *cfgfile, FILE **fd) +{ + if (cfgfile[0] != '\0') { + + if ((*fd = fopen(cfgfile, "r")) != NULL) { + if (debug) + printf("Config file: --config\n"); + } + + } + + return 2; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94688.c b/gcc/testsuite/gcc.dg/analyzer/pr94688.c new file mode 100644 index 0000000..f553b8c --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94688.c @@ -0,0 +1,6 @@ +int a, b; +void d(); +void c() +{ + d((void (*)()) & a + b); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94689.c b/gcc/testsuite/gcc.dg/analyzer/pr94689.c new file mode 100644 index 0000000..09802a7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94689.c @@ -0,0 +1,8 @@ +typedef void (*F) (void); +void bar (F); + +void +foo (void *a, int b) +{ + bar ((F) a + b); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94839.c b/gcc/testsuite/gcc.dg/analyzer/pr94839.c new file mode 100644 index 0000000..46c8bb9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94839.c @@ -0,0 +1,20 @@ +struct bitmap +{ + int min; + int max; + int *vec; +}; + +int bitmap_create(struct bitmap *bm, int min, int max) +{ + int sz; + + sz = (max / sizeof(int)) + 1; + + bm->min = min; + bm->max = max; + bm->vec = __builtin_calloc(sz, sizeof(int)); + if (!bm->vec) + return (-12); + return 0; /* { dg-bogus "leak" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-1.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-1.c new file mode 100644 index 0000000..da79652 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-1.c @@ -0,0 +1,47 @@ +/* { dg-additional-options "-O2" } */ + +#include <stdio.h> +#include <stdlib.h> + +typedef struct AMARK { + struct AMARK *m_next; + char m_name; +} AMARK; + +struct buf { + AMARK *b_amark; +}; + +struct buf *curbp; + +int pamark(void) { + int c; + AMARK *p = curbp->b_amark; + AMARK *last = curbp->b_amark; + + c = getchar(); + + while (p != (AMARK *)NULL && p->m_name != (char)c) { + last = p; + p = p->m_next; + } + + if (p != (AMARK *)NULL) { + printf("over writing mark %c\n", c); + } else { + if ((p = (AMARK *)malloc(sizeof(AMARK))) == (AMARK *)NULL) + return 0; + + p->m_next = (AMARK *)NULL; + + if (curbp->b_amark == (AMARK *)NULL) + curbp->b_amark = p; + else + last->m_next = p; + } + + p->m_name = (char)c; /* { dg-bogus "leak of 'p'" "bogus leak" { xfail *-*-* } } */ + // TODO(xfail): related to PR analyzer/97072 and PR analyzer/97074 + + return 1; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-3.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-3.c new file mode 100644 index 0000000..0f95397 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-3.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-O1" } */ + +struct List { + struct List *next; +}; + +void foo(struct List *p, struct List *q) +{ + while (p && p != q){ + p = p->next; + } +} + +int main() +{ + struct List x = {0}; + foo(0, &x); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c new file mode 100644 index 0000000..2a15a5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c @@ -0,0 +1,24 @@ +/* { dg-additional-options "-O2" } */ + +#include <stdlib.h> + +struct List { + struct List *next; +}; + +void foo(struct List *p, struct List *q) +{ + while (p && p != q){ + struct List *next = p->next; + free(p); + p = next; + } +} + +int main() +{ + struct List x = {0}; + foo(NULL, &x); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c b/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c new file mode 100644 index 0000000..f7be1c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c @@ -0,0 +1,42 @@ +#include <stdlib.h> + +typedef short hashNx; + +typedef struct hashSt { + hashNx *hs_index; + int hs_used; + int hs_slots; +} hashSt; + +void hashEmpty(hashSt *td); + +int hashAlloc(hashSt *td, int slots) { + hashNx *index; + + if (slots > td->hs_slots) { + if (td->hs_index != NULL) + index = realloc(td->hs_index, (size_t)slots * sizeof(hashNx)); + else + index = malloc((size_t)slots * sizeof(hashNx)); + + if (index == NULL) + return 0; + + td->hs_index = index; + td->hs_slots = slots; + } + + hashEmpty(td); + + return 1; +} + +void hashEmpty(hashSt *td) { + hashNx *index; + int slots; + + for (slots = td->hs_slots, index = td->hs_index; --slots >= 0;) + *index++ = -1; + + td->hs_used = 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94858-2.c b/gcc/testsuite/gcc.dg/analyzer/pr94858-2.c new file mode 100644 index 0000000..874fe8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94858-2.c @@ -0,0 +1,25 @@ +#include <stdlib.h> + +typedef short hashNx; + +typedef struct hashSt { + hashNx *hs_index; + int hs_used; + int hs_slots; +} hashSt; + +int test (hashSt *td, int slots) +{ + hashNx *index; + + index = malloc((size_t)slots * sizeof(hashNx)); + if (index == NULL) + return 0; + td->hs_index = index; + td->hs_slots = slots; + + for (slots = td->hs_slots, index = td->hs_index; --slots >= 0;) + *index++ = -1; + + return 1; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr95026.c b/gcc/testsuite/gcc.dg/analyzer/pr95026.c new file mode 100644 index 0000000..1845f15 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr95026.c @@ -0,0 +1,17 @@ +struct _IO_FILE; +typedef struct _IO_FILE FILE; +typedef struct _message +{ + FILE *fp; +} MESSAGE; +extern FILE *fopen (const char *__restrict __filename, + const char *__restrict __modes); +FILE *f (void); +int imap_fetch_message (int i, MESSAGE *msg, char *p) +{ + if ((msg->fp = i ? 0 : f ())) + return 0; + if (p) + msg->fp = fopen (p, "r"); + return -1; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr95152-4.c b/gcc/testsuite/gcc.dg/analyzer/pr95152-4.c new file mode 100644 index 0000000..f2a72ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr95152-4.c @@ -0,0 +1,11 @@ +/* { dg-additional-options "-Wno-pointer-to-int-cast" } */ +extern void my_func (int); +typedef struct { + int var; +} info_t; +extern void *_data_offs; +void test() +{ + info_t *info = ((void *)((void *)1) + ((unsigned int)&_data_offs)); + my_func(info->var == 0); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr95152-5.c b/gcc/testsuite/gcc.dg/analyzer/pr95152-5.c new file mode 100644 index 0000000..604b784 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr95152-5.c @@ -0,0 +1,6 @@ +/* { dg-additional-options "-Wno-incompatible-pointer-types" } */ +void foo(void) +{ + void (*a[1]) (); + void (*p) () = a + 1; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr95240.c b/gcc/testsuite/gcc.dg/analyzer/pr95240.c new file mode 100644 index 0000000..c84c64d --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr95240.c @@ -0,0 +1,27 @@ +typedef __SIZE_TYPE__ size_t; + +extern void *calloc(size_t nmemb, size_t size); +extern void free(void *ptr); + +static char *activeTroubleArray; + +int +initActiveTroubleArray () +{ + activeTroubleArray = calloc (1, 1); + return activeTroubleArray ? 0 : 1; +} + +void +freeActiveTroubleArray () +{ + free (activeTroubleArray); +} + +int main (int argc, char *argv[]) +{ + initActiveTroubleArray (); + freeActiveTroubleArray (); + + return 1; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96598.c b/gcc/testsuite/gcc.dg/analyzer/pr96598.c new file mode 100644 index 0000000..b4354cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96598.c @@ -0,0 +1,26 @@ +/* { dg-additional-options "-O0 -fsanitize=undefined" } */ + +extern char *foo (char *dest, const char *src) + __attribute__ ((__nonnull__ (1, 2))); + +unsigned bar(const char *str) + __attribute__ ((__nonnull__ ())); + +unsigned test(const char *str, unsigned **pv) + __attribute__ ((__nonnull__ ())); + +unsigned test(const char* str, unsigned **pv) +{ + char buffer[130]; + + *pv = 0; + + foo(buffer, str); + if (bar(buffer)) + { + const char *ptr = 0; + foo(buffer, str); + return bar(buffer); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96611.c b/gcc/testsuite/gcc.dg/analyzer/pr96611.c new file mode 100644 index 0000000..4f75023 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96611.c @@ -0,0 +1,14 @@ +struct s { int a; } *ptr; +void unknown_int_ptr (int *); +void unknown_void (void); + +void test_1 () +{ + unknown_int_ptr (&ptr->a); +} + +void test_2 () +{ + unknown_void (); + unknown_int_ptr (&ptr->a); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96639.c b/gcc/testsuite/gcc.dg/analyzer/pr96639.c new file mode 100644 index 0000000..02ca3f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96639.c @@ -0,0 +1,10 @@ +void *calloc (__SIZE_TYPE__, __SIZE_TYPE__); + +int +x7 (void) +{ + int **md = calloc (1, 1); + + return md[0][0]; /* { dg-warning "possibly-NULL" "unchecked deref" } */ + /* { dg-warning "leak of 'md'" "leak" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96642.c b/gcc/testsuite/gcc.dg/analyzer/pr96642.c new file mode 100644 index 0000000..117aa04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96642.c @@ -0,0 +1,10 @@ +void +ut (void) +{ + struct { + char *cc; + } sr[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, "", + 0, 0, "", 0, 0, "", 0, 0, "", 0, 0, "", 0, 0, 0, 0, 0, + }; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96644.c b/gcc/testsuite/gcc.dg/analyzer/pr96644.c new file mode 100644 index 0000000..3953c8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96644.c @@ -0,0 +1,24 @@ +/* { dg-additional-options "-O1" } */ + +int oh[1]; +int *x3; + +int * +cm (char *m0) +{ + return oh; +} + +void +ek (void) +{ + for (;;) + { + char *b2 = 0; + + if (*b2 != 0) /* { dg-warning "dereference of NULL" } */ + ++b2; + + x3 = cm (b2); + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96646.c b/gcc/testsuite/gcc.dg/analyzer/pr96646.c new file mode 100644 index 0000000..2ac5a03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96646.c @@ -0,0 +1,24 @@ +/* { dg-additional-options "-O1" } */ + +struct zx { + struct zx *b4, *g0; +}; + +struct oo { + void *ph; + struct zx el; +}; + +inline void +k7 (struct zx *xj) +{ + xj->b4->g0 = 0; /* { dg-warning "dereference of NULL" } */ + xj->b4 = 0; +} + +void +n8 (struct oo *yx) +{ + k7 (&yx->el); + n8 (yx); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96648.c b/gcc/testsuite/gcc.dg/analyzer/pr96648.c new file mode 100644 index 0000000..a6b0c72 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96648.c @@ -0,0 +1,36 @@ +/* { dg-additional-options "-O1" } */ + +struct vd { + struct vd *rs; +}; + +struct fh { + struct vd cl; +}; + +struct i3 { + struct fh *h4; +}; + +struct fh * +gm (void); + +void +j7 (struct vd *); + +inline void +mb (struct vd *e7) +{ + j7 (e7->rs); +} + +void +po (struct i3 *d2) +{ + struct i3 *s2; + + d2->h4 = gm (); + mb (&d2->h4->cl); + s2 = ({ d2 - 1; }); + po (s2); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96650-1-notrans.c b/gcc/testsuite/gcc.dg/analyzer/pr96650-1-notrans.c new file mode 100644 index 0000000..94c7555 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96650-1-notrans.c @@ -0,0 +1,30 @@ +/* { dg-additional-options "-O2 -fno-analyzer-transitivity" } */ + +int *wf; + +void +yd (void); + +int +cy (void); + +int * +ee (int hp) +{ + if (hp != 0) + yd (); + + return 0; +} + +void +z0 (int co) +{ + int l4 = sizeof (int); + + aq: + wf = ee (l4); + if (l4 < co) + l4 = cy () + sizeof (int); + goto aq; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96650-1-trans.c b/gcc/testsuite/gcc.dg/analyzer/pr96650-1-trans.c new file mode 100644 index 0000000..b20630b --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96650-1-trans.c @@ -0,0 +1,30 @@ +/* { dg-additional-options "-O2 -fanalyzer-transitivity" } */ + +int *wf; + +void +yd (void); + +int +cy (void); + +int * +ee (int hp) +{ + if (hp != 0) + yd (); + + return 0; +} + +void +z0 (int co) +{ + int l4 = sizeof (int); + + aq: + wf = ee (l4); + if (l4 < co) + l4 = cy () + sizeof (int); + goto aq; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96650-2-notrans.c b/gcc/testsuite/gcc.dg/analyzer/pr96650-2-notrans.c new file mode 100644 index 0000000..fc7c045 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96650-2-notrans.c @@ -0,0 +1,30 @@ +/* { dg-additional-options "-fno-analyzer-transitivity" } */ + +#include "analyzer-decls.h" + +int foo (void); + +/* Infeasible path, requiring transitivity to find. */ + +void test_1 (int co, int y) +{ + if (4 < co) + if (co < y) + if (y == 0) + __analyzer_dump_path (); /* { dg-message "path" } */ +} + +/* Infeasible path, requiring transitivity to find, with a merger. */ + +void test_2 (int co, int y, int z) +{ + if (4 < co) + if (co < y) + if (y == 0) + { + while (foo ()) + { + } + __analyzer_dump_path (); /* { dg-message "path" } */ + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96650-2-trans.c b/gcc/testsuite/gcc.dg/analyzer/pr96650-2-trans.c new file mode 100644 index 0000000..8d0c295 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96650-2-trans.c @@ -0,0 +1,30 @@ +/* { dg-additional-options "-fanalyzer-transitivity" } */ + +#include "analyzer-decls.h" + +int foo (void); + +/* Infeasible path, requiring transitivity to find. */ + +void test_1 (int co, int y) +{ + if (4 < co) + if (co < y) + if (y == 0) + __analyzer_dump_path (); /* { dg-bogus "path" } */ +} + +/* Infeasible path, requiring transitivity to find, with a merger. */ + +void test_2 (int co, int y, int z) +{ + if (4 < co) + if (co < y) + if (y == 0) + { + while (foo ()) + { + } + __analyzer_dump_path (); /* { dg-bogus "path" } */ + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96651-1.c b/gcc/testsuite/gcc.dg/analyzer/pr96651-1.c new file mode 100644 index 0000000..2f3a9b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96651-1.c @@ -0,0 +1,22 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +static int a; + +int main(void) +{ + char *src = NULL; + char buf[128]; + + /* "a" can't have been touched yet, and thus + is implicitly zero. */ + switch (a) { + case 1: + strcpy(buf, src); /* { dg-bogus "NULL" } */ + break; + case 0: + strcpy(buf, "hello"); + } + printf("%s\n", buf); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96651-2.c b/gcc/testsuite/gcc.dg/analyzer/pr96651-2.c new file mode 100644 index 0000000..249a32b --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96651-2.c @@ -0,0 +1,72 @@ +#include "analyzer-decls.h" + +extern void unknown_fn (void *, void *); + +static int a; +static int b = 42; +int c; +int d = 17; +struct { int x; int y; char rgb[3]; } s = {5, 10, {0x80, 0x40, 0x20}}; +void *e = &d; + +extern struct _IO_FILE *stderr; + +/* If we're not on a direct path from "main", we know nothing about + the values of globals. */ + +void test (void) +{ + __analyzer_eval (a == 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (b == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (c == 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (d == 17); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (s.rgb[2] == 0x20); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (e == &d); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (stderr == 0); /* { dg-warning "UNKNOWN" } */ +} + +static void __attribute__((noinline)) +called_from_main (void) +{ + /* When accessed from main, the vars still have their initializer values. */ + __analyzer_eval (a == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (b == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (c == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (d == 17); /* { dg-warning "TRUE" } */ + __analyzer_eval (s.rgb[2] == 0x20); /* { dg-warning "TRUE" } */ + __analyzer_eval (e == &d); /* { dg-warning "TRUE" } */ + /* ...apart from those defined in a different TU (or that were inited + before "main"). */ + __analyzer_eval (stderr == 0); /* { dg-warning "UNKNOWN" } */ +} + +int main (void) +{ + /* When accessed from main, the vars still have their initializer values. */ + __analyzer_eval (a == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (b == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (c == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (d == 17); /* { dg-warning "TRUE" } */ + __analyzer_eval (s.rgb[2] == 0x20); /* { dg-warning "TRUE" } */ + __analyzer_eval (e == &d); /* { dg-warning "TRUE" } */ + /* ...apart from those defined in a different TU (or that were inited + before "main"). */ + __analyzer_eval (stderr == 0); /* { dg-warning "UNKNOWN" } */ + + called_from_main (); + + unknown_fn (&a, &c); + + /* "a" escaped above and so could have been written to. */ + __analyzer_eval (a == 0); /* { dg-warning "UNKNOWN" } */ + /* "b" doesn't escape and is static, and so must still have its + initial value. */ + __analyzer_eval (b == 42); /* { dg-warning "TRUE" } */ + /* The other globals are non-static and so have implicitly escaped, + and so could have been written to. */ + __analyzer_eval (c == 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (d == 17); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (s.rgb[2] == 0x20); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (e == &d); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (stderr == 0); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96653.c b/gcc/testsuite/gcc.dg/analyzer/pr96653.c new file mode 100644 index 0000000..e5e387c --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96653.c @@ -0,0 +1,1104 @@ +/* Examples of switch statements with many cases (with default values). + Adapted from Linux 5.9-rc1:drivers/media/v4l2-core/v4l2-ctrls.c. */ + +/* { dg-additional-options "-O1" } */ + +typedef unsigned int u32; +typedef long long s64; +typedef unsigned long long u64; + +enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, + V4L2_CTRL_TYPE_BITMASK = 8, + V4L2_CTRL_TYPE_INTEGER_MENU = 9, + + V4L2_CTRL_COMPOUND_TYPES = 0x0100, + V4L2_CTRL_TYPE_U8 = 0x0100, + V4L2_CTRL_TYPE_U16 = 0x0101, + V4L2_CTRL_TYPE_U32 = 0x0102, + V4L2_CTRL_TYPE_AREA = 0x0106, +}; + +const char *v4l2_ctrl_get_name(u32 id) { + switch (id) { + case (0x00980000 | 1): + return "User Controls"; + case ((0x00980000 | 0x900) + 0): + return "Brightness"; + case ((0x00980000 | 0x900) + 1): + return "Contrast"; + case ((0x00980000 | 0x900) + 2): + return "Saturation"; + case ((0x00980000 | 0x900) + 3): + return "Hue"; + case ((0x00980000 | 0x900) + 5): + return "Volume"; + case ((0x00980000 | 0x900) + 6): + return "Balance"; + case ((0x00980000 | 0x900) + 7): + return "Bass"; + case ((0x00980000 | 0x900) + 8): + return "Treble"; + case ((0x00980000 | 0x900) + 9): + return "Mute"; + case ((0x00980000 | 0x900) + 10): + return "Loudness"; + case ((0x00980000 | 0x900) + 11): + return "Black Level"; + case ((0x00980000 | 0x900) + 12): + return "White Balance, Automatic"; + case ((0x00980000 | 0x900) + 13): + return "Do White Balance"; + case ((0x00980000 | 0x900) + 14): + return "Red Balance"; + case ((0x00980000 | 0x900) + 15): + return "Blue Balance"; + case ((0x00980000 | 0x900) + 16): + return "Gamma"; + case ((0x00980000 | 0x900) + 17): + return "Exposure"; + case ((0x00980000 | 0x900) + 18): + return "Gain, Automatic"; + case ((0x00980000 | 0x900) + 19): + return "Gain"; + case ((0x00980000 | 0x900) + 20): + return "Horizontal Flip"; + case ((0x00980000 | 0x900) + 21): + return "Vertical Flip"; + case ((0x00980000 | 0x900) + 24): + return "Power Line Frequency"; + case ((0x00980000 | 0x900) + 25): + return "Hue, Automatic"; + case ((0x00980000 | 0x900) + 26): + return "White Balance Temperature"; + case ((0x00980000 | 0x900) + 27): + return "Sharpness"; + case ((0x00980000 | 0x900) + 28): + return "Backlight Compensation"; + case ((0x00980000 | 0x900) + 29): + return "Chroma AGC"; + case ((0x00980000 | 0x900) + 30): + return "Color Killer"; + case ((0x00980000 | 0x900) + 31): + return "Color Effects"; + case ((0x00980000 | 0x900) + 32): + return "Brightness, Automatic"; + case ((0x00980000 | 0x900) + 33): + return "Band-Stop Filter"; + case ((0x00980000 | 0x900) + 34): + return "Rotate"; + case ((0x00980000 | 0x900) + 35): + return "Background Color"; + case ((0x00980000 | 0x900) + 36): + return "Chroma Gain"; + case ((0x00980000 | 0x900) + 37): + return "Illuminator 1"; + case ((0x00980000 | 0x900) + 38): + return "Illuminator 2"; + case ((0x00980000 | 0x900) + 39): + return "Min Number of Capture Buffers"; + case ((0x00980000 | 0x900) + 40): + return "Min Number of Output Buffers"; + case ((0x00980000 | 0x900) + 41): + return "Alpha Component"; + case ((0x00980000 | 0x900) + 42): + return "Color Effects, CbCr"; + case (0x00990000 | 1): + return "Codec Controls"; + case ((0x00990000 | 0x900) + 0): + return "Stream Type"; + case ((0x00990000 | 0x900) + 1): + return "Stream PMT Program ID"; + case ((0x00990000 | 0x900) + 2): + return "Stream Audio Program ID"; + case ((0x00990000 | 0x900) + 3): + return "Stream Video Program ID"; + case ((0x00990000 | 0x900) + 4): + return "Stream PCR Program ID"; + case ((0x00990000 | 0x900) + 5): + return "Stream PES Audio ID"; + case ((0x00990000 | 0x900) + 6): + return "Stream PES Video ID"; + case ((0x00990000 | 0x900) + 7): + return "Stream VBI Format"; + case ((0x00990000 | 0x900) + 100): + return "Audio Sampling Frequency"; + case ((0x00990000 | 0x900) + 101): + return "Audio Encoding"; + case ((0x00990000 | 0x900) + 102): + return "Audio Layer I Bitrate"; + case ((0x00990000 | 0x900) + 103): + return "Audio Layer II Bitrate"; + case ((0x00990000 | 0x900) + 104): + return "Audio Layer III Bitrate"; + case ((0x00990000 | 0x900) + 105): + return "Audio Stereo Mode"; + case ((0x00990000 | 0x900) + 106): + return "Audio Stereo Mode Extension"; + case ((0x00990000 | 0x900) + 107): + return "Audio Emphasis"; + case ((0x00990000 | 0x900) + 108): + return "Audio CRC"; + case ((0x00990000 | 0x900) + 109): + return "Audio Mute"; + case ((0x00990000 | 0x900) + 110): + return "Audio AAC Bitrate"; + case ((0x00990000 | 0x900) + 111): + return "Audio AC-3 Bitrate"; + case ((0x00990000 | 0x900) + 112): + return "Audio Playback"; + case ((0x00990000 | 0x900) + 113): + return "Audio Multilingual Playback"; + case ((0x00990000 | 0x900) + 200): + return "Video Encoding"; + case ((0x00990000 | 0x900) + 201): + return "Video Aspect"; + case ((0x00990000 | 0x900) + 202): + return "Video B Frames"; + case ((0x00990000 | 0x900) + 203): + return "Video GOP Size"; + case ((0x00990000 | 0x900) + 204): + return "Video GOP Closure"; + case ((0x00990000 | 0x900) + 205): + return "Video Pulldown"; + case ((0x00990000 | 0x900) + 206): + return "Video Bitrate Mode"; + case ((0x00990000 | 0x900) + 207): + return "Video Bitrate"; + case ((0x00990000 | 0x900) + 208): + return "Video Peak Bitrate"; + case ((0x00990000 | 0x900) + 209): + return "Video Temporal Decimation"; + case ((0x00990000 | 0x900) + 210): + return "Video Mute"; + case ((0x00990000 | 0x900) + 211): + return "Video Mute YUV"; + case ((0x00990000 | 0x900) + 212): + return "Decoder Slice Interface"; + case ((0x00990000 | 0x900) + 213): + return "MPEG4 Loop Filter Enable"; + case ((0x00990000 | 0x900) + 214): + return "Number of Intra Refresh MBs"; + case ((0x00990000 | 0x900) + 215): + return "Frame Level Rate Control Enable"; + case ((0x00990000 | 0x900) + 218): + return "H264 MB Level Rate Control"; + case ((0x00990000 | 0x900) + 216): + return "Sequence Header Mode"; + case ((0x00990000 | 0x900) + 217): + return "Max Number of Reference Pics"; + case ((0x00990000 | 0x900) + 300): + return "H263 I-Frame QP Value"; + case ((0x00990000 | 0x900) + 301): + return "H263 P-Frame QP Value"; + case ((0x00990000 | 0x900) + 302): + return "H263 B-Frame QP Value"; + case ((0x00990000 | 0x900) + 303): + return "H263 Minimum QP Value"; + case ((0x00990000 | 0x900) + 304): + return "H263 Maximum QP Value"; + case ((0x00990000 | 0x900) + 350): + return "H264 I-Frame QP Value"; + case ((0x00990000 | 0x900) + 351): + return "H264 P-Frame QP Value"; + case ((0x00990000 | 0x900) + 352): + return "H264 B-Frame QP Value"; + case ((0x00990000 | 0x900) + 354): + return "H264 Maximum QP Value"; + case ((0x00990000 | 0x900) + 353): + return "H264 Minimum QP Value"; + case ((0x00990000 | 0x900) + 355): + return "H264 8x8 Transform Enable"; + case ((0x00990000 | 0x900) + 356): + return "H264 CPB Buffer Size"; + case ((0x00990000 | 0x900) + 357): + return "H264 Entropy Mode"; + case ((0x00990000 | 0x900) + 358): + return "H264 I-Frame Period"; + case ((0x00990000 | 0x900) + 359): + return "H264 Level"; + case ((0x00990000 | 0x900) + 360): + return "H264 Loop Filter Alpha Offset"; + case ((0x00990000 | 0x900) + 361): + return "H264 Loop Filter Beta Offset"; + case ((0x00990000 | 0x900) + 362): + return "H264 Loop Filter Mode"; + case ((0x00990000 | 0x900) + 363): + return "H264 Profile"; + case ((0x00990000 | 0x900) + 364): + return "Vertical Size of SAR"; + case ((0x00990000 | 0x900) + 365): + return "Horizontal Size of SAR"; + case ((0x00990000 | 0x900) + 366): + return "Aspect Ratio VUI Enable"; + case ((0x00990000 | 0x900) + 367): + return "VUI Aspect Ratio IDC"; + case ((0x00990000 | 0x900) + 368): + return "H264 Enable Frame Packing SEI"; + case ((0x00990000 | 0x900) + 369): + return "H264 Set Curr. Frame as Frame0"; + case ((0x00990000 | 0x900) + 370): + return "H264 FP Arrangement Type"; + case ((0x00990000 | 0x900) + 371): + return "H264 Flexible MB Ordering"; + case ((0x00990000 | 0x900) + 372): + return "H264 Map Type for FMO"; + case ((0x00990000 | 0x900) + 373): + return "H264 FMO Number of Slice Groups"; + case ((0x00990000 | 0x900) + 374): + return "H264 FMO Direction of Change"; + case ((0x00990000 | 0x900) + 375): + return "H264 FMO Size of 1st Slice Grp"; + case ((0x00990000 | 0x900) + 376): + return "H264 FMO No. of Consecutive MBs"; + case ((0x00990000 | 0x900) + 377): + return "H264 Arbitrary Slice Ordering"; + case ((0x00990000 | 0x900) + 378): + return "H264 ASO Slice Order"; + case ((0x00990000 | 0x900) + 379): + return "Enable H264 Hierarchical Coding"; + case ((0x00990000 | 0x900) + 380): + return "H264 Hierarchical Coding Type"; + case ((0x00990000 | 0x900) + 381): + return "H264 Number of HC Layers"; + case ((0x00990000 | 0x900) + 382): + return "H264 Set QP Value for HC Layers"; + case ((0x00990000 | 0x900) + 383): + return "H264 Constrained Intra Pred"; + case ((0x00990000 | 0x900) + 384): + return "H264 Chroma QP Index Offset"; + case ((0x00990000 | 0x900) + 385): + return "H264 I-Frame Minimum QP Value"; + case ((0x00990000 | 0x900) + 386): + return "H264 I-Frame Maximum QP Value"; + case ((0x00990000 | 0x900) + 387): + return "H264 P-Frame Minimum QP Value"; + case ((0x00990000 | 0x900) + 388): + return "H264 P-Frame Maximum QP Value"; + case ((0x00990000 | 0x900) + 1000): + return "H264 Sequence Parameter Set"; + case ((0x00990000 | 0x900) + 1001): + return "H264 Picture Parameter Set"; + case ((0x00990000 | 0x900) + 1002): + return "H264 Scaling Matrix"; + case ((0x00990000 | 0x900) + 1003): + return "H264 Slice Parameters"; + case ((0x00990000 | 0x900) + 1004): + return "H264 Decode Parameters"; + case ((0x00990000 | 0x900) + 1005): + return "H264 Decode Mode"; + case ((0x00990000 | 0x900) + 1006): + return "H264 Start Code"; + case ((0x00990000 | 0x900) + 270): + return "MPEG2 Level"; + case ((0x00990000 | 0x900) + 271): + return "MPEG2 Profile"; + case ((0x00990000 | 0x900) + 400): + return "MPEG4 I-Frame QP Value"; + case ((0x00990000 | 0x900) + 401): + return "MPEG4 P-Frame QP Value"; + case ((0x00990000 | 0x900) + 402): + return "MPEG4 B-Frame QP Value"; + case ((0x00990000 | 0x900) + 403): + return "MPEG4 Minimum QP Value"; + case ((0x00990000 | 0x900) + 404): + return "MPEG4 Maximum QP Value"; + case ((0x00990000 | 0x900) + 405): + return "MPEG4 Level"; + case ((0x00990000 | 0x900) + 406): + return "MPEG4 Profile"; + case ((0x00990000 | 0x900) + 407): + return "Quarter Pixel Search Enable"; + case ((0x00990000 | 0x900) + 219): + return "Maximum Bytes in a Slice"; + case ((0x00990000 | 0x900) + 220): + return "Number of MBs in a Slice"; + case ((0x00990000 | 0x900) + 221): + return "Slice Partitioning Method"; + case ((0x00990000 | 0x900) + 222): + return "VBV Buffer Size"; + case ((0x00990000 | 0x900) + 223): + return "Video Decoder PTS"; + case ((0x00990000 | 0x900) + 224): + return "Video Decoder Frame Count"; + case ((0x00990000 | 0x900) + 225): + return "Initial Delay for VBV Control"; + case ((0x00990000 | 0x900) + 227): + return "Horizontal MV Search Range"; + case ((0x00990000 | 0x900) + 228): + return "Vertical MV Search Range"; + case ((0x00990000 | 0x900) + 226): + return "Repeat Sequence Header"; + case ((0x00990000 | 0x900) + 229): + return "Force Key Frame"; + case ((0x00990000 | 0x900) + 250): + return "MPEG-2 Slice Parameters"; + case ((0x00990000 | 0x900) + 251): + return "MPEG-2 Quantization Matrices"; + case ((0x00990000 | 0x900) + 292): + return "FWHT Stateless Parameters"; + case ((0x00990000 | 0x900) + 290): + return "FWHT I-Frame QP Value"; + case ((0x00990000 | 0x900) + 291): + return "FWHT P-Frame QP Value"; + + case ((0x00990000 | 0x900) + 500): + return "VPX Number of Partitions"; + case ((0x00990000 | 0x900) + 501): + return "VPX Intra Mode Decision Disable"; + case ((0x00990000 | 0x900) + 502): + return "VPX No. of Refs for P Frame"; + case ((0x00990000 | 0x900) + 503): + return "VPX Loop Filter Level Range"; + case ((0x00990000 | 0x900) + 504): + return "VPX Deblocking Effect Control"; + case ((0x00990000 | 0x900) + 505): + return "VPX Golden Frame Refresh Period"; + case ((0x00990000 | 0x900) + 506): + return "VPX Golden Frame Indicator"; + case ((0x00990000 | 0x900) + 507): + return "VPX Minimum QP Value"; + case ((0x00990000 | 0x900) + 508): + return "VPX Maximum QP Value"; + case ((0x00990000 | 0x900) + 509): + return "VPX I-Frame QP Value"; + case ((0x00990000 | 0x900) + 510): + return "VPX P-Frame QP Value"; + case ((0x00990000 | 0x900) + 511): + return "VP8 Profile"; + case ((0x00990000 | 0x900) + 512): + return "VP9 Profile"; + case ((0x00990000 | 0x900) + 2000): + return "VP8 Frame Header"; + + case ((0x00990000 | 0x900) + 602): + return "HEVC I-Frame QP Value"; + case ((0x00990000 | 0x900) + 603): + return "HEVC P-Frame QP Value"; + case ((0x00990000 | 0x900) + 604): + return "HEVC B-Frame QP Value"; + case ((0x00990000 | 0x900) + 600): + return "HEVC Minimum QP Value"; + case ((0x00990000 | 0x900) + 601): + return "HEVC Maximum QP Value"; + case ((0x00990000 | 0x900) + 615): + return "HEVC Profile"; + case ((0x00990000 | 0x900) + 616): + return "HEVC Level"; + case ((0x00990000 | 0x900) + 618): + return "HEVC Tier"; + case ((0x00990000 | 0x900) + 617): + return "HEVC Frame Rate Resolution"; + case ((0x00990000 | 0x900) + 619): + return "HEVC Maximum Coding Unit Depth"; + case ((0x00990000 | 0x900) + 623): + return "HEVC Refresh Type"; + case ((0x00990000 | 0x900) + 626): + return "HEVC Constant Intra Prediction"; + case ((0x00990000 | 0x900) + 625): + return "HEVC Lossless Encoding"; + case ((0x00990000 | 0x900) + 627): + return "HEVC Wavefront"; + case ((0x00990000 | 0x900) + 620): + return "HEVC Loop Filter"; + case ((0x00990000 | 0x900) + 605): + return "HEVC QP Values"; + case ((0x00990000 | 0x900) + 606): + return "HEVC Hierarchical Coding Type"; + case ((0x00990000 | 0x900) + 607): + return "HEVC Hierarchical Coding Layer"; + case ((0x00990000 | 0x900) + 608): + return "HEVC Hierarchical Layer 0 QP"; + case ((0x00990000 | 0x900) + 609): + return "HEVC Hierarchical Layer 1 QP"; + case ((0x00990000 | 0x900) + 610): + return "HEVC Hierarchical Layer 2 QP"; + case ((0x00990000 | 0x900) + 611): + return "HEVC Hierarchical Layer 3 QP"; + case ((0x00990000 | 0x900) + 612): + return "HEVC Hierarchical Layer 4 QP"; + case ((0x00990000 | 0x900) + 613): + return "HEVC Hierarchical Layer 5 QP"; + case ((0x00990000 | 0x900) + 614): + return "HEVC Hierarchical Layer 6 QP"; + case ((0x00990000 | 0x900) + 636): + return "HEVC Hierarchical Lay 0 BitRate"; + case ((0x00990000 | 0x900) + 637): + return "HEVC Hierarchical Lay 1 BitRate"; + case ((0x00990000 | 0x900) + 638): + return "HEVC Hierarchical Lay 2 BitRate"; + case ((0x00990000 | 0x900) + 639): + return "HEVC Hierarchical Lay 3 BitRate"; + case ((0x00990000 | 0x900) + 640): + return "HEVC Hierarchical Lay 4 BitRate"; + case ((0x00990000 | 0x900) + 641): + return "HEVC Hierarchical Lay 5 BitRate"; + case ((0x00990000 | 0x900) + 642): + return "HEVC Hierarchical Lay 6 BitRate"; + case ((0x00990000 | 0x900) + 628): + return "HEVC General PB"; + case ((0x00990000 | 0x900) + 629): + return "HEVC Temporal ID"; + case ((0x00990000 | 0x900) + 630): + return "HEVC Strong Intra Smoothing"; + case ((0x00990000 | 0x900) + 632): + return "HEVC Intra PU Split"; + case ((0x00990000 | 0x900) + 633): + return "HEVC TMV Prediction"; + case ((0x00990000 | 0x900) + 631): + return "HEVC Max Num of Candidate MVs"; + case ((0x00990000 | 0x900) + 634): + return "HEVC ENC Without Startcode"; + case ((0x00990000 | 0x900) + 624): + return "HEVC Num of I-Frame b/w 2 IDR"; + case ((0x00990000 | 0x900) + 621): + return "HEVC Loop Filter Beta Offset"; + case ((0x00990000 | 0x900) + 622): + return "HEVC Loop Filter TC Offset"; + case ((0x00990000 | 0x900) + 635): + return "HEVC Size of Length Field"; + case ((0x00990000 | 0x900) + 643): + return "Reference Frames for a P-Frame"; + case ((0x00990000 | 0x900) + 644): + return "Prepend SPS and PPS to IDR"; + case ((0x00990000 | 0x900) + 1008): + return "HEVC Sequence Parameter Set"; + case ((0x00990000 | 0x900) + 1009): + return "HEVC Picture Parameter Set"; + case ((0x00990000 | 0x900) + 1010): + return "HEVC Slice Parameters"; + case ((0x00990000 | 0x900) + 1015): + return "HEVC Decode Mode"; + case ((0x00990000 | 0x900) + 1016): + return "HEVC Start Code"; + + case (0x009a0000 | 1): + return "Camera Controls"; + case ((0x009a0000 | 0x900) + 1): + return "Auto Exposure"; + case ((0x009a0000 | 0x900) + 2): + return "Exposure Time, Absolute"; + case ((0x009a0000 | 0x900) + 3): + return "Exposure, Dynamic Framerate"; + case ((0x009a0000 | 0x900) + 4): + return "Pan, Relative"; + case ((0x009a0000 | 0x900) + 5): + return "Tilt, Relative"; + case ((0x009a0000 | 0x900) + 6): + return "Pan, Reset"; + case ((0x009a0000 | 0x900) + 7): + return "Tilt, Reset"; + case ((0x009a0000 | 0x900) + 8): + return "Pan, Absolute"; + case ((0x009a0000 | 0x900) + 9): + return "Tilt, Absolute"; + case ((0x009a0000 | 0x900) + 10): + return "Focus, Absolute"; + case ((0x009a0000 | 0x900) + 11): + return "Focus, Relative"; + case ((0x009a0000 | 0x900) + 12): + return "Focus, Automatic Continuous"; + case ((0x009a0000 | 0x900) + 13): + return "Zoom, Absolute"; + case ((0x009a0000 | 0x900) + 14): + return "Zoom, Relative"; + case ((0x009a0000 | 0x900) + 15): + return "Zoom, Continuous"; + case ((0x009a0000 | 0x900) + 16): + return "Privacy"; + case ((0x009a0000 | 0x900) + 17): + return "Iris, Absolute"; + case ((0x009a0000 | 0x900) + 18): + return "Iris, Relative"; + case ((0x009a0000 | 0x900) + 19): + return "Auto Exposure, Bias"; + case ((0x009a0000 | 0x900) + 20): + return "White Balance, Auto & Preset"; + case ((0x009a0000 | 0x900) + 21): + return "Wide Dynamic Range"; + case ((0x009a0000 | 0x900) + 22): + return "Image Stabilization"; + case ((0x009a0000 | 0x900) + 23): + return "ISO Sensitivity"; + case ((0x009a0000 | 0x900) + 24): + return "ISO Sensitivity, Auto"; + case ((0x009a0000 | 0x900) + 25): + return "Exposure, Metering Mode"; + case ((0x009a0000 | 0x900) + 26): + return "Scene Mode"; + case ((0x009a0000 | 0x900) + 27): + return "3A Lock"; + case ((0x009a0000 | 0x900) + 28): + return "Auto Focus, Start"; + case ((0x009a0000 | 0x900) + 29): + return "Auto Focus, Stop"; + case ((0x009a0000 | 0x900) + 30): + return "Auto Focus, Status"; + case ((0x009a0000 | 0x900) + 31): + return "Auto Focus, Range"; + case ((0x009a0000 | 0x900) + 32): + return "Pan, Speed"; + case ((0x009a0000 | 0x900) + 33): + return "Tilt, Speed"; + case ((0x009e0000 | 0x900) + 8): + return "Unit Cell Size"; + case ((0x009a0000 | 0x900) + 34): + return "Camera Orientation"; + case ((0x009a0000 | 0x900) + 35): + return "Camera Sensor Rotation"; + + case (0x009b0000 | 1): + return "FM Radio Modulator Controls"; + case ((0x009b0000 | 0x900) + 1): + return "RDS Signal Deviation"; + case ((0x009b0000 | 0x900) + 2): + return "RDS Program ID"; + case ((0x009b0000 | 0x900) + 3): + return "RDS Program Type"; + case ((0x009b0000 | 0x900) + 5): + return "RDS PS Name"; + case ((0x009b0000 | 0x900) + 6): + return "RDS Radio Text"; + case ((0x009b0000 | 0x900) + 7): + return "RDS Stereo"; + case ((0x009b0000 | 0x900) + 8): + return "RDS Artificial Head"; + case ((0x009b0000 | 0x900) + 9): + return "RDS Compressed"; + case ((0x009b0000 | 0x900) + 10): + return "RDS Dynamic PTY"; + case ((0x009b0000 | 0x900) + 11): + return "RDS Traffic Announcement"; + case ((0x009b0000 | 0x900) + 12): + return "RDS Traffic Program"; + case ((0x009b0000 | 0x900) + 13): + return "RDS Music"; + case ((0x009b0000 | 0x900) + 14): + return "RDS Enable Alt Frequencies"; + case ((0x009b0000 | 0x900) + 15): + return "RDS Alternate Frequencies"; + case ((0x009b0000 | 0x900) + 64): + return "Audio Limiter Feature Enabled"; + case ((0x009b0000 | 0x900) + 65): + return "Audio Limiter Release Time"; + case ((0x009b0000 | 0x900) + 66): + return "Audio Limiter Deviation"; + case ((0x009b0000 | 0x900) + 80): + return "Audio Compression Enabled"; + case ((0x009b0000 | 0x900) + 81): + return "Audio Compression Gain"; + case ((0x009b0000 | 0x900) + 82): + return "Audio Compression Threshold"; + case ((0x009b0000 | 0x900) + 83): + return "Audio Compression Attack Time"; + case ((0x009b0000 | 0x900) + 84): + return "Audio Compression Release Time"; + case ((0x009b0000 | 0x900) + 96): + return "Pilot Tone Feature Enabled"; + case ((0x009b0000 | 0x900) + 97): + return "Pilot Tone Deviation"; + case ((0x009b0000 | 0x900) + 98): + return "Pilot Tone Frequency"; + case ((0x009b0000 | 0x900) + 112): + return "Pre-Emphasis"; + case ((0x009b0000 | 0x900) + 113): + return "Tune Power Level"; + case ((0x009b0000 | 0x900) + 114): + return "Tune Antenna Capacitor"; + + case (0x009c0000 | 1): + return "Flash Controls"; + case ((0x009c0000 | 0x900) + 1): + return "LED Mode"; + case ((0x009c0000 | 0x900) + 2): + return "Strobe Source"; + case ((0x009c0000 | 0x900) + 3): + return "Strobe"; + case ((0x009c0000 | 0x900) + 4): + return "Stop Strobe"; + case ((0x009c0000 | 0x900) + 5): + return "Strobe Status"; + case ((0x009c0000 | 0x900) + 6): + return "Strobe Timeout"; + case ((0x009c0000 | 0x900) + 7): + return "Intensity, Flash Mode"; + case ((0x009c0000 | 0x900) + 8): + return "Intensity, Torch Mode"; + case ((0x009c0000 | 0x900) + 9): + return "Intensity, Indicator"; + case ((0x009c0000 | 0x900) + 10): + return "Faults"; + case ((0x009c0000 | 0x900) + 11): + return "Charge"; + case ((0x009c0000 | 0x900) + 12): + return "Ready to Strobe"; + + case (0x009d0000 | 1): + return "JPEG Compression Controls"; + case ((0x009d0000 | 0x900) + 1): + return "Chroma Subsampling"; + case ((0x009d0000 | 0x900) + 2): + return "Restart Interval"; + case ((0x009d0000 | 0x900) + 3): + return "Compression Quality"; + case ((0x009d0000 | 0x900) + 4): + return "Active Markers"; + + case (0x009e0000 | 1): + return "Image Source Controls"; + case ((0x009e0000 | 0x900) + 1): + return "Vertical Blanking"; + case ((0x009e0000 | 0x900) + 2): + return "Horizontal Blanking"; + case ((0x009e0000 | 0x900) + 3): + return "Analogue Gain"; + case ((0x009e0000 | 0x900) + 4): + return "Red Pixel Value"; + case ((0x009e0000 | 0x900) + 5): + return "Green (Red) Pixel Value"; + case ((0x009e0000 | 0x900) + 6): + return "Blue Pixel Value"; + case ((0x009e0000 | 0x900) + 7): + return "Green (Blue) Pixel Value"; + + case (0x009f0000 | 1): + return "Image Processing Controls"; + case ((0x009f0000 | 0x900) + 1): + return "Link Frequency"; + case ((0x009f0000 | 0x900) + 2): + return "Pixel Rate"; + case ((0x009f0000 | 0x900) + 3): + return "Test Pattern"; + case ((0x009f0000 | 0x900) + 4): + return "Deinterlacing Mode"; + case ((0x009f0000 | 0x900) + 5): + return "Digital Gain"; + + case (0x00a00000 | 1): + return "Digital Video Controls"; + case ((0x00a00000 | 0x900) + 1): + return "Hotplug Present"; + case ((0x00a00000 | 0x900) + 2): + return "RxSense Present"; + case ((0x00a00000 | 0x900) + 3): + return "EDID Present"; + case ((0x00a00000 | 0x900) + 4): + return "Transmit Mode"; + case ((0x00a00000 | 0x900) + 5): + return "Tx RGB Quantization Range"; + case ((0x00a00000 | 0x900) + 6): + return "Tx IT Content Type"; + case ((0x00a00000 | 0x900) + 100): + return "Power Present"; + case ((0x00a00000 | 0x900) + 101): + return "Rx RGB Quantization Range"; + case ((0x00a00000 | 0x900) + 102): + return "Rx IT Content Type"; + + case (0x00a10000 | 1): + return "FM Radio Receiver Controls"; + case ((0x00a10000 | 0x900) + 1): + return "De-Emphasis"; + case ((0x00a10000 | 0x900) + 2): + return "RDS Reception"; + case (0x00a20000 | 1): + return "RF Tuner Controls"; + case ((0x00a20000 | 0x900) + 32): + return "RF Gain"; + case ((0x00a20000 | 0x900) + 41): + return "LNA Gain, Auto"; + case ((0x00a20000 | 0x900) + 42): + return "LNA Gain"; + case ((0x00a20000 | 0x900) + 51): + return "Mixer Gain, Auto"; + case ((0x00a20000 | 0x900) + 52): + return "Mixer Gain"; + case ((0x00a20000 | 0x900) + 61): + return "IF Gain, Auto"; + case ((0x00a20000 | 0x900) + 62): + return "IF Gain"; + case ((0x00a20000 | 0x900) + 11): + return "Bandwidth, Auto"; + case ((0x00a20000 | 0x900) + 12): + return "Bandwidth"; + case ((0x00a20000 | 0x900) + 91): + return "PLL Lock"; + case ((0x00a10000 | 0x900) + 3): + return "RDS Program Type"; + case ((0x00a10000 | 0x900) + 4): + return "RDS PS Name"; + case ((0x00a10000 | 0x900) + 5): + return "RDS Radio Text"; + case ((0x00a10000 | 0x900) + 6): + return "RDS Traffic Announcement"; + case ((0x00a10000 | 0x900) + 7): + return "RDS Traffic Program"; + case ((0x00a10000 | 0x900) + 8): + return "RDS Music"; + + case (0x00a30000 | 1): + return "Detection Controls"; + case ((0x00a30000 | 0x900) + 1): + return "Motion Detection Mode"; + case ((0x00a30000 | 0x900) + 2): + return "MD Global Threshold"; + case ((0x00a30000 | 0x900) + 3): + return "MD Threshold Grid"; + case ((0x00a30000 | 0x900) + 4): + return "MD Region Grid"; + default: + return ((void *)0); + } +} + +void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, + s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags) { + *name = v4l2_ctrl_get_name(id); + *flags = 0; + + switch (id) { + case ((0x00980000 | 0x900) + 9): + case ((0x00980000 | 0x900) + 10): + case ((0x00980000 | 0x900) + 12): + case ((0x00980000 | 0x900) + 18): + case ((0x00980000 | 0x900) + 20): + case ((0x00980000 | 0x900) + 21): + case ((0x00980000 | 0x900) + 25): + case ((0x00980000 | 0x900) + 29): + case ((0x00980000 | 0x900) + 30): + case ((0x00980000 | 0x900) + 32): + case ((0x00990000 | 0x900) + 109): + case ((0x00990000 | 0x900) + 210): + case ((0x00990000 | 0x900) + 204): + case ((0x00990000 | 0x900) + 205): + case ((0x009a0000 | 0x900) + 3): + case ((0x009a0000 | 0x900) + 12): + case ((0x009a0000 | 0x900) + 16): + case ((0x009b0000 | 0x900) + 64): + case ((0x009b0000 | 0x900) + 80): + case ((0x009b0000 | 0x900) + 96): + case ((0x00980000 | 0x900) + 37): + case ((0x00980000 | 0x900) + 38): + case ((0x009c0000 | 0x900) + 5): + case ((0x009c0000 | 0x900) + 11): + case ((0x009c0000 | 0x900) + 12): + case ((0x00990000 | 0x900) + 213): + case ((0x00990000 | 0x900) + 212): + case ((0x00990000 | 0x900) + 215): + case ((0x00990000 | 0x900) + 218): + case ((0x00990000 | 0x900) + 355): + case ((0x00990000 | 0x900) + 366): + case ((0x00990000 | 0x900) + 407): + case ((0x00990000 | 0x900) + 226): + case ((0x009a0000 | 0x900) + 21): + case ((0x009a0000 | 0x900) + 22): + case ((0x00a10000 | 0x900) + 2): + case ((0x00a20000 | 0x900) + 41): + case ((0x00a20000 | 0x900) + 51): + case ((0x00a20000 | 0x900) + 61): + case ((0x00a20000 | 0x900) + 11): + case ((0x00a20000 | 0x900) + 91): + case ((0x009b0000 | 0x900) + 7): + case ((0x009b0000 | 0x900) + 8): + case ((0x009b0000 | 0x900) + 9): + case ((0x009b0000 | 0x900) + 10): + case ((0x009b0000 | 0x900) + 11): + case ((0x009b0000 | 0x900) + 12): + case ((0x009b0000 | 0x900) + 13): + case ((0x009b0000 | 0x900) + 14): + case ((0x00a10000 | 0x900) + 6): + case ((0x00a10000 | 0x900) + 7): + case ((0x00a10000 | 0x900) + 8): + *type = V4L2_CTRL_TYPE_BOOLEAN; + *min = 0; + *max = *step = 1; + break; + case ((0x00980000 | 0x900) + 34): + *type = V4L2_CTRL_TYPE_INTEGER; + *flags |= 0x0400; + break; + case ((0x00990000 | 0x900) + 227): + case ((0x00990000 | 0x900) + 228): + *type = V4L2_CTRL_TYPE_INTEGER; + break; + case ((0x00990000 | 0x900) + 229): + case ((0x009a0000 | 0x900) + 6): + case ((0x009a0000 | 0x900) + 7): + case ((0x009c0000 | 0x900) + 3): + case ((0x009c0000 | 0x900) + 4): + case ((0x009a0000 | 0x900) + 28): + case ((0x009a0000 | 0x900) + 29): + case ((0x00980000 | 0x900) + 13): + *type = V4L2_CTRL_TYPE_BUTTON; + *flags |= 0x0040 | 0x0200; + *min = *max = *step = *def = 0; + break; + case ((0x00980000 | 0x900) + 24): + case ((0x00990000 | 0x900) + 100): + case ((0x00990000 | 0x900) + 101): + case ((0x00990000 | 0x900) + 102): + case ((0x00990000 | 0x900) + 103): + case ((0x00990000 | 0x900) + 104): + case ((0x00990000 | 0x900) + 111): + case ((0x00990000 | 0x900) + 105): + case ((0x00990000 | 0x900) + 106): + case ((0x00990000 | 0x900) + 107): + case ((0x00990000 | 0x900) + 108): + case ((0x00990000 | 0x900) + 112): + case ((0x00990000 | 0x900) + 113): + case ((0x00990000 | 0x900) + 200): + case ((0x00990000 | 0x900) + 201): + case ((0x00990000 | 0x900) + 206): + case ((0x00990000 | 0x900) + 0): + case ((0x00990000 | 0x900) + 7): + case ((0x009a0000 | 0x900) + 1): + case ((0x009a0000 | 0x900) + 31): + case ((0x00980000 | 0x900) + 31): + case ((0x009a0000 | 0x900) + 20): + case ((0x009b0000 | 0x900) + 112): + case ((0x009c0000 | 0x900) + 1): + case ((0x009c0000 | 0x900) + 2): + case ((0x00990000 | 0x900) + 216): + case ((0x00990000 | 0x900) + 221): + case ((0x00990000 | 0x900) + 357): + case ((0x00990000 | 0x900) + 359): + case ((0x00990000 | 0x900) + 362): + case ((0x00990000 | 0x900) + 363): + case ((0x00990000 | 0x900) + 367): + case ((0x00990000 | 0x900) + 370): + case ((0x00990000 | 0x900) + 372): + case ((0x00990000 | 0x900) + 1005): + case ((0x00990000 | 0x900) + 1006): + case ((0x00990000 | 0x900) + 270): + case ((0x00990000 | 0x900) + 271): + case ((0x00990000 | 0x900) + 405): + case ((0x00990000 | 0x900) + 406): + case ((0x009d0000 | 0x900) + 1): + case ((0x009a0000 | 0x900) + 24): + case ((0x009a0000 | 0x900) + 25): + case ((0x009a0000 | 0x900) + 26): + case ((0x00a00000 | 0x900) + 4): + case ((0x00a00000 | 0x900) + 5): + case ((0x00a00000 | 0x900) + 6): + case ((0x00a00000 | 0x900) + 101): + case ((0x00a00000 | 0x900) + 102): + case ((0x009f0000 | 0x900) + 3): + case ((0x009f0000 | 0x900) + 4): + case ((0x00a10000 | 0x900) + 1): + case ((0x00990000 | 0x900) + 506): + case ((0x00990000 | 0x900) + 511): + case ((0x00990000 | 0x900) + 512): + case ((0x00a30000 | 0x900) + 1): + case ((0x00990000 | 0x900) + 615): + case ((0x00990000 | 0x900) + 616): + case ((0x00990000 | 0x900) + 606): + case ((0x00990000 | 0x900) + 623): + case ((0x00990000 | 0x900) + 635): + case ((0x00990000 | 0x900) + 618): + case ((0x00990000 | 0x900) + 620): + case ((0x00990000 | 0x900) + 1015): + case ((0x00990000 | 0x900) + 1016): + case ((0x009a0000 | 0x900) + 34): + *type = V4L2_CTRL_TYPE_MENU; + break; + case ((0x009f0000 | 0x900) + 1): + *type = V4L2_CTRL_TYPE_INTEGER_MENU; + break; + case ((0x009b0000 | 0x900) + 5): + case ((0x009b0000 | 0x900) + 6): + case ((0x00a10000 | 0x900) + 4): + case ((0x00a10000 | 0x900) + 5): + *type = V4L2_CTRL_TYPE_STRING; + break; + case ((0x009a0000 | 0x900) + 23): + case ((0x009a0000 | 0x900) + 19): + case ((0x00990000 | 0x900) + 500): + case ((0x00990000 | 0x900) + 502): + *type = V4L2_CTRL_TYPE_INTEGER_MENU; + break; + case (0x00980000 | 1): + case (0x009a0000 | 1): + case (0x00990000 | 1): + case (0x009b0000 | 1): + case (0x009c0000 | 1): + case (0x009d0000 | 1): + case (0x009e0000 | 1): + case (0x009f0000 | 1): + case (0x00a00000 | 1): + case (0x00a10000 | 1): + case (0x00a20000 | 1): + case (0x00a30000 | 1): + *type = V4L2_CTRL_TYPE_CTRL_CLASS; + + *flags |= 0x0004 | 0x0040; + *min = *max = *step = *def = 0; + break; + case ((0x00980000 | 0x900) + 35): + *type = V4L2_CTRL_TYPE_INTEGER; + *step = 1; + *min = 0; + + *max = 0xFFFFFF; + break; + case ((0x009c0000 | 0x900) + 10): + case ((0x009d0000 | 0x900) + 4): + case ((0x009a0000 | 0x900) + 27): + case ((0x009a0000 | 0x900) + 30): + case ((0x00a00000 | 0x900) + 1): + case ((0x00a00000 | 0x900) + 2): + case ((0x00a00000 | 0x900) + 3): + case ((0x00a00000 | 0x900) + 100): + *type = V4L2_CTRL_TYPE_BITMASK; + break; + case ((0x00980000 | 0x900) + 39): + case ((0x00980000 | 0x900) + 40): + *type = V4L2_CTRL_TYPE_INTEGER; + *flags |= 0x0004; + break; + case ((0x00990000 | 0x900) + 223): + *type = V4L2_CTRL_TYPE_INTEGER64; + *flags |= 0x0080 | 0x0004; + *min = *def = 0; + *max = 0x1ffffffffLL; + *step = 1; + break; + case ((0x00990000 | 0x900) + 224): + *type = V4L2_CTRL_TYPE_INTEGER64; + *flags |= 0x0080 | 0x0004; + *min = *def = 0; + *max = 0x7fffffffffffffffLL; + *step = 1; + break; + case ((0x009f0000 | 0x900) + 2): + *type = V4L2_CTRL_TYPE_INTEGER64; + *flags |= 0x0004; + break; + case ((0x00a30000 | 0x900) + 4): + *type = V4L2_CTRL_TYPE_U8; + break; + case ((0x00a30000 | 0x900) + 3): + *type = V4L2_CTRL_TYPE_U16; + break; + case ((0x009b0000 | 0x900) + 15): + *type = V4L2_CTRL_TYPE_U32; + break; + case ((0x00990000 | 0x900) + 250): + *type = 0x0103; + break; + case ((0x00990000 | 0x900) + 251): + *type = 0x0104; + break; + case ((0x00990000 | 0x900) + 292): + *type = 0x0105; + break; + case ((0x00990000 | 0x900) + 1000): + *type = 0x0110; + break; + case ((0x00990000 | 0x900) + 1001): + *type = 0x0111; + break; + case ((0x00990000 | 0x900) + 1002): + *type = 0x0112; + break; + case ((0x00990000 | 0x900) + 1003): + *type = 0x0113; + break; + case ((0x00990000 | 0x900) + 1004): + *type = 0x0114; + break; + case ((0x00990000 | 0x900) + 2000): + *type = 0x301; + break; + case ((0x00990000 | 0x900) + 1008): + *type = 0x0120; + break; + case ((0x00990000 | 0x900) + 1009): + *type = 0x0121; + break; + case ((0x00990000 | 0x900) + 1010): + *type = 0x0122; + break; + case ((0x009e0000 | 0x900) + 8): + *type = V4L2_CTRL_TYPE_AREA; + *flags |= 0x0004; + break; + default: + *type = V4L2_CTRL_TYPE_INTEGER; + break; + } + switch (id) { + case ((0x00990000 | 0x900) + 101): + case ((0x00990000 | 0x900) + 105): + case ((0x00990000 | 0x900) + 206): + case ((0x00990000 | 0x900) + 202): + case ((0x00990000 | 0x900) + 0): + *flags |= 0x0008; + break; + case ((0x00980000 | 0x900) + 5): + case ((0x00980000 | 0x900) + 6): + case ((0x00980000 | 0x900) + 7): + case ((0x00980000 | 0x900) + 8): + case ((0x00980000 | 0x900) + 0): + case ((0x00980000 | 0x900) + 1): + case ((0x00980000 | 0x900) + 2): + case ((0x00980000 | 0x900) + 3): + case ((0x00980000 | 0x900) + 14): + case ((0x00980000 | 0x900) + 15): + case ((0x00980000 | 0x900) + 16): + case ((0x00980000 | 0x900) + 27): + case ((0x00980000 | 0x900) + 36): + case ((0x009b0000 | 0x900) + 1): + case ((0x009b0000 | 0x900) + 65): + case ((0x009b0000 | 0x900) + 66): + case ((0x009b0000 | 0x900) + 81): + case ((0x009b0000 | 0x900) + 82): + case ((0x009b0000 | 0x900) + 83): + case ((0x009b0000 | 0x900) + 84): + case ((0x009b0000 | 0x900) + 97): + case ((0x009b0000 | 0x900) + 98): + case ((0x009b0000 | 0x900) + 113): + case ((0x009b0000 | 0x900) + 114): + case ((0x00a20000 | 0x900) + 32): + case ((0x00a20000 | 0x900) + 42): + case ((0x00a20000 | 0x900) + 52): + case ((0x00a20000 | 0x900) + 62): + case ((0x00a20000 | 0x900) + 12): + case ((0x00a30000 | 0x900) + 2): + *flags |= 0x0020; + break; + case ((0x009a0000 | 0x900) + 4): + case ((0x009a0000 | 0x900) + 5): + case ((0x009a0000 | 0x900) + 11): + case ((0x009a0000 | 0x900) + 18): + case ((0x009a0000 | 0x900) + 14): + *flags |= 0x0040 | 0x0200; + break; + case ((0x009c0000 | 0x900) + 5): + case ((0x009a0000 | 0x900) + 30): + case ((0x009c0000 | 0x900) + 12): + case ((0x00a00000 | 0x900) + 1): + case ((0x00a00000 | 0x900) + 2): + case ((0x00a00000 | 0x900) + 3): + case ((0x00a00000 | 0x900) + 100): + case ((0x00a00000 | 0x900) + 102): + case ((0x00a10000 | 0x900) + 3): + case ((0x00a10000 | 0x900) + 4): + case ((0x00a10000 | 0x900) + 5): + case ((0x00a10000 | 0x900) + 6): + case ((0x00a10000 | 0x900) + 7): + case ((0x00a10000 | 0x900) + 8): + case ((0x009a0000 | 0x900) + 34): + case ((0x009a0000 | 0x900) + 35): + *flags |= 0x0004; + break; + case ((0x00a20000 | 0x900) + 91): + *flags |= 0x0080; + break; + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96699.c b/gcc/testsuite/gcc.dg/analyzer/pr96699.c new file mode 100644 index 0000000..c68e45a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96699.c @@ -0,0 +1,13 @@ +struct qi { + union { + int hj; + float sl; + }; +}; + +void +i2 (struct qi *la) +{ + if (la->hj == 0) + la->sl = 0.0f; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96705.c b/gcc/testsuite/gcc.dg/analyzer/pr96705.c new file mode 100644 index 0000000..d7856d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96705.c @@ -0,0 +1,9 @@ +int __attribute__ ((vector_size (8))) v; +int i; + +void +test (void) +{ + v &= 0; + v *= i; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96713.c b/gcc/testsuite/gcc.dg/analyzer/pr96713.c new file mode 100644 index 0000000..fe9cafd --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96713.c @@ -0,0 +1,8 @@ +typedef int __attribute__ ((vector_size (8))) V; + +void +foo (V d, V e) +{ + d <= e; + foo ((V){}, (V){}); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96764.c b/gcc/testsuite/gcc.dg/analyzer/pr96764.c new file mode 100644 index 0000000..70b25d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96764.c @@ -0,0 +1,6 @@ +void +ar (int *hd) +{ + int **zv = &hd; + *(double *) zv = 0.0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96777.c b/gcc/testsuite/gcc.dg/analyzer/pr96777.c new file mode 100644 index 0000000..2bb2a4e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96777.c @@ -0,0 +1,12 @@ +struct ge { + char au; + char pz[]; +}; + +struct ge tr = { 'X', 'X', }; + +int +main (void) +{ + return tr.pz[0] == 'X'; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96792.c b/gcc/testsuite/gcc.dg/analyzer/pr96792.c new file mode 100644 index 0000000..7757645 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96792.c @@ -0,0 +1,39 @@ +#define NULL (void *)0 + +struct block +{ + void *function; + const struct block *superblock; +}; + +struct global_block +{ + struct block block; + void *compunit_symtab; +}; + +extern const struct block *block_global_block (const struct block *block); + +void * +block_objfile (const struct block *block) +{ + const struct global_block *global_block; + + if (block->function != NULL) + return block->function; + + global_block = (struct global_block *) block_global_block (block); + return global_block->compunit_symtab; +} + +const struct block * +block_global_block (const struct block *block) +{ + if (block == NULL) + return NULL; + + while (block->superblock != NULL) + block = block->superblock; + + return block; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96841.c b/gcc/testsuite/gcc.dg/analyzer/pr96841.c new file mode 100644 index 0000000..d9d35f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96841.c @@ -0,0 +1,23 @@ +/* { dg-additional-options "-O1 -Wno-builtin-declaration-mismatch" } */ + +int +l8 (void); + +__SIZE_TYPE__ +malloc (__SIZE_TYPE__); + +void +th (int *); + +void +bv (__SIZE_TYPE__ ny) +{ + int ***mf; + + while (l8 ()) + { + *mf = 0; + (*mf)[ny] = (int *) malloc (sizeof (int)); + th ((*mf)[ny]); /* { dg-warning "leak" } */ + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c new file mode 100644 index 0000000..8f298ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c @@ -0,0 +1,9 @@ +/* { dg-require-effective-target int128 } */ +/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */ + +void x7 (void) +{ + __int128 z5[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, + }; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c new file mode 100644 index 0000000..90a818c --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */ + +void x7 (void) +{ + long z5[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, + }; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97029.c b/gcc/testsuite/gcc.dg/analyzer/pr97029.c new file mode 100644 index 0000000..ff83ad4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr97029.c @@ -0,0 +1,7 @@ +struct vj {}; + +void +setjmp (struct vj pl) +{ + setjmp (pl); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97130.c b/gcc/testsuite/gcc.dg/analyzer/pr97130.c new file mode 100644 index 0000000..f437b76 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr97130.c @@ -0,0 +1,10 @@ +/* { dg-additional-options "-Wno-builtin-declaration-mismatch" } */ + +void * +memset (int, int, __SIZE_TYPE__); + +void +mp (int xl) +{ + memset (xl, 0, sizeof xl); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97233.c b/gcc/testsuite/gcc.dg/analyzer/pr97233.c new file mode 100644 index 0000000..86930aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr97233.c @@ -0,0 +1,8 @@ +void +longjmp (__SIZE_TYPE__, int); + +void +e7 (__SIZE_TYPE__ gr) +{ + longjmp (gr, 1); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/refcounting-1.c b/gcc/testsuite/gcc.dg/analyzer/refcounting-1.c new file mode 100644 index 0000000..4eb3a3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/refcounting-1.c @@ -0,0 +1,31 @@ +#include "analyzer-decls.h" + +typedef struct obj { + int ob_refcnt; +} PyObject; + +extern void Py_Dealloc (PyObject *op); + +#define Py_INCREF(op) \ + do { \ + ((PyObject*)(op))->ob_refcnt++; \ + } while (0) + +#define Py_DECREF(op) \ + do { \ + if (--((PyObject*)(op))->ob_refcnt == 0) \ + { \ + /*Py_Dealloc((PyObject *)(op));*/ \ + } \ + } while (0) + +void test_1 (PyObject *obj) +{ + int orig_refcnt = obj->ob_refcnt; + Py_INCREF (obj); + Py_INCREF (obj); + Py_DECREF (obj); + Py_INCREF (obj); + __analyzer_eval (obj->ob_refcnt == orig_refcnt + 2); /* { dg-warning "TRUE" } */ +} +/* TODO: uncomment the Py_Dealloc, which leads to two paths. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/rhbz1878600.c b/gcc/testsuite/gcc.dg/analyzer/rhbz1878600.c new file mode 100644 index 0000000..9f6ccb6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/rhbz1878600.c @@ -0,0 +1,34 @@ +#include <stdio.h> + +#define INI_MAX_LINE 200 + +typedef char* (*ini_reader)(char* str, int num, void* stream); + +int ini_parse(const char* filename); + +static int ini_parse_stream(ini_reader reader, void* stream) +{ + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; + while (reader(line, max_line, stream) != NULL) + ; + return 0; +} + +static int ini_parse_file(FILE* file) +{ + return ini_parse_stream((ini_reader)fgets, file); +} + +int ini_parse(const char* filename) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file); + fclose(file); + return error; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-1.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-1.c index c9827fb..72da6c4 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-1.c @@ -1 +1,2 @@ +/* { dg-require-effective-target indirect_jumps } */ #include "../pr26983.c" diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c index beaf436..f5d9c53 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include "test-setjmp.h" #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c index 5c1d406..3e4f870 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include <stddef.h> #include "test-setjmp.h" diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c index f216a45..b6f7d0e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include "test-setjmp.h" #include "analyzer-decls.h" diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c index 3ee0298..bf5b9bf 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include "test-setjmp.h" #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-6.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-6.c index 0e0f12f..3aa6b23 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-6.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-6.c @@ -1,3 +1,5 @@ +/* { dg-require-effective-target indirect_jumps } */ + #include "test-setjmp.h" #include <stddef.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-7.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-7.c index 6cf9824..6a519b7 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-7.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-7.c @@ -1,3 +1,5 @@ +/* { dg-require-effective-target indirect_jumps } */ + #include "test-setjmp.h" #include <stddef.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-7a.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-7a.c index 87d35bc..220f95e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-7a.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-7a.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include "test-setjmp.h" #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c index abbee2d..79614d1 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include "test-setjmp.h" #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c index cf75d3a..c2b00e3 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target indirect_jumps } */ #include "test-setjmp.h" #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-pr93378.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-pr93378.c index 73b94d4..6e2468e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-pr93378.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-pr93378.c @@ -1,4 +1,5 @@ /* { dg-additional-options "-O1 -g" } */ +/* { dg-require-effective-target indirect_jumps } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-1.c b/gcc/testsuite/gcc.dg/analyzer/signal-1.c index 4dcbcc0..43f911b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-1.c @@ -1,6 +1,7 @@ /* Example of a bad call within a signal handler. 'handler' calls 'custom_logger' which calls 'fprintf', and 'fprintf' is not allowed from a signal handler. */ +/* { dg-require-effective-target signal } */ #include <stdio.h> #include <signal.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-2.c b/gcc/testsuite/gcc.dg/analyzer/signal-2.c index a56acb0..d047c67 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-2.c @@ -1,6 +1,7 @@ /* Example of a bad call within a signal handler. 'handler' calls 'custom_logger' which calls 'fprintf', and 'fprintf' is not allowed from a signal handler. */ +/* { dg-require-effective-target signal } */ #include <stdio.h> #include <signal.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-3.c b/gcc/testsuite/gcc.dg/analyzer/signal-3.c index 5b30888..f5072b5 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-3.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target signal } */ #include <stdio.h> #include <signal.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-4a.c b/gcc/testsuite/gcc.dg/analyzer/signal-4a.c index 4b68b6d..4ee6f0e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-4a.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-4a.c @@ -2,6 +2,7 @@ /* { dg-options "-fanalyzer -fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target signal } */ #include <stdio.h> #include <signal.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-4b.c b/gcc/testsuite/gcc.dg/analyzer/signal-4b.c index 38d4024..cb1e7e4 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-4b.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-4b.c @@ -2,6 +2,7 @@ /* { dg-options "-fanalyzer -fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ /* { dg-enable-nn-line-numbers "" } */ +/* { dg-require-effective-target signal } */ #include <stdio.h> #include <signal.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-5.c b/gcc/testsuite/gcc.dg/analyzer/signal-5.c index 4e464ff..81ac812 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-5.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-5.c @@ -1,4 +1,5 @@ /* Example of other bad calls within a signal handler. */ +/* { dg-require-effective-target signal } */ #include <stdlib.h> #include <signal.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-6.c b/gcc/testsuite/gcc.dg/analyzer/signal-6.c index f518451..ea2290c 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-6.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-6.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target signal } */ #include <stdio.h> #include <signal.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-exit.c b/gcc/testsuite/gcc.dg/analyzer/signal-exit.c index a567124..41a819b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/signal-exit.c +++ b/gcc/testsuite/gcc.dg/analyzer/signal-exit.c @@ -1,6 +1,7 @@ /* Example of a bad call within a signal handler with replacement alternative. 'handler' calls 'exit', and 'exit' is not allowed from a signal handler. But '_exit' is allowed. */ +/* { dg-require-effective-target signal } */ #include <signal.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-registration-loc.c b/gcc/testsuite/gcc.dg/analyzer/signal-registration-loc.c new file mode 100644 index 0000000..4bac126 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/signal-registration-loc.c @@ -0,0 +1,23 @@ +/* Ensure we use the correct location when reporting where the + signal handler was registered (PR analyzer/95188). */ + +/* { dg-require-effective-target signal } */ + +#include <stdio.h> +#include <signal.h> + +int g; +extern int foo (void); + +static void +handler (int n) +{ + fprintf (stderr, "got here: %i\n", g); /* { dg-warning "call to 'fprintf' from within signal handler" } */ +} + +int main (int argc, char *argv[]) +{ + g = foo (); /* { dg-bogus "registering" } */ + signal (SIGSEGV, handler); /* { dg-message "registering 'handler' as signal handler" } */ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/single-field.c b/gcc/testsuite/gcc.dg/analyzer/single-field.c new file mode 100644 index 0000000..d54cfb0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/single-field.c @@ -0,0 +1,37 @@ +#include <stdlib.h> +#include "analyzer-decls.h" + +struct foo +{ + char *ptr; +}; + +void test_1 (struct foo f) +{ + __analyzer_describe (0, f.ptr); /* { dg-warning "svalue: 'INIT_VAL\\(f.ptr\\)'" } */ +} + +static void called_by_test_2 (struct foo f_inner) +{ + free (f_inner.ptr); + free (f_inner.ptr); /* { dg-warning "double-'free' of 'f_outer.ptr'" } */ +} +void test_2 (struct foo f_outer) +{ + called_by_test_2 (f_outer); +} + +struct nested +{ + struct foo f; +}; + +static void called_by_test_3 (struct nested n_inner) +{ + free (n_inner.f.ptr); + free (n_inner.f.ptr); /* { dg-warning "double-'free' of 'n_outer.f.ptr'" } */ +} +void test_3 (struct nested n_outer) +{ + called_by_test_3 (n_outer); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c b/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c new file mode 100644 index 0000000..0422147 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c @@ -0,0 +1,15 @@ + +int *global_ptr; + +static void __attribute__((noinline)) +called_by_test_1 (void) +{ + int i = 42; + global_ptr = &i; +} + +int test_1 (void) +{ + called_by_test_1 (); + return *global_ptr; /* { dg-warning "dereferencing pointer 'global_ptr' to within stale stack frame" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/strcpy-1.c b/gcc/testsuite/gcc.dg/analyzer/strcpy-1.c new file mode 100644 index 0000000..ed5bab9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/strcpy-1.c @@ -0,0 +1,18 @@ +#include <string.h> +#include "analyzer-decls.h" + +char * +test_1 (char *dst, char *src) +{ + char *result = strcpy (dst, src); + __analyzer_eval (result == dst); /* { dg-warning "TRUE" } */ + return result; +} + +char * +test_1a (char *dst, char *src) +{ + char *result = __strcpy_chk (dst, src, -1); + __analyzer_eval (result == dst); /* { dg-warning "TRUE" } */ + return result; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/strdup-1.c b/gcc/testsuite/gcc.dg/analyzer/strdup-1.c new file mode 100644 index 0000000..6b950ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/strdup-1.c @@ -0,0 +1,21 @@ +#include <string.h> +#include <stdlib.h> + +extern void requires_nonnull (void *ptr) + __attribute__((nonnull)); + +void test_1 (const char *s) +{ + char *p = strdup (s); /* { dg-message "allocated here" } */ +} /* { dg-warning "leak of 'p'" } */ + +void test_2 (const char *s) +{ + char *p = strdup (s); + free (p); +} +void test_3 (const char *s) +{ + char *p = strdup (s); /* { dg-message "this call could return NULL" } */ + requires_nonnull (p); /* { dg-warning "use of possibly-NULL 'p'" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/strndup-1.c b/gcc/testsuite/gcc.dg/analyzer/strndup-1.c new file mode 100644 index 0000000..23d9b60 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/strndup-1.c @@ -0,0 +1,21 @@ +#include <string.h> +#include <stdlib.h> + +extern void requires_nonnull (void *ptr) + __attribute__((nonnull)); + +void test_1 (const char *s) +{ + char *p = strndup (s, 42); /* { dg-message "allocated here" } */ +} /* { dg-warning "leak of 'p'" } */ + +void test_2 (const char *s) +{ + char *p = strndup (s, 42); + free (p); +} +void test_3 (const char *s) +{ + char *p = strndup (s, 42); /* { dg-message "this call could return NULL" } */ + requires_nonnull (p); /* { dg-warning "use of possibly-NULL 'p'" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c new file mode 100644 index 0000000..9d228e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c @@ -0,0 +1,43 @@ +#include "analyzer-decls.h" + +/* The example from store2.h */ + +void test_1 (char a, char b, char c, char d, char e, char f, + int i, int j) +{ + char arr[1024]; + arr[2] = a; /* (1) */ + arr[3] = b; /* (2) */ + + __analyzer_eval (arr[2] == a); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[3] == b); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[4]); /* { dg-warning "UNKNOWN" } */ // TODO: report uninit + + /* Replace one concrete binding's value with a different value. */ + arr[3] = c; /* (3) */ + __analyzer_eval (arr[2] == a); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[3] == c); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[3] == b); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (arr[4]); /* { dg-warning "UNKNOWN" } */ // TODO: report uninit + + /* Symbolic binding. */ + arr[i] = d; /* (4) */ + __analyzer_eval (arr[i] == d); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[2] == a); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (arr[3] == c); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (arr[4]); /* { dg-warning "UNKNOWN" } */ /* Don't report uninit. */ + + /* Replace symbolic binding with a different one. */ + arr[j] = e; /* (5) */ + __analyzer_eval (arr[j] == e); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[i] == d); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (arr[4]); /* { dg-warning "UNKNOWN" } */ /* Don't report uninit. */ + + /* Add a concrete binding. */ + arr[3] = f; /* (6) */ + __analyzer_eval (arr[3] == f); /* { dg-warning "TRUE" } */ + __analyzer_eval (arr[j] == e); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (arr[4]); /* { dg-warning "UNKNOWN" } */ /* Don't report uninit. */ +} + +// TODO: as above, but with int rather than char so there's a cast diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-2.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-2.c new file mode 100644 index 0000000..70c00ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-2.c @@ -0,0 +1,32 @@ +#include "analyzer-decls.h" + +struct foo +{ + int ival; + int iarr[10]; +}; + +void test_1 (int i, int j) +{ + struct foo fooarr[4]; + fooarr[1].ival = 42; + fooarr[1].iarr[3] = 27; + fooarr[2].iarr[1] = 17; + __analyzer_eval (fooarr[1].ival == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (fooarr[1].iarr[3] == 27); /* { dg-warning "TRUE" } */ + __analyzer_eval (fooarr[2].iarr[1] == 17); /* { dg-warning "TRUE" } */ + + /* Symbolic binding. */ + fooarr[2].iarr[i] = j; + __analyzer_eval (fooarr[2].iarr[i] == j); /* { dg-warning "TRUE" } */ + + /* We should have lost our knowledge about fooarr[2]. + It's not clear to me if we should also lose our knowledge about + fooarr[1] (for the case where i is negative). For now, we do. */ + __analyzer_eval (fooarr[1].ival == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (fooarr[1].iarr[3] == 27); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (fooarr[2].iarr[1] == 17); /* { dg-warning "UNKNOWN" } */ + /* Should also be safe to read from fooarr[2]; + it isn't known to be uninit anymore. */ + __analyzer_eval (fooarr[2].iarr[10] == 17); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-3.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-3.c new file mode 100644 index 0000000..da4cdbb --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-3.c @@ -0,0 +1,12 @@ +#include "analyzer-decls.h" + +int iarr[16]; + +void test_1 (int i, int j) +{ + int init_el_8 = iarr[8]; + __analyzer_eval (init_el_8 == iarr[8]); /* { dg-warning "TRUE" } */ + + iarr[i] = j; + __analyzer_eval (init_el_8 == iarr[8]); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-4.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-4.c new file mode 100644 index 0000000..a466f91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-4.c @@ -0,0 +1,20 @@ +#include <string.h> +#include "analyzer-decls.h" + +void test_1 (int i, int j, int k) +{ + int iarr[16]; + iarr[i] = j; + __analyzer_eval (iarr[i] == j); /* { dg-warning "TRUE" } */ + __analyzer_eval (iarr[k] == j); /* { dg-warning "UNKNOWN" } */ + + memset (iarr, 0, sizeof (iarr)); + __analyzer_eval (iarr[0] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (iarr[i] == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (iarr[i] == j); /* { dg-warning "UNKNOWN" } */ + + iarr[i] = j; + __analyzer_eval (iarr[i] == j); /* { dg-warning "TRUE" } */ + __analyzer_eval (iarr[0] == 0); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (iarr[i] == 0); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-5.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-5.c new file mode 100644 index 0000000..3f69650 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-5.c @@ -0,0 +1,29 @@ +#include "analyzer-decls.h" + +int a[1024]; +int b[1024]; + +extern void escape (void *ptr); + +void test_1 (int *p) +{ + int c, d; + escape (&c); + a[16] = 42; + b[16] = 17; + c = 33; + d = 44; + __analyzer_eval (a[16] == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (b[16] == 17); /* { dg-warning "TRUE" } */ + __analyzer_eval (c == 33); /* { dg-warning "TRUE" } */ + __analyzer_eval (d == 44); /* { dg-warning "TRUE" } */ + + /* Write through an externally-provided pointer. */ + *p = 100; + /* It could clobber our writes to the global arrays... */ + __analyzer_eval (a[16] == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (b[16] == 17); /* { dg-warning "UNKNOWN" } */ + /* ...but can't clobber locals, even ones like "c" that have escaped. */ + __analyzer_eval (c == 33); /* { dg-warning "TRUE" } */ + __analyzer_eval (d == 44); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-6.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-6.c new file mode 100644 index 0000000..10d4e97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-6.c @@ -0,0 +1,24 @@ +#include "analyzer-decls.h" + +int a[1024]; +int b[1024]; + +extern void escape (void *ptr); + +void test_1 (int *p) +{ + int c, d; + escape (&c); + + *p = 42; + __analyzer_eval (*p == 42); /* { dg-warning "TRUE" } */ + + /* These writes shouldn't affect *p. */ + c = 33; + d = 44; + __analyzer_eval (*p == 42); /* { dg-warning "TRUE" } */ + + /* This write could affect *p. */ + a[16] = 55; + __analyzer_eval (*p == 42); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/taint-1.c b/gcc/testsuite/gcc.dg/analyzer/taint-1.c index 549e266..cd46dd5 100644 --- a/gcc/testsuite/gcc.dg/analyzer/taint-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/taint-1.c @@ -14,14 +14,14 @@ char test_1(FILE *f) { struct foo tmp; - if (1 == fread(&tmp, sizeof(tmp), 1, f)) { /* { dg-message "\\(1\\) 'tmp' gets an unchecked value here" "event 1" } */ - /* { dg-message "\\(2\\) following 'true' branch\\.\\.\\." "event 2" { target *-*-* } .-1 } */ + if (1 == fread(&tmp, sizeof(tmp), 1, f)) { /* { dg-message "\\(\[0-9\]+\\) 'tmp' gets an unchecked value here" "event: tmp gets unchecked value" { xfail *-*-* } } */ + /* { dg-message "\\(\[0-9\]+\\) following 'true' branch\\.\\.\\." "event: following true branch" { target *-*-* } .-1 } */ /* BUG: the following array lookup trusts that the input data's index is in the range 0 <= i < 256; otherwise it's accessing the stack */ return tmp.buf[tmp.i]; // { dg-warning "use of tainted value 'tmp.i' in array lookup without bounds checking" "warning" } */ - /* { dg-message "23: \\(3\\) \\.\\.\\.to here" "event 3" { target *-*-* } .-1 } */ - /* { dg-message "23: \\(4\\) 'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "event 4" { target *-*-* } .-2 } */ - /* { dg-message "\\(5\\) use of tainted value 'tmp.i' in array lookup without bounds checking" "event 5" { target *-*-* } .-3 } */ + /* { dg-message "23: \\(\[0-9\]+\\) \\.\\.\\.to here" "event: to here" { target *-*-* } .-1 } */ + /* { dg-message "23: \\(\[0-9\]+\\) 'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "event: tmp.i has an unchecked value" { xfail *-*-* } .-2 } */ + /* { dg-message "\\(\[0-9\]+\\) use of tainted value 'tmp.i' in array lookup without bounds checking" "final event" { target *-*-* } .-3 } */ // TOOD: better messages for state changes } @@ -52,9 +52,9 @@ char test_4(FILE *f) struct foo tmp; if (1 == fread(&tmp, sizeof(tmp), 1, f)) { - if (tmp.i >= 0) { /* { dg-message "'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "warning" } */ - /* { dg-message "'tmp.i' has its lower bound checked here" "event" { target *-*-* } .-1 } */ - return tmp.buf[tmp.i]; /* { dg-warning "use of tainted value 'tmp.i' in array lookup without upper-bounds checking" } */ + if (tmp.i >= 0) { /* { dg-message "'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "event: tmp.i has an unchecked value" { xfail *-*-* } } */ + /* { dg-message "'tmp.i' has its lower bound checked here" "event: lower bound checked" { target *-*-* } .-1 } */ + return tmp.buf[tmp.i]; /* { dg-warning "use of tainted value 'tmp.i' in array lookup without upper-bounds checking" "warning" } */ } } return 0; @@ -65,9 +65,9 @@ char test_5(FILE *f) struct foo tmp; if (1 == fread(&tmp, sizeof(tmp), 1, f)) { - if (tmp.i < 256) { /* { dg-message "'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "warning" } */ - /* { dg-message "'tmp.i' has its upper bound checked here" "event" { target *-*-* } .-1 } */ - return tmp.buf[tmp.i]; /* { dg-warning "use of tainted value 'tmp.i' in array lookup without lower-bounds checking" } */ + if (tmp.i < 256) { /* { dg-message "'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "event: tmp.i has an unchecked value" { xfail *-*-* } } */ + /* { dg-message "'tmp.i' has its upper bound checked here" "event: upper bound checked" { target *-*-* } .-1 } */ + return tmp.buf[tmp.i]; /* { dg-warning "use of tainted value 'tmp.i' in array lookup without lower-bounds checking" "warning" } */ } } return 0; diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-1.c b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-1.c new file mode 100644 index 0000000..afb2718 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-1.c @@ -0,0 +1,15 @@ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */ + +#include "../analyzer-decls.h" + +void test (int *p) +{ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + while (*p) + { + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enode" } */ + p++; + } + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c new file mode 100644 index 0000000..d5b10ab --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-2.c @@ -0,0 +1,17 @@ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */ + +#include "../analyzer-decls.h" + +void test (int *p, int val, int count) +{ + int n = count; + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + while (n--) + { + __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */ + *p++ = val; + } + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c new file mode 100644 index 0000000..c3a1e11 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/loop-inc-ptr-3.c @@ -0,0 +1,18 @@ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */ + +#include "../analyzer-decls.h" + +void test (int *p, int a, int b, int count) +{ + int n = count; + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ + + while (n--) + { + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2|3 processed enodes" } */ + *p++ = a; + *p++ = b; + } + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c new file mode 100644 index 0000000..1c4bdd6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c @@ -0,0 +1,238 @@ +/* Tests for data model handling of unknown fns. */ + +#include <stddef.h> +#include "analyzer-decls.h" + +void unknown_fn (void *); + +void test_1 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + unknown_fn (NULL); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + unknown_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Even though we're not passing &i to unknown_fn, it escaped + above, so unknown_fn could write to it. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} + +/* As test_1, but with an unknown fn_ptr. */ + +void test_1a (void (*fn_ptr) (void *)) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + fn_ptr (NULL); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + fn_ptr (&i); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Even though we're not passing &i to unknown_fn, it escaped + above, so fn_ptr (NULL) could write to it. */ + fn_ptr (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} + +int *global_for_test_2; + +void test_2 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + global_for_test_2 = &i; + unknown_fn (NULL); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + global_for_test_2 = NULL; + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Even though the global no longer points to i, it escaped + above, so unknown_fn could write to it. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} + +struct used_by_test_3 +{ + int *int_ptr; +}; + +void test_3 (void) +{ + int i; + + struct used_by_test_3 s; + s.int_ptr = &i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + unknown_fn (NULL); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (s.int_ptr == &i); /* { dg-warning "TRUE" } */ + + /* i should escape here. */ + unknown_fn (&s); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (s.int_ptr == &i); /* { dg-warning "UNKNOWN" } */ + + s.int_ptr = NULL; + __analyzer_eval (s.int_ptr == NULL); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Even though nothing we know about points to i, it escaped + above, so unknown_fn could write to it. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} + +struct used_by_test_4 +{ + int *int_ptr; +}; + +void test_4 (struct used_by_test_4 *st4_ptr) +{ + /* Something unknown called "test_4", and hence *st4_ptr has + effectively already escaped. */ + + int i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + unknown_fn (NULL); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + /* Given that *st4_ptr has effectively already escaped, calling + an unknown fn should invalidate our knowledge of i". */ + st4_ptr->int_ptr = &i; + unknown_fn (NULL); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + /* ...and "&i" should now be treated as having escaped. */ + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + st4_ptr->int_ptr = NULL; + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} + +static void __attribute__((noinline)) +known_fn (void *ptr) +{ + /* Empty. */ +} + +void test_5 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + known_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Ensure that we don't consider &i to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ +} + +extern int __attribute__ ((__pure__)) +unknown_pure_fn (void *); + +void test_6 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + unknown_pure_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Ensure that we don't consider &i to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ +} + +extern void unknown_const_fn (const void *); + +void test_7 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + /* &i is passed as a const void *, so i shouldn't be clobbered by + the call. */ + unknown_const_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Ensure that we don't consider &i to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ +} + +struct used_by_test_8 +{ + int *int_ptr; +}; + +void test_8 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + struct used_by_test_8 st8; + st8.int_ptr = &i; + + /* Although unknown_const_fn takes a const void *, the + int_ptr is a non-const int *, and so &i should be considered + writable. */ + unknown_const_fn (&st8); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* &i should be considered to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/unknown-fns-3.c b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-3.c new file mode 100644 index 0000000..095df5e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-3.c @@ -0,0 +1,67 @@ +/* Tests for handling constraints on results of unknown fns. */ + +#include <stddef.h> +#include "analyzer-decls.h" + +void unknown_fn (void *); + +void test_1 (void) +{ + int i; + unknown_fn (&i); + if (i) + __analyzer_eval (i); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (i); /* { dg-warning "FALSE" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} + +struct foo +{ + int i; + int j; +}; + +void test_2 (void) +{ + struct foo f; + unknown_fn (&f); + if (f.j) + __analyzer_eval (f.j); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (f.j); /* { dg-warning "FALSE" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} + +void test_3 (int flag) +{ + int i; + unknown_fn (&i); + if (i) + { + __analyzer_eval (i); /* { dg-warning "TRUE" } */ + if (flag) + __analyzer_eval (flag); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (flag); /* { dg-warning "FALSE" } */ + } + else + __analyzer_eval (i); /* { dg-warning "FALSE" } */ + if (flag) + __analyzer_eval (flag); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (flag); /* { dg-warning "FALSE" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} + +void test_4 (int y) +{ + int x; + unknown_fn (&x); + if (x) + { + __analyzer_eval (x); /* { dg-warning "TRUE" } */ + x = 0; + } + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/unknown-fns-4.c b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-4.c new file mode 100644 index 0000000..3d8f82e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-4.c @@ -0,0 +1,15 @@ +#include "analyzer-decls.h" + +int get(void); +void test (void) +{ + int got = 0; + while (1) + { + if (get ()) + got = 1; + else + if (got) + __analyzer_dump_path (); /* { dg-message "path" "" { xfail *-*-* } } */ + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/unknown-fns.c b/gcc/testsuite/gcc.dg/analyzer/unknown-fns.c index 355c8b3..fd1ecbb 100644 --- a/gcc/testsuite/gcc.dg/analyzer/unknown-fns.c +++ b/gcc/testsuite/gcc.dg/analyzer/unknown-fns.c @@ -76,10 +76,10 @@ void test_4a (void) node_b.ptr = malloc (sizeof (int)); global_ptr = &node_a; *node_b.ptr = 42; /* { dg-warning "possibly-NULL" "possibly-NULL" } */ - /* { dg-warning "leak" "leak" { target *-*-* } .-1 } */ - /* FIXME: the above leak report is correct, but is reported at the wrong - location. */ -} /* { dg-warning "leak" } */ + /* Although there's a chain of pointers to the allocation, pointed to + by global_ptr, the chain goes through the stack frame and thus + there's a leak when it is popped. */ +} /* { dg-warning "leak of 'node_b.ptr'" } */ /* With a call to an unknown function. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/use-after-free.c b/gcc/testsuite/gcc.dg/analyzer/use-after-free.c new file mode 100644 index 0000000..d7e4bc2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/use-after-free.c @@ -0,0 +1,12 @@ +#include <stdlib.h> +#include "analyzer-decls.h" + +struct link { struct link *next; }; + +int free_a_list_badly (struct link *n) +{ + while (n) { + free(n); /* { dg-message "freed here" } */ + n = n->next; /* { dg-warning "use after 'free' of 'n'" } */ + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/vla-1.c b/gcc/testsuite/gcc.dg/analyzer/vla-1.c new file mode 100644 index 0000000..e5971c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/vla-1.c @@ -0,0 +1,14 @@ +/* { dg-require-effective-target alloca } */ +#include "analyzer-decls.h" + +void test_1 (int n) +{ + struct + { + char a[n], b; + } s; + s.a[0] = 42; + __analyzer_eval (s.a[0] == 42); /* { dg-warning "TRUE" } */ + s.b = 17; + __analyzer_eval (s.b == 17); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/write-to-const-1.c b/gcc/testsuite/gcc.dg/analyzer/write-to-const-1.c new file mode 100644 index 0000000..dc724e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/write-to-const-1.c @@ -0,0 +1,29 @@ +/* PR middle-end/90404 */ + +const int c1 = 20; /* { dg-message "declared here" } */ +int test_1 (void) +{ + *((int*) &c1) = 10; /* { dg-warning "write to 'const' object 'c1'" } */ + return c1; +} + +/* Example of writing to a subregion (an element within a const array). */ + +const int c2[10]; /* { dg-message "declared here" } */ +int test_2 (void) +{ + ((int*) &c2)[5] = 10; /* { dg-warning "write to 'const' object 'c2'" } */ + return c2[5]; +} + +const char s3[] = "012.45"; /* { dg-message "declared here" } */ +int test_3 (void) +{ + char *p = __builtin_strchr (s3, '.'); + *p = 0; /* { dg-warning "write to 'const' object 's3'" } */ + + if (__builtin_strlen (p) != 3) + __builtin_abort (); + + return s3[3] == 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/write-to-string-literal-1.c b/gcc/testsuite/gcc.dg/analyzer/write-to-string-literal-1.c new file mode 100644 index 0000000..092500e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/write-to-string-literal-1.c @@ -0,0 +1,58 @@ +#include <string.h> + +/* PR analyzer/95007. */ + +void test_1 (void) +{ + char *s = "foo"; + s[0] = 'g'; /* { dg-warning "write to string literal" } */ +} + +/* PR c/83347. */ + +void test_2 (void) +{ + memcpy ("abc", "def", 3); /* { dg-warning "write to string literal" } */ +} + +static char * __attribute__((noinline)) +called_by_test_3 (void) +{ + return (char *)"foo"; +} + +void test_3 (void) +{ + char *s = called_by_test_3 (); + s[1] = 'a'; /* { dg-warning "write to string literal" } */ +} + +static char * __attribute__((noinline)) +called_by_test_4 (int flag) +{ + if (flag) + return (char *)"foo"; + else + return (char *)"bar"; +} + +void test_4 (void) +{ + char *s = called_by_test_4 (0); + s[1] = 'z'; /* { dg-warning "write to string literal" } */ +} + +static char * __attribute__((noinline)) +called_by_test_5 (int flag) +{ + if (flag) + return (char *)"foo"; + else + return (char *)"bar"; +} + +void test_5 (int flag) +{ + char *s = called_by_test_5 (flag); + s[1] = 'z'; /* We miss this one, unless we disable state merging. */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/zlib-4.c b/gcc/testsuite/gcc.dg/analyzer/zlib-4.c index 0826144..ae2f6c9 100644 --- a/gcc/testsuite/gcc.dg/analyzer/zlib-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/zlib-4.c @@ -7,14 +7,18 @@ typedef unsigned long uLong; #define Z_NULL 0 -void test () +int test () { uLong comprLen = 10000*sizeof(int); uLong uncomprLen = comprLen; Byte *compr = (Byte*)calloc((uInt)comprLen, 1); Byte *uncompr = (Byte*)calloc((uInt)uncomprLen, 1); if (compr == Z_NULL || uncompr == Z_NULL) - exit (1); + { + return 1; /* { dg-warning "leak of 'uncompr'" "uncompr leak" } */ + /* { dg-warning "leak of 'compr'" "compr leak" { target *-*-* } .-1 } */ + } strcpy((char*)uncompr, "garbage"); - exit (0); + return 0; /* { dg-warning "leak of 'uncompr'" "uncompr leak" } */ + /* { dg-warning "leak of 'compr'" "compr leak" { target *-*-* } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/asan/pr97294.c b/gcc/testsuite/gcc.dg/asan/pr97294.c new file mode 100644 index 0000000..6de6c3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/pr97294.c @@ -0,0 +1,41 @@ +/* PR sanitizer/97294 */ +/* { dg-do compile { target fopenmp } } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ +/* { dg-options "-O0 -fsanitize=address -fopenmp" } */ +/* { dg-final { scan-assembler "foo._omp_fn.\[0-9]\[1-9]*:.*call\[ \t]\*__*asan_allocas_unpoison.*\.size\[ \t]\*foo._omp_fn.\[0-9]\[1-9]*," { target x86_64-*-linux* i?86-*-linux* } } } */ + +__attribute__((noipa)) void +foo (int *p, int n) +{ + int i; + #pragma omp parallel for num_threads(2) reduction(+:p[:n]) + for (i = 0; i < 10; i++) + { + p[0]++; + p[n - 1] += 2; + } +} + +__attribute__((noipa)) void +bar (void) +{ + unsigned char buf[1024]; + int i; + asm volatile ("" : : "r" (&buf[0]) : "memory"); + for (i = 0; i < 1024; i++) + buf[i] = i; + asm volatile ("" : : "r" (&buf[0]) : "memory"); +} + +int +main () +{ + int p[50], i; + for (i = 0; i < 50; i++) + p[i] = 0; + foo (p, 50); + bar (); + if (p[0] != 10 || p[49] != 20) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-vm.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-vm.c index f43fa49..cdfb701 100644 --- a/gcc/testsuite/gcc.dg/atomic/stdatomic-vm.c +++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-vm.c @@ -2,6 +2,7 @@ with side effects. */ /* { dg-do run } */ /* { dg-options "-std=c11 -pedantic-errors" } */ +/* { dg-require-effective-target alloca } */ #include <stdatomic.h> diff --git a/gcc/testsuite/gcc.dg/attr-access-2.c b/gcc/testsuite/gcc.dg/attr-access-2.c new file mode 100644 index 0000000..76baddf --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-access-2.c @@ -0,0 +1,122 @@ +/* PR 50584 - No warning for passing small array to C99 static array declarator + Exercise interaction between explicit attribute access and VLA parameters. + { dg-do compile } + { dg-options "-Wall" } */ + +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) + + +void f1 (int n, int[n], int); // { dg-message "designating the bound of variable length array argument 2" "note" } + +// Verify that a redundant attribute access doesn't trigger a warning. +RW (2, 1) void f1 (int n, int[n], int); + +RW (2, 3) void f1 (int n, int[n], int); // { dg-warning "attribute 'access\\\(read_write, 2, 3\\\)' positional argument 2 conflicts with previous designation by argument 1" } + + +/* Verify that applying the attribute to a VLA with an unspecified bound + doesn't trigger any warnings, both with and without a size operand. */ + void f2 (int, int[*], int); +RW (2) void f2 (int, int[*], int); +RW (2, 3) void f2 (int, int[*], int); + +/* Designating a parameter that comes before the VLA is the same as + using the standard VLA int[n] syntax. It might be worth issuing + a portability warning suggesting to prefer the standard syntax. */ + void f3 (int, int[*], int); +RW (2, 1) void f3 (int, int[*], int); + +/* Designating a parameter that comes after the VLA cannot be expressed + using the standard VLA int[n] syntax. Verify it doesn't trigger + a warning. */ + void f4 (int, int[*], int); +RW (2, 3) void f4 (int, int[*], int); + +/* Also verify the same on the same declaration. */ + void f5 (int[*], int) RW (1, 2); +RW (1, 2) void f5 (int[*], int); +RW (1, 2) void f5 (int[*], int) RW (1, 2); + + +/* Verify that designating a VLA parameter with an explicit bound without + also designating the same bound parameter triggers a warning (it has + a different meaning). */ + void f7 (int n, int[n]); // { dg-message "21:note: designating the bound of variable length array argument 2" "note" } +RW (2) void f7 (int n, int[n]); // { dg-warning "attribute 'access\\\(read_write, 2\\\)' missing positional argument 2 provided in previous designation by argument 1" } + + void f8 (int n, int[n]); +RW (2, 1) void f8 (int n, int[n]); + + + void f9 (int, char[]); // { dg-message "25:note: previously declared as an ordinary array 'char\\\[]'" note" } +RW (2) void f9 (int n, char a[n]) // { dg-warning "argument 2 of type 'char\\\[n]' declared as a variable length array" } + // { dg-warning "attribute 'access *\\\(read_write, 2\\\)' positional argument 2 missing in previous designation" "" { target *-*-* } .-1 } + // { dg-message "24:note: designating the bound of variable length array argument 2" "note" { target *-*-* } .-2 } +{ (void)&n; (void)&a; } + + + void f10 (int, char[]); // { dg-message "26:note: previously declared as an ordinary array 'char\\\[]'" "note" } +RW (2, 1) void f10 (int n, char a[n]) // { dg-warning "attribute 'access *\\\(read_write, 2, 1\\\)' positional argument 2 missing in previous designation" "pr????" { xfail *-*-* } } + // { dg-warning "argument 2 of type 'char\\\[n]' declared as a variable length array" "" { target *-*-* } .-1 } +{ (void)&n; (void)&a; } + + +/* The following is diagnosed to point out declarations with the T[*] + form in headers where specifying the bound is just as important as + in the definition (to detect bugs). */ + void f11 (int, char[*]); // { dg-warning "argument 2 of type 'char\\\[\\\*\\\]' declared with 1 unspecified variable bound" } + void f11 (int m, char a[m]); // { dg-message "subsequently declared as 'char\\\[m]' with 0 unspecified variable bounds" "note" } +RW (2, 1) void f11 (int n, char arr[n]) // { dg-message "subsequently declared as 'char\\\[n]' with 0 unspecified variable bounds" "note" } +{ (void)&n; (void)&arr; } + + +/* Verify that redeclaring a function with attribute access applying + to an array parameter of any form is not diagnosed. */ + void f12__ (int, int[]) RW (2, 1); +RW (2, 1) void f12__ (int, int[]); + + void f12_3 (int, int[3]) RW (2, 1); +RW (2, 1) void f12_3 (int, int[3]); + + void f12_n (int n, int[n]) RW (2, 1); +RW (2, 1) void f12_n (int n, int[n]); + + void f12_x (int, int[*]) RW (2, 1); +RW (2, 1) void f12_x (int, int[*]); + + void f13__ (int, int[]); +RW (2, 1) void f13__ (int, int[]); + + void f13_5 (int, int[5]); +RW (2, 1) void f13_5 (int, int[5]); + + void f13_n (int n, int[n]); +RW (2, 1) void f13_n (int n, int[n]); + + void f13_x (int, int[*]); +RW (2, 1) void f13_x (int, int[*]); + +RW (2, 1) void f14__ (int, int[]); + void f14__ (int, int[]); + +RW (2, 1) void f14_7 (int, int[7]); + void f14_7 (int, int[7]); + +RW (2, 1) void f14_n (int n, int[n]); + void f14_n (int n, int[n]); + +RW (2, 1) void f14_x (int, int[*]); + void f14_x (int, int[*]); + +typedef void G1 (int n, int[n], int); + +G1 g1; + +/* The warning is about the attribute positional argument 2 which refers + to the last function argument. Ideally, the caret would be under + the corresponding function argument, i.e., the last one here) but + that location isn't available yet. Verify that the caret doesn't + point to function argument 1 which is the VLA bound (that's what + the caret in the note points to). */ +RW (2, 3) void g1 (int n, int[n], int); // { dg-warning "16: attribute 'access *\\\(read_write, 2, 3\\\)' positional argument 2 conflicts with previous designation by argument 3" } +// { dg-message "24:designating the bound of variable length array argument 2" "note" { target *-*-* } .-1 } diff --git a/gcc/testsuite/gcc.dg/attr-access-none.c b/gcc/testsuite/gcc.dg/attr-access-none.c index d983f2f..dc06d05 100644 --- a/gcc/testsuite/gcc.dg/attr-access-none.c +++ b/gcc/testsuite/gcc.dg/attr-access-none.c @@ -23,7 +23,7 @@ void nowarn_fnone_pcv1 (void) int __attribute__ ((access (none, 1, 2))) -fnone_pcv1_2 (const void*, int); // { dg-message "in a call to function 'fnone_pcv1_2' declared with attribute 'none \\\(1, 2\\\)'" } +fnone_pcv1_2 (const void*, int); // { dg-message "in a call to function 'fnone_pcv1_2' declared with attribute 'access \\\(none, 1, 2\\\)'" "note" } void nowarn_fnone_pcv1_2 (void) { diff --git a/gcc/testsuite/gcc.dg/attr-access-read-write-2.c b/gcc/testsuite/gcc.dg/attr-access-read-write-2.c index c2ac6c3..deeee73 100644 --- a/gcc/testsuite/gcc.dg/attr-access-read-write-2.c +++ b/gcc/testsuite/gcc.dg/attr-access-read-write-2.c @@ -22,12 +22,12 @@ int RW (1) grdwr1_wr1 (void*, void*); // { dg-message "previous declar int WO (1) grdwr1_wr1 (void*, void*); // { dg-warning "attribute 'access\\(write_only, 1\\)' mismatch with mode 'read_write'" } -int RW (1) RW (1, 2) frdwr1_rdwr1_1 (void*, int); // { dg-warning "attribute 'access\\(read_write, 1, 2\\)' positional argument 2 conflicts with previous designation" } +int RW (1) RW (1, 2) frdwr1_rdwr1_1 (void*, int); // { dg-warning "attribute 'access\\(read_write, 1, 2\\)' positional argument 2 missing in previous designation" } int RW (1, 2) RW (1) frdwr1_1_rdwr1 (void*, int); // { dg-warning "attribute 'access\\(read_write, 1\\)' missing positional argument 2 provided in previous designation" } int RW (1) grdwr1_rdwr1_1 (void*, int); // { dg-message "previous declaration here" } -int RW (1, 2) grdwr1_rdwr1_1 (void*, int); // { dg-warning "attribute 'access\\(read_write, 1, 2\\)' positional argument 2 conflicts with previous designation" } +int RW (1, 2) grdwr1_rdwr1_1 (void*, int); // { dg-warning "attribute 'access\\(read_write, 1, 2\\)' positional argument 2 missing in previous designation" } typedef int *P; diff --git a/gcc/testsuite/gcc.dg/attr-alloc_align-5.c b/gcc/testsuite/gcc.dg/attr-alloc_align-5.c new file mode 100644 index 0000000..d6f2bc1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-alloc_align-5.c @@ -0,0 +1,23 @@ +/* PR c/78666 - conflicting attribute alloc_size accepted + { dg-do compile } + { dg-options "-Wall" } */ + +#define A(pos) __attribute__ ((alloc_align (pos))) + +A (1) char* f2_1 (int, int); +A (1) char* f2_1 (int, int); // { dg-message "previous declaration here" } + +A (2) char* f2_1 (int, int); // { dg-warning "ignoring attribute 'alloc_align \\\(2\\\)' because it conflicts with previous 'alloc_align \\\(1\\\)'" } + + +A (2) char* f2_2 (int, int); +A (2) char* f2_2 (int, int); // { dg-message "previous declaration here" } + +A (1) char* f2_2 (int, int); // { dg-warning "ignoring attribute 'alloc_align \\\(1\\\)' because it conflicts with previous 'alloc_align \\\(2\\\)'" } + + +A (1) char* f3_1 (int, int, int); +A (1) char* f3_1 (int, int, int); // { dg-message "previous declaration here" } + +A (2) char* f3_1 (int, int, int); // { dg-warning "ignoring attribute 'alloc_align \\\(2\\\)' because it conflicts with previous 'alloc_align \\\(1\\\)'" } +A (3) char* f3_1 (int, int, int); // { dg-warning "ignoring attribute 'alloc_align \\\(3\\\)' because it conflicts with previous 'alloc_align \\\(1\\\)'" } diff --git a/gcc/testsuite/gcc.dg/attr-alloc_size-13.c b/gcc/testsuite/gcc.dg/attr-alloc_size-13.c new file mode 100644 index 0000000..df44f47 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-alloc_size-13.c @@ -0,0 +1,34 @@ +/* PR c/78666 - conflicting attribute alloc_size accepted + { dg-do compile } + { dg-options "-Wall" } */ + +#define A(...) __attribute__ ((alloc_size (__VA_ARGS__))) + +A (1) char* f2_1 (int, int); +A (1) A (1) char* f2_1 (int, int); + +A (1) char* f2_1 (int, int); // { dg-message "previous declaration here" } + +A (2) char* f2_1 (int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(2\\\)' because it conflicts with previous 'alloc_size \\\(1\\\)'" } + + +A (2) char* f2_2 (int, int); +A (2) char* f2_2 (int, int); // { dg-message "previous declaration here" } + +A (1) char* f2_2 (int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(1\\\)' because it conflicts with previous 'alloc_size \\\(2\\\)'" } + + +A (1) char* f3_1 (int, int, int); +A (1) char* f3_1 (int, int, int); // { dg-message "previous declaration here" } + +A (2) char* f3_1 (int, int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(2\\\)' because it conflicts with previous 'alloc_size \\\(1\\\)'" } +A (3) char* f3_1 (int, int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(3\\\)' because it conflicts with previous 'alloc_size \\\(1\\\)'" } +A (1, 2) char* f3_1 (int, int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(1, 2\\\)' because it conflicts with previous 'alloc_size \\\(1\\\)'" } +A (1, 3) char* f3_1 (int, int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(1, 3\\\)' because it conflicts with previous 'alloc_size \\\(1\\\)'" } + + +typedef A (2, 3) char* F3_2_3 (int, int, int); +typedef A (2, 3) char* F3_2_3 (int, int, int); +typedef A (2, 3) A (2, 3) char* F3_2_3 (int, int, int); + +typedef A (1) char* F3_2_3 (int, int, int); // { dg-warning "ignoring attribute 'alloc_size \\\(1\\\)' because it conflicts with previous 'alloc_size \\\(2, 3\\\)'" } diff --git a/gcc/testsuite/gcc.dg/attr-copy-4.c b/gcc/testsuite/gcc.dg/attr-copy-4.c index 1350a35..01fae3f 100644 --- a/gcc/testsuite/gcc.dg/attr-copy-4.c +++ b/gcc/testsuite/gcc.dg/attr-copy-4.c @@ -21,7 +21,8 @@ Assert (__alignof (struct PackedA) == __alignof (struct PackedB)); struct PackedMember { char c; - ATTR ((copy ((struct PackedB*)0))) double packed_mem; + ATTR ((copy ((struct PackedB*)0))) double packed_mem; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ }; Assert (__alignof (struct PackedMember) == 1); @@ -31,6 +32,7 @@ extern const struct PackedA packed; struct Unpacked { int i; char c; }; Assert (__alignof (struct Unpacked) > 1); +/* { dg-error "size of array .* is negative" "" { target default_packed } .-1 } */ /* Verify that copying the packed attribute to the declaration of an object is ignored with a warning. (There should be diff --git a/gcc/testsuite/gcc.dg/attr-copy-6.c b/gcc/testsuite/gcc.dg/attr-copy-6.c index d1a2865..cf578bd 100644 --- a/gcc/testsuite/gcc.dg/attr-copy-6.c +++ b/gcc/testsuite/gcc.dg/attr-copy-6.c @@ -2,6 +2,7 @@ { dg-do compile } { dg-skip-if "Attributes not supported" { { hppa*-*-hpux* } && { ! lp64 } } } { dg-options "-O2 -Wall" } + { dg-require-visibility "hidden" } { dg-require-alias "" } { dg-require-weak "" } */ diff --git a/gcc/testsuite/gcc.dg/attr-copy-8.c b/gcc/testsuite/gcc.dg/attr-copy-8.c index c75d9e5..7195f6b 100644 --- a/gcc/testsuite/gcc.dg/attr-copy-8.c +++ b/gcc/testsuite/gcc.dg/attr-copy-8.c @@ -21,41 +21,66 @@ extern B *pb; typedef struct C { ATTR (copy ((struct A *)0)) short m_pa_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy ((struct A *)(1, 0))) int m_pa_1_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy ((struct A *)(0, 1))) long m_pa_0_1; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*(struct A *)0)) short m_xpa_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*(struct A *)(1, 0))) int m_xpa_1_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*(struct A *)(0, 1))) long m_xpa_0_1; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (((struct A *)0)[0])) short m_arpa_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (((struct A *)(1, 0))[0])) int m_arpa_1_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (((struct A *)(0, 1))[0])) long m_arpa_0_1; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ /* Also exercise COMPONENT_REF, ARRAY_REF, and INDIRECT_REF. */ ATTR (copy (a)) short m_ra; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (b.a)) int m_rb_a; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (b.pa)) long m_rb_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (&a)) short m_ara; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (&b.a)) int m_arb_a; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*b.pa)) long m_xb_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (b.pa[0])) long m_arb_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*pa)) short m_xpa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (pa[0])) short m_arpa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (ab[0].a)) int m_arab_a; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (ab[1].pa)) long m_arab_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*ab[2].pa)) int m_xarab_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (ab[3].pa->bf)) unsigned int m_arab_pa_bf: 1; ATTR (copy (pb->a)) int m_pb_a; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (pb->pa)) long m_pb_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (*pb->pa)) int m_xpb_pa; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ ATTR (copy (pb->pa->bf)) unsigned int m_pb_pa_bf: 1; ATTR (aligned (4), copy ((struct A *)(0))) short m_a4_pa_0; + /* { dg-warning "attribute ignored" "" { target default_packed } .-1 } */ } C; diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-2.c b/gcc/testsuite/gcc.dg/attr-nonstring-2.c index ef2144d..ba4757d 100644 --- a/gcc/testsuite/gcc.dg/attr-nonstring-2.c +++ b/gcc/testsuite/gcc.dg/attr-nonstring-2.c @@ -26,8 +26,8 @@ void test_strnlen_array_cst (void) T (strnlen (ns3, 1)); T (strnlen (ns3, 2)); T (strnlen (ns3, 3)); - T (strnlen (ns3, 4)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 4" } */ - T (strnlen (ns3, DIFF_MAX)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \[0-9\]+" } */ + T (strnlen (ns3, 4)); /* { dg-warning "specified bound 4 exceeds source size 3" } */ + T (strnlen (ns3, DIFF_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds source size" } */ T (strnlen (ns3, SIZE_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ NONSTRING char ns5[5]; @@ -37,8 +37,8 @@ void test_strnlen_array_cst (void) T (strnlen (ns5, 1)); T (strnlen (ns5, 2)); T (strnlen (ns5, 3)); - T (strnlen (ns5, 6)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 6" } */ - T (strnlen (ns5, DIFF_MAX)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \[0-9\]+" } */ + T (strnlen (ns5, 6)); /* { dg-warning "specified bound 6 exceeds source size 5" } */ + T (strnlen (ns5, DIFF_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds source size 5" } */ T (strnlen (ns5, SIZE_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ } @@ -52,8 +52,8 @@ void test_strnlen_array_range (void) T (strnlen (ns3, UR (0, 9))); T (strnlen (ns3, UR (3, 4))); T (strnlen (ns3, UR (3, DIFF_MAX))); - T (strnlen (ns3, UR (4, 5))); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \\\[4, 5]" } */ - T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX))); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller " } */ + T (strnlen (ns3, UR (4, 5))); /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */ + T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX))); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 3 " } */ } @@ -73,8 +73,8 @@ void test_strnlen_string_cst (void) T (3, "12", 3, 1); T (3, "12", 3, 9); T (3, "123", 3, 1); - T (3, "123", 3, 4); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 4" } */ - T (3, "123", 3, 9); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 9" } */ + T (3, "123", 3, 4); /* { dg-warning "specified bound 4 exceeds source size 3" } */ + T (3, "123", 3, 9); /* { dg-warning "specified bound 9 exceeds source size 3" } */ T (5, "1", 2, 1); T (5, "1", 2, 2); @@ -84,7 +84,7 @@ void test_strnlen_string_cst (void) T (5, "12", 3, 9); T (5, "123", 3, 1); T (5, "123", 3, 5); - T (5, "123", 3, 6); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 6" } */ + T (5, "123", 3, 6); /* { dg-warning "specified bound 6 exceeds source size 5" } */ /* Strnlen shouldn't trigger a warning for arrays of unknown size (except for accesses to uninitialized elements when those are @@ -110,6 +110,6 @@ void test_strnlen_string_range (void) { T (3, "1", 2, UR (0, 1)); T (3, "1", 2, UR (3, 9)); - T (3, "123", 3, UR (4, 5)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \\\[4, 5]" } */ - T (3, "123", 3, UR (5, 9)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \\\[5, 9]" } */ + T (3, "123", 3, UR (4, 5)); /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */ + T (3, "123", 3, UR (5, 9)); /* { dg-warning "specified bound \\\[5, 9] exceeds source size 3" } */ } diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-3.c b/gcc/testsuite/gcc.dg/attr-nonstring-3.c index 4a10450..34f31fb 100644 --- a/gcc/testsuite/gcc.dg/attr-nonstring-3.c +++ b/gcc/testsuite/gcc.dg/attr-nonstring-3.c @@ -37,15 +37,21 @@ void strncmp_cst (void) T (STR, /* [] */, STR, /* [] */, n); T (STR, /* [] */, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ + T (STR, 1, STR, /* [] */, 1); T (STR, 1, STR, /* [] */, n); T (STR, 2, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ + T (STR, /* [] */, STR, 3, 3); T (STR, /* [] */, STR, 3, n); T (STR, /* [] */, STR, 4, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ + T (STR, /* [] */, NS, /* [] */, 3); T (STR, /* [] */, NS, /* [] */, n); T (STR, /* [] */, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ + T (STR, 5, NS, /* [] */, 4); + T (STR, 5, NS, /* [] */, 5); + T (STR, 5, NS, /* [] */, 6); T (STR, 5, NS, /* [] */, n); T (STR, 6, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ @@ -56,19 +62,22 @@ void strncmp_cst (void) T (NS, /* [] */, STR, /* [] */, n); T (NS, /* [] */, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ - T (NS, 9, STR, /* [] */, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */ + T (NS, 9, STR, /* [] */, n); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \[0-9\]+" } */ T (NS, 10, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ + T (NS, /* [] */, STR, 11, 11); T (NS, /* [] */, STR, 11, n); T (NS, /* [] */, STR, 12, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ T (NS, /* [] */, NS, /* [] */, n); T (NS, /* [] */, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ - T (NS, 13, NS, /* [] */, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */ + T (NS, 13, NS, /* [] */, 13); + T (NS, 13, NS, /* [] */, n); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \[0-9\]+" } */ T (NS, 14, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ - T (NS, /* [] */, NS, 15, n); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound" } */ + T (NS, /* [] */, NS, 15, 15); + T (NS, /* [] */, NS, 15, 16); /* { dg-warning "argument 2 declared attribute 'nonstring' is smaller than the specified bound 16" } */ T (NS, /* [] */, NS, 16, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ } @@ -81,6 +90,7 @@ void strncmp_range (void) T (STR, /* [] */, STR, /* [] */, n); T (STR, /* [] */, STR, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ + T (STR, 1, STR, /* [] */, 1); T (STR, 1, STR, /* [] */, n); T (STR, 2, STR, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ @@ -93,7 +103,7 @@ void strncmp_range (void) T (STR, 5, NS, /* [] */, n); T (STR, 6, NS, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ - T (STR, /* [] */, NS, 7, n); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound" } */ + T (STR, /* [] */, NS, 7, n); /* { dg-warning "argument 2 declared attribute 'nonstring' is smaller than the specified bound \\\[\[0-9\]+, \[0-9\]+]" } */ T (STR, /* [] */, NS, 8, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-4.c b/gcc/testsuite/gcc.dg/attr-nonstring-4.c index 7daff97..f2416c1 100644 --- a/gcc/testsuite/gcc.dg/attr-nonstring-4.c +++ b/gcc/testsuite/gcc.dg/attr-nonstring-4.c @@ -40,7 +40,7 @@ void strnlen_cst (void) T (NS, /* [] */, n); T (NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ - T (NS, 9, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */ + T (NS, 9, n); /* { dg-warning "specified bound \[0-9\]+ exceeds source size 9" } */ T (NS, 10, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */ } @@ -53,12 +53,12 @@ void strnlen_range (void) T (STR, /* [] */, n); T (STR, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ - T (STR, 1, n); + T (STR, 1, n); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 1" } */ T (STR, 2, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ T (NS, /* [] */, n); T (NS, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ - T (NS, 9, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */ + T (NS, 9, n); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 9" } */ T (NS, 10, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */ } diff --git a/gcc/testsuite/gcc.dg/attr-nonstring.c b/gcc/testsuite/gcc.dg/attr-nonstring.c index 46f5c0d..d93e93c 100644 --- a/gcc/testsuite/gcc.dg/attr-nonstring.c +++ b/gcc/testsuite/gcc.dg/attr-nonstring.c @@ -44,80 +44,80 @@ int strcmp_nonstring_1 (NONSTRING const char *a, const char *b) no good on its own. Use dg-regexp instead to verify that just one instance of the warning is issued. See gcc.dg/pr64223-1 for a different approach. */ - return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcmp" } */ + return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strcmp" } */ } int strcmp_nonstring_2 (const char *a, NONSTRING const char *b) { - return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcmp" } */ + return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strcmp" } */ } int strncmp_nonstring_1 (const char *s) { - return strncmp (s, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncmp" } */ + return strncmp (s, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "strncmp" } */ } int strncmp_nonstring_2 (const char *s) { - return strncmp (ns5, s, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 1 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncmp" } */ + return strncmp (ns5, s, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 1 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "strncmp" } */ } char* stpcpy_nonstring (char *d, NONSTRING const char *s) { - return stpcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .stpcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "stpcpy" } */ + return stpcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .stpcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "stpcpy" } */ } char* stpncpy_nonstring (char *d) { - return stpncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .stpncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "stpncpy" } */ + return stpncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .stpncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "stpncpy" } */ } char* strchr_nonstring (NONSTRING const char *s, int c) { - return strchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strchr" } */ + return strchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strchr" } */ } char* strrchr_nonstring (NONSTRING const char *s, int c) { - return strrchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strrchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strrchr" } */ + return strrchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strrchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strrchr" } */ } char* strcpy_nonstring (char *d, NONSTRING const char *s) { - return strcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .strcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcpy" } */ + return strcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .strcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strcpy" } */ } char* strncpy_nonstring (char *d) { - return strncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncpy" } */ + return strncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "strncpy" } */ } char* strstr_nonstring_1 (NONSTRING const char *a, const char *b) { - return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strstr" } */ + return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strstr" } */ } char* strstr_nonstring_2 (const char *a, NONSTRING const char *b) { - return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strstr" } */ + return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strstr" } */ } char* stdup_nonstring (NONSTRING const char *s) { - return strdup (s); /* { dg-regexp "\[^\n\r\]+: warning: .strdup. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strdup" } */ + return strdup (s); /* { dg-regexp "\[^\n\r\]+: warning: .strdup. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strdup" } */ } size_t strlen_nonstring (NONSTRING const char *s) { - return strlen (s); /* { dg-regexp "\[^\n\r\]+: warning: .strlen. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strlen" } */ + return strlen (s); /* { dg-regexp "\[^\n\r\]+: warning: .strlen. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strlen" } */ } int printf_nonstring (NONSTRING const char *s) { - return printf (s); /* { dg-regexp "\[^\n\r\]+: warning: .printf. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "printf" } */ + return printf (s); /* { dg-regexp "\[^\n\r\]+: warning: .printf. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "printf" } */ } int sprintf_nonstring_2 (char *d, NONSTRING const char *s) { - return sprintf (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .sprintf. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "sprintf" } */ + return sprintf (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .sprintf. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "sprintf" } */ } diff --git a/gcc/testsuite/gcc.dg/attr-section.c b/gcc/testsuite/gcc.dg/attr-section.c new file mode 100644 index 0000000..0062b54 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-section.c @@ -0,0 +1,13 @@ +/* PR c/96126 - conflicting attribute section accepted on redeclaration + { dg-do compile } + { dg-options "-Wall" } + { dg-require-named-sections "" } */ + +__attribute__ ((section ("s1"))) void f1 (void); +__attribute__ ((section ("s2"))) void f1 (void); // { dg-warning "ignoring attribute 'section \\\(\"s2\"\\\)' because it conflicts with previous 'section \\\(\"s1\"\\\)'" } + +__attribute__ ((section ("s3"), section ("s4"))) +void f2 (void); // { dg-error "conflicts" } + +__attribute__ ((section ("s5"))) __attribute ((section ("s6"))) +void f3 (void); // { dg-error "conflicts" } diff --git a/gcc/testsuite/gcc.dg/bad-binary-ops.c b/gcc/testsuite/gcc.dg/bad-binary-ops.c index 46c158e..45668be 100644 --- a/gcc/testsuite/gcc.dg/bad-binary-ops.c +++ b/gcc/testsuite/gcc.dg/bad-binary-ops.c @@ -35,10 +35,10 @@ int test_2 (void) ~~~~~~~~~~~~~~~~ | struct s - + some_other_function ()); - ^ ~~~~~~~~~~~~~~~~~~~~~~ - | - struct t + + some_other_function ()); + ^ ~~~~~~~~~~~~~~~~~~~~~~ + | + struct t { dg-end-multiline-output "" } */ } diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c index 06ef24e..9049af5 100644 --- a/gcc/testsuite/gcc.dg/builtin-apply2.c +++ b/gcc/testsuite/gcc.dg/builtin-apply2.c @@ -1,7 +1,7 @@ /* { dg-do run } */ /* { dg-require-effective-target untyped_assembly } */ /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-* nds32*-*-* amdgcn-*-*" } } */ -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "riscv*-*-* or1k*-*-* msp430-*-* pru-*-*" } } */ +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "csky*-*-* riscv*-*-* or1k*-*-* msp430-*-* pru-*-*" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } } */ /* PR target/12503 */ diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-21.c b/gcc/testsuite/gcc.dg/builtin-object-size-21.c index 1c42374..7e0f85f 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-21.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-21.c @@ -1,7 +1,8 @@ /* PR middle-end/92815 - spurious -Wstringop-overflow writing into a flexible array of an extern struct { dg-do compile } - { dg-options "-Wall -fdump-tree-optimized" } */ + { dg-options "-Wall -fdump-tree-optimized" } + { dg-require-effective-target large_initializer } */ #define PTRDIFF_MAX __PTRDIFF_MAX__ diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c index c22654d..9f159e3 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c @@ -170,6 +170,9 @@ test1 (void *q, int x) r = (char *) L"abcd\0efg"; if (__builtin_object_size (r + 2, 3) != sizeof (L"abcd\0efg") - 2) abort (); + /* Prevent DSE from removing calls that prevent bad combining of + addresses and offsets. */ + asm volatile ("" : : "g" (&a)); } size_t l1 = 1; diff --git a/gcc/testsuite/gcc.dg/builtin-stringop-chk-5.c b/gcc/testsuite/gcc.dg/builtin-stringop-chk-5.c index b07629d..7d5b03b 100644 --- a/gcc/testsuite/gcc.dg/builtin-stringop-chk-5.c +++ b/gcc/testsuite/gcc.dg/builtin-stringop-chk-5.c @@ -87,7 +87,7 @@ void test_memop_warn_local (const void *src) memset (&b->d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" } */ escape (b); - /* Same as above but clearing just elements of the second element + /* Same as above but clearing just members of the second element of the array. */ memset (&b[1].a.b, 0, offsetfrom (struct B, b[1], a.b) + 1); /* { dg-warning "writing 4 bytes into a region of size 3" } */ escape (b); diff --git a/gcc/testsuite/gcc.dg/builtin-stringop-chk-8.c b/gcc/testsuite/gcc.dg/builtin-stringop-chk-8.c index 12d2491..f2e9c48 100644 --- a/gcc/testsuite/gcc.dg/builtin-stringop-chk-8.c +++ b/gcc/testsuite/gcc.dg/builtin-stringop-chk-8.c @@ -1,6 +1,6 @@ -/* Test exercising -Wstringop-overflow warnings for reading past the end. */ +/* Test exercising -Wstringop-overread warnings for reading past the end. */ /* { dg-do compile } */ -/* { dg-options "-O2 -Wstringop-overflow=1 -ftrack-macro-expansion=0" } */ +/* { dg-options "-O2 -Wstringop-overread -ftrack-macro-expansion=0" } */ #define PTRDIFF_MAX __PTRDIFF_MAX__ #define SIZE_MAX __SIZE_MAX__ @@ -73,22 +73,22 @@ void test_memop_warn_local (void *p, const void *q) /* Verify memchr/memcmp. */ int i = R (0, 255); - memchr ("", i, 2); /* { dg-warning "reading 2 bytes from a region of size 1" } */ - memchr ("", i, 2); /* { dg-warning "reading 2 bytes from a region of size 1" } */ - memchr ("123", i, 5); /* { dg-warning "reading 5 bytes from a region of size 4" } */ - memchr (a, i, sizeof a + 1); /* { dg-warning "reading 5 bytes from a region of size 4" } */ + memchr ("", i, 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memchr" } */ + memchr ("", i, 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memchr" } */ + memchr ("123", i, 5); /* { dg-warning "specified bound 5 exceeds source size 4" "memchr" } */ + memchr (a, i, sizeof a + 1); /* { dg-warning "specified bound 5 exceeds source size 4" "memchr" } */ - memcmp (p, "", 2); /* { dg-warning "reading 2 bytes from a region of size 1" } */ - memcmp (p, "123", 5); /* { dg-warning "reading 5 bytes from a region of size 4" } */ - memcmp (p, a, sizeof a + 1); /* { dg-warning "reading 5 bytes from a region of size 4" } */ + memcmp (p, "", 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memcmp" } */ + memcmp (p, "123", 5); /* { dg-warning "specified bound 5 exceeds source size 4" "memcmp" } */ + memcmp (p, a, sizeof a + 1); /* { dg-warning "specified bound 5 exceeds source size 4" "memcmp" } */ size_t n = PTRDIFF_MAX + (size_t)1; - memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" } */ - memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" } */ + memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" "memchr" } */ + memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" "memcmp" } */ n = SIZE_MAX; - memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" } */ - memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" } */ + memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" "memchr" } */ + memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" "memcmp" } */ } /* Verify that reading beyond the end of a dynamically allocated array @@ -117,8 +117,8 @@ void test_memop_warn_alloc (void *p) /* Verify memchr/memcmp. */ n = sizeof *b * 2 + 1; - memchr (b, 1, n); /* { dg-warning "reading 9 bytes from a region of size 8" "memcmp from allocated" } */ - memcmp (p, b, n); /* { dg-warning "reading 9 bytes from a region of size 8" "memcmp from allocated" } */ + memchr (b, 1, n); /* { dg-warning "specified bound 9 exceeds source size 8" "memchr from allocated" } */ + memcmp (p, b, n); /* { dg-warning "specified bound 9 exceeds source size 8" "memcmp from allocated" } */ } diff --git a/gcc/testsuite/gcc.dg/c11-align-9.c b/gcc/testsuite/gcc.dg/c11-align-9.c index 3c9cf55..6a0d424 100644 --- a/gcc/testsuite/gcc.dg/c11-align-9.c +++ b/gcc/testsuite/gcc.dg/c11-align-9.c @@ -2,8 +2,8 @@ are at least some alignment constraints), case of compound literals. */ /* { dg-do compile } */ /* { dg-options "-std=c11 -pedantic-errors" } */ -/* { dg-skip-if "no alignment constraints" { "avr-*-*" } } */ #include <stddef.h> -max_align_t *p = &(_Alignas (_Alignof (char)) max_align_t) { 1 }; /* { dg-error "reduce alignment" } */ +max_align_t *p = &(_Alignas (_Alignof (char)) max_align_t) { 1 }; +/* { dg-error "reduce alignment" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/cdce3.c b/gcc/testsuite/gcc.dg/cdce3.c index 7e85d8a..601ddf0 100644 --- a/gcc/testsuite/gcc.dg/cdce3.c +++ b/gcc/testsuite/gcc.dg/cdce3.c @@ -1,8 +1,9 @@ /* { dg-do compile } */ /* { dg-require-effective-target hard_float } */ /* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump "cdce3.c:10: \[^\n\r]* function call is shrink-wrapped into error conditions\." "cdce" } } */ +/* { dg-final { scan-tree-dump "cdce3.c:11: \[^\n\r]* function call is shrink-wrapped into error conditions\." "cdce" } } */ /* { dg-final { scan-tree-dump "sqrtf \\(\[^\n\r]*\\); \\\[tail call\\\]" "optimized" } } */ +/* { dg-skip-if "doesn't have a sqrtf insn" { mmix-*-* } } */ float sqrtf (float); float foo (float x) diff --git a/gcc/testsuite/gcc.dg/const-uniq-1.c b/gcc/testsuite/gcc.dg/const-uniq-1.c index 0e0718b..ba7021b 100644 --- a/gcc/testsuite/gcc.dg/const-uniq-1.c +++ b/gcc/testsuite/gcc.dg/const-uniq-1.c @@ -20,4 +20,4 @@ int lookup2 (int i) return a[i+1]; } -/* { dg-final { scan-tree-dump-times "\[lL\]\\\$?C\\\.*0" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "\[lL\]\\\$?C\[.:\]*0" 2 "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/darwin-sections.c b/gcc/testsuite/gcc.dg/darwin-sections.c index 276ffa3..dbe3702 100644 --- a/gcc/testsuite/gcc.dg/darwin-sections.c +++ b/gcc/testsuite/gcc.dg/darwin-sections.c @@ -13,45 +13,41 @@ e_s ea; /* { dg-final { scan-assembler ".comm\[\t \]_ub,1" } } */ /* { dg-final { scan-assembler ".comm\[\t \]_ea,1" } } */ -/* These should go into .data */ +/* These should go into __DATA,__common */ char a = 0; short b = 0; -/* { dg-final { scan-assembler ".globl _a.*.data.*.space\[\t \]1" } } */ -/* { dg-final { scan-assembler ".globl _b.*.data.*.space\[\t \]2" } } */ - -/* These should go into __pu_bssN */ long long d = 0; float e = 0; double f = 0; long double g = 0.L; long long al_256 __attribute__((aligned (256))) = 0; -/* { dg-final { scan-assembler ".zerofill __DATA,__pu_bss3,_d,8,3" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__pu_bss2,_e,4,2" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__pu_bss3,_f,8,3" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__pu_bss4,_g,16,4" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__pu_bss8,_al_256,8,8" } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_a,1,0} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_b,2,1} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_d,8,3} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_e,4,2} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_f,8,3} } } */ +/* long double can be 64 or 128 bits depending on the Darwin subtarget. */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_g,(16,4|8,3)} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__common,_al_256,8,8} } } */ -/* This should go into __zo_bss0 */ +/* These should go into __DATA,__bss */ static e_s sea; -/* { dg-final { scan-assembler ".zerofill __DATA,__zo_bss0,_sea,1" } } */ - -/* These should go into .static_data */ static char sa ; static short sb ; -/* { dg-final { scan-assembler ".static_data.*_sa:.*.space\[\t \]1" } } */ -/* { dg-final { scan-assembler ".static_data.*_sb:.*.space\[\t \]2" } } */ - -/* These should go into _bssN */ static long long sd; static float se ; static double sf ; static long double sg; static long long sal_256 __attribute__((aligned (2048))); -/* { dg-final { scan-assembler ".zerofill __DATA,__bss3,_sd,8,3" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__bss2,_se,4,2" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__bss3,_sf,8,3" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__bss4,_sg,16,4" } } */ -/* { dg-final { scan-assembler ".zerofill __DATA,__bss11,_sal_256,8,11" } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sea,1,0} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sa,1,0} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sb,2,1} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sd,8,3} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_se,4,2} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sf,8,3} } } */ +/* long double can be 64 or 128 bits depending on the Darwin subtarget. */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sg,(16,4|8,3)} } } */ +/* { dg-final { scan-assembler {.zerofill __DATA,__bss,_sal_256,8,11} } } */ long long foo (int x) { diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-1.c index a004042..8802bd1 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-1.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-1.c @@ -1,6 +1,6 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 1 } } int __attribute__((__aligned__(64))) i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-2.c index 439a7da..0de960e 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-2.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-2.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 1 } } typedef int __attribute__((__aligned__(64))) i_t; i_t i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-3.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-3.c index 01c19cd..94db588 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-3.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-3.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 1 } } typedef int int_t; typedef int_t __attribute__((__aligned__(64))) i_t; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-4.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-4.c index 8418274..bc3c516 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-4.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-4.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 2 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 2 } } struct tt { int __attribute__((__aligned__(64))) i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-5.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-5.c index 322ac50..86cd3a9 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-5.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-5.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 1 } } struct tt { int i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-6.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-6.c index 784f213..bb1895f 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-6.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-6.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 1 } } struct tt { int i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/align-as-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/align-as-1.c index 5ef02c3..0b23580 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/align-as-1.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/align-as-1.c @@ -1,6 +1,6 @@ // { dg-do compile } // { dg-options "-O -g -dA -gno-strict-dwarf" } // { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } -// { dg-final { scan-assembler-times " DW_AT_alignment" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_alignment" 1 } } int _Alignas(64) i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c index 24b598e..fd61296 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c @@ -1,7 +1,7 @@ /* Test to make sure the mcaro info includes a start file command for the main source */ /* { dg-do compile } */ /* { dg-options "-g3 -gdwarf -dA -fverbose-asm" } */ -/* { dg-final { scan-assembler "Start new file" { xfail { powerpc-ibm-aix* } } } } */ +/* { dg-final { scan-assembler "Start new file" } } */ #define ADD(x) (M + x) diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c index 5204342..3dfa290 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c @@ -1,7 +1,7 @@ /* Test to make sure the macro info includes the predefined macros with line number 0. */ /* { dg-do compile } */ /* { dg-options "-g3 -gdwarf -dA -fverbose-asm" } */ -/* { dg-final { scan-assembler "At line number 0" { xfail { powerpc-ibm-aix* } } } } */ +/* { dg-final { scan-assembler "At line number 0" } } */ #define FOO 1 int i; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c index 7e019a6..9c36450 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c @@ -14,7 +14,9 @@ properly nested DW_TAG_inlined_subroutine DIEs for third, second and first. */ -/* { dg-options "-O -g3 -gdwarf -dA -fgnu89-inline" } */ +/* Explicitly use dwarf-2 because dwarf-5 might use DW_FORM_implicit_const + which is hard to scan for. */ +/* { dg-options "-O -g3 -gdwarf-2 -dA -fgnu89-inline" } */ /* { dg-do compile } */ /* There are 6 inlined subroutines: diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/inline5.c b/gcc/testsuite/gcc.dg/debug/dwarf2/inline5.c index 7587a28..bd34f0d 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/inline5.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/inline5.c @@ -9,7 +9,7 @@ /* We do not know which is output first so look for both invalid abstract origins on the lexical blocks (knowing that the abstract instance has no attribute following the DW_TAG_lexical_block. */ -/* { dg-final { scan-assembler-not "\\(DIE \\(0x(\[0-9a-f\]*)\\) DW_TAG_lexical_block\\)\[^#/!@;\\|\]*\[#/!@;\\|\]+ +\[^(\].*DW_TAG_lexical_block\\)\[^#/!@;\\|x\]*x\\1\[^#/!@;\\|\]*\[#/!@;\\|\] +DW_AT_abstract_origin" { xfail { *-*-solaris2.* && { ! gas } } } } } */ +/* { dg-final { scan-assembler-not "\\(DIE \\(0x(\[0-9a-f\]*)\\) DW_TAG_lexical_block\\)\[^#/!@;\\|\]*\[#/!@;\\|\]+ +\[^(\].*DW_TAG_lexical_block\\)\[^#/!@;\\|x\]*x\\1\[^#/!@;\\|\]*\[#/!@;\\|\] +DW_AT_abstract_origin" { xfail { { *-*-aix* || *-*-solaris2.* } && { ! gas } } } } } */ /* { dg-final { scan-assembler-not "DW_TAG_lexical_block\\)\[^#/!@;\\|x\]*x(\[0-9a-f\]*)\[^#/!@;\\|\]*\[#/!@;\\|\]+ +DW_AT_abstract_origin.*\\(DIE \\(0x\\1\\) DW_TAG_lexical_block\\)\[^#/!@;\\|\]*\[#/!@;\\|\]+ +DW_AT" } } */ int foo (int i) diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/inline6.c b/gcc/testsuite/gcc.dg/debug/dwarf2/inline6.c new file mode 100644 index 0000000..03013f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/inline6.c @@ -0,0 +1,69 @@ +/* DWARF5 variant of inline2. + Origin: PR debug/37801 + + Abstract instances (DW_TAG_subroutines having the DW_AT_inline attribute) + of second and first were having a DW_TAG_lexical_block DIE wrongly + representing the inlined calls to third (in second) and to + second (in first). At the same time, main didn't have children + DW_TAG_inlined_subroutine DIEs representing the inlined calls to + first, second and third. + + The ideal goal here is to test that we have no superfluous + DW_TAG_lexical_block DIE anymore, that abstract instances DIEs have + no descendant DIE with a DW_AT_abstract_origin attribute, and that main has + properly nested DW_TAG_inlined_subroutine DIEs for third, second and first. +*/ + +/* Explicitly use dwarf-5 which uses DW_FORM_implicit_const. */ +/* { dg-options "-O -g3 -gdwarf-5 -dA -fgnu89-inline" } */ +/* { dg-do compile } */ + +/* There are 6 inlined subroutines: + - One for each subroutine inlined into main, that's 3. + - One for earch subroutine inline into the out of line instances + of third, second and first. */ +/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_inlined_subroutine" 6 } } */ + +/* We should have no DW_TAG_lexical_block DIEs, all inline instances + should have the first subblock elided to match the abstract instance + layout. */ +/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_lexical_block" 0 } } */ + + +/* There are 3 DW_AT_inline attributes: one per abstract inline instance. + The value of the attribute must be 0x3, meaning the function was + actually inlined. */ +/* { dg-final { scan-assembler-times " DW_AT_inline \\(0x3\\)" 3 } } */ + +volatile int *a; + +inline void +third (int arg3) +{ + int var3 = arg3; + a[0] = var3; +} + +inline void +second (int arg2) +{ + int var2 = arg2; + third (var2+1); +} + +inline void +first (int arg1) +{ + int var1 = arg1; + second (var1+1); +} + +int +main () +{ + int some_int = 1; + first (some_int); + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/lang-c89.c b/gcc/testsuite/gcc.dg/debug/dwarf2/lang-c89.c index b6b4a89..6292cf8 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/lang-c89.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/lang-c89.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -std=c89 -g -dA" } */ /* DW_LANG_C89 = 0x0001 */ -/* { dg-final { scan-assembler "0x1.*DW_AT_language" { xfail { powerpc-ibm-aix* } } } } */ +/* { dg-final { scan-assembler "0x1.*DW_AT_language" } } */ int version; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-attribute.c b/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-attribute.c index bc2cfa5..7c8924a6 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-attribute.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-attribute.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -std=c99 -g -dA -gno-strict-dwarf" } // Expect DW_AT_noreturn once in .debug_info and once in .debug_abbrev -// { dg-final { scan-assembler-times "DW_AT_noreturn" 2 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times "DW_AT_noreturn" 2 } } void __attribute__ ((noreturn)) baz (void) diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-keyword.c b/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-keyword.c index 0105e6c..ced96d1 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-keyword.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/noreturn-function-keyword.c @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-O -std=c11 -g -dA -gno-strict-dwarf" } // Expect DW_AT_noreturn once in .debug_info and once in .debug_abbrev -// { dg-final { scan-assembler-times "DW_AT_noreturn" 2 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times "DW_AT_noreturn" 2 } } _Noreturn void exit (int); diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c index d646f59..80300ec 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-5.c @@ -2,7 +2,7 @@ /* Test that token after multi-line function-like macro use gets correct locus even when preprocessing separately. */ /* { dg-do compile } */ -/* { dg-options "-save-temps -gdwarf -O0 -dA -fno-merge-debug-strings" } */ +/* { dg-options "-save-temps -gdwarf-2 -O0 -dA -fno-merge-debug-strings" } */ #define A(x) vari x #define vari(x) diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c index 340cb38..fbf0337 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-6.c @@ -1,6 +1,6 @@ /* PR preprocessor/41445 */ /* { dg-do compile } */ -/* { dg-options "-gdwarf -O0 -dA -fno-merge-debug-strings" } */ +/* { dg-options "-gdwarf-2 -O0 -dA -fno-merge-debug-strings" } */ #include "pr41445-5.c" diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-7.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-7.c new file mode 100644 index 0000000..0e0de82 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-7.c @@ -0,0 +1,16 @@ +/* PR preprocessor/41445 DWARF5 variant */ +/* Test that token after multi-line function-like macro use + gets correct locus even when preprocessing separately. */ +/* { dg-do compile } */ +/* { dg-options "-save-temps -gdwarf-5 -O0 -dA -fno-merge-debug-strings" } */ + +#define A(x) vari x +#define vari(x) +#define B , varj +int A(B) ; + +/* We want to check that both vari and varj have the same line + number. */ + +/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"vari\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^\\r\\n\]*DW_AT_decl_line \\((0xa|10)\\)" } } */ +/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"varj\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^\\r\\n\]*DW_AT_decl_line \\((0xa|10)\\)" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-8.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-8.c new file mode 100644 index 0000000..3a6eeb5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr41445-8.c @@ -0,0 +1,11 @@ +/* PR preprocessor/41445 DWARF5 variant*/ +/* { dg-do compile } */ +/* { dg-options "-gdwarf-5 -O0 -dA -fno-merge-debug-strings" } */ + +#include "pr41445-5.c" + +/* We want to check that both vari and varj have the same line + number. */ + +/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"vari\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^\\r\\n\]*DW_AT_decl_line \\((0xa|10)\\)" } } */ +/* { dg-final { scan-assembler "DW_TAG_variable\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\"varj\[^\\r\\n\]*DW_AT_name(\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*DW_AT_)*\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\[^\\r\\n\]*DW_AT_decl_line \\((0xa|10)\\)" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c index 3842dbc..4fd8b74 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c @@ -8,4 +8,4 @@ foo (const char *format, ...) { } -// { dg-final { scan-assembler-times "DIE.*DW_TAG_unspecified_parameters" 1 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times "DIE.*DW_TAG_unspecified_parameters" 1 } } diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr96383-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr96383-1.c new file mode 100644 index 0000000..a9c0efb --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr96383-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-g -gdwarf -dA" } */ + +extern void foo (int); +extern void unusedbar (int); + +int main() +{ + foo (1); +} + +/* We want subprogram DIEs for both foo and main and a DIE for + the formal parameter of foo. We do not want a DIE for + unusedbar. */ +/* { dg-final { scan-assembler-times "DW_TAG_subprogram" 4 } } */ +/* { dg-final { scan-assembler-times "DW_TAG_formal_parameter" 2 } } */ +/* { dg-final { scan-assembler-not "unusedbar" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr96383-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr96383-2.c new file mode 100644 index 0000000..c3a710e --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr96383-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-g -O2 -gdwarf -dA" } */ + +extern void foo (int); +extern void unusedbar (int); + +int main() +{ + foo (1); +} + +/* We want subprogram DIEs for both foo and main and a DIE for + the formal parameter of foo. We do not want a DIE for + unusedbar. */ +/* { dg-final { scan-assembler-times "DW_TAG_subprogram" 4 } } */ +/* { dg-final { scan-assembler-times "DW_TAG_formal_parameter" 2 } } */ +/* { dg-final { scan-assembler-not "unusedbar" } } */ diff --git a/gcc/testsuite/gcc.dg/dfp/composite-type.c b/gcc/testsuite/gcc.dg/dfp/composite-type.c index 6d461c7..ce7d5c1 100644 --- a/gcc/testsuite/gcc.dg/dfp/composite-type.c +++ b/gcc/testsuite/gcc.dg/dfp/composite-type.c @@ -53,3 +53,6 @@ int main() return 0; } + +/* The invalid function redeclarations might also trigger: + { dg-prune-output "-Warray-parameter" } */ diff --git a/gcc/testsuite/gcc.dg/fold-parity-1.c b/gcc/testsuite/gcc.dg/fold-parity-1.c new file mode 100644 index 0000000..3ba56c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-parity-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +int foo(unsigned int x) +{ + return __builtin_popcount(x) & 1; +} + +int fool(unsigned long x) +{ + return __builtin_popcountl(x) & 1; +} + +int fooll(unsigned long long x) +{ + return __builtin_popcountll(x) & 1; +} + +/* { dg-final { scan-tree-dump-times "__builtin_popcount" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_parity" 3 "original" } } */ + diff --git a/gcc/testsuite/gcc.dg/fold-parity-2.c b/gcc/testsuite/gcc.dg/fold-parity-2.c new file mode 100644 index 0000000..8c7acbf --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-parity-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(unsigned int x) +{ + return __builtin_parity(~x); +} + +int fool(unsigned long x) +{ + return __builtin_parityl(~x); +} + +int fooll(unsigned long long x) +{ + return __builtin_parityll(~x); +} + +/* { dg-final { scan-tree-dump-times "~" 0 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/fold-parity-3.c b/gcc/testsuite/gcc.dg/fold-parity-3.c new file mode 100644 index 0000000..e0355cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-parity-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(unsigned int x) +{ + return __builtin_parity(x&1); +} + +int fool(unsigned long x) +{ + return __builtin_parityl(x&1); +} + +int fooll(unsigned long long x) +{ + return __builtin_parityll(x&1); +} + +/* { dg-final { scan-tree-dump-times "__builtin_parity" 0 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/fold-parity-4.c b/gcc/testsuite/gcc.dg/fold-parity-4.c new file mode 100644 index 0000000..5dfedab --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-parity-4.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(unsigned int x, unsigned int y) +{ + return __builtin_parity(x) ^ __builtin_parity(y); +} + +int fool(unsigned long x, unsigned long y) +{ + return __builtin_parityl(x) ^ __builtin_parityl(y); +} + +int fooll(unsigned long long x, unsigned long long y) +{ + return __builtin_parityll(x) ^ __builtin_parityll(y); +} + +/* { dg-final { scan-tree-dump-times "__builtin_parity" 3 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/fold-parity-5.c b/gcc/testsuite/gcc.dg/fold-parity-5.c new file mode 100644 index 0000000..69d3a6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-parity-5.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int test_and4(unsigned int a) +{ + return __builtin_parity(a&4); +} + +int test_and4l(unsigned long b) +{ + return __builtin_parityl(b&4); +} + +int test_and4ll(unsigned long long c) +{ + return __builtin_parityll(c&4); +} + +int test_shift(unsigned int d) +{ + int bits = 8*sizeof(unsigned int)-1; + return __builtin_parity(d<<31); +} + +int test_shiftl(unsigned long e) +{ + int bits = 8*sizeof(unsigned long)-1; + return __builtin_parityl(e<<bits); +} + +int test_shiftll(unsigned long long f) +{ + int bits = 8*sizeof(unsigned long long)-1; + return __builtin_parityll(f<<bits); +} + +/* { dg-final { scan-tree-dump-times "parity" 0 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/fold-popcount-5.c b/gcc/testsuite/gcc.dg/fold-popcount-5.c new file mode 100644 index 0000000..943726f --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-popcount-5.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int test_and4(unsigned int a) +{ + return __builtin_popcount(a&4); +} + +int test_and4l(unsigned long b) +{ + return __builtin_popcountl(b&4); +} + +int test_and4ll(unsigned long long c) +{ + return __builtin_popcountll(c&4); +} + +int test_shift(unsigned int d) +{ + int bits = 8*sizeof(unsigned int)-1; + return __builtin_popcount(d<<31); +} + +int test_shiftl(unsigned long e) +{ + int bits = 8*sizeof(unsigned long)-1; + return __builtin_popcountl(e<<bits); +} + +int test_shiftll(unsigned long long f) +{ + int bits = 8*sizeof(unsigned long long)-1; + return __builtin_popcountll(f<<bits); +} + +/* { dg-final { scan-tree-dump-times "popcount" 0 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/format/branch-1.c b/gcc/testsuite/gcc.dg/format/branch-1.c index 1782064..4ea39b5 100644 --- a/gcc/testsuite/gcc.dg/format/branch-1.c +++ b/gcc/testsuite/gcc.dg/format/branch-1.c @@ -10,7 +10,7 @@ foo (long l, int nfoo) { printf ((nfoo > 1) ? "%d foos" : "%d foo", nfoo); printf ((l > 1) ? "%d foos" /* { dg-warning "23:int" "wrong type in conditional expr" } */ - : "%d foo", l); /* { dg-warning "16:int" "wrong type in conditional expr" } */ + : "%d foo", l); /* { dg-warning "23:int" "wrong type in conditional expr" } */ printf ((l > 1) ? "%ld foos" : "%d foo", l); /* { dg-warning "36:int" "wrong type in conditional expr" } */ printf ((l > 1) ? "%d foos" : "%ld foo", l); /* { dg-warning "23:int" "wrong type in conditional expr" } */ /* Should allow one case to have extra arguments. */ diff --git a/gcc/testsuite/gcc.dg/format/pr79210.c b/gcc/testsuite/gcc.dg/format/pr79210.c index 71f5dd6..6bdabdf 100644 --- a/gcc/testsuite/gcc.dg/format/pr79210.c +++ b/gcc/testsuite/gcc.dg/format/pr79210.c @@ -20,4 +20,4 @@ LPFC_VPORT_ATTR_R(peer_port_login, "Allow peer ports on the same physical port to login to each " "other."); -/* { dg-warning "6: format .%d. expects argument of type .int., but argument 4 has type .unsigned int. " "" { target *-*-* } .-12 } */ +/* { dg-warning "20: format .%d. expects argument of type .int., but argument 4 has type .unsigned int. " "" { target *-*-* } .-12 } */ diff --git a/gcc/testsuite/gcc.dg/format/pr96935.c b/gcc/testsuite/gcc.dg/format/pr96935.c new file mode 100644 index 0000000..c311097 --- /dev/null +++ b/gcc/testsuite/gcc.dg/format/pr96935.c @@ -0,0 +1,9 @@ +/* PR preprocessor/96935 */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +void +foo (char const *name) +{ + /* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ __builtin_printf ("%s", name); +} diff --git a/gcc/testsuite/gcc.dg/gimplefe-44.c b/gcc/testsuite/gcc.dg/gimplefe-44.c index a9a92b1..3c83d49 100644 --- a/gcc/testsuite/gcc.dg/gimplefe-44.c +++ b/gcc/testsuite/gcc.dg/gimplefe-44.c @@ -1,5 +1,7 @@ /* { dg-do compile } */ +/* { dg-require-effective-target exceptions } */ /* { dg-options "-fexceptions -fgimple -fdump-tree-eh-eh" } */ +/* { dg-require-effective-target nonlocal_goto } */ void __GIMPLE foo() { diff --git a/gcc/testsuite/gcc.dg/gomp/block-7.c b/gcc/testsuite/gcc.dg/gomp/block-7.c index 6219e7e..3e87464 100644 --- a/gcc/testsuite/gcc.dg/gomp/block-7.c +++ b/gcc/testsuite/gcc.dg/gomp/block-7.c @@ -6,15 +6,15 @@ void foo() for (i = 0; i < 10; ++i) { #pragma omp for - for (j = ({ continue; 0; }); // { dg-error "invalid branch to/from OpenMP structured block" } - j < ({ continue; 10; }); // { dg-error "invalid branch to/from OpenMP structured block" } - j += ({ continue; 1; })) // { dg-error "invalid branch to/from OpenMP structured block" } + for (j = ({ continue; 0; }); // { dg-error "invalid exit from OpenMP structured block" } + j < ({ continue; 10; }); // { dg-error "invalid exit from OpenMP structured block" } + j += ({ continue; 1; })) // { dg-error "invalid exit from OpenMP structured block" } continue; #pragma omp for - for (j = ({ break; 0; }); // { dg-error "invalid branch to/from OpenMP structured block" } - j < ({ break; 10; }); // { dg-error "invalid branch to/from OpenMP structured block" } - j += ({ break; 1; })) // { dg-error "invalid branch to/from OpenMP structured block" } + for (j = ({ break; 0; }); // { dg-error "invalid exit from OpenMP structured block" } + j < ({ break; 10; }); // { dg-error "invalid exit from OpenMP structured block" } + j += ({ break; 1; })) // { dg-error "invalid exit from OpenMP structured block" } break; // { dg-error "break" } } } diff --git a/gcc/testsuite/gcc.dg/gomp/gomp.exp b/gcc/testsuite/gcc.dg/gomp/gomp.exp index 2414c22..8a7f18e 100644 --- a/gcc/testsuite/gcc.dg/gomp/gomp.exp +++ b/gcc/testsuite/gcc.dg/gomp/gomp.exp @@ -31,7 +31,7 @@ dg-init # Main loop. dg-runtest [lsort [concat \ [find $srcdir/$subdir *.c] \ - [find $srcdir/c-c++-common/gomp *.c]]] "" "-fopenmp -Wno-hsa" + [find $srcdir/c-c++-common/gomp *.c]]] "" "-fopenmp" # All done. dg-finish diff --git a/gcc/testsuite/gcc.dg/gomp/simd-2.c b/gcc/testsuite/gcc.dg/gomp/simd-2.c new file mode 100644 index 0000000..7ac3eb4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-2.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[1-9]\[0-9]* loops in function" 5 "vect" } } */ + +int a[10000][128]; + +void +foo (void) +{ + #pragma omp for simd schedule (simd: dynamic, 32) collapse(2) + for (int i = 0; i < 10000; i++) + for (int j = 0; j < 128; j++) + a[i][j] += 3; +} + +void +bar (void) +{ + #pragma omp parallel for simd schedule (simd: dynamic, 32) collapse(2) + for (int i = 0; i < 10000; i++) + for (int j = 0; j < 128; j++) + a[i][j] += 3; +} + +void +baz (void) +{ + #pragma omp distribute parallel for simd schedule (simd: dynamic, 32) collapse(2) + for (int i = 0; i < 10000; i++) + for (int j = 0; j < 128; j++) + a[i][j] += 3; +} + +void +qux (void) +{ + #pragma omp distribute simd dist_schedule (static, 128) collapse(2) + for (int i = 0; i < 10000; i++) + for (int j = 0; j < 128; j++) + a[i][j] += 3; +} + +void +corge (void) +{ + #pragma omp taskloop simd collapse(2) + for (int i = 0; i < 10000; i++) + for (int j = 0; j < 128; j++) + a[i][j] += 3; +} diff --git a/gcc/testsuite/gcc.dg/gomp/simd-3.c b/gcc/testsuite/gcc.dg/gomp/simd-3.c new file mode 100644 index 0000000..13e1346 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-3.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fopenmp -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx" { target avx } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[1-9]\[0-9]* loops in function" 5 "vect" } } */ + +int a[1024][1024]; + +void +foo (void) +{ + #pragma omp for simd collapse(2) + for (int i = 0; i < 1024; i++) + for (int j = 0; j < i; j++) + a[i][j] += 3; +} + +void +bar (void) +{ + #pragma omp parallel for simd collapse(2) + for (int i = 0; i < 1024; i++) + for (int j = 0; j < i; j++) + a[i][j] += 3; +} + +void +baz (void) +{ + #pragma omp distribute parallel for simd collapse(2) + for (int i = 0; i < 1024; i++) + for (int j = 0; j < i; j++) + a[i][j] += 3; +} + +void +qux (void) +{ + #pragma omp distribute simd collapse(2) + for (int i = 0; i < 1024; i++) + for (int j = 0; j < i; j++) + a[i][j] += 3; +} + +void +corge (void) +{ + #pragma omp taskloop simd collapse(2) + for (int i = 0; i < 1024; i++) + for (int j = 0; j < i; j++) + a[i][j] += 3; +} diff --git a/gcc/testsuite/gcc.dg/ia64-sync-5.c b/gcc/testsuite/gcc.dg/ia64-sync-5.c new file mode 100644 index 0000000..a3923b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ia64-sync-5.c @@ -0,0 +1,83 @@ +/* { dg-do run } */ +/* { dg-require-effective-target sync_char_short } */ +/* { dg-options } */ +/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */ +/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */ + +/* Test basic functionality of the intrinsics. */ + +/* This is a copy of gcc.dg/ia64-sync-3.c, for 8-bit and 16-bit. */ + +__extension__ typedef __SIZE_TYPE__ size_t; + +extern void abort (void); +extern void *memcpy (void *, const void *, size_t); +extern int memcmp (const void *, const void *, size_t); + +static signed char AC[4]; +static signed char init_qi[4] = { -30,-30,-50,-50 }; +static signed char test_qi[4] = { -115,-115,25,25 }; + +static void +do_qi (void) +{ + if (__sync_val_compare_and_swap(AC+0, -30, -115) != -30) + abort (); + if (__sync_val_compare_and_swap(AC+0, -30, -115) != -115) + abort (); + if (__sync_bool_compare_and_swap(AC+1, -30, -115) != 1) + abort (); + if (__sync_bool_compare_and_swap(AC+1, -30, -115) != 0) + abort (); + + if (__sync_val_compare_and_swap(AC+2, AC[2], 25) != -50) + abort (); + if (__sync_val_compare_and_swap(AC+2, AC[2], 25) != 25) + abort (); + if (__sync_bool_compare_and_swap(AC+3, AC[3], 25) != 1) + abort (); + if (__sync_bool_compare_and_swap(AC+3, AC[3], 25) != 1) + abort (); +} + +static short AS[4]; +static short init_hi[4] = { -30,-30,-50,-50 }; +static short test_hi[4] = { -115,-115,25,25 }; + +static void +do_hi (void) +{ + if (__sync_val_compare_and_swap(AS+0, -30, -115) != -30) + abort (); + if (__sync_val_compare_and_swap(AS+0, -30, -115) != -115) + abort (); + if (__sync_bool_compare_and_swap(AS+1, -30, -115) != 1) + abort (); + if (__sync_bool_compare_and_swap(AS+1, -30, -115) != 0) + abort (); + + if (__sync_val_compare_and_swap(AS+2, AS[2], 25) != -50) + abort (); + if (__sync_val_compare_and_swap(AS+2, AS[2], 25) != 25) + abort (); + if (__sync_bool_compare_and_swap(AS+3, AS[3], 25) != 1) + abort (); + if (__sync_bool_compare_and_swap(AS+3, AS[3], 25) != 1) + abort (); +} + +int main() +{ + memcpy(AC, init_qi, sizeof(init_qi)); + memcpy(AS, init_hi, sizeof(init_hi)); + + do_qi (); + do_hi (); + + if (memcmp (AC, test_qi, sizeof(test_qi))) + abort (); + if (memcmp (AS, test_hi, sizeof(test_hi))) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/ifcvt-3.c b/gcc/testsuite/gcc.dg/ifcvt-3.c index b250bc1..56fdd75 100644 --- a/gcc/testsuite/gcc.dg/ifcvt-3.c +++ b/gcc/testsuite/gcc.dg/ifcvt-3.c @@ -11,7 +11,7 @@ foo (s64 a, s64 b, s64 c) if (d == 0) return a + c; else - return b + d + c; + return b + c + d; } /* This test can be reduced to just return a + c; */ diff --git a/gcc/testsuite/gcc.dg/independent-cloneids-1.c b/gcc/testsuite/gcc.dg/independent-cloneids-1.c index 61c1203..efbc1c5 100644 --- a/gcc/testsuite/gcc.dg/independent-cloneids-1.c +++ b/gcc/testsuite/gcc.dg/independent-cloneids-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -fipa-cp -fipa-cp-clone" } */ +/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-rtl-final" } */ +/* { dg-skip-if "Odd label definition syntax" { mmix-*-* } } */ extern int printf (const char *, ...); @@ -28,11 +29,11 @@ baz (int arg) return foo (8); } -/* { dg-final { scan-assembler-times {(?n)^_*bar[.$_]constprop[.$_]0:} 1 } } */ -/* { dg-final { scan-assembler-times {(?n)^_*bar[.$_]constprop[.$_]1:} 1 } } */ -/* { dg-final { scan-assembler-times {(?n)^_*bar[.$_]constprop[.$_]2:} 1 } } */ -/* { dg-final { scan-assembler-times {(?n)^_*foo[.$_]constprop[.$_]0:} 1 } } */ -/* { dg-final { scan-assembler-times {(?n)^_*foo[.$_]constprop[.$_]1:} 1 } } */ -/* { dg-final { scan-assembler-times {(?n)^_*foo[.$_]constprop[.$_]2:} 1 } } */ -/* { dg-final { scan-assembler-not {(?n)^_*foo[.$_]constprop[.$_]3:} } } */ -/* { dg-final { scan-assembler-not {(?n)^_*foo[.$_]constprop[.$_]4:} } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function bar.constprop \(bar[.$_]constprop[.$_]0,} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function bar.constprop \(bar[.$_]constprop[.$_]1,} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function bar.constprop \(bar[.$_]constprop[.$_]2,} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function foo.constprop \(foo[.$_]constprop[.$_]0,} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function foo.constprop \(foo[.$_]constprop[.$_]1,} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function foo.constprop \(foo[.$_]constprop[.$_]2,} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function foo.constprop \(foo[.$_]constprop[.$_]3,} 0 "final" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^;; Function foo.constprop \(foo[.$_]constprop[.$_]4,} 0 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c b/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c index d513020..53ae25a 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -fdump-ipa-cp-details -fno-early-inlining --param ipa-cp-max-recursive-depth=8" } */ +/* { dg-options "-O3 -fdump-ipa-cp-details -fno-early-inlining --param ipa-cp-max-recursive-depth=8 --param=ipa-cp-eval-threshold=400" } */ int fn(); diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-pta-13.c b/gcc/testsuite/gcc.dg/ipa/ipa-pta-13.c index 93dd871..e7bf6d4 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-pta-13.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-pta-13.c @@ -1,5 +1,5 @@ /* { dg-do link } */ -/* { dg-options "-O2 -fipa-pta -fdump-ipa-pta2-details -fdump-tree-fre3 -fno-ipa-icf" } */ +/* { dg-options "-O2 -fipa-pta -fdump-ipa-pta2-details -fdump-tree-fre3 -fno-ipa-icf -fno-ipa-modref" } */ static int x, y; diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c index 4a22e39..df7e356 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c @@ -24,7 +24,7 @@ ox (struct bovid cow) } int -main (int argc, char *argv[]) +main (int argc, char **argv) { struct bovid cow; diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-12.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-12.c index 4d9057e..0cc76bd 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-12.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-12.c @@ -34,7 +34,7 @@ bar (struct S s) } int -main (int argc, char *argv[]) +main (int argc, char **argv) { struct S s; diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-13.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-13.c index 4d4ed74..e8751da 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-13.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-13.c @@ -33,7 +33,7 @@ bar (struct S *s) } int -main (int argc, char *argv[]) +main (int argc, char **argv) { struct S s; diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-14.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-14.c index 3ca302c..75619c6 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-14.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-14.c @@ -43,7 +43,7 @@ bar (struct S s) } int -main (int argc, char *argv[]) +main (int argc, char **argv) { struct S s; diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-15.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-15.c index 6c57c7b..aa13a94 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-15.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-15.c @@ -45,7 +45,7 @@ bar (struct S *s, int rec) volatile int g; int -main (int argc, char *argv[]) +main (int argc, char **argv) { struct S s; diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-loophint-1.c b/gcc/testsuite/gcc.dg/ipa/ipcp-loophint-1.c new file mode 100644 index 0000000..6d049af --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipcp-loophint-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-ipa-cp-details" } */ + +extern int *o, *p, *q, *r; + +#define FUNCTIONS fa(), fb(), fc(), fd(), fe(), ff(), fg() + +extern void FUNCTIONS; + +void foo (int c) +{ + FUNCTIONS; + FUNCTIONS; + for (int i = 0; i < 100; i++) + { + for (int j = 0; j < c; j++) + o[i] = p[i] + q[i] * r[i]; + } + FUNCTIONS; + FUNCTIONS; +} + +void bar() +{ + foo (8); + p[4]++; +} + +/* { dg-final { scan-ipa-dump {with known iterations:[1-9]} "cp" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/pr96482-2.c b/gcc/testsuite/gcc.dg/ipa/pr96482-2.c new file mode 100644 index 0000000..54b71ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr96482-2.c @@ -0,0 +1,33 @@ +/* PR ipa/96482 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int i2c_transfer(); +void _dev_err(); + +struct i2c_msg { + char bufaddr; + int adapterdev; +} wdt87xx_i2c_xfer_client; + +int wdt87xx_i2c_xfer_client_0, wdt87xx_i2c_xfer_rxdata, wdt87xx_get_string_str_idx; + +void +static wdt87xx_i2c_xfer(void *txdata, unsigned rxlen) { + struct i2c_msg msgs[] = {wdt87xx_i2c_xfer_client_0, rxlen, + wdt87xx_i2c_xfer_rxdata}; + int error = i2c_transfer(wdt87xx_i2c_xfer_client, msgs); + _dev_err("", __func__, error); +} +static void wdt87xx_get_string(unsigned len) { + char tx_buf[] = {wdt87xx_get_string_str_idx, 3}; + int rx_len = len + 2; + wdt87xx_i2c_xfer(tx_buf, rx_len); +} + +void +wdt87xx_ts_probe_tx_buf() { + wdt87xx_get_string(34); + wdt87xx_get_string(8); + wdt87xx_i2c_xfer(wdt87xx_ts_probe_tx_buf, 2); +} diff --git a/gcc/testsuite/gcc.dg/ipa/pr96482.c b/gcc/testsuite/gcc.dg/ipa/pr96482.c new file mode 100644 index 0000000..68ead79 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr96482.c @@ -0,0 +1,44 @@ +/* PR ipa/96482 */ +/* { dg-do run } */ +/* { dg-options "-O2 -flto" } */ +/* { dg-require-effective-target lto } */ + +int +__attribute__((noinline)) +foo(int arg) +{ + if (arg == 3) + return 1; + if (arg == 4) + return 123; + + __builtin_unreachable (); +} + +int +__attribute__((noinline)) +baz(int x) +{ + if (x != 0) + return foo(3); /* called */ + + return 1; +} + +int +__attribute__((noinline)) +bar(int x) +{ + if (x == 0) + return foo(5); /* not executed */ + + return 1; +} + +int main(int argc, char **argv) +{ + if (bar(argc) != baz(argc)) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/ipa/remref-2a.c b/gcc/testsuite/gcc.dg/ipa/remref-2a.c index 34a6188..c2f3eac 100644 --- a/gcc/testsuite/gcc.dg/ipa/remref-2a.c +++ b/gcc/testsuite/gcc.dg/ipa/remref-2a.c @@ -1,7 +1,7 @@ /* Verify that indirect inlining can also remove references of the functions it discovers calls for. */ /* { dg-do compile } */ -/* { dg-options "-O3 -fno-early-inlining -fno-ipa-cp -fdump-ipa-inline -fdump-tree-optimized -fno-ipa-icf" } */ +/* { dg-options "-O3 -fno-early-inlining -fno-ipa-cp -fdump-ipa-inline -fdump-tree-optimized -fno-ipa-icf -fno-ipa-modref" } */ int global; diff --git a/gcc/testsuite/gcc.dg/ipa/symver1.c b/gcc/testsuite/gcc.dg/ipa/symver1.c new file mode 100644 index 0000000..2cd0258 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/symver1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-skip-if "only works for ELF targets" { *-*-darwin* *-*-aix* } } */ + +__attribute__ ((__symver__ ("foo@VER_2"))) +__attribute__ ((__symver__ ("foo@VER_3"))) +int foo() +{ + return 2; +} + +/* { dg-final { scan-assembler ".symver.*foo, foo@VER_2" } } */ +/* { dg-final { scan-assembler ".symver.*foo, foo@VER_3" } } */ diff --git a/gcc/testsuite/gcc.dg/loop-8.c b/gcc/testsuite/gcc.dg/loop-8.c index 1eefccc..af317d8 100644 --- a/gcc/testsuite/gcc.dg/loop-8.c +++ b/gcc/testsuite/gcc.dg/loop-8.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O1 -fdump-rtl-loop2_invariant" } */ -/* { dg-skip-if "unexpected IV" { "hppa*-*-* mips*-*-* visium-*-* powerpc*-*-* riscv*-*-*" } } */ +/* { dg-skip-if "unexpected IV" { "hppa*-*-* mips*-*-* visium-*-* powerpc*-*-* riscv*-*-* mmix-*-*" } } */ /* Load immediate on condition is available from z13 on and prevents moving the load out of the loop, so always run this test with -march=zEC12 that does not have load immediate on condition. */ diff --git a/gcc/testsuite/gcc.dg/lto/modref-1_0.c b/gcc/testsuite/gcc.dg/lto/modref-1_0.c new file mode 100644 index 0000000..8fcb9ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/modref-1_0.c @@ -0,0 +1,14 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options {"-O2 -flto-partition=max -flto"} } */ +extern void recursive (int *a, int *b, int *c, int level); +int +main() +{ + int x = 123, y=124, z=125; + recursive (&x,&y,&z,1); + if (y) + __builtin_abort (); + if (!__builtin_constant_p (z)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/lto/modref-1_1.c b/gcc/testsuite/gcc.dg/lto/modref-1_1.c new file mode 100644 index 0000000..c7c0eae --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/modref-1_1.c @@ -0,0 +1,13 @@ +short aa; +void +__attribute__ ((noinline, noclone)) +recursive (int *a, int *b, int *c, int level) +{ + if (level && c) + { + recursive (b,a,c,0); + aa++; + } + else + *a=0; +} diff --git a/gcc/testsuite/gcc.dg/lto/pr96291.h b/gcc/testsuite/gcc.dg/lto/pr96291.h new file mode 100644 index 0000000..70eb3cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr96291.h @@ -0,0 +1,4 @@ +void e(void); +void f(void); +void a(void *, void *); +void c(int); diff --git a/gcc/testsuite/gcc.dg/lto/pr96291_0.c b/gcc/testsuite/gcc.dg/lto/pr96291_0.c new file mode 100644 index 0000000..07e6303 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr96291_0.c @@ -0,0 +1,11 @@ +/* { dg-lto-do link } */ + +#include "pr96291.h" + +static void * b; +void c(int d) { + f(); + a(b, b); +} + +void e(void) { c(0); } diff --git a/gcc/testsuite/gcc.dg/lto/pr96291_1.c b/gcc/testsuite/gcc.dg/lto/pr96291_1.c new file mode 100644 index 0000000..44744a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr96291_1.c @@ -0,0 +1,3 @@ +#include "pr96291.h" + +void f(void) { c(0); } diff --git a/gcc/testsuite/gcc.dg/lto/pr96291_2.c b/gcc/testsuite/gcc.dg/lto/pr96291_2.c new file mode 100644 index 0000000..5febffb --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr96291_2.c @@ -0,0 +1,7 @@ +/* { dg-options {-O0} } */ + +#include "pr96291.h" + +void a(void * a1, void * a2) { e(); } + +int main(){} diff --git a/gcc/testsuite/gcc.dg/memchr-2.c b/gcc/testsuite/gcc.dg/memchr-2.c new file mode 100644 index 0000000..61357f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memchr-2.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/96670 - ICE on memchr with an empty initializer + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +struct { + int i, j; +} const s = { }; + +void memchr_success_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memchr (p, '\0', n); +} + +void memchr_success_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (&s != __builtin_memchr (p, '\0', n)) + __builtin_abort (); +} + +void memchr_fail_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memchr (p, '\5', n); +} + +void memchr_fail_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (__builtin_memchr (p, '\5', n)) + __builtin_abort (); +} + +/* { dg-prune-output "\\\[-Wunused-value" } + { dg-final { scan-tree-dump-not "abort" "optimized" } } + { dg-final { scan-tree-dump-not "memcmp \\(" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memchr.c b/gcc/testsuite/gcc.dg/memchr.c new file mode 100644 index 0000000..fb21d58 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memchr.c @@ -0,0 +1,94 @@ +/* PR middle-end/78257 - missing memcmp optimization with constant arrays + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __SIZE_TYPE__ size_t; + +extern void* memchr (const void*, int, size_t); + +/* Verify that initializers for flexible array members are handled + correctly. */ + +struct SX +{ + /* offset */ + /* 0 */ int32_t n; + /* 4 */ int8_t: 1; + /* 6 */ int16_t a[]; +}; + +_Static_assert (__builtin_offsetof (struct SX, a) == 6); + +const struct SX sx = + { + 0x11121314, { 0x2122, 0x3132, 0x4142, 0x5152 } + }; + +const char sx_rep[] = + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + 0x11, 0x12, 0x13, 0x14, 0, 0, 0x21, 0x22, 0x31, 0x32, 0x41, 0x42, 0x51, 0x52 +#else + 0x14, 0x13, 0x12, 0x11, 0, 0, 0x22, 0x21, 0x32, 0x31, 0x42, 0x41, 0x52, 0x51 +#endif + }; + + +void test_find (void) +{ + int n = 0, nb = (const char*)&sx.a[4] - (const char*)&sx; + const char *p = (const char*)&sx, *q = sx_rep; + + if (nb != sizeof sx_rep) + __builtin_abort (); + + n += p == memchr (p, q[ 0], nb); + n += p + 1 == memchr (p, q[ 1], nb); + n += p + 2 == memchr (p, q[ 2], nb); + n += p + 3 == memchr (p, q[ 3], nb); + n += p + 4 == memchr (p, q[ 4], nb); + n += p + 4 == memchr (p, q[ 5], nb); + n += p + 6 == memchr (p, q[ 6], nb); + n += p + 7 == memchr (p, q[ 7], nb); + n += p + 8 == memchr (p, q[ 8], nb); + n += p + 9 == memchr (p, q[ 9], nb); + n += p + 10 == memchr (p, q[10], nb); + n += p + 11 == memchr (p, q[11], nb); + n += p + 12 == memchr (p, q[12], nb); + n += p + 13 == memchr (p, q[13], nb); + + if (n != 14) + __builtin_abort (); +} + +void test_not_find (void) +{ + int n = 0, nb = (const char*)&sx.a[4] - (const char*)&sx; + const char *p = (const char*)&sx, *q = sx_rep; + + if (nb != sizeof sx_rep) + __builtin_abort (); + + n += 0 == memchr (p, 0xff, nb); + n += 0 == memchr (p + 1, q[ 0], nb - 1); + n += 0 == memchr (p + 2, q[ 1], nb - 2); + n += 0 == memchr (p + 3, q[ 2], nb - 3); + n += 0 == memchr (p + 4, q[ 3], nb - 4); + n += 0 == memchr (p + 6, q[ 4], nb - 6); + n += 0 == memchr (p + 7, q[ 6], nb - 7); + n += 0 == memchr (p + 8, q[ 7], nb - 8); + n += 0 == memchr (p + 9, q[ 8], nb - 9); + n += 0 == memchr (p + 10, q[ 9], nb - 10); + n += 0 == memchr (p + 11, q[10], nb - 11); + n += 0 == memchr (p + 12, q[11], nb - 12); + n += 0 == memchr (p + 13, q[12], nb - 13); + n += 0 == memchr (p + 14, q[13], nb - 14); + + if (n != 14) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memcmp-2.c b/gcc/testsuite/gcc.dg/memcmp-2.c new file mode 100644 index 0000000..ff99c12 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-2.c @@ -0,0 +1,183 @@ +/* PR middle-end/78257 - missing memcmp optimization with constant arrays + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +#define assert(e) ((e) ? (void)0 : __builtin_abort ()) + +typedef __INT32_TYPE__ int32_t; + +extern int memcmp (const void*, const void*, __SIZE_TYPE__); + +const int32_t i_0 = 0; +const int32_t j_0 = 0; + +void eq_i0_j0 (void) +{ + const char *pi = (char*)&i_0, *pj = (char*)&j_0; + int n = 0; + + n += 0 == memcmp (pi, pj, sizeof (int32_t)); + n += 0 == memcmp (pi + 1, pj + 1, sizeof (int32_t) - 1); + n += 0 == memcmp (pi + 2, pj + 2, sizeof (int32_t) - 2); + n += 0 == memcmp (pi + 3, pj + 3, sizeof (int32_t) - 3); + n += 0 == memcmp (pi + 4, pj + 4, sizeof (int32_t) - 4); + + assert (n == 5); +} + + +const int32_t i1234 = 1234; +const int32_t j1234 = 1234; + +void eq_i1234_j1245 (void) +{ + const char *pi = (char*)&i1234, *pj = (char*)&j1234; + int n = 0; + + n += 0 == memcmp (pi, pj, sizeof (int32_t)); + n += 0 == memcmp (pi + 1, pj + 1, sizeof (int32_t) - 1); + n += 0 == memcmp (pi + 2, pj + 2, sizeof (int32_t) - 2); + n += 0 == memcmp (pi + 3, pj + 3, sizeof (int32_t) - 3); + n += 0 == memcmp (pi + 4, pj + 4, sizeof (int32_t) - 4); + + assert (n == 5); +} + + +const int32_t a1[2] = { 1234 }; +const int32_t b1[2] = { 1234 }; + +void eq_a1_b1 (void) +{ + const char *pi = (char*)&a1, *pj = (char*)&b1; + int n = 0, nb = sizeof a1; + + n += 0 == memcmp (pi, pj, nb); + n += 0 == memcmp (pi + 1, pj + 1, nb - 1); + n += 0 == memcmp (pi + 2, pj + 2, nb - 2); + n += 0 == memcmp (pi + 3, pj + 3, nb - 3); + n += 0 == memcmp (pi + 4, pj + 4, nb - 4); + n += 0 == memcmp (pi + 5, pj + 5, nb - 5); + n += 0 == memcmp (pi + 6, pj + 6, nb - 6); + n += 0 == memcmp (pi + 7, pj + 7, nb - 7); + n += 0 == memcmp (pi + 8, pj + 8, nb - 8); + + assert (n == 9); +} + +const int32_t a2[2] = { 1234 }; +const int32_t b2[2] = { 1234, 0 }; + +void eq_a2_b2 (void) +{ + const char *pi = (char*)&a2, *pj = (char*)&b2; + int n = 0, nb = sizeof a2; + + n += 0 == memcmp (pi, pj, nb); + n += 0 == memcmp (pi + 1, pj + 1, nb - 1); + n += 0 == memcmp (pi + 2, pj + 2, nb - 2); + n += 0 == memcmp (pi + 3, pj + 3, nb - 3); + n += 0 == memcmp (pi + 4, pj + 4, nb - 4); + n += 0 == memcmp (pi + 5, pj + 5, nb - 5); + n += 0 == memcmp (pi + 6, pj + 6, nb - 6); + n += 0 == memcmp (pi + 7, pj + 7, nb - 7); + n += 0 == memcmp (pi + 8, pj + 8, nb - 8); + + assert (n == 9); +} + + +const int32_t a5[5] = { [3] = 1234, [1] = 0 }; +const int32_t b5[5] = { 0, 0, 0, 1234 }; + +void eq_a5_b5 (void) +{ + int n = 0, b = sizeof a5; + const char *pi = (char*)a5, *pj = (char*)b5; + + n += 0 == memcmp (pi, pj, b); + n += 0 == memcmp (pi + 1, pj + 1, b - 1); + n += 0 == memcmp (pi + 2, pj + 2, b - 2); + n += 0 == memcmp (pi + 3, pj + 3, b - 3); + + n += 0 == memcmp (pi + 4, pj + 4, b - 4); + n += 0 == memcmp (pi + 5, pj + 5, b - 5); + n += 0 == memcmp (pi + 6, pj + 6, b - 6); + n += 0 == memcmp (pi + 7, pj + 7, b - 7); + + n += 0 == memcmp (pi + 8, pj + 8, b - 8); + n += 0 == memcmp (pi + 9, pj + 9, b - 9); + n += 0 == memcmp (pi + 10, pj + 10, b - 10); + n += 0 == memcmp (pi + 11, pj + 11, b - 11); + + n += 0 == memcmp (pi + 12, pj + 12, b - 12); + n += 0 == memcmp (pi + 13, pj + 13, b - 13); + n += 0 == memcmp (pi + 14, pj + 14, b - 14); + n += 0 == memcmp (pi + 15, pj + 15, b - 15); + + n += 0 == memcmp (pi + 16, pj + 16, b - 16); + n += 0 == memcmp (pi + 17, pj + 17, b - 17); + n += 0 == memcmp (pi + 18, pj + 18, b - 18); + n += 0 == memcmp (pi + 19, pj + 19, b - 19); + + assert (n == 20); +} + + +const int32_t a19[19] = { [13] = 13, [8] = 8, [4] = 4, [1] = 1 }; +const int32_t b19[19] = { 0, 1, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 13 }; + +void eq_a19_b19 (void) +{ + int n = 0, b = sizeof a19; + const char *pi = (char*)a19, *pj = (char*)b19; + + n += 0 == memcmp (pi, pj, b); + n += 0 == memcmp (pi + 1, pj + 1, b - 1); + n += 0 == memcmp (pi + 2, pj + 2, b - 2); + n += 0 == memcmp (pi + 3, pj + 3, b - 3); + + n += 0 == memcmp (pi + 14, pj + 14, b - 14); + n += 0 == memcmp (pi + 15, pj + 15, b - 15); + n += 0 == memcmp (pi + 16, pj + 16, b - 16); + n += 0 == memcmp (pi + 17, pj + 17, b - 17); + + n += 0 == memcmp (pi + 28, pj + 28, b - 28); + n += 0 == memcmp (pi + 29, pj + 29, b - 29); + n += 0 == memcmp (pi + 30, pj + 30, b - 30); + n += 0 == memcmp (pi + 31, pj + 31, b - 31); + + n += 0 == memcmp (pi + 42, pj + 42, b - 42); + n += 0 == memcmp (pi + 43, pj + 43, b - 43); + n += 0 == memcmp (pi + 44, pj + 44, b - 44); + n += 0 == memcmp (pi + 45, pj + 45, b - 45); + + n += 0 == memcmp (pi + 56, pj + 56, b - 56); + n += 0 == memcmp (pi + 57, pj + 57, b - 57); + n += 0 == memcmp (pi + 58, pj + 58, b - 58); + n += 0 == memcmp (pi + 59, pj + 59, b - 59); + + assert (n == 20); +} + + +const int32_t A20[20] = { [13] = 14, [8] = 8, [4] = 4, [1] = 1 }; +const int32_t b20[20] = { 0, 1, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 13 }; + +void gt_A20_b20 (void) +{ + int n = memcmp (A20, b20, sizeof A20) > 0; + assert (n == 1); +} + +const int32_t a21[21] = { [13] = 12, [8] = 8, [4] = 4, [1] = 1 }; +const int32_t B21[21] = { 0, 1, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 13 }; + +void lt_a21_B21 (void) +{ + int n = memcmp (a21, B21, sizeof a21) < 0; + assert (n == 1); +} + + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memcmp-3.c b/gcc/testsuite/gcc.dg/memcmp-3.c new file mode 100644 index 0000000..b5b8ac1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-3.c @@ -0,0 +1,349 @@ +/* PR middle-end/78257 - missing memcmp optimization with constant arrays + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } + { dg-skip-if "missing data representation" { "pdp11-*-*" } } */ + +#define offsetof(T, m) __builtin_offsetof (T, m) + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __INT64_TYPE__ int64_t; +typedef __SIZE_TYPE__ size_t; + +extern int memcmp (const void*, const void*, size_t); + +const int32_t ia4[4] = { 0x11121314, 0x21222324, 0x31323334, 0x41424344 }; +const int32_t ia4_des[4] = + { [2] = 0x31323334, [0] = 0x11121314, 0x21222324, [3] = 0x41424344 }; +const char ia4_rep[] = + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + "\x11\x12\x13\x14" "\x21\x22\x23\x24" + "\x31\x32\x33\x34" "\x41\x42\x43\x44" +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + "\x14\x13\x12\x11" "\x24\x23\x22\x21" + "\x34\x33\x32\x31" "\x44\x43\x42\x41" +#endif + }; + +void eq_ia4 (void) +{ + int n = 0, b = sizeof ia4; + const char *p = (const char*)ia4, *q = ia4_rep; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + n += memcmp (p + 9, q + 9, b - 9); + n += memcmp (p + 10, q + 10, b - 10); + n += memcmp (p + 11, q + 11, b - 11); + n += memcmp (p + 12, q + 12, b - 12); + n += memcmp (p + 13, q + 13, b - 13); + n += memcmp (p + 14, q + 14, b - 14); + n += memcmp (p + 15, q + 15, b - 15); + n += memcmp (p + 16, q + 16, b - 16); + + p = (const char*)ia4_des; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + n += memcmp (p + 9, q + 9, b - 9); + n += memcmp (p + 10, q + 10, b - 10); + n += memcmp (p + 11, q + 11, b - 11); + n += memcmp (p + 12, q + 12, b - 12); + n += memcmp (p + 13, q + 13, b - 13); + n += memcmp (p + 14, q + 14, b - 14); + n += memcmp (p + 15, q + 15, b - 15); + n += memcmp (p + 16, q + 16, b - 16); + + if (n != 0) + __builtin_abort (); +} + +const float fa4[4] = { 1.0, 2.0, 3.0, 4.0 }; +const float fa4_des[4] = { [0] = fa4[0], [1] = 2.0, [2] = fa4[2], [3] = 4.0 }; + +void eq_fa4 (void) +{ + int n = 0, b = sizeof fa4; + const char *p = (const char*)fa4, *q = (const char*)fa4_des; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + n += memcmp (p + 9, q + 9, b - 9); + n += memcmp (p + 10, q + 10, b - 10); + n += memcmp (p + 11, q + 11, b - 11); + n += memcmp (p + 12, q + 12, b - 12); + n += memcmp (p + 13, q + 13, b - 13); + n += memcmp (p + 14, q + 14, b - 14); + n += memcmp (p + 15, q + 15, b - 15); + n += memcmp (p + 16, q + 16, b - 16); + + if (n != 0) + __builtin_abort (); +} + +/* Verify "greater than" comparison with the difference in the last byte. */ +const char ia4_xrep_16[sizeof ia4] = + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + 0x11, 0x12, 0x13, 0x14, 0x21, 0x22, 0x23, 0x24, + 0x31, 0x32, 0x33, 0x34, 0x41, 0x42, 0x43 +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + 0x14, 0x13, 0x12, 0x11, 0x24, 0x23, 0x22, 0x21, + 0x34, 0x33, 0x32, 0x31, 0x44, 0x43, 0x42 +#endif + }; + +void gt_ia4 (void) +{ + int n = 0, b = sizeof ia4; + const char *p = (const char*)ia4, *q = ia4_xrep_16; + + n += 0 < memcmp (p, q, b); + n += 0 < memcmp (p + 1, q + 1, b - 1); + n += 0 < memcmp (p + 2, q + 2, b - 2); + n += 0 < memcmp (p + 3, q + 3, b - 3); + n += 0 < memcmp (p + 4, q + 4, b - 4); + n += 0 < memcmp (p + 5, q + 5, b - 5); + n += 0 < memcmp (p + 6, q + 6, b - 6); + n += 0 < memcmp (p + 7, q + 7, b - 7); + n += 0 < memcmp (p + 8, q + 8, b - 8); + n += 0 < memcmp (p + 9, q + 9, b - 9); + n += 0 < memcmp (p + 10, q + 10, b - 10); + n += 0 < memcmp (p + 11, q + 11, b - 11); + n += 0 < memcmp (p + 12, q + 12, b - 12); + n += 0 < memcmp (p + 13, q + 13, b - 13); + n += 0 < memcmp (p + 14, q + 14, b - 14); + n += 0 < memcmp (p + 15, q + 15, b - 15); + + if (n != 16) + __builtin_abort (); +} + +struct S8_16_32 +{ + int8_t i8; + int16_t i16; + int32_t i32; +}; + +_Static_assert (sizeof (struct S8_16_32) == 8); + +const struct S8_16_32 s8_16_32 = { 1, 0x2122, 0x31323334 }; +const struct S8_16_32 s8_16_32_des = + { .i8 = 1, .i16 = 0x2122, .i32 = 0x31323334 }; + +const char s8_16_32_rep[] = + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + 1, 0, 0x21, 0x22, 0x31, 0x32, 0x33, 0x34 +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + 1, 0, 0x22, 0x21, 0x34, 0x33, 0x32, 0x31 +#endif + }; + +void eq_s8_16_32 (void) +{ + int n = 0, b = sizeof s8_16_32; + const char *p = (char*)&s8_16_32, *q = s8_16_32_rep; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + + p = (char*)&s8_16_32_des; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + + if (n != 0) + __builtin_abort (); +} + + +struct S8_16_32_64 +{ + /* 0 */ int8_t i8; + /* 1 */ int8_t: 1; + /* 2 */ int16_t i16; + /* 4 */ int32_t: 1; + /* 8 */ int32_t i32; + /* 12 */ int32_t: 1; + /* 16 */ int64_t i64; + /* 24 */ int8_t: 0; +}; + +_Static_assert (offsetof (struct S8_16_32_64, i16) == 2); +_Static_assert (offsetof (struct S8_16_32_64, i32) == 8); +_Static_assert (offsetof (struct S8_16_32_64, i64) == 16); +_Static_assert (sizeof (struct S8_16_32_64) == 24); + +const struct S8_16_32_64 s8_16_32_64 = + { 1, 0x2122, 0x31323334, 0x4142434445464748LLU }; + +const char s8_16_32_64_rep[sizeof s8_16_32_64] = + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + "\x01" "\x00" "\x21\x22" "\x00\x00\x00\x00" "\x31\x32\x33\x34" + "\x00\x00\x00\x00" "\x41\x42\x43\x44\x45\x46\x47\x48" +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + "\x01" "\x00" "\x22\x21" "\x00\x00\x00\x00" "\x34\x33\x32\x31" + "\x00\x00\x00\x00" "\x48\x47\x46\x45\x44\x43\x42\x41" +#endif + }; + +const struct S8_16_32_64 s8_16_32_64_des = + { .i64 = 0x4142434445464748LLU, .i16 = 0x2122, .i32 = 0x31323334, .i8 = 1 }; + + +void eq_8_16_32_64 (void) +{ + int n = 0, b = sizeof s8_16_32_64; + const char *p = (char*)&s8_16_32_64, *q = s8_16_32_64_rep; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + n += memcmp (p + 9, q + 9, b - 9); + n += memcmp (p + 10, q + 10, b - 10); + n += memcmp (p + 11, q + 11, b - 11); + n += memcmp (p + 12, q + 12, b - 12); + n += memcmp (p + 13, q + 13, b - 13); + n += memcmp (p + 14, q + 14, b - 14); + n += memcmp (p + 15, q + 15, b - 15); + n += memcmp (p + 16, q + 16, b - 16); + n += memcmp (p + 17, q + 17, b - 17); + n += memcmp (p + 18, q + 18, b - 18); + n += memcmp (p + 19, q + 19, b - 19); + n += memcmp (p + 20, q + 20, b - 20); + n += memcmp (p + 21, q + 21, b - 21); + n += memcmp (p + 22, q + 22, b - 22); + n += memcmp (p + 23, q + 23, b - 23); + + p = (char*)&s8_16_32_64_des; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + n += memcmp (p + 9, q + 9, b - 9); + n += memcmp (p + 10, q + 10, b - 10); + n += memcmp (p + 11, q + 11, b - 11); + n += memcmp (p + 12, q + 12, b - 12); + n += memcmp (p + 13, q + 13, b - 13); + n += memcmp (p + 14, q + 14, b - 14); + n += memcmp (p + 15, q + 15, b - 15); + n += memcmp (p + 16, q + 16, b - 16); + n += memcmp (p + 17, q + 17, b - 17); + n += memcmp (p + 18, q + 18, b - 18); + n += memcmp (p + 19, q + 19, b - 19); + n += memcmp (p + 20, q + 20, b - 20); + n += memcmp (p + 21, q + 21, b - 21); + n += memcmp (p + 22, q + 22, b - 22); + n += memcmp (p + 23, q + 23, b - 23); + + if (n != 0) + __builtin_abort (); +} + +struct S64_x_3 +{ + int64_t i64a[3]; +}; + +_Static_assert (sizeof (struct S64_x_3) == 24); + +const struct S64_x_3 s64_x_3 = + { { 0x0000000021220001LLU, 0x0000000031323334LLU, 0x4142434445464748LLU } }; + +const char s64_x_3_rep[sizeof s64_x_3] = + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + "\x00\x00\x00\x00\x21\x22\x00\x01" + "\x00\x00\x00\x00\x31\x32\x33\x34" + "\x41\x42\x43\x44\x45\x46\x47\x48" +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + "\x01\x00\x22\x21\x00\x00\x00\x00" + "\x34\x33\x32\x31\x00\x00\x00\x00" + "\x48\x47\x46\x45\x44\x43\x42\x41" +#endif + }; + +void eq_64_x_3 (void) +{ + int n = 0, b = sizeof s8_16_32_64; + const char *p = (char*)&s8_16_32_64, *q = s64_x_3_rep; + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + n += memcmp (p + 9, q + 9, b - 9); + n += memcmp (p + 10, q + 10, b - 10); + n += memcmp (p + 11, q + 11, b - 11); + n += memcmp (p + 12, q + 12, b - 12); + n += memcmp (p + 13, q + 13, b - 13); + n += memcmp (p + 14, q + 14, b - 14); + n += memcmp (p + 15, q + 15, b - 15); + n += memcmp (p + 16, q + 16, b - 16); + n += memcmp (p + 17, q + 17, b - 17); + n += memcmp (p + 18, q + 18, b - 18); + n += memcmp (p + 19, q + 19, b - 19); + n += memcmp (p + 20, q + 20, b - 20); + n += memcmp (p + 21, q + 21, b - 21); + n += memcmp (p + 22, q + 22, b - 22); + n += memcmp (p + 23, q + 23, b - 23); + + if (n != 0) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memcmp-4.c b/gcc/testsuite/gcc.dg/memcmp-4.c new file mode 100644 index 0000000..bbac719 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-4.c @@ -0,0 +1,81 @@ +/* PR middle-end/78257 - missing memcmp optimization with constant arrays + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __SIZE_TYPE__ size_t; + +extern int memcmp (const void*, const void*, size_t); + +/* Verify that initializers for flexible array members are handled + correctly. */ + +struct Si16_x +{ + int16_t n, a[]; +}; + +const struct Si16_x si16_4 = + { + 0x1112, { 0x2122, 0x3132, 0x4142 } + }; + +const char si16_4_rep[] = + { + 0x12, 0x11, 0x22, 0x21, 0x32, 0x31, 0x42, 0x41 + }; + +void eq_si16_x (void) +{ + int n = 0, b = sizeof si16_4_rep; + const char *p = (const char*)&si16_4, *q = si16_4_rep; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + + p = (const char*)&si16_4.n; + + n += memcmp (p, q, b); + n += memcmp (p + 1, q + 1, b - 1); + n += memcmp (p + 2, q + 2, b - 2); + n += memcmp (p + 3, q + 3, b - 3); + n += memcmp (p + 4, q + 4, b - 4); + n += memcmp (p + 5, q + 5, b - 5); + n += memcmp (p + 6, q + 6, b - 6); + n += memcmp (p + 7, q + 7, b - 7); + n += memcmp (p + 8, q + 8, b - 8); + + p = (const char*)si16_4.a; + q = si16_4_rep + 2; + + n += memcmp (p, q, b - 2); + n += memcmp (p + 1, q + 1, b - 3); + n += memcmp (p + 2, q + 2, b - 4); + n += memcmp (p + 3, q + 3, b - 5); + n += memcmp (p + 4, q + 4, b - 6); + n += memcmp (p + 5, q + 5, b - 7); + n += memcmp (p + 6, q + 6, b - 8); + + p = (const char*)&si16_4.a[1]; + q = si16_4_rep + 4; + + n += memcmp (p, q, b - 4); + n += memcmp (p + 1, q + 1, b - 5); + n += memcmp (p + 2, q + 2, b - 6); + n += memcmp (p + 3, q + 3, b - 7); + n += memcmp (p + 4, q + 4, b - 8); + + if (n != 0) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memcmp-5.c b/gcc/testsuite/gcc.dg/memcmp-5.c new file mode 100644 index 0000000..34bae92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-5.c @@ -0,0 +1,72 @@ +/* PR middle-end/78257 - missing memcmp optimization with constant arrays + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +#define A "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0" + +const char a257[sizeof A - 1] = A; +const char a258[sizeof A] = A; + +_Static_assert (sizeof A == 258); +_Static_assert (sizeof a257 == 257); + +/* Verify that initializers longer than 256 characters (an internal limit + on the size of a buffer used to store representations in) are handled. */ + +void eq_256plus (void) +{ + int n = 0; + + n += __builtin_memcmp (a257, A, sizeof a257); + n += __builtin_memcmp (a257 + 1, A + 1, sizeof a257 - 1); + n += __builtin_memcmp (a257 + 2, A + 2, sizeof a257 - 2); + n += __builtin_memcmp (a257 + 127, A + 127, sizeof a257 - 127); + n += __builtin_memcmp (a257 + 128, A + 128, sizeof a257 - 128); + n += __builtin_memcmp (a257 + 255, A + 255, 2); + n += __builtin_memcmp (a257 + 256, A + 256, 1); + + n += __builtin_memcmp (a258, A, sizeof a257); + n += __builtin_memcmp (a258 + 1, A + 1, sizeof a257 - 1); + n += __builtin_memcmp (a258 + 2, A + 2, sizeof a257 - 2); + n += __builtin_memcmp (a258 + 127, A + 127, sizeof a257 - 127); + n += __builtin_memcmp (a258 + 128, A + 128, sizeof a257 - 128); + n += __builtin_memcmp (a258 + 256, A + 256, 2); + n += __builtin_memcmp (a258 + 257, A + 257, 1); + + if (n) + __builtin_abort (); +} + +#define X "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" \ + "1" + +void lt_256plus (void) +{ + int n = 0; + + n += 0 > __builtin_memcmp (a257, X, sizeof a257); + n += 0 > __builtin_memcmp (a257 + 1, X + 1, sizeof a257 - 1); + n += 0 > __builtin_memcmp (a257 + 2, X + 2, sizeof a257 - 2); + n += 0 > __builtin_memcmp (a257 + 127, X + 127, sizeof a257 - 127); + n += 0 > __builtin_memcmp (a257 + 128, X + 128, sizeof a257 - 128); + n += 0 > __builtin_memcmp (a257 + 255, X + 255, 2); + n += 0 > __builtin_memcmp (a257 + 256, X + 256, 1); + + n += 0 > __builtin_memcmp (a258, X, sizeof a258); + n += 0 > __builtin_memcmp (a258 + 1, X + 1, sizeof a258 - 1); + n += 0 > __builtin_memcmp (a258 + 2, X + 2, sizeof a258 - 2); + n += 0 > __builtin_memcmp (a258 + 127, X + 127, sizeof a257 - 127); + n += 0 > __builtin_memcmp (a258 + 128, X + 128, sizeof a257 - 128); + n += 0 > __builtin_memcmp (a258 + 256, X + 256, 2); + n += 0 == __builtin_memcmp (a258 + 257, X + 257, 1); + + if (n != 14) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/memcmp-6.c b/gcc/testsuite/gcc.dg/memcmp-6.c new file mode 100644 index 0000000..d573526 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-6.c @@ -0,0 +1,47 @@ +/* PR tree-optimization/96670 - ICE on memchr with an empty initializer + { dg-do compile } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +struct { + int i, j; +} const s = { }; + +const char a[sizeof s] = { }; + +void memcmp_success_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memcmp (p, a, n); + __builtin_memcmp (a, p, n); +} + +void memcmp_success_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (__builtin_memcmp (p, a, n) + || __builtin_memcmp (a, p, n)) + __builtin_abort (); +} + +void memcmp_fail_unused (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + __builtin_memcmp (p, a, n); + __builtin_memcmp (a, p, n); +} + +void memcmp_fail_used (void) +{ + int n = (char *)&s.j - (char *)&s; + char *p = (char *)&s; + if (__builtin_memcmp (p, a, n) + || __builtin_memcmp (a, p, n)) + __builtin_abort (); +} + +/* { dg-prune-output "\\\[-Wunused-value" } + { dg-final { scan-tree-dump-not "abort" "optimized" } } + { dg-final { scan-tree-dump-not "memcmp \\\(" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/memcmp-pr95189.c b/gcc/testsuite/gcc.dg/memcmp-pr95189.c new file mode 100644 index 0000000..d8250ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcmp-pr95189.c @@ -0,0 +1,28 @@ +/* PR middle-end/95189 - memcmp being wrongly stripped like strcmp + { dg-do run } + { dg-options "-O2 -Wall" } */ + +char a4[] = "\0abc"; +char a8[] = "\0abcdefg"; +char a16[] = "\0abcdefghijklmno"; + +int cmp4 (void) +{ + return __builtin_memcmp (a4, "\0\0\0\0", 4); +} + +int cmp8 (void) +{ + return __builtin_memcmp (a8, "\0\0\0\0\0\0\0\0", 8); +} + +int cmp16 (void) +{ + return __builtin_memcmp (a16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); +} + +int main (void) +{ + if (cmp4 () < 1 || cmp8 () < 1 || cmp16 () < 1) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c index 0c7e096..909f8a6 100644 --- a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c +++ b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c @@ -18,7 +18,7 @@ int main () return foo (); } -/* { dg-final { scan-tree-dump-times "__gcov0\\.main.* = PROF_edge_counter" 1 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "__gcov0\[._\]main.* = PROF_edge_counter" 1 "optimized"} } */ /* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "__gcov_time_profiler_counter = " 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "__gcov_init" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c deleted file mode 100644 index 5712dbd..0000000 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c +++ /dev/null @@ -1,142 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fdiagnostics-show-caret" } */ - -#include <stdlib.h> - -void *wrapped_malloc (size_t size) -{ - return malloc (size); -} - -void wrapped_free (void *ptr) -{ - free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\]" } */ - /* { dg-begin-multiline-output "" } - free (ptr); - ^~~~~~~~~~ - 'test': events 1-2 - | - | { - | ^ - | | - | (1) entering 'test' - | boxed_int *obj = make_boxed_int (i); - | ~~~~~~~~~~~~~~~~~~ - | | - | (2) calling 'make_boxed_int' - | - +--> 'make_boxed_int': events 3-4 - | - | { - | ^ - | | - | (3) entering 'make_boxed_int' - | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - | | - | (4) calling 'wrapped_malloc' - | - +--> 'wrapped_malloc': events 5-6 - | - | { - | ^ - | | - | (5) entering 'wrapped_malloc' - | return malloc (size); - | ~~~~~~~~~~~~~ - | | - | (6) calling 'malloc' - | - <-------------+ - | - 'test': event 7 - | - | free_boxed_int (obj); - | ^~~~~~~~~~~~~~~~~~~~ - | | - | (7) calling 'free_boxed_int' - | - +--> 'free_boxed_int': events 8-9 - | - | { - | ^ - | | - | (8) entering 'free_boxed_int' - | wrapped_free (bi); - | ~~~~~~~~~~~~~~~~~ - | | - | (9) calling 'wrapped_free' - | - +--> 'wrapped_free': events 10-11 - | - | { - | ^ - | | - | (10) entering 'wrapped_free' - | free (ptr); - | ~~~~~~~~~~ - | | - | (11) calling 'free' - | - <-------------+ - | - 'test': event 12 - | - | free_boxed_int (obj); - | ^~~~~~~~~~~~~~~~~~~~ - | | - | (12) calling 'free_boxed_int' - | - +--> 'free_boxed_int': events 13-14 - | - | { - | ^ - | | - | (13) entering 'free_boxed_int' - | wrapped_free (bi); - | ~~~~~~~~~~~~~~~~~ - | | - | (14) calling 'wrapped_free' - | - +--> 'wrapped_free': events 15-16 - | - | { - | ^ - | | - | (15) entering 'wrapped_free' - | free (ptr); - | ~~~~~~~~~~ - | | - | (16) calling 'free' - | - { dg-end-multiline-output "" } */ -} - -typedef struct boxed_int -{ - int i; -} boxed_int; - -boxed_int * -make_boxed_int (int i) -{ - boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); - result->i = i; - return result; -} - -void -free_boxed_int (boxed_int *bi) -{ - wrapped_free (bi); -} - -void test (int i) -{ - boxed_int *obj = make_boxed_int (i); - - free_boxed_int (obj); - - free_boxed_int (obj); -} - diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-plain.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-plain.c new file mode 100644 index 0000000..75acd25 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-plain.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ + +#include <stdlib.h> + +void *wrapped_malloc (size_t size) +{ + return malloc (size); +} + +void wrapped_free (void *ptr) +{ + free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\]" } */ +} + +typedef struct boxed_int +{ + int i; +} boxed_int; + +boxed_int * +make_boxed_int (int i) +{ + boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); + result->i = i; + return result; +} + +void +free_boxed_int (boxed_int *bi) +{ + wrapped_free (bi); +} + +void test (int i) +{ /* { dg-message "\\(1\\) entering 'test'" } */ + boxed_int *obj = make_boxed_int (i); /* { dg-message "\\(2\\) calling 'make_boxed_int'" } */ + /* etc */ + + free_boxed_int (obj); + + free_boxed_int (obj); +} diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c index 03b7804..d7691e4 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c @@ -540,15 +540,15 @@ void test_builtin_types_compatible_p (unsigned long i) __emit_expression_range (0, f (i) + __builtin_types_compatible_p (long, int)); /* { dg-warning "range" } */ /* { dg-begin-multiline-output "" } - f (i) + __builtin_types_compatible_p (long, int)); - ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + f (i) + __builtin_types_compatible_p (long, int)); + ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { dg-end-multiline-output "" } */ __emit_expression_range (0, __builtin_types_compatible_p (long, int) + f (i)); /* { dg-warning "range" } */ /* { dg-begin-multiline-output "" } - __builtin_types_compatible_p (long, int) + f (i)); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ + __builtin_types_compatible_p (long, int) + f (i)); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ { dg-end-multiline-output "" } */ } @@ -671,8 +671,8 @@ void test_multiple_ordinary_maps (void) /* { dg-begin-multiline-output "" } __emit_expression_range (0, foo (0, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789")); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789")); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { dg-end-multiline-output "" } */ /* Another expression that transitions between ordinary maps; this @@ -685,8 +685,8 @@ void test_multiple_ordinary_maps (void) /* { dg-begin-multiline-output "" } __emit_expression_range (0, foo (0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 0)); - ~~ + 0)); + ~~ { dg-end-multiline-output "" } */ } diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c index 946a234..b2b269a 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */ +/* { dg-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events" } */ #include <stddef.h> #include <stdlib.h> @@ -43,9 +43,9 @@ make_a_list_of_random_ints_badly(PyObject *self, | | (1) when 'PyList_New' fails, returning NULL | 26 | | 27 | for (i = 0; i < count; i++) { - | | ~~~ - | | | - | | (2) when 'i < count' + | | ~~~~~~~~~ + | | | + | | (2) when 'i < count' | 28 | item = PyLong_FromLong(random()); | 29 | PyList_Append(list, item); | | ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c index ac4fa1b..4cba87b 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c @@ -335,11 +335,11 @@ pr87652 (const char *stem, int counter) /* { dg-error "unable to read substring location: unable to read source line" "" { target c } 329 } */ /* { dg-error "unable to read substring location: failed to get ordinary maps" "" { target c++ } 329 } */ /* { dg-begin-multiline-output "" } - __emit_string_literal_range(__FILE__":%5d: " format, \ + __emit_string_literal_range(__FILE__":%5d: " format, \ ^~~~~~~~ { dg-end-multiline-output "" { target c } } */ /* { dg-begin-multiline-output "" } - __emit_string_literal_range(__FILE__":%5d: " format, \ + __emit_string_literal_range(__FILE__":%5d: " format, \ ^ { dg-end-multiline-output "" { target c++ } } */ diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index c02b008..5dd102a 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -100,7 +100,7 @@ set plugin_test_list [list \ diagnostic-test-paths-2.c \ diagnostic-test-paths-3.c \ diagnostic-test-paths-4.c \ - diagnostic-path-format-default.c \ + diagnostic-path-format-plain.c \ diagnostic-path-format-none.c \ diagnostic-path-format-separate-events.c \ diagnostic-path-format-inline-events-1.c \ diff --git a/gcc/testsuite/gcc.dg/pr21137.c b/gcc/testsuite/gcc.dg/pr21137.c new file mode 100644 index 0000000..6d73dea --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr21137.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void foo(); + +void test5_1(int e) +{ + if ((e >> 31) & 64) + foo(); +} + +typedef int myint; + +void test5_2(myint e) +{ + if ((e >> 31) & 64) + foo(); +} + +/* { dg-final { scan-tree-dump-times " < 0" 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr30957-1.c b/gcc/testsuite/gcc.dg/pr30957-1.c index 6a0ed20..5644109 100644 --- a/gcc/testsuite/gcc.dg/pr30957-1.c +++ b/gcc/testsuite/gcc.dg/pr30957-1.c @@ -1,4 +1,4 @@ -/* { dg-do run } */ +/* { dg-do run { xfail { mmix-*-* } } } */ /* We don't (and don't want to) perform this optimisation on soft-float targets, where each addition is a library call. / /* { dg-require-effective-target hard_float } */ @@ -33,4 +33,4 @@ main () exit (0); } -/* { dg-final { scan-rtl-dump "Expanding Accumulator" "loop2_unroll" } } */ +/* { dg-final { scan-rtl-dump "Expanding Accumulator" "loop2_unroll" { xfail mmix-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/pr44194-1.c b/gcc/testsuite/gcc.dg/pr44194-1.c index 20b74a5..a38270b 100644 --- a/gcc/testsuite/gcc.dg/pr44194-1.c +++ b/gcc/testsuite/gcc.dg/pr44194-1.c @@ -1,4 +1,5 @@ /* { dg-do compile { target { { { { { { { { { { i?86-*-* x86_64-*-* } && x32 } || lp64 } && { ! s390*-*-* } } && { ! hppa*64*-*-* } } && { ! alpha*-*-* } } && { { ! powerpc*-*-linux* } || powerpc_elfv2 } } && { ! nvptx-*-* } } } } } } */ +/* { dg-skip-if "returns that struct in memory" { mmix-*-* } } */ /* { dg-options "-O2 -fdump-rtl-dse1 -fdump-rtl-final" } */ /* Restrict to 64-bit targets since 32-bit targets usually return small diff --git a/gcc/testsuite/gcc.dg/pr51628-17.c b/gcc/testsuite/gcc.dg/pr51628-17.c index 0be95b2..42dc9d7 100644 --- a/gcc/testsuite/gcc.dg/pr51628-17.c +++ b/gcc/testsuite/gcc.dg/pr51628-17.c @@ -7,4 +7,4 @@ struct A { } __attribute__ ((packed)); long* f8 (struct A *p) { return &p->i; } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-19.c b/gcc/testsuite/gcc.dg/pr51628-19.c index 7ff03e8..91ff39a 100644 --- a/gcc/testsuite/gcc.dg/pr51628-19.c +++ b/gcc/testsuite/gcc.dg/pr51628-19.c @@ -16,11 +16,11 @@ bar (int n, int k, void *ptr) int *p0, *p1; p0 = p->x; -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ foo (p0); p1 = &p->x[1]; -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ foo (p1); return &p->x[1]; -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/pr51628-20.c b/gcc/testsuite/gcc.dg/pr51628-20.c index bcdbff1..2249d85 100644 --- a/gcc/testsuite/gcc.dg/pr51628-20.c +++ b/gcc/testsuite/gcc.dg/pr51628-20.c @@ -8,4 +8,4 @@ struct C { struct B b; } __attribute__ ((packed)); extern struct C *p; long* g8 (void) { return p; } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-21.c b/gcc/testsuite/gcc.dg/pr51628-21.c index 0c7fab7..f1adbe6 100644 --- a/gcc/testsuite/gcc.dg/pr51628-21.c +++ b/gcc/testsuite/gcc.dg/pr51628-21.c @@ -8,4 +8,4 @@ struct C { struct B b; } __attribute__ ((packed)); extern struct C p[]; long* g8 (void) { return p; } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-22.c b/gcc/testsuite/gcc.dg/pr51628-22.c index 1bd5d79..25ac36c 100644 --- a/gcc/testsuite/gcc.dg/pr51628-22.c +++ b/gcc/testsuite/gcc.dg/pr51628-22.c @@ -6,4 +6,4 @@ struct B { int i; }; struct C { struct B b; } __attribute__ ((packed)); int* g4 (struct C *p) { return &p->b; } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-24.c b/gcc/testsuite/gcc.dg/pr51628-24.c index 3ad99cd..1e454a1 100644 --- a/gcc/testsuite/gcc.dg/pr51628-24.c +++ b/gcc/testsuite/gcc.dg/pr51628-24.c @@ -7,4 +7,4 @@ struct A { } __attribute__ ((packed)); short* f2 (struct A *p) { return &p->i; } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-25.c b/gcc/testsuite/gcc.dg/pr51628-25.c index 94a3a8f..f00d9b1 100644 --- a/gcc/testsuite/gcc.dg/pr51628-25.c +++ b/gcc/testsuite/gcc.dg/pr51628-25.c @@ -6,4 +6,4 @@ struct B { int i; }; struct C { struct B b; } __attribute__ ((packed)); long* g8 (struct C *p) { return p; } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr51628-34.c b/gcc/testsuite/gcc.dg/pr51628-34.c index 51d4b26..0f6ae34 100644 --- a/gcc/testsuite/gcc.dg/pr51628-34.c +++ b/gcc/testsuite/gcc.dg/pr51628-34.c @@ -9,9 +9,9 @@ baz (int x, struct S *p) { return (x ? &p->a -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ : &p->b); -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ } short * @@ -19,7 +19,7 @@ qux (int x, struct S *p) { return (short *) (x ? &p->a -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ : &p->b); -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/pr51683.c b/gcc/testsuite/gcc.dg/pr51683.c index c477cd8..7a624e4 100644 --- a/gcc/testsuite/gcc.dg/pr51683.c +++ b/gcc/testsuite/gcc.dg/pr51683.c @@ -12,6 +12,9 @@ void * foo (void *p) { return bar ((void *) 0x12345000, p, 256); + /* Integers converted to pointers are assumed to be the result of + (invalid) arithmetic on null pointers. + { dg-prune-output "writing 256 bytes into a region of size 0" } */ } /* { dg-final { scan-tree-dump "memcpy" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr53037-1.c b/gcc/testsuite/gcc.dg/pr53037-1.c index 3ea5ae6..3f22696 100644 --- a/gcc/testsuite/gcc.dg/pr53037-1.c +++ b/gcc/testsuite/gcc.dg/pr53037-1.c @@ -40,7 +40,7 @@ struct foo5 { int i1; int x __attribute__((warn_if_not_aligned(16))); /* { dg-warning "'x' offset 4 in 'struct foo5' isn't aligned to 16" } */ -}; /* { dg-warning "alignment 4 of 'struct foo5' is less than 16" } */ +}; /* { dg-warning {alignment [0-9]+ of 'struct foo5' is less than 16} } */ struct foo6 { @@ -73,7 +73,7 @@ union bar3 { int i1; int x __attribute__((warn_if_not_aligned(16))); -}; /* { dg-warning "alignment 4 of 'union bar3' is less than 16" } */ +}; /* { dg-warning {alignment [0-9]+ of 'union bar3' is less than 16} } */ union bar4 { diff --git a/gcc/testsuite/gcc.dg/pr55940.c b/gcc/testsuite/gcc.dg/pr55940.c index d046d0b..85761f6 100644 --- a/gcc/testsuite/gcc.dg/pr55940.c +++ b/gcc/testsuite/gcc.dg/pr55940.c @@ -1,5 +1,6 @@ /* PR target/55940 */ /* { dg-do run } */ +/* { dg-skip-if "pointer arithmetic can wrap" { msp430-*-* } { "*" } { "-mlarge" } } */ /* { dg-options "-Os" } */ /* { dg-additional-options "-mpreferred-stack-boundary=2" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */ diff --git a/gcc/testsuite/gcc.dg/pr78902.c b/gcc/testsuite/gcc.dg/pr78902.c index 51b4254..a9a617c 100644 --- a/gcc/testsuite/gcc.dg/pr78902.c +++ b/gcc/testsuite/gcc.dg/pr78902.c @@ -12,4 +12,5 @@ void foo(void) __builtin_aligned_alloc (10, 16); /* { dg-warning "ignoring return value of '__builtin_aligned_alloc' declared with attribute 'warn_unused_result'" } */ __builtin_strdup ("pes"); /* { dg-warning "ignoring return value of '__builtin_strdup' declared with attribute 'warn_unused_result'" } */ __builtin_strndup ("pes", 10); /* { dg-warning "ignoring return value of '__builtin_strndup' declared with attribute 'warn_unused_result'" } */ + /* { dg-warning "\\\[-Wstringop-overread" "strndup excessive bound" { target *-*-* } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/pr79214.c b/gcc/testsuite/gcc.dg/pr79214.c index 23119ed..3f5d935 100644 --- a/gcc/testsuite/gcc.dg/pr79214.c +++ b/gcc/testsuite/gcc.dg/pr79214.c @@ -84,5 +84,5 @@ char* test_strncat (int i) { const char *s = i < 0 ? "123" : "4567"; - return strncat (d, s, range ()); /* { dg-warning ".__builtin_strncat. specified bound between 4 and \[0-9\]+" } */ + return strncat (d, s, range ()); /* { dg-warning ".__builtin_strncat. specified bound \\\[4, \[0-9\]+] exceeds destination size 3" } */ } diff --git a/gcc/testsuite/gcc.dg/pr81192.c b/gcc/testsuite/gcc.dg/pr81192.c index 0049f37..71bbc13 100644 --- a/gcc/testsuite/gcc.dg/pr81192.c +++ b/gcc/testsuite/gcc.dg/pr81192.c @@ -1,4 +1,20 @@ -/* { dg-options "-Os -fdump-tree-pre-details" } */ +/* { dg-options "-Os -fdump-tree-pre-details -fdisable-tree-evrp" } */ + +/* Disable tree-evrp because the new version of evrp sees +<bb 3> : + if (j_8(D) != 2147483647) + goto <bb 4>; [50.00%] + else + goto <bb 5>; [50.00%] +<bb 4> : + iftmp.2_11 = j_8(D) + 1; +<bb 5> : + # iftmp.2_12 = PHI <j_8(D)(3), iftmp.2_11(4)> + +EVRP now recognizes a constant can be propagated into the 3->5 edge and +produces + # iftmp.2_12 = PHI <2147483647(3), iftmp.2_11(4)> +which causes the situation being tested to dissapear before we get to PRE. */ #if __SIZEOF_INT__ == 2 #define unsigned __UINT32_TYPE__ diff --git a/gcc/testsuite/gcc.dg/pr84131.c b/gcc/testsuite/gcc.dg/pr84131.c index 0ba9651..ced2e5d 100644 --- a/gcc/testsuite/gcc.dg/pr84131.c +++ b/gcc/testsuite/gcc.dg/pr84131.c @@ -1,7 +1,8 @@ /* PR 94131 - ICE on printf with a VLA string and -fno-tree-ccp -fno-tree-forwprop { dg-do compile } - { dg-options "-O1 -fno-tree-ccp -fno-tree-forwprop" } */ + { dg-options "-O1 -fno-tree-ccp -fno-tree-forwprop" } + { dg-require-effective-target alloca } */ void rv1 (int n) { diff --git a/gcc/testsuite/gcc.dg/pr86314.c b/gcc/testsuite/gcc.dg/pr86314.c index 8962a3c..565fb02 100644 --- a/gcc/testsuite/gcc.dg/pr86314.c +++ b/gcc/testsuite/gcc.dg/pr86314.c @@ -1,5 +1,5 @@ // PR target/86314 -// { dg-do run { target sync_int_long } } +// { dg-do run { target sync_int_long_stack } } // { dg-options "-O2" } __attribute__((noinline, noclone)) unsigned long diff --git a/gcc/testsuite/gcc.dg/pr87314-1.c b/gcc/testsuite/gcc.dg/pr87314-1.c index 9bc9056..0cb9c07 100644 --- a/gcc/testsuite/gcc.dg/pr87314-1.c +++ b/gcc/testsuite/gcc.dg/pr87314-1.c @@ -8,4 +8,6 @@ int h() { return "bye"=="helloooobye"+8; } /* { dg-final { scan-tree-dump-times "hello" 1 "original" } } */ /* The test in h() should be retained because the result depends on string merging. */ -/* { dg-final { scan-assembler "hellooo" } } */ +/* { dg-final { scan-assembler "hellooo" { target { ! nvptx*-*-* } } } } */ +/* { dg-final { scan-assembler "104, 101, 108, 108, 111, 111, 111" { target { nvptx*-*-* } } } } */ + diff --git a/gcc/testsuite/gcc.dg/pr87485.c b/gcc/testsuite/gcc.dg/pr87485.c index 7e09173..17d1c24 100644 --- a/gcc/testsuite/gcc.dg/pr87485.c +++ b/gcc/testsuite/gcc.dg/pr87485.c @@ -2,6 +2,7 @@ /* { dg-do compile { target int128 } } */ /* { dg-options "-O2 -fschedule-insns -fno-guess-branch-probability -fno-isolate-erroneous-paths-dereference -fno-omit-frame-pointer -fno-split-wide-types -fno-tree-ccp -fno-tree-sra" } */ /* { dg-additional-options "-fstack-protector-strong" { target fstack_protector } } */ +/* { dg-require-effective-target scheduling } */ int *a; diff --git a/gcc/testsuite/gcc.dg/pr88928.c b/gcc/testsuite/gcc.dg/pr88928.c index c0a1f76..0b6c1d7 100644 --- a/gcc/testsuite/gcc.dg/pr88928.c +++ b/gcc/testsuite/gcc.dg/pr88928.c @@ -3,4 +3,4 @@ struct a { } __attribute__((__packed__)); void c (struct a **); void d (const struct a *b) { c ((struct a **) b); } -/* { dg-warning "may result in an unaligned pointer value" "" { target *-*-* } .-1 } */ +/* { dg-warning "may result in an unaligned pointer value" "" { target { ! default_packed } } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr93986.c b/gcc/testsuite/gcc.dg/pr93986.c index bdbc192..0d533f4 100644 --- a/gcc/testsuite/gcc.dg/pr93986.c +++ b/gcc/testsuite/gcc.dg/pr93986.c @@ -1,6 +1,7 @@ /* PR tree-optimization/93986 - ICE in decompose, at wide-int.h:984 { dg-do compile } - { dg-options "-O1 -foptimize-strlen -ftree-slp-vectorize" } */ + { dg-options "-O1 -foptimize-strlen -ftree-slp-vectorize" } + { dg-require-effective-target alloca } */ int dd (void); diff --git a/gcc/testsuite/gcc.dg/pr94234-1.c b/gcc/testsuite/gcc.dg/pr94234-1.c new file mode 100644 index 0000000..d85563b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94234-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +typedef __INTPTR_TYPE__ ssize_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; + +ptrdiff_t foo (char *a, ssize_t n, ssize_t m) +{ + char *b1 = a + 8 * n; + char *b2 = a + 8 * (n + 1); + + return (b1 + m) - (b2 + m); +} + +/* { dg-final { scan-tree-dump-times "return -8;" 1 "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94234-2.c b/gcc/testsuite/gcc.dg/pr94234-2.c new file mode 100644 index 0000000..1f4b194 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94234-2.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +int use_fn (int a); + +int foo (int n) +{ + int b1 = 8 * (n + 1); + int b2 = 8 * n; + + use_fn (b1 ^ b2); + + return b1 - b2; +} + +unsigned goo (unsigned m_param, unsigned n_param) +{ + unsigned b1 = m_param * (n_param + 2); + unsigned b2 = m_param * (n_param + 1); + + use_fn (b1 ^ b2); + + return b1 - b2; +} + +unsigned hoo (unsigned k_param) +{ + unsigned b1 = k_param * 28; + unsigned b2 = k_param * 15; + unsigned b3 = k_param * 12; + + use_fn (b1 ^ b2 ^ b3); + + return (b1 - b2) - b3; +} + +/* { dg-final { scan-tree-dump-times "return 8;" 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times "return m_param" 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-not "return k_param" "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94234-3.c b/gcc/testsuite/gcc.dg/pr94234-3.c new file mode 100644 index 0000000..9bb9b46 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94234-3.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; + +ptrdiff_t foo1 (char *a, size_t n) +{ + char *b1 = a + 8 * n; + char *b2 = a + 8 * (n - 1); + + return b1 - b2; +} + +int use_ptr (char *a, char *b); + +ptrdiff_t foo2 (char *a, size_t n) +{ + char *b1 = a + 8 * (n - 1); + char *b2 = a + 8 * n; + + use_ptr (b1, b2); + + return b1 - b2; +} + +int use_int (int i); + +unsigned goo (unsigned m_param, unsigned n_param) +{ + unsigned b1 = m_param * (n_param + 2); + unsigned b2 = m_param * (n_param + 1); + int r = (int)(b1) - (int)(b2); + + use_int (r); + + return r; +} + +/* { dg-final { scan-tree-dump-times "return 8;" 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times "return -8;" 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times "return m_param" 1 "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-1.c b/gcc/testsuite/gcc.dg/pr94600-1.c new file mode 100644 index 0000000..149e4f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2" } */ +/* { dg-additional-options "-DALIGN_VAR" { target { ! non_strict_align } } } */ + +/* Assignments to a whole struct of suitable size (32 bytes) must not be + picked apart into field accesses. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0; + +static t0 a0[] +#ifdef ALIGN_VAR +__attribute__((aligned (4))) +#endif + = { + { .f0 = 7, .f1 = 99, .f3 = 1, }, + { .f0 = 7, .f1 = 251, .f3 = 1, }, + { .f0 = 8, .f1 = 127, .f3 = 5, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, +}; + +void +foo(void) +{ + __SIZE_TYPE__ i; + __SIZE_TYPE__ base = 0x000a0000; + for (i = 0; i < (sizeof (a0) / sizeof ((a0)[0])); i++) { + *(volatile t0 *) (base + 44 + i * 4) = a0[i]; + } +} + +/* The only volatile accesses should be the obvious writes. */ +/* { dg-final { scan-rtl-dump-times {\(mem/v} 6 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 6 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-2.c b/gcc/testsuite/gcc.dg/pr94600-2.c new file mode 100644 index 0000000..cb96cc9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-2.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2" } */ + +/* Unrolled version of pr94600-1.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0; + +void +bar(void) +{ + t0 a00 = { .f0 = 7, .f1 = 99, .f3 = 1, }; + t0 a01 = { .f0 = 7, .f1 = 251, .f3 = 1, }; + t0 a02 = { .f0 = 8, .f1 = 127, .f3 = 5, }; + t0 a03 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a04 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a05 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + __SIZE_TYPE__ base = 0x000a0000; + + *(volatile t0 *) ((base) + 44 + (0) * 4) = a00; + *(volatile t0 *) ((base) + 44 + (1) * 4) = a01; + *(volatile t0 *) ((base) + 44 + (2) * 4) = a02; + *(volatile t0 *) ((base) + 44 + (3) * 4) = a03; + *(volatile t0 *) ((base) + 44 + (4) * 4) = a04; + *(volatile t0 *) ((base) + 44 + (5) * 4) = a05; +} + +/* { dg-final { scan-rtl-dump-times {\(mem/v} 6 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 6 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-3.c b/gcc/testsuite/gcc.dg/pr94600-3.c new file mode 100644 index 0000000..2fce9f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-3.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2 -fno-unroll-loops" } */ +/* { dg-additional-options "-DALIGN_VAR" { target { ! non_strict_align } } } */ + +/* Same-address version of pr94600-1.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0; + +static t0 a0[] +#ifdef ALIGN_VAR +__attribute__((aligned (4))) +#endif + = { + { .f0 = 7, .f1 = 99, .f3 = 1, }, + { .f0 = 7, .f1 = 251, .f3 = 1, }, + { .f0 = 8, .f1 = 127, .f3 = 5, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, +}; + +void +foo(void) +{ + __SIZE_TYPE__ i; + __SIZE_TYPE__ base = 0x000a0000; + for (i = 0; i < (sizeof (a0) / sizeof ((a0)[0])); i++) { + *(volatile t0 *) (base + 44) = a0[i]; + } +} + +/* The loop isn't unrolled. */ +/* { dg-final { scan-rtl-dump-times {\(mem/v} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 1 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-4.c b/gcc/testsuite/gcc.dg/pr94600-4.c new file mode 100644 index 0000000..c2901ab --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-4.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2" } */ + +/* Unrolled version of pr94600-2.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0; + +void +bar(void) +{ + t0 a00 = { .f0 = 7, .f1 = 99, .f3 = 1, }; + t0 a01 = { .f0 = 7, .f1 = 251, .f3 = 1, }; + t0 a02 = { .f0 = 8, .f1 = 127, .f3 = 5, }; + t0 a03 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a04 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a05 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + __SIZE_TYPE__ base = 0x000a0000; + + *(volatile t0 *) ((base) + 44) = a00; + *(volatile t0 *) ((base) + 44) = a01; + *(volatile t0 *) ((base) + 44) = a02; + *(volatile t0 *) ((base) + 44) = a03; + *(volatile t0 *) ((base) + 44) = a04; + *(volatile t0 *) ((base) + 44) = a05; +} + +/* { dg-final { scan-rtl-dump-times {\(mem/v} 6 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 6 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-5.c b/gcc/testsuite/gcc.dg/pr94600-5.c new file mode 100644 index 0000000..3be0249 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-5.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2 -fno-unroll-loops" } */ + +/* Target-as-parameter version of pr94600-1.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0 __attribute__((__aligned__(4))); + +static t0 a0[] = { + { .f0 = 7, .f1 = 99, .f3 = 1, }, + { .f0 = 7, .f1 = 251, .f3 = 1, }, + { .f0 = 8, .f1 = 127, .f3 = 5, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, +}; + +void +foo(volatile t0 *b) +{ + __SIZE_TYPE__ i; + for (i = 0; i < (sizeof (a0) / sizeof ((a0)[0])); i++) { + b[i+11] = a0[i]; + } +} + +/* The loop isn't unrolled. */ +/* { dg-final { scan-rtl-dump-times {\(mem/v} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 1 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-6.c b/gcc/testsuite/gcc.dg/pr94600-6.c new file mode 100644 index 0000000..c247afe --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-6.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2" } */ + +/* Target-as-parameter version of pr94600-2.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0 __attribute__((__aligned__(4))); + +void +bar(volatile t0 *b) +{ + t0 a00 = { .f0 = 7, .f1 = 99, .f3 = 1, }; + t0 a01 = { .f0 = 7, .f1 = 251, .f3 = 1, }; + t0 a02 = { .f0 = 8, .f1 = 127, .f3 = 5, }; + t0 a03 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a04 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a05 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + + b[11+0] = a00; + b[11+1] = a01; + b[11+2] = a02; + b[11+3] = a03; + b[11+4] = a04; + b[11+5] = a05; +} + +/* { dg-final { scan-rtl-dump-times {\(mem/v} 6 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 6 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-7.c b/gcc/testsuite/gcc.dg/pr94600-7.c new file mode 100644 index 0000000..81c5231 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-7.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2 -fno-unroll-loops" } */ + +/* Target-as-parameter version of pr94600-3.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0 __attribute__((__aligned__(4))); + +static t0 a0[] = { + { .f0 = 7, .f1 = 99, .f3 = 1, }, + { .f0 = 7, .f1 = 251, .f3 = 1, }, + { .f0 = 8, .f1 = 127, .f3 = 5, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, + { .f0 = 5, .f1 = 1, .f3 = 1, }, +}; + +void +foo(volatile t0 *b) +{ + __SIZE_TYPE__ i; + for (i = 0; i < (sizeof (a0) / sizeof ((a0)[0])); i++) { + b[11] = a0[i]; + } +} + +/* { dg-final { scan-rtl-dump-times {\(mem/v} 1 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 1 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr94600-8.c b/gcc/testsuite/gcc.dg/pr94600-8.c new file mode 100644 index 0000000..201b2add4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94600-8.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fdump-rtl-final -O2" } */ + +/* Unrolled version of pr94600-2.c. */ + +typedef struct { + unsigned int f0 : 4; + unsigned int f1 : 11; + unsigned int f2 : 10; + unsigned int f3 : 7; +} t0 __attribute__((__aligned__(4))); + +void +bar(volatile t0 *b) +{ + t0 a00 = { .f0 = 7, .f1 = 99, .f3 = 1, }; + t0 a01 = { .f0 = 7, .f1 = 251, .f3 = 1, }; + t0 a02 = { .f0 = 8, .f1 = 127, .f3 = 5, }; + t0 a03 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a04 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + t0 a05 = { .f0 = 5, .f1 = 1, .f3 = 1, }; + + b[11] = a00; + b[11] = a01; + b[11] = a02; + b[11] = a03; + b[11] = a04; + b[11] = a05; +} + +/* { dg-final { scan-rtl-dump-times {\(mem/v} 6 "final" } } */ +/* { dg-final { scan-rtl-dump-times {\(set \(mem/v} 6 "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr95133.c b/gcc/testsuite/gcc.dg/pr95133.c index 523deca..5e23359 100644 --- a/gcc/testsuite/gcc.dg/pr95133.c +++ b/gcc/testsuite/gcc.dg/pr95133.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O3" } */ +/* { dg-require-effective-target label_values } */ extern int a[16]; void f (int *ip, int x) diff --git a/gcc/testsuite/gcc.dg/pr95857.c b/gcc/testsuite/gcc.dg/pr95857.c index 41506ea..afd6f46 100644 --- a/gcc/testsuite/gcc.dg/pr95857.c +++ b/gcc/testsuite/gcc.dg/pr95857.c @@ -1,6 +1,7 @@ /* PR tree-optimization/95857 */ /* { dg-do compile } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target label_values } */ struct E { int e; }; int bar (void), baz (void); diff --git a/gcc/testsuite/gcc.dg/pr96298.c b/gcc/testsuite/gcc.dg/pr96298.c new file mode 100644 index 0000000..8f825751 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96298.c @@ -0,0 +1,18 @@ +/* PR rtl-optimization/96298 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-tree-forwprop" } */ + +typedef unsigned char __attribute__ ((__vector_size__ (8))) v64u8; + +v64u8 a; + +int +main (void) +{ + v64u8 x = (a - 1) ^ -a; + for (unsigned i = 0; i < sizeof (x); i++) + if (x[i] != 0xff) + __builtin_abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/pr96335.c b/gcc/testsuite/gcc.dg/pr96335.c new file mode 100644 index 0000000..ab243b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96335.c @@ -0,0 +1,12 @@ +/* PR middle-end/96335 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void bar (int, void *) __attribute__((__access__(__read_only__, 2))); + +void +foo (void *x) +{ + void (*fn) () = bar; + fn (0, x); +} diff --git a/gcc/testsuite/gcc.dg/pr96370.c b/gcc/testsuite/gcc.dg/pr96370.c new file mode 100644 index 0000000..b939b21 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96370.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target dfp } } */ +/* { dg-options "-O2 -ffast-math" } */ + +void c(_Decimal128); +void a(_Decimal128 b) +{ + c(-b * b); +} diff --git a/gcc/testsuite/gcc.dg/pr96377-1.c b/gcc/testsuite/gcc.dg/pr96377-1.c new file mode 100644 index 0000000..75b0c96 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96377-1.c @@ -0,0 +1,32 @@ +/* { dg-options "-fno-lax-vector-conversions -Wno-psabi" } */ +/* { dg-message "use '-flax-vector-conversions' to permit conversions" "" { target *-*-* } 0 } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); + +struct s { v8hi x; v4si y; }; +union u1 { v8hi x; v4si y; }; +union u2 { v4si s; v8hi y; }; + +void +foo (v4si i, v8hi h) +{ + struct s x1 = { i, i }; // { dg-error "incompatible types when initializing type '__vector" } + struct s x2 = { h, h }; // { dg-error "incompatible types" } + struct s x3 = { i, h }; // { dg-error "incompatible types" } + struct s x4 = { h, i }; + + union u1 y1 = { i }; // { dg-error "incompatible types" } + union u1 y2 = { h }; + union u2 y3 = { i }; + union u2 y4 = { h }; // { dg-error "incompatible types" } + + v4si z1[] = { i, i }; + v4si z2[] = { i, h }; // { dg-error "incompatible types" } + v4si z3[] = { h, i }; // { dg-error "incompatible types" } + v4si z4[] = { h, h }; // { dg-error "incompatible types" } + v8hi z5[] = { i, i }; // { dg-error "incompatible types" } + v8hi z6[] = { i, h }; // { dg-error "incompatible types" } + v8hi z7[] = { h, i }; // { dg-error "incompatible types" } + v8hi z8[] = { h, h }; +} diff --git a/gcc/testsuite/gcc.dg/pr96377-2.c b/gcc/testsuite/gcc.dg/pr96377-2.c new file mode 100644 index 0000000..8355040 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96377-2.c @@ -0,0 +1,31 @@ +/* { dg-options "-flax-vector-conversions -Wno-psabi" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); + +struct s { v8hi x; v4si y; }; +union u1 { v8hi x; v4si y; }; +union u2 { v4si s; v8hi y; }; + +void +foo (v4si i, v8hi h) +{ + struct s x1 = { i, i }; + struct s x2 = { h, h }; + struct s x3 = { i, h }; + struct s x4 = { h, i }; + + union u1 y1 = { i }; + union u1 y2 = { h }; + union u2 y3 = { i }; + union u2 y4 = { h }; + + v4si z1[] = { i, i }; + v4si z2[] = { i, h }; + v4si z3[] = { h, i }; + v4si z4[] = { h, h }; + v8hi z5[] = { i, i }; + v8hi z6[] = { i, h }; + v8hi z7[] = { h, i }; + v8hi z8[] = { h, h }; +} diff --git a/gcc/testsuite/gcc.dg/pr96377-3.c b/gcc/testsuite/gcc.dg/pr96377-3.c new file mode 100644 index 0000000..66dce01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96377-3.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-fno-lax-vector-conversions" } */ +/* { dg-message "use '-flax-vector-conversions' to permit conversions" "" { target *-*-* } 0 } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); + +struct s { v8hi x; v4si y; }; +union u1 { v8hi x; v4si y; }; +union u2 { v4si s; v8hi y; }; + +void +foo (__Int32x4_t i, __Int16x8_t h) +{ + struct s x1 = { i, i }; // { dg-error "incompatible types when initializing type '__vector" } + struct s x2 = { h, h }; // { dg-error "incompatible types" } + struct s x3 = { i, h }; // { dg-error "incompatible types" } + struct s x4 = { h, i }; + + union u1 y1 = { i }; // { dg-error "incompatible types" } + union u1 y2 = { h }; + union u2 y3 = { i }; + union u2 y4 = { h }; // { dg-error "incompatible types" } + + v4si z1[] = { i, i }; + v4si z2[] = { i, h }; // { dg-error "incompatible types" } + v4si z3[] = { h, i }; // { dg-error "incompatible types" } + v4si z4[] = { h, h }; // { dg-error "incompatible types" } + v8hi z5[] = { i, i }; // { dg-error "incompatible types" } + v8hi z6[] = { i, h }; // { dg-error "incompatible types" } + v8hi z7[] = { h, i }; // { dg-error "incompatible types" } + v8hi z8[] = { h, h }; +} diff --git a/gcc/testsuite/gcc.dg/pr96377-4.c b/gcc/testsuite/gcc.dg/pr96377-4.c new file mode 100644 index 0000000..f7aaf49 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96377-4.c @@ -0,0 +1,32 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-flax-vector-conversions" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); + +struct s { v8hi x; v4si y; }; +union u1 { v8hi x; v4si y; }; +union u2 { v4si s; v8hi y; }; + +void +foo (__Int32x4_t i, __Int16x8_t h) +{ + struct s x1 = { i, i }; + struct s x2 = { h, h }; + struct s x3 = { i, h }; + struct s x4 = { h, i }; + + union u1 y1 = { i }; + union u1 y2 = { h }; + union u2 y3 = { i }; + union u2 y4 = { h }; + + v4si z1[] = { i, i }; + v4si z2[] = { i, h }; + v4si z3[] = { h, i }; + v4si z4[] = { h, h }; + v8hi z5[] = { i, i }; + v8hi z6[] = { i, h }; + v8hi z7[] = { h, i }; + v8hi z8[] = { h, h }; +} diff --git a/gcc/testsuite/gcc.dg/pr96377-5.c b/gcc/testsuite/gcc.dg/pr96377-5.c new file mode 100644 index 0000000..3d0c24b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96377-5.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-fno-lax-vector-conversions" } */ +/* { dg-message "use '-flax-vector-conversions' to permit conversions" "" { target *-*-* } 0 } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); + +struct s { __Int16x8_t x; __Int32x4_t y; }; +union u1 { __Int16x8_t x; __Int32x4_t y; }; +union u2 { __Int32x4_t s; __Int16x8_t y; }; + +void +foo (v4si i, v8hi h) +{ + struct s x1 = { i, i }; // { dg-error "incompatible types when initializing type '__Int16x8_t" } + struct s x2 = { h, h }; // { dg-error "incompatible types" } + struct s x3 = { i, h }; // { dg-error "incompatible types" } + struct s x4 = { h, i }; + + union u1 y1 = { i }; // { dg-error "incompatible types" } + union u1 y2 = { h }; + union u2 y3 = { i }; + union u2 y4 = { h }; // { dg-error "incompatible types" } + + v4si z1[] = { i, i }; + v4si z2[] = { i, h }; // { dg-error "incompatible types" } + v4si z3[] = { h, i }; // { dg-error "incompatible types" } + v4si z4[] = { h, h }; // { dg-error "incompatible types" } + v8hi z5[] = { i, i }; // { dg-error "incompatible types" } + v8hi z6[] = { i, h }; // { dg-error "incompatible types" } + v8hi z7[] = { h, i }; // { dg-error "incompatible types" } + v8hi z8[] = { h, h }; +} diff --git a/gcc/testsuite/gcc.dg/pr96377-6.c b/gcc/testsuite/gcc.dg/pr96377-6.c new file mode 100644 index 0000000..165327f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96377-6.c @@ -0,0 +1,32 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-flax-vector-conversions" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); + +struct s { __Int16x8_t x; __Int32x4_t y; }; +union u1 { __Int16x8_t x; __Int32x4_t y; }; +union u2 { __Int32x4_t s; __Int16x8_t y; }; + +void +foo (v4si i, v8hi h) +{ + struct s x1 = { i, i }; + struct s x2 = { h, h }; + struct s x3 = { i, h }; + struct s x4 = { h, i }; + + union u1 y1 = { i }; + union u1 y2 = { h }; + union u2 y3 = { i }; + union u2 y4 = { h }; + + v4si z1[] = { i, i }; + v4si z2[] = { i, h }; + v4si z3[] = { h, i }; + v4si z4[] = { h, h }; + v8hi z5[] = { i, i }; + v8hi z6[] = { i, h }; + v8hi z7[] = { h, i }; + v8hi z8[] = { h, h }; +} diff --git a/gcc/testsuite/gcc.dg/pr96453.c b/gcc/testsuite/gcc.dg/pr96453.c new file mode 100644 index 0000000..f758e7e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96453.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-Og -fno-early-inlining -fno-tree-ccp -fno-tree-dce" } */ +/* { dg-additional-options "-mavx -mno-sse4.2" { target x86_64-*-* i?86-*-* } } */ + +typedef int __attribute__ ((__vector_size__ (16))) U; +typedef unsigned long __attribute__ ((__vector_size__ (16))) V; + +static inline int +bar (unsigned long e, V f) +{ + V g = f != e; + (union {U b;}){(U) g}; +} + +void +foo (void) +{ + int j = bar (8, (V) { }); + for (unsigned i;; i[&j]) + ; +} diff --git a/gcc/testsuite/gcc.dg/pr96466.c b/gcc/testsuite/gcc.dg/pr96466.c new file mode 100644 index 0000000..a8840f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96466.c @@ -0,0 +1,19 @@ +/* PR tree-optimization/96466 */ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-Og -finline-functions-called-once -fno-tree-ccp" } */ + +typedef unsigned long __attribute__ ((__vector_size__ (8))) V; + +V +bar (unsigned long x, V v) +{ + v &= x >= v; + return (V) v; +} + +V +foo (void) +{ + return bar (5, (V) 4441221375); +} diff --git a/gcc/testsuite/gcc.dg/pr96514.c b/gcc/testsuite/gcc.dg/pr96514.c new file mode 100644 index 0000000..891b4da --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96514.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ + +int __attribute__ ((pure, returns_twice)) +r0 (void); + +void +vy (int t7) +{ + while (t7 == 0) + r0 (); +} + +void +qw (int t7) +{ + vy (t7); + + if (0) + r0 (); +} + +void __attribute__ ((simd)) +un (int t7) +{ + qw (t7); + qw (t7); +} diff --git a/gcc/testsuite/gcc.dg/pr96558.c b/gcc/testsuite/gcc.dg/pr96558.c new file mode 100644 index 0000000..2f5739e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96558.c @@ -0,0 +1,32 @@ +/* PR target/96558 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2 -fno-expensive-optimizations -fno-gcse" } */ + +int ky; +long int h1; +__int128 f1; + +int +sd (void); + +int __attribute__ ((simd)) +i8 (void) +{ + __int128 vh; + + if (sd () == 0) + h1 = 0; + + do + { + long int lf = (long int) f1 ? h1 : 0; + + ky += lf; + vh = lf | f1; + f1 = 1; + } + while (vh < (f1 ^ 2)); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/pr96579.c b/gcc/testsuite/gcc.dg/pr96579.c new file mode 100644 index 0000000..982f8ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96579.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target dfp } } */ +/* { dg-options "-O -fno-tree-forwprop -ffast-math -fno-tree-vrp" } */ + +#include "pr96370.c" diff --git a/gcc/testsuite/gcc.dg/pr96818.c b/gcc/testsuite/gcc.dg/pr96818.c new file mode 100644 index 0000000..ea2ac54 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96818.c @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O2" } + +int a, b, c; +void d() { + unsigned short e; + while (b) + ; + e = (e + 5) / a; + switch (e) + case 0: + case 3: + c = a; +} diff --git a/gcc/testsuite/gcc.dg/pr96931.c b/gcc/testsuite/gcc.dg/pr96931.c new file mode 100644 index 0000000..94b8a11 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96931.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fpredictive-commoning -fno-tree-loop-im" } */ + +int bl; + +void +p3 (void); + +void __attribute__ ((returns_twice)) +ie (void) +{ + p3 (); + + bl = 0; + for (;;) + ++bl; + + ie (); +} diff --git a/gcc/testsuite/gcc.dg/pr97078.c b/gcc/testsuite/gcc.dg/pr97078.c new file mode 100644 index 0000000..997d5fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97078.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffloat-store" } */ + +extern void foo (long double); + +void bar (long double d) +{ + foo (d); +} diff --git a/gcc/testsuite/gcc.dg/pr97192.c b/gcc/testsuite/gcc.dg/pr97192.c new file mode 100644 index 0000000..16647ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97192.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftracer" } */ +/* { dg-additional-options "-mavx512vl" { target x86_64-*-* i?86-*-* } } */ + +typedef int __attribute__ ((__vector_size__ (32))) V; + +int a, b; +V v; + +int +foo (void) +{ + b -= 4 - !a; + V u = 0 != v == a; + return u[0]; +} diff --git a/gcc/testsuite/gcc.dg/pr97238.c b/gcc/testsuite/gcc.dg/pr97238.c new file mode 100644 index 0000000..746e93a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97238.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wno-psabi -w" } */ + +typedef int __attribute__ ((__vector_size__ (8))) V; +int b, c, e; +V d; + +V +foo (void) +{ + return (b || e) | c > d | ((b || e) | c > d); +} diff --git a/gcc/testsuite/gcc.dg/pr97315-2.c b/gcc/testsuite/gcc.dg/pr97315-2.c new file mode 100644 index 0000000..5dd1b6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97315-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void c(int); + +int a; +void b() +{ + if (a >= 2147483647) + c(a + 1); +} diff --git a/gcc/testsuite/gcc.dg/pr97317.c b/gcc/testsuite/gcc.dg/pr97317.c new file mode 100644 index 0000000..f07327a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97317.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct a { + unsigned c : 17; +}; +struct a b; +int d(void) { + short e = b.c; + return e ? 0 : b.c; +} diff --git a/gcc/testsuite/gcc.dg/pr97322.c b/gcc/testsuite/gcc.dg/pr97322.c new file mode 100644 index 0000000..f253c0d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97322.c @@ -0,0 +1,17 @@ +/* PR target/97322 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void +foo (unsigned long long x, unsigned long long *y) +{ + y[0] = x / 10; + y[1] = x % 10; +} + +void +bar (unsigned int x, unsigned int *y) +{ + y[0] = x / 10; + y[1] = x % 10; +} diff --git a/gcc/testsuite/gcc.dg/pr97357.c b/gcc/testsuite/gcc.dg/pr97357.c new file mode 100644 index 0000000..6b391b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97357.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ +/* { dg-require-effective-target indirect_jumps } */ + +#include <setjmp.h> +#include <stdlib.h> + +void * my_malloc (size_t size); + +typedef struct glk { + struct glk *nxt; +} glk; + +typedef struct Lock +{ + glk ByteLock; +} Lock; + +static Lock *l, *lk; + +void bytelocks(glk *rethead, jmp_buf jb) +{ + glk *cur, *cur_lk; + + if (( setjmp (jb)) == 0) + for (cur = &l->ByteLock; cur != ((glk *)0) ; cur = (cur)->nxt) + for (cur_lk = &lk->ByteLock; cur_lk != ((glk *)0); cur_lk = cur_lk->nxt) + { + glk *retrng; + + if(!rethead) + rethead = (glk *) my_malloc (sizeof(glk)); + retrng = (glk *) my_malloc (sizeof(glk)); + + retrng->nxt = rethead; + } + + return; +} diff --git a/gcc/testsuite/gcc.dg/pr97359.c b/gcc/testsuite/gcc.dg/pr97359.c new file mode 100644 index 0000000..142542e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97359.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -w" } */ + +typedef unsigned int uint32_t; +int a; +void b(uint32_t c) { + uint32_t *d = &c; + for (; a;) + for (;; (*d %= a) / (*d > 1 > (c > 0)) ?: d) + ; +} diff --git a/gcc/testsuite/gcc.dg/pr97371.c b/gcc/testsuite/gcc.dg/pr97371.c new file mode 100644 index 0000000..ffefad0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97371.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -w" } */ + +int a, b; +void c() { + if (b >> 38) + a = b; +} diff --git a/gcc/testsuite/gcc.dg/pubtypes-2.c b/gcc/testsuite/gcc.dg/pubtypes-2.c index 6669f3d..116e348 100644 --- a/gcc/testsuite/gcc.dg/pubtypes-2.c +++ b/gcc/testsuite/gcc.dg/pubtypes-2.c @@ -2,7 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler "long+\[ \t\]+0x12e+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ +/* { dg-final { scan-assembler {long+[ \t]+0x14d+[ \t]+[#;]+[ \t]+Pub Info Length} } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ diff --git a/gcc/testsuite/gcc.dg/pubtypes-3.c b/gcc/testsuite/gcc.dg/pubtypes-3.c index 345e4ed..3fb3468 100644 --- a/gcc/testsuite/gcc.dg/pubtypes-3.c +++ b/gcc/testsuite/gcc.dg/pubtypes-3.c @@ -2,7 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler "long+\[ \t\]+0x12e+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ +/* { dg-final { scan-assembler {long+[ \t]+0x14d+[ \t]+[#;]+[ \t]+Pub Info Length} } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "\"list_name_type\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ diff --git a/gcc/testsuite/gcc.dg/pubtypes-4.c b/gcc/testsuite/gcc.dg/pubtypes-4.c index da2f9b0..83fba8d 100644 --- a/gcc/testsuite/gcc.dg/pubtypes-4.c +++ b/gcc/testsuite/gcc.dg/pubtypes-4.c @@ -2,7 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler "long+\[ \t\]+0x165+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ +/* { dg-final { scan-assembler {long+[ \t]+0x184+[ \t]+[#;]+[ \t]+Pub Info Length} } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler "\"list_name_type\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ diff --git a/gcc/testsuite/gcc.dg/redecl-4.c b/gcc/testsuite/gcc.dg/redecl-4.c index 8f12488..2c214bb 100644 --- a/gcc/testsuite/gcc.dg/redecl-4.c +++ b/gcc/testsuite/gcc.dg/redecl-4.c @@ -15,7 +15,7 @@ f (void) /* Should get format warnings even though the built-in declaration isn't "visible". */ printf ( - "%s", 1); /* { dg-warning "8:format" } */ + "%s", 1); /* { dg-warning "15:format" } */ /* The type of strcmp here should have no prototype. */ if (0) strcmp (1); diff --git a/gcc/testsuite/gcc.dg/sinatan-2.c b/gcc/testsuite/gcc.dg/sinatan-2.c index 8e7ea3c..64d6d30 100644 --- a/gcc/testsuite/gcc.dg/sinatan-2.c +++ b/gcc/testsuite/gcc.dg/sinatan-2.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-Ofast -fdump-tree-optimized" } */ +/* { dg-require-effective-target c99_runtime } */ extern float sinf (float); extern float cosf (float); diff --git a/gcc/testsuite/gcc.dg/sinhovercosh-1.c b/gcc/testsuite/gcc.dg/sinhovercosh-1.c index d41093f..564d3c5 100644 --- a/gcc/testsuite/gcc.dg/sinhovercosh-1.c +++ b/gcc/testsuite/gcc.dg/sinhovercosh-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-Ofast -fdump-tree-optimized" } */ +/* { dg-require-effective-target c99_runtime } */ extern float sinhf (float); extern float coshf (float); diff --git a/gcc/testsuite/gcc.dg/spellcheck-inttypes.c b/gcc/testsuite/gcc.dg/spellcheck-inttypes.c index 1146a7c..611d7f0 100644 --- a/gcc/testsuite/gcc.dg/spellcheck-inttypes.c +++ b/gcc/testsuite/gcc.dg/spellcheck-inttypes.c @@ -1,7 +1,7 @@ /* { dg-options "-std=c99" } */ /* Prevent AIX from implicitly including inttypes.h. */ #ifdef _AIX -#define _H_INTTYPES_TYPE_TS +#define _STD_TYPES_T #endif #include <stdio.h> #include <stdint.h> diff --git a/gcc/testsuite/gcc.dg/store_merging_31.c b/gcc/testsuite/gcc.dg/store_merging_31.c new file mode 100644 index 0000000..32c21eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/store_merging_31.c @@ -0,0 +1,27 @@ +/* PR tree-optimization/97053 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +struct S { short a; char b[9]; int c; char d; int e; }; + +__attribute__((noipa)) void +foo (char *x, char *y) +{ + if (__builtin_strcmp (x, "ABCDXXXX") != 0 + || __builtin_strcmp (y, "ABCDXXXX") != 0) + __builtin_abort (); +} + +int +main () +{ + char a[9] = "XXXXXXXX"; + struct S b = {}; + __builtin_memcpy (a, "ABCD", 4); + b.a = 5; + __builtin_memcpy (b.b, a, 8); + b.d = 'X'; + b.e = 1; + foo (a, b.b); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/store_merging_32.c b/gcc/testsuite/gcc.dg/store_merging_32.c new file mode 100644 index 0000000..8c90489 --- /dev/null +++ b/gcc/testsuite/gcc.dg/store_merging_32.c @@ -0,0 +1,129 @@ +/* PR tree-optimization/97053 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-tree-dse" } */ + +struct __attribute__((packed, may_alias)) S { long long s; }; +struct __attribute__((packed, may_alias)) T { short t; }; + +__attribute__((noipa)) void +test (char *p, char *q, int s) +{ + if ((s & 1) == 0) + { + if (*(short __attribute__((may_alias)) *) &p[sizeof (short)] + != *(short __attribute__((may_alias)) *) &q[sizeof (short)] + || (((struct S __attribute__((may_alias)) *) &p[1])->s + != ((struct S __attribute__((may_alias)) *) &q[1])->s) + || (*(short __attribute__((may_alias)) *) &p[2 * sizeof (short)] + != *(short __attribute__((may_alias)) *) &q[2 * sizeof (short)])) + __builtin_abort (); + } + else + { + if (*(short __attribute__((may_alias)) *) &p[sizeof (short)] + != *(short __attribute__((may_alias)) *) &q[sizeof (short)] + || (((struct S __attribute__((may_alias)) *) &p[1])->s + != ((struct S __attribute__((may_alias)) *) &q[1])->s) + || (((struct T __attribute__((may_alias)) *) &p[2 * sizeof (short) - 1])->t + != ((struct T __attribute__((may_alias)) *) &q[2 * sizeof (short) - 1])->t) + || p[3 * sizeof (short) - 2] != q[3 * sizeof (short) - 2]) + __builtin_abort (); + } +} + +__attribute__((noipa)) void +foo (long long *p, char *q, char *r, char *s) +{ + char a[64] __attribute__((aligned (__alignof (short)))); + *(short __attribute__((may_alias)) *) &a[sizeof (short)] = 1; + ((struct S __attribute__((may_alias)) *) &a[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &a[2 * sizeof (short)] = 2; + *(short __attribute__((may_alias)) *) &q[sizeof (short)] = 1; + ((struct S __attribute__((may_alias)) *) &r[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &s[2 * sizeof (short)] = 2; + test (a, q, 0); +} + +__attribute__((noipa)) void +bar (long long *p, char *q, char *r, char *s, char *t) +{ + char a[64] __attribute__((aligned (__alignof (short)))); + *(short __attribute__((may_alias)) *) &a[sizeof (short)] = 1; + ((struct S __attribute__((may_alias)) *) &a[1])->s = p[0]; + ((struct T __attribute__((may_alias)) *) &a[2 * sizeof (short) - 1])->t = 2; + a[3 * sizeof (short) - 2] = 3; + *(short __attribute__((may_alias)) *) &q[sizeof (short)] = 1; + ((struct S __attribute__((may_alias)) *) &r[1])->s = p[0]; + ((struct T __attribute__((may_alias)) *) &s[2 * sizeof (short) - 1])->t = 2; + t[3 * sizeof (short) - 2] = 3; + test (a, q, 1); +} + +__attribute__((noipa)) void +baz (long long *p, char *q, char *r, char *s) +{ + char a[64] __attribute__((aligned (__alignof (short)))); + *(short __attribute__((may_alias)) *) &a[2 * sizeof (short)] = 2; + ((struct S __attribute__((may_alias)) *) &a[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &a[sizeof (short)] = 1; + *(short __attribute__((may_alias)) *) &q[2 * sizeof (short)] = 2; + ((struct S __attribute__((may_alias)) *) &r[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &s[sizeof (short)] = 1; + test (a, q, 2); +} + +__attribute__((noipa)) void +qux (long long *p, char *q, char *r, char *s, char *t) +{ + char a[64] __attribute__((aligned (__alignof (short)))); + *(short __attribute__((may_alias)) *) &a[2 * sizeof (short) - 1] = 2; + ((struct S __attribute__((may_alias)) *) &a[1])->s = p[0]; + a[3 * sizeof (short) - 2] = 3; + *(short __attribute__((may_alias)) *) &a[sizeof (short)] = 1; + ((struct T __attribute__((may_alias)) *) &q[2 * sizeof (short) - 1])->t = 2; + ((struct S __attribute__((may_alias)) *) &r[1])->s = p[0]; + s[3 * sizeof (short) - 2] = 3; + ((struct T __attribute__((may_alias)) *) &t[sizeof (short)])->t = 1; + test (a, q, 3); +} + +__attribute__((noipa)) void +corge (long long *p, char *q, char *r, char *s, short u[3]) +{ + char a[64] __attribute__((aligned (__alignof (short)))); + *(short __attribute__((may_alias)) *) &a[2 * sizeof (short)] = u[2]; + ((struct S __attribute__((may_alias)) *) &a[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &a[sizeof (short)] = u[1]; + *(short __attribute__((may_alias)) *) &q[2 * sizeof (short)] = u[2]; + ((struct S __attribute__((may_alias)) *) &r[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &s[sizeof (short)] = u[1]; + test (a, q, 4); +} + +__attribute__((noipa)) void +garply (long long *p, char *q, char *r, char *s, short u[3]) +{ + char a[64] __attribute__((aligned (__alignof (short)))); + *(short __attribute__((may_alias)) *) &a[sizeof (short)] = u[1]; + ((struct S __attribute__((may_alias)) *) &a[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &a[2 * sizeof (short)] = u[2]; + *(short __attribute__((may_alias)) *) &s[sizeof (short)] = u[1]; + ((struct S __attribute__((may_alias)) *) &r[1])->s = p[0]; + *(short __attribute__((may_alias)) *) &q[2 * sizeof (short)] = u[2]; + test (a, q, 6); +} + +int +main () +{ + char a[64] __attribute__((aligned (__alignof (short)))); + long long p = -1LL; + short u[] = { 1, 2, 3 }; + foo (&p, &a[0], &a[0], &a[0]); + bar (&p, &a[0], &a[0], &a[0], &a[0]); + baz (&p, &a[0], &a[0], &a[0]); + qux (&p, &a[0], &a[0], &a[0], &a[0]); + corge (&p, &a[0], &a[0], &a[0], u); + garply (&p, &a[0], &a[0], &a[0], u); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/strcmpopt_10.c b/gcc/testsuite/gcc.dg/strcmpopt_10.c index 94fda59..d7f94ac 100644 --- a/gcc/testsuite/gcc.dg/strcmpopt_10.c +++ b/gcc/testsuite/gcc.dg/strcmpopt_10.c @@ -3,7 +3,7 @@ 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" } */ + { dg-options "-O2 -Wall -Wextra -Wno-stringop-overread -fdump-tree-optimized" } */ void init (void*); diff --git a/gcc/testsuite/gcc.dg/strcmpopt_12.c b/gcc/testsuite/gcc.dg/strcmpopt_12.c new file mode 100644 index 0000000..d8077b6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strcmpopt_12.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/96758 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int v = 1; + +int +main () +{ + const char *s = v ? "a" : "b"; + char x[5]; + char y[5] = "a\0a"; + __builtin_memcpy (x, y, sizeof (y)); + if (__builtin_strncmp (x, s, 4) != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/strlenopt-55.c b/gcc/testsuite/gcc.dg/strlenopt-55.c index ea6fb22..ca89ecd 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-55.c +++ b/gcc/testsuite/gcc.dg/strlenopt-55.c @@ -3,7 +3,8 @@ Verify that strlen() of braced initialized array is folded { dg-do compile } - { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */ + { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } + { dg-require-effective-target large_initializer } */ #include "strlenopt.h" diff --git a/gcc/testsuite/gcc.dg/strlenopt-57.c b/gcc/testsuite/gcc.dg/strlenopt-57.c index b7212bc..2f67bab 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-57.c +++ b/gcc/testsuite/gcc.dg/strlenopt-57.c @@ -21,9 +21,9 @@ void test_var_flexarray_cst_off (void) { /* Use arbitrary constants greater than 16 in case GCC ever starts unrolling strlen() calls with small array arguments. */ - a[0] = 17 < strlen (a0.a + 1); // { dg-warning "\\\[-Warray-bounds" } - a[1] = 19 < strlen (a1.a + 1); - a[2] = 23 < strlen (a9.a + 9); + a[0] = 17 < strlen (a0.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } + a[1] = 19 < strlen (a1.a + 1); // { dg-warning "\\\[-Wstringop-overread" } + a[2] = 23 < strlen (a9.a + 9); // { dg-warning "\\\[-Wstringop-overread" } a[3] = 29 < strlen (ax.a + 3); } diff --git a/gcc/testsuite/gcc.dg/strlenopt-83.c b/gcc/testsuite/gcc.dg/strlenopt-83.c index 5baafea..baa80cf 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-83.c +++ b/gcc/testsuite/gcc.dg/strlenopt-83.c @@ -1,7 +1,8 @@ /* PR tree-optimization/83821 - local aggregate initialization defeats strlen optimization { dg-do compile } - { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + { dg-options "-O2 -Wall -fdump-tree-optimized" } + { dg-require-effective-target alloca } */ #include "strlenopt.h" char *p_p2, *p_p5, *p_p9, *p_p14; diff --git a/gcc/testsuite/gcc.dg/strlenopt-84.c b/gcc/testsuite/gcc.dg/strlenopt-84.c index d6102b6..0c9da3c 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-84.c +++ b/gcc/testsuite/gcc.dg/strlenopt-84.c @@ -3,7 +3,8 @@ Verify that stores that overwrite an interior nul are correctly reflected in strlen results. { dg-do run } - { dg-options "-O2 -Wall" } */ + { dg-options "-O2 -Wall" } + { dg-require-effective-target alloca } */ #define false (0 == 1) #define true (0 == 0) diff --git a/gcc/testsuite/gcc.dg/strlenopt-91.c b/gcc/testsuite/gcc.dg/strlenopt-91.c index 2381d03..a305561 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-91.c +++ b/gcc/testsuite/gcc.dg/strlenopt-91.c @@ -1,7 +1,8 @@ /* PR tree-optimization/92412 - excessive errno aliasing assumption defeats optimization { dg-do compile } - { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + { dg-options "-O2 -Wall -fdump-tree-optimized" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/strncmp-3.c b/gcc/testsuite/gcc.dg/strncmp-3.c new file mode 100644 index 0000000..0e8101c --- /dev/null +++ b/gcc/testsuite/gcc.dg/strncmp-3.c @@ -0,0 +1,57 @@ +/* PR middle-end/95189 - memcmp being wrongly stripped like strcmp + { dg-do run } + { dg-options "-O2 -Wall" } */ + +#define AB_D "ab\0d" +#define ABCDEF_H "abcdef\0h" +#define ABCDEFGHIJKLMN_P "abcdefghijklmn\0p" + +char ab_d[] = AB_D; +char abcdef_h[] = ABCDEF_H; + +extern int strncmp (const char*, const char*, __SIZE_TYPE__); + +__attribute__((noipa)) void sink (const void *p, ...) { (void)&p; } + +#define strncmp(a, b, n) (sink (a, b), strncmp (a, b, n)) + +int main (void) +{ + int zero = 0; + + zero += strncmp (ab_d, AB_D, 1); + zero += strncmp (ab_d, AB_D, 2); + zero += strncmp (ab_d, AB_D, 3); + zero += strncmp (ab_d, AB_D, 4); + zero += strncmp (ab_d, AB_D, 5); + + zero += strncmp (ab_d, ABCDEF_H, 1); + zero += strncmp (ab_d, ABCDEF_H, 2); + + zero += strncmp (abcdef_h, AB_D, 2); + + zero += strncmp (abcdef_h, ABCDEF_H, 2); + zero += strncmp (abcdef_h, ABCDEF_H, 3); + zero += strncmp (abcdef_h, ABCDEF_H, 4); + zero += strncmp (abcdef_h, ABCDEF_H, 5); + zero += strncmp (abcdef_h, ABCDEF_H, 6); + zero += strncmp (abcdef_h, ABCDEF_H, 7); + zero += strncmp (abcdef_h, ABCDEF_H, 8); + zero += strncmp (abcdef_h, ABCDEF_H, 9); + + if (zero != 0) + __builtin_abort (); + + int neg = 0; + + neg -= strncmp (ab_d, ABCDEF_H, 3) < 0; + neg -= strncmp (ab_d, ABCDEF_H, 4) < 0; + neg -= strncmp (ab_d, ABCDEF_H, 5) < 0; + neg -= strncmp (ab_d, ABCDEF_H, 6) < 0; + neg -= strncmp (ab_d, ABCDEF_H, 7) < 0; + neg -= strncmp (ab_d, ABCDEF_H, 8) < 0; + neg -= strncmp (ab_d, ABCDEF_H, 9) < 0; + + if (neg != -7) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/tanhbysinh.c b/gcc/testsuite/gcc.dg/tanhbysinh.c index fde72c2..9dbe133 100644 --- a/gcc/testsuite/gcc.dg/tanhbysinh.c +++ b/gcc/testsuite/gcc.dg/tanhbysinh.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-Ofast -fdump-tree-optimized" } */ +/* { dg-require-effective-target c99_runtime } */ extern float sinhf (float); extern float tanhf (float); @@ -37,4 +38,4 @@ tanhbysinhl_ (long double x) /* {dg-final { scan-tree-dump-not "tanhl " "optimized" }} */ /* { dg-final { scan-tree-dump "cosh " "optimized" } } */ /* { dg-final { scan-tree-dump "coshf " "optimized" } } */ -/* { dg-final { scan-tree-dump "coshl " "optimized" } } */
\ No newline at end of file +/* { dg-final { scan-tree-dump "coshl " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tls/thr-cse-1.c b/gcc/testsuite/gcc.dg/tls/thr-cse-1.c index 84eedfd..7145671 100644 --- a/gcc/testsuite/gcc.dg/tls/thr-cse-1.c +++ b/gcc/testsuite/gcc.dg/tls/thr-cse-1.c @@ -4,6 +4,7 @@ registers and thus getting the counts wrong. */ /* { dg-additional-options "-mshort-calls" { target epiphany-*-* } } */ /* { dg-require-effective-target tls_emulated } */ +/* { dg-additional-options "-fdump-rtl-final-slim" { target nvptx-*-* } }*/ /* Test that we only get one call to emutls_get_address when CSE is active. Note that the var _must_ be initialized for the scan asm @@ -18,10 +19,12 @@ int foo (int b, int c, int d) return a; } -/* { dg-final { scan-assembler-not "emutls_get_address.*emutls_get_address.*" { target { ! { "*-wrs-vxworks" "*-*-darwin8" "hppa*-*-hpux*" "i?86-*-mingw*" "x86_64-*-mingw*" visium-*-* } } } } } */ +/* { dg-final { scan-assembler-not "emutls_get_address.*emutls_get_address.*" { target { ! { "*-wrs-vxworks" "*-*-darwin8" "hppa*-*-hpux*" "i?86-*-mingw*" "x86_64-*-mingw*" visium-*-* nvptx-*-* } } } } } */ /* { dg-final { scan-assembler-not "call\tL___emutls_get_address.stub.*call\tL___emutls_get_address.stub.*" { target "*-*-darwin8" } } } */ /* { dg-final { scan-assembler-not "(b,l|bl) __emutls_get_address.*(b,l|bl) __emutls_get_address.*" { target "hppa*-*-hpux*" } } } */ /* { dg-final { scan-assembler-not "tls_lookup.*tls_lookup.*" { target *-wrs-vxworks } } } */ /* { dg-final { scan-assembler-not "call\t___emutls_get_address.*call\t___emutls_get_address" { target "i?86-*-mingw*" } } } */ /* { dg-final { scan-assembler-not "call\t__emutls_get_address.*call\t__emutls_get_address" { target "x86_64-*-mingw*" } } } */ /* { dg-final { scan-assembler-not "%l __emutls_get_address.*%l __emutls_get_address" { target visium-*-* } } } */ + +/* { dg-final { scan-rtl-dump-times "emutls_get_address" 1 "final" { target nvptx-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/torture/20200727-0.c b/gcc/testsuite/gcc.dg/torture/20200727-0.c new file mode 100644 index 0000000..ab91568 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/20200727-0.c @@ -0,0 +1,82 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-g" } */ + +typedef long unsigned int size_t; +typedef signed int __int32_t; +typedef __int32_t int32_t; +typedef long int ptrdiff_t; +typedef enum { + BT_UNKNOWN = 0, BT_INTEGER, BT_LOGICAL, BT_REAL, BT_COMPLEX, BT_DERIVED, BT_CHARACTER, BT_CLASS, BT_PROCEDURE, BT_HOLLERITH, BT_VOID, BT_ASSUMED, BT_UNION, BT_BOZ } bt; +typedef int32_t GFC_INTEGER_4; +typedef ptrdiff_t index_type; +typedef size_t gfc_charlen_type; +typedef struct descriptor_dimension { + index_type _stride; + index_type lower_bound; + } descriptor_dimension; +typedef struct { + descriptor_dimension dim[15]; + } gfc_full_array_i4; +typedef void (*formatted_dtio)(void *, GFC_INTEGER_4 *, char *, gfc_full_array_i4 *, GFC_INTEGER_4 *, char *, gfc_charlen_type, gfc_charlen_type); +typedef enum { DECIMAL_POINT, DECIMAL_COMMA, DECIMAL_UNSPECIFIED } unit_decimal; +typedef struct st_parameter_dt { + union { + struct { + struct gfc_unit *current_unit; + unsigned namelist_mode : 1; + unsigned unit_is_internal : 1; + formatted_dtio fdtio_ptr; + } p; + } u; + } st_parameter_dt; +typedef struct gfc_unit { + int unit_number; + unit_decimal decimal_status; + int (*next_char_fn_ptr) (st_parameter_dt *); + void (*push_char_fn_ptr) (st_parameter_dt *, int); + } gfc_unit; +void read_real (st_parameter_dt *dtp) +{ + int c; + int seen_dp; + seen_dp = 0; + for (;;) + { + c = ((dtp)->u.p.current_unit->next_char_fn_ptr (dtp)); + if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA) + c = '.'; + switch (c) { + case '.': + if (seen_dp) goto bad_real; + seen_dp = 1; + ((dtp)->u.p.current_unit->push_char_fn_ptr (dtp, c)); + goto real_loop; + case 'E': + case 'e': + case 'D': + case 'd': + case 'Q': + case 'q': + goto exp1; + case '+': + case '-': + ((dtp)->u.p.current_unit->push_char_fn_ptr (dtp, 'e')); + goto got_repeat; + } + } +got_repeat: +real_loop: + for (;;) + { + c = ((dtp)->u.p.current_unit->next_char_fn_ptr (dtp)); + switch (c) { + case '.': + if (seen_dp) goto bad_real; + seen_dp = 1; + ((dtp)->u.p.current_unit->push_char_fn_ptr (dtp, c)); + } + } +exp1: +bad_real: + return; +} diff --git a/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c b/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c index 11367d1..12e6f25 100644 --- a/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c +++ b/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c @@ -1,6 +1,6 @@ /* Test -Wsizeof-pointer-memaccess warnings. */ /* { dg-do compile } */ -/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-truncation" } */ +/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread -Wno-stringop-truncation" } */ /* Test just twice, once with -O0 non-fortified, once with -O2 fortified. */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } */ /* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c index 707d539..1070230 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c @@ -4,6 +4,7 @@ /* { dg-require-effective-target int128 } */ /* { dg-require-effective-target fenv } */ /* { dg-options "-frounding-math" } */ +/* { dg-xfail-run-if "see PR80556 c63" { x86_64-*-darwin* i68?-*-darwin* } { "*" } { "" } } */ #include <fenv.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c index 09600f9..3facf32 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c @@ -4,6 +4,7 @@ /* { dg-require-effective-target int128 } */ /* { dg-require-effective-target fenv } */ /* { dg-options "-frounding-math" } */ +/* { dg-xfail-run-if "see PR80556 c63" { x86_64-*-darwin* i68?-*-darwin* } { "*" } { "" } } */ #include <fenv.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/torture/pr39074-2.c b/gcc/testsuite/gcc.dg/torture/pr39074-2.c index 0693f2d..7286a4f 100644 --- a/gcc/testsuite/gcc.dg/torture/pr39074-2.c +++ b/gcc/testsuite/gcc.dg/torture/pr39074-2.c @@ -30,5 +30,5 @@ int main() return 0; } -/* { dg-final { scan-tree-dump "y.._. = { i }" "alias" } } */ -/* { dg-final { scan-tree-dump "y.._., points-to NULL, points-to vars: { D..... }" "alias" } } */ +/* { dg-final { scan-tree-dump "y.\?.._. = { i }" "alias" } } */ +/* { dg-final { scan-tree-dump "y.\?.._., points-to NULL, points-to vars: { D..... }" "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr39074.c b/gcc/testsuite/gcc.dg/torture/pr39074.c index 54c444e..40ecdb9 100644 --- a/gcc/testsuite/gcc.dg/torture/pr39074.c +++ b/gcc/testsuite/gcc.dg/torture/pr39074.c @@ -29,5 +29,5 @@ int main() return 0; } -/* { dg-final { scan-tree-dump "y.._. = { i }" "alias" } } */ -/* { dg-final { scan-tree-dump "y.._., points-to NULL, points-to vars: { D..... }" "alias" } } */ +/* { dg-final { scan-tree-dump "y.\?.._. = { i }" "alias" } } */ +/* { dg-final { scan-tree-dump "y.\?.._., points-to NULL, points-to vars: { D..... }" "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr57147-1.c b/gcc/testsuite/gcc.dg/torture/pr57147-1.c index 5c2a30e..5fd4ee7 100644 --- a/gcc/testsuite/gcc.dg/torture/pr57147-1.c +++ b/gcc/testsuite/gcc.dg/torture/pr57147-1.c @@ -2,11 +2,11 @@ /* { dg-options "-fdump-tree-optimized" } */ /* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */ -struct __jmp_buf_tag {}; +struct __jmp_buf_tag { int mask; }; typedef struct __jmp_buf_tag jmp_buf[1]; extern int _setjmp (struct __jmp_buf_tag __env[1]); -jmp_buf g_return_jmp_buf; +extern jmp_buf g_return_jmp_buf; void SetNaClSwitchExpectations (void) { diff --git a/gcc/testsuite/gcc.dg/torture/pr57147-3.c b/gcc/testsuite/gcc.dg/torture/pr57147-3.c index 7a5926a..699c7f9 100644 --- a/gcc/testsuite/gcc.dg/torture/pr57147-3.c +++ b/gcc/testsuite/gcc.dg/torture/pr57147-3.c @@ -1,8 +1,7 @@ /* { dg-do compile } */ typedef char * ptr_t; -struct __jmp_buf_tag { -}; +struct __jmp_buf_tag { int mask; }; typedef struct __jmp_buf_tag sigjmp_buf[1]; sigjmp_buf GC_jmp_buf; int __sigsetjmp (sigjmp_buf, int); diff --git a/gcc/testsuite/gcc.dg/torture/pr59330.c b/gcc/testsuite/gcc.dg/torture/pr59330.c index 74b832e..536171e 100644 --- a/gcc/testsuite/gcc.dg/torture/pr59330.c +++ b/gcc/testsuite/gcc.dg/torture/pr59330.c @@ -1,4 +1,5 @@ /* { dg-do run } */ +/* { dg-skip-if "free inseparable from malloc when wrapped" { mmix-knuth-mmixware } } */ void free(void *ptr) { diff --git a/gcc/testsuite/gcc.dg/torture/pr92088-1.c b/gcc/testsuite/gcc.dg/torture/pr92088-1.c index b56f8ad..488bdcb 100644 --- a/gcc/testsuite/gcc.dg/torture/pr92088-1.c +++ b/gcc/testsuite/gcc.dg/torture/pr92088-1.c @@ -1,4 +1,5 @@ /* { dg-do run } */ +/* { dg-require-effective-target alloca } */ int __attribute__((noipa)) g (char *p) diff --git a/gcc/testsuite/gcc.dg/torture/pr92088-2.c b/gcc/testsuite/gcc.dg/torture/pr92088-2.c index a20a01c..6c9e504 100644 --- a/gcc/testsuite/gcc.dg/torture/pr92088-2.c +++ b/gcc/testsuite/gcc.dg/torture/pr92088-2.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target alloca } */ void foo(int n) { diff --git a/gcc/testsuite/gcc.dg/torture/pr93124.c b/gcc/testsuite/gcc.dg/torture/pr93124.c index 16bc8b5..0d361d8 100644 --- a/gcc/testsuite/gcc.dg/torture/pr93124.c +++ b/gcc/testsuite/gcc.dg/torture/pr93124.c @@ -1,4 +1,5 @@ /* { dg-additional-options "-fno-rerun-cse-after-loop -fno-guess-branch-probability -fno-tree-fre" } */ +/* { dg-require-effective-target alloca } */ int x; diff --git a/gcc/testsuite/gcc.dg/torture/pr94479.c b/gcc/testsuite/gcc.dg/torture/pr94479.c index 53285bb..3e40582 100644 --- a/gcc/testsuite/gcc.dg/torture/pr94479.c +++ b/gcc/testsuite/gcc.dg/torture/pr94479.c @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-require-stack-check "specific" } */ /* { dg-additional-options "-fstack-check -w" } */ +/* { dg-require-effective-target alloca } */ int a; struct b { diff --git a/gcc/testsuite/gcc.dg/torture/pr96130.c b/gcc/testsuite/gcc.dg/torture/pr96130.c new file mode 100644 index 0000000..f722b9a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr96130.c @@ -0,0 +1,26 @@ +/* PR ipa/96130 */ +/* { dg-do compile } */ + +struct S { unsigned j : 3; }; +int k, l, m; + +void +foo (struct S x) +{ + while (l != 5) + switch (x.j) + { + case 1: + case 3: + case 4: + case 6: + case 2: + case 5: + l = m; + case 7: + case 0: + k = 0; + default: + break; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr96133.c b/gcc/testsuite/gcc.dg/torture/pr96133.c index 8d051ce..ac31a71 100644 --- a/gcc/testsuite/gcc.dg/torture/pr96133.c +++ b/gcc/testsuite/gcc.dg/torture/pr96133.c @@ -1,7 +1,7 @@ /* { dg-do run } */ typedef int T; -static const T a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; +static const T a[2][3] __attribute__((aligned(2*sizeof(T)))) = { { 1, 2, 3 }, { 4, 5, 6 } }; typedef T v2 __attribute__((vector_size(2*sizeof(T)))); int diff --git a/gcc/testsuite/gcc.dg/torture/pr96349.c b/gcc/testsuite/gcc.dg/torture/pr96349.c new file mode 100644 index 0000000..4ce3949 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr96349.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ + +void __attribute__ ((returns_twice)) +gr (void); + +void +ib (void); + +void +zg (void); + +void +yw (int uz) +{ + gr (); + + for (;;) + if (uz != 0) + { + uz = 0; + ib (); + } + else + zg (); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr96491.c b/gcc/testsuite/gcc.dg/torture/pr96491.c new file mode 100644 index 0000000..784559f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr96491.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ + +int rj; + +void __attribute__ ((returns_twice)) +da (void) +{ + rj = 1; +} + +void +c5 (void) +{ + for (;;) + ++rj; +} + +void +ls (int kz) +{ + if (kz == 0) + { + rj = 0; + c5 (); + } + + da (); + c5 (); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr96522.c b/gcc/testsuite/gcc.dg/torture/pr96522.c new file mode 100644 index 0000000..2f55d1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr96522.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fno-tree-pta" } */ + +__attribute__((noipa)) void +bar (void) +{ + volatile int v = 1; + if (v) + __builtin_abort (); +} + +__attribute__((noipa)) void +baz (void) +{ +} + +__attribute__((noipa)) void +foo (int n, double *p, double *x) +{ + if (n < 10 && p != 0) + for (int i = 0; i < 10; i++) + if (x[0] < p[i]) + x[i] = 0; + if (p != 0) + bar (); + else + baz (); +} + +int +main () +{ + double arr[10]; + foo (1000, 0, arr); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr96548.c b/gcc/testsuite/gcc.dg/torture/pr96548.c new file mode 100644 index 0000000..a054742 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr96548.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +int c9, d3; + +void +sg (int *rs, int f2) +{ + for (;;) + { + if (*rs < 1) + __builtin_unreachable (); + + for (c9 = 0; c9 < 1; ++c9) + while (f2 < 1) + ++c9; + + if (d3) + c9 += !!f2 ? 0 : d3; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr96760.c b/gcc/testsuite/gcc.dg/torture/pr96760.c new file mode 100644 index 0000000..4f6bbe9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr96760.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ + +char a = 0, f = 0, c = 5; +unsigned long d = 0; +int g = 0; +int *e = &g; + +int main() { + char b = 0; + for (;;) { + for (a = 0; a < 2; a++) { // no UB I believe + if (c) { + if (d != 0) + __builtin_abort (); + return 0; + } + } + f = (d++, *e); + } + + return 1; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr97135.c b/gcc/testsuite/gcc.dg/torture/pr97135.c new file mode 100644 index 0000000..223f4d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr97135.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ + +long long e, *d = &e; +int a, b, c; + +int +main () +{ + for (; c <= 5; c++) + for (b = 0; b <= 5; b++) + { + for (a = 1; a <= 5; a++) + ; + *d = 0; + if (c) + break; + } + if (a != 6) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr97330-1.c b/gcc/testsuite/gcc.dg/torture/pr97330-1.c new file mode 100644 index 0000000..7dce5bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr97330-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ + +typedef int a; +typedef char b; +int c; +void d(e, f, dst, g, avail, h) int e; +b *f, *dst; +a g, avail; +int h; +{ + b i = *f; + if (e) + goto j; + while (avail) { + *dst = i; + j: + avail -= c; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr97330-2.c b/gcc/testsuite/gcc.dg/torture/pr97330-2.c new file mode 100644 index 0000000..a064483 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr97330-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +int a, b, d; +char c, e; +void f(void) { + char g = c; + if (b) + goto h; + while (d) { + e = c; + h: + d -= a; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pta-callused-1.c b/gcc/testsuite/gcc.dg/torture/pta-callused-1.c index b35959c..0ca6ac9 100644 --- a/gcc/testsuite/gcc.dg/torture/pta-callused-1.c +++ b/gcc/testsuite/gcc.dg/torture/pta-callused-1.c @@ -21,4 +21,4 @@ int main() return 0; } -/* { dg-final { scan-tree-dump "p.._. = { i j }" "alias" } } */ +/* { dg-final { scan-tree-dump "p.\?.._. = { i j }" "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c index 31585a0..5ec0558 100644 --- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c +++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c @@ -9,7 +9,7 @@ /* arm_hf_eabi: Variadic funcs use Base AAPCS. Normal funcs use VFP variant. avr: Variadic funcs don't pass arguments in registers, while normal funcs do. */ -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* } } } */ +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { csky*-*-* avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* } } } */ /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } { v850*-*-* } } */ /* { dg-require-effective-target untyped_assembly } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c b/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c index 450308d..511b610 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c +++ b/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c @@ -3,6 +3,12 @@ /* { dg-require-effective-target freorder } */ /* { dg-options "-O2 -freorder-blocks-and-partition -save-temps -fdump-tree-optimized" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 1000000 +#else +#define MAXITER 10000 +#endif + #define SIZE 10000 const char *sarr[SIZE]; @@ -32,7 +38,7 @@ main (int argc, char *argv[]) int i; buf_hot = "hello"; buf_cold = "world"; - for (i = 0; i < 1000000; i++) + for (i = 0; i < MAXITER; i++) foo (argc); return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-1.c b/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-1.c index a13b08c..b57d30f 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-1.c @@ -3,6 +3,12 @@ /* { dg-require-profiling "-fprofile-generate" } */ /* { dg-options "-O2 -flto -DDOJOB=1 -fdump-ipa-profile_estimate" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 350000000 +#else +#define MAXITER 3500000 +#endif + #include <stdio.h> typedef int (*fptr) (int); @@ -22,7 +28,7 @@ main() x = one (3); - for (i = 0; i < 350000000; i++) + for (i = 0; i < MAXITER; i++) { x = (*p) (3); p = table[x]; diff --git a/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-2.c b/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-2.c index 9b996fc..6b5ae93 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-2.c +++ b/gcc/testsuite/gcc.dg/tree-prof/crossmodule-indir-call-topn-2.c @@ -3,6 +3,12 @@ /* { dg-require-profiling "-fprofile-generate" } */ /* { dg-options "-O2 -flto -DDOJOB=1 -fdump-ipa-profile_estimate" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 350000000 +#else +#define MAXITER 3500000 +#endif + #include <stdio.h> typedef int (*fptr) (int); @@ -21,7 +27,7 @@ int foo () x = one (3); - for (i = 0; i < 350000000; i++) + for (i = 0; i < MAXITER; i++) { x = (*p) (3); p = table[x]; diff --git a/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-malloc.c b/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-malloc.c new file mode 100644 index 0000000..454e224 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-malloc.c @@ -0,0 +1,49 @@ +/* { dg-options "-O2 -ldl" } */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdint.h> +#include <dlfcn.h> + +int global; +int global2; + +void report1 (size_t size) +{ + global++; +} + +void report2 (size_t size) +{ + global2++; +} + +typedef void (*tp) (size_t); +static tp fns[] = {report1, report2}; + +void* malloc(size_t size) +{ + static void* (*real_malloc)(size_t) = NULL; + if (!real_malloc) + real_malloc = dlsym(RTLD_NEXT, "malloc"); + + void *p = real_malloc (size); + fns[size % 2] (size); + // fprintf(stderr, "malloc(%d) = %p\n", size, p); + return p; +} + +void *calloc (size_t n, size_t size) +{ + void *ptr = malloc (n * size); + __builtin_memset (ptr, 0, n * size); + return ptr; +} + +void *ptr; + +int main() +{ + ptr = malloc (16); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-topn.c b/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-topn.c index 063996c..9a1a0be 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-topn.c +++ b/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-topn.c @@ -1,6 +1,12 @@ /* { dg-require-profiling "-fprofile-generate" } */ /* { dg-options "-O2 -fdump-ipa-profile_estimate" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 350000000 +#else +#define MAXITER 3500000 +#endif + #include <stdio.h> typedef int (*fptr) (int); @@ -26,7 +32,7 @@ main() one (3); - for (i = 0; i < 350000000; i++) + for (i = 0; i < MAXITER; i++) { x = (*p) (3); p = table[x]; diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr96394.c b/gcc/testsuite/gcc.dg/tree-prof/pr96394.c new file mode 100644 index 0000000..4280182 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/pr96394.c @@ -0,0 +1,64 @@ +/* PR ipa/96394 */ +/* { dg-options "-O2" } */ + +typedef struct _entry { + int has_next; + int next_ix; + int count; +} entry; + +extern entry table[]; + +void * +__attribute__((noipa)) +PyErr_Format(entry * e){ return 0; } + +void ae(entry *); +int h(entry *); +int ap(entry *); +int ag(entry *); + +int ag(entry *j) { + if (j->has_next) + h(&table[j->next_ix]); + return 0; +} +static int ai(entry *j, int k(entry *), int l, int m) { + int am = 1; + int ab; + + /* k is either 'h' or 'ap': 50%/50% */ + ab = k(j); + + /* loop never gets executed on real data */ + for (; j->count >= 2; am += 2) + if (l) { + entry *i = &table[am + m]; + PyErr_Format(i); + } + return ab; +} +void +__attribute__((noipa)) +bug() { + h(table); + h(table); +} +int h(entry *j) { return ai(j, ap, 4, 5); } +int ap(entry *j) { return ai(j, ag, 14, 4); } + +int main(void) +{ + bug(); +} + +entry table[2] = { + { .has_next = 1 + , .next_ix = 1 + , .count = 0 + }, + { .has_next = 0 + , .next_ix = 0 + , .count = 0 + }, +}; diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c index 89ecc1c..2087d0d 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c @@ -3,6 +3,12 @@ /* { dg-require-effective-target freorder } */ /* { dg-options "-O2 -fno-profile-reorder-functions -freorder-blocks-and-partition -save-temps" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 1000000 +#else +#define MAXITER 10000 +#endif + #define SIZE 10000 #define NOINLINE __attribute__((noinline)) __attribute__ ((noclone)) @@ -24,7 +30,7 @@ main (int argc, char *argv[]) int i; buf_hot = "hello"; buf_cold = "world"; - for (i = 0; i < 1000000; i++) + for (i = 0; i < MAXITER; i++) foo (argc); return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c index b856457..b02526b 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c +++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c @@ -4,6 +4,12 @@ /* { dg-require-effective-target freorder } */ /* { dg-options "-O2 -fno-profile-reorder-functions -freorder-blocks-and-partition -save-temps" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 1000000 +#else +#define MAXITER 10000 +#endif + #define SIZE 10000 #define NOINLINE __attribute__((noinline)) __attribute__ ((noclone)) @@ -20,7 +26,7 @@ main (int argc, char *argv[]) int i; buf_hot = "hello"; buf_cold = "world"; - for (i = 0; i < 1000000; i++) + for (i = 0; i < MAXITER; i++) foo (argc); return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c index 8d85cf3..da06407 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c +++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c @@ -4,6 +4,12 @@ /* { dg-require-effective-target freorder } */ /* { dg-options "-O2 -fno-profile-reorder-functions -freorder-blocks-and-partition -save-temps" } */ +#ifdef FOR_AUTOFDO_TESTING +#define MAXITER 1000000 +#else +#define MAXITER 10000 +#endif + #define SIZE 10000 #define NOINLINE __attribute__((noinline)) __attribute__ ((noclone)) @@ -24,7 +30,7 @@ main (int argc, char *argv[]) int i; buf_hot = "hello"; buf_cold = "world"; - for (i = 0; i < 1000000; i++) + for (i = 0; i < MAXITER; i++) foo (argc); return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c index 0903f3c..0e01e51 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c @@ -7,7 +7,7 @@ unsigned int subreg_highpart_offset (outermode, innermode) int outermode, innermode; { - unsigned int offset = 0; + unsigned int offset = 1; int difference = (mode_size[innermode] - mode_size[outermode]); if (difference > 0) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/andnot-2.c b/gcc/testsuite/gcc.dg/tree-ssa/andnot-2.c new file mode 100644 index 0000000..e0955ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/andnot-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop3-raw -w -Wno-psabi" } */ + +typedef long vec __attribute__((vector_size(16))); +vec f(vec x){ + vec y = x < 10; + return y & (y == 0); +} + +/* { dg-final { scan-tree-dump-not "_expr" "forwprop3" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c index 6fd1bca..685a4fd 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c @@ -1,7 +1,8 @@ /* PR tree-optimization/91567 - Spurious -Wformat-overflow warnings building glibc (32-bit only) { dg-do compile } - { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c index 0912b68..3946a8c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c @@ -14,13 +14,13 @@ main (void) /* MEMCHR. */ if (__builtin_memchr ("", 'x', 1000)) /* Not folded away. */ { - /* { dg-warning "reading 1000 bytes from a region of size 1" "" { target *-*-* } .-2 } */ + /* { dg-warning "\\\[-Wstringop-overread" "" { target *-*-* } .-2 } */ __builtin_abort (); } if (__builtin_memchr (foo1, 'x', 1000)) /* Not folded away. */ { - /* { dg-warning "reading 1000 bytes from a region of size 1" "" { target *-*-* } .-2 } */ + /* { dg-warning "\\\[-Wstringop-overread" "" { target *-*-* } .-2 } */ __builtin_abort (); } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-3.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-3.c new file mode 100644 index 0000000..f52e04d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-3.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/96715 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "= __builtin_copysign" "optimized" } } */ +/* { dg-final { scan-tree-dump-times " = -x_\[0-9]*\\(D\\)" 3 "optimized" } } */ + +float +foo (float x) +{ + return __builtin_copysignf (x, -x); +} + +double +bar (double x) +{ + return __builtin_copysign (x, -x); +} + +long double +baz (long double x) +{ + return __builtin_copysignl (x, -x); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-36.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-36.c index 9de73ff..f3871bf 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-36.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-36.c @@ -21,4 +21,5 @@ main () return 0; } -/* { dg-final { scan-tree-dump "if \\(b.0_\[0-9\]+ != 0\\)" "cddce1" } } */ +/* { dg-final { scan-tree-dump "if \\(b.0_\[0-9\]+ != 0\\)" "cddce1" { target { ! mmix-knuth-mmixware } } } } */ +/* { dg-final { scan-tree-dump "if \\(b::1_\[0-9\]+ != 0\\)" "cddce1" { target { mmix-knuth-mmixware } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c b/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c index 3c358e0..6746758 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c @@ -12,5 +12,5 @@ t(int a, int b, int c) p = &c; return *p; } -/* { dg-final { scan-tree-dump-times "local memory is OK" 1 "local-pure-const1"} } */ +/* { dg-final { scan-tree-dump-times "local or readonly memory is OK" 1 "local-pure-const1"} } */ /* { dg-final { scan-tree-dump-times "found to be const" 1 "local-pure-const1"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c index af7a3da..0c73111 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c @@ -22,6 +22,6 @@ void tuned_STREAM_Copy() However, due to a bug in jump threading, we end up peeling one iteration from the loop, which creates an additional occurrence. */ -/* { dg-final { scan-tree-dump-times "MEM.(base: &|symbol: )a," 2 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "MEM.(base: &|symbol: )c," 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MEM\[^;\]*&a" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MEM\[^;\]*&c" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c index bda2516..e58561a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c @@ -27,7 +27,6 @@ void xxx(void) /* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */ /* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "MEM\\\[base" 1 "optimized" } } */ /* 17 * iter should be strength reduced. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c index d3b26b7..74491f8 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c @@ -20,8 +20,7 @@ void xxx(void) /* Access to arr_base[iter].y should not be strength reduced, since we have a memory mode including multiplication by 4. */ -/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "step:" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MEM\[^;\]* \* 4" 1 "optimized" } } */ /* And original induction variable should be preserved. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-1.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-1.c new file mode 100644 index 0000000..a80ca6b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int p,q,r,s,*ptr=&q, *ptr2=&p; +__attribute__ ((noinline)) +int +test (int *p) +{ + *p = 1; +} +int +test1() +{ + q = 123; + test(&p); + return q; +} +int +test2() +{ + int *ptr = p ? &q : &s; + *ptr = 124; + test(&p); + return *ptr; +} +int +test3() +{ + int *ptr = p ? &p : &s; + q = 125; + test(ptr); + return q; +} +int +test4() +{ + int *ptr1 = p ? &q : &s; + int *ptr = p ? &r : &p; + *ptr1 = 126; + test(ptr); + return *ptr1; +} +/* { dg-final { scan-tree-dump "return 123" "optimized"} } */ +/* { dg-final { scan-tree-dump "return 124" "optimized"} } */ +/* { dg-final { scan-tree-dump "return 125" "optimized"} } */ +/* { dg-final { scan-tree-dump "return 126" "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-2.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-2.c new file mode 100644 index 0000000..9999d37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-2.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +short aa; +void +__attribute__ ((noinline, noclone)) +recursive (int *a, int *b, int *c, int level) +{ + if (level && c) + { + recursive (b,a,c,0); + aa++; + } + else + *a=0; +} +int +main() +{ + int x = 123, y=124, z=125; + recursive (&x,&y,&z,1); + if (y) + __builtin_abort (); + if (!__builtin_constant_p (z)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-3.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-3.c new file mode 100644 index 0000000..668c6c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-3.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +struct a +{ + int b; + int c; +}; + +__attribute__ ((noclone, noinline)) +void +test (struct a *a) +{ + a->b = 2; +} +int +foo () +{ + struct a a = {113,114}; + test (&a); + return a.c; +} +int +foo2 (struct a *a) +{ + a->b = 123; + a->c = 124; + test (a); + return a->c; +} +/* { dg-final { scan-tree-dump "return 114" "optimized"} } */ +/* { dg-final { scan-tree-dump "return 124" "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c index 9c22c53..cf74e15 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread-details-blocks-stats" } */ +/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-thread-details-blocks-stats" } */ typedef enum STATES { START=0, INVALID, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93121-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93121-1.c new file mode 100644 index 0000000..4bf40c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93121-1.c @@ -0,0 +1,56 @@ +/* PR libstdc++/93121 */ +/* { dg-do compile { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +union U { int a[3]; short c[6]; struct S { int d; int a : 2; int f : 1; int b : 24; int c : 5; int e; } b; }; +const union U u = { .b = { 0x7efa3412, 3, 0, 0x50eca8, 0xb, 0x1eeffeed } }; +const union U v = { .b = { 0x7efa3412, 1, 1, 0x7feedb, 0x5, 0x1eeffeed } }; +union W { struct T { long long int a, b : 11, c : 3, d : 37, e : 1, f : 10, g : 2, h; } a; int b[6]; short c[12]; long long d[3]; }; +const union W w = { .a = { 0x0feedbacdeadbeefLL, -1011, 2, -0xbacdeadbeLL, -1, 721, 1, 0x0feedbacdeadbeefLL } }; +int a, b, c, d, e, f, g, h, i, j, k, l; +long long m; + +void +foo () +{ + a = u.a[1]; + b = v.a[1]; + c = u.c[2]; + d = u.c[3]; + e = v.c[2]; + f = v.c[3]; + g = w.b[2]; + h = w.b[3]; + i = w.c[4]; + j = w.c[5]; + k = w.c[6]; + l = w.c[7]; + m = w.d[1]; +} + +/* { dg-final { scan-tree-dump-times "a = 1518822723;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "b = 738162397;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "c = 25923;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "d = 23175;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "e = 30429;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "f = 11263;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "g = 1418761229;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "h = 1830622408;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "i = -27635;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "j = 21648;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "k = 5320;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "l = 27933;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "m = 7862463375103529997;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "a = -904030965;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "b = 1878907749;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "c = -13795;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "d = -27381;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "e = 28669;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "f = -9371;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "g = -2119529884;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "h = 709385029;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "i = -32342;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "j = -30108;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "k = 10824;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "l = 23365;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "m = -9103311533965288635;" 1 "optimized" { target be } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93121-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93121-2.c new file mode 100644 index 0000000..323dca6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93121-2.c @@ -0,0 +1,22 @@ +/* PR libstdc++/93121 */ +/* { dg-do compile { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +union U { int a[3]; struct S { int d; int a : 3; int b : 24; int c : 5; int e; } b; }; +const union U u = { .a = { 0x7efa3412, 0x5a876543, 0x1eeffeed } }; +int a, b, c; + +void +foo () +{ + a = u.b.a; + b = u.b.b; + c = u.b.c; +} + +/* { dg-final { scan-tree-dump-times "a = 3;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "b = 5303464;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "c = 11;" 1 "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump-times "a = 2;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "b = -2868438;" 1 "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump-times "c = 3;" 1 "optimized" { target be } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94801.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94801.c new file mode 100644 index 0000000..5382e5e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94801.c @@ -0,0 +1,16 @@ +/* PR tree-optimization/94801 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */ + +int +foo (int a) +{ + return __builtin_clz (a) >> 5; +} + +int +bar (int a) +{ + return __builtin_ctz (a) >> 5; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c new file mode 100644 index 0000000..c830a3d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fwrapv -fdump-tree-gimple" } */ + +typedef __INT32_TYPE__ int32_t; +typedef unsigned __INT32_TYPE__ uint32_t; + +int e(int32_t x){return 3*x==5;} +int f(int32_t x){return 3*x==-5;} +int g(int32_t x){return -3*x==5;} +int h(int32_t x){return 7*x==3;} +int i(uint32_t x){return 7*x==3;} + +/* { dg-final { scan-tree-dump-times "== 1431655767" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "== -1431655767" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "== 613566757" 2 "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c new file mode 100644 index 0000000..4e161ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int f(int x){return x*7==17;} +int g(int x){return x*3==15;} + +/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */ +/* { dg-final { scan-tree-dump "== 5;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr95906.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95906.c new file mode 100644 index 0000000..3d820a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95906.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop3-raw -w -Wno-psabi" } */ + +// FIXME: this should further optimize to a MAX_EXPR +typedef signed char v16i8 __attribute__((vector_size(16))); +v16i8 f(v16i8 a, v16i8 b) +{ + v16i8 cmp = (a > b); + return (cmp & a) | (~cmp & b); +} + +/* { dg-final { scan-tree-dump-not "bit_(and|ior)_expr" "forwprop3" } } */ +/* { dg-final { scan-tree-dump-times "vec_cond_expr" 1 "forwprop3" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c new file mode 100644 index 0000000..f2a91ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/96480 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump " = _\[0-9]* <= 3;" "optimized" } } */ + +int v[4]; + +int +foo (int x) +{ + int *p; + if (x == 0) + p = &v[0]; + else if (x == 1) + p = &v[1]; + else if (x == 2) + p = &v[2]; + else if (x == 3) + p = &v[3]; + else + p = &v[4]; + return p != &v[4]; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96730.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96730.c new file mode 100644 index 0000000..39a0684 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96730.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +struct a { + int b; + int c; +} d() { + struct a e[9]; + int f = 3362953455; + e[f] = e[6]; + e[6].c = 1; +} +int main() {} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96820.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96820.c new file mode 100644 index 0000000..f5c2195 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96820.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +struct a { + int b; +}; +int main() { + struct a d[][6] = {4}; + struct a e; + d[1955249013][1955249013] = e; + return e.b; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96967.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96967.c new file mode 100644 index 0000000..249dfc7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96967.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fshort-enums" } */ + +enum re { + o3, +}; + +int +uj (int mq, enum re dn) +{ + enum re nr = mq; + + switch (nr) + { + case 4: + if (dn == 0) + goto wdev_inactive_unlock; + break; + + default: + break; + } + + switch (nr) + { + case 0: + case 4: + return 0; + + default: + break; + } + + wdev_inactive_unlock: + return 1; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c index 3d2ea6b..a7d57f1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c @@ -15,5 +15,5 @@ int main(void) printf ("%d %d\n", e, f); } -/* { dg-final { scan-tree-dump-times "\[ab\].._. \\\+ \[ab\].._." 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[ab\].\?.._. \\\+ \[ab\].\?.._." 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times " \\\+ " 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c index e4daa9d..a879d30 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c @@ -27,4 +27,4 @@ foo () but the loop reads only one element at a time, and DOM cannot resolve these. The same happens on powerpc depending on the SIMD support available. */ -/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* hppa*64*-*-* nvptx*-*-* } || { { { lp64 && { powerpc*-*-* sparc*-*-* riscv*-*-* } } || aarch64_sve } || { arm*-*-* && { ! arm_neon } } } } } } } */ +/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* hppa*64*-*-* nvptx*-*-* mmix-knuth-mmixware } || { { { lp64 && { powerpc*-*-* sparc*-*-* riscv*-*-* } } || aarch64_sve } || { arm*-*-* && { ! arm_neon } } } } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c index 551fbac..16a9ef4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c @@ -1,7 +1,41 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread2-details" } */ -/* { dg-final { scan-tree-dump-times "FSM" 3 "thread1" } } */ -/* { dg-final { scan-tree-dump-times "FSM" 5 "thread2" } } */ + +/* All the threads in the thread1 dump start on a X->BB12 edge, as can + be seen in the dump: + + Registering FSM jump thread: (x, 12) incoming edge; ... + etc + etc + + Before the new evrp, we were threading paths that started at the + following edges: + + Registering FSM jump thread: (10, 12) incoming edge + Registering FSM jump thread: (6, 12) incoming edge + Registering FSM jump thread: (9, 12) incoming edge + + This was because the PHI at BB12 had constant values coming in from + BB10, BB6, and BB9: + + # state_10 = PHI <state_11(7), 0(10), state_11(5), 1(6), state_11(8), 2(9), state_11(11)> + + Now with the new evrp, we get: + + # state_10 = PHI <0(7), 0(10), state_11(5), 1(6), 0(8), 2(9), 1(11)> + + Thus, we have 3 more paths that are known to be constant and can be + threaded. Which means that by the second threading pass, we can + only find one profitable path. + + For the record, all these extra constants are better paths coming + out of switches. For example: + + SWITCH_BB -> BBx -> BBy -> BBz -> PHI + + We now know the value of the switch index at PHI. */ +/* { dg-final { scan-tree-dump-times "FSM" 6 "thread1" } } */ +/* { dg-final { scan-tree-dump-times "FSM" 1 "thread2" } } */ int sum0, sum1, sum2, sum3; int foo (char *s, char **ret) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c index a339557..bad5bc1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c @@ -1,20 +1,31 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */ -/* { dg-final { scan-tree-dump "Jumps threaded: 16" "thread1" } } */ -/* { dg-final { scan-tree-dump "Jumps threaded: 9" "thread2" } } */ + +/* Here we have the same issue as was commented in ssa-dom-thread-6.c. + The PHI coming into the threader has a lot more constants, so the + threader can thread more paths. + +$ diff clean/a.c.105t.mergephi2 a.c.105t.mergephi2 +252c252 +< # s_50 = PHI <s_49(10), 5(14), s_51(18), s_51(22), 1(26), 1(29), 1(31), s_51(5), 4(12), 1(15), 5(17), 1(19), 3(21), 1(23), 6(25), 7(28), s_51(30)> +--- +> # s_50 = PHI <s_49(10), 5(14), 4(18), 5(22), 1(26), 1(29), 1(31), s_51(5), 4(12), 1(15), 5(17), 1(19), 3(21), 1(23), 6(25), 7(28), 7(30)> +272a273 + + I spot checked a few and they all have the same pattern. We are + basically tracking the switch index better through multiple + paths. */ + +/* { dg-final { scan-tree-dump "Jumps threaded: 19" "thread1" } } */ +/* { dg-final { scan-tree-dump "Jumps threaded: 8" "thread2" } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */ + /* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough to change decisions in switch expansion which in turn can expose new jump threading opportunities. Skip the later tests on aarch64. */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom3" { target { ! aarch64*-*-* } } } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp2" { target { ! aarch64*-*-* } } } } */ -/* Most architectures get 3 threadable paths here, whereas aarch64 and - possibly others get 5. We really should rewrite threading tests to - test a specific IL sequence, not gobs of code whose IL can vary - from architecture to architecture. */ -/* { dg-final { scan-tree-dump "Jumps threaded: \[35\]" "thread3" } } */ - enum STATE { S0=0, SI, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c index 8abc28b..271e666 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c @@ -31,12 +31,14 @@ constraint_equal (struct constraint a, struct constraint b) } /* Most targets should be using this test. */ -/* { dg-final { scan-tree-dump-times "Deleted dead store: x = " 1 "dse1" { target { ! tic6x-*-* } } } } */ -/* { dg-final { scan-tree-dump-times "Deleted dead store: y = " 1 "dse1" { target { ! tic6x-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead store: x = " 1 "dse1" { target { ! { tic6x-*-* mmix-knuth-mmixware } } } } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead store: y = " 1 "dse1" { target { ! { tic6x-*-* mmix-knuth-mmixware } } } } } */ /* The c6x port generates significantly different gimple which changes the SRA and DSE decisions. Verify we remove all - dead stores. */ + dead stores. Similarly for mmix. */ /* { dg-final { scan-tree-dump-times "Deleted dead store: \[ax\].. = " 2 "dse1" { target tic6x-*-* } } } */ /* { dg-final { scan-tree-dump-times "Deleted dead store: \[by\].. = " 2 "dse1" { target tic6x-*-* } } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead store: x::. = " 1 "dse1" { target mmix-knuth-mmixware } } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead store: y::. = " 1 "dse1" { target mmix-knuth-mmixware } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-40.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-40.c new file mode 100644 index 0000000..36f69c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-40.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-dse1-details" } */ + +_Bool g(void); + +void f(int x) +{ + char arr[x]; + + arr[0] = 0; + + if (g()) + __builtin_abort(); +} + +/* { dg-final { scan-tree-dump "Deleted dead store" "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-88.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-88.c new file mode 100644 index 0000000..15d2ca0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-88.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ + +double y[2]; +void foo (double x) +{ + y[0] = x * -3.; + y[1] = x * 3.; +} +void bar (double x, double z) +{ + y[0] = -z / x; + y[1] = z / x; +} + +/* { dg-final { scan-tree-dump-times " \\* " 1 "fre1" } } */ +/* { dg-final { scan-tree-dump-times " / " 1 "fre1" } } */ +/* { dg-final { scan-tree-dump-times "= -_" 2 "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c new file mode 100644 index 0000000..cf2e2a0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/97307 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sink-details" } */ + +int pure_f(int a, int b) __attribute__((pure)); +int my_f(int a, int b) +{ + int x = pure_f(a, b); + if (a > 0) + return x; + return a; +} + +/* We should sink the call to pure_f to the if block. */ +/* { dg-final { scan-tree-dump "Sinking # VUSE" "sink" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-4.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-4.c index 17c56e9..00ddd29 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vector-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-4.c @@ -11,5 +11,6 @@ v4si vs (v4si a, v4si b) /* The compound literal should be placed directly in the vec_perm. */ /* Test is xfailed on 32-bit hppa*-*-* because target-callee-copies. */ -/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR <a, b, { 0, 4, 1, 5 }>;" 1 "gimple" { xfail { hppa*-*-* && { ! lp64 } } } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR <a, b, { 0, 4, 1, 5 }>;" 1 "gimple" { target { ! mmix-knuth-mmixware } xfail { hppa*-*-* && { ! lp64 } } } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR <a::., b::., { 0, 4, 1, 5 }>;" 1 "gimple" { target mmix-knuth-mmixware } } } */ diff --git a/gcc/testsuite/gcc.dg/uninit-32.c b/gcc/testsuite/gcc.dg/uninit-32.c index cdc0512..cf9efa0 100644 --- a/gcc/testsuite/gcc.dg/uninit-32.c +++ b/gcc/testsuite/gcc.dg/uninit-32.c @@ -1,7 +1,8 @@ /* PR middle-end/10138 - warn for uninitialized arrays passed as const* arguments { dg-do compile } - { dg-options "-O -Wall" } */ + { dg-options "-O -Wall" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/uninit-33.c b/gcc/testsuite/gcc.dg/uninit-33.c index a45f18d..732d33e 100644 --- a/gcc/testsuite/gcc.dg/uninit-33.c +++ b/gcc/testsuite/gcc.dg/uninit-33.c @@ -27,7 +27,7 @@ void nowarn_scalar_plus_fpri (void) int i; /* This gets a -Wstringop-overflow for reading past the end but not -Wuninitialized because there's nothing to initialize there. */ - fpri (&i + 1); // { dg-warning "\\\[-Wstringop-overflow" } + fpri (&i + 1); // { dg-warning "\\\[-Wstringop-overread" } } void nowarn_array_assign_fpcri (void) diff --git a/gcc/testsuite/gcc.dg/uninit-36.c b/gcc/testsuite/gcc.dg/uninit-36.c index 9524e7a..f6307ce 100644 --- a/gcc/testsuite/gcc.dg/uninit-36.c +++ b/gcc/testsuite/gcc.dg/uninit-36.c @@ -3,7 +3,8 @@ Verify that passing pointers to uninitialized objects to const arguments to built-ins is diagnosed where expected. { dg-do compile } - { dg-options "-O -Wall" } */ + { dg-options "-O -Wall" } + { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/gcc.dg/uninit-37.c b/gcc/testsuite/gcc.dg/uninit-37.c new file mode 100644 index 0000000..b8c49ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-37.c @@ -0,0 +1,154 @@ +/* PR middle-end/10138 - warn for uninitialized arrays passed as const arguments + Verify that -Wuninitialized and -Wmaybe-uninitialized trigger (or don't) + when passing uninitialized variables by reference to functions declared + with or without attribute access and with (or without) const qualified + arguments of array, VLA, or pointer types. + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +#define NONE /* none */ +#define RO(...) __attribute__ ((access (read_only, __VA_ARGS__))) +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) +#define WO(...) __attribute__ ((access (write_only, __VA_ARGS__))) +#define X(...) __attribute__ ((access (none, __VA_ARGS__))) + +#define CONCAT(x, y) x ## y +#define CAT(x, y) CONCAT (x, y) +#define UNIQ(pfx) CAT (pfx, __LINE__) + +extern void sink (void*); + + +#define T1(attr, name, type) \ + void UNIQ (CAT (test_, name))(void) { \ + extern attr void UNIQ (name)(type); \ + int x; \ + UNIQ (name)(&x); \ + sink (&x); \ + } + +#define T2(attr, name, types) \ + void UNIQ (CAT (test_, name))(void) { \ + extern attr void UNIQ (name)(types); \ + int x; \ + UNIQ (name)(1, &x); \ + sink (&x); \ + } + + +typedef int IA_[]; +typedef const int CIA_[]; + +T1 (NONE, fia_, IA_); +T1 (NONE, fcia_, CIA_); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froia_, IA_); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwia_, IA_); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoia_, IA_); +T1 (X (1), fxia_, IA_); + + +typedef int IA1[1]; +typedef const int CIA1[1]; + +T1 (NONE, fia1, IA1); +T1 (NONE, fcia1, CIA1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froia1, IA1); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwia1, IA1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoia1, IA1); +T1 (X (1), fxia1, IA1); + + +#define IARS1 int[restrict static 1] +#define CIARS1 const int[restrict static 1] + +T1 (NONE, fiars1, IARS1); +T1 (NONE, fciars1, CIARS1);// { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froiars1, IARS1); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwiars1, IARS1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoiars1, IARS1); +T1 (X (1), fxiars1, IARS1); + + +#define IAS1 int[static 1] +#define CIAS1 const int[static 1] + +T1 (NONE, fias1, IAS1); +T1 (NONE, fcias1, CIAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froias1, IAS1); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwias1, IAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoias1, IAS1); +T1 (X (1), fxias1, IAS1); + + +#define IAX int[*] +#define CIAX const int[*] + +T1 (NONE, fiax, IAX); +T1 (NONE, fciax, CIAX); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froiax, IAX); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwiax, IAX); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoiax, IAX); +T1 (X (1), fxiax, IAX); + + +#define IAN int n, int[n] +#define CIAN int n, const int[n] + +T2 (NONE, fian, IAN); +T2 (NONE, fcian, CIAN); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T2 (RO (2, 1), froian, IAN); // { dg-warning "\\\[-Wuninitialized" } +T2 (RW (2, 1), frwian, IAN); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T2 (WO (2, 1), fwoian, IAN); +T2 (X (2, 1), fxian, IAN); + + +typedef int* IP; +typedef const int* CIP; + +T1 (NONE, fip, IP); +T1 (NONE, fcip, CIP); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froip, IP); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwip, IP); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoip, IP); +T1 (X (1), fxip, IP); + + +/* Verify that the notes printed after the warning mention attribute + access only when the attribute is explicitly used in the declaration + and not otherwise. */ + +void test_note_cst_restrict (void) +{ + extern void + fccar (const char[restrict]); // { dg-message "by argument 1 of type 'const char\\\[restrict]' to 'fccar'" "note" } + + char a[1]; // { dg-message "'a' declared here" "note" } + fccar (a); // { dg-warning "'a' may be used uninitialized" } +} + +void test_note_vla (int n) +{ + extern void + fccvla (const char[n]); // { dg-message "by argument 1 of type 'const char\\\[n]' to 'fccvla'" "note" } + + char a[2]; // { dg-message "'a' declared here" "note" } + fccvla (a); // { dg-warning "'a' may be used uninitialized" } +} + +void test_note_ro (void) +{ + extern RO (1) void + frocar (char[restrict]); // { dg-message "in a call to 'frocar' declared with attribute 'access \\\(read_only, 1\\\)'" "note" } + + char a[3]; // { dg-message "'a' declared here" "note" } + frocar (a); // { dg-warning "'a' is used uninitialized" } +} + +void test_note_rw (void) +{ + extern RW (1) void + frwcar (char[restrict]); // { dg-message "in a call to 'frwcar' declared with attribute 'access \\\(read_write, 1\\\)'" "note" } + + char a[4]; // { dg-message "'a' declared here" "note" } + frwcar (a); // { dg-warning "'a' may be used uninitialized" } +} diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-1.c index e6818cb..793c41f 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-1.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-1.c @@ -55,4 +55,4 @@ int main (void) } /* { dg-final { scan-tree-dump-not "can't force alignment" "slp1" } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-10.c b/gcc/testsuite/gcc.dg/vect/bb-slp-10.c index ad6f878..697dc4e 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-10.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-10.c @@ -50,5 +50,5 @@ int main (void) } /* { dg-final { scan-tree-dump "unsupported unaligned access" "slp2" { target { ! vect_element_align } } } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_element_align } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_element_align } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-11.c b/gcc/testsuite/gcc.dg/vect/bb-slp-11.c index cb8bddd..ff43253 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-11.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-11.c @@ -49,5 +49,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect64 } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect64 } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-13.c b/gcc/testsuite/gcc.dg/vect/bb-slp-13.c index 302e20f..fdff76e 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-13.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-13.c @@ -46,5 +46,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-14.c b/gcc/testsuite/gcc.dg/vect/bb-slp-14.c index e7d4e6c..62ee757 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-14.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-14.c @@ -48,5 +48,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-15.c b/gcc/testsuite/gcc.dg/vect/bb-slp-15.c index a749041..efe7d6a 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-15.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-15.c @@ -51,5 +51,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c index 42abd64..e68a9b6 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c @@ -65,5 +65,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-17.c b/gcc/testsuite/gcc.dg/vect/bb-slp-17.c index c20e0ff..f8bfb4b 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-17.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-17.c @@ -57,5 +57,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-18.c b/gcc/testsuite/gcc.dg/vect/bb-slp-18.c index 9476653..db3f0ba 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-18.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-18.c @@ -46,5 +46,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-19.c b/gcc/testsuite/gcc.dg/vect/bb-slp-19.c index db446be..7e3ccb4 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-19.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-19.c @@ -52,5 +52,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-2.c index cee9db5..fcf1cd3 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-2.c @@ -53,5 +53,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-20.c b/gcc/testsuite/gcc.dg/vect/bb-slp-20.c index f6dfaa7..134858c 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-20.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-20.c @@ -63,6 +63,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-21.c b/gcc/testsuite/gcc.dg/vect/bb-slp-21.c index 5464d09..d4c98d6 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-21.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-21.c @@ -63,6 +63,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-22.c b/gcc/testsuite/gcc.dg/vect/bb-slp-22.c index b531651..92cc2a5 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-22.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-22.c @@ -63,5 +63,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ /* { dg-final { scan-tree-dump "vectorizing SLP node starting from: _\[0-9\]+ = _\[0-9\]+ \\\* a0" "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-23.c b/gcc/testsuite/gcc.dg/vect/bb-slp-23.c index e57ca41..ed4a595 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-23.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-23.c @@ -51,5 +51,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-24.c b/gcc/testsuite/gcc.dg/vect/bb-slp-24.c index d5b6bfb..ca049c8 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-24.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-24.c @@ -55,5 +55,5 @@ int main (void) /* Exclude POWER8 (only POWER cpu for which vect_element_align is true) because loops have vectorized before SLP gets a shot. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" { target { vect_element_align && { ! powerpc*-*-* } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" { target { vect_element_align && { ! powerpc*-*-* } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-25.c b/gcc/testsuite/gcc.dg/vect/bb-slp-25.c index ec31329..7a9cf95 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-25.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-25.c @@ -56,5 +56,5 @@ int main (void) /* Exclude POWER8 (only POWER cpu for which vect_element_align is true) because loops have vectorized before SLP gets a shot. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" { target { vect_element_align && { ! powerpc*-*-* } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" { target { vect_element_align && { ! powerpc*-*-* } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-26.c b/gcc/testsuite/gcc.dg/vect/bb-slp-26.c index 91b6cac..df52967 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-26.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-26.c @@ -54,5 +54,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" { target { vect64 && vect_hw_misalign } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" { target { vect64 && vect_hw_misalign } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-27.c b/gcc/testsuite/gcc.dg/vect/bb-slp-27.c index 8ef8bb0..bc27f2f 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-27.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-27.c @@ -44,5 +44,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target { vect_int_mult && { vect_unpack && vect_pack_trunc } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target { vect_int_mult && { vect_unpack && vect_pack_trunc } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-28.c b/gcc/testsuite/gcc.dg/vect/bb-slp-28.c index a4c01b9..8749a1f 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-28.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-28.c @@ -66,5 +66,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target { vect_int_mult && { vect_pack_trunc && vect_unpack } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" { target { vect_int_mult && { vect_pack_trunc && vect_unpack } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-29.c b/gcc/testsuite/gcc.dg/vect/bb-slp-29.c index 747896b..b531350 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-29.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-29.c @@ -56,5 +56,5 @@ int main (void) /* Exclude POWER8 (only POWER cpu for which vect_element_align is true) because loops have vectorized before SLP gets a shot. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" { target { { vect_int_mult && vect_element_align } && { ! powerpc*-*-* } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" { target { { vect_int_mult && vect_element_align } && { ! powerpc*-*-* } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-3.c b/gcc/testsuite/gcc.dg/vect/bb-slp-3.c index 4f47738..2636670 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-3.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-3.c @@ -42,5 +42,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-30.c b/gcc/testsuite/gcc.dg/vect/bb-slp-30.c index 224f9de..c3d7ae1 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-30.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-30.c @@ -50,4 +50,4 @@ int main() return a[21]; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-31.c b/gcc/testsuite/gcc.dg/vect/bb-slp-31.c index 8e4e2d4..6a131e7 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-31.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-31.c @@ -9,4 +9,4 @@ void f(){ a[1]=1+2*a[1]*a[1]; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-32.c b/gcc/testsuite/gcc.dg/vect/bb-slp-32.c index 41bbf35..020b636 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-32.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-32.c @@ -7,16 +7,21 @@ int foo (int *p, int a, int b) { int x[4]; int tem0, tem1, tem2, tem3; + int sum = 0; tem0 = p[0] + 1 + a; + sum += tem0; x[0] = tem0; tem1 = p[1] + 2 + b; + sum += tem1; x[1] = tem1; tem2 = p[2] + 3 + b; + sum += tem2; x[2] = tem2; tem3 = p[3] + 4 + a; + sum += tem3; x[3] = tem3; bar (x); - return tem0 + tem1 + tem2 + tem3; + return sum; } /* { dg-final { scan-tree-dump "vectorization is not profitable" "slp2" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-34.c b/gcc/testsuite/gcc.dg/vect/bb-slp-34.c index c51c770..a625c45 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-34.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-34.c @@ -32,4 +32,4 @@ int main() return 0; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_perm } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target vect_perm } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-35.c b/gcc/testsuite/gcc.dg/vect/bb-slp-35.c index 5803f8e..81b228b 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-35.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-35.c @@ -9,4 +9,4 @@ void foo (int * __restrict__ p, short * __restrict__ q) p[3] = q[3] + 1; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_hw_misalign } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target vect_hw_misalign } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-36.c b/gcc/testsuite/gcc.dg/vect/bb-slp-36.c index f424d12..fbcedd0 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-36.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-36.c @@ -32,4 +32,4 @@ int main() return 0; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_perm } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target vect_perm } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-38.c b/gcc/testsuite/gcc.dg/vect/bb-slp-38.c index 59aec54..a7bc032 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-38.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-38.c @@ -40,5 +40,4 @@ int main() return 0; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_perm } } } */ -/* { dg-final { scan-tree-dump-times "basic block part vectorized" 2 "slp2" { target vect_perm } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target vect_perm } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-4.c b/gcc/testsuite/gcc.dg/vect/bb-slp-4.c index 293b0e3..9e36963 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-4.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-4.c @@ -38,4 +38,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-45.c b/gcc/testsuite/gcc.dg/vect/bb-slp-45.c new file mode 100644 index 0000000..d24ef2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-45.c @@ -0,0 +1,36 @@ +/* { dg-require-effective-target vect_double } */ + +#include "tree-vect.h" + +extern void abort (void); + +double a[8], b[8]; +int x; + +void __attribute__((noinline,noclone)) +bar (void) +{ + x = 1; +} + +void __attribute__((noinline,noclone)) +foo(int i) +{ + double tem1 = a[2*i]; + double tem2 = 2*a[2*i+1]; + bar (); + b[2*i] = 2*tem1; + b[2*i+1] = tem2; +} + +int main() +{ + int i; + check_vect (); + for (i = 0; i < 8; ++i) + b[i] = i; + foo (2); + return 0; +} + +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-46.c b/gcc/testsuite/gcc.dg/vect/bb-slp-46.c new file mode 100644 index 0000000..8daa5c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-46.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-additional-options "-fdump-tree-optimized" } */ + +int a[4], b[4]; +int foo () +{ + int tem0 = a[0] + b[0]; + int temx = tem0 * 17; /* this fails without a real need */ + int tem1 = a[1] + b[1]; + int tem2 = a[2] + b[2]; + int tem3 = a[3] + b[3]; + int temy = tem3 * 13; + a[0] = tem0; + a[1] = tem1; + a[2] = tem2; + a[3] = tem3; + return temx + temy; +} + +/* We should extract the live lane from the vectorized add rather than + keeping the original scalar add. + ??? Because of a too conservative check we fail for temx here. */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */ +/* { dg-final { scan-tree-dump "extracting lane for live stmt" "slp2" } } */ +/* { dg-final { scan-tree-dump-times "extracting lane for live stmt" 2 "slp2" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times " \\+ " 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\+ " 2 "optimized" { xfail *-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-47.c b/gcc/testsuite/gcc.dg/vect/bb-slp-47.c new file mode 100644 index 0000000..9583b09 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-47.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +int bar(); +int foo (int *a, int b, int c) +{ + int tem0 = bar (); + int tem1 = tem0 + b; + int tem3 = tem1 + c; + a[0] = tem3; + a[1] = tem3 + 1; + a[2] = tem3 + 2; + a[3] = tem3 + 3; + return tem1; +} diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-48.c b/gcc/testsuite/gcc.dg/vect/bb-slp-48.c new file mode 100644 index 0000000..dfae617 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-48.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fgimple -fdump-tree-optimized" } */ +/* { dg-require-effective-target vect_double } */ + +double a[2]; + +void __GIMPLE (ssa,startwith ("fix_loops")) +foo (double x) +{ + double tem2; + double tem1; + double _1; + double _2; + double _3; + double _4; + + __BB(2): + _1 = a[0]; + _2 = x_6(D) * 3.0e+0; + tem1_7 = _1 + _2; + _3 = x_6(D) + 1.0e+0; + _4 = a[1]; + tem2_8 = _4 + _3; + a[0] = tem1_7; + a[1] = tem2_8; + return; +} + +void __GIMPLE (ssa,startwith ("fix_loops")) +bar (double x) +{ + double tem2; + double tem1; + double _1; + double _2; + double _3; + double _4; + + __BB(2): + _1 = a[0]; + _2 = x_6(D) * 3.0e+0; + tem1_7 = _1 + _2; + _3 = x_6(D) + 1.0e+0; + _4 = a[1]; + /* Once with operands swapped. */ + tem2_8 = _3 + _4; + a[0] = tem1_7; + a[1] = tem2_8; + return; +} + +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" } } */ +/* We want to vectorize as { a[0], a[1] } + { x*3, x+1 } and thus + elide one add in each function. */ +/* { dg-final { scan-tree-dump-times " \\+ " 4 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-49.c b/gcc/testsuite/gcc.dg/vect/bb-slp-49.c new file mode 100644 index 0000000..e7101fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-49.c @@ -0,0 +1,28 @@ +/* This checks that vectorized constructors have the correct ordering. */ +/* { dg-require-effective-target vect_int } */ + +typedef int V __attribute__((__vector_size__(16))); + +__attribute__((__noipa__)) void +foo (unsigned int x, V *y) +{ + unsigned int a[4] = { x + 0, x + 2, x + 4, x + 6 }; + for (unsigned int i = 0; i < 3; ++i) + if (a[i] == 1234) + a[i]--; + *y = (V) { a[3], a[2], a[1], a[0] }; +} + +int +main () +{ + V b; + foo (0, &b); + if (b[0] != 6 || b[1] != 4 || b[2] != 2 || b[3] != 0) + __builtin_abort (); + return 0; +} + +/* See that we vectorize an SLP instance. */ +/* { dg-final { scan-tree-dump "Analyzing vectorizable constructor" "slp1" } } */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-5.c b/gcc/testsuite/gcc.dg/vect/bb-slp-5.c index 192b7dc..bb78e1b 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-5.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-5.c @@ -47,5 +47,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-50.c b/gcc/testsuite/gcc.dg/vect/bb-slp-50.c new file mode 100644 index 0000000..80216be --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-50.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_double } */ + +double a[2]; +double b[2]; +double c[2]; +double d[2]; +double e[2]; +void foo(double x) +{ + double tembc0 = b[1] + c[1]; + double tembc1 = b[0] + c[0]; + double temde0 = d[0] + e[1]; + double temde1 = d[1] + e[0]; + a[0] = tembc0 + temde0; + a[1] = tembc1 + temde1; +} + +/* We should common the permutation on the tembc{0,1} operands. */ +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 2 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-51.c b/gcc/testsuite/gcc.dg/vect/bb-slp-51.c new file mode 100644 index 0000000..1481018 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-51.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_double } */ + +double a[2]; +double b[2]; +double c[2]; +double e[2]; +void foo(double x) +{ + double tembc0 = b[1] + c[1]; + double tembc1 = b[0] + c[0]; + double temde0 = 5 + e[1]; + double temde1 = 11 + e[0]; + a[0] = tembc0 + temde0; + a[1] = tembc1 + temde1; +} + +/* We should common the permutations on the tembc{0,1} and temde{0,1} + operands. */ +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\r\\n\]* VEC_PERM_EXPR" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-6.c b/gcc/testsuite/gcc.dg/vect/bb-slp-6.c index 98fe5ea..fa3e76d 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-6.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-6.c @@ -45,5 +45,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-7.c b/gcc/testsuite/gcc.dg/vect/bb-slp-7.c index b8bef8c..ebe8189 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-7.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-7.c @@ -22,6 +22,7 @@ main1 (unsigned int x, unsigned int y) a2 = *pin++ + 2; a3 = *pin++ * 31; + /* But we can still vectorize the multiplication or the store. */ *pout++ = a0 * x; *pout++ = a1 * y; *pout++ = a2 * x; @@ -46,5 +47,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 0 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-8.c b/gcc/testsuite/gcc.dg/vect/bb-slp-8.c index 750d713..b653469 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-8.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-8.c @@ -48,5 +48,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_hw_misalign } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_hw_misalign } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-8a.c b/gcc/testsuite/gcc.dg/vect/bb-slp-8a.c index cf355ef..381593b 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-8a.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-8a.c @@ -47,5 +47,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 0 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 0 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-8b.c b/gcc/testsuite/gcc.dg/vect/bb-slp-8b.c index a5b643b..03a47fd 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-8b.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-8b.c @@ -49,5 +49,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_hw_misalign } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_hw_misalign } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-9.c b/gcc/testsuite/gcc.dg/vect/bb-slp-9.c index d022d5f..b4cc101 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-9.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-9.c @@ -46,5 +46,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c index 65d83a4..87ffc9b 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-div-1.c @@ -16,4 +16,4 @@ f (void) x[7] /= 9; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { xfail *-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c index 715c22a..dd17e8c 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-div-2.c @@ -11,4 +11,4 @@ f (void) x[3] += y[3] / z[3] * 2; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_int } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c index 0082b83..5a9fe42 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c @@ -64,4 +64,4 @@ main (void) /* { dg-final { scan-tree-dump "demoting int to signed short" "slp2" { target { ! vect_widen_shift } } } } */ /* { dg-final { scan-tree-dump "demoting int to unsigned short" "slp2" { target { ! vect_widen_shift } } } } */ /* { dg-final { scan-tree-dump {\.AVG_FLOOR} "slp2" { target vect_avg_qi } } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" { target vect_hw_misalign } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" { target vect_hw_misalign } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c index 042b7e9..15a94e6 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c @@ -63,4 +63,4 @@ main (void) /* { dg-final { scan-tree-dump "demoting int to signed short" "slp2" { target { ! vect_widen_shift } } } } */ /* { dg-final { scan-tree-dump "demoting int to unsigned short" "slp2" { target { ! vect_widen_shift } } } } */ /* { dg-final { scan-tree-dump {\.AVG_FLOOR} "slp2" { target vect_avg_qi } } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" { target vect_hw_misalign } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" { target vect_hw_misalign } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c index d32cb75..f6b99ea 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c @@ -49,4 +49,4 @@ int main () return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" { target { vect_element_align && vect_pack_trunc } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" { target { vect_element_align && vect_pack_trunc } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-phis-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-phis-1.c new file mode 100644 index 0000000..014c13b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-phis-1.c @@ -0,0 +1,20 @@ +/* From gcc.c-torture/execute/loop-13.c */ +/* { dg-do compile } */ +/* { dg-additional-options "-march=cascadelake" { target x86_64-*-* i?86-*-* } } */ +#define TYPE long + +void +scale (TYPE *alpha, TYPE *x, int n) +{ + int i, ix; + + if (*alpha != 1) + for (i = 0, ix = 0; i < n; i++, ix += 2) + { + TYPE tmpr, tmpi; + tmpr = *alpha * x[ix]; + tmpi = *alpha * x[ix + 1]; + x[ix] = tmpr; + x[ix + 1] = tmpi; + } +} diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c index cfe654e..fc76700 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c @@ -29,4 +29,4 @@ main (void) -mno-allow-movmisalign prevents vectorization. On POWER8 and later, when vect_hw_misalign is true, vectorization occurs. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target {{ ! powerpc*-*-* } || { powerpc*-*-* && vect_hw_misalign }} } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target {{ ! powerpc*-*-* } || { powerpc*-*-* && vect_hw_misalign }} } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr58135.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr58135.c index ca25000..d3ac0de 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr58135.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr58135.c @@ -7,4 +7,4 @@ void foo () a[0] = a[1] = a[2] = a[3] = a[4]= 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c index 0e4f1a7..ea37e4e 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c @@ -59,4 +59,7 @@ int main() /* We should also be able to use 2-lane SLP to initialize the real and imaginary components in the first loop of main. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp1" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 10 "slp1" } } */ +/* We should see the s->phase[dir] operand and only that operand built + from scalars. See PR97334. */ +/* { dg-final { scan-tree-dump-times "Building vector operands from scalars" 1 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr69907.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr69907.c index fe52d18..b348526 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr69907.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr69907.c @@ -1,5 +1,7 @@ /* { dg-do compile } */ -/* { dg-additional-options "-O3" } */ +/* Disable for vectorization using partial vectors since it would have only + one iteration left, consequently BB vectorization won't happen. */ +/* { dg-additional-options "-O3 --param=vect-partial-vector-usage=0" } */ /* { dg-require-effective-target vect_unpack } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c index f5dc534..27cba9b 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c @@ -22,6 +22,6 @@ void foo () but we do want to vectorize the other two store groups. But we may end up using scalar loads to vectorize the last group. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 3 "slp2" } } */ /* { dg-final { scan-tree-dump-times "BB vectorization with gaps at the end of a load is not supported" 1 "slp2" } } */ /* { dg-final { scan-tree-dump-times " = c\\\[4\\\];" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-1.c index f024dc7..dcba9a0 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-1.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-1.c @@ -89,4 +89,4 @@ f6 (int n) } } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 6 "slp1" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 6 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-2.c index 11e8f0f..6b213d4 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-2.c @@ -61,4 +61,4 @@ f4 (double *p, double *q) } } -/* { dg-final { scan-tree-dump-not "basic block vectorized" "slp1" } } */ +/* { dg-final { scan-tree-dump-not "optimized: basic block" "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-3.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-3.c index 1cca1d0..793f185 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-3.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-3.c @@ -59,4 +59,4 @@ f4 (double *p, double *q, unsigned int start, unsigned int n) } } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 4 "slp1" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 4 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-4.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-4.c index 1aa3c8d..599f718 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-4.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr81635-4.c @@ -44,4 +44,4 @@ f3 (double *p, double *q, unsigned int start, unsigned int n) } } -/* { dg-final { scan-tree-dump-not "basic block vectorized" "slp1" } } */ +/* { dg-final { scan-tree-dump-not "optimized: basic block" "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr90006.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr90006.c index 104d3fb..7d82e94 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr90006.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr90006.c @@ -28,4 +28,4 @@ int e() return 0; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target { { x86_64-*-* i?86-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" { target { { x86_64-*-* i?86-*-* } && ilp32 } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839-2.c index 49e75d8..5a831ae 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839-2.c @@ -16,5 +16,5 @@ v2df g(v2df a, v2df b) /* Verify we manage to vectorize this with using the original vectors and do not end up with any vector CTORs. */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" } } */ /* { dg-final { scan-tree-dump-not "vect_cst" "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839.c index 0bfba01..931fd46 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95839.c @@ -10,4 +10,4 @@ v4f32 f(v4f32 a, v4f32 b) return (v4f32){a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]}; } -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c index 5de4671..edcaf17 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr95866.c @@ -14,4 +14,4 @@ void foo() /* The scalar shift argument should be extracted from the available vector. */ /* { dg-final { scan-tree-dump "BIT_FIELD_REF" "slp2" } } */ -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-1.c index 39c23c3..40a02ed 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-1.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-1.c @@ -41,4 +41,4 @@ main (int argc, char **argv) } /* { dg-final { scan-tree-dump-times "Basic block will be vectorized using SLP" 1 "slp2" } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-2.c index 36938d0..968cdf1 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-2.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-2.c @@ -39,4 +39,4 @@ main (int argc, char **argv) } /* { dg-final { scan-tree-dump-times "Basic block will be vectorized using SLP" 1 "slp2" } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c index 6ae9a89..fe36f90 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-subgroups-3.c @@ -38,4 +38,4 @@ main (int argc, char **argv) } /* { dg-final { scan-tree-dump-times "Basic block will be vectorized using SLP" 1 "slp2" } } */ -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-bb-slp-9a.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-bb-slp-9a.c index 915a962..df01918 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-bb-slp-9a.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-bb-slp-9a.c @@ -38,4 +38,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c index e65a30c..ef74785 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c @@ -74,10 +74,28 @@ foo (int* diff) d[13] = m[12] - m[13]; d[14] = m[14] + m[15]; d[15] = m[15] - m[14]; + /* The following obviously profitable part should not make + the former unprofitable one profitable. */ + diff[16 + 16] = diff[16]; + diff[17 + 16] = diff[17]; + diff[18 + 16] = diff[18]; + diff[19 + 16] = diff[19]; + diff[20 + 16] = diff[20]; + diff[21 + 16] = diff[21]; + diff[22 + 16] = diff[22]; + diff[23 + 16] = diff[23]; + diff[24 + 16] = diff[24]; + diff[25 + 16] = diff[25]; + diff[26 + 16] = diff[26]; + diff[27 + 16] = diff[27]; + diff[28 + 16] = diff[28]; + diff[29 + 16] = diff[29]; + diff[30 + 16] = diff[30]; + diff[31 + 16] = diff[31]; for (k=0; k<16; k++) satd += abs(d[k]); return satd; } /* { dg-final { scan-tree-dump "vectorization is not profitable" "slp1" } } */ -/* { dg-final { scan-tree-dump-not "basic block vectorized" "slp1" } } */ +/* { dg-final { scan-tree-dump-times "Vectorizing SLP tree" 1 "slp1" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-slp.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-slp.c index 5121a88..819c4f6 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-slp.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-slp.c @@ -25,4 +25,4 @@ foo () } /* { dg-final { scan-tree-dump-not "vectorization is not profitable" "slp2" } } */ -/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" } } */ +/* { dg-final { scan-tree-dump "optimized: basic block" "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-1.c b/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-1.c index 1c75c87..cfea872 100644 --- a/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-1.c +++ b/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-1.c @@ -45,4 +45,4 @@ main () return main1 (); } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target { vect_call_copysignf && vect_call_sqrtf } } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target { vect_call_copysignf && vect_call_sqrtf } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c b/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c index 49a7c05..6d67d12 100644 --- a/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c +++ b/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c @@ -63,4 +63,4 @@ main () return main1 (); } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" { target vect_call_lrint } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" { target vect_call_lrint } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c b/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c index c7f9cd3..2202362 100644 --- a/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c +++ b/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c @@ -47,5 +47,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" { target vect_int_mult } } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" { target vect_int_mult } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c b/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c index 8fe67f4..e837418 100644 --- a/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c +++ b/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c @@ -13,4 +13,4 @@ A sum(A a,A b) return a; } -/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr37027.c b/gcc/testsuite/gcc.dg/vect/pr37027.c index ef6760e..69f5826 100644 --- a/gcc/testsuite/gcc.dg/vect/pr37027.c +++ b/gcc/testsuite/gcc.dg/vect/pr37027.c @@ -33,4 +33,4 @@ foo (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_add } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_add } } } */ - +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr65947-3.c b/gcc/testsuite/gcc.dg/vect/pr65947-3.c index 6b4077e..f1bfad6 100644 --- a/gcc/testsuite/gcc.dg/vect/pr65947-3.c +++ b/gcc/testsuite/gcc.dg/vect/pr65947-3.c @@ -51,6 +51,10 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 2 "vect" } } */ +/* Since the fix for PR97307 which sinks the load of a[i], preventing + if-conversion to happen, targets that cannot do masked loads only + vectorize the inline copy. */ +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 2 "vect" { target vect_masked_load } } } */ +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 1 "vect" { target { ! vect_masked_load } } } } */ /* { dg-final { scan-tree-dump-times "optimizing condition reduction with FOLD_EXTRACT_LAST" 2 "vect" { target vect_fold_extract_last } } } */ /* { dg-final { scan-tree-dump-not "condition expression based on integer induction." "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr67790.c b/gcc/testsuite/gcc.dg/vect/pr67790.c index 5e2d506..32eacd9 100644 --- a/gcc/testsuite/gcc.dg/vect/pr67790.c +++ b/gcc/testsuite/gcc.dg/vect/pr67790.c @@ -38,3 +38,4 @@ int main() } /* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr92324-4.c b/gcc/testsuite/gcc.dg/vect/pr92324-4.c index 8347985..57e117c 100644 --- a/gcc/testsuite/gcc.dg/vect/pr92324-4.c +++ b/gcc/testsuite/gcc.dg/vect/pr92324-4.c @@ -28,3 +28,5 @@ int main () __builtin_abort (); return 0; } + +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr92558.c b/gcc/testsuite/gcc.dg/vect/pr92558.c index 1d24fa0..11f4132 100644 --- a/gcc/testsuite/gcc.dg/vect/pr92558.c +++ b/gcc/testsuite/gcc.dg/vect/pr92558.c @@ -21,3 +21,5 @@ int main() __builtin_abort (); return 0; } + +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr95495.c b/gcc/testsuite/gcc.dg/vect/pr95495.c index a961aef..683f0f2 100644 --- a/gcc/testsuite/gcc.dg/vect/pr95495.c +++ b/gcc/testsuite/gcc.dg/vect/pr95495.c @@ -14,3 +14,5 @@ h() d += e[f].b >> 1 | e[f].b & 1; } } + +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr96698.c b/gcc/testsuite/gcc.dg/vect/pr96698.c new file mode 100644 index 0000000..1d141c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr96698.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ + +void test(int a, int* i) +{ + for (; a < 5; ++a) + { + int b = 0; + int c = 0; + for (; b != -11; b--) + for (int d = 0; d ==0; d++) + { + *i += c & a; + c = b; + } + } +} + +/* We should be able to vectorize the inner cycle. */ +/* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr96783-1.c b/gcc/testsuite/gcc.dg/vect/pr96783-1.c new file mode 100644 index 0000000..55d1364 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr96783-1.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +void __attribute__((noipa)) +foo (long *a, int off, int n) +{ + for (int i = 0; i < n; ++i) + { + long tem1 = a[0]; + long tem2 = a[1]; + long tem3 = a[2]; + long tem4 = a[off + 1]; + a[0] = tem4; + long tem5 = a[off + 2]; + a[1] = tem5; + long tem6 = a[off + 3]; + a[2] = tem6; + a[off + 1] = tem1; + a[off + 2] = tem2; + a[off + 3] = tem3; + a -= 3; + } +} + +int main () +{ + long a[3 * 9]; + check_vect (); + for (int i = 0; i < 3 * 9; ++i) + a[i] = i; + foo (a + 3 * 5, 6-1, 5); + const long b[3 * 8] = { 0, 1, 2, 21, 22, 23, 18, 19, 20, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; + for (int i = 0; i < 3 * 8; ++i) + if (a[i] != b[i]) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr96783-2.c b/gcc/testsuite/gcc.dg/vect/pr96783-2.c new file mode 100644 index 0000000..33c3710 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr96783-2.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +long a[1024]; +long b[1024]; + +void __attribute__((noipa)) foo () +{ + for (int i = 0; i < 256; ++i) + { + a[3*i] = b[1023 - 3*i - 2]; + a[3*i + 1] = b[1023 - 3*i - 1]; + a[3*i + 2] = b[1023 - 3*i]; + } +} + +int main() +{ + for (int i = 0; i < 1024; ++i) + b[i] = i; + foo (); + for (int i = 0; i < 256; ++i) + if (a[3*i] != 1023 - 3*i - 2 + || a[3*i+1] != 1023 - 3*i - 1 + || a[3*i+2] != 1023 - 3*i) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr96854.c b/gcc/testsuite/gcc.dg/vect/pr96854.c new file mode 100644 index 0000000..e3980d4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr96854.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-ffast-math" } */ + +double _Complex __attribute__((noipa)) +foo (double _Complex acc, const double _Complex *x, const double _Complex* y, int N) +{ + for (int c = 0; c < N; ++c) + acc -= x[c] * y[c]; + return acc; +} + +int +main() +{ + static const double _Complex y[] = { 1, 2, }; + static const double _Complex x[] = { 1, 3, }; + double _Complex ref = foo (0, x, y, 2); + if (__builtin_creal (ref) != -7.) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr96920.c b/gcc/testsuite/gcc.dg/vect/pr96920.c new file mode 100644 index 0000000..af5da4a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr96920.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +int a[1024]; +int b[2048]; + +void foo (int x, int y) +{ + for (int i = 0; i < 1024; ++i) + { + int tem0 = b[2*i]; + int tem1 = b[2*i+1]; + for (int j = 0; j < 32; ++j) + { + int tem = tem0; + tem0 = tem1; + tem1 = tem; + a[i] += tem0; + } + } +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97081-2.c b/gcc/testsuite/gcc.dg/vect/pr97081-2.c new file mode 100644 index 0000000..98ad3c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97081-2.c @@ -0,0 +1,32 @@ +/* PR tree-optimization/97081 */ + +#include "tree-vect.h" + +unsigned short s[1024]; +unsigned char c[1024]; + +__attribute__((noipa)) void +foo (int n) +{ + for (int i = 0; i < 1024; i++) + s[i] = (s[i] << n) | (s[i] >> (__SIZEOF_SHORT__ * __CHAR_BIT__ - n)); + for (int i = 0; i < 1024; i++) + c[i] = (c[i] << n) | (c[i] >> (__CHAR_BIT__ - n)); +} + +int +main () +{ + check_vect (); + for (int i = 0; i < 1024; i++) + { + s[i] = i; + c[i] = i; + } + foo (3); + for (int i = 0; i < 1024; i++) + if (s[i] != (unsigned short) ((i << 3) | (i >> (__SIZEOF_SHORT__ * __CHAR_BIT__ - 3))) + || c[i] != (unsigned char) ((((unsigned char) i) << 3) | (((unsigned char) i) >> (__CHAR_BIT__ - 3)))) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97081.c b/gcc/testsuite/gcc.dg/vect/pr97081.c new file mode 100644 index 0000000..bc83c88 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97081.c @@ -0,0 +1,26 @@ +#include "tree-vect.h" + +#define EXEC_ROR2(a, b, sz) (a >> b) | (a << (64 - b)) + +#define TYPE __UINT64_TYPE__ + +void __attribute__((noipa)) +exec_VRORudi_i(TYPE *__restrict__ pvd, + TYPE *__restrict__ const pva, unsigned char IMM) +{ + unsigned char I2 = IMM & 63; + + for (unsigned i = 0; i < 4; i++) + pvd[i] = EXEC_ROR2(pva[i], I2, 8); +} + +int main() +{ + check_vect (); + + TYPE pvd[4], pva[4] = { 0x0102030405060708, 0x0102030405060708, 0x0102030405060708, 0x0102030405060708 }; + exec_VRORudi_i (pvd, pva, 7); + if (pvd[0] != 0x10020406080a0c0e) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97085.c b/gcc/testsuite/gcc.dg/vect/pr97085.c new file mode 100644 index 0000000..ffde9f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97085.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=armv8.2-a+sve" { target aarch64-*-* } } */ + +int a, b, c, d; +short e, g; +unsigned short f; +void h() { + for (; d; d++) { + g = d; + e = b == 0 ? 1 : a % b; + c ^= (f = e) > (g == 5); + } +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97139.c b/gcc/testsuite/gcc.dg/vect/pr97139.c new file mode 100644 index 0000000..1b9f31c --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97139.c @@ -0,0 +1,27 @@ +/* { dg-require-effective-target vect_int } */ + +#include "tree-vect.h" + +int pix[4]; + +int __attribute__((noipa)) foo (void) +{ + pix[0] = pix[0] / 4; + pix[1] = pix[1] / 4; + pix[2] = pix[2] / 4; + pix[3] = pix[3] / 4; + return pix[0] + pix[1] + pix[2] + pix[3]; +} + +int main () +{ + check_vect (); + + pix[0] = 8; + pix[1] = 16; + pix[2] = 32; + pix[3] = 64; + if (foo () != 30) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97173.c b/gcc/testsuite/gcc.dg/vect/pr97173.c new file mode 100644 index 0000000..fd4a889 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97173.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ + +typedef struct { + char *track; + char *clocks; + char *fm; + char *weak; +} disk_t; + +disk_t disk_update_tlens_d; +int disk_update_tlens_d_0; + +void disk_update_tlens() { + disk_update_tlens_d.track = disk_update_tlens_d.clocks = + disk_update_tlens_d.track + disk_update_tlens_d_0; + disk_update_tlens_d.fm = disk_update_tlens_d.clocks + disk_update_tlens_d_0; + disk_update_tlens_d.weak = disk_update_tlens_d.fm; + disk_update_tlens_d.track[2] = 5; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97236.c b/gcc/testsuite/gcc.dg/vect/pr97236.c new file mode 100644 index 0000000..9d3dc20 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97236.c @@ -0,0 +1,43 @@ +typedef unsigned char __uint8_t; +typedef __uint8_t uint8_t; +typedef struct plane_t { + uint8_t *p_pixels; + int i_lines; + int i_pitch; +} plane_t; + +typedef struct { + plane_t p[5]; +} picture_t; + +#define N 4 + +void __attribute__((noipa)) +picture_Clone(picture_t *picture, picture_t *res) +{ + for (int i = 0; i < N; i++) { + res->p[i].p_pixels = picture->p[i].p_pixels; + res->p[i].i_lines = picture->p[i].i_lines; + res->p[i].i_pitch = picture->p[i].i_pitch; + } +} + +int +main() +{ + picture_t aaa, bbb; + uint8_t pixels[10] = {1, 1, 1, 1, 1, 1, 1, 1}; + + for (unsigned i = 0; i < N; i++) + aaa.p[i].p_pixels = pixels; + + picture_Clone (&aaa, &bbb); + + uint8_t c = 0; + for (unsigned i = 0; i < N; i++) + c += bbb.p[i].p_pixels[0]; + + if (c != N) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97241.c b/gcc/testsuite/gcc.dg/vect/pr97241.c new file mode 100644 index 0000000..d4be8f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97241.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 --param max-loop-header-insns=2" } */ + +short int *ev; +int l4; + +short int +a7 (void) +{ + short int uo = ev[0], ie = uo; + + for (int kp = 0; kp < l4; kp += 4) + { + uo += ev[kp + 1]; + ie += ev[kp]; + } + + return uo + ie; +} diff --git a/gcc/testsuite/gcc.dg/vect/slp-3.c b/gcc/testsuite/gcc.dg/vect/slp-3.c index 5e40499..46ab584 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-3.c +++ b/gcc/testsuite/gcc.dg/vect/slp-3.c @@ -141,8 +141,8 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target { ! vect_fully_masked } } } } */ -/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target vect_fully_masked } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { ! vect_fully_masked } } } }*/ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target vect_fully_masked } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target { ! vect_partial_vectors } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target vect_partial_vectors } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { ! vect_partial_vectors } } } }*/ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target vect_partial_vectors } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-46.c b/gcc/testsuite/gcc.dg/vect/slp-46.c index 17dfa285..58a238a 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-46.c +++ b/gcc/testsuite/gcc.dg/vect/slp-46.c @@ -1,4 +1,5 @@ /* { dg-require-effective-target vect_double } */ +/* { dg-additional-options "--param vect-epilogues-nomask=0" } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/slp-multitypes-11.c b/gcc/testsuite/gcc.dg/vect/slp-multitypes-11.c index 5200ed1..9621886 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-multitypes-11.c +++ b/gcc/testsuite/gcc.dg/vect/slp-multitypes-11.c @@ -49,5 +49,7 @@ int main (void) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_unpack } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_unpack xfail { vect_variable_length && vect_load_lanes } } } } */ +/* The epilogues are vectorized using partial vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_unpack && {! vect_partial_vectors_usage_1 } } xfail { vect_variable_length && vect_load_lanes } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_unpack && vect_partial_vectors_usage_1 } xfail { vect_variable_length && vect_load_lanes } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c index ca7803e..4128cca 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c @@ -80,7 +80,9 @@ int main (int argc, const char* argv[]) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && {! vect_load_lanes } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */ +/* The epilogues are vectorized using partial vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-5.c b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c index b86a3dc..b137821 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-5.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c @@ -104,7 +104,9 @@ int main (int argc, const char* argv[]) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */ +/* The epilogues are vectorized using partial vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c index 97a0ebf..3848929 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c @@ -103,7 +103,9 @@ int main (int argc, const char* argv[]) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */ +/* The epilogues are vectorized using partial vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c index 346411f..498999a 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c @@ -96,7 +96,9 @@ int main (int argc, const char* argv[]) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */ +/* The epilogues are vectorized using partial vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-8.c b/gcc/testsuite/gcc.dg/vect/slp-perm-8.c index 17aa111..9e59832 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-8.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-8.c @@ -60,7 +60,9 @@ int main (int argc, const char* argv[]) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm_byte } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_byte && { ! vect_load_lanes } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_byte && { { ! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */ +/* The epilogues are vectorized using partial vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_byte && { { ! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_byte && vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-9.c b/gcc/testsuite/gcc.dg/vect/slp-perm-9.c index c54420a..ab75f44 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-9.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-9.c @@ -61,7 +61,9 @@ int main (int argc, const char* argv[]) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm_short || vect_load_lanes } } } } */ /* We don't try permutes with a group size of 3 for variable-length vectors. */ -/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 1 "vect" { target { vect_perm_short && { ! vect_perm3_short } } xfail vect_variable_length } } } */ +/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 1 "vect" { target { vect_perm_short && { { ! vect_perm3_short } && { ! vect_partial_vectors_usage_1 } } } xfail vect_variable_length } } } */ +/* Try to vectorize the epilogue using partial vectors. */ +/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 2 "vect" { target { vect_perm_short && { { ! vect_perm3_short } && vect_partial_vectors_usage_1 } } xfail vect_variable_length } } } */ /* { dg-final { scan-tree-dump-not "permutation requires at least three vectors" "vect" { target vect_perm3_short } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { { ! vect_perm3_short } || vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_short && { ! vect_load_lanes } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-1.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-1.c index b353dd7..b9bddb8 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-1.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-1.c @@ -44,4 +44,4 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_add } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_add } } } */ - +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-2.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-2.c index 15dd599..aa09d01 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-2.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-2.c @@ -41,4 +41,5 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_add } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_add } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c index 7358275..4969fe8 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c @@ -60,3 +60,4 @@ int main (void) /* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected" 1 "vect" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target { vect_short_mult && { vect_widen_sum_hi_to_si && vect_unpack } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_widen_sum_hi_to_si_pattern || { ! vect_unpack } } } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c index d58e5b0..266b439 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c @@ -58,4 +58,5 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_min_max || vect_variable_length } } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c index f457c11..11f5a741 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c @@ -46,4 +46,4 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail vect_no_int_min_max } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_min_max } } } */ - +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c index 43d1cee..05cc9ed 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c @@ -56,4 +56,4 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_add } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_add || vect_variable_length } } } } */ - +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-13.c b/gcc/testsuite/gcc.dg/vect/vect-cond-13.c new file mode 100644 index 0000000..2dfb879 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cond-13.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +int a[1024]; +int b[1024]; + +int +foo () +{ + int tem; + for (int i = 0; i < 1024; ++i) + { + if (a[i] < 0) + tem = -a[i] - 1; + else + tem = a[i]; + b[i] = tem + 10; + } + return tem; +} + +int main() +{ + check_vect (); + + for (int i = 0; i < 1024; ++i) + { + a[i] = i - 333; + __asm__ volatile ("" ::: "memory"); + } + int res = foo (); + if (res != 1023 - 333) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target vect_condition } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-live-6.c b/gcc/testsuite/gcc.dg/vect/vect-live-6.c new file mode 100644 index 0000000..c986c97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-live-6.c @@ -0,0 +1,31 @@ +#include "tree-vect.h" + +int a[1024]; +int b[1024]; + +_Bool +fn1 () +{ + _Bool tem; + for (int i = 0; i < 1024; ++i) + { + tem = !a[i]; + b[i] = tem; + } + return tem; +} + +int main() +{ + check_vect (); + for (int i = 0; i < 1024; ++i) + { + a[i] = i & 5; + __asm__ volatile ("" ::: "memory"); + } + if (fn1 () != !(1023 & 5) || b[2] != 1) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-in-order-4.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-in-order-4.c index 1cc046e..7706a2d 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-in-order-4.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-in-order-4.c @@ -43,3 +43,4 @@ main () /* { dg-final { scan-tree-dump {in-order unchained SLP reductions not supported} "vect" } } */ /* { dg-final { scan-tree-dump-not {vectorizing stmts using SLP} "vect" } } */ +/* { dg-final { scan-tree-dump-times "VECT_PERM_EXPR" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-17.c b/gcc/testsuite/gcc.dg/vect/vect-simd-17.c new file mode 100644 index 0000000..951ba3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-17.c @@ -0,0 +1,304 @@ +/* { dg-additional-options "-fopenmp-simd -fno-tree-vectorize" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump "vectorized 1\[1-2] loops" "vect" { target i?86-*-* x86_64-*-* } } } */ + +#include "tree-vect.h" + +int x, i, j; +volatile int a, b, c, d, e, f, g, h; +int k[11][101]; + +__attribute__((noipa)) void +doit (void) +{ + int niters, err = 0; + for (i = 1; i <= 10; i++) + for (j = 1; j <= 10 * i; j++) + { + k[i][j] = 1; + asm volatile ("" : : : "memory"); + } + a = 1; b = 11; c = 1; d = 0; e = 1; f = 10; g = 1; h = 1; + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = 1; i <= 10; i++) + for (j = 1; j <= 10 * i; j++) + { + err |= (i < 1); + err |= (i > 10); + err |= (j < 1); + err |= (j > 10 * i); + err |= (k[i][j] != 1); + k[i][j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 11 || j != 101 || x != 10340 || niters != 550 || err) + abort (); + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = a; i < b; i += c) + for (j = d * i + e; j < g + i * f; j += h) + { + err |= (i < 1); + err |= (i > 10); + err |= (j < 1); + err |= (j > 10 * i); + err |= (k[i][j] != 2); + k[i][j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 11 || j != 101 || x != 10340 || niters != 550 || err) + abort (); + for (i = 1; i <= 10; i++) + for (j = 1; j <= 10 * i; j++) + if (k[i][j] == 3) + k[i][j] = 0; + else + abort (); + for (i = 0; i < 11; i++) + for (j = 0; j < 101; j++) + if (k[i][j] != 0) + abort (); + for (i = 0; i < 10; i++) + for (j = 0; j < 10 * i; j++) + { + k[i][j] = 1; + asm volatile ("" : : : "memory"); + } + a = 0; b = 10; c = 1; d = 0; e = 0; f = 10; g = 0; h = 1; + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = 0; i < 10; i++) + for (j = 0; j < 10 * i; j++) + { + err |= (i < 0); + err |= (i >= 10); + err |= (j < 0); + err |= (j >= 10 * i); + err |= (k[i][j] != 1); + k[i][j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 10 || j != 90 || x != 9305 || niters != 450 || err) + abort (); + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = a; i < b; i += c) + for (j = d * i + e; j < g + i * f; j += h) + { + err |= (i < 0); + err |= (i >= 10); + err |= (j < 0); + err |= (j >= 10 * i); + err |= (k[i][j] != 2); + k[i][j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 10 || j != 90 || x != 9305 || niters != 450 || err) + abort (); + for (i = 0; i < 10; i++) + for (j = 0; j < 10 * i; j++) + if (k[i][j] == 3) + k[i][j] = 0; + else + abort (); + for (i = 0; i < 11; i++) + for (j = 0; j < 101; j++) + if (k[i][j] != 0) + abort (); + for (i = 4; i < 10; i++) + for (j = -9 + 2 * i; j < i; j++) + { + k[i][j + 1] = 1; + asm volatile ("" : : : "memory"); + } + a = 4; b = 10; c = 1; d = 2; e = -9; f = 1; g = 0; h = 1; + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = 4; i < 10; i++) + for (j = -9 + 2 * i; j < i; j++) + { + err |= (i < 4); + err |= (i >= 10); + err |= (j < -9 + 2 * i); + err |= (j >= i); + err |= (k[i][j + 1] != 1); + k[i][j + 1]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (/*i != 10 || j != 9 || */x != 8199 || niters != 15 || err) + abort (); + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = a; i < b; i += c) + for (j = d * i + e; j < g + i * f; j += h) + { + err |= (i < 4); + err |= (i >= 10); + err |= (j < -9 + 2 * i); + err |= (j >= i); + err |= (k[i][j + 1] != 2); + k[i][j + 1]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (/*i != 10 || j != 9 || */x != 8199 || niters != 15 || err) + abort (); + for (i = 4; i < 10; i++) + for (j = -9 + 2 * i; j < i; j++) + if (k[i][j + 1] == 3) + k[i][j + 1] = 0; + else + abort (); + for (i = 0; i < 11; i++) + for (j = 0; j < 101; j++) + if (k[i][j] != 0) + abort (); + for (i = 1; i < 10; i += 2) + for (j = 1; j < i + 1; j++) + { + k[i][j] = 1; + asm volatile ("" : : : "memory"); + } + a = 1; b = 10; c = 2; d = 0; e = 1; f = 1; g = 1; h = 1; + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = 1; i < 10; i += 2) + for (j = 1; j < i + 1; j++) + { + err |= (i < 1); + err |= (i >= 10); + err |= (j < 1); + err |= (j >= i + 1); + err |= (k[i][j] != 1); + k[i][j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 11 || j != 10 || x != 9225 || niters != 25 || err) + abort (); + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = a; i < b; i += c) + for (j = d * i + e; j < g + i * f; j += h) + { + err |= (i < 1); + err |= (i >= 10); + err |= (j < 1); + err |= (j >= i + 1); + err |= (k[i][j] != 2); + k[i][j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 11 || j != 10 || x != 9225 || niters != 25 || err) + abort (); + for (i = 1; i < 10; i += 2) + for (j = 1; j < i + 1; j++) + if (k[i][j] == 3) + k[i][j] = 0; + else + abort (); + for (i = 0; i < 11; i++) + for (j = 0; j < 101; j++) + if (k[i][j] != 0) + abort (); + for (j = -11; j >= -41; j -= 15) + { + k[0][-j] = 1; + asm volatile ("" : : : "memory"); + } + a = 4; b = 8; c = 12; d = -8; e = -9; f = -3; g = 6; h = 15; + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = 4; i < 8; i += 12) + for (j = -8 * i - 9; j < i * -3 + 6; j += 15) + { + err |= (i != 4); + err |= (j < -41); + err |= (j > -11); + err |= (k[0][-j] != 1); + k[0][-j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 16 || j != 4 || x != 5109 || niters != 3 || err) + abort (); + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = a; i < b; i += c) + for (j = d * i + e; j < g + i * f; j += h) + { + err |= (i != 4); + err |= (j < -41); + err |= (j > -11); + err |= (k[0][-j] != 2); + k[0][-j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (i != 16 || j != 4 || x != 5109 || niters != 3 || err) + abort (); + for (j = -11; j >= -41; j -= 15) + if (k[0][-j] == 3) + k[0][-j] = 0; + else + abort (); + for (j = -11; j >= -41; j--) + if (k[0][-j] != 0) + abort (); + for (j = -34; j <= -7; j++) + { + k[0][-j] = 1; + asm volatile ("" : : : "memory"); + } + a = -13; b = 7; c = 12; d = 3; e = 5; f = 0; g = -6; h = 1; + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = -13; i < 7; i += 12) + for (j = 3 * i + 5; j < -6; j++) + { + err |= (i != -13); + err |= (j < -34); + err |= (j > -7); + err |= (k[0][-j] != 1); + k[0][-j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (/*i != 11 || j != 2 || */x != -12295 || niters != 28 || err) + abort (); + niters = 0; i = -100; j = -100; x = -100; + #pragma omp simd collapse(2) lastprivate (i, j, x) reduction(+:niters) reduction(|:err) + for (i = a; i < b; i += c) + for (j = d * i + e; j < g + i * f; j += h) + { + err |= (i != -13); + err |= (j < -34); + err |= (j > -7); + err |= (k[0][-j] != 2); + k[0][-j]++; + x = i * 1024 + (j & 1023); + niters++; + } + if (/*i != 11 || j != 2 || */x != -12295 || niters != 28 || err) + abort (); + for (j = -34; j <= -7; j++) + if (k[0][-j] == 3) + k[0][-j] = 0; + else + abort (); +} + +int +main () +{ + check_vect (); + doit (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-18.c b/gcc/testsuite/gcc.dg/vect/vect-simd-18.c new file mode 100644 index 0000000..b25f5a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-18.c @@ -0,0 +1,40 @@ +/* { dg-additional-options "-fopenmp-simd -fno-tree-vectorize" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target i?86-*-* x86_64-*-* } } } */ + +#include "tree-vect.h" + +__attribute__((noipa)) int +foo (int s, int *p) +{ + int r = 0, l = 0, i; + #pragma omp simd reduction (+:r) linear(l) + for (i = 0; i < 10000; i += s) + { + p[l++] = i; + r += i * 3; + } + return r; +} + +int p[10000 / 78]; + +int +main () +{ + int i, r; + check_vect (); + r = foo (78, p); + for (i = 0; i < 10000 / 78; i++) + if (p[i] != 78 * i) + abort (); + if (r != (10000 / 78) * (10000 / 78 + 1) / 2 * 78 * 3) + abort (); + r = foo (87, p); + for (i = 0; i < 10000 / 87; i++) + if (p[i] != 87 * i) + abort (); + if (r != (10000 / 87) * (10000 / 87 + 1) / 2 * 87 * 3) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-19.c b/gcc/testsuite/gcc.dg/vect/vect-simd-19.c new file mode 100644 index 0000000..a71dfa6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-19.c @@ -0,0 +1,40 @@ +/* { dg-additional-options "-fopenmp-simd -fno-tree-vectorize" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target i?86-*-* x86_64-*-* } } } */ + +#include "tree-vect.h" + +__attribute__((noipa)) int +foo (int s, int m, int n, int *p) +{ + int r = 0, l = 0, i; + #pragma omp simd reduction (+:r) linear(l) + for (i = m; i < n; i += s) + { + p[l++] = i; + r += i * 3; + } + return r; +} + +int p[10000 / 78]; + +int +main () +{ + int i, r; + check_vect (); + r = foo (78, 0, 10000, p); + for (i = 0; i < 10000 / 78; i++) + if (p[i] != 78 * i) + abort (); + if (r != (10000 / 78) * (10000 / 78 + 1) / 2 * 78 * 3) + abort (); + r = foo (87, 0, 10000, p); + for (i = 0; i < 10000 / 87; i++) + if (p[i] != 87 * i) + abort (); + if (r != (10000 / 87) * (10000 / 87 + 1) / 2 * 87 * 3) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-20.c b/gcc/testsuite/gcc.dg/vect/vect-simd-20.c new file mode 100644 index 0000000..c85f05f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-20.c @@ -0,0 +1,43 @@ +/* { dg-additional-options "-fopenmp-simd -fno-tree-vectorize" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target i?86-*-* x86_64-*-* } } } */ + +#include "tree-vect.h" + +__attribute__((noipa)) int +foo (int s, int m, int n, int *p) +{ + int r = 0, l = 0, i, j; + #pragma omp simd reduction (+:r) linear(l) collapse(2) + for (j = 0; j < 7; j++) + for (i = m; i < n; i += s) + { + p[l++] = i; + r += i * 3; + } + return r; +} + +int p[10000 / 78 * 7]; + +int +main () +{ + int i, j, r; + check_vect (); + r = foo (78, 0, 10000, p); + for (j = 0; j < 7; j++) + for (i = 0; i < 10000 / 78; i++) + if (p[j * (10000 / 78 + 1) + i] != 78 * i) + abort (); + if (r != (10000 / 78) * (10000 / 78 + 1) / 2 * 78 * 3 * 7) + abort (); + r = foo (87, 0, 10000, p); + for (j = 0; j < 7; j++) + for (i = 0; i < 10000 / 87; i++) + if (p[j * (10000 / 87 + 1) + i] != 87 * i) + abort (); + if (r != (10000 / 87) * (10000 / 87 + 1) / 2 * 87 * 3 * 7) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-version-2.c b/gcc/testsuite/gcc.dg/vect/vect-version-2.c index 0ea39e3..7d3fb72 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-version-2.c +++ b/gcc/testsuite/gcc.dg/vect/vect-version-2.c @@ -17,4 +17,8 @@ void foo (double *x, double *y, int m, int n, int o, int p) } } -/* { dg-final { scan-tree-dump "reusing loop version created by if conversion" "vect" } } */ +/* Vectorization using partial vectors has zero versioning_threshold with + either usage 1 or usage 2, the cond_expr replies on the computation in + outer loop, so it doesn't need to reuse the loop version created by if + conversion. */ +/* { dg-final { scan-tree-dump "reusing loop version created by if conversion" "vect" {target {! vect_partial_vectors } } } } */ diff --git a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c index e91e8ce..76180a3 100644 --- a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c +++ b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c @@ -62,5 +62,11 @@ void test (int n0) int n = n0 < n1 ? n1 : n0; - sink (strnlen (c + n, n + 1)); /* { dg-warning "specified bound \\\[5, \[0-9\]+] may exceed the size of at most 4 of unterminated array" } */ + /* N is at least 4 and c[4] is out-of-bounds. This could trigger + either -Warray-bounds or -Wstringop-overread. -Warray-bounds + only diagnoses past-the-end accesses by modifying functions + (in gimple-ssa-warn-restrict.c) and even for those, either + -Wstringop-overflow or -Wstringop-overread would be more + appropriate. */ + sink (strnlen (c + n, n + 1)); /* { dg-warning "specified bound \\\[5, \[0-9\]+] exceeds the size of at most 4 of unterminated array" } */ } diff --git a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c index 09a527e..02f6f3d 100644 --- a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c +++ b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c @@ -35,7 +35,7 @@ T (&a[1], asz - 1); T (&a[v0], asz); /* { dg-warning "specified bound 5 may exceed the size of at most 5 of unterminated array" } */ T (&a[v0] + 1, asz); /* { dg-warning "specified bound 5 may exceed the size of at most 5 of unterminated array" } */ -T (a, asz + 1); /* { dg-warning "specified bound 6 exceeds the size 5 " } */ +T (a, asz + 1); /* { dg-warning "specified bound 6 exceeds the size 5 of unterminated array" } */ T (&a[0], asz + 1); /* { dg-warning "unterminated" } */ T (&a[0] + 1, asz - 1); T (&a[0] + 1, asz + 1); /* { dg-warning "unterminated" } */ @@ -110,7 +110,7 @@ T (&b[3][1] + i1, bsz); /* { dg-warning "unterminated" } */ T (&b[3][1] + i1, bsz - i1); /* { dg-warning "unterminated" } */ T (&b[3][1] + i1, bsz - i2); T (&b[3][v0], bsz); -T (&b[3][1] + v0, bsz); /* { dg-warning "specified bound 5 may exceed the size of at most 4 of unterminated array" } */ +T (&b[3][1] + v0, bsz); /* { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" } */ T (&b[3][v0] + v1, bsz); /* { dg-warning "specified bound 5 may exceed the size of at most 4 of unterminated array" "pr?????" { xfail *-*-* } } */ T (&b[3][1], bsz + 1); /* { dg-warning "unterminated" } */ @@ -124,7 +124,7 @@ T (&b[i3][i1], bsz); /* { dg-warning "unterminated" } */ T (&b[i3][i1] + 1, bsz); /* { dg-warning "unterminated" } */ T (&b[i3][i1] + i1, bsz); /* { dg-warning "specified bound 5 exceeds the size 3 of unterminated array" } */ T (&b[i3][v0], bsz); -T (&b[i3][i1] + v0, bsz); /* { dg-warning "specified bound 5 may exceed the size of at most 4 of unterminated array" } */ +T (&b[i3][i1] + v0, bsz); /* { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" } */ T (&b[i3][v0] + v1, bsz); T (&b[i3][i1], bsz + 1); /* { dg-warning "unterminated" } */ @@ -212,10 +212,10 @@ T (&s.a[i1] + v0, asz); T (s.a, asz + 1); T (&s.a[0], asz + 1); T (&s.a[0] + 1, asz + 1); -T (&s.a[0] + v0, asz + 1); +T (&s.a[0] + v0, asz + 1); /* { dg-warning "specified bound 6 exceeds source size 5 " } */ T (&s.a[1], asz + 1); T (&s.a[1] + 1, asz + 1); -T (&s.a[1] + v0, asz + 1); +T (&s.a[1] + v0, asz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" "pr95794" { xfail *-*-* } } */ T (&s.a[i0], asz + 1); T (&s.a[i0] + i1, asz + 1); @@ -266,10 +266,10 @@ const struct B ba[] = { T (ba[0].a[0].a, asz + 1); T (&ba[0].a[0].a[0], asz + 1); T (&ba[0].a[0].a[0] + 1, asz + 1); -T (&ba[0].a[0].a[0] + v0, asz + 1); +T (&ba[0].a[0].a[0] + v0, asz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */ T (&ba[0].a[0].a[1], asz + 1); T (&ba[0].a[0].a[1] + 1, asz + 1); -T (&ba[0].a[0].a[1] + v0, asz + 1); +T (&ba[0].a[0].a[1] + v0, asz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */ T (ba[0].a[0].b, bsz); T (&ba[0].a[0].b[0], bsz); @@ -302,10 +302,10 @@ T (&ba[0].a[1].a[1] + v0, asz + 1); /* { dg-warning "unterminated" } */ T (ba[0].a[1].b, bsz + 1); T (&ba[0].a[1].b[0], bsz + 1); T (&ba[0].a[1].b[0] + 1, bsz + 1); -T (&ba[0].a[1].b[0] + v0, bsz + 1); +T (&ba[0].a[1].b[0] + v0, bsz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */ T (&ba[0].a[1].b[1], bsz + 1); T (&ba[0].a[1].b[1] + 1, bsz + 1); -T (&ba[0].a[1].b[1] + v0, bsz + 1); +T (&ba[0].a[1].b[1] + v0, bsz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */ T (ba[1].a[0].a, asz); T (&ba[1].a[0].a[0], asz); |