diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-12-03 12:12:10 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-12-03 12:12:10 -0800 |
commit | f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (patch) | |
tree | 582e5d7b377b6e973666a71960b28a7d11d72b07 /gcc/testsuite/gcc.dg | |
parent | 8d703821c69062c0cd255787d793e44f1a95d463 (diff) | |
parent | 3089f5feef36810c625b5813370a97b4ecc841f8 (diff) | |
download | gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.zip gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.tar.gz gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.tar.bz2 |
Merge from trunk revision 3089f5feef36810c625b5813370a97b4ecc841f8
Diffstat (limited to 'gcc/testsuite/gcc.dg')
225 files changed, 5791 insertions, 223 deletions
diff --git a/gcc/testsuite/gcc.dg/20021029-1.c b/gcc/testsuite/gcc.dg/20021029-1.c index f11a6e4..57c2b48 100644 --- a/gcc/testsuite/gcc.dg/20021029-1.c +++ b/gcc/testsuite/gcc.dg/20021029-1.c @@ -3,6 +3,7 @@ /* { dg-do compile { target fpic } } */ /* { dg-options "-O2 -fpic" } */ /* { dg-final { scan-assembler-not ".data.rel.ro.local" } } */ +/* { dg-final { scan-assembler-symbol-section {ar} {^\.(const|rodata)|\[RO\]} } } */ /* { dg-require-effective-target label_values } */ /* { dg-require-effective-target indirect_jumps } */ diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-43.c b/gcc/testsuite/gcc.dg/Warray-bounds-43.c index 8892921..0f521a7 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-43.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-43.c @@ -5,20 +5,9 @@ #define NOIPA __attribute__ ((noipa)) -const char a0[] = ""; -const char a1[] = "1"; -const char a2[] = "12"; -const char a3[] = "123"; -const char a4[] = "1234"; -const char a5[] = "12345"; -const char a6[] = "123456"; -const char a7[] = "1234567"; -const char a8[] = "12345678"; const char a9[] = "123456789"; -void f (const char*, ...); - -int i0, i1, i2, i3, i4, i5, i6, i7, i8; +void sink (const char*, ...); NOIPA int g2 (int i) { @@ -28,7 +17,7 @@ NOIPA int g2 (int i) const char *p1 = p0 + i; const char *p2 = p1 + i; - f (p0, p1, p2); + sink (p0, p1, p2); return p2[8]; // { dg-warning "\\\[-Warray-bounds]" } } @@ -42,7 +31,7 @@ NOIPA int g3 (int i) const char *p2 = p1 + i; const char *p3 = p2 + i; - f (p0, p1, p2, p3); + sink (p0, p1, p2, p3); return p3[7]; // { dg-warning "\\\[-Warray-bounds]" } } @@ -57,7 +46,7 @@ NOIPA int g4 (int i) const char *p3 = p2 + i; const char *p4 = p3 + i; - f (p0, p1, p2, p3, p4); + sink (p0, p1, p2, p3, p4); return p4[6]; // { dg-warning "\\\[-Warray-bounds]" } } @@ -73,7 +62,7 @@ NOIPA int g5 (int i) const char *p4 = p3 + i; const char *p5 = p4 + i; - f (p0, p1, p2, p3, p4, p5); + sink (p0, p1, p2, p3, p4, p5); return p5[5]; } @@ -90,7 +79,7 @@ NOIPA int g6 (int i) const char *p5 = p4 + i; const char *p6 = p5 + i; - f (p0, p1, p2, p3, p4, p5, p6); + sink (p0, p1, p2, p3, p4, p5, p6); return p6[4]; } @@ -108,7 +97,7 @@ NOIPA int g7 (int i) const char *p6 = p5 + i; const char *p7 = p6 + i; - f (p0, p1, p2, p3, p4, p5, p6, p7); + sink (p0, p1, p2, p3, p4, p5, p6, p7); return p7[3]; } @@ -127,7 +116,7 @@ NOIPA int g8 (int i) const char *p7 = p6 + i; const char *p8 = p7 + i; - f (p0, p1, p2, p3, p4, p5, p6, p7, p8); + sink (p0, p1, p2, p3, p4, p5, p6, p7, p8); return p8[2]; } diff --git a/gcc/testsuite/gcc.dg/Wstring-compare-3.c b/gcc/testsuite/gcc.dg/Wstring-compare-3.c new file mode 100644 index 0000000..d4d7121 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstring-compare-3.c @@ -0,0 +1,106 @@ +/* PR middle-end/95673 - missing -Wstring-compare for an impossible strncmp test + { dg-do compile } + { dg-options "-O2 -Wall -Wstring-compare -ftrack-macro-expansion=0" } */ + +typedef __SIZE_TYPE__ size_t; + +extern int strcmp (const char*, const char*); +extern int strncmp (const char*, const char*, size_t); + +void sink (int, ...); + +extern char a3[3]; + +int nowarn_strcmp_one_use_ltz (int c) +{ + const char *s = c ? "1234" : a3; + int n = strcmp (s, "123"); + return n < 0; +} + + +int nowarn_strcmp_one_use_eqnz (int c) +{ + const char *s = c ? "12345" : a3; + int n = strcmp (s, "123"); + return n == 1; +} + + +int warn_strcmp_one_use_eqz (int c) +{ + const char *s = c ? "123456" : a3; + int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" } + return n == 0; // { dg-message "in this expression" } +} + + +int warn_strcmp_one_use_bang (int c) +{ + const char *s = c ? "1234567" : a3; + int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" } + return !n; // { dg-message "in this expression" } +} + + +int warn_strcmp_one_use_bang_bang (int c) +{ + const char *s = c ? "12345678" : a3; + int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" } + return !!n; // { dg-message "in this expression" } +} + + +_Bool warn_one_use_bool (int c) +{ + const char *s = c ? "123456789" : a3; + int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" } + return (_Bool)n; // { dg-message "in this expression" } +} + + +int warn_strcmp_one_use_cond (int c) +{ + const char *s = c ? "1234567890" : a3; + int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" } + return n ? 3 : 5; // { dg-message "in this expression" } +} + + +int nowarn_strcmp_multiple_uses (int c) +{ + const char *s = c ? "1234" : a3; + int n = strcmp (s, "123"); + sink (n < 0); + sink (n > 0); + sink (n <= 0); + sink (n >= 0); + sink (n + 1); + return n; +} + + +int warn_strcmp_multiple_uses (int c) +{ + const char *s = c ? "12345" : a3; + int n = strcmp (s, "123"); // { dg-warning "'strcmp' of a string of length 3 and an array of size 3 evaluates to nonzero" } + sink (n < 0); + sink (n > 0); + sink (n <= 0); + sink (n >= 0); + sink (n == 0); // { dg-message "in this expression" } + return n; +} + + +int warn_strncmp_multiple_uses (int c) +{ + const char *s = a3; + int n = strncmp (s, "1234", 4); // { dg-warning "'strncmp' of a string of length 4, an array of size 3 and bound of 4 evaluates to nonzero" } + sink (n < 0); + sink (n > 0); + sink (n <= 0); + sink (n >= 0); + sink (n == 0); // { dg-message "in this expression" } + return n; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c index f5dac45..ec3c97e 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-11.c @@ -72,7 +72,7 @@ void test_memset_array_range_cst_off (void) { T (SR (-7, 7), 1, 7); T (SR (-1, 1), 1, 7); - T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */ + T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */ T (SR ( 1, 2), 1, 1); T (SR ( 1, 2), 1, 5); @@ -147,7 +147,7 @@ void test_memcpy_array_range_cst_off (const void *s) { T (SR (-7, 7), 1, 7); T (SR (-1, 1), 1, 7); - T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */ + T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */ T (SR ( 1, 2), 1, 1); T (SR ( 1, 2), 1, 5); @@ -224,7 +224,7 @@ void test_strcpy_array_range_cst_off (const char *s) { T (SR (-7, 7), 1, 6); T (SR (-1, 1), 1, 6); - T (SR (-1, 1), 1, 8); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */ + T (SR (-1, 1), 1, 8); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */ T (SR ( 1, 2), 1, 0); T (SR ( 1, 2), 1, 1); T (SR ( 1, 2), 1, 4); @@ -290,7 +290,7 @@ void test_strncpy_array_range_cst_off (const char *s) { T (SR (-7, 7), 1, 7); T (SR (-1, 1), 1, 7); - T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" { xfail *-*-*} } */ + T (SR (-1, 1), 1, 9); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr89428" } */ T (SR ( 1, 2), 1, 1); T (SR ( 1, 2), 1, 5); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c index 1e67b5f..7c3dc8c 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-12.c @@ -25,7 +25,9 @@ void test_memcpy_array_cst_range_off (const void *s) T (d + UR (1, 2), 5); T (d + UR (0, 1), 6); - T (d + UR (0, 1), 7); /* { dg-warning ".memcpy. writing 6 bytes into a region of size 5 overflows the destination" "pr89428" { xfail *-*-* } } */ + /* The warning below should be "writing" but the [0, 1] range + is somehow lost and get_range_info() returns VR_VARYING. */ + T (d + UR (0, 1), 7); /* { dg-warning ".memcpy. writing 7 bytes into a region of size 6 overflows the destination" "pr89428" { xfail *-*-* } } */ T (d + UR (1, 2), 6); /* { dg-warning ".memcpy. writing 6 bytes into a region of size 5 overflows the destination" } */ T (d + UR (1, 2), 7); /* { dg-warning "writing 7 bytes into a region of size 5 " } */ @@ -48,7 +50,8 @@ void test_memcpy_array_range_range_off (const void *s) char *d = ga7 + UR (0, 1); T (d + SR (-1, 0), 1); T (d + SR (-1, 0), 7); - T (d + SR (-1, 0), 9); /* { dg-warning "writing 1 byte into a region of size 0 " "pr89350" { xfail *-*-* } } */ + T (d + SR (-1, 0), 8); /* { dg-warning "writing 8 bytes into a region of size 7 " } */ + T (d + SR (-1, 0), 9); /* { dg-warning "writing 9 bytes into a region of size 7 " "pr89350" } */ } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c index fb81420..9c05d04 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c @@ -13,7 +13,7 @@ void sink (void*); void call_copy_n (const char *s) { - char a[7]; // { dg-message "declared here" } + char a[7]; // { dg-message "at offset 7 into destination object 'a'" } copy_n (a, "1234567", 7); sink (a); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c index 37c1ca2..607c279 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-27.c @@ -261,8 +261,7 @@ void test_strcpy_warn (const char *s) that the conversion from signed int to size_t doesn't prevent the detection. */ int n = strlen (a); - char *t = (char*)calloc (n, 1); // { dg-message "at offset 0 to an object with size 3 allocated by 'calloc' here" "calloc note 1" { xfail *-*-* } } - // { dg-message "at offset 0 to an object with size at most 3 allocated by 'calloc' here" "calloc note 2" { target *-*-* } .-1 } + char *t = (char*)calloc (n, 1); // { dg-message "destination object of size 3 allocated by 'calloc'" "note" } strcpy (t, a); // { dg-warning "writing 4 bytes into a region of size (between 0 and )?3 " } sink (t); @@ -271,8 +270,7 @@ void test_strcpy_warn (const char *s) { const char a[] = "1234"; size_t n = strlen (a); - char *t = (char*)malloc (n); // { dg-message "at offset 0 to an object with size 4 allocated by 'malloc' here" "malloc note 1" { xfail *-*-* } } - // { dg-message "at offset 0 to an object with size at most 4 allocated by 'malloc' here" "malloc note 2" { target *-*-* } .-1 } + char *t = (char*)malloc (n); // { dg-message "destination object of size 4 allocated by 'malloc'" "note" } strcpy (t, a); // { dg-warning "writing 5 bytes into a region of size (between 0 and )?4 " } sink (t); } @@ -280,14 +278,14 @@ void test_strcpy_warn (const char *s) // Exercise PR middle-end/85484. { size_t len = strlen (s); - char vla[len]; // { dg-message "at offset 0 to an object declared here" "vla note" } + char vla[len]; // { dg-message "destination object 'vla'" "vla note" } strcpy (vla, s); // { dg-warning "writing one too many bytes into a region of a size that depends on 'strlen'" } sink (vla); } { size_t n = strlen (s); - char *t = (char*)malloc (n); // { dg-message "at offset 0 to an object allocated by 'malloc' here" "malloc note" } + char *t = (char*)malloc (n); // { dg-message "allocated by 'malloc'" "malloc note" } strcpy (t, s); // { dg-warning "writing one too many bytes into a region of a size that depends on 'strlen'" } sink (t); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c index be7f51a..5009fb5 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-28.c @@ -40,27 +40,27 @@ void same_size_and_offset_idx_cst (void) const size_t n = UR (2, 3); T (n, n, -4); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[-2, -1] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[-2, -1] into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 } T (n, n, -3); T (n, n, -2); T (n, n, -1); T (n, n, 0); T (n, n, 1); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[3, 4] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset 3 into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 } } { const size_t n = UR (3, 4); T (n, n, -5); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[-2, -1] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[-2, -1] into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 } T (n, n, -4); T (n, n, -3); T (n, n, -2); T (n, n, -1); T (n, n, 0); T (n, n, 1); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[4, 5] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset 4 into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 } } { @@ -84,15 +84,15 @@ void different_size_and_offset_idx_cst (void) const size_t i = UR (1, 2); T (n, i, -4); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[-3, -2] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[-3, -2] into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 } T (n, i, -3); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[-2, -1] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[-2, -1] into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 } T (n, i, -2); T (n, i, -1); T (n, i, 0); T (n, i, 1); T (n, i, 2); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[3, 4] to an object with size between 2 and 3 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset 3 into destination object of size \\\[2, 3] allocated by 'alloc1'" "note" { target *-*-* } .-1 } } { @@ -100,20 +100,20 @@ void different_size_and_offset_idx_cst (void) const size_t i = UR (2, 5); T (n, i, -6); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[-4, -1] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[-4, -2] into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 } - /* The offsets -5 and -4 are both necessarily invalid even if the sum - (i - 5) and (i - 4) are (or could be) in bounds because they imply - that the intermediate offset (p + i) is out of bounds. */ - T (n, i, -5); // { dg-warning "" "intermediate offset" { xfail *-*-* } } - T (n, i, -4); // { dg-warning "" "intermediate offset" { xfail *-*-* } } + /* The offset -5 is necessarily invalid even if the sum (i - 5) is (or + could be) in bounds because it implies that the intermediate offset + (p + i) is out of bounds. */ + T (n, i, -5); // { dg-warning "writing 1 byte into a region of size 0 " } + T (n, i, -4); T (n, i, -3); T (n, i, -2); T (n, i, -1); T (n, i, 0); T (n, i, 1); T (n, i, 2); // { dg-warning "writing 1 byte into a region of size 0" } - // { dg-message "at offset \\\[4, 7] to an object with size between 3 and 4 allocated by 'alloc1'" "note" { target *-*-* } .-1 } + // { dg-message "at offset 4 into destination object of size \\\[3, 4] allocated by 'alloc1'" "note" { target *-*-* } .-1 } } } @@ -133,11 +133,8 @@ void different_size_and_offset_idx_var (void) T (n, i, SR ( 0, 1)); T (n, i, SR ( 1, 2)); T (n, i, SR ( 2, 3)); - /* The warning is issued below but the offset and the size in - the note are wrong. See the FIXME in compute_objsize(). */ T (n, i, SR ( 3, 4)); // { dg-warning "\\\[-Wstringop-overflow" } - // { dg-message "at offset 4 to an object with size between 3 and 4 allocated by 'alloc1'" "pr92940 note: offset addition" { xfail *-*-* } .-1 } - // { dg-message "at offset . to an object with size . allocated by 'alloc1'" "note: offset addition" { target *-*-* } .-2 } + // { dg-message "at offset 4 into destination object of size \\\[3, 4] allocated by 'alloc1'" "pr92940 note: offset addition" { target *-*-* } .-1 } } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c index c011d05..f13abbd 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-29.c @@ -11,7 +11,7 @@ void sink (void*); void direct_call (void) { - char *q = allocfn (0); // { dg-message "at offset 0 to an object with size 0 allocated by 'allocfn'" } + char *q = allocfn (0); // { dg-message "object of size 0 allocated by 'allocfn'" "note" } q[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } sink (q); } @@ -20,7 +20,7 @@ void direct_call (void) void local_ptr_call (void) { allocfn_t *ptr = allocfn; - char *q = ptr (1); // { dg-message "at offset -1 to an object with size 1 allocated by 'allocfn'" } + char *q = ptr (1); // { dg-message "at offset -1 into destination object of size 1 allocated by 'allocfn'" "note" } q[0] = 0; q[-1] = 0; // { dg-warning "\\\[-Wstringop-overflow" } sink (q); @@ -32,7 +32,7 @@ void global_ptr_call (void) extern allocfn_t *ptralloc; allocfn_t *ptr = ptralloc; - char *q = ptr (2); // { dg-message "at offset 3 to an object with size 2 allocated by 'ptralloc'" } + char *q = ptr (2); // { dg-message "at offset 3 into destination object of size 2 allocated by 'ptralloc'" "note" } q[0] = 0; q[1] = 1; q[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" } @@ -44,7 +44,7 @@ void global_ptr_array_call (void) extern allocfn_t * (arralloc[]); allocfn_t *ptr = arralloc[0]; - char *q = ptr (2); // { dg-message "at offset 3 to an object with size 2 allocated by 'ptr'" } + char *q = ptr (2); // { dg-message "at offset 3 into destination object of size 2 allocated by 'ptr'" "note" } q[0] = 1; q[1] = 2; q[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" } @@ -56,7 +56,7 @@ struct S { allocfn_t *ptralloc; }; void member_ptr_call (struct S *p) { - char *q = p->ptralloc (3); // { dg-message "at offset 5 to an object with size 3 allocated by 'ptralloc' here" } + char *q = p->ptralloc (3); // { dg-message "at offset 5 into destination object of size 3 allocated by 'ptralloc'" "note" } q[0] = 0; q[1] = 1; q[2] = 2; diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c index 46f8fed..d9cf32d 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-37.c @@ -67,7 +67,7 @@ void* warn_malloc_3_5 (const char *s, unsigned n) { if (n < 3 || 5 < n) n = 3; - char *p = (char*)malloc (n); // { dg-message "at offset 1 into destination object of size \\\[3, 5] allocated by 'malloc'" } + char *p = (char*)malloc (n); // { dg-message "at offset 1 into destination object of size \\\[3, 5] allocated by 'malloc'" "note" } // The size below should be a range like the one above. strncpy (p + 1, s, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } return p; @@ -89,7 +89,7 @@ void* warn_usr_alloc_3_5 (UsrAlloc *usr_alloc, const char *s, unsigned n) { if (n < 3 || 5 < n) n = 3; - char *p = (char*)usr_alloc (n, 3); // { dg-message "at offset 1 into destination object of size \\\[9, 15] allocated by 'usr_alloc'" } + char *p = (char*)usr_alloc (n, 3); // { dg-message "at offset 1 into destination object of size \\\[9, 15] allocated by 'usr_alloc'" "note" } // The size below should be a range like the one above. strncpy (p + 1, s, 15); // { dg-warning "writing 15 bytes into a region of size 14 " } return p; @@ -179,67 +179,67 @@ void test_note (const char *s) extern void sink (void*); { - char a[1][1][2]; // { dg-message "destination object" } + char a[1][1][2]; // { dg-message "destination object" "note" } strncpy (a[0][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } sink (a); } { - char a[1][1][2]; // { dg-message "at offset 2 into " } + char a[1][1][2]; // { dg-message "at offset 2 into " "note" } 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" } + char a[1][2][2]; // { dg-message "destination object" "note" } 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 " } + char a[1][2][2]; // { dg-message "at offset 2 into " "note" } strncpy (a[0][1], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } sink (a); } { - char a[1][2][2]; // { dg-message "at offset 4 into " } + char a[1][2][2]; // { dg-message "at offset 4 into " "note" } 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 " } + char a[2][1][2]; // { dg-message "at offset 2 into " "note" } strncpy (a[0][1], 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 " } + char a[2][1][2]; // { dg-message "at offset 2 into " "note" } strncpy (a[1][0], s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } sink (a); } { - char a[2][2][3]; // { dg-message "at offset 9 into " } + char a[2][2][3]; // { dg-message "at offset 9 into " "note" } strncpy (a[1][1], s, 4); // { dg-warning "writing 4 bytes into a region of size 3 " } sink (a); } { - char a[2][3][3]; // { dg-message "at offset 12 into " } + char a[2][3][3]; // { dg-message "at offset 12 into " "note" } strncpy (a[1][1], s, 5); // { dg-warning "writing 5 bytes into a region of size 3 " } sink (a); } { - char a[2][3][3]; // { dg-message "at offset 12 into " } + char a[2][3][3]; // { dg-message "at offset 12 into " "note" } strncpy (a[1][1], s, 6); // { dg-warning "writing 6 bytes into a region of size 3 " } sink (a); } { - char a[2][3][3]; // { dg-message "at offset 15 into " } + char a[2][3][3]; // { dg-message "at offset 15 into " "note" } strncpy (a[1][2], s, 7); // { dg-warning "writing 7 bytes into a region of size 3 " } sink (a); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c index a4d78b2..b126fcb 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c @@ -53,7 +53,7 @@ void nowarn_memchr_anti_range_memset_cst (const void *s, size_t n) 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" } + char *p = malloc (4); // { dg-message "destination object of size 4 " "note" } sink (p); p = memchr (p, '1', 4); @@ -62,7 +62,7 @@ void warn_memchr_cst_memset_cst (const void *s) 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" } + char *p = malloc (4); // { dg-message "destination object of size 4 " "note" } sink (p); p = memchr (p, '1', n); @@ -79,9 +79,9 @@ void warn_memchr_var_memset_range (const void *s, unsigned n) 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 } + // { dg-message ": destination object of size \\\[5, 7]" "note 1" { target *-*-* } .-1 } + // { dg-message "at offset \\\[1, 7] into destination object of size \\\[5, 7]" "note 2" { target *-*-* } .-2 } + // { dg-message "at offset \\\[2, 7] into destination object of size \\\[5, 7]" "note 3" { target *-*-* } .-3 } sink (p0); char *p1 = memchr (p0, '1', n); diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c index 02b14ee..cb2c329 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c @@ -26,7 +26,7 @@ void nowarn_c32 (char c) void warn_c32 (char c) { - extern char warn_a32[32]; // { dg-message "at offset 32 to object 'warn_a32' with size 32" } + extern char warn_a32[32]; // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "note" } void *p = warn_a32 + 1; *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c index 26568f8..f5929c9 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c @@ -15,7 +15,7 @@ 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'" } + caxcc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'caxcc'" "note" } char *p = caxcc.a; size_t idx = DIFF_MAX - 4; @@ -38,7 +38,7 @@ void char_flexarray_cst_off_cst_size (void) void char_flexarray_var_off_cst_size (ptrdiff_t idx) { extern struct { char n, a[]; } - caxvc; // { dg-message "destination object 'caxvc'" } + caxvc; // { dg-message "destination object 'caxvc'" "note" } char *p = caxvc.a; @@ -55,7 +55,7 @@ void char_flexarray_var_off_cst_size (ptrdiff_t idx) void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx) { extern struct { char n, a[]; } - caxvv; // { dg-message "destination object 'caxvv'" } + caxvv; // { dg-message "destination object 'caxvv'" "note" } char *p = caxvv.a; @@ -76,7 +76,7 @@ void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx) 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" } + *p = __builtin_malloc (n); // { dg-message "at offset \\d+ into destination object" "note" } if (idx < DIFF_MAX - 4) idx = DIFF_MAX - 4; @@ -91,7 +91,7 @@ void alloc_array_var_off_cst_size (size_t n, ptrdiff_t idx) 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'" } + iaxc; // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'iaxc'" "note" } int *p = iaxc.a; size_t idx = DIFF_MAX / sizeof *p - 1; diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-58.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-58.c new file mode 100644 index 0000000..b81186c --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-58.c @@ -0,0 +1,260 @@ +/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI + Exercise warnings for writing into one of two or more declared objects. + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */ + +#include "range.h" + +#define INT_MAX __INT_MAX__ + +extern void* memset (void*, int, size_t); +#define memset(d, c, n) sink (memset (d, c, n)) + +void sink (int, ...); +#define sink(...) sink (0, __VA_ARGS__) + +volatile int cond1, cond2; + +extern char ca0[0], ca1[1], ca2[2], ca3[3], ca4[4], + ca5[5], ca6[6], ca7[7], ca8[8], ca9[9], cax[]; + +#define CHOOSE_DECL_2(n1, n2) \ + (cond1 ? ca ## n1 : ca ## n2) +#define CHOOSE_DECL_3(n1, n2, n3) \ + (cond1 < 0 ? ca ## n1 : 0 < cond1 ? ca ## n2 : ca ## n3) + + +void memset_decl_2 (void) +{ + { + char *p0_1 = CHOOSE_DECL_2 (0, 1); + + memset (p0_1, 0, 0); + /* Writing more than the smallest destination should trigger a "may + write" warning if the access is unconditionally reachable from + the block where the pointer to either object is assigned. */ + memset (p0_1, 0, 1); + memset (p0_1, 0, 2); // { dg-warning "memset' writing 2 bytes into a region of size 1 " } + memset (p0_1, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 1 " } + } + + { + char *p0_x = CHOOSE_DECL_2 (0, x); + + memset (p0_x, 0, 0); + memset (p0_x, 0, 1); + memset (p0_x, 0, 2); + memset (p0_x, 0, 9); + } + + { + char *p3_5 = CHOOSE_DECL_2 (3, 5); + + memset (p3_5, 0, 1); + memset (p3_5, 0, 3); + memset (p3_5, 0, 4); + memset (p3_5, 0, 5); + memset (p3_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *p5_3 = CHOOSE_DECL_2 (5, 3); + + memset (p5_3, 0, 3); + memset (p5_3, 0, 4); + memset (p5_3, 0, 5); + memset (p5_3, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *px_3 = CHOOSE_DECL_2 (x, 3); + + memset (px_3, 0, 1); + memset (px_3, 0, 3); + memset (px_3, 0, 4); + memset (px_3, 0, 1234); + } + + { + char *p5_x = CHOOSE_DECL_2 (5, x); + + memset (p5_x, 0, 1); + memset (p5_x, 0, 5); + memset (p5_x, 0, 6); + memset (p5_x, 0, 1234); + } + +} + + +void memset_decl_3 (void) +{ + { + char *p0_1_2 = CHOOSE_DECL_3 (0, 1, 2); + memset (p0_1_2, 0, 0); + memset (p0_1_2, 0, 1); + memset (p0_1_2, 0, 2); + memset (p0_1_2, 0, 3); // { dg-warning "memset' writing 3 bytes into a region of size 2 " } + memset (p0_1_2, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 2 " } + } + + { + char *p0_2_x = CHOOSE_DECL_3 (0, 2, x); + + memset (p0_2_x, 0, 0); + memset (p0_2_x, 0, 1); + memset (p0_2_x, 0, 3); + memset (p0_2_x, 0, 9); + } + + { + char *p3_4_5 = CHOOSE_DECL_3 (3, 4, 5); + + memset (p3_4_5, 0, 3); + memset (p3_4_5, 0, 4); + memset (p3_4_5, 0, 5); + memset (p3_4_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *p5_3_4 = CHOOSE_DECL_3 (5, 3, 4); + + memset (p5_3_4, 0, 3); + memset (p5_3_4, 0, 4); + memset (p5_3_4, 0, 5); + memset (p5_3_4, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *p9_8_7 = CHOOSE_DECL_3 (9, 8, 7); + + memset (p9_8_7, 0, 7); + memset (p9_8_7, 0, 8); + memset (p9_8_7, 0, 9); + memset (p9_8_7, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9 " } + } +} + + +/* Verify conditionally writing into one of two objects with the same + size. */ + +void memset_decl_2_same_size (int i) +{ + { + char a4_1[4], a4_2[4]; + char *p4 = cond1 ? a4_1 : a4_2; + + memset (p4, 0, 1); + memset (p4, 0, 2); + memset (p4, 0, 3); + memset (p4, 0, 4); + memset (p4, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" } + } + + { + char a4_1[4]; // { dg-message "destination object 'a4_1" "note" } + char a4_2[4]; // { dg-message "destination object 'a4_2" "note" } + char *p4 = cond1 ? a4_1 : a4_2; + char *p4_i = p4 + i; + + memset (p4_i, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" } + } + + { + if (i < 1) + i = 1; + + char a4_1[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" } + char a4_2[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" } + char *p4 = cond1 ? a4_1 : a4_2; + char *p4_i = p4 + i; + + memset (p4_i, 0, 3); + memset (p4_i, 0, 4); // { dg-warning "memset' writing 4 bytes into a region of size 3 " } + } +} + + +void memset_decl_2_off (void) +{ + int i1 = SR (1, INT_MAX); + int i2 = SR (2, INT_MAX); + + { + char a5[5]; // { dg-warning "at offset [1, 5] into destination object 'a5' + char a7[7]; // { dg-warning "at offset [2, 7] into destination object 'a7' + char *p5_p1 = a5 + i1; + char *p7_p2 = a7 + i2; + char *p5_7 = cond1 ? p5_p1 : p7_p2; + + memset (p5_7, 0, 1); + memset (p5_7, 0, 2); + memset (p5_7, 0, 3); + memset (p5_7, 0, 4); + memset (p5_7, 0, 5); + memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + int i3 = SR (3, INT_MAX); + + { + char a5[5]; + // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 } + // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 } + // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 } + char a9[9]; + // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 } + // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 } + // { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 } + char *p5_p2 = a5 + i2; // 3 bytes left + char *p9_p3 = a9 + i3; // 6 bytes left + char *p = + cond1 ? p5_p2 : p9_p3; // [3 - 6] bytes left + char *q = p + i1; // [2 - 5] bytes left + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" } + + --q; // [3 - 6] bytes left + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); + memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" } + + --q; // [4 - 7] bytes left + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); + memset (q, 0, 7); + memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" } + + int m1_x = SR (-1, INT_MAX); + int m2_x = SR (-2, INT_MAX); + + q += cond2 ? m1_x : m2_x; // [5 - 9] bytes left + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); + memset (q, 0, 7); + memset (q, 0, 8); + memset (q, 0, 9); + memset (q, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9" } + } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-59.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-59.c new file mode 100644 index 0000000..c45a92d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-59.c @@ -0,0 +1,267 @@ +/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI + Exercise warnings for writing into one of two or more allocated objects. + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */ + +#include "range.h" + +#define INT_MAX __INT_MAX__ + +extern void* malloc (size_t); +extern void* memset (void*, int, size_t); +#define memset(d, c, n) sink (memset (d, c, n)) + +void sink (int, ...); +#define sink(...) sink (0, __VA_ARGS__) + +volatile int cond1, cond2, x; + +#define CHOOSE_MALLOC_2(n1, n2) \ + (cond1 ? malloc (n1) : malloc (n2)) +#define CHOOSE_MALLOC_3(n1, n2, n3) \ + (cond1 < 0 ? malloc (n1) : 0 < cond1 ? malloc (n2) : malloc (n3)) + + +void memset_malloc_2 (void) +{ + { + char *p0_1 = CHOOSE_MALLOC_2 (0, 1); + + memset (p0_1, 0, 0); + /* Writing more than the smallest destination should trigger a "may + write" warning if the access is unconditionally reachable from + the block where the pointer to either object is assigned. */ + memset (p0_1, 0, 1); + memset (p0_1, 0, 2); // { dg-warning "memset' writing 2 bytes into a region of size 1 " } + memset (p0_1, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 1 " } + } + + { + char *p0_x = CHOOSE_MALLOC_2 (0, x); + + memset (p0_x, 0, 0); + memset (p0_x, 0, 1); + memset (p0_x, 0, 2); + memset (p0_x, 0, 12345); + } + + { + char *px_x = CHOOSE_MALLOC_2 (x, x); + + memset (px_x, 0, 0); + memset (px_x, 0, 1); + memset (px_x, 0, 2); + memset (px_x, 0, 12345); + } + + { + char *p3_5 = CHOOSE_MALLOC_2 (3, 5); + + memset (p3_5, 0, 1); + memset (p3_5, 0, 3); + memset (p3_5, 0, 4); + memset (p3_5, 0, 5); + memset (p3_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *p5_3 = CHOOSE_MALLOC_2 (5, 3); + + memset (p5_3, 0, 3); + memset (p5_3, 0, 4); + memset (p5_3, 0, 5); + memset (p5_3, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *px_3 = CHOOSE_MALLOC_2 (x, 3); + + memset (px_3, 0, 1); + memset (px_3, 0, 3); + memset (px_3, 0, 4); + memset (px_3, 0, 1234); + } + + { + char *p5_x = CHOOSE_MALLOC_2 (5, x); + + memset (p5_x, 0, 1); + memset (p5_x, 0, 5); + memset (p5_x, 0, 6); + memset (p5_x, 0, 1234); + } + +} + + +void memset_malloc_3 (void) +{ + { + char *p0_1_2 = CHOOSE_MALLOC_3 (0, 1, 2); + memset (p0_1_2, 0, 0); + memset (p0_1_2, 0, 1); + memset (p0_1_2, 0, 2); + memset (p0_1_2, 0, 3); // { dg-warning "memset' writing 3 bytes into a region of size 2 " } + memset (p0_1_2, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 2 " } + } + + { + char *p0_2_x = CHOOSE_MALLOC_3 (0, 2, x); + + memset (p0_2_x, 0, 0); + memset (p0_2_x, 0, 1); + memset (p0_2_x, 0, 3); + memset (p0_2_x, 0, 9); + } + + { + char *p3_4_5 = CHOOSE_MALLOC_3 (3, 4, 5); + + memset (p3_4_5, 0, 3); + memset (p3_4_5, 0, 4); + memset (p3_4_5, 0, 5); + memset (p3_4_5, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *p5_3_4 = CHOOSE_MALLOC_3 (5, 3, 4); + + memset (p5_3_4, 0, 3); + memset (p5_3_4, 0, 4); + memset (p5_3_4, 0, 5); + memset (p5_3_4, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + { + char *p9_8_7 = CHOOSE_MALLOC_3 (9, 8, 7); + + memset (p9_8_7, 0, 7); + memset (p9_8_7, 0, 8); + memset (p9_8_7, 0, 9); + memset (p9_8_7, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9 " } + } +} + + +/* Verify conditionally writing into one of two objects with the same + size. */ + +void memset_malloc_2_same_size (int i) +{ + { + char a4_1[4], a4_2[4]; + char *p4 = cond1 ? a4_1 : a4_2; + + memset (p4, 0, 1); + memset (p4, 0, 2); + memset (p4, 0, 3); + memset (p4, 0, 4); + memset (p4, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" } + } + + { + char a4_1[4]; // { dg-message "destination object 'a4_1" "note" } + char a4_2[4]; // { dg-message "destination object 'a4_2" "note" } + char *p4 = cond1 ? a4_1 : a4_2; + char *p4_i = p4 + i; + + memset (p4_i, 0, 5); // { dg-warning "memset' writing 5 bytes into a region of size 4" } + } + + { + if (i < 1) + i = 1; + + char a4_1[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" } + char a4_2[4]; // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" } + char *p4 = cond1 ? a4_1 : a4_2; + char *p4_i = p4 + i; + + memset (p4_i, 0, 3); + memset (p4_i, 0, 4); // { dg-warning "memset' writing 4 bytes into a region of size 3 " } + } +} + + +void memset_malloc_2_off (void) +{ + int i1 = SR (1, INT_MAX); + int i2 = SR (2, INT_MAX); + + { + char a5[5]; // { dg-warning "at offset [1, 5] into destination object 'a5' + char a7[7]; // { dg-warning "at offset [2, 7] into destination object 'a7' + char *p5_p1 = a5 + i1; + char *p7_p2 = a7 + i2; + char *p5_7 = cond1 ? p5_p1 : p7_p2; + + memset (p5_7, 0, 1); + memset (p5_7, 0, 2); + memset (p5_7, 0, 3); + memset (p5_7, 0, 4); + memset (p5_7, 0, 5); + memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " } + } + + int i3 = SR (3, INT_MAX); + + { + char a5[5]; + // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 } + // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 } + // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 } + char a9[9]; + // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 } + // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 } + // { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 } + char *p5_p2 = a5 + i2; // 3 bytes left + char *p9_p3 = a9 + i3; // 6 bytes left + char *p = + cond1 ? p5_p2 : p9_p3; // [3 - 6] bytes left + char *q = p + i1; // [2 - 5] bytes left + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" } + + --q; // [3 - 6] bytes left + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); + memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" } + + --q; // [4 - 7] bytes left + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); + memset (q, 0, 7); + memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" } + + int m1_x = SR (-1, INT_MAX); + int m2_x = SR (-2, INT_MAX); + + q += cond2 ? m1_x : m2_x; // [5 - 9] bytes left + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); + memset (q, 0, 6); + memset (q, 0, 7); + memset (q, 0, 8); + memset (q, 0, 9); + memset (q, 0, 10); // { dg-warning "memset' writing 10 bytes into a region of size 9" } + } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c new file mode 100644 index 0000000..8c9de20 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c @@ -0,0 +1,72 @@ +/* Test derived from Glibc's getifaddrs_internal. The code could be + rewritten to avoid the warning for the memcpy call but since unions + are designed to have their members treated as interchangeable there + isn't a whole lot to be gained from issuing one. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +extern void* memcpy (void*, const void*, size_t); + +struct sockaddr +{ + short sa_family; + char sa_data[14]; +}; + +struct in_addr +{ + int s_addr; +}; + +struct in6_addr +{ + union + { + char __u6_addr8[16]; + short __u6_addr16[8]; + int __u6_addr32[4]; + } __in6_u; +}; + +struct sockaddr_in +{ + short sin_family; + short sin_port; + struct in_addr sin_addr; + unsigned char sin_zero[sizeof (struct sockaddr) - + (sizeof (short)) - + sizeof (short) - + sizeof (struct in_addr)]; +}; + +struct sockaddr_in6 +{ + short sin6_family; + short sin6_port; + int sin6_flowinfo; + struct in6_addr sin6_addr; + int sin6_scope_id; +}; + +union +{ + struct sockaddr sa; + struct sockaddr_in s4; + struct sockaddr_in6 s6; +} u1, u2; + +struct sockaddr *sa; + +void test_unconditional (void *p) +{ + sa = &u1.sa; + memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, p, 16); +} + +void test_conditional (void *p, int i) +{ + sa = i ? &u1.sa : &u2.sa; + memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, p, 16); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c new file mode 100644 index 0000000..7601679 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c @@ -0,0 +1,88 @@ +/* { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +void* malloc (size_t); +void* memcpy (void*, const void*, size_t); +size_t strlen (const char *); + +// Test case reduced from gcc/attribs.c. + +char* sorted_attr_string (char *argv[]) +{ + size_t n = 0; + unsigned int i; + + for (i = 0; argv[i]; ++i) + n += strlen (argv[i]); + + char *s = (char*)malloc (n); + n = 0; + for (i = 0; argv[i]; ++i) + { + const char *str = argv[i]; + size_t len = strlen (str); + memcpy (s + n, str, len); + n += len + 1; + } + + /* Replace "=,-" with "_". */ + for (i = 0; i < strlen (s); i++) + if (s[i] == '=') + s[i] = '_'; // { dg-bogus "\\\[-Wstringop-overflow" } + + return s; +} + + +void f (void*); + +void nowarn_cond_escape (int c, int *x) +{ + extern char a3[3], a5[5]; + + char *p; + if (c) + { + p = a3; + *x = 2; + } + else + { + p = a5; + *x = 4; + } + + f (p); // may modify *x + + if (*x == 2) + p[2] = 0; + else if (*x == 4) + p[4] = 0; // { dg-bogus "\\\[-Wstringop-overflow" } +} + +void warn_cond_escape (int c, int *x) +{ + extern char a3_2[3]; + extern char a5_2[5]; // { dg-message "at offset 5 into destination object 'a5_2'" } + + char *p; + if (c) + { + p = a3_2; + *x = 2; + } + else + { + p = a5_2; + *x = 5; + } + + f (p); // may modify *x + + if (*x == 2) + p[2] = 0; + else if (*x == 5) + p[5] = 0; // { dg-warning "\\\[-Wstringop-overflow" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c new file mode 100644 index 0000000..318d9bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c @@ -0,0 +1,363 @@ +/* Test for MIN and MAX expressions involving pointers. + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */ + +#include "range.h" + +#define INT_MAX __INT_MAX__ + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) < (y) ? (y) : (x)) + +typedef __SIZE_TYPE__ size_t; + +void* memset (void*, int, size_t); +#define memset(...) sink (memset (__VA_ARGS__)) + +void sink (void*, ...); + +volatile int cond, vi; +char* volatile ptr; + +void test_min (void) +{ + const int i1 = SR (1, INT_MAX); + const int i2 = SR (2, INT_MAX); + + { + /* Exercise both pointers pointing to a different unknown object plus + positive constant offset. Since PTR is volatile P1 and P2 cannot + normally be considered to point to the same object. It can only + be inferred from the MIN expression. */ + char *p1 = ptr + 1; + char *p2 = ptr + 2; + + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, INT_MAX); + // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 } + memset (q, 0, DIFF_MAX - 2); + memset (q, 0, DIFF_MAX); + // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 } + // { dg-warning "writing 9223372036854775807 bytes into a region of size 9223372036854775806" "lp64" { target lp64 } .-2 } + } + + { + /* Exercise both pointers pointing to a different unknown object plus + variable offset. */ + char *p1 = ptr + vi; + char *p2 = ptr + vi; + + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, INT_MAX); + } + + { + /* Exercise both pointers pointing to the same object plus constant + offset. */ + char a2[2]; // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" } + char *p1 = a2 + 1; + char *p2 = a2 + 2; + + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); // { dg-warning "writing 2 bytes into a region of size 1 " } + } + + { + /* Exercise both pointers pointing to the same object plus offset + in a known range. */ + char a3[3]; // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" } + char *pi = a3 + i1; + char *pj = a3 + i2; + + char *q = MIN (pi, pj); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } + } + + { + /* Exercise both pointers pointing to the same object plus variable + offset. Verify that no offset is mentioned in the note (since + its unknown, printing its full range is unnecessary). */ + char a4[4]; // { dg-message ": destination object 'a4'" "note" } + char *pi = a4 + vi; + char *pj = a4 + vi; + + char *q = MIN (pi, pj); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } + } + + { + /* Exercise a pointer pointing to a known object with one pointing + to an unknown object. */ + char a5[5]; // { dg-message ": destination object 'a5'" "note" } + char *p = ptr; + char *q = MIN (p, a5); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } + } + + { + /* Exercise a pointer pointing to a known object plus constant offset + with one pointing to an unknown object. */ + char a6[6]; // { dg-message ": destination object 'a6'" "note" } + char *p1 = ptr; + char *p2 = a6 + 1; + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 6); + memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " } + } + + { + /* Exercise a pointer pointing to a known object with one pointing + to an unknown object plus constant offset. */ + char a7[7]; // { dg-message ": destination object 'a7'" "note" } + char *p1 = a7; + char *p2 = ptr + 1; + /* Since p1 points to a7[0] it must be less than any pointer to a7 + plus positive offset, and so Q == P1. */ + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 7); + memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 7 " } + } + + { + /* Exercise a pointer pointing to a known object plus constant offset + with one pointing to an unknown object plus a different constant + offset. */ + char a8[8]; // { dg-message "at offset 1 into destination object 'a8'" "note" } + char *p1 = a8 + 1; + char *p2 = ptr + 2; + /* Since P1 points to A8[1] it must be less than or equal to any + pointer to A8 plus positive offset. Either way, Q must point + to A8[1]. */ + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 7); + memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 7 " } + } + + { + /* Same as above but with larger offsets. */ + char a9[9]; // { dg-message "at offset 3 into destination object 'a9'" "note" } + char *p1 = a9 + 3; + char *p2 = ptr + 4; + /* Since P1 points to A9[3] it must be less than or equal to any + pointer anywhere into A9 plus 4, so Q must point to A9[3]. */ + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 6); + memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " } + } + + { + /* Same as above but with the offsets reversed. */ + char a10[10]; // { dg-message "at offset 5 into destination object 'a10'" "note" } + char *p1 = a10 + 10; + char *p2 = ptr + 5; + /* Since P1 points just past the end of A10 it could be either less + or equal to another pointer anywhere into A10 plus 3 because + the other pointer itself could start at a non-zero offset that's + not reflected in the determined offset). */ + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } + } + + { + char a3[3]; // { dg-message ": destination object 'a3'" "note" } + char *p1 = ptr; + char *p2 = a3 + i1; + char *q = MIN (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); // { dg-warning "writing 4 bytes into a region of size 3 " } + } +} + + +void test_max (void) +{ + const int i1 = SR (1, INT_MAX); + const int i2 = SR (2, INT_MAX); + + { + /* Exercise both pointers pointing to the same object plus constant + offset. */ + char a2[2]; // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" } + char *pi = a2 + 1; + char *pj = a2 + 2; + + char *q = MAX (pi, pj); + + memset (q, 0, 1); + memset (q, 0, 2); // { dg-warning "writing 2 bytes into a region of size 1 " } + } + + { + /* Exercise both pointers pointing to the same object plus offset + in a known range. */ + char a3[3]; // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" } + char *pi = a3 + i1; + char *pj = a3 + i2; + + char *q = MAX (pi, pj); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } + } + + { + /* Exercise both pointers pointing to the same object plus variable + offset. Verify that no offset is mentioned in the note (since + its unknown, printing its full range is unnecessary). */ + char a4[4]; // { dg-message ": destination object 'a4'" "note" } + char *pi = a4 + vi; + char *pj = a4 + vi; + + char *q = MAX (pi, pj); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 3); + memset (q, 0, 4); + memset (q, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } + } + + { + /* Exercise a pointer pointing to a known object with one pointing + to an unknown object. */ + char a5[5]; // { dg-message ": destination object 'a5'" "note" } + char *p = ptr; + char *q = MAX (p, a5); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } + } + + { + /* Exercise a pointer pointing to a known object plus constant offset + with one pointing to an unknown object. */ + char a6[6]; // { dg-message "at offset 1 into destination object 'a6'" "note" } + char *p1 = ptr; + char *p2 = a6 + 1; + char *q = MAX (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } + memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 5 " } + } + + { + /* Exercise a pointer pointing to a known object with one pointing + to an unknown object plus constant offset. */ + char a7[7]; // { dg-message "at offset 1 into destination object 'a7'" "note" } + char *p1 = a7; + char *p2 = ptr + 1; + /* Since p1 points to a7[0] it must be less than any pointer to a7 + plus positive offset, and so Q == P2. */ + char *q = MAX (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 6); + memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " } + memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 6 " } + } + + { + /* Exercise a pointer pointing to a known object plus constant offset + with one pointing to an unknown object plus a different constant + offset. */ + char a8[8]; // { dg-message "at offset 2 into destination object 'a8'" "note" } + char *p1 = a8 + 1; + char *p2 = ptr + 2; + /* Since P1 points to A8[1] it must be less than or equal to any + pointer to A8 plus positive offset. Either way, Q must point + to A8[2]. */ + char *q = MAX (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 6); + memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " } + memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 6 " } + } + + { + /* Same as above but with larger offsets. */ + char a9[9]; // { dg-message "at offset 4 into destination object 'a9'" "note" } + char *p1 = a9 + 3; + char *p2 = ptr + 4; + /* Since P1 points to A9[3] it must be less than or equal to any + pointer anywhere into A9 plus 4, so Q must point to A9[4]. */ + char *q = MAX (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 5); + memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } + } + + { + /* Same as above but with the offsets reversed. */ + char a10[10]; // { dg-message "at offset 10 into destination object 'a10'" "note" } + char *p1 = a10 + 10; + char *p2 = ptr + 5; + /* Since P1 points just past the end of A10 it could be either less + or equal to another pointer anywhere into A10 plus 3 because + the other pointer itself could start at a non-zero offset that's + not reflected in the determaxed offset). */ + char *q = MAX (p1, p2); + + memset (q, 0, 1); // { dg-warning "writing 1 byte into a region of size 0 " } + } + + { + char a11[11]; // { dg-message "at offset \\\[1, 11] into destination object 'a11'" "note" } + char *p1 = ptr; + char *p2 = a11 + i1; + char *q = MAX (p1, p2); + + memset (q, 0, 1); + memset (q, 0, 2); + memset (q, 0, 10); + memset (q, 0, 11); // { dg-warning "writing 11 bytes into a region of size 10 " } + } +} + diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-63.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-63.c new file mode 100644 index 0000000..c98721d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-63.c @@ -0,0 +1,33 @@ +/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI + Test case derived from gcc/opts-common.c. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +char* f (const void*, ...); + +const char * +candidates_list_and_hint (const char *arg, char **str, const char *a[]) +{ + size_t len = 0; + int i; + + for (i = 0; a[i]; ++i) + len += __builtin_strlen (a[i]) + 1; + + char *p = (char*)__builtin_malloc (len); + *str = p; + + for (i = 0; a[i]; ++i) + { + len = __builtin_strlen (a[i]); + __builtin_memcpy (p, a[i], len); + p[len] = ' '; + p += len + 1; + } + + p[-1] = '\0'; // { dg-bogus "\\\[-Wstringop-overflow" } + + return f (arg, &a); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c new file mode 100644 index 0000000..88b9d29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c @@ -0,0 +1,74 @@ +/* PR middle-end/92936 - missing warning on a past-the-end store to a PHI + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds" } */ + +typedef __SIZE_TYPE__ size_t; + +void* malloc (size_t); +void* memset (void*, int, size_t); + +extern char a3[3], a5[5], a9[9]; + +extern int cnd[]; + +void* f2 (void) +{ + char *p0 = cnd[0] ? a3 : 0; + char *p1 = cnd[1] ? a5 : p0; + + return memset (p1, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" } +} + +void* f3 (void) +{ + char *p0 = cnd[0] ? a3 : 0; + char *p1 = cnd[1] ? a5 : 0; + char *p2 = cnd[2] ? p0 : p1; + + return memset (p2, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" } +} + +void* f3_2 (void) +{ + char *p0 = cnd[0] ? a3 : 0; + char *p1 = cnd[1] ? a5 : 0; + char *p2 = cnd[2] ? p1 : p0; + + return memset (p2, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" } +} + +void* f3_3 (void) +{ + char *p0 = cnd[0] ? a5 : 0; + char *p1 = cnd[1] ? p0 : a5; + char *p2 = cnd[2] ? p1 : p0; + + return memset (p2, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" } +} + +void* f4 (void) +{ + char *p0 = cnd[0] ? a3 : 0; + char *p1 = cnd[1] ? a5 : 0; + char *p2 = cnd[2] ? p0 : 0; + char *p3 = cnd[3] ? p1 : p2; + + return memset (p3, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" } +} + +void* f9 (void) +{ + char *p0 = cnd[0] ? a5 : 0; + char *p1 = cnd[1] ? a5 + 1 : 0; + char *p2 = cnd[2] ? a5 + 2 : 0; + char *p3 = cnd[3] ? a5 + 3 : 0; + char *p4 = cnd[4] ? a5 + 4 : 0; + + char *p5 = cnd[5] ? p0 : p1; + char *p6 = cnd[6] ? p5 : p2; + char *p7 = cnd[7] ? p6 : p3; + char *p8 = cnd[8] ? p7 : p4; + char *p9 = cnd[9] ? p8 : p5; + + return memset (p9, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-7.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-7.c new file mode 100644 index 0000000..cb2addf3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-7.c @@ -0,0 +1,124 @@ +/* Test to verify that --param ssa_name_def_chain_limit can be used to + limit the maximum number of SSA_NAME assignments the warning follows. + { dg-do compile } + { dg-options "-O2 -Wall -Wno-array-bounds --param ssa-name-def-chain-limit=5" } */ + +#define NOIPA __attribute__ ((noipa)) + +void* memset (void*, int, __SIZE_TYPE__); + +char a9[9]; + +void sink (const char*, ...); + +NOIPA void g2 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + + sink (p0, p1, p2); + + memset (p2, 0, 8); // { dg-warning "\\\[-Wstringop-overflow" } +} + +NOIPA void g3 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + char *p3 = p2 + i; + + sink (p0, p1, p2, p3); + + memset (p3, 0, 7); // { dg-warning "\\\[-Wstringop-overflow" } +} + +NOIPA void g4 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + char *p3 = p2 + i; + char *p4 = p3 + i; + + sink (p0, p1, p2, p3, p4); + + memset (p4, 0, 6); // { dg-warning "\\\[-Wstringop-overflow" } +} + +NOIPA void g5 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + char *p3 = p2 + i; + char *p4 = p3 + i; + char *p5 = p4 + i; + + sink (p0, p1, p2, p3, p4, p5); + + memset (p5, 0, 5); // { dg-warning "\\\[-Wstringop-overflow" } +} + +NOIPA void g6 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + char *p3 = p2 + i; + char *p4 = p3 + i; + char *p5 = p4 + i; + char *p6 = p5 + i; + + sink (p0, p1, p2, p3, p4, p5, p6); + + memset (p6, 0, 4); +} + +NOIPA void g7 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + char *p3 = p2 + i; + char *p4 = p3 + i; + char *p5 = p4 + i; + char *p6 = p5 + i; + char *p7 = p6 + i; + + sink (p0, p1, p2, p3, p4, p5, p6, p7); + + memset (p7, 0, 4); +} + +NOIPA void g8 (int i) +{ + if (i < 1) i = 1; + + char *p0 = a9; + char *p1 = p0 + i; + char *p2 = p1 + i; + char *p3 = p2 + i; + char *p4 = p3 + i; + char *p5 = p4 + i; + char *p6 = p5 + i; + char *p7 = p6 + i; + char *p8 = p7 + i; + + sink (p0, p1, p2, p3, p4, p5, p6, p7, p8); + + memset (p8, 0, 2); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c b/gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c new file mode 100644 index 0000000..08e5272 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/invalid-shift-1.c @@ -0,0 +1,34 @@ +/* PR tree-optimization/97424. */ + +#include <stdint.h> + +static inline uint32_t +_dl_hwcaps_subdirs_build_bitmask (int subdirs, int active) +{ + /* Leading subdirectories that are not active. */ + int inactive = subdirs - active; + if (inactive == 32) + return 0; + + uint32_t mask; + if (subdirs != 32) + mask = (1 << subdirs) - 1; /* { dg-message "shift by count \\('33'\\) >= precision of type \\('\[0-9\]+'\\)" } */ + else + mask = -1; + return mask ^ ((1U << inactive) - 1); /* { dg-message "shift by negative count \\('-1'\\)" } */ +} + +void f1 (int); + +void +f2 (void) +{ + f1 (_dl_hwcaps_subdirs_build_bitmask (1, 2)); + f1 (_dl_hwcaps_subdirs_build_bitmask (33, 31)); +} + +static int __attribute__((noinline)) op3 (int op, int c) { return op << c; } /* { dg-message "shift by negative count \\('-1'\\)" } */ +int test_3 (void) { return op3 (1, -1); } + +static int __attribute__((noinline)) op4 (int op, int c) { return op << c; } +int test_4 (void) { return op4 (1, 0); } diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c index 38ce1a5..c5bf1227c 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c @@ -30,14 +30,14 @@ void test_2a (void *ptr) int *test_3 (void) { int *ptr = (int *)malloc (sizeof (int)); - *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */ + *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */ return ptr; } int *test_3a (void) { int *ptr = (int *)__builtin_malloc (sizeof (int)); - *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */ + *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */ return ptr; } @@ -47,7 +47,7 @@ int *test_4 (void) if (ptr) *ptr = 42; else - *ptr = 43; /* { dg-warning "dereference of NULL 'ptr'" } */ + *ptr = 43; /* { dg-warning "dereference of NULL 'ptr' \\\[CWE-476\\\]" } */ return ptr; } @@ -260,14 +260,14 @@ void test_22 (void) int *test_23 (int n) { int *ptr = (int *)calloc (n, sizeof (int)); - ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */ + ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */ return ptr; } int *test_23a (int n) { int *ptr = (int *)__builtin_calloc (n, sizeof (int)); - ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */ + ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */ return ptr; } @@ -302,7 +302,7 @@ struct coord { struct coord *test_27 (void) { struct coord *p = (struct coord *) malloc (sizeof (struct coord)); /* { dg-message "this call could return NULL" } */ - p->x = 0.f; /* { dg-warning "dereference of possibly-NULL 'p'" } */ + p->x = 0.f; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */ /* Only the first such usage should be reported: */ p->y = 0.f; @@ -313,7 +313,7 @@ struct coord *test_27 (void) struct coord *test_28 (void) { struct coord *p = NULL; - p->x = 0.f; /* { dg-warning "dereference of NULL 'p'" } */ + p->x = 0.f; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */ /* Only the first such usage should be reported: */ p->y = 0.f; @@ -416,7 +416,7 @@ void test_36 (void) void *test_37a (void) { void *ptr = malloc(4096); /* { dg-message "this call could return NULL" } */ - __builtin_memset(ptr, 0, 4096); /* { dg-warning "use of possibly-NULL 'ptr' where non-null expected" } */ + __builtin_memset(ptr, 0, 4096); /* { dg-warning "use of possibly-NULL 'ptr' where non-null expected \\\[CWE-690\\\]" } */ return ptr; } @@ -427,7 +427,7 @@ int test_37b (void) if (p) { __builtin_memset(p, 0, 4096); /* Not a bug: checked */ } else { - __builtin_memset(q, 0, 4096); /* { dg-warning "use of possibly-NULL 'q' where non-null expected" } */ + __builtin_memset(q, 0, 4096); /* { dg-warning "use of possibly-NULL 'q' where non-null expected \\\[CWE-690\\\]" } */ } free(p); free(q); @@ -452,7 +452,7 @@ int * test_39 (int i) { int *p = (int*)malloc(sizeof(int*)); /* { dg-message "this call could return NULL" } */ - *p = i; /* { dg-warning "dereference of possibly-NULL 'p'" } */ + *p = i; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */ return p; } @@ -460,7 +460,7 @@ int * test_40 (int i) { int *p = (int*)malloc(sizeof(int*)); - i = *p; /* { dg-warning "dereference of possibly-NULL 'p'" } */ + i = *p; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */ /* TODO: (it's also uninitialized) */ return p; } @@ -476,8 +476,8 @@ test_41 (int flag) buffer = NULL; } - buffer[0] = 'a'; /* { dg-warning "dereference of possibly-NULL 'buffer'" "possibly-NULL" } */ - /* { dg-warning "dereference of NULL 'buffer'" "NULL" { target *-*-* } .-1 } */ + buffer[0] = 'a'; /* { dg-warning "dereference of possibly-NULL 'buffer' \\\[CWE-690\\\]" "possibly-NULL" } */ + /* { dg-warning "dereference of NULL 'buffer' \\\[CWE-476\\\]" "NULL" { target *-*-* } .-1 } */ return buffer; } @@ -594,7 +594,7 @@ int test_47 (void) void test_48 (void) { int *p = NULL; /* { dg-message "'p' is NULL" } */ - *p = 1; /* { dg-warning "dereference of NULL 'p'" } */ + *p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */ } /* As test_48, but where the assignment of NULL is not at the start of a BB. */ @@ -606,6 +606,6 @@ int test_49 (int i) x = i * 2; p = NULL; /* { dg-message "'p' is NULL" } */ - *p = 1; /* { dg-warning "dereference of NULL 'p'" } */ + *p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */ return x; } diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c index bf5b9bf..4787fa3 100644 --- a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c +++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c @@ -51,18 +51,25 @@ void outer (void) | | | | | (4) 'setjmp' called here | + 'inner': event 5 + | + | NN | } + | | ^ + | | | + | | (5) stack frame is popped here, invalidating saved environment + | <------+ | - 'outer': events 5-6 + 'outer': events 6-7 | | NN | inner (); | | ^~~~~~~~ | | | - | | (5) returning to 'outer' from 'inner' + | | (6) returning to 'outer' from 'inner' | NN | | NN | longjmp (env, 42); | | ~~~~~~~~~~~~~~~~~ | | | - | | (6) here + | | (7) 'longjmp' called after enclosing function of 'setjmp' returned at (5) | { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/array-quals-1.c b/gcc/testsuite/gcc.dg/array-quals-1.c index 3981c91..31aa1d3 100644 --- a/gcc/testsuite/gcc.dg/array-quals-1.c +++ b/gcc/testsuite/gcc.dg/array-quals-1.c @@ -6,26 +6,46 @@ /* { dg-options "-Wno-discarded-array-qualifiers" } */ /* The MMIX port always switches to the .data section at the end of a file. */ /* { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail powerpc*-*-aix* mmix-*-* x86_64-*-mingw* } } } */ +/* { dg-final { scan-assembler-symbol-section {^_?a$} {^\.(const|rodata)|\[RO\]} } } */ static const int a[2] = { 1, 2 }; +/* { dg-final { scan-assembler-symbol-section {^_?a1$} {^\.(const|rodata)|\[RO\]} } } */ const int a1[2] = { 1, 2 }; typedef const int ci; +/* { dg-final { scan-assembler-symbol-section {^_?b$} {^\.(const|rodata)|\[RO\]} } } */ static ci b[2] = { 3, 4 }; +/* { dg-final { scan-assembler-symbol-section {^_?b1$} {^\.(const|rodata)|\[RO\]} } } */ ci b1[2] = { 3, 4 }; typedef int ia[2]; +/* { dg-final { scan-assembler-symbol-section {^_?c$} {^\.(const|rodata)|\[RO\]} } } */ static const ia c = { 5, 6 }; +/* { dg-final { scan-assembler-symbol-section {^_?c1$} {^\.(const|rodata)|\[RO\]} } } */ const ia c1 = { 5, 6 }; typedef const int cia[2]; +/* { dg-final { scan-assembler-symbol-section {^_?d$} {^\.(const|rodata)|\[RO\]} } } */ static cia d = { 7, 8 }; +/* { dg-final { scan-assembler-symbol-section {^_?d1$} {^\.(const|rodata)|\[RO\]} } } */ cia d1 = { 7, 8 }; +/* { dg-final { scan-assembler-symbol-section {^_?e$} {^\.(const|rodata)|\[RO\]} } } */ static cia e[2] = { { 1, 2 }, { 3, 4 } }; +/* { dg-final { scan-assembler-symbol-section {^_?e1$} {^\.(const|rodata)|\[RO\]} } } */ cia e1[2] = { { 1, 2 }, { 3, 4 } }; +/* { dg-final { scan-assembler-symbol-section {^_?p$} {^\.(const|rodata)|\[RW\]} } } */ void *const p = &a; +/* { dg-final { scan-assembler-symbol-section {^_?q$} {^\.(const|rodata)|\[RW\]} } } */ void *const q = &b; +/* { dg-final { scan-assembler-symbol-section {^_?r$} {^\.(const|rodata)|\[RW\]} } } */ void *const r = &c; +/* { dg-final { scan-assembler-symbol-section {^_?s$} {^\.(const|rodata)|\[RW\]} } } */ void *const s = &d; +/* { dg-final { scan-assembler-symbol-section {^_?t$} {^\.(const|rodata)|\[RW\]} } } */ void *const t = &e; +/* { dg-final { scan-assembler-symbol-section {^_?p1$} {^\.(const|rodata)|\[RW\]} } } */ void *const p1 = &a1; +/* { dg-final { scan-assembler-symbol-section {^_?q1$} {^\.(const|rodata)|\[RW\]} } } */ void *const q1 = &b1; +/* { dg-final { scan-assembler-symbol-section {^_?r1$} {^\.(const|rodata)|\[RW\]} } } */ void *const r1 = &c1; +/* { dg-final { scan-assembler-symbol-section {^_?s1$} {^\.(const|rodata)|\[RW\]} } } */ void *const s1 = &d1; +/* { dg-final { scan-assembler-symbol-section {^_?t1$} {^\.(const|rodata)|\[RW\]} } } */ void *const t1 = &e1; diff --git a/gcc/testsuite/gcc.dg/attr-access-3.c b/gcc/testsuite/gcc.dg/attr-access-3.c new file mode 100644 index 0000000..45dd1aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-access-3.c @@ -0,0 +1,21 @@ +/* PR middle-end/97879 - ICE on invalid mode in attribute access + { dg-do compile } + { dg-options "-Wall" } */ + +#define A(...) __attribute__ ((access (__VA_ARGS__))) + +A (" ", 1) void f1 (int *); // { dg-error "attribute 'access' mode '\" \"' is not an identifier; expected one of 'read_only', 'read_write', 'write_only', or 'none'" } + void f1 (int *); + + +A ("none", 1) void f2 (char *); // { dg-error "not an identifier" } + void f2 (char *); + +A (1) void f3 (); // { dg-error "not an identifier" } + +A (1, 2) void f4 (); // { dg-error "not an identifier" } +A (2., 3.) void f5 (); // { dg-error "not an identifier" } + +// Verify that copying a valid access attribute doesn't cause errors. +A (read_only, 1, 2) void f6 (void*, int); +__attribute__ ((copy (f6))) void f7 (void*, int); diff --git a/gcc/testsuite/gcc.dg/attr-access-4.c b/gcc/testsuite/gcc.dg/attr-access-4.c new file mode 100644 index 0000000..7a2870a --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-access-4.c @@ -0,0 +1,8 @@ +/* PR middle-end/97861 - ICE on an invalid redeclaration of a function + with attribute access + { dg-do compile } + { dg-options "-Wall" } */ + +__attribute__ ((access (read_only, 2))) +void f (int, int*); +void f (int a) { } // { dg-error "conflicting types for 'f'" } diff --git a/gcc/testsuite/gcc.dg/attr-access-5.c b/gcc/testsuite/gcc.dg/attr-access-5.c new file mode 100644 index 0000000..e78b360 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-access-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } + { dg-options "-fdump-tree-gimple" } */ + +__attribute__ ((aligned (32))) +__attribute__ ((access (write_only, 2, 1))) +void f (int n, void *p) +{ + __builtin_memset (p, 0, n); +} + +/* Verify the DECL_ATTRIBUTE "aligned" is mentioned: + { dg-final { scan-tree-dump "__attribute__\\(\\(aligned" "gimple" } } + and the TYPE_ATTRIBUTE "access" is also mentioned: + { dg-final { scan-tree-dump "__attribute__\\(\\(access" "gimple" } } + and the function signature including its return type is mentioned: + { dg-final { scan-tree-dump "void f *\\(int n, void *\\* *p\\)" "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/binary-constants-2.c b/gcc/testsuite/gcc.dg/binary-constants-2.c index 6c3928a..5339d57 100644 --- a/gcc/testsuite/gcc.dg/binary-constants-2.c +++ b/gcc/testsuite/gcc.dg/binary-constants-2.c @@ -9,8 +9,8 @@ int foo (void) { -#if FOO /* { dg-warning "binary constants are a GCC extension" } */ +#if FOO /* { dg-warning "binary constants are a C2X feature or GCC extension" } */ return 23; #endif - return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */ + return 0b1101; /* { dg-warning "binary constants are a C2X feature or GCC extension" } */ } diff --git a/gcc/testsuite/gcc.dg/binary-constants-3.c b/gcc/testsuite/gcc.dg/binary-constants-3.c index 410fc4c..5b49cb4 100644 --- a/gcc/testsuite/gcc.dg/binary-constants-3.c +++ b/gcc/testsuite/gcc.dg/binary-constants-3.c @@ -9,8 +9,8 @@ int foo (void) { -#if FOO /* { dg-error "binary constants are a GCC extension" } */ +#if FOO /* { dg-error "binary constants are a C2X feature or GCC extension" } */ return 23; #endif - return 0b1101; /* { dg-error "binary constants are a GCC extension" } */ + return 0b1101; /* { dg-error "binary constants are a C2X feature or GCC extension" } */ } diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c new file mode 100644 index 0000000..ab7d82a --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-4.c @@ -0,0 +1,43 @@ +/* PR c/90628 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +_Atomic int a = 1, b = 2, c = 3; +_Atomic long d = 4, e = 5, f = 6; +_Atomic long long g = 7, h = 8, i = 9; + +void +f1 () +{ + __builtin_add_overflow (a, b, &c); /* { dg-error "argument 3 in call to function '__builtin_add_overflow' has pointer to '_Atomic' type" } */ +} + +void +f2 () +{ + __builtin_sub_overflow (d, e, &f); /* { dg-error "argument 3 in call to function '__builtin_sub_overflow' has pointer to '_Atomic' type" } */ +} + +void +f3 () +{ + __builtin_mul_overflow (g, h, &i); /* { dg-error "argument 3 in call to function '__builtin_mul_overflow' has pointer to '_Atomic' type" } */ +} + +void +f4 () +{ + __builtin_sadd_overflow (a, b, &c); /* { dg-warning "passing argument 3 of '__builtin_sadd_overflow' from incompatible pointer type" } */ +} + +void +f5 () +{ + __builtin_ssubl_overflow (d, e, &f); /* { dg-warning "passing argument 3 of '__builtin_ssubl_overflow' from incompatible pointer type" } */ +} + +void +f6 () +{ + __builtin_smulll_overflow (g, h, &i); /* { dg-warning "passing argument 3 of '__builtin_smulll_overflow' from incompatible pointer type" } */ +} diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c new file mode 100644 index 0000000..b43fd18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-5.c @@ -0,0 +1,87 @@ +/* PR rtl-optimization/95862 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int +f1 (int a, int b) +{ + unsigned long long c; + return __builtin_mul_overflow (a, b, &c); +} + +int +f2 (int a, unsigned b) +{ + unsigned long long c; + return __builtin_mul_overflow (a, b, &c); +} + +int +f3 (unsigned a, unsigned b) +{ + long long c; + return __builtin_mul_overflow (a, b, &c); +} + +int +f4 (int a, unsigned b) +{ + long long c; + return __builtin_mul_overflow (a, b, &c); +} + +short +f5 (short a, short b) +{ + unsigned c; + return __builtin_mul_overflow (a, b, &c); +} + +short +f6 (short a, unsigned short b) +{ + unsigned c; + return __builtin_mul_overflow (a, b, &c); +} + +short +f7 (unsigned short a, unsigned short b) +{ + int c; + return __builtin_mul_overflow (a, b, &c); +} + +short +f8 (short a, unsigned short b) +{ + int c; + return __builtin_mul_overflow (a, b, &c); +} + +signed char +f9 (signed char a, signed char b) +{ + unsigned short c; + return __builtin_mul_overflow (a, b, &c); +} + +signed char +f10 (signed char a, unsigned char b) +{ + unsigned short c; + return __builtin_mul_overflow (a, b, &c); +} + +signed char +f11 (unsigned char a, unsigned char b) +{ + short c; + return __builtin_mul_overflow (a, b, &c); +} + +signed char +f12 (signed char a, unsigned char b) +{ + short c; + return __builtin_mul_overflow (a, b, &c); +} diff --git a/gcc/testsuite/gcc.dg/builtin-clear-padding-1.c b/gcc/testsuite/gcc.dg/builtin-clear-padding-1.c new file mode 100644 index 0000000..27ffc0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-clear-padding-1.c @@ -0,0 +1,10 @@ +/* PR libstdc++/88101 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (int n) +{ + struct S { char a; int b[n]; long long c; } s; + __builtin_clear_padding (&s); /* { dg-message "unimplemented: __builtin_clear_padding not supported for variable length aggregates" } */ +} diff --git a/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c b/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c new file mode 100644 index 0000000..641d47d --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c @@ -0,0 +1,15 @@ +/* PR middle-end/97943 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); }; +struct T { int a; struct S b; int c; }; +union U { int a; struct S b; }; +struct V { int a; union U b; int : 15; int c; }; + +void +foo (struct T *t, struct V *v) +{ + __builtin_clear_padding (t); /* { dg-error "flexible array member 'b' does not have well defined padding bits for '__builtin_clear_padding'" } */ + __builtin_clear_padding (v); /* { dg-error "flexible array member 'b' does not have well defined padding bits for '__builtin_clear_padding'" } */ +} diff --git a/gcc/testsuite/gcc.dg/c11-binary-constants-1.c b/gcc/testsuite/gcc.dg/c11-binary-constants-1.c new file mode 100644 index 0000000..fdc7df4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-binary-constants-1.c @@ -0,0 +1,11 @@ +/* Test that binary constants are diagnosed in C11 mode: -pedantic. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic" } */ + +int a = 0b1; /* { dg-warning "binary constants" } */ +#if 0b101 /* { dg-warning "binary constants" } */ +#endif + +int b = 0B1; /* { dg-warning "binary constants" } */ +#if 0B101 /* { dg-warning "binary constants" } */ +#endif diff --git a/gcc/testsuite/gcc.dg/c11-binary-constants-2.c b/gcc/testsuite/gcc.dg/c11-binary-constants-2.c new file mode 100644 index 0000000..6b48a5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-binary-constants-2.c @@ -0,0 +1,11 @@ +/* Test that binary constants are diagnosed in C11 mode: -pedantic-errors. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int a = 0b1; /* { dg-error "binary constants" } */ +#if 0b101 /* { dg-error "binary constants" } */ +#endif + +int b = 0B1; /* { dg-error "binary constants" } */ +#if 0B101 /* { dg-error "binary constants" } */ +#endif diff --git a/gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c b/gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c new file mode 100644 index 0000000..b1c05cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-compare-incomplete-1.c @@ -0,0 +1,52 @@ +/* Test comparisons of pointers to complete and incomplete types are + accepted in C11 mode. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int +f (int (*p)[], int (*q)[3]) +{ + return p < q; +} + +int +f2 (int (*p)[], int (*q)[3]) +{ + return p <= q; +} + +int +f3 (int (*p)[], int (*q)[3]) +{ + return p > q; +} + +int +f4 (int (*p)[], int (*q)[3]) +{ + return p >= q; +} + +int +g (int (*p)[], int (*q)[3]) +{ + return q < p; +} + +int +g2 (int (*p)[], int (*q)[3]) +{ + return q <= p; +} + +int +g3 (int (*p)[], int (*q)[3]) +{ + return q > p; +} + +int +g4 (int (*p)[], int (*q)[3]) +{ + return q >= p; +} diff --git a/gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c b/gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c new file mode 100644 index 0000000..8e809e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-compare-incomplete-2.c @@ -0,0 +1,52 @@ +/* Test comparisons of pointers to complete and incomplete types are + diagnosed in C11 mode with -Wc99-c11-compat. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors -Wc99-c11-compat" } */ + +int +f (int (*p)[], int (*q)[3]) +{ + return p < q; /* { dg-warning "complete and incomplete" } */ +} + +int +f2 (int (*p)[], int (*q)[3]) +{ + return p <= q; /* { dg-warning "complete and incomplete" } */ +} + +int +f3 (int (*p)[], int (*q)[3]) +{ + return p > q; /* { dg-warning "complete and incomplete" } */ +} + +int +f4 (int (*p)[], int (*q)[3]) +{ + return p >= q; /* { dg-warning "complete and incomplete" } */ +} + +int +g (int (*p)[], int (*q)[3]) +{ + return q < p; /* { dg-warning "complete and incomplete" } */ +} + +int +g2 (int (*p)[], int (*q)[3]) +{ + return q <= p; /* { dg-warning "complete and incomplete" } */ +} + +int +g3 (int (*p)[], int (*q)[3]) +{ + return q > p; /* { dg-warning "complete and incomplete" } */ +} + +int +g4 (int (*p)[], int (*q)[3]) +{ + return q >= p; /* { dg-warning "complete and incomplete" } */ +} diff --git a/gcc/testsuite/gcc.dg/c11-float-4.c b/gcc/testsuite/gcc.dg/c11-float-4.c new file mode 100644 index 0000000..ceac6ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-float-4.c @@ -0,0 +1,25 @@ +/* Test infinity and NaN macros not defined for C11. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +#include <float.h> + +#ifdef INFINITY +#error "INFINITY defined" +#endif + +#ifdef NAN +#error "NAN defined" +#endif + +#ifdef FLT_SNAN +#error "FLT_SNAN defined" +#endif + +#ifdef DBL_SNAN +#error "DBL_SNAN defined" +#endif + +#ifdef LDBL_SNAN +#error "LDBL_SNAN defined" +#endif diff --git a/gcc/testsuite/gcc.dg/c11-float-5.c b/gcc/testsuite/gcc.dg/c11-float-5.c new file mode 100644 index 0000000..bb48695 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-float-5.c @@ -0,0 +1,35 @@ +/* Test sNaN macros for _FloatN and _FloatNx not defined for C11 with + __STDC_WANT_IEC_60559_TYPES_EXT__. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> + +#ifdef FLT16_SNAN +#error "FLT16_SNAN defined" +#endif + +#ifdef FLT32_SNAN +#error "FLT32_SNAN defined" +#endif + +#ifdef FLT64_SNAN +#error "FLT64_SNAN defined" +#endif + +#ifdef FLT128_SNAN +#error "FLT128_SNAN defined" +#endif + +#ifdef FLT32X_SNAN +#error "FLT32X_SNAN defined" +#endif + +#ifdef FLT64X_SNAN +#error "FLT64X_SNAN defined" +#endif + +#ifdef FLT128X_SNAN +#error "FLT128X_SNAN defined" +#endif diff --git a/gcc/testsuite/gcc.dg/c11-float-6.c b/gcc/testsuite/gcc.dg/c11-float-6.c new file mode 100644 index 0000000..b0381e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-float-6.c @@ -0,0 +1,17 @@ +/* Test *_IS_IEC_60559 not defined for C11. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +#include <float.h> + +#ifdef FLT_IS_IEC_60559 +#error "FLT_IS_IEC_60559 defined" +#endif + +#ifdef DBL_IS_IEC_60559 +#error "DBL_IS_IEC_60559 defined" +#endif + +#ifdef LDBL_IS_IEC_60559 +#error "LDBL_IS_IEC_60559 defined" +#endif diff --git a/gcc/testsuite/gcc.dg/c11-float-dfp-2.c b/gcc/testsuite/gcc.dg/c11-float-dfp-2.c new file mode 100644 index 0000000..e63ebbc --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-float-dfp-2.c @@ -0,0 +1,6 @@ +/* Test DFP macros not defined in <float.h> for C11. Infinity and NaN + macros. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11" } */ + +#include "c2x-float-no-dfp-3.c" diff --git a/gcc/testsuite/gcc.dg/c2x-binary-constants-1.c b/gcc/testsuite/gcc.dg/c2x-binary-constants-1.c new file mode 100644 index 0000000..bbb2bc8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-binary-constants-1.c @@ -0,0 +1,5 @@ +/* Test C2x binary constants. Valid syntax and types. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include "binary-constants-1.c" diff --git a/gcc/testsuite/gcc.dg/c2x-binary-constants-2.c b/gcc/testsuite/gcc.dg/c2x-binary-constants-2.c new file mode 100644 index 0000000..4379427 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-binary-constants-2.c @@ -0,0 +1,11 @@ +/* Test that binary constants are accepted in C2X mode: compat warnings. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -Wc11-c2x-compat" } */ + +int a = 0b1; /* { dg-warning "C2X feature" } */ +#if 0b101 /* { dg-warning "C2X feature" } */ +#endif + +int b = 0B1; /* { dg-warning "C2X feature" } */ +#if 0B101 /* { dg-warning "C2X feature" } */ +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-binary-constants-3.c b/gcc/testsuite/gcc.dg/c2x-binary-constants-3.c new file mode 100644 index 0000000..7604791f --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-binary-constants-3.c @@ -0,0 +1,9 @@ +/* Test C2x binary constants. Invalid constants. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +int a = 0b; /* { dg-error "invalid suffix" } */ +int b = 0B2; /* { dg-error "invalid suffix" } */ +int c = 0B02; /* { dg-error "invalid digit" } */ +int d = 0b1.1; /* { dg-error "invalid prefix" } */ +int e = 0B0p0; /* { dg-error "invalid suffix" } */ diff --git a/gcc/testsuite/gcc.dg/c2x-float-10.c b/gcc/testsuite/gcc.dg/c2x-float-10.c new file mode 100644 index 0000000..7b53a6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-10.c @@ -0,0 +1,33 @@ +/* Test *_IS_IEC_60559 macros. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include <float.h> + +#ifndef FLT_IS_IEC_60559 +#error "FLT_IS_IEC_60559 undefined" +#endif + +#ifndef DBL_IS_IEC_60559 +#error "DBL_IS_IEC_60559 undefined" +#endif + +#ifndef LDBL_IS_IEC_60559 +#error "LDBL_IS_IEC_60559 undefined" +#endif + +#if defined __pdp11__ || defined __vax__ +_Static_assert (FLT_IS_IEC_60559 == 0); +_Static_assert (DBL_IS_IEC_60559 == 0); +_Static_assert (LDBL_IS_IEC_60559 == 0); +#else +_Static_assert (FLT_IS_IEC_60559 == 2); +_Static_assert (DBL_IS_IEC_60559 == 2); +#if LDBL_MANT_DIG == 106 || LDBL_MIN_EXP == -16382 +/* IBM long double and m68k extended format do not meet the definition + of an IEC 60559 interchange or extended format. */ +_Static_assert (LDBL_IS_IEC_60559 == 0); +#else +_Static_assert (LDBL_IS_IEC_60559 == 2); +#endif +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-float-2.c b/gcc/testsuite/gcc.dg/c2x-float-2.c new file mode 100644 index 0000000..4f669fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-2.c @@ -0,0 +1,23 @@ +/* Test INFINITY macro. Generic test even if infinities not + supported. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -w" } */ +/* { dg-add-options ieee } */ + +#include <float.h> + +#ifndef INFINITY +#error "INFINITY undefined" +#endif + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (INFINITY, float : 0); + if (!(INFINITY >= FLT_MAX)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-float-3.c b/gcc/testsuite/gcc.dg/c2x-float-3.c new file mode 100644 index 0000000..7c6298b --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-3.c @@ -0,0 +1,27 @@ +/* Test INFINITY macro. Test when infinities supported. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target inff } */ + +#include <float.h> + +#ifndef INFINITY +#error "INFINITY undefined" +#endif + +volatile float f = INFINITY; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (INFINITY, float : 0); + if (!(INFINITY > FLT_MAX)) + abort (); + if (!(f > FLT_MAX)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-float-4.c b/gcc/testsuite/gcc.dg/c2x-float-4.c new file mode 100644 index 0000000..bca8435 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-4.c @@ -0,0 +1,33 @@ +/* Test NAN macro. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ +/* { dg-add-options ieee } */ + +#include <float.h> + +/* This should be defined if and only if quiet NaNs are supported for + type float. If the testsuite gains effective-target support for + targets not supporting NaNs, or not supporting them for all types, + this test should be split into versions for targets with and + without NaNs for float. */ +#ifndef NAN +#error "NAN undefined" +#endif + +volatile float f = NAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (NAN, float : 0); + if (!__builtin_isnan (NAN)) + abort (); + if (!__builtin_isnan (f)) + abort (); + if (!__builtin_isnan (f + f)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-float-5.c b/gcc/testsuite/gcc.dg/c2x-float-5.c new file mode 100644 index 0000000..477f9cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-5.c @@ -0,0 +1,32 @@ +/* Test NAN macro. Runtime exceptions test, to verify NaN is quiet + not signaling. */ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ +/* { dg-add-options ieee } */ + +#include <fenv.h> +#include <float.h> + +/* This should be defined if and only if quiet NaNs are supported for + type float. If the testsuite gains effective-target support for + targets not supporting NaNs, or not supporting them for all types, + this test should only be run for targets supporting quiet NaNs for + float. */ +#ifndef NAN +#error "NAN undefined" +#endif + +volatile float f = NAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + f += f; + if (fetestexcept (FE_INVALID)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-float-6.c b/gcc/testsuite/gcc.dg/c2x-float-6.c new file mode 100644 index 0000000..573540b --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-6.c @@ -0,0 +1,49 @@ +/* Test SNAN macros. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors -fsignaling-nans" } */ +/* { dg-add-options ieee } */ + +#include <float.h> + +/* These should be defined if and only if signaling NaNs are supported + for the given types. If the testsuite gains effective-target + support for targets not supporting signaling NaNs, or not + supporting them for all types, this test should be made + appropriately conditional. */ +#ifndef FLT_SNAN +#error "FLT_SNAN undefined" +#endif +#ifndef DBL_SNAN +#error "DBL_SNAN undefined" +#endif +#ifndef LDBL_SNAN +#error "LDBL_SNAN undefined" +#endif + +volatile float f = FLT_SNAN; +volatile double d = DBL_SNAN; +volatile long double ld = LDBL_SNAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (FLT_SNAN, float : 0); + (void) _Generic (DBL_SNAN, double : 0); + (void) _Generic (LDBL_SNAN, long double : 0); + if (!__builtin_isnan (FLT_SNAN)) + abort (); + if (!__builtin_isnan (f)) + abort (); + if (!__builtin_isnan (DBL_SNAN)) + abort (); + if (!__builtin_isnan (d)) + abort (); + if (!__builtin_isnan (LDBL_SNAN)) + abort (); + if (!__builtin_isnan (ld)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-float-7.c b/gcc/testsuite/gcc.dg/c2x-float-7.c new file mode 100644 index 0000000..0c90ff2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-7.c @@ -0,0 +1,49 @@ +/* Test SNAN macros. Runtime exceptions test, to verify NaN is + signaling. */ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-std=c2x -pedantic-errors -fsignaling-nans" } */ +/* { dg-add-options ieee } */ + +#include <fenv.h> +#include <float.h> + +/* These should be defined if and only if signaling NaNs are supported + for the given types. If the testsuite gains effective-target + support for targets not supporting signaling NaNs, or not + supporting them for all types, this test should be made + appropriately conditional. */ +#ifndef FLT_SNAN +#error "FLT_SNAN undefined" +#endif +#ifndef DBL_SNAN +#error "DBL_SNAN undefined" +#endif +#ifndef LDBL_SNAN +#error "LDBL_SNAN undefined" +#endif + +volatile float f = FLT_SNAN; +volatile double d = DBL_SNAN; +volatile long double ld = LDBL_SNAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + feclearexcept (FE_ALL_EXCEPT); + f += f; + if (!fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + d += d; + if (!fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + ld += ld; + if (!fetestexcept (FE_INVALID)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-float-8.c b/gcc/testsuite/gcc.dg/c2x-float-8.c new file mode 100644 index 0000000..b10cb85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-8.c @@ -0,0 +1,7 @@ +/* Test including <math.h> then <float.h> does not result in errors + from duplicate NAN and INFINITY macros. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include <math.h> +#include <float.h> diff --git a/gcc/testsuite/gcc.dg/c2x-float-9.c b/gcc/testsuite/gcc.dg/c2x-float-9.c new file mode 100644 index 0000000..0a54bc2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-9.c @@ -0,0 +1,7 @@ +/* Test including <float.h> then <math.h> does not result in errors + from duplicate NAN and INFINITY macros. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include <float.h> +#include <math.h> diff --git a/gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c new file mode 100644 index 0000000..aa790c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-3.c @@ -0,0 +1,26 @@ +/* Test DFP macros not defined in <float.h> if no DFP support. + Infinity and NaN macros. */ +/* { dg-do compile { target { ! dfp } } } */ +/* { dg-options "-std=c2x" } */ + +#include <float.h> + +#ifdef DEC_INFINITY +# error "DEC_INFINITY defined" +#endif + +#ifdef DEC_NAN +# error "DEC_NAN defined" +#endif + +#ifdef DEC32_SNAN +# error "DEC32_SNAN defined" +#endif + +#ifdef DEC64_SNAN +# error "DEC64_SNAN defined" +#endif + +#ifdef DEC128_SNAN +# error "DEC128_SNAN defined" +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c new file mode 100644 index 0000000..855922a --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-no-dfp-4.c @@ -0,0 +1,10 @@ +/* Test DFP macros not defined in <float.h> if no DFP support. + Infinity and NaN macros. Test with feature test macros + defined. */ +/* { dg-do compile { target { ! dfp } } } */ +/* { dg-options "-std=c2x" } */ + +#define __STDC_WANT_DEC_FP__ +#define __STDC_WANT_IEC_60559_DFP_EXT__ + +#include "c2x-float-no-dfp-3.c" diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c new file mode 100644 index 0000000..fe06abf --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-1.c @@ -0,0 +1,28 @@ +/* Test __has_c_attribute. Test basic properties. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#ifdef __has_c_attribute +/* OK. */ +#else +#error "__has_c_attribute not defined" +#endif + +#ifndef __has_c_attribute +#error "__has_c_attribute not defined" +#endif + +#if defined __has_c_attribute +/* OK. */ +#else +#error "__has_c_attribute not defined" +#endif + +#if __has_c_attribute(foo) +#error "foo attribute supported" +#endif + +#if 0 +#elif __has_c_attribute(foo) +#error "foo attribute supported" +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c new file mode 100644 index 0000000..d6c4c6d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c @@ -0,0 +1,41 @@ +/* Test __has_c_attribute. Test supported attributes. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#if __has_c_attribute ( nodiscard ) != 202003L +#error "bad result for nodiscard" +#endif + +#if __has_c_attribute ( __nodiscard__ ) != 202003L +#error "bad result for __nodiscard__" +#endif + +#if __has_c_attribute(maybe_unused) != 201904L +#error "bad result for maybe_unused" +#endif + +#if __has_c_attribute(__maybe_unused__) != 201904L +#error "bad result for __maybe_unused__" +#endif + +#if __has_c_attribute (deprecated) != 201904L +#error "bad result for deprecated" +#endif + +#if __has_c_attribute (__deprecated__) != 201904L +#error "bad result for __deprecated__" +#endif + +#if __has_c_attribute (fallthrough) != 201904L +#error "bad result for fallthrough" +#endif + +#if __has_c_attribute (__fallthrough__) != 201904L +#error "bad result for __fallthrough__" +#endif + +/* Macros in the attribute name are expanded. */ +#define foo deprecated +#if __has_c_attribute (foo) != 201904L +#error "bad result for foo" +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c new file mode 100644 index 0000000..36842ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-3.c @@ -0,0 +1,25 @@ +/* Test __has_c_attribute. Test GNU attributes. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#if __has_c_attribute (gnu::packed) != 1 +#error "bad result for gnu::packed" +#endif + +#if __has_c_attribute (__gnu__::__packed__) != 1 +#error "bad result for __gnu__::__packed__" +#endif + +#if __has_c_attribute (gnu::__packed__) != 1 +#error "bad result for gnu::__packed__" +#endif + +#if __has_c_attribute (__gnu__::packed) != 1 +#error "bad result for __gnu__::packed" +#endif + +/* GNU attributes should not be reported as accepted without a scope + specified. */ +#if __has_c_attribute (packed) != 0 +#error "bad result for packed" +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c new file mode 100644 index 0000000..acd35d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-4.c @@ -0,0 +1,18 @@ +/* Test __has_c_attribute. Test syntax errors. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#if __has_c_attribute /* { dg-error "missing '\\('" } */ +#endif + +#if __has_c_attribute 0 /* { dg-error "missing '\\('" } */ +#endif + +#if __has_c_attribute (0 /* { dg-error "requires an identifier" } */ +#endif + +#if __has_c_attribute (x /* { dg-error "missing '\\)'" } */ +#endif + +#if __has_c_attribute (x::0) /* { dg-error "required after scope" } */ +#endif diff --git a/gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c b/gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c new file mode 100644 index 0000000..dfafc39 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-compare-incomplete-1.c @@ -0,0 +1,52 @@ +/* Test comparisons of pointers to complete and incomplete types are + diagnosed in C99 mode: -pedantic. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -pedantic" } */ + +int +f (int (*p)[], int (*q)[3]) +{ + return p < q; /* { dg-warning "complete and incomplete" } */ +} + +int +f2 (int (*p)[], int (*q)[3]) +{ + return p <= q; /* { dg-warning "complete and incomplete" } */ +} + +int +f3 (int (*p)[], int (*q)[3]) +{ + return p > q; /* { dg-warning "complete and incomplete" } */ +} + +int +f4 (int (*p)[], int (*q)[3]) +{ + return p >= q; /* { dg-warning "complete and incomplete" } */ +} + +int +g (int (*p)[], int (*q)[3]) +{ + return q < p; /* { dg-warning "complete and incomplete" } */ +} + +int +g2 (int (*p)[], int (*q)[3]) +{ + return q <= p; /* { dg-warning "complete and incomplete" } */ +} + +int +g3 (int (*p)[], int (*q)[3]) +{ + return q > p; /* { dg-warning "complete and incomplete" } */ +} + +int +g4 (int (*p)[], int (*q)[3]) +{ + return q >= p; /* { dg-warning "complete and incomplete" } */ +} diff --git a/gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c b/gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c new file mode 100644 index 0000000..5ae7f30 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-compare-incomplete-2.c @@ -0,0 +1,52 @@ +/* Test comparisons of pointers to complete and incomplete types are + diagnosed in C99 mode: -pedantic-errors. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -pedantic-errors" } */ + +int +f (int (*p)[], int (*q)[3]) +{ + return p < q; /* { dg-error "complete and incomplete" } */ +} + +int +f2 (int (*p)[], int (*q)[3]) +{ + return p <= q; /* { dg-error "complete and incomplete" } */ +} + +int +f3 (int (*p)[], int (*q)[3]) +{ + return p > q; /* { dg-error "complete and incomplete" } */ +} + +int +f4 (int (*p)[], int (*q)[3]) +{ + return p >= q; /* { dg-error "complete and incomplete" } */ +} + +int +g (int (*p)[], int (*q)[3]) +{ + return q < p; /* { dg-error "complete and incomplete" } */ +} + +int +g2 (int (*p)[], int (*q)[3]) +{ + return q <= p; /* { dg-error "complete and incomplete" } */ +} + +int +g3 (int (*p)[], int (*q)[3]) +{ + return q > p; /* { dg-error "complete and incomplete" } */ +} + +int +g4 (int (*p)[], int (*q)[3]) +{ + return q >= p; /* { dg-error "complete and incomplete" } */ +} diff --git a/gcc/testsuite/gcc.dg/cond-constqual-1.c b/gcc/testsuite/gcc.dg/cond-constqual-1.c index 3354c72..b5a09cb 100644 --- a/gcc/testsuite/gcc.dg/cond-constqual-1.c +++ b/gcc/testsuite/gcc.dg/cond-constqual-1.c @@ -11,5 +11,5 @@ test (void) __typeof__ (1 ? foo (0) : 0) texpr; __typeof__ (1 ? i : 0) texpr2; texpr = 0; /* { dg-bogus "read-only variable" "conditional expression with call to const function" } */ - texpr2 = 0; /* { dg-error "read-only variable" "conditional expression with const variable" } */ + texpr2 = 0; /* { dg-bogus "read-only variable" "conditional expression with const variable" } */ } diff --git a/gcc/testsuite/gcc.dg/cpp/line10.c b/gcc/testsuite/gcc.dg/cpp/line10.c new file mode 100644 index 0000000..9f5f079 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/line10.c @@ -0,0 +1,5 @@ +/* Test #line overflow checks: bug 97602. */ +/* { dg-do preprocess } */ +/* { dg-options "-pedantic" } */ + +#line 4294967296 /* { dg-warning "line number out of range" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/line9.c b/gcc/testsuite/gcc.dg/cpp/line9.c new file mode 100644 index 0000000..8060aff --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/line9.c @@ -0,0 +1,5 @@ +/* Test #line overflow checks: bug 97602. */ +/* { dg-do preprocess } */ +/* { dg-options "-pedantic" } */ + +#line 5000000000 /* { dg-warning "line number out of range" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/pr97989-1.c b/gcc/testsuite/gcc.dg/cpp/pr97989-1.c new file mode 100644 index 0000000..108dcba --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/pr97989-1.c @@ -0,0 +1,8 @@ +/* PR debug/97989 */ +/* { dg-do preprocess } */ +/* { dg-options "-g3 -g2 -P" } */ + +#define foo bar +int i; + +/* { dg-final { scan-file-not pr97989-1.i "(^|\\n)#define foo bar($|\\n)" } } */ diff --git a/gcc/testsuite/gcc.dg/cpp/pr97989-2.c b/gcc/testsuite/gcc.dg/cpp/pr97989-2.c new file mode 100644 index 0000000..77a295a --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/pr97989-2.c @@ -0,0 +1,8 @@ +/* PR debug/97989 */ +/* { dg-do preprocess } */ +/* { dg-options "-g2 -g3 -P" } */ + +#define foo bar +int i; + +/* { dg-final { scan-file pr97989-2.i "(^|\\n)#define foo bar($|\\n)" } } */ diff --git a/gcc/testsuite/gcc.dg/cr-decimal-dig-3.c b/gcc/testsuite/gcc.dg/cr-decimal-dig-3.c new file mode 100644 index 0000000..8e07b67 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cr-decimal-dig-3.c @@ -0,0 +1,14 @@ +/* Test C2x CR_DECIMAL_DIG: defined for __STDC_WANT_IEC_60559_EXT__. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x" } */ + +#define __STDC_WANT_IEC_60559_EXT__ +#include <float.h> + +#ifndef CR_DECIMAL_DIG +#error "CR_DECIMAL_DIG not defined" +#endif + +#if CR_DECIMAL_DIG < DECIMAL_DIG + 3 +#error "CR_DECIMAL_DIG too small" +#endif diff --git a/gcc/testsuite/gcc.dg/darwin-sections.c b/gcc/testsuite/gcc.dg/darwin-sections.c index dbe3702..5fc2860 100644 --- a/gcc/testsuite/gcc.dg/darwin-sections.c +++ b/gcc/testsuite/gcc.dg/darwin-sections.c @@ -10,7 +10,9 @@ typedef struct _empty {} e_s; /* These should go in .comm */ char ub; e_s ea; +/* { dg-final { scan-assembler-symbol-section {^_a$} {\.data} } } */ /* { dg-final { scan-assembler ".comm\[\t \]_ub,1" } } */ +/* { dg-final { scan-assembler-symbol-section {^_b$} {\.data} } } */ /* { dg-final { scan-assembler ".comm\[\t \]_ea,1" } } */ /* These should go into __DATA,__common */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c new file mode 100644 index 0000000..c07b904 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr97060.c @@ -0,0 +1,13 @@ +/* PR debug/97060 */ +/* { dg-do compile } */ +/* { dg-options "-g -dA" } */ +/* { dg-final { scan-assembler-times "DW_AT_declaration" 2 } } */ + +extern int foo (unsigned int, unsigned int); + +int +bar (void) +{ + foo (1, 2); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c new file mode 100644 index 0000000..58ee74d --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-4.c @@ -0,0 +1,25 @@ +/* Test DEC_INFINITY defined in <float.h> with DFP support. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x" } */ + +#include <float.h> + +#ifndef DEC_INFINITY +# error "DEC_INFINITY not defined" +#endif + +volatile _Decimal32 d = DEC_INFINITY; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (DEC_INFINITY, _Decimal32 : 0); + if (!(DEC_INFINITY > DEC32_MAX)) + abort (); + if (!(d > DEC32_MAX)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c new file mode 100644 index 0000000..8d09725 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-5.c @@ -0,0 +1,25 @@ +/* Test DEC_NAN defined in <float.h> with DFP support. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x" } */ + +#include <float.h> + +#ifndef DEC_NAN +# error "DEC_NAN not defined" +#endif + +volatile _Decimal32 d = DEC_NAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (DEC_NAN, _Decimal32 : 0); + if (!__builtin_isnan (DEC_NAN)) + abort (); + if (!__builtin_isnan (d)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c new file mode 100644 index 0000000..4533c61 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-6.c @@ -0,0 +1,28 @@ +/* Test DEC_NAN macro. Runtime exceptions test, to verify NaN is + quiet not signaling. (This would only actually fail for a + signaling NaN in the hardware DFP case, because the software DFP + support in libgcc does not integrate with hardware exceptions.) */ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-std=c2x" } */ + +#include <fenv.h> +#include <float.h> + +#ifndef DEC_NAN +# error "DEC_NAN not defined" +#endif + +volatile _Decimal32 d = DEC_NAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + d += d; + if (fetestexcept (FE_INVALID)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c new file mode 100644 index 0000000..dec6b50 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-7.c @@ -0,0 +1,45 @@ +/* Test DEC*_SNAN macros defined in <float.h> with DFP support. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x" } */ + +#include <float.h> + +#ifndef DEC32_SNAN +# error "DEC32_SNAN not defined" +#endif + +#ifndef DEC64_SNAN +# error "DEC64_SNAN not defined" +#endif + +#ifndef DEC128_SNAN +# error "DEC128_SNAN not defined" +#endif + +volatile _Decimal32 d32 = DEC32_SNAN; +volatile _Decimal64 d64 = DEC64_SNAN; +volatile _Decimal128 d128 = DEC128_SNAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + (void) _Generic (DEC32_SNAN, _Decimal32 : 0); + if (!__builtin_isnan (DEC32_SNAN)) + abort (); + if (!__builtin_isnan (d32)) + abort (); + (void) _Generic (DEC64_SNAN, _Decimal64 : 0); + if (!__builtin_isnan (DEC64_SNAN)) + abort (); + if (!__builtin_isnan (d64)) + abort (); + (void) _Generic (DEC128_SNAN, _Decimal128 : 0); + if (!__builtin_isnan (DEC128_SNAN)) + abort (); + if (!__builtin_isnan (d128)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c new file mode 100644 index 0000000..4169602 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/c2x-float-dfp-8.c @@ -0,0 +1,45 @@ +/* Test DEC*_SNAN macros. Test requiring runtime exceptions + support. */ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions_dfp } */ +/* { dg-options "-std=c2x" } */ + +#include <fenv.h> +#include <float.h> + +volatile _Decimal32 d32 = DEC32_SNAN; +volatile _Decimal64 d64 = DEC64_SNAN; +volatile _Decimal128 d128 = DEC128_SNAN; + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + feclearexcept (FE_ALL_EXCEPT); + d32 += d32; + if (!fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + d32 += d32; + if (fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + d64 += d64; + if (!fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + d64 += d64; + if (fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + d128 += d128; + if (!fetestexcept (FE_INVALID)) + abort (); + feclearexcept (FE_ALL_EXCEPT); + d128 += d128; + if (fetestexcept (FE_INVALID)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/fold-isfinite-1.c b/gcc/testsuite/gcc.dg/fold-isfinite-1.c new file mode 100644 index 0000000..2ea0192 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-isfinite-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target inf } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(int x) +{ + return __builtin_finite((double)x); +} + +int foof(int x) +{ + return __builtin_finitef((float)x); +} + +int fool(int x) +{ + return __builtin_finitel((long double)x); +} + +/* { dg-final { scan-tree-dump-times "_finite" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " u> " 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/fold-isfinite-2.c b/gcc/testsuite/gcc.dg/fold-isfinite-2.c new file mode 100644 index 0000000..ff70d8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-isfinite-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target inf } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(unsigned int x) +{ + return __builtin_finite((double)x); +} + +int foof(unsigned int x) +{ + return __builtin_finitef((float)x); +} + +int fool(unsigned int x) +{ + return __builtin_finitel((long double)x); +} + +/* { dg-final { scan-tree-dump-times "_finite" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " u> " 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/fold-isinf-1.c b/gcc/testsuite/gcc.dg/fold-isinf-1.c new file mode 100644 index 0000000..485816e --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-isinf-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target inf } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(int x) +{ + return __builtin_isinf((double)x); +} + +int foof(int x) +{ + return __builtin_isinff((float)x); +} + +int fool(int x) +{ + return __builtin_isinfl((long double)x); +} + +/* { dg-final { scan-tree-dump-times "_isinf" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " u<= " 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/fold-isinf-2.c b/gcc/testsuite/gcc.dg/fold-isinf-2.c new file mode 100644 index 0000000..a236ca1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-isinf-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target inf } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(unsigned int x) +{ + return __builtin_isinf((double)x); +} + +int foof(unsigned int x) +{ + return __builtin_isinff((float)x); +} + +int fool(unsigned int x) +{ + return __builtin_isinfl((long double)x); +} + +/* { dg-final { scan-tree-dump-times "_isinf" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " u<= " 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/fold-isnan-1.c b/gcc/testsuite/gcc.dg/fold-isnan-1.c new file mode 100644 index 0000000..05ee930 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-isnan-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target inf } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(int x) +{ + return __builtin_isnan((double)x); +} + +int foof(int x) +{ + return __builtin_isnanf((float)x); +} + +int fool(int x) +{ + return __builtin_isnanl((long double)x); +} + +/* { dg-final { scan-tree-dump-times "_isnan" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " unord " 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/fold-isnan-2.c b/gcc/testsuite/gcc.dg/fold-isnan-2.c new file mode 100644 index 0000000..32b8833 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-isnan-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target inf } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(unsigned int x) +{ + return __builtin_isnan((double)x); +} + +int foof(unsigned int x) +{ + return __builtin_isnanf((float)x); +} + +int fool(unsigned int x) +{ + return __builtin_isnanl((long double)x); +} + +/* { dg-final { scan-tree-dump-times "_isnan" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " unord " 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c b/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c index d8c51ea..f46f155 100644 --- a/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c +++ b/gcc/testsuite/gcc.dg/format/ms_c99-printf-3.c @@ -9,13 +9,33 @@ #include "format.h" void -foo (int i, char *s, size_t n, va_list v0, va_list v1, va_list v2, va_list v3, +foo (int i, char *s, size_t n, long l, llong ll, double d, + long double ld, va_list v0, va_list v1, va_list v2, va_list v3, va_list v4, va_list v5, va_list v6, va_list v7) { fprintf (stdout, "%d", i); fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */ printf ("%d", i); printf ("%ld", i); /* { dg-warning "format" "printf" } */ + /* These are accepted since MSVCR80, MSVCRT from Vista, UCRT, + * and mingw-w64 8.0 with C99/C++11. */ + printf ("%lld", i); /* { dg-warning "format" "printf" } */ + printf ("%lld", l); /* { dg-warning "format" "printf" } */ + printf ("%lld", ll); + printf ("%llu", i); /* { dg-warning "format" "printf" } */ + printf ("%llu", l); /* { dg-warning "format" "printf" } */ + printf ("%llu", ll); + printf ("%llx", i); /* { dg-warning "format" "printf" } */ + printf ("%llx", l); /* { dg-warning "format" "printf" } */ + printf ("%llx", ll); + /* As MSABI uses an 8-byte `long double`, `%Lg` matches GCC's + * `double` instead of `long double` which takes 10 bytes. */ + printf ("%Lg", d); + printf ("%Lg", ld); /* { dg-warning "format" "printf" } */ + printf ("%Le", d); + printf ("%Le", ld); /* { dg-warning "format" "printf" } */ + printf ("%Lf", d); + printf ("%Lf", ld); /* { dg-warning "format" "printf" } */ /* The "unlocked" functions shouldn't warn in c99 mode. */ fprintf_unlocked (stdout, "%ld", i); printf_unlocked ("%ld", i); diff --git a/gcc/testsuite/gcc.dg/goacc/tile-1.c b/gcc/testsuite/gcc.dg/goacc/tile-1.c new file mode 100644 index 0000000..6898397 --- /dev/null +++ b/gcc/testsuite/gcc.dg/goacc/tile-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +/* PR c/97880 */ + +void f () +{ + #pragma acc parallel loop tile(2, 3) + for (int i = 0; i < 8; i++) + for (long j = 0; j < 8; j++); +} diff --git a/gcc/testsuite/gcc.dg/guality/pr59776.c b/gcc/testsuite/gcc.dg/guality/pr59776.c index 6c1c816..7c95a9f 100644 --- a/gcc/testsuite/gcc.dg/guality/pr59776.c +++ b/gcc/testsuite/gcc.dg/guality/pr59776.c @@ -6,7 +6,7 @@ struct S { float f, g; }; -__attribute__((noinline, noclone)) void +__attribute__((noipa)) void foo (struct S *p) { struct S s1, s2; /* { dg-final { gdb-test pr59776.c:17 "s1.f" "5.0" } } */ diff --git a/gcc/testsuite/gcc.dg/hwasan/hwasan.exp b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp new file mode 100644 index 0000000..5c040ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp @@ -0,0 +1,36 @@ +# Copyright (C) 2012-2019 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp +load_lib hwasan-dg.exp + +# Initialize `dg'. +dg-init +hwasan_init + +# Main loop. +if [check_effective_target_fsanitize_hwaddress] { + gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/hwasan/*.c]] "" "" +} + +# All done. +hwasan_finish +dg-finish diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c new file mode 100644 index 0000000..0afcc10 --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +/* + Tests of nested funtions are: + 0) Accessing closed over variables works. + 1) Accesses outside of variables is caught. + 2) Accessing variable out of scope is caught. + + Here we test that accessing closed over variables works. + */ + +/* We need a second layer of indirection so that GCC doesn't notice we're + returning the address of a local variable and put 0 in it's place. */ +__attribute__((noinline)) +int *Ident(void *x) { + return x; +} + +int __attribute__ ((noinline)) +intermediate (void (*f) (int, char), + char num) +{ + if (num == 1) + /* NOTE: We need to overrun by an amount greater than the "extra data" in a + nonlocal goto structure. The entire structure is allocated on the stack + with a single tag, which means hwasan can't tell if a closed-over buffer + was overrun by an amount small enough that the access was still to some + data in that nonlocal goto structure. */ + f (100, 100); + else + f (3, 100); + /* Just return something ... */ + return num % 3; +} + +int* __attribute__ ((noinline)) +nested_function (char num) +{ + int big_array[16]; + int other_array[16]; + void store (int index, char value) + { big_array[index] = value; } + return Ident(&other_array[intermediate (store, num)]); +} + +#ifndef MAIN +int main () +{ + nested_function (0); + return 0; +} +#endif diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c new file mode 100644 index 0000000..0161281 --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* + Tests of nested funtions are: + 0) Accessing closed over variables works. + 1) Accesses outside of variables is caught. + 2) Accessing variable out of scope is caught. + + Here we test option 1. + */ + +#define MAIN 0 +#include "nested-functions-0.c" +#undef MAIN + +int main () +{ + nested_function (1); + return 0; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c new file mode 100644 index 0000000..b1a033f --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* + Tests of nested funtions are: + 0) Accessing closed over variables works. + 1) Accesses outside of variables is caught. + 2) Accessing variable out of scope is caught. + + Here we test option 2. + */ + +#define MAIN 0 +#include "nested-functions-0.c" +#undef MAIN + +int main () +{ + int *retval = nested_function (2); + *retval = 100; + return 0; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/gcc.dg/ipa/modref-2.c b/gcc/testsuite/gcc.dg/ipa/modref-2.c index 5ac2c65..51ac658 100644 --- a/gcc/testsuite/gcc.dg/ipa/modref-2.c +++ b/gcc/testsuite/gcc.dg/ipa/modref-2.c @@ -11,5 +11,6 @@ test2 (double x, double *y) __builtin_modf (x,y); } /* 321*8 */ -/* { dg-final { scan-ipa-dump "Parm 0 param offset:0 offset:0 size:-1 max_size:2568" "modref" } } */ -/* { dg-final { scan-ipa-dump "Parm 1 param offset:0 offset:0 size:-1 max_size:64" "modref" } } */ +/* { dg-final { scan-ipa-dump "Parm 0 param offset:0 offset:0 size:-1 max_size:2568" "modref" } } */ +/* { dg-final { scan-ipa-dump "Parm 1 param offset:0 offset:0 size:-1 max_size:64" "modref" { target lp64 } } } */ +/* { dg-final { scan-ipa-dump "Parm 1 param offset:0 offset:0 size:-1 max_size:32" "modref" { target ilp32 } } } */ diff --git a/gcc/testsuite/gcc.dg/lto/modref-3_0.c b/gcc/testsuite/gcc.dg/lto/modref-3_0.c new file mode 100644 index 0000000..bd8f96f --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/modref-3_0.c @@ -0,0 +1,17 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { {-O2 -flto-partition=max -fdump-ipa-modref -fno-ipa-sra -fno-ipa-cp -flto} } } */ +extern void copy (int *a, int *b); +extern void barrier (); +extern int *ptr; +int +main() +{ + int a = 1, b = 2; + copy (&a,&b); + barrier (); + *ptr = 1; + if (!__builtin_constant_p (b == 2)) + __builtin_abort (); + return 0; +} +/* { dg-final { scan-wpa-ipa-dump "parm 1 flags: nodirectescape" "modref" } } */ diff --git a/gcc/testsuite/gcc.dg/lto/modref-3_1.c b/gcc/testsuite/gcc.dg/lto/modref-3_1.c new file mode 100644 index 0000000..c36f3d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/modref-3_1.c @@ -0,0 +1,13 @@ +__attribute__ ((noinline)) +void +copy (int *a, int *b) +{ + *a=*b; +} +int p, *ptr = &p; +__attribute__ ((noinline)) +void +barrier () +{ + asm ("":"=r"(ptr):"0"(ptr)); +} diff --git a/gcc/testsuite/gcc.dg/lto/modref-4_0.c b/gcc/testsuite/gcc.dg/lto/modref-4_0.c new file mode 100644 index 0000000..db90b4f --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/modref-4_0.c @@ -0,0 +1,17 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { {-O2 -flto-partition=max -fdump-ipa-modref -fno-ipa-sra -flto} } } */ +extern void copy (int *a, int *b); +extern void barrier (); +extern int *ptr; +int +main() +{ + int a = 1, b = 2; + copy (&a,&b); + barrier (); + *ptr = 1; + if (!__builtin_constant_p (b == 2)) + __builtin_abort (); + return 0; +} +/* { dg-final { scan-wpa-ipa-dump "parm 1 flags: nodirectescape" "modref" } } */ diff --git a/gcc/testsuite/gcc.dg/lto/modref-4_1.c b/gcc/testsuite/gcc.dg/lto/modref-4_1.c new file mode 100644 index 0000000..c36f3d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/modref-4_1.c @@ -0,0 +1,13 @@ +__attribute__ ((noinline)) +void +copy (int *a, int *b) +{ + *a=*b; +} +int p, *ptr = &p; +__attribute__ ((noinline)) +void +barrier () +{ + asm ("":"=r"(ptr):"0"(ptr)); +} diff --git a/gcc/testsuite/gcc.dg/lvalue-11.c b/gcc/testsuite/gcc.dg/lvalue-11.c new file mode 100644 index 0000000..d8b5a60c --- /dev/null +++ b/gcc/testsuite/gcc.dg/lvalue-11.c @@ -0,0 +1,40 @@ +/* test that lvalue conversions drops qualifiers, Bug 97702 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + + +const int jc; +extern int j; +extern typeof(0,jc) j; +extern typeof(+jc) j; +extern typeof(-jc) j; +extern typeof(1?jc:0) j; +extern typeof((int)jc) j; +extern typeof((const int)jc) j; + +volatile int kv; +extern int k; +extern typeof(0,kv) k; +extern typeof(+kv) k; +extern typeof(-kv) k; +extern typeof(1?kv:0) k; +extern typeof((int)kv) k; +extern typeof((volatile int)kv) k; + +_Atomic int la; +extern int l; +extern typeof(0,la) l; +extern typeof(+la) l; +extern typeof(-la) l; +extern typeof(1?la:0) l; +extern typeof((int)la) l; +extern typeof((_Atomic int)la) l; + +int * restrict mr; +extern int *m; +extern typeof(0,mr) m; +extern typeof(1?mr:0) m; +extern typeof((int *)mr) m; +extern typeof((int * restrict)mr) m; + + diff --git a/gcc/testsuite/gcc.dg/memchr-3.c b/gcc/testsuite/gcc.dg/memchr-3.c new file mode 100644 index 0000000..c38d9cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/memchr-3.c @@ -0,0 +1,25 @@ +/* PR middle-end/97956 - ICE due to type mismatch in pointer_plus_expr + during memchr folding + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __INT8_TYPE__ int8_t; +typedef __INT32_TYPE__ int32_t; + +extern void* memchr (const void*, int, long); + +struct SX +{ + int32_t n; + int8_t a[]; +}; + +const struct SX sx = { 0x1221 }; +const char sx_rep[] = { }; + +void test_find (void) +{ + int n = 0, nb = (const char*)&sx.a - (const char*)&sx; + const char *p = (const char*)&sx, *q = sx_rep; + n += p + 1 == memchr (p, q[1], nb); +} diff --git a/gcc/testsuite/gcc.dg/nextafter-1.c b/gcc/testsuite/gcc.dg/nextafter-1.c index 1916ac2..646a741 100644 --- a/gcc/testsuite/gcc.dg/nextafter-1.c +++ b/gcc/testsuite/gcc.dg/nextafter-1.c @@ -6,12 +6,14 @@ /* { dg-final { scan-tree-dump-not "nextafter" "optimized" } } */ /* { dg-final { scan-tree-dump-not "nexttoward" "optimized" } } */ +#ifndef _NEXT_AFTER_2 float nextafterf (float, float); double nextafter (double, double); long double nextafterl (long double, long double); float nexttowardf (float, long double); double nexttoward (double, long double); long double nexttowardl (long double, long double); +#endif #define CHECK(x) if (!(x)) __builtin_abort () diff --git a/gcc/testsuite/gcc.dg/nextafter-2.c b/gcc/testsuite/gcc.dg/nextafter-2.c index e51ae94..b36bc8b 100644 --- a/gcc/testsuite/gcc.dg/nextafter-2.c +++ b/gcc/testsuite/gcc.dg/nextafter-2.c @@ -6,6 +6,18 @@ #include <stdlib.h> +/* In order to run on systems like the PowerPC that have 3 different long + double types, include math.h so it can choose what is the appropriate + nextafterl function to use. + + If we didn't use -fno-builtin for this test, the PowerPC compiler would have + changed the names of the built-in functions that use long double. The + nextafter-1.c function runs with this mapping. + + Since this test uses -fno-builtin, include math.h, so that math.h can make + the appropriate choice to use. */ +#include <math.h> + #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) # if !__GLIBC_PREREQ (2, 24) /* Workaround buggy nextafterl in glibc 2.23 and earlier, @@ -13,4 +25,7 @@ # define NO_LONG_DOUBLE 1 # endif #endif + +#define _NEXT_AFTER_2 + #include "nextafter-1.c" diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c new file mode 100644 index 0000000..05133d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c @@ -0,0 +1,436 @@ +/* Proof-of-concept of a -fanalyzer plugin. + Detect (some) uses of CPython API outside of the Global Interpreter Lock. + https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock +*/ +/* { dg-options "-g" } */ + +#include "gcc-plugin.h" +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "diagnostic.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-iterator.h" +#include "gimple-walk.h" +#include "diagnostic-event-id.h" +#include "analyzer/analyzer.h" +#include "analyzer/analyzer-logging.h" +#include "json.h" +#include "analyzer/sm.h" +#include "analyzer/pending-diagnostic.h" + +int plugin_is_GPL_compatible; + +#if ENABLE_ANALYZER + +namespace ana { + +static bool +type_based_on_pyobject_p (tree type) +{ + /* Ideally we'd also check for "subclasses" here by iterating up the + first field of each struct. */ + if (TREE_CODE (type) != RECORD_TYPE) + return false; + tree name = TYPE_IDENTIFIER (type); + if (!name) + return false; + return id_equal (name, "PyObject"); +} + +/* An experimental state machine, for tracking whether the GIL is held, + as global state.. */ + +class gil_state_machine : public state_machine +{ +public: + gil_state_machine (logger *logger); + + bool inherited_state_p () const FINAL OVERRIDE { return false; } + + bool on_stmt (sm_context *sm_ctxt, + const supernode *node, + const gimple *stmt) const FINAL OVERRIDE; + + void on_condition (sm_context *sm_ctxt, + const supernode *node, + const gimple *stmt, + tree lhs, + enum tree_code op, + tree rhs) const FINAL OVERRIDE; + + bool can_purge_p (state_t s) const FINAL OVERRIDE; + + void check_for_pyobject_usage_without_gil (sm_context *sm_ctxt, + const supernode *node, + const gimple *stmt, + tree op) const; + + private: + void check_for_pyobject_in_call (sm_context *sm_ctxt, + const supernode *node, + const gcall *call, + tree callee_fndecl) const; + + public: + /* These states are "global", rather than per-expression. */ + + /* State for when we've released the GIL. */ + state_t m_released_gil; + + /* Stop state. */ + state_t m_stop; +}; + +/* Subclass for diagnostics involving the GIL. */ + +class gil_diagnostic : public pending_diagnostic +{ +public: + location_t fixup_location (location_t loc) const FINAL OVERRIDE + { + /* Ideally we'd check for specific macros here, and only + resolve certain macros. */ + if (linemap_location_from_macro_expansion_p (line_table, loc)) + loc = linemap_resolve_location (line_table, loc, + LRK_MACRO_EXPANSION_POINT, NULL); + return loc; + } + + label_text describe_state_change (const evdesc::state_change &change) + FINAL OVERRIDE + { + if (change.is_global_p () + && change.m_new_state == m_sm.m_released_gil) + return change.formatted_print ("releasing the GIL here"); + if (change.is_global_p () + && change.m_new_state == m_sm.get_start_state ()) + return change.formatted_print ("acquiring the GIL here"); + return label_text (); + } + + protected: + gil_diagnostic (const gil_state_machine &sm) : m_sm (sm) + { + } + + private: + const gil_state_machine &m_sm; +}; + +class double_save_thread : public gil_diagnostic +{ + public: + double_save_thread (const gil_state_machine &sm, const gcall *call) + : gil_diagnostic (sm), m_call (call) + {} + + const char *get_kind () const FINAL OVERRIDE + { + return "double_save_thread"; + } + + bool subclass_equal_p (const pending_diagnostic &base_other) const OVERRIDE + { + const double_save_thread &sub_other + = (const double_save_thread &)base_other; + return m_call == sub_other.m_call; + } + + bool emit (rich_location *rich_loc) FINAL OVERRIDE + { + return warning_at (rich_loc, 0, + "nested usage of %qs", "Py_BEGIN_ALLOW_THREADS"); + } + + label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE + { + return ev.formatted_print ("nested usage of %qs here", + "Py_BEGIN_ALLOW_THREADS"); + } + + private: + const gcall *m_call; +}; + +class fncall_without_gil : public gil_diagnostic +{ + public: + fncall_without_gil (const gil_state_machine &sm, const gcall *call, + tree callee_fndecl, unsigned arg_idx) + : gil_diagnostic (sm), m_call (call), m_callee_fndecl (callee_fndecl), + m_arg_idx (arg_idx) + {} + + const char *get_kind () const FINAL OVERRIDE + { + return "fncall_without_gil"; + } + + bool subclass_equal_p (const pending_diagnostic &base_other) const OVERRIDE + { + const fncall_without_gil &sub_other + = (const fncall_without_gil &)base_other; + return (m_call == sub_other.m_call + && m_callee_fndecl == sub_other.m_callee_fndecl + && m_arg_idx == sub_other.m_arg_idx); + } + + bool emit (rich_location *rich_loc) FINAL OVERRIDE + { + auto_diagnostic_group d; + /* There isn't a warning ID for use to use. */ + if (m_callee_fndecl) + return warning_at (rich_loc, 0, + "use of PyObject as argument %i of %qE" + " without the GIL", + m_arg_idx + 1, m_callee_fndecl); + else + return warning_at (rich_loc, 0, + "use of PyObject as argument %i of call" + " without the GIL", + m_arg_idx + 1, m_callee_fndecl); + } + + label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE + { + if (m_callee_fndecl) + return ev.formatted_print ("use of PyObject as argument %i of %qE here" + " without the GIL", + m_arg_idx + 1, m_callee_fndecl); + else + return ev.formatted_print ("use of PyObject as argument %i of call here" + " without the GIL", + m_arg_idx + 1, m_callee_fndecl); + } + + private: + const gcall *m_call; + tree m_callee_fndecl; + unsigned m_arg_idx; +}; + +class pyobject_usage_without_gil : public gil_diagnostic +{ + public: + pyobject_usage_without_gil (const gil_state_machine &sm, tree expr) + : gil_diagnostic (sm), m_expr (expr) + {} + + const char *get_kind () const FINAL OVERRIDE + { + return "pyobject_usage_without_gil"; + } + + bool subclass_equal_p (const pending_diagnostic &base_other) const OVERRIDE + { + return same_tree_p (m_expr, + ((const pyobject_usage_without_gil&)base_other).m_expr); + } + + bool emit (rich_location *rich_loc) FINAL OVERRIDE + { + auto_diagnostic_group d; + /* There isn't a warning ID for use to use. */ + return warning_at (rich_loc, 0, + "use of PyObject %qE without the GIL", m_expr); + } + + label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE + { + return ev.formatted_print ("PyObject %qE used here without the GIL", + m_expr); + } + + private: + tree m_expr; +}; + +/* gil_state_machine's ctor. */ + +gil_state_machine::gil_state_machine (logger *logger) +: state_machine ("gil", logger) +{ + m_released_gil = add_state ("released_gil"); + m_stop = add_state ("stop"); +} + +struct cb_data +{ + cb_data (const gil_state_machine &sm, sm_context *sm_ctxt, + const supernode *snode, const gimple *stmt) + : m_sm (sm), m_sm_ctxt (sm_ctxt), m_snode (snode), m_stmt (stmt) + { + } + + const gil_state_machine &m_sm; + sm_context *m_sm_ctxt; + const supernode *m_snode; + const gimple *m_stmt; +}; + +static bool +check_for_pyobject (gimple *, tree op, tree, void *data) +{ + cb_data *d = (cb_data *)data; + d->m_sm.check_for_pyobject_usage_without_gil (d->m_sm_ctxt, d->m_snode, + d->m_stmt, op); + return true; +} + +/* Assuming that the GIL has been released, complain about any + PyObject * arguments passed to CALL. */ + +void +gil_state_machine::check_for_pyobject_in_call (sm_context *sm_ctxt, + const supernode *node, + const gcall *call, + tree callee_fndecl) const +{ + for (unsigned i = 0; i < gimple_call_num_args (call); i++) + { + tree arg = gimple_call_arg (call, i); + if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE) + continue; + tree type = TREE_TYPE (TREE_TYPE (arg)); + if (type_based_on_pyobject_p (type)) + { + sm_ctxt->warn (node, call, NULL_TREE, + new fncall_without_gil (*this, call, + callee_fndecl, + i)); + sm_ctxt->set_global_state (m_stop); + } + } +} + +/* Implementation of state_machine::on_stmt vfunc for gil_state_machine. */ + +bool +gil_state_machine::on_stmt (sm_context *sm_ctxt, + const supernode *node, + const gimple *stmt) const +{ + const state_t global_state = sm_ctxt->get_global_state (); + if (const gcall *call = dyn_cast <const gcall *> (stmt)) + { + if (tree callee_fndecl = sm_ctxt->get_fndecl_for_call (call)) + { + if (is_named_call_p (callee_fndecl, "PyEval_SaveThread", call, 0)) + { + if (0) + inform (input_location, "found call to %qs", + "PyEval_SaveThread"); + if (global_state == m_released_gil) + { + sm_ctxt->warn (node, stmt, NULL_TREE, + new double_save_thread (*this, call)); + sm_ctxt->set_global_state (m_stop); + } + else + sm_ctxt->set_global_state (m_released_gil); + return true; + } + else if (is_named_call_p (callee_fndecl, "PyEval_RestoreThread", + call, 1)) + { + if (0) + inform (input_location, "found call to %qs", + "PyEval_SaveThread"); + if (global_state == m_released_gil) + sm_ctxt->set_global_state (m_start); + return true; + } + else if (global_state == m_released_gil) + { + /* Find PyObject * args of calls to fns with unknown bodies. */ + if (!fndecl_has_gimple_body_p (callee_fndecl)) + check_for_pyobject_in_call (sm_ctxt, node, call, callee_fndecl); + } + } + else if (global_state == m_released_gil) + check_for_pyobject_in_call (sm_ctxt, node, call, NULL); + } + else + if (global_state == m_released_gil) + { + /* Walk the stmt, finding uses of PyObject (or "subclasses"). */ + cb_data d (*this, sm_ctxt, node, stmt); + walk_stmt_load_store_addr_ops (const_cast <gimple *> (stmt), &d, + check_for_pyobject, + check_for_pyobject, + check_for_pyobject); + } + return false; +} + +/* Implementation of state_machine::on_condition vfunc for + gil_state_machine. */ + +void +gil_state_machine::on_condition (sm_context *sm_ctxt ATTRIBUTE_UNUSED, + const supernode *node ATTRIBUTE_UNUSED, + const gimple *stmt ATTRIBUTE_UNUSED, + tree lhs ATTRIBUTE_UNUSED, + enum tree_code op ATTRIBUTE_UNUSED, + tree rhs ATTRIBUTE_UNUSED) const +{ + // Empty +} + +bool +gil_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const +{ + return true; +} + +void +gil_state_machine::check_for_pyobject_usage_without_gil (sm_context *sm_ctxt, + const supernode *node, + const gimple *stmt, + tree op) const +{ + tree type = TREE_TYPE (op); + if (type_based_on_pyobject_p (type)) + { + sm_ctxt->warn (node, stmt, NULL_TREE, + new pyobject_usage_without_gil (*this, op)); + sm_ctxt->set_global_state (m_stop); + } +} + +/* Callback handler for the PLUGIN_ANALYZER_INIT event. */ + +static void +gil_analyzer_init_cb (void *gcc_data, void */*user_data*/) +{ + ana::plugin_analyzer_init_iface *iface + = (ana::plugin_analyzer_init_iface *)gcc_data; + LOG_SCOPE (iface->get_logger ()); + if (0) + inform (input_location, "got here: gil_analyzer_init_cb"); + iface->register_state_machine (new gil_state_machine (iface->get_logger ())); +} + +} // namespace ana + +#endif /* #if ENABLE_ANALYZER */ + +int +plugin_init (struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ +#if ENABLE_ANALYZER + const char *plugin_name = plugin_info->base_name; + if (0) + inform (input_location, "got here; %qs", plugin_name); + register_callback (plugin_info->base_name, + PLUGIN_ANALYZER_INIT, + ana::gil_analyzer_init_cb, + NULL); /* void *user_data */ +#else + sorry_no_analyzer (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/plugin/gil-1.c b/gcc/testsuite/gcc.dg/plugin/gil-1.c new file mode 100644 index 0000000..4e8f535 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/gil-1.c @@ -0,0 +1,90 @@ +/* { dg-do compile } */ +/* { dg-options "-fanalyzer" } */ + +#include "gil.h" + +void test_1 (void) +{ + Py_BEGIN_ALLOW_THREADS + Py_END_ALLOW_THREADS +} + +void test_2 (PyObject *obj) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */ + + Py_INCREF (obj); /* { dg-warning "use of PyObject '\\*\\(obj\\)' without the GIL" } */ + Py_DECREF (obj); + + Py_END_ALLOW_THREADS +} + +void test_3 (PyObject *obj) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */ + + Py_BEGIN_ALLOW_THREADS /* { dg-warning "nested usage of 'Py_BEGIN_ALLOW_THREADS'" } */ + Py_END_ALLOW_THREADS + + Py_END_ALLOW_THREADS +} + +void test_4 (PyObject *obj) +{ + /* These aren't nested, so should be OK. */ + Py_BEGIN_ALLOW_THREADS + Py_END_ALLOW_THREADS + + Py_BEGIN_ALLOW_THREADS + Py_END_ALLOW_THREADS +} + +/* Interprocedural example of erroneously nested usage. */ + +static void __attribute__((noinline)) +called_by_test_5 (void) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-warning "nested usage of 'Py_BEGIN_ALLOW_THREADS'" } */ + Py_END_ALLOW_THREADS +} + +void test_5 (PyObject *obj) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */ + called_by_test_5 (); + Py_END_ALLOW_THREADS +} + +/* Interprocedural example of bogusly using a PyObject outside of GIL. */ + +static void __attribute__((noinline)) +called_by_test_6 (PyObject *obj) +{ + Py_INCREF (obj); /* { dg-warning "use of PyObject '\\*\\(obj\\)' without the GIL" } */ + Py_DECREF (obj); +} + +void test_6 (PyObject *obj) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */ + called_by_test_6 (obj); + Py_END_ALLOW_THREADS +} + +extern void called_by_test_7 (PyObject *obj); + +void test_7 (PyObject *obj) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */ + called_by_test_7 (obj); /* { dg-warning "use of PyObject as argument 1 of 'called_by_test_7' without the GIL" } */ + Py_END_ALLOW_THREADS +} + +typedef void (*callback_t) (PyObject *); + +void test_8 (PyObject *obj, callback_t cb) +{ + Py_BEGIN_ALLOW_THREADS /* { dg-message "releasing the GIL here" } */ + cb (obj); /* { dg-warning "use of PyObject as argument 1 of call without the GIL" } */ + Py_END_ALLOW_THREADS +} diff --git a/gcc/testsuite/gcc.dg/plugin/gil.h b/gcc/testsuite/gcc.dg/plugin/gil.h new file mode 100644 index 0000000..b0610cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/gil.h @@ -0,0 +1,32 @@ +/* Adapted from CPython 3.8's ceval.h. */ +typedef struct PyThreadState PyThreadState; +extern PyThreadState * PyEval_SaveThread(void); +extern void PyEval_RestoreThread(PyThreadState *); + +#define Py_BEGIN_ALLOW_THREADS { \ + PyThreadState *_save; \ + _save = PyEval_SaveThread(); +#define Py_BLOCK_THREADS PyEval_RestoreThread(_save); +#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread(); +#define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \ + } + +/* Adapted/hacked up from CPython 3.8's object.h. */ + +typedef struct _object { + int ob_refcnt; +} PyObject; + +#define _PyObject_CAST(op) ((PyObject*)(op)) + +extern void _Py_Dealloc(PyObject *); + +#define _Py_INCREF(OP) do { (OP)->ob_refcnt++; } while (0); +#define _Py_DECREF(OP) do { \ + if (--(OP)->ob_refcnt == 0) { \ + _Py_Dealloc(OP); \ + } \ + } while (0) + +#define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op)) +#define Py_DECREF(op) _Py_DECREF(_PyObject_CAST(op)) diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index 5dd102a..7f0ffd6 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -118,6 +118,8 @@ set plugin_test_list [list \ { dump_plugin.c \ dump-1.c \ dump-2.c } \ + { analyzer_gil_plugin.c \ + gil-1.c } \ ] foreach plugin_test $plugin_test_list { diff --git a/gcc/testsuite/gcc.dg/pr25376.c b/gcc/testsuite/gcc.dg/pr25376.c index 3008b09..d66f2e1 100644 --- a/gcc/testsuite/gcc.dg/pr25376.c +++ b/gcc/testsuite/gcc.dg/pr25376.c @@ -7,3 +7,4 @@ void simple (void) } /* { dg-final { scan-assembler "my_named_section" } } */ +/* { dg-final { scan-assembler-symbol-section {simple$} {^\.?my_named_section|simple\[DS\]|^\"\.opd\"} } } */ diff --git a/gcc/testsuite/gcc.dg/pr46309-2.c b/gcc/testsuite/gcc.dg/pr46309-2.c index f56df42..2903fff 100644 --- a/gcc/testsuite/gcc.dg/pr46309-2.c +++ b/gcc/testsuite/gcc.dg/pr46309-2.c @@ -1,6 +1,6 @@ /* PR tree-optimization/46309 */ /* { dg-do compile } */ -/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-reassoc-details" } */ +/* { dg-options "-O2 -fno-ipa-icf -fno-jump-tables -fno-bit-tests -fdump-tree-reassoc-details" } */ int foo (void); diff --git a/gcc/testsuite/gcc.dg/pr60195.c b/gcc/testsuite/gcc.dg/pr60195.c index 0a50a30..8eccf7f 100644 --- a/gcc/testsuite/gcc.dg/pr60195.c +++ b/gcc/testsuite/gcc.dg/pr60195.c @@ -15,7 +15,7 @@ atomic_int fn2 (void) { atomic_int y = 0; - y; + y; /* { dg-warning "statement with no effect" } */ return y; } diff --git a/gcc/testsuite/gcc.dg/pr83072.c b/gcc/testsuite/gcc.dg/pr83072.c new file mode 100644 index 0000000..3bed8d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr83072.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre" } */ + +void kill (void); + +int f(int c){ + c |= 1; + if (c == 0) + kill (); + + return c; +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/pr85811.c b/gcc/testsuite/gcc.dg/pr85811.c new file mode 100644 index 0000000..868f66c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr85811.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +#include <stdio.h> + +int main() { + const double negval = -1.0; + const double nanval = 0.0 / 0.0; + const double val = __builtin_fmax(negval, nanval); + const double absval = __builtin_fabs(val); + printf("fabs(%.16e) = %.16e\n", val, absval); + return absval >= 0 ? 0 : 1; +} + +/* We hope not to see: printf ("fabs(%.16e) = %.16e\n", val_4, val_4); */ +/* { dg-final { scan-tree-dump-not "val_\[0-9\]*, val_\[0-9\]*" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr91029.c b/gcc/testsuite/gcc.dg/pr91029.c new file mode 100644 index 0000000..4904764 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr91029.c @@ -0,0 +1,48 @@ +/* PR tree-optimization/91029 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); +int xx; + +void f1 (int i) +{ + if ((i % 7) == 3) + { + xx = (i < 0); + if (xx) + kill (); + } +} + +void f2 (int i) +{ + if ((i % 7) > 0) + { + xx = (i < 0); + if (xx) + kill (); + } +} + +void f3 (int i) +{ + if ((i % 7) == -3) + { + xx = (i > 0); + if (xx) + kill (); + } +} + +void f4 (int i) +{ + if ((i % 7) < 0) + { + xx = (i > 0); + if (xx) + kill (); + } +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/pr95853.c b/gcc/testsuite/gcc.dg/pr95853.c new file mode 100644 index 0000000..fdd3c30 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr95853.c @@ -0,0 +1,59 @@ +/* PR tree-optimization/95853 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-widening_mul" } */ + +#if __SIZEOF_INT128__ +typedef __uint128_t W; +typedef unsigned long long T; +#else +typedef unsigned long long W; +typedef unsigned int T; +#endif + +struct S { int p; T r; }; + +struct S +foo (T x, T y) +{ + W z = (W) x + y; + return (struct S) { z > ~(T) 0, (T) z }; +} + +struct S +bar (T x) +{ + W z = (W) x + 132; + return (struct S) { z > ~(T) 0, (T) z }; +} + +struct S +baz (T x, unsigned short y) +{ + W z = (W) x + y; + return (struct S) { z > ~(T) 0, (T) z }; +} + +struct S +qux (unsigned short x, T y) +{ + W z = (W) x + y; + return (struct S) { z > ~(T) 0, (T) z }; +} + +struct S +corge (T x, T y) +{ + T w = x + y; + W z = (W) x + y; + return (struct S) { z > ~(T) 0, w }; +} + +struct S +garple (T x, T y) +{ + W z = (W) x + y; + T w = x + y; + return (struct S) { z > ~(T) 0, w }; +} + +/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 6 "widening_mul" { target { i?86-*-* x86_64-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/pr96708-negative.c b/gcc/testsuite/gcc.dg/pr96708-negative.c new file mode 100644 index 0000000..91964d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96708-negative.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdbool.h> + +bool __attribute__ ((noinline)) +test1 (int a, int b) +{ + int tmp = (a < b) ? b : a; + return tmp <= a; +} + +bool __attribute__ ((noinline)) +test2 (int a, int b) +{ + int tmp = (a < b) ? b : a; + return tmp > a; +} + +bool __attribute__ ((noinline)) +test3 (int a, int b) +{ + int tmp = (a > b) ? b : a; + return tmp >= a; +} + +bool __attribute__ ((noinline)) +test4 (int a, int b) +{ + int tmp = (a > b) ? b : a; + return tmp < a; +} + +int main() +{ + if (test1 (1, 2) || !test1 (2, 1) || + !test2 (1, 2) || test2 (2, 1) || + !test3 (1, 2) || test3 (2, 1) || + test4 (1, 2) || !test4 (2, 1)) { + __builtin_abort(); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-not { "return 1;" } "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr96708-positive.c b/gcc/testsuite/gcc.dg/pr96708-positive.c new file mode 100644 index 0000000..65af853 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr96708-positive.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdbool.h> + +bool __attribute__ ((noinline)) +test1(int a, int b) +{ + int tmp = (a < b) ? b : a; + return tmp >= a; +} + +bool __attribute__ ((noinline)) +test2(int a, int b) +{ + int tmp = (a < b) ? b : a; + return tmp < a; +} + +bool __attribute__ ((noinline)) +test3(int a, int b) +{ + int tmp = (a > b) ? b : a; + return tmp <= a; +} + +bool __attribute__ ((noinline)) +test4(int a, int b) +{ + int tmp = (a > b) ? b : a; + return tmp > a; +} + +int main() +{ + if (!test1 (1, 2) || !test1 (2, 1) || + test2 (1, 2) || test2 (2, 1) || + !test3 (1, 2) || !test3 (2, 1) || + test4 (1, 2) || test4 (2, 1)) { + __builtin_abort(); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "return 0;" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-not { "MAX_EXPR" } "optimized" } } */ +/* { dg-final { scan-tree-dump-not { "MIN_EXPR" } "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr97459-1.c b/gcc/testsuite/gcc.dg/pr97459-1.c new file mode 100644 index 0000000..96c7ab6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97459-1.c @@ -0,0 +1,54 @@ +/* PR rtl-optimization/97459 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */ + +#ifdef __SIZEOF_INT128__ +typedef __uint128_t T; +#else +typedef unsigned long long T; +#endif + +T __attribute__((noipa)) foo (T x, T n) { return x % n; } +#define C(n) T __attribute__((noipa)) foo##n (T x) { return x % (n - 10000); } + +#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9) +#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \ + C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9) +#ifdef EXPENSIVE +#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \ + C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9) +#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \ + C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9) +#else +#define C3(n) C2(n##0) C2(n##4) C2(n##9) +#define C4(n) C3(n##0) C3(n##3) C3(n##7) +#endif +#define TESTS C4(1) C1(10010) C1(10012) C1(16144) + +TESTS + +struct S { T x; T (*foo) (T); }; + +#undef C +#define C(n) { n - 10000, foo##n }, + +struct S tests[] = { +TESTS + { 0, 0 } +}; + +int +main () +{ + int i, j, k; + for (k = 0; tests[k].x; k++) + for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++) + for (j = -5; j <= 5; j++) + { + T x = ((T) 1 << i) + j; + if (foo (x, tests[k].x) != tests[k].foo (x)) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97459-2.c b/gcc/testsuite/gcc.dg/pr97459-2.c new file mode 100644 index 0000000..0e2bfbd --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97459-2.c @@ -0,0 +1,57 @@ +/* PR rtl-optimization/97459 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */ + +#ifdef __SIZEOF_INT128__ +typedef __int128_t T; +typedef __uint128_t U; +#else +typedef long long T; +typedef unsigned long long U; +#endif + +T __attribute__((noipa)) foo (T x, T n) { return x % n; } +#define C(n) T __attribute__((noipa)) foo##n (T x) { return x % (n - 10000); } + +#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9) +#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \ + C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9) +#ifdef EXPENSIVE +#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \ + C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9) +#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \ + C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9) +#else +#define C3(n) C2(n##0) C2(n##4) C2(n##9) +#define C4(n) C3(n##0) C3(n##3) C3(n##7) +#endif +#define TESTS C4(1) C1(10010) C1(10012) C1(16144) + +TESTS + +struct S { T x; T (*foo) (T); }; + +#undef C +#define C(n) { n - 10000, foo##n }, + +struct S tests[] = { +TESTS + { 0, 0 } +}; + +int +main () +{ + int i, j, k; + for (k = 0; tests[k].x; k++) + for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++) + for (j = -5; j <= 5; j++) + { + U x = ((U) 1 << i) + j; + if (foo ((T) x, tests[k].x) != tests[k].foo ((T) x) + || foo ((T) -x, tests[k].x) != tests[k].foo ((T) -x)) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97459-3.c b/gcc/testsuite/gcc.dg/pr97459-3.c new file mode 100644 index 0000000..7fbb7ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97459-3.c @@ -0,0 +1,54 @@ +/* PR rtl-optimization/97459 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */ + +#ifdef __SIZEOF_INT128__ +typedef __uint128_t T; +#else +typedef unsigned long long T; +#endif + +T __attribute__((noipa)) foo (T x, T n) { return x / n; } +#define C(n) T __attribute__((noipa)) foo##n (T x) { return x / (n - 10000); } + +#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9) +#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \ + C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9) +#ifdef EXPENSIVE +#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \ + C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9) +#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \ + C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9) +#else +#define C3(n) C2(n##0) C2(n##4) C2(n##9) +#define C4(n) C3(n##0) C3(n##3) C3(n##7) +#endif +#define TESTS C4(1) C1(10010) C1(10012) C1(16144) + +TESTS + +struct S { T x; T (*foo) (T); }; + +#undef C +#define C(n) { n - 10000, foo##n }, + +struct S tests[] = { +TESTS + { 0, 0 } +}; + +int +main () +{ + int i, j, k; + for (k = 0; tests[k].x; k++) + for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++) + for (j = -5; j <= 5; j++) + { + T x = ((T) 1 << i) + j; + if (foo (x, tests[k].x) != tests[k].foo (x)) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97459-4.c b/gcc/testsuite/gcc.dg/pr97459-4.c new file mode 100644 index 0000000..33e49a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97459-4.c @@ -0,0 +1,57 @@ +/* PR rtl-optimization/97459 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */ + +#ifdef __SIZEOF_INT128__ +typedef __int128_t T; +typedef __uint128_t U; +#else +typedef long long T; +typedef unsigned long long U; +#endif + +T __attribute__((noipa)) foo (T x, T n) { return x / n; } +#define C(n) T __attribute__((noipa)) foo##n (T x) { return x / (n - 10000); } + +#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9) +#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \ + C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9) +#ifdef EXPENSIVE +#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \ + C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9) +#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \ + C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9) +#else +#define C3(n) C2(n##0) C2(n##4) C2(n##9) +#define C4(n) C3(n##0) C3(n##3) C3(n##7) +#endif +#define TESTS C4(1) C1(10010) C1(10012) C1(16144) + +TESTS + +struct S { T x; T (*foo) (T); }; + +#undef C +#define C(n) { n - 10000, foo##n }, + +struct S tests[] = { +TESTS + { 0, 0 } +}; + +int +main () +{ + int i, j, k; + for (k = 0; tests[k].x; k++) + for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++) + for (j = -5; j <= 5; j++) + { + U x = ((U) 1 << i) + j; + if (foo ((T) x, tests[k].x) != tests[k].foo ((T) x) + || foo ((T) -x, tests[k].x) != tests[k].foo ((T) -x)) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97459-5.c b/gcc/testsuite/gcc.dg/pr97459-5.c new file mode 100644 index 0000000..f658a5a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97459-5.c @@ -0,0 +1,56 @@ +/* PR rtl-optimization/97459 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */ + +#ifdef __SIZEOF_INT128__ +typedef __uint128_t T; +#else +typedef unsigned long long T; +#endif + +T __attribute__((noipa)) foo (T x, T n, T *r) { *r = x % n; return x / n; } +#define C(n) T __attribute__((noipa)) foo##n (T x, T *r) { *r = x % (n - 10000); return x / (n - 10000); } + +#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9) +#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \ + C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9) +#ifdef EXPENSIVE +#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \ + C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9) +#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \ + C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9) +#else +#define C3(n) C2(n##0) C2(n##4) C2(n##9) +#define C4(n) C3(n##0) C3(n##3) C3(n##7) +#endif +#define TESTS C4(1) C1(10010) C1(10012) C1(16144) + +TESTS + +struct S { T x; T (*foo) (T, T *); }; + +#undef C +#define C(n) { n - 10000, foo##n }, + +struct S tests[] = { +TESTS + { 0, 0 } +}; + +int +main () +{ + int i, j, k; + for (k = 0; tests[k].x; k++) + for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++) + for (j = -5; j <= 5; j++) + { + T x = ((T) 1 << i) + j; + T r1, r2; + if (foo (x, tests[k].x, &r1) != tests[k].foo (x, &r2) + || r1 != r2) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97459-6.c b/gcc/testsuite/gcc.dg/pr97459-6.c new file mode 100644 index 0000000..d4602be --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97459-6.c @@ -0,0 +1,62 @@ +/* PR rtl-optimization/97459 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } } */ + +#ifdef __SIZEOF_INT128__ +typedef __int128_t T; +typedef __uint128_t U; +#else +typedef long long T; +typedef unsigned long long U; +#endif + +T __attribute__((noipa)) foo (T x, T n, T *r) { *r = x % n; return x / n; } +#define C(n) T __attribute__((noipa)) foo##n (T x, T *r) { *r = x % (n - 10000); return x / (n - 10000); } + +#define C1(n) C(n##1) C(n##3) C(n##5) C(n##7) C(n##9) +#define C2(n) C1(n##0) C1(n##1) C1(n##2) C1(n##3) C1(n##4) \ + C1(n##5) C1(n##6) C1(n##7) C1(n##8) C1(n##9) +#ifdef EXPENSIVE +#define C3(n) C2(n##0) C2(n##1) C2(n##2) C2(n##3) C2(n##4) \ + C2(n##5) C2(n##6) C2(n##7) C2(n##8) C2(n##9) +#define C4(n) C3(n##0) C3(n##1) C3(n##2) C3(n##3) C3(n##4) \ + C3(n##5) C3(n##6) C3(n##7) C3(n##8) C3(n##9) +#else +#define C3(n) C2(n##0) C2(n##4) C2(n##9) +#define C4(n) C3(n##0) C3(n##3) C3(n##7) +#endif +#define TESTS C4(1) C1(10010) C1(10012) C1(16144) + +TESTS + +struct S { T x; T (*foo) (T, T *); }; + +#undef C +#define C(n) { n - 10000, foo##n }, + +struct S tests[] = { +TESTS + { 0, 0 } +}; + +int +main () +{ + int i, j, k; + for (k = 0; tests[k].x; k++) + for (i = 0; i < sizeof (T) * __CHAR_BIT__; i++) + for (j = -5; j <= 5; j++) + { + U x = ((U) 1 << i) + j; + T r1 = 0, r2 = 0; + if (foo ((T) x, tests[k].x, &r1) != tests[k].foo ((T) x, &r2) + || r1 != r2) + __builtin_abort (); + r1 = 0; r2 = 0; + if (foo ((T) -x, tests[k].x, &r1) != tests[k].foo ((T) -x, &r2) + || r1 != r2) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97515.c b/gcc/testsuite/gcc.dg/pr97515.c index 84f145a..b4f2481 100644 --- a/gcc/testsuite/gcc.dg/pr97515.c +++ b/gcc/testsuite/gcc.dg/pr97515.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-ccp2" } */ int e7 (int gg) @@ -20,6 +20,8 @@ e7 (int gg) return xe; } -/* EVRP should be able to reduce this to a single goto. */ +/* EVRP should be able to reduce this to a single goto when we can + * revisit statements to try folding again based on changed inputs. + * Until then, make sure its gone by ccp2. */ -/* { dg-final { scan-tree-dump-times "goto" 1 "evrp" } } */ +/* { dg-final { scan-tree-dump-times "goto" 1 "ccp2" } } */ diff --git a/gcc/testsuite/gcc.dg/pr97534.c b/gcc/testsuite/gcc.dg/pr97534.c new file mode 100644 index 0000000..b363a32 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97534.c @@ -0,0 +1,9 @@ +/* PR target/97534 - ICE in decompose on arm*-*-*. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -O2 -g" } */ + +int f (int a) +{ + int b; + __atomic_fetch_sub(&b, (int)(-__INT_MAX__ - 1), (int)0); +} diff --git a/gcc/testsuite/gcc.dg/pr97579.c b/gcc/testsuite/gcc.dg/pr97579.c new file mode 100644 index 0000000..5cd5427 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97579.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 --param=max-unswitch-insns=1024" } */ +/* { dg-additional-options "-mavx512vl" { target x86_64-*-* i?86-*-* } } */ + +int bad_odd_rows_0_0, rows_bad_row1, rows_bad_group_okay, calc_rows_row2; + +int +rows_bad() { + int i, in_zeroes; + char block; + i = 0; + for (; i < 5; i++) + if (rows_bad_row1 & i) + in_zeroes = 0; + else { + if (!in_zeroes) + in_zeroes = 1; + if (block & 1) + rows_bad_group_okay = 1; + } + if (in_zeroes) + return rows_bad_group_okay; +} + +void +calc_rows() { + for (; calc_rows_row2; calc_rows_row2++) { + rows_bad(); + bad_odd_rows_0_0 = rows_bad(); + } +} diff --git a/gcc/testsuite/gcc.dg/pr97806.c b/gcc/testsuite/gcc.dg/pr97806.c new file mode 100644 index 0000000..9ec3299 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97806.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int b; +long c; +int g(); +void h(long *); +void i(long *); +void d() { + int e, f = b - e; + if (g()) + h(&c + f); + else + i(&c + f); + __builtin_memset(0, 0, f * 8); +} diff --git a/gcc/testsuite/gcc.dg/pr97830.c b/gcc/testsuite/gcc.dg/pr97830.c new file mode 100644 index 0000000..3729a65 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97830.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef enum { LangC } cLanguage; +typedef enum { FunctionOneArg, FunctionStandard } cFunctionType; +void *CCTK_CallFunction_function; +cLanguage CCTK_CallFunction_fdata_0; +cFunctionType CCTK_CallFunction_fdata_1; +void CCTK_CallFunction_data() { + void (*standardfunc)(); + int (*oneargfunc)(); + switch (CCTK_CallFunction_fdata_1) { + case FunctionOneArg: + oneargfunc = CCTK_CallFunction_function; + oneargfunc(CCTK_CallFunction_data); + break; + case FunctionStandard: + switch (CCTK_CallFunction_fdata_0) { + case LangC: + standardfunc = CCTK_CallFunction_function; + standardfunc(CCTK_CallFunction_data); + } + } +} diff --git a/gcc/testsuite/gcc.dg/pr97860.c b/gcc/testsuite/gcc.dg/pr97860.c new file mode 100644 index 0000000..04c0f19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97860.c @@ -0,0 +1,11 @@ +/* PR c/97860 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (int n) +{ + typedef int T[0]; + typedef T V[n]; + void bar (V); +} diff --git a/gcc/testsuite/gcc.dg/pr97897.c b/gcc/testsuite/gcc.dg/pr97897.c new file mode 100644 index 0000000..084c1cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97897.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void h (); +void f () __attribute__ ((returns_twice)); +void g (_Complex int a) +{ + f (); + if (a != 0) + { + a = 0; + h (); + } +} diff --git a/gcc/testsuite/gcc.dg/pr97953.c b/gcc/testsuite/gcc.dg/pr97953.c new file mode 100644 index 0000000..6219619 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97953.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-tree-fre" } */ + +int __attribute__((noipa)) +foo (int flag, int *p) +{ + int val = *p; + if (flag) + { + if (val != 1) + __builtin_unreachable (); + return 0; + } + int val2 = *p; + return val2 == 2; +} + +int main() +{ + int i = 2; + if (foo (0, &i) != 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr97954.c b/gcc/testsuite/gcc.dg/pr97954.c new file mode 100644 index 0000000..178e1d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97954.c @@ -0,0 +1,12 @@ +/* PR rtl-optimization/97954 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int +foo (void) +{ + int x; + lab: + asm goto ("": "=r" (x) : : : lab); + return x; +} diff --git a/gcc/testsuite/gcc.dg/pr97955.c b/gcc/testsuite/gcc.dg/pr97955.c new file mode 100644 index 0000000..a5236c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97955.c @@ -0,0 +1,7 @@ +/* PR 97955 - ICE in build_array_type_1 on invalid redeclaration of function + with VLA parameter + { dg-do compile } + { dg-options "-Wall" } */ + +void f (int n, int a[n]); +void f (int *b) { } // { dg-error "conflicting types" } diff --git a/gcc/testsuite/gcc.dg/pr97979.c b/gcc/testsuite/gcc.dg/pr97979.c new file mode 100644 index 0000000..44aaff2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97979.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/97979 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-ccp" } */ + +short a = 0; +int b = 0; + +void +foo (void) +{ + unsigned short d = b; + a = d >> -2U; /* { dg-warning "right shift count >= width of type" } */ +} diff --git a/gcc/testsuite/gcc.dg/pr98099.c b/gcc/testsuite/gcc.dg/pr98099.c new file mode 100644 index 0000000..34909f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr98099.c @@ -0,0 +1,12 @@ +/* PR middle-end/98099 */ +/* Reported by G. Steinmetz <gscfq@t-online.de> */ + +/* { dg-do compile } */ +/* { dg-options "-fsso-struct=big-endian" } */ + +struct S { _Decimal128 a; }; + +_Decimal128 f (struct S x) +{ + return x.a; /* { dg-message "sorry, unimplemented: reverse storage order" "" { target { ! int128 } } } */ +} diff --git a/gcc/testsuite/gcc.dg/profile-info-section.c b/gcc/testsuite/gcc.dg/profile-info-section.c new file mode 100644 index 0000000..8f31f3b --- /dev/null +++ b/gcc/testsuite/gcc.dg/profile-info-section.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-skip-if "profile-info-section" { powerpc-ibm-aix* } } */ +/* { dg-options "-fprofile-arcs -fprofile-info-section -fdump-tree-optimized" } */ + +int foo() +{ + return 0; +} + +int bar() +{ + return 1; +} + +int main () +{ + return foo (); +} + +/* { dg-final { scan-tree-dump-not "__gcov_init" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__gcov_exit" "optimized" } } */ +/* { dg-final { scan-assembler "\.gcov_info" } } */ diff --git a/gcc/testsuite/gcc.dg/strncmp-2.c b/gcc/testsuite/gcc.dg/strncmp-2.c index 6818b30..0d84f93 100644 --- a/gcc/testsuite/gcc.dg/strncmp-2.c +++ b/gcc/testsuite/gcc.dg/strncmp-2.c @@ -40,6 +40,7 @@ static void test_driver_strncmp (void (test_strncmp)(const char *, const char *, e = lib_memcmp(buf1,p2,sz); (*test_memcmp)(buf1,p2,e); } + mprotect (buf2+pgsz,pgsz,PROT_READ|PROT_WRITE); free(buf2); } diff --git a/gcc/testsuite/gcc.dg/system-binary-constants-1.c b/gcc/testsuite/gcc.dg/system-binary-constants-1.c index 921ee20..ca16215 100644 --- a/gcc/testsuite/gcc.dg/system-binary-constants-1.c +++ b/gcc/testsuite/gcc.dg/system-binary-constants-1.c @@ -14,5 +14,5 @@ foo (void) warning. */ return 23; #endif - return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */ + return 0b1101; /* { dg-warning "binary constants are a C2X feature or GCC extension" } */ } diff --git a/gcc/testsuite/gcc.dg/torture/float128-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float128-nan-floath.c new file mode 100644 index 0000000..69fd45a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float128 NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float128 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float128_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 128 +#define EXT 0 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c new file mode 100644 index 0000000..5be4c07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128x-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float128x NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float128x } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float128x_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 128 +#define EXT 1 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/float16-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float16-nan-floath.c new file mode 100644 index 0000000..cf03b45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float16-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float16 NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float16 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float16_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 16 +#define EXT 0 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float32-nan-floath.c new file mode 100644 index 0000000..2976a40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float32 NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float32 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float32_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 32 +#define EXT 0 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c new file mode 100644 index 0000000..0aab4be --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32x-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float32x NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float32x } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float32x_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 32 +#define EXT 1 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float64-nan-floath.c new file mode 100644 index 0000000..1f5298b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float64 NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float64 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float64_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 64 +#define EXT 0 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c b/gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c new file mode 100644 index 0000000..fbc8676 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64x-nan-floath.c @@ -0,0 +1,11 @@ +/* Test _Float64x NaNs in <float.h>. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -fsignaling-nans" } */ +/* { dg-add-options float64x } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float64x_runtime } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#define WIDTH 64 +#define EXT 1 +#include "floatn-nan-floath.h" diff --git a/gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h b/gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h new file mode 100644 index 0000000..9892fd0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/floatn-nan-floath.h @@ -0,0 +1,36 @@ +/* Tests for _FloatN / _FloatNx types: compile and execution tests for + NaNs, SNAN macros in <float.h>. Before including this file, define + WIDTH as the value N; define EXT to 1 for _FloatNx and 0 for + _FloatN. */ + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define SNAN CONCAT3 (FLT, WIDTH, X_SNAN) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define SNAN CONCAT3 (FLT, WIDTH, _SNAN) +#endif + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <fenv.h> +#include <float.h> + +extern void exit (int); +extern void abort (void); + +volatile TYPE nans_cst = SNAN; + +int +main (void) +{ + volatile TYPE r; + r = nans_cst + nans_cst; + if (!fetestexcept (FE_INVALID)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr97812.c b/gcc/testsuite/gcc.dg/torture/pr97812.c new file mode 100644 index 0000000..4d468ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr97812.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fdisable-tree-evrp" } */ + +unsigned char c; + +int main() { +volatile short b = 4066; + unsigned short bp = b; + unsigned d = bp & 2305; + signed char e = d; + c = e ? : e; + if (!d) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr97901.c b/gcc/testsuite/gcc.dg/torture/pr97901.c new file mode 100644 index 0000000..a6a89ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr97901.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +int a[1], b, *c, *d; + +int main() { +L: + d = c; + for (b = 0; b < 2; b++) + d = &a[0]; + if (c) + goto L; + if (*d) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c index 99a5488..85b6806 100644 --- a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c +++ b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c @@ -6,11 +6,14 @@ struct Foo { int *p; }; +struct Foo *ff; + void __attribute__((noinline)) foo (void *p) { struct Foo *f = (struct Foo *)p - 1; *f->p = 0; + ff = f; } int bar (void) diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c index 180fd72..1915b9a 100644 --- a/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c +++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c @@ -11,14 +11,14 @@ foo () int * p; int i; int x[4]; - long unsigned int _1; - long unsigned int _2; + __SIZETYPE__ _1; + __SIZETYPE__ _2; int _7; __BB(2): i_3 = 0; - _1 = (long unsigned int) i_3; - _2 = _1 * 4ul; + _1 = (__SIZETYPE__) i_3; + _2 = _1 * _Literal (__SIZETYPE__) 4; p_4 = _Literal (int *) &x + _2; __MEM <v4si> ((v4si *)p_4) = _Literal (v4si) { 1, 2, 3, 4 }; _7 = x[0]; diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c index 2c4235f..041d921 100644 --- a/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c +++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c @@ -11,14 +11,14 @@ foo () int * p; int i; int x[4]; - long unsigned int _1; - long unsigned int _2; + __SIZETYPE__ _1; + __SIZETYPE__ _2; int _7; __BB(2): i_3 = 0; - _1 = (long unsigned int) i_3; - _2 = _1 * 4ul; + _1 = (__SIZETYPE__) i_3; + _2 = _1 * _Literal (__SIZETYPE__) 4; p_4 = _Literal (int *) &x + _2; __MEM <v4si> ((v4si *)p_4) = _Literal (v4si) {}; _7 = x[0]; diff --git a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c index b7471bf..e8b1644 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c +++ b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c @@ -20,6 +20,6 @@ main() return 0; } /* autofdo doesn't support value profiling for now: */ -/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile"} } */ +/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile" { target { ! aarch64*-*-* } } } } */ /* The versioned memset of size 4 should be optimized to an assignment. - { dg-final-use-not-autofdo { scan-tree-dump "MEM <\[a-z \]+> \\\[\\(void .\\)&a\\\] = 168430090" "optimized" } } */ + { dg-final-use-not-autofdo { scan-tree-dump "MEM <\[a-z \]+> \\\[\\(void .\\)&a\\\] = 168430090" "optimized" { target { ! aarch64*-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c index a94d123..0cc03ff 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c @@ -112,17 +112,21 @@ void test_sprintf_c_const (void) T ( 3, "%1$c%2$c", '1', '2'); /* Verify that a warning is issued for exceeding INT_MAX bytes and - not otherwise. */ + not otherwise. In ILP32 the maximum object size is INT_MAX - 1 + bytes so the calls are diagnosed due to the overflow. */ T (-1, "%*c", INT_MAX - 1, '1'); - T (-1, "%*c", INT_MAX, '1'); - T (-1, "X%*c", INT_MAX - 1, '1'); - T (-1, "X%*c", INT_MAX, '1'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */ + T (-1, "%*c", INT_MAX, '1'); /* { dg-warning "writing a terminating nul past the end " "ilp32" { target ilp32 } } */ + T (-1, "X%*c", INT_MAX - 1, '1'); /* { dg-warning "writing a terminating nul past the end " "ilp32" { target ilp32 } } */ + T (-1, "X%*c", INT_MAX, '1'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */ + /* { dg-warning "directive writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 } */ - T (-1, "%*c%*c", INT_MAX - 1, '1', INT_MAX - 1, '2'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */ + T (-1, "%*c%*c", INT_MAX - 1, '1', INT_MAX - 1, '2'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */ + /* { dg-warning "directive writing 2147483646 bytes into a region of size 1" "ilp32" { target ilp32 } .-1 } */ T (-1, "%*cX", INT_MAX - 2, '1'); - T (-1, "%*cX", INT_MAX - 1, '1'); - T (-1, "%*cX", INT_MAX, '1'); /* { dg-warning "output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */ + T (-1, "%*cX", INT_MAX - 1, '1'); /* { dg-warning "writing a terminating nul past the end of the destination" "ilp32" { target ilp32 } } */ + T (-1, "%*cX", INT_MAX, '1'); /* { dg-warning "output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */ + /* { dg-warning "directive writing 1 byte into a region of size 0" "ilp32" { target ilp32 } .-1 } */ } /* Verify that no warning is issued for calls that write into a flexible @@ -288,8 +292,9 @@ void test_sprintf_chk_s_const (void) /* Verify that output in excess of INT_MAX bytes is diagnosed even when the size of the destination object is unknown. */ T (-1, "%*s", INT_MAX - 1, ""); - T (-1, "%*s", INT_MAX, ""); - T (-1, "X%*s", INT_MAX, ""); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */ + T (-1, "%*s", INT_MAX, ""); /* { dg-warning "writing a terminating nul past the end" "ilp32" { target ilp32 } } */ + T (-1, "X%*s", INT_MAX, ""); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." "lp64" { target lp64 } } */ + /* { dg-warning "directive writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 } */ /* Multiple directives. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c index 02072b5..134967d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c @@ -197,17 +197,21 @@ void test_narrow_string_with_width_and_precision (void) IR (imax / 9, imax / 8), IR (imax / 7, imax / 6), SR (x, y), IR (imax / 5, imax / 4), IR (imax / 3, imax / 2), SR (x, y)); - /* The two directives below combined convert to [INT_MAX, INT_MAX + 1]. + /* The two directives below combined convert to [INT_MAX -1, INT_MAX + 1]. Since the lower end of the range doesn't exceed INT_MAX no warning is expected. */ T (-1, "%*.*s%*.*s", - IR (imax - 5, imax - 3), IR (1, 2), SR (x, y), + IR (imax - 6, imax - 3), IR (1, 2), SR (x, y), IR ( 5, 6), IR (3, 4), SR (x, y)); /* The three directives below (the two %s plus the space in between) combined convert to [INT_MAX + 1, INT_MAX + 2]. Since the lower - end of the range exceeds INT_MAX a warning is expected. */ - T (-1, "%*.*s %*.*s", /* { dg-warning "INT_MAX" } */ + end of the range exceeds INT_MAX a warning is expected. In ILP32, + the output overflows the maximum object size. */ + T (-1, "%*.*s %*.*s", + /* { dg-warning "INT_MAX" "LP64" { target lp64 } .-1 } + { dg-warning "directive writing between 5 and 6 bytes into a region of size between 2 and 4" "ILP32" { target ilp32 } .-2 } + */ IR (imax - 5, imax - 3), IR (1, 2), SR (x, y), IR ( 5, 6), IR (3, 4), SR (x, y)); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c index 6a18f17..2c410b1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c @@ -117,10 +117,10 @@ void test_width_and_precision_out_of_range (char *d) { /* The range here happens to be a property of the compiler, not one of the target. */ - T ("%9223372036854775808i", 0); /* { dg-warning "width out of range" "first" } */ - /* { dg-warning "exceeds .INT_MAX." "second" { target *-*-* } .-1 } */ - T ("%.9223372036854775808i", 0); /* { dg-warning "precision out of range" "first" } */ - /* { dg-warning "exceeds .INT_MAX." "second" { target *-*-* } .-1 } */ + T ("%9223372036854775808i", 0); /* { dg-warning "width out of range|exceeds 'INT_MAX'" "first" } */ + /* { dg-warning "directive writing \\d+ bytes into a region of size \\d+" "" { target ilp32 } .-1 } */ + T ("%.9223372036854775808i", 0); /* { dg-warning "precision out of range|exceeds 'INT_MAX'" "first" } */ + /* { dg-warning "directive writing \\d+ bytes into a region of size \\d+" "ilp32" { target ilp32 } .-1 } */ /* The following is diagnosed by -Wformat (disabled here). */ /* T ("%9223372036854775808$i", 0); */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c new file mode 100644 index 0000000..df46023 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-25.c @@ -0,0 +1,76 @@ +/* PR middle-end/97373 - missing warning on sprintf into allocated destination + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +#include "../range.h" + +extern void* alloca (size_t); +extern void* malloc (size_t); + +extern int sprintf (char*, const char*, ...); +#define sprintf(d, ...) (sprintf (d, __VA_ARGS__), sink (d)) + +void sink (void*, ...); + +void test_alloca_range (void) +{ + int n1_2 = UR (1, 2); + int n5_9 = UR (5, 9); + + char *d = (char*)alloca (n5_9); + + sprintf (d, "%i", 12345); + + d += n1_2; + sprintf (d, "%i", 12345); + + d += n1_2; + sprintf (d, "%i", 12345); + + d += n1_2; + sprintf (d, "%i", 12345); + + d += n1_2; + sprintf (d, "%i", 12345); // { dg-warning "writing a terminating nul past the end of the destination" } + + d += n1_2; + sprintf (d, "%i", 12345); // { dg-warning "'%i' directive writing 5 bytes into a region of size 4" } +} + + +void test_malloc_range (void) +{ + int n2_3 = UR (2, 3); + int n5_9 = UR (5, 9); + + char *d = (char*)malloc (n5_9); + + sprintf (d, "%i", 12345); + + d += n2_3; + sprintf (d, "%i", 12345); + + d += n2_3; + sprintf (d, "%i", 12345); // { dg-warning "writing a terminating nul past the end of the destination" } + + d += n2_3; + sprintf (d, "%i", 12345); // { dg-warning "'%i' directive writing 5 bytes into a region of size 3" } +} + + +void test_vla_range (void) +{ + int n3_4 = UR (3, 4); + int n5_9 = UR (5, 9); + + char vla[n5_9]; + char *d = vla; + + sprintf (d, "%i", 12345); + + d += n3_4; + sprintf (d, "%i", 12345); + + d += n3_4; + sprintf (d, "%i", 12345); // { dg-warning "'%i' directive writing 5 bytes into a region of size 3" } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp20.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp20.c new file mode 100644 index 0000000..7d4d55f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp20.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void call (void); + +void foo (int base) +{ + unsigned i; + + // Ranger should be able to remove the (i > 123) comparison. + for (i = base; i < 10; i++) + if (i > 123) + { + call (); + return; + } +} + +/* { dg-final { scan-tree-dump-not "call" "evrp"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp21.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp21.c new file mode 100644 index 0000000..dae788c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp21.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +extern void vrp_keep (void); +extern void vrp_kill (void); + +void +f2 (int s, int b) +{ + if (s > 4) + s = 4; + if (s < -16) + s = -16; + /* s in [-16, 4]. */ + b = (b & 1) + 1; + /* b in range [1, 2]. */ + b = s << b; + /* b in range [-64, 16]. */ + if (b == -2) + vrp_keep (); + if (b <= -65) + vrp_kill (); + if (b >= 17) + vrp_kill (); +} + +/* { dg-final { scan-tree-dump-times "vrp_keep \\(" 1 "evrp"} } */ +/* { dg-final { scan-tree-dump-times "vrp_kill \\(" 0 "evrp"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp22.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp22.c new file mode 100644 index 0000000..3dd47e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp22.c @@ -0,0 +1,43 @@ +/* See backwards thru casts if the range fits the LHS type. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +extern void kill(int i); +extern void keep(int i); + +void +foo (int i) +{ + if (i >= 10) + { + if (i <= 100) + { + /* i has a range of [10, 100] */ + char c = (char) i; + if (c < 30) + { + /* If we wind back thru the cast with the range of c being [10,29] + * from the branch, and recognize that the range of i fits within + * a cast to c, then there is no missing information in a cast + * back to int. We can use the range calculated for 'c' with 'i' + * as well and Ranger should be able to kill the call. */ + if (i > 29) + kill (i); + } + } + /* i has a range of [10, MAX] */ + char d = (char) i; + if (d < 30) + { + /* Here, a cast to a char and back is NOT equivalent, so we cannot use + * the value of d to remove the call. */ + if (i > 29) + keep (i); + } + + } +} + +/* { dg-final { scan-tree-dump-times "kill \\(" 0 "evrp"} } */ +/* { dg-final { scan-tree-dump-times "keep \\(" 1 "evrp"} } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c new file mode 100644 index 0000000..e66fa73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-1.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int global; +int foo (); + +int main(int argc, char **argv) +{ + if (argc == 1) + foo (); + else if (argc == 2) + { + global += 1; + } + else if (argc == 3) + { + foo (); + foo (); + } + else if (argc == 4) + { + foo (); + } + else if (argc == 5) + { + global = 2; + } + else + global -= 123; + + global -= 12; + return 0; +} + +/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c new file mode 100644 index 0000000..252bea6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int isMyRandomCharacter(int aChar) +{ + return aChar == 0x0001 || aChar == 0x000A || + aChar == 0x000C || aChar == 0x000E || + aChar == 0x0020; +} + +/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c new file mode 100644 index 0000000..707e630 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int IsMySuperRandomChar(int aChar) +{ + return aChar == 0x0009 || aChar == 0x000A || + aChar == 0x000C || aChar == 0x000D || + aChar == 0x0020 || aChar == 0x0030; +} + +/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c new file mode 100644 index 0000000..6a03588 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int global; +int foo (); + +int main(int argc, char **argv) +{ + if (argc == 1) + foo (); + else if (argc == 2) + { + global += 1; + } + else if (argc == 3) + { + foo (); + foo (); + } + else if (argc == 4) + { + foo (); + } + /* This will be removed with EVRP. */ + else if (argc == 1) + { + global = 2; + } + else + global -= 123; + + global -= 12; + return 0; +} + +/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c new file mode 100644 index 0000000..ceeae90 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-5.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int crud (unsigned char c) +{ + return (((((((((((int) c == 46) || (int) c == 44) + || (int) c == 58) || (int) c == 59) || (int) c == 60) + || (int) c == 62) || (int) c == 34) || (int) c == 92) + || (int) c == 39) != 0); +} + +/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c new file mode 100644 index 0000000..464b1fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int global; +int foo (); + +int main(int argc, char **argv) +{ + if (argc >= 1 && argc <= 10) + foo (); + else if (argc == 12) + { + global += 1; + } + else if (argc == 13) + { + foo (); + foo (); + } + else if (argc == 14) + { + foo (); + } + /* This will be removed with EVRP. */ + else if (argc == 5) + { + global = 2; + } + /* This will be removed with EVRP. */ + else if (argc >= 7 && argc <= 9) + { + global = 2; + } + + else + global -= 123; + + global -= 12; + return 0; +} + +/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c new file mode 100644 index 0000000..4a176f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-7.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int global; + +int foo(int a) +{ + int x = 0; + for (unsigned i = 0; i < a; i++) + { + if (a == 2) + { + global += 123; + x = 1; + } + else if (a == 3) + x = 2; + else if (a == 10) + x = 3; + } + + return x; +} + +/* { dg-final { scan-tree-dump-not "Condition chain " "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c new file mode 100644 index 0000000..f43ce7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int global; +int global1; +int global2; +int global3; + +int foo(int a, int b) +{ + int x = 0; + for (unsigned i = 0; i < a; i++) + { + if (b == 1) + global += 2; + else if (a == 2) + global = 123; + else if (a == 3) + global1 = 1234; + else if (a == 10) + global2 = 12345; + else if (a == 1) + global2 = 123456; + } +} + +/* { dg-final { scan-tree-dump-not "Condition chain" "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c new file mode 100644 index 0000000..e67198b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-9.c @@ -0,0 +1,11 @@ +/* PR tree-optimization/88702 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */ + +int IsHTMLWhitespace(int aChar) { + return aChar == 0x0009 || aChar == 0x000A || + aChar == 0x000C || aChar == 0x000D || + aChar == 0x0020; +} + +/* { dg-final { scan-tree-dump "Condition chain with \[^\n\r]\* BBs transformed into a switch statement." "iftoswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c b/gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c new file mode 100644 index 0000000..d71b757 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-tree-ch -w -fdump-tree-loopdone-details" } */ + +void +t6 (int qz, int wh) +{ + int jl = wh; + + while (1.0 * qz / wh < 1) + { + qz = wh * (wh + 2); + + while (wh < 1) + jl = 0; + } + + while (qz < 1) + qz = jl * wh; +} + +/* { dg-final { scan-tree-dump-times "Replacing" 2 "loopdone"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-5.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-5.c new file mode 100644 index 0000000..fde3177 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-5.c @@ -0,0 +1,27 @@ +/* { dg-options "-O2 -fdump-tree-modref1" } */ +/* { dg-do run } */ +__attribute__ ((noinline)) +void +copy (int *a, int *b) +{ + *a=*b; +} +int p, *ptr = &p; +__attribute__ ((noinline)) +void +barrier () +{ + asm ("":"=r"(ptr):"0"(ptr)); +} +int +main() +{ + int a = 1, b = 2; + copy (&a,&b); + barrier (); + *ptr = 1; + if (!__builtin_constant_p (b == 2)) + __builtin_abort (); + return 0; +} +/* { dg-final { scan-tree-dump "parm 1 flags: nodirectescape" "modref1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c index fb8aebf..a93fcaf 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c @@ -19,5 +19,5 @@ int ffff(int i) /* We should not use extra temporaries apart from for i1 + i2. */ -/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "int" 6 "gimple" } } */ /* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c index 84dfcc9..5c1945b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c @@ -13,5 +13,5 @@ int qqq (int a) /* We should not use an extra temporary for the result of the function call. */ -/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "int" 4 "gimple" } } */ /* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c new file mode 100644 index 0000000..e9158e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fdump-tree-evrp" } */ + +struct A{int a,b;}; +inline int*f1(struct A*p){return&p->a;} /* offset of 0. */ +inline int*f2(struct A*p){return&p->b;} /* Offset of non-zero. */ +inline int*g(struct A*p){return(int*)p+1;} /* Always non-zero offet. */ + +/* Should be able to eliminate all calls to bad(). */ + +void bad(void); + +int +main() +{ + struct A* ptr = 0; + struct A addr; + + if (f1 (ptr) != 0) + bad(); + if (f1 (&addr) == 0) + bad(); + + if (f2 (ptr) == 0) + bad(); + if (f2 (&addr) == 0) + bad(); + + if (g (ptr) == 0) + bad(); + if (g (&addr) == 0) + bad(); + +} + +/* { dg-final { scan-tree-dump-not "bad" "evrp"} } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c new file mode 100644 index 0000000..d52734b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-1.c @@ -0,0 +1,68 @@ +/* PR tree-optimization/91029 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); +int xx; + +void f1 (int i, int j) +{ + if ((i % j) == 3) + { + xx = (i < 3); + if (xx) + kill (); + } +} + +void f2 (int i, int j) +{ + if ((i % j) > 0) + { + xx = (i <= 0); + if (xx) + kill (); + } +} + +void f3 (int i, int j) +{ + if ((i % j) == -3) + { + xx = (i > -3); + if (xx) + kill (); + } +} + +void f4 (int i, int j) +{ + if ((i % j) < 0) + { + xx = (i >= 0); + if (xx) + kill (); + } +} + +void f5 (int i, int j) +{ + if ((i % j) > 42) + { + xx = (i <= 42); + if (xx) + kill (); + } +} + +void f6 (int i, int j) +{ + if ((i % j) < -124) + { + xx = (i >= -124); + if (xx) + kill (); + } +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c new file mode 100644 index 0000000..ad9213a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91029-2.c @@ -0,0 +1,98 @@ +/* PR tree-optimization/91029 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); +int xx; + +void f1 (int i, int j) +{ + if ((i % j) == 3) + { + xx = (j <= 3 && j >= -3); + if (xx) + kill (); + } +} + +void f2 (int i, int j) +{ + if ((i % j) > 0) + { + xx = (j <= 1 && j >= -1); + if (xx) + kill (); + } +} + +void f3 (int i, int j) +{ + if ((i % j) == -3) + { + xx = (j <= 3 && j >= -3); + if (xx) + kill (); + } +} + +void f4 (int i, int j) +{ + if ((i % j) < 0) + { + xx = (j <= 1 && j >= -1); + if (xx) + kill (); + } +} + +void f5 (int i, int j) +{ + if ((i % j) > 42) + { + xx = (j <= 43 && j >= -43); + if (xx) + kill (); + } +} + +void f6 (int i, int j) +{ + if ((i % j) < -124) + { + xx = (j <= 125 && j >= -125); + if (xx) + kill (); + } +} + +void f7 (unsigned int i, unsigned int j) +{ + if ((i % j) == 3) + { + xx = (j <= 3); + if (xx) + kill (); + } +} + +void f8 (unsigned int i, unsigned int j) +{ + if ((i % j) > 0) + { + xx = (j <= 1); + if (xx) + kill (); + } +} + +void f9 (unsigned int i, unsigned int j) +{ + if ((i % j) >= 124) + { + xx = (j <= 124); + if (xx) + kill (); + } +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c new file mode 100644 index 0000000..5ebd805 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); + +void foo (unsigned int arg) +{ + int a = arg - 3; + unsigned int b = 4; + int x = 0x1 << arg; + + if (a < 0) + b = x; + + /* In the fullness of time, we will delete this call. */ + if (b >= 5) + kill ();; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c new file mode 100644 index 0000000..c9b2878 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); + +void foo (unsigned int arg) +{ + unsigned int C000003FE = 4; + + if (arg + 1 < 4) // work for if (arg < 3) + C000003FE = 0x1 << arg; + + if (C000003FE >= 5) + kill (); +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c new file mode 100644 index 0000000..e1d2be0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93781-3.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); + +void foo (unsigned int arg) +{ + int a = arg - 3; + unsigned int b = 4; + + if (a < 0) + { + int x = 0x1 << arg; + b = x; + } + + if (b >= 5) + kill (); +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c index f2a91ef..fc2103d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96480.c @@ -1,6 +1,6 @@ /* PR tree-optimization/96480 */ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized -fno-bit-tests -fno-jump-tables" } */ /* { dg-final { scan-tree-dump " = _\[0-9]* <= 3;" "optimized" } } */ int v[4]; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c index d6139a0..5704952 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96789.c @@ -1,5 +1,8 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -funroll-loops -ftree-vectorize -fdump-tree-dse-details" } */ +/* Disable loop vectorization to avoid that loop vectorizer + optimizes those two loops that operate tmp array so that + subsequent dse3 won't eliminate expected tmp stores. */ +/* { dg-options "-O2 -funroll-loops -ftree-slp-vectorize -fno-tree-loop-vectorize -fdump-tree-dse-details" } */ /* Test if scalar cleanup pass takes effects, mainly check its secondary pass DSE can remove dead stores on array diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96929.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96929.c new file mode 100644 index 0000000..65b6147 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96929.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/96929 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump "baz \\\(\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return -1;" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-not " >> " "optimized" } } */ + +int baz (void); + +int +foo (void) +{ + return -1 >> baz (); +} + +int +bar (int y) +{ + int z = -1; + return z >> y; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97849.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97849.c new file mode 100644 index 0000000..57a31e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97849.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-vectorize" } */ +/* { dg-additional-options "-march=armv8.2-a+sve" { target aarch64*-*-* } } */ + +int a, b, c; + +int g() { + char i = 0; + for (c = 0; c <= 8; c++) + --i; + + while (b) { + _Bool f = i <= 0; + a = (a == 0) ? 0 : f / a; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97964.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97964.c new file mode 100644 index 0000000..0ee0196 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97964.c @@ -0,0 +1,18 @@ +/* PR tree-optimization/97964 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "link_failure \\\(\\\);" "optimized" } } */ + +void link_failure (void); + +void +foo (int a) +{ + long b = -2; + int c = a > 0; + int d = b * c; + int e = 1 - d; + int t = (-1 / e) == 1; + if (t != 0) + link_failure (); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c new file mode 100644 index 0000000..3c4b468 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-1.c @@ -0,0 +1,52 @@ +/* PR tree-optimization/97997 */ +/* { dg-do compile { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return x_\[0-9]*\\\(D\\\);" 6 "optimized" } } */ +/* { dg-final { scan-tree-dump-not " / " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */ + +unsigned short +f1 (unsigned short x) +{ + return x * 10 / 10; +} + +unsigned short +f2 (unsigned short x) +{ + int a = x; + int b = 10; + int c = 10; + return a * b / c; +} + +unsigned short +f3 (unsigned short x) +{ + return x * 10U / 10; +} + +unsigned short +f4 (unsigned short x) +{ + unsigned a = x; + unsigned b = 10; + unsigned c = 10; + return a * b / c; +} + +unsigned short +f5 (unsigned short x, unsigned short y) +{ + return (unsigned) x * y / y; +} + +unsigned int +f6 (unsigned int x, unsigned int y) +{ + if (x >= 30000) + __builtin_unreachable (); + if (y >= ~0U / 30000) + __builtin_unreachable (); + return x * y / y; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c new file mode 100644 index 0000000..a9d5075 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97997-2.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/97997 */ +/* { dg-do compile { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2 -fdump-tree-optimized -fwrapv" } */ +/* { dg-final { scan-tree-dump-times "return x_\[0-9]*\\\(D\\\);" 4 "optimized" } } */ +/* { dg-final { scan-tree-dump-not " / " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */ + +unsigned short +f1 (unsigned short x) +{ + return x * 10 / 10; +} + +unsigned short +f2 (unsigned short x) +{ + int a = x; + int b = 10; + int c = 10; + return a * b / c; +} + +short +f3 (short x, short y) +{ + return x * y / y; +} + +int +f4 (int x, int y) +{ + if (x >= 30000) + __builtin_unreachable (); + if (x <= -30000) + __builtin_unreachable (); + if (y >= __INT_MAX__ / 30000) + __builtin_unreachable (); + if (y <= -__INT_MAX__ / 30000) + __builtin_unreachable (); + return x * y / y; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98084.c b/gcc/testsuite/gcc.dg/tree-ssa/pr98084.c new file mode 100644 index 0000000..6379624 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98084.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/98084 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +enum { + JSON_VARIANT_STRING, + JSON_VARIANT_UNSIGNED, + JSON_VARIANT_REAL, + JSON_VARIANT_ARRAY, + _JSON_VARIANT_TYPE_INVALID, + _JSON_VARIANT_MAGIC_ZERO_UNSIGNED, + _JSON_VARIANT_MAGIC_ZERO_REAL, + _JSON_VARIANT_MAGIC_EMPTY_STRING, + _JSON_VARIANT_MAGIC_EMPTY_ARRAY +} json_variant_type(int *v) { + if (!v) + return _JSON_VARIANT_TYPE_INVALID; + if (v == (int *)_JSON_VARIANT_MAGIC_ZERO_UNSIGNED) + return JSON_VARIANT_UNSIGNED; + if (v == (int *)_JSON_VARIANT_MAGIC_ZERO_REAL) + return JSON_VARIANT_REAL; + if (v == (int *)_JSON_VARIANT_MAGIC_EMPTY_STRING) + return JSON_VARIANT_STRING; + if (v == (int *)_JSON_VARIANT_MAGIC_EMPTY_ARRAY) + return JSON_VARIANT_ARRAY; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98094.c b/gcc/testsuite/gcc.dg/tree-ssa/pr98094.c new file mode 100644 index 0000000..f88534a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98094.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/98084 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct +{ + unsigned a : 10; +} b; + +int c; +void e(); +void d () +{ + c = b.a; + if (c == 8 || c == 0) + ; + else if (c > 8 * 8) + ; + else if (c < 8 * 8) + e (); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c index 944362a..093e7a5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c @@ -1,6 +1,6 @@ /* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ -/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1" } */ +/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1 -fno-bit-tests" } */ /* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c index 585b660..479f40f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c @@ -23,7 +23,7 @@ f (int s, int *c, int *d) However, this proves to be a useful test for introducing an initializer with a cast, so we'll keep it as is. */ -/* There are 4 ' * ' instances in the decls (since "int * iftmp.0;" is - added), 2 parms, 3 in the code. The second one in the code may - be a widening multiply (for example, on AArch64). */ -/* { dg-final { scan-tree-dump-times " w?\\* " 9 "optimized" } } */ +/* There are 5 ' * ' instances in the decls (since "int * iftmp.0;" is + added), 2 parms, 3 in the code, and the return value. The second one + in the code may be a widening multiply (for example, on AArch64). */ +/* { dg-final { scan-tree-dump-times " w?\\* " 10 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c index 51ba59c..de3051b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-3.c @@ -15,4 +15,4 @@ int test (int a, int b, int c, int g) /* We should hoist and CSE only the multiplication. */ /* { dg-final { scan-tree-dump-times " \\* " 1 "pre" } } */ -/* { dg-final { scan-tree-dump "Insertions: 1" "pre" } } */ +/* { dg-final { scan-tree-dump "HOIST inserted: 1" "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c index ce9cec6..fdb6a3e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-hoist-7.c @@ -49,6 +49,6 @@ void foo (int a, int b, int c, int d, int e, int x, int y, int z) /* Now inserting x + y five times is unnecessary but the cascading cannot be avoided with the simple-minded dataflow. But make sure - we do the insertions all in the first iteration. */ -/* { dg-final { scan-tree-dump "insert iterations == 2" "pre" } } */ + we do not iterate PRE insertion. */ +/* { dg-final { scan-tree-dump "insert iterations == 1" "pre" } } */ /* { dg-final { scan-tree-dump "HOIST inserted: 5" "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c index 59af63a..cf93173 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-30.c @@ -24,4 +24,4 @@ bar (int b, int x) /* We should see the partial redundant loads of f even though they are using different types (of the same size). */ -/* { dg-final { scan-tree-dump-times "Replaced MEM" 2 "pre" } } */ +/* { dg-final { scan-tree-dump-times "Replaced MEM" 3 "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c index 149687c..6f70c9d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-1.c @@ -54,7 +54,7 @@ int foo3 (int x) } } -/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: JT:0-62" "switchlower1" } } */ +/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:0-62" "switchlower1" } } */ int foo4 (int x) { @@ -77,7 +77,7 @@ int foo4 (int x) } } -/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: -100 JT:10-62 600-700" "switchlower1" } } */ +/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: -100 BT:10-62 600-700" "switchlower1" } } */ int foo5 (int x) { @@ -107,4 +107,4 @@ int foo5 (int x) } } -/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: JT:10-62 600-700 JT:1000-1021 111111" "switchlower1" } } */ +/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:10-62 600-700 JT:1000-1021 111111" "switchlower1" } } */ diff --git a/gcc/testsuite/gcc.dg/typeof-2.c b/gcc/testsuite/gcc.dg/typeof-2.c index 21ef5b0..68f91c6 100644 --- a/gcc/testsuite/gcc.dg/typeof-2.c +++ b/gcc/testsuite/gcc.dg/typeof-2.c @@ -1,21 +1,23 @@ -/* Test qualifier discard of typeof for atomic types. */ +/* Test qualifier preservation of typeof and discarded for __auto_type. */ /* { dg-do compile } */ /* { dg-options "-std=c11" } */ -/* Check that the qualifiers are discarded for atomic types. */ +/* Check that the qualifiers are preserved for atomic types. */ extern int i; extern int * p; extern int _Atomic const ci; -extern __typeof (ci) i; +extern __typeof (ci) ci; extern int _Atomic volatile vi; -extern __typeof (vi) i; +extern __typeof (vi) vi; extern int * _Atomic restrict ri; -extern __typeof (ri) p; +extern __typeof (ri) ri; + +/* Check that the qualifiers are discarded for atomic types. */ void f(void) { @@ -46,14 +48,16 @@ extern __typeof (nvi) k; extern int * restrict nri; extern __typeof (nri) q; +/* Check that the qualifiers are discarded for non-atomic types. */ + void g(void) { __auto_type aci = nci; - int const *paci = &aci; + int *paci = &aci; __auto_type avi = nvi; - int volatile *pavi = &avi; + int *pavi = &avi; __auto_type ari = nri; - int * restrict *pari = &ari; + int **pari = &ari; } diff --git a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c index f8c36a8..24b2fa8 100644 --- a/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c +++ b/gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c @@ -30,4 +30,4 @@ int *foo(void) return &c[0][0]; } -/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" } } */ +/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" { xfail vect_element_align_preferred } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-43.c b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c index a65d951..40bd2e0 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-43.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c @@ -14,4 +14,4 @@ f (int *restrict x, short *restrict y) } /* { dg-final { scan-tree-dump-not "mixed mask and nonmask" "slp2" } } */ -/* { dg-final { scan-tree-dump-not "vector operands from scalars" "slp2" { target { { vect_int && vect_bool_cmp } && { vect_unpack && vect_hw_misalign } } xfail vect_variable_length } } } */ +/* { dg-final { scan-tree-dump-not "vector operands from scalars" "slp2" { target { { vect_int && vect_bool_cmp } && { vect_unpack && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c index 8cd3a6a..e9909cf 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr68892.c @@ -15,6 +15,6 @@ void foo(void) /* ??? Due to the gaps we fall back to scalar loads which makes the vectorization profitable. */ -/* { dg-final { scan-tree-dump "not profitable" "slp2" { xfail *-*-* } } } */ -/* { 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 "Basic block will be vectorized" 1 "slp2" } } */ +/* { dg-final { scan-tree-dump "not profitable" "slp2" { xfail { ! aarch64*-*-* } } } } */ +/* { dg-final { scan-tree-dump "BB vectorization with gaps at the end of a load is not supported" "slp2" } } */ +/* { dg-final { scan-tree-dump-times "Basic block will be vectorized" 1 "slp2" { xfail aarch64*-*-* } } } */ 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 fe36f90..e27f956 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,7 @@ 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 "optimized: basic block" 2 "slp2" } } */ +/* Because we disable the cost model, targets with variable-length + vectors can end up vectorizing the store to a[0..7] on its own. + With the cost model we do something sensible. */ +/* { dg-final { scan-tree-dump-times "optimized: basic block" 2 "slp2" { xfail vect_variable_length } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c index 877de4e..495c031 100644 --- a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c +++ b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c @@ -97,4 +97,4 @@ main () } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { { vect_call_copysignf && vect_call_sqrtf } && vect_perm3_int } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c index 3bfe498..6834b9a 100644 --- a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c +++ b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-1.c @@ -5,8 +5,8 @@ void vadd (int *dst, int *op1, int *op2, int count) { /* { dg-prune-output " version\[^\n\r]* alignment" } */ -/* { dg-optimized "loop vectorized" "" { target *-*-* } .+2 } */ -/* { dg-optimized "loop versioned for vectorization because of possible aliasing" "" { target *-*-* } .+1 } */ +/* { dg-optimized "21: loop vectorized" "" { target *-*-* } .+2 } */ +/* { dg-optimized "21: loop versioned for vectorization because of possible aliasing" "" { target *-*-* } .+1 } */ for (int i = 0; i < count; ++i) dst[i] = op1[i] + op2[i]; } diff --git a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c index 94c55a9..23a3b39 100644 --- a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c +++ b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c @@ -6,7 +6,7 @@ extern void accumulate (int x, int *a); int test_missing_function_defn (int *arr, int n) /* { dg-message "vectorized 0 loops in function" } */ { int sum = 0; - for (int i = 0; i < n; ++i) /* { dg-missed "couldn't vectorize loop" } */ - accumulate (arr[i], &sum); /* { dg-missed "statement clobbers memory: accumulate \\(.*\\);" } */ + for (int i = 0; i < n; ++i) /* { dg-missed "21: couldn't vectorize loop" } */ + accumulate (arr[i], &sum); /* { dg-missed "5: statement clobbers memory: accumulate \\(.*\\);" } */ return sum; } diff --git a/gcc/testsuite/gcc.dg/vect/pr65947-8.c b/gcc/testsuite/gcc.dg/vect/pr65947-8.c index a2a940d..d042679 100644 --- a/gcc/testsuite/gcc.dg/vect/pr65947-8.c +++ b/gcc/testsuite/gcc.dg/vect/pr65947-8.c @@ -41,6 +41,6 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" { target { ! amdgcn*-*-* } } } } */ -/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target amdgcn*-*-* } } } */ -/* { dg-final { scan-tree-dump "multiple types in double reduction or condition reduction" "vect" { target { ! amdgcn*-*-* } } } } */ +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" { target { ! { amdgcn*-*-* || aarch64_sve } } } } } */ +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target { amdgcn*-*-* || aarch64_sve } } } } */ +/* { dg-final { scan-tree-dump "multiple types in double reduction or condition reduction" "vect" { target { ! { amdgcn*-*-* || aarch64_sve } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr91750.c b/gcc/testsuite/gcc.dg/vect/pr91750.c index fe914b2..3586f11 100644 --- a/gcc/testsuite/gcc.dg/vect/pr91750.c +++ b/gcc/testsuite/gcc.dg/vect/pr91750.c @@ -11,5 +11,5 @@ foo (int n) } /* Make sure the induction IV uses an unsigned increment. */ -/* { dg-final { scan-tree-dump "vector\\\(\[0-9\]*\\\) unsigned int" "vect" } } */ +/* { dg-final { scan-tree-dump {vector\([][0-9,]*\) unsigned int} "vect" } } */ /* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr97678.c b/gcc/testsuite/gcc.dg/vect/pr97678.c index ebe4a35..d9ffb7a 100644 --- a/gcc/testsuite/gcc.dg/vect/pr97678.c +++ b/gcc/testsuite/gcc.dg/vect/pr97678.c @@ -26,4 +26,5 @@ main () } /* The init loop should be vectorized with SLP. */ -/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* We don't yet support SLP inductions for variable length vectors. */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr97693.c b/gcc/testsuite/gcc.dg/vect/pr97693.c new file mode 100644 index 0000000..4da44c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97693.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +extern short a[]; +int b; +short c, d; +unsigned e() { + if (c) + return c; + return d; +} +void f() { + for (unsigned g = b; g; g += 6) + for (_Bool h = 0; h < (_Bool)e(); h = 1) + a[g] = 1 / b; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97730.c b/gcc/testsuite/gcc.dg/vect/pr97730.c new file mode 100644 index 0000000..af4bca4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97730.c @@ -0,0 +1,12 @@ +/* { dg-additional-options "-O1" } */ +unsigned b = 0xce8e5a48, c = 0xb849691a; +unsigned a[8080]; +int main() { + a[0] = b; + c = c; + unsigned f = 0xb1e8; + for (int h = 0; h < 5; h++) + a[h] = (b & c) ^ f; + if (a[0] != 0x8808f9e0) + __builtin_abort(); +} diff --git a/gcc/testsuite/gcc.dg/vect/pr97835.c b/gcc/testsuite/gcc.dg/vect/pr97835.c new file mode 100644 index 0000000..a90c773 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97835.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +struct co { + int gx; + int ty; +}; + +void +x0 (struct co *yy, long int kc, int wi, int md) +{ + while (wi < 1) + { + yy[wi].gx = md; + yy[wi].ty = wi; + md += kc; + ++wi; + } +} + +/* We don't yet support SLP inductions for variable length vectors. */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr97838.c b/gcc/testsuite/gcc.dg/vect/pr97838.c new file mode 100644 index 0000000..06ec035 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr97838.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ + +int a, b, c, d; + +void f() { + while (c++) { + int e = -1; + d = a ? e / a : e; + b ^= ~d; + } +} diff --git a/gcc/testsuite/gcc.dg/vect/pr98048.c b/gcc/testsuite/gcc.dg/vect/pr98048.c new file mode 100644 index 0000000..e61a376 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr98048.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +extern short var_0; +extern int var_3; +extern int arr_277[]; +int a(int b, int c) { return b < c ? b : c; } +int e; +void test() +{ + e = var_0; + for (int d = 0; d < 9; d++) + if (var_3) + arr_277[d] = a(var_0, -var_0); +} diff --git a/gcc/testsuite/gcc.dg/vect/slp-21.c b/gcc/testsuite/gcc.dg/vect/slp-21.c index 1f8c82e..117d65c 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-21.c +++ b/gcc/testsuite/gcc.dg/vect/slp-21.c @@ -201,6 +201,16 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target { vect_strided4 || vect_extract_even_odd } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided4 || vect_extract_even_odd } } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_strided4 } } } */ +/* Some targets can vectorize the second of the three main loops using + hybrid SLP. For 128-bit vectors, the required 4->3 permutations are: + + { 0, 1, 2, 4, 5, 6, 8, 9 } + { 2, 4, 5, 6, 8, 9, 10, 12 } + { 5, 6, 8, 9, 10, 12, 13, 14 } + + Not all vect_perm targets support that, and it's a bit too specific to have + its own effective-target selector, so we just test targets directly. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { aarch64*-*-* arm*-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_strided4 && { ! { aarch64*-*-* arm*-*-* } } } } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { vect_strided4 } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-46.c b/gcc/testsuite/gcc.dg/vect/slp-46.c index 58a238a..18476a4 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-46.c +++ b/gcc/testsuite/gcc.dg/vect/slp-46.c @@ -94,4 +94,4 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { xfail vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-49.c b/gcc/testsuite/gcc.dg/vect/slp-49.c index 3f53baf..4141a09 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-49.c +++ b/gcc/testsuite/gcc.dg/vect/slp-49.c @@ -34,5 +34,6 @@ main() return 0; } -/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* We don't yet support SLP inductions for variable length vectors. */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */ /* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c index 4128cca..ca7803e 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c @@ -80,9 +80,7 @@ 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 } && {! 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" 1 "vect" { target { vect_perm3_int && {! vect_load_lanes } } } } } */ /* { 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 b137821..b86a3dc 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-5.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c @@ -104,9 +104,7 @@ 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 } && {! 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" 2 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */ /* { 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 cc863de..bec1544 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c @@ -103,10 +103,7 @@ 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 } && {! 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" 2 "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 } xfail { vect_perm3_int && vect_load_lanes } } } } */ -/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target { vect_load_lanes } xfail { vect_load_lanes } } } } */ -/* { dg-final { scan-tree-dump "STORE_LANES" "vect" { target { vect_load_lanes } xfail { vect_load_lanes } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_perm3_int } } } */ +/* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes xfail vect_perm3_int } } } */ +/* { dg-final { scan-tree-dump "STORE_LANES" "vect" { target vect_load_lanes xfail vect_perm3_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c index 498999a..346411f 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c @@ -96,9 +96,7 @@ 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 } && {! 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" 1 "vect" { target { vect_perm3_int && { ! vect_load_lanes } } } } } */ /* { 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-reduc-4.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c index 266b439..cffb011 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c @@ -57,6 +57,8 @@ 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" } } */ +/* For variable-length SVE, the number of scalar statements in the + reduction exceeds the number of elements in a 128-bit granule. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_min_max || { aarch64_sve && vect_variable_length } } } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" { xfail { aarch64_sve && vect_variable_length } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c index 05cc9ed..7a958f2 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-7.c @@ -55,5 +55,7 @@ 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" } } */ +/* For variable-length SVE, the number of scalar statements in the + reduction exceeds the number of elements in a 128-bit granule. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail { vect_no_int_add || { aarch64_sve && vect_variable_length } } } } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 0 "vect" { xfail { aarch64_sve && vect_variable_length } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c index ca57a10..28a99c9 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-35-big-array.c @@ -20,10 +20,6 @@ int main1 () s.b[i] = i; } - /* Dependence analysis fails cause s.a and s.b may overlap. - Try to use runtime aliasing test with versioning, and - later versioning/vectorization are skipped because the - overlap is proven at compilation time. */ for (i = 0; i < N; i++) { s.a[i] = s.b[i] + 1; @@ -47,5 +43,4 @@ int main (void) } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */ -/* { dg-final { scan-tree-dump "can't determine dependence between" "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-35.c b/gcc/testsuite/gcc.dg/vect/vect-35.c index 76fe32d..a7ec0f16 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-35.c +++ b/gcc/testsuite/gcc.dg/vect/vect-35.c @@ -20,10 +20,6 @@ int main1 () s.b[i] = i; } - /* Dependence analysis fails cause s.a and s.b may overlap. - Try to use runtime aliasing test with versioning, and - later versioning/vectorization are skipped because the - overlap is proven at compilation time. */ for (i = 0; i < N; i++) { s.a[i] = s.b[i] + 1; @@ -47,5 +43,4 @@ int main (void) } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */ -/* { dg-final { scan-tree-dump "can't determine dependence between" "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail { ia64-*-* sparc*-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c new file mode 100644 index 0000000..0737da5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=cheap" } */ + +void +f (int *x, int *y) +{ + for (unsigned int i = 0; i < 1024; ++i) + x[i] += y[i]; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c new file mode 100644 index 0000000..fa9bdb6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=very-cheap" } */ + +void +f (int *x, int *y) +{ + for (unsigned int i = 0; i < 1024; ++i) + x[i] += y[i]; +} + +/* { dg-final { scan-tree-dump-not {LOOP VECTORIZED} vect { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c new file mode 100644 index 0000000..d7c6cfd --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=cheap" } */ + +void +f (int *restrict x, int *restrict y) +{ + for (unsigned int i = 0; i < 1024; ++i) + x[i] += y[i]; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c new file mode 100644 index 0000000..bb018ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=very-cheap" } */ + +int x[1024], y[1024]; + +void +f (void) +{ + for (unsigned int i = 0; i < 1024; ++i) + x[i] += y[i]; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c new file mode 100644 index 0000000..536ec0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=cheap" } */ + +void +f (int *restrict x, int *restrict y) +{ + for (unsigned int i = 0; i < 1023; ++i) + x[i] += y[i]; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target vect_int } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c b/gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c new file mode 100644 index 0000000..552febb --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-cost-model-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O2 -ftree-vectorize -fvect-cost-model=very-cheap" } */ + +void +f (int *restrict x, int *restrict y) +{ + for (unsigned int i = 0; i < 1023; ++i) + x[i] += y[i]; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} vect { target { vect_int && vect_partial_vectors_usage_2 } } } } */ +/* { dg-final { scan-tree-dump-not {LOOP VECTORIZED} vect { target { vect_int && { ! vect_partial_vectors_usage_2 } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-epilogues.c b/gcc/testsuite/gcc.dg/vect/vect-epilogues.c index a146bb6..ab7e8a1 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-epilogues.c +++ b/gcc/testsuite/gcc.dg/vect/vect-epilogues.c @@ -16,4 +16,4 @@ void pixel_avg( unsigned char *dst, int i_dst_stride, } } -/* { dg-final { scan-tree-dump "LOOP EPILOGUE VECTORIZED" "vect" { target vect_multiple_sizes xfail { arm32 && be } } } } */ +/* { dg-final { scan-tree-dump "LOOP EPILOGUE VECTORIZED" "vect" { target vect_multiple_sizes xfail { { arm32 && be } || vect_partial_vectors_usage_2 } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c index 62b18bd..445157d 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-1.c @@ -27,5 +27,6 @@ void foo (void) /* We should vectorize this outer loop with SLP. */ /* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" } } */ -/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* We don't yet support SLP inductions for variable length vectors. */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" { xfail vect_variable_length } } } */ /* { dg-final { scan-tree-dump-not "VEC_PERM_EXPR" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c index 08b4fc5..ec1e103 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-2.c @@ -48,4 +48,5 @@ int main () } /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" } } */ +/* We don't yet support SLP inductions for variable length vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_variable_length } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c index c67d369..53865d4 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-slp-3.c @@ -59,4 +59,5 @@ int main () } /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" } } */ +/* We don't yet support SLP inductions for variable length vectors. */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_variable_length } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c b/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c index be70bc6..484efb1 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c +++ b/gcc/testsuite/gcc.dg/vect/vect-sdiv-pow2-1.c @@ -62,7 +62,10 @@ main (void) { int p = power2 (fns[i].po2); for (int j = 0; j < N; j++) - a[j] = ((p << 4) * j) / (N - 1) - (p << 5); + { + a[j] = ((p << 4) * j) / (N - 1) - (p << 5); + asm volatile ("" ::: "memory"); + } fns[i].div (b, a, N); fns[i].mod (c, a, N); diff --git a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c index 02f6f3d..2afd2b5 100644 --- a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c +++ b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c @@ -143,11 +143,11 @@ T (v0 ? b[1] : "", bsz); T (v0 ? b[2] : "", bsz); T (v0 ? b[3] : "", bsz); -T (v0 ? "" : b[0], bsz + 1); +T (v0 ? "" : b[0], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" } */ T (v0 ? "" : b[1], bsz + 1); T (v0 ? "" : b[2], bsz + 1); T (v0 ? "" : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? b[0] : "", bsz + 1); +T (v0 ? b[0] : "", bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" } */ T (v0 ? b[1] : "", bsz + 1); T (v0 ? b[2] : "", bsz + 1); T (v0 ? b[3] : "", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ @@ -185,8 +185,8 @@ T (v0 ? "1234" : b[i3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfa T (v0 ? b[3] : "1234", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ T (v0 ? b[i3] : "1234", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? a : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? b[0] : b[2], bsz + 1); +T (v0 ? a : b[3], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" "pr86937" { xfail *-*-*} } */ +T (v0 ? b[0] : b[2], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" "pr86937" } */ T (v0 ? b[2] : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ T (v0 ? b[3] : b[2], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ |