// 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]; };