1/* Check if ObjC class layout follows the ABI (informally)
2   set in the past.  ObjC structs must be laid out as if
3   all ivars, including those inherited from superclasses,
4   were defined at once (i.e., any padding introduced for
5   superclasses should be removed).  */
6/* Contributed by Ziemowit Laski <zlaski@apple.com>.  */
7/* { dg-do run } */
8/* { dg-options "-Wpadded -Wabi=8" } */
9
10/* Leave blank lines here to keep warnings on the same lines.  */
11
12#include "../objc-obj-c++-shared/TestsuiteObject.m"
13#include <objc/objc.h>
14#include <stdlib.h>
15
16#define CHECK_IF(expr) if(!(expr)) abort()
17
18enum Enum { zero, one, two, three, four };
19
20@interface Base: TestsuiteObject {
21@public
22  unsigned a: 2;
23  int b: 3;
24  enum Enum c: 4;
25  unsigned d: 5;
26} /* { dg-warning "padding struct size to alignment boundary" } */
27@end
28
29struct Base_0 { /* { dg-warning "padding struct size to alignment boundary" } */
30  Class isa;
31  unsigned a: 2;
32  int b: 3;
33  enum Enum c: 4;
34  unsigned d: 5;
35};
36
37@interface Derived: Base {
38@public
39  signed e: 5;
40  unsigned f: 4;
41  enum Enum g: 3;
42} /* { dg-line interface_Derived } */
43@end
44
45struct Derived_0 { /* { dg-line struct_Derived_0 } */
46  Class isa;
47  unsigned a: 2;
48  int b: 3;
49  enum Enum c: 4;
50  unsigned d: 5;
51  signed e: 5;
52  int f: 4;
53  enum Enum g: 3;
54};
55
56@interface Leaf: Derived {
57@public
58  signed h: 2;
59} /* { dg-line interface_Leaf } */
60@end
61
62struct Leaf_0 { /* { dg-line struct_Leaf_0 } */
63  Class isa;
64  unsigned a: 2;
65  int b: 3;
66  enum Enum c: 4;
67  unsigned d: 5;
68  signed e: 5;
69  unsigned f: 4;
70  enum Enum g: 3;
71  signed h: 2;
72};
73
74/* Note that the semicolon after @defs(...) is optional.  */
75
76typedef struct { @defs(Base) } Base_t; /* { dg-warning "padding struct size to alignment boundary" } */
77typedef struct { @defs(Derived); } Derived_t; /* { dg-line Derived_t_def } */
78typedef struct { @defs(Leaf); } Leaf_t; /* { dg-line Leaf_t_def } */
79
80int main(void)
81{
82  struct Leaf_0 l_0;
83  Leaf *l = (Leaf *)&l_0;
84  Leaf_t *l_t = (Leaf_t *)&l_0;
85
86  CHECK_IF(sizeof(Base_t) == sizeof(Base));
87  CHECK_IF(sizeof(Derived_t) == sizeof(Derived));
88  CHECK_IF(sizeof(Leaf_t) == sizeof(Leaf));
89
90  CHECK_IF(sizeof(struct Base_0) == sizeof(Base));
91  CHECK_IF(sizeof(struct Derived_0) == sizeof(Derived));
92  CHECK_IF(sizeof(struct Leaf_0) == sizeof(Leaf));
93
94  l_0.isa = (Class)0;
95  l_0.a = 3;
96  l_0.b = 0;
97  l_0.c = three;
98  l_0.d = 31;
99  l_0.e = 0;
100  l_0.f = 15;
101  l_0.g = zero;
102  l_0.h = -2;
103
104  CHECK_IF(!l_t->isa);
105  CHECK_IF(l->a == 3 && l_t->a == 3);
106  CHECK_IF(!l->b && !l_t->b);
107  CHECK_IF(l->c == three && l_t->c == three);
108  CHECK_IF(l->d == 31 && l_t->d == 31);
109  CHECK_IF(!l->e && !l_t->e);
110  CHECK_IF(l->f == 15 && l_t->f == 15);
111  CHECK_IF(l->g == zero && l_t->g == zero);
112  CHECK_IF(l->h == -2 && l_t->h == -2);
113
114  return 0;
115}
116
117/* { dg-prune-output "In file included from" }  Ignore this message.  */
118/* { dg-bogus "padding struct to align" "PR23610" { target *-*-* } 0 } */
119/* { dg-bogus "padding struct size" "PR23610" { xfail lp64 } interface_Derived } */
120/* { dg-bogus "padding struct size" "PR23610" { xfail lp64 } struct_Derived_0 } */
121/* { dg-bogus "padding struct size" "PR23610" { xfail lp64 } interface_Leaf } */
122/* { dg-bogus "padding struct size" "PR23610" { xfail lp64 } struct_Leaf_0 } */
123/* { dg-bogus "padding struct size" "PR23610" { xfail lp64 } Derived_t_def } */
124/* { dg-bogus "padding struct size" "PR23610" { xfail lp64 } Leaf_t_def } */
125