blob: bd28cf55de2bedf4e8c1cd559414ebaafc0b5c8f [file] [log] [blame]
// 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];
};