| /* PR middle-end/91458 - inconsistent warning for writing past the end |
| of an array member |
| { dg-do compile } |
| { dg-options "-O2 -Wall -Wno-array-bounds" } */ |
| |
| #define NOIPA __attribute__ ((noipa)) |
| |
| void sink (void*); |
| |
| // Exercise flexible array members. |
| |
| struct Ax |
| { |
| char n; |
| char a[]; // { dg-message "destination object 'Ax::a' of size 0" "note: flexarray" } |
| }; |
| |
| // Verify warning for a definition with no initializer. |
| Ax ax_; |
| |
| NOIPA void gax_ () |
| { |
| ax_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| ax_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| ax_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that doesn't |
| // initialize the flexible array member. |
| Ax ax0 = { 0 }; |
| |
| NOIPA void gax0 () |
| { |
| ax0.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| ax0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| ax0.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that |
| // initializes the flexible array member to empty. |
| Ax ax0_ = { 0, { } }; |
| |
| NOIPA void gax0_ () |
| { |
| ax0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| ax0_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| ax0_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for out-of-bounds accesses to a definition with |
| // an initializer. |
| Ax ax1 = { 1, { 0 } }; |
| |
| NOIPA void gax1 () |
| { |
| ax1.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| ax1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| ax1.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| Ax ax2 = { 2, { 1, 0 } }; |
| |
| NOIPA void gax2 () |
| { |
| ax2.a[0] = 0; |
| ax2.a[1] = 0; |
| ax2.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| |
| // Verify no warning for an unknown struct object. |
| NOIPA void gaxp (Ax *p) |
| { |
| p->a[0] = 0; |
| p->a[3] = 0; |
| p->a[9] = 0; |
| } |
| |
| |
| // Verify no warning for an extern struct object whose array may be |
| // initialized to any number of elements. |
| extern Ax axx; |
| |
| NOIPA void gaxx () |
| { |
| axx.a[0] = 0; |
| axx.a[3] = 0; |
| axx.a[9] = 0; |
| } |
| |
| // Exercise zero-length array members. |
| |
| struct A0 |
| { |
| char n; |
| char a[0]; // { dg-message "destination object 'A0::a' of size 0" "note: trailing zero-length array" } |
| }; |
| |
| // Verify warning for a definition with no initializer. |
| A0 a0_; |
| |
| NOIPA void ga0_ () |
| { |
| a0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a0_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a0_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that doesn't |
| // initialize the flexible array member. |
| A0 a00 = { 0 }; |
| |
| NOIPA void ga00 () |
| { |
| a00.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a00.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a00.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that |
| // initializes the flexible array member to empty. |
| A0 a00_ = { 0, { } }; |
| |
| NOIPA void ga00_ () |
| { |
| a00_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a00_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a00_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // The following are rejected with |
| // error: too many initializers for 'char [0]' |
| // A0 a01 = { 1, { 0 } }; |
| // A0 a02 = { 2, { 1, 0 } }; |
| |
| |
| // Verify no warning for an unknown struct object. |
| NOIPA void ga0p (A0 *p) |
| { |
| p->a[0] = 0; |
| p->a[3] = 0; |
| p->a[9] = 0; |
| } |
| |
| |
| // Verify warning for an extern struct object which (unlike a true |
| // flexible array member) may not be initialized. |
| extern A0 a0x; |
| |
| NOIPA void ga0x () |
| { |
| a0x.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a0x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a0x.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| |
| // Exercise trailing one-element array members. |
| |
| struct A1 |
| { |
| char n; |
| char a[1]; // { dg-message "at offset \[1-2\] into destination object 'A1::a' of size 1" "note: trailing one-element array" } |
| }; |
| |
| // Verify warning for a definition with no initializer. |
| A1 a1_; |
| |
| NOIPA void ga1_ () |
| { |
| a1_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| a1_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that doesn't |
| // initialize the one-element array member. |
| A1 a1__ = { 0 }; |
| |
| NOIPA void ga1__ () |
| { |
| a1__.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| a1__.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1__.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that |
| // initializes the one-element array member to empty. |
| A1 a1_0 = { 0, { } }; |
| |
| NOIPA void ga1_0_ () |
| { |
| a1_0.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| a1_0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1_0.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that |
| // initializes the one-element array member. |
| A1 a1_1 = { 0, { 1 } }; |
| |
| NOIPA void ga1_1 () |
| { |
| a1_1.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| a1_1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1_1.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| |
| // Verify no warning for an unknown struct object. |
| NOIPA void ga1p (A1 *p) |
| { |
| p->a[0] = 0; |
| p->a[3] = 0; |
| p->a[9] = 0; |
| } |
| |
| |
| // Verify warning for an extern struct object. Similar to the zero-length |
| // array case, a one-element trailing array can be initialized to at most |
| // a single element. |
| extern A1 a1x; |
| |
| NOIPA void ga1x () |
| { |
| a1x.a[0] = 0; |
| a1x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a1x.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Exercise interior one-element array members (verify they're not |
| // treated as trailing. |
| |
| struct A1i |
| { |
| char n; |
| char a[1]; // { dg-message "at offset \[1-2\] into destination object 'A1i::a' of size 1" "note: interior one-element array" } |
| char x; |
| }; |
| |
| // Verify warning for a definition with no initializer. |
| A1i a1i_; |
| |
| NOIPA void ga1i_ () |
| { |
| a1i_.a[0] = 0; |
| a1i_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1i_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that doesn't |
| // initialize the one-element array member. |
| A1i a1i__ = { 0 }; |
| |
| NOIPA void ga1i__ () |
| { |
| a1i__.a[0] = 0; |
| a1i__.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1i__.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that |
| // initializes the one-element array member to empty. |
| A1 a1i_0 = { 0, { } }; |
| |
| NOIPA void ga1i_0_ () |
| { |
| a1i_0.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| a1i_0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1i_0.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| // Verify warning for access to a definition with an initializer that |
| // initializes the one-element array member. |
| A1 a1i_1 = { 0, { 1 } }; |
| |
| NOIPA void ga1i_1 () |
| { |
| a1i_1.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store_unalign } } } |
| a1i_1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store_unalign } } } |
| a1i_1.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| |
| // Verify no warning for an unknown struct object. |
| NOIPA void ga1ip (A1i *p) |
| { |
| p->a[0] = 0; |
| p->a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| p->a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| |
| // Verify no warning for an extern struct object. |
| extern A1i a1ix; |
| |
| NOIPA void ga1ix () |
| { |
| a1ix.a[0] = 0; |
| a1ix.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| a1ix.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" } |
| } |
| |
| |
| // Verify non-POD classes with flexible array members. |
| |
| struct Bx |
| { |
| char n; |
| char a[]; // { dg-message "destination object 'Bx::a' of size 0" "note: flexarray class member" } |
| |
| // Verify the warning for a constant. |
| Bx () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" } |
| |
| // And also for a non-constant. Regardless of the subscript, the array |
| // of the object in function gxi() below has a zero size. |
| Bx (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" } |
| }; |
| |
| NOIPA void gbx (void) |
| { |
| struct Bx bx; |
| sink (&bx); |
| } |
| |
| NOIPA void gbxi (int i) |
| { |
| struct Bx bxi (i); |
| sink (&bxi); |
| } |
| |
| struct B0 |
| { |
| char n; |
| char a[0]; // { dg-message "destination object 'B0::a' of size 0" "note: zero-length trailing array class member" } |
| |
| B0 () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" } |
| }; |
| |
| |
| NOIPA void gb0 (void) |
| { |
| struct B0 b0; |
| sink (&b0); |
| } |
| |
| |
| struct B1 |
| { |
| char n; |
| char a[1]; // { dg-message "at offset 1 into destination object 'B1::a' of size 1" "note: one-element trailing array class member" } |
| |
| B1 () { a[1] = 0; } // { dg-warning "\\\[-Wstringop-overflow" } |
| }; |
| |
| NOIPA void gb1 (void) |
| { |
| struct B1 b1; |
| sink (&b1); |
| } |
| |
| |
| struct B123 |
| { |
| char a[123]; // { dg-message "at offset 123 into destination object 'B123::a' of size 123" "note: large trailing array class member" } |
| |
| B123 () { a[123] = 0; } // { dg-warning "\\\[-Wstringop-overflow" } |
| }; |
| |
| NOIPA void gb123 (void) |
| { |
| struct B123 b123; |
| sink (&b123); |
| } |
| |
| |
| struct B234 |
| { |
| char a[234]; // { dg-message "at offset 234 into destination object 'B234::a' of size 234" "note: large trailing array class member" } |
| |
| B234 (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" } |
| }; |
| |
| NOIPA void g234 (void) |
| { |
| struct B234 b234 (234); |
| sink (&b234); |
| } |