1// Check if the '- .cxx_construct' and '-.cxx_destruct' methods get called
2// and if they perform their desired function.
3
4// { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } }
5// { dg-do run { target *-*-darwin* } }
6// { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } }
7// { dg-options "-fobjc-call-cxx-cdtors" }
8
9#include "../objc-obj-c++-shared/TestsuiteObject.m"
10#include <stdlib.h>
11#define CHECK_IF(expr) if(!(expr)) abort()
12
13static int ctor1_called, ctor2_called, dtor1_called;
14
15struct bar {
16  int a, b;
17  bar(void) {
18    a = 5; b = 6;
19    ctor1_called++;
20  }
21  ~bar(void) {
22    a = b = 99;
23    dtor1_called++;
24  }
25};
26
27struct boo: bar {
28  int c;
29  boo(int _c = 9): c(_c) {
30    ctor2_called++;
31  }
32};
33
34@interface Baz: TestsuiteObject {
35@public
36  bar aa;
37}
38@end
39
40@implementation Baz
41@end
42
43@interface Foo: Baz {
44@public
45  int a;
46  boo bb;
47  bar b;
48  float c;
49  bar d;
50}
51@end
52
53@implementation Foo
54@end
55
56int main (void)
57{
58  CHECK_IF(!ctor1_called && !ctor2_called && !dtor1_called); /* are we sane? */
59
60  Baz *baz = [Baz new];
61  CHECK_IF(ctor1_called && !ctor2_called && !dtor1_called);
62  CHECK_IF(baz->aa.a == 5 && baz->aa.b == 6);
63  ctor1_called = 0;  /* reset */
64
65  [baz free];
66  CHECK_IF(!ctor1_called && !ctor2_called && dtor1_called);
67  dtor1_called = 0;  /* reset */
68
69  Foo *foo = [Foo new];
70  CHECK_IF(ctor1_called && ctor2_called && !dtor1_called);
71  CHECK_IF(foo->bb.a == 5 && foo->bb.b == 6 && foo->bb.c == 9);
72  CHECK_IF(foo->b.a == 5 && foo->b.b == 6);
73  CHECK_IF(foo->d.a == 5 && foo->d.b == 6);
74  ctor1_called = ctor2_called = 0;  /* reset */
75
76  [foo free];
77  CHECK_IF(!ctor1_called && !ctor2_called && dtor1_called);
78}
79
80