// { dg-do compile } // { dg-options "-Wno-error=pedantic" } // Test to verify flexible array members handling in base and derived // classes. #include "flexary.h" template struct S_no_diag: T { char a[]; // cannot be diagnosed unless/until T is known }; template struct STx_1: T { char a[]; // { dg-error "flexible array member" } }; template struct STI: T { char a[I]; // cannot be diagnosed unless/until T and I are known }; template struct STIx: T { char a[I]; }; template struct E { }; STx_1 > stx_empty_1; STIx, 0> stix_empty_1; // Verify that a sole flexible array member in a class with all empty // base classes is diagnosed. struct E1: E<0>, E<1> { }; struct E2: E<2>, E<3> { }; struct D1: E1, E2 { char a[]; // { dg-error "flexible array member" } }; struct NE { size_t i; }; struct A1x { int n, a[]; }; struct D2: A1x, E1, E2 { }; // Verify that the offset of the flexible array member is equal // to the size of each of the valid structs. ASSERT_AT_END (D2, a); struct D3: E1, A1x, E2 { }; ASSERT_AT_END (D3, a); struct D4: E1, E2, A1x { }; ASSERT_AT_END (D4, a); // Class with non-static data members and at least one base class // with such a member is not a standard layout class. The warning // below is benign since GCC computes the expected value. struct D5: E1, E2, NE { char a[]; }; ASSERT_AT_END (D5, a); // { dg-warning "offsetof within non-standard-layout" } struct A2x_1 { size_t n; size_t a[]; // { dg-error "not at end of .struct D6." } }; struct A2x_2 { size_t n; size_t a[]; // { dg-error "not at end of .struct D7." } }; struct A2x_3 { size_t n; size_t a[]; // { dg-error "not at end of .struct D8." } }; // Verify that the flexible array member in A2x above is diagnosed // for each of the three struct defintions below which also derive // from another struct with a flexible array member. struct D6: A2x_1, E1, A1x { }; struct D7: E1, A2x_2, E2, A1x { }; struct D8: E1, E2, A2x_3, A1x { }; struct DA2x: A2x_1 { }; struct D9: DA2x, E1, E2 { }; ASSERT_AT_END (D9, a); struct D10: E1, DA2x, E2 { }; ASSERT_AT_END (D10, a); struct D11: E1, E2, DA2x { }; ASSERT_AT_END (D11, a); struct A3x { size_t n; size_t a[]; // { dg-error "not at end of .struct D12.| D13.| D14.| D15." } }; // Verify that the flexible array member in A3x above is diagnosed // for each of the three struct defintions below which also derive // from another struct with a non-static member. struct D12: A3x, E1, NE { }; struct D13: E1, A3x, NE { }; struct D14: E1, E2, A3x, NE { }; struct D15: E1, E2, NE, A3x { }; struct A4x { A4x (); ~A4x (); size_t n; struct AS { AS (int); ~AS (); size_t i; } a[]; }; struct D16: A4x, E1, E2 { }; ASSERT_AT_END (D16, a); struct D17: E1, A4x, E2 { }; ASSERT_AT_END (D17, a); struct D18: E1, E2, A4x { }; ASSERT_AT_END (D18, a); struct DA4x: A4x { }; struct D19: DA4x, E1, E2 { }; ASSERT_AT_END (D19, a); struct D20: E1, DA4x, E2 { }; ASSERT_AT_END (D20, a); struct D21: E1, E2, DA4x { }; ASSERT_AT_END (D21, a); struct A5x { A5x (int); virtual ~A5x (); size_t n; struct AS { AS (int); ~AS (); size_t i; } a[]; }; struct D22: A5x, E1, E2 { }; ASSERT_AT_END (D22, a); // { dg-warning "offsetof within non-standard-layout" } struct D23: E1, A5x, E2 { }; ASSERT_AT_END (D23, a); // { dg-warning "offsetof within non-standard-layout" } struct D24: E1, E2, A5x { }; ASSERT_AT_END (D24, a); // { dg-warning "offsetof within non-standard-layout" } struct DA5x: A5x { }; struct D25: DA5x, E1, E2 { }; ASSERT_AT_END (D25, a); // { dg-warning "offsetof within non-standard-layout" } struct D26: E1, DA5x, E2 { }; ASSERT_AT_END (D26, a); // { dg-warning "offsetof within non-standard-layout" } struct D27: E1, E2, DA5x { }; ASSERT_AT_END (D27, a); // { dg-warning "offsetof within non-standard-layout" } // Verfify that a flexible array member is diagnosed even when deep // in the base class hierarchy. struct A6x { size_t n; size_t a[]; // { dg-error "not at end of .struct D28.| D29." } }; struct AA6x: A6x { }; struct NE1: NE { }; struct NE2: NE { }; struct D28: NE1, AA6x { }; struct D29: AA6x, NE1 { }; struct A7x { size_t n; size_t a[]; // { dg-error "flexible array member .A7x::a. not at end of .struct D33." } }; // Verify that a flexible array member in a virtual base class is not // diagnosed. struct DA7xV1: virtual A7x { }; struct DA7xV2: virtual A7x { }; struct D30: DA7xV1, DA7xV2 { }; struct D31: DA7xV1, DA7xV2 { }; struct D32: D30, D31 { }; // Verify the diagnostic when the flexible array is in an anonymous struct. struct A8x { struct { // { dg-message "next member .A8x:: A8x::. declared here" } size_t n; size_t a[]; }; }; struct D33: // { dg-message "in the definition of .struct D33." } A7x, A8x { };