1 // { dg-do compile }
2 // { dg-options "-Wno-error=pedantic" }
3 
4 // Test to verify flexible array members handling in base and derived
5 // classes.
6 
7 #include "flexary.h"
8 
9 template <class T>
10 struct S_no_diag: T {
11   char a[];   // cannot be diagnosed unless/until T is known
12 };
13 
14 template <class T>
15 struct STx_1: T {
16   char a[];   // { dg-error "flexible array member" }
17 };
18 
19 template <class T, int I>
20 struct STI: T {
21   char a[I];   // cannot be diagnosed unless/until T and I are known
22 };
23 
24 template <class T, int I>
25 struct STIx: T {
26   char a[I];
27 };
28 
29 template <int> struct E { };
30 
31 STx_1<E<0> > stx_empty_1;
32 STIx<E<0>, 0> stix_empty_1;
33 
34 // Verify that a sole flexible array member in a class with all empty
35 // base classes is diagnosed.
36 struct E1: E<0>, E<1> { };
37 struct E2: E<2>, E<3> { };
38 struct D1: E1, E2
39 {
40     char a[];   // { dg-error "flexible array member" }
41 };
42 
43 struct NE { size_t i; };
44 
45 struct A1x { int n, a[]; };
46 struct D2: A1x, E1, E2 { };
47 
48 // Verify that the offset of the flexible array member is equal
49 // to the size of each of the valid structs.
50 ASSERT_AT_END (D2, a);
51 
52 struct D3: E1, A1x, E2 { };
53 
54 ASSERT_AT_END (D3, a);
55 
56 struct D4: E1, E2, A1x { };
57 
58 ASSERT_AT_END (D4, a);
59 
60 // Class with non-static data members and at least one base class
61 // with such a member is not a standard layout class.  The warning
62 // below is benign since GCC computes the expected value.
63 struct D5: E1, E2, NE { char a[]; };
64 
65 ASSERT_AT_END (D5, a);   // { dg-warning "offsetof within non-standard-layout" }
66 
67 struct A2x_1 {
68   size_t n;
69   size_t a[];   // { dg-error "not at end of .struct D6." }
70 };
71 
72 struct A2x_2 {
73   size_t n;
74   size_t a[];   // { dg-error "not at end of .struct D7." }
75 };
76 
77 struct A2x_3 {
78   size_t n;
79   size_t a[];   // { dg-error "not at end of .struct D8." }
80 };
81 
82 // Verify that the flexible array member in A2x above is diagnosed
83 // for each of the three struct defintions below which also derive
84 // from another struct with a flexible array member.
85 struct D6: A2x_1, E1, A1x { };
86 struct D7: E1, A2x_2, E2, A1x { };
87 struct D8: E1, E2, A2x_3, A1x { };
88 
89 struct DA2x: A2x_1 { };
90 
91 struct D9: DA2x, E1, E2 { };
92 
93 ASSERT_AT_END (D9, a);
94 
95 struct D10: E1, DA2x, E2 { };
96 
97 ASSERT_AT_END (D10, a);
98 
99 struct D11: E1, E2, DA2x { };
100 
101 ASSERT_AT_END (D11, a);
102 
103 struct A3x {
104   size_t n;
105   size_t a[];   // { dg-error "not at end of .struct D12.| D13.| D14.| D15." }
106 };
107 
108 // Verify that the flexible array member in A3x above is diagnosed
109 // for each of the three struct defintions below which also derive
110 // from another struct with a non-static member.
111 struct D12: A3x, E1, NE { };
112 struct D13: E1, A3x, NE { };
113 struct D14: E1, E2, A3x, NE { };
114 struct D15: E1, E2, NE, A3x { };
115 
116 struct A4x {
117   A4x ();
118   ~A4x ();
119 
120   size_t n;
121   struct AS {
122     AS (int);
123     ~AS ();
124     size_t i;
125   } a[];
126 };
127 
128 struct D16: A4x, E1, E2 { };
129 
130 ASSERT_AT_END (D16, a);
131 
132 struct D17: E1, A4x, E2 { };
133 
134 ASSERT_AT_END (D17, a);
135 
136 struct D18: E1, E2, A4x { };
137 
138 ASSERT_AT_END (D18, a);
139 
140 struct DA4x: A4x { };
141 
142 struct D19: DA4x, E1, E2 { };
143 
144 ASSERT_AT_END (D19, a);
145 
146 struct D20: E1, DA4x, E2 { };
147 
148 ASSERT_AT_END (D20, a);
149 
150 struct D21: E1, E2, DA4x { };
151 
152 ASSERT_AT_END (D21, a);
153 
154 
155 struct A5x {
156   A5x (int);
157   virtual ~A5x ();
158 
159   size_t n;
160   struct AS {
161     AS (int);
162     ~AS ();
163     size_t i;
164   } a[];
165 };
166 
167 struct D22: A5x, E1, E2 { };
168 
169 ASSERT_AT_END (D22, a);   // { dg-warning "offsetof within non-standard-layout" }
170 
171 struct D23: E1, A5x, E2 { };
172 
173 ASSERT_AT_END (D23, a);   // { dg-warning "offsetof within non-standard-layout" }
174 
175 struct D24: E1, E2, A5x { };
176 
177 ASSERT_AT_END (D24, a);   // { dg-warning "offsetof within non-standard-layout" }
178 
179 struct DA5x: A5x { };
180 
181 struct D25: DA5x, E1, E2 { };
182 
183 ASSERT_AT_END (D25, a);   // { dg-warning "offsetof within non-standard-layout" }
184 
185 struct D26: E1, DA5x, E2 { };
186 
187 ASSERT_AT_END (D26, a);   // { dg-warning "offsetof within non-standard-layout" }
188 
189 struct D27: E1, E2, DA5x { };
190 
191 ASSERT_AT_END (D27, a);   // { dg-warning "offsetof within non-standard-layout" }
192 
193 // Verfify that a flexible array member is diagnosed even when deep
194 // in the base class hierarchy.
195 struct A6x {
196   size_t n;
197   size_t a[];               // { dg-error "not at end of .struct D28.| D29." }
198 };
199 
200 struct AA6x: A6x { };
201 struct NE1: NE { };
202 struct NE2: NE { };
203 
204 struct D28: NE1, AA6x { };
205 struct D29: AA6x, NE1 { };
206 
207 struct A7x {
208   size_t n;
209   size_t a[];               // { dg-error "flexible array member .A7x::a. not at end of .struct D33." }
210 };
211 
212 // Verify that a flexible array member in a virtual base class is not
213 // diagnosed.
214 struct DA7xV1: virtual A7x { };
215 struct DA7xV2: virtual A7x { };
216 
217 struct D30: DA7xV1, DA7xV2 { };
218 struct D31: DA7xV1, DA7xV2 { };
219 struct D32: D30, D31 { };
220 
221 // Verify the diagnostic when the flexible array is in an anonymous struct.
222 struct A8x {
223   struct {                  // { dg-message "next member .A8x::<unnamed struct> A8x::<anonymous>. declared here" }
224     size_t n;
225     size_t a[];
226   };
227 };
228 
229 struct D33:                 // { dg-message "in the definition of .struct D33." }
230   A7x, A8x { };
231