| // PR c++/42121 - g++ should warn or error on internal 0 size array in struct |
| // { dg-do compile } |
| // { dg-options "-Wno-error=pedantic" } |
| |
| // Flexible array members are a feature of C99 (and newer) not provided |
| // by C++ 2014 and prior. G++ supports both the C99/C11 kind of flexible |
| // array members and pre-C99 zero-size arrays (defining an array of size |
| // zero). Since both features are provided for compatibility with C, |
| // G++ allows them in the same contexts as in C. |
| |
| #include "flexary.h" |
| |
| struct Sx { |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| // Verify that non-data members or static data members either before |
| // or after a flexible array member in an otherwise empty struct don't |
| // suppress the diagnostic. |
| struct Sx2 { |
| int a[]; // { dg-error "in an otherwise empty" } |
| typedef int I; |
| }; |
| |
| struct Sx3 { |
| typedef int I; |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx4 { |
| int a[]; // { dg-error "in an otherwise empty" } |
| enum E { e }; |
| }; |
| |
| struct Sx5 { |
| enum E { e }; |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx6 { |
| int a[]; // { dg-error "in an otherwise empty" } |
| static int i; |
| }; |
| |
| struct Sx7 { |
| static int i; |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx8 { |
| int a[]; // { dg-error "in an otherwise empty" } |
| Sx8 () { } |
| }; |
| |
| struct Sx9 { |
| Sx9 () { } |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx10 { |
| int a[]; // { dg-error "in an otherwise empty" } |
| virtual ~Sx10 () { } |
| }; |
| |
| struct Sx11 { |
| virtual ~Sx11 () { } |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx12 { |
| int a[]; // { dg-error "in an otherwise empty" } |
| virtual void foo () = 0; |
| }; |
| |
| struct Sx13 { |
| virtual void foo () = 0; |
| int a[]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx14 { |
| int a[][1]; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx15 { |
| typedef int A[]; |
| A a; // { dg-error "in an otherwise empty" } |
| }; |
| |
| // Verify also that a zero-size array doesn't suppress the diagnostic. |
| struct Sx16 { |
| // a_0 below is diagnosed with -Wpedantic only and emits |
| // warning: ISO C++ forbids zero-size arrays |
| int a_0 [0]; |
| int a_x []; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx17 { |
| int a_x []; // { dg-error "flexible array member" } |
| |
| // a_0 below is diagnosed with -Wpedantic only and emits |
| // warning: ISO C++ forbids zero-size arrays |
| int a_0 [0]; |
| }; |
| |
| // An empty struct is treated as if it had a single member of type |
| // char but the member cannot be accessed. Therefore, a struct |
| // containing a flexible array member followed by an empty struct |
| // is diagnosed to prevent the former subobject from sharing space |
| // with the latter. |
| struct Sx18 { |
| int a_x []; // { dg-error "flexible array member" } |
| struct { /* empty */ } s; |
| }; |
| |
| // Anonymous structs are a G++ extension. Members of anonymous structs |
| // are treated as if they were declared in the enclosing class. |
| struct Sx19 { |
| struct { int i; }; // anonymous struct |
| int a_x []; |
| }; |
| |
| // Unlike in the case above, a named struct is not anonymous and |
| // so doesn't contribute its member to that of the enclosing struct. |
| struct Sx20 { |
| struct S { int i; }; |
| int a_x []; // { dg-error "in an otherwise empty" } |
| }; |
| |
| struct Sx21 { |
| int a_x []; // { dg-error "not at end" } |
| struct S { } s; |
| }; |
| |
| struct Sx22 { |
| int a_x []; // { dg-error "not at end" } |
| union { int i; }; |
| }; |
| |
| struct Sx23 { |
| union { int i; }; |
| int a_x []; |
| }; |
| |
| struct Sx24 { |
| struct S; |
| S a_x []; // { dg-error "5:field .a_x. has incomplete type" } |
| }; |
| |
| struct Sx25 { |
| struct S { }; |
| S a_x []; // { dg-error "flexible array member" } |
| }; |
| |
| struct Sx26 { |
| struct { } |
| a_x []; // { dg-error "flexible array member" } |
| }; |
| |
| struct Sx27 { |
| int i; |
| struct { } |
| a_x []; |
| }; |
| |
| ASSERT_AT_END (Sx27, a_x); |
| |
| struct Sx28 { |
| struct { } |
| a_x []; // { dg-error "not at end" } |
| int i; |
| }; |
| |
| struct Sx29 { |
| // Pointer to an array of unknown size. |
| int (*a_x)[]; |
| }; |
| |
| struct Sx30 { |
| // Reference to an array of unknown size. |
| int (&a_x)[]; |
| }; |
| |
| struct Sx31 { |
| int a []; // { dg-error "not at end" } |
| unsigned i: 1; |
| }; |
| |
| struct Sx32 { |
| unsigned i: 1; |
| int a []; |
| }; |
| |
| ASSERT_AT_END (Sx32, a); |
| |
| struct Sx33 { |
| int a []; // { dg-error "otherwise empty" } |
| friend int foo (); |
| }; |
| |
| struct Sx34 { |
| friend int foo (); |
| int a []; // { dg-error "otherwise empty" } |
| }; |
| |
| // Verify that intervening non-field declarations of members other |
| // than non-static data members don't affect the diagnostics. |
| struct Sx35 { |
| int a[]; // { dg-error "not at end" } |
| typedef int I; |
| int n; |
| }; |
| |
| struct Sx36 { |
| int n; |
| typedef int I; |
| int a[]; |
| }; |
| |
| ASSERT_AT_END (Sx36, a); |
| |
| struct Sx37 { |
| int a[]; // { dg-error "not at end" } |
| enum E { }; |
| int n; |
| }; |
| |
| struct Sx38 { |
| int n; |
| enum E { }; |
| int a[]; |
| }; |
| |
| ASSERT_AT_END (Sx38, a); |
| |
| struct Sx39 { |
| int a[]; // { dg-error "not at end" } |
| struct S; |
| int n; |
| }; |
| |
| struct Sx40 { |
| int n; |
| struct S; |
| int a[]; |
| }; |
| |
| ASSERT_AT_END (Sx40, a); |
| |
| struct Sx41 { |
| int a[]; // { dg-error "not at end" } |
| static int i; |
| int n; |
| }; |
| |
| struct Sx42 { |
| int n; |
| static int i; |
| int a[]; |
| }; |
| |
| ASSERT_AT_END (Sx42, a); |
| |
| struct Sx43 { |
| int a[]; // { dg-error "not at end" } |
| Sx43 (); |
| int n; |
| }; |
| |
| struct Sx44 { |
| int n; |
| Sx44 (); |
| int a[]; |
| }; |
| |
| ASSERT_AT_END (Sx44, a); |
| |
| struct S_S_S_x { |
| struct A { |
| struct B { |
| int a[]; // { dg-error "flexible array member" } |
| } b; |
| } a; |
| }; |
| |
| // Since members of an anonymous struct or union are considered to be |
| // members of the enclosing union the below defintions are valid and |
| // must be accepted. |
| |
| struct Anon1 { |
| int n; |
| struct { |
| int good[]; |
| }; |
| }; |
| |
| ASSERT_AT_END (Anon1, good); |
| |
| struct NotAnon1 { |
| int n; |
| // The following is not an anonymous struct -- the type is unnamed |
| // but the object has a name. |
| struct { |
| int bad[]; // { dg-error "otherwise empty" } |
| } name; |
| }; |
| |
| struct Anon2 { |
| struct { |
| int n; |
| struct { |
| int good[]; |
| }; |
| }; |
| }; |
| |
| ASSERT_AT_END (Anon2, good); |
| |
| struct Anon3 { |
| struct { |
| struct { |
| int n; |
| int good[]; |
| }; |
| }; |
| }; |
| |
| ASSERT_AT_END (Anon3, good); |
| |
| struct Anon4 { |
| struct { |
| int in_empty_struct[]; // { dg-error "in an otherwise empty" } |
| }; |
| }; |
| |
| struct Anon5 { |
| struct { |
| int not_at_end[]; // { dg-error "not at end" } |
| }; |
| int n; |
| }; |
| |
| struct Anon6 { |
| struct { |
| struct { |
| int not_at_end[]; // { dg-error "not at end" } |
| }; |
| int n; |
| }; |
| }; |
| |
| |
| struct Anon7 { |
| struct { |
| struct { |
| int not_at_end[]; // { dg-error "not at end" } |
| }; |
| }; |
| int n; |
| }; |
| |
| struct Six { |
| int i; |
| int a[]; |
| }; |
| |
| ASSERT_AT_END (Six, a); |
| |
| class Cx { |
| int a[]; // { dg-error "flexible array member" } |
| }; |
| |
| class Cix { |
| int i; |
| int a[]; |
| }; |
| |
| struct Sxi { |
| int a[]; // { dg-error "not at end" } |
| int i; |
| }; |
| |
| struct S0 { |
| int a[0]; |
| }; |
| |
| struct S0i { |
| int a[0]; |
| int i; |
| }; |
| |
| struct S_a0_ax { |
| int a0[0]; |
| int ax[]; // { dg-error "flexible array member" } |
| }; |
| |
| struct S_a0_i_ax { |
| int a0[0]; |
| int i; |
| int ax[]; |
| }; |
| |
| ASSERT_AT_END (S_a0_i_ax, ax); |
| |
| struct Si_a0_ax { |
| int i; |
| int a0[0]; |
| int ax[]; |
| }; |
| |
| ASSERT_AT_END (Si_a0_ax, ax); |
| |
| struct Si_ax_a0 { |
| int i; |
| int ax[]; // { dg-error "not at end" } |
| int a0[0]; |
| }; |
| |
| struct S_u0_ax { |
| union { } u[0]; |
| int ax[]; // { dg-error "flexible array member" } |
| }; |
| |
| struct S_a1_s2 { |
| int a[1]; |
| int b[2]; |
| }; |