1 #include <cstdarg>
2 #include <cstdint>
3 #include <cstdlib>
4 #include <ostream>
5 #include <new>
6 
7 struct Foo {
8   bool a;
9   int32_t b;
10 
operator ==Foo11   bool operator==(const Foo& aOther) const {
12     return a == aOther.a &&
13            b == aOther.b;
14   }
operator !=Foo15   bool operator!=(const Foo& aOther) const {
16     return a != aOther.a ||
17            b != aOther.b;
18   }
19 };
20 
21 union Bar {
22   enum class Tag : uint8_t {
23     Baz,
24     Bazz,
25     FooNamed,
26     FooParen,
27   };
28 
29   struct Bazz_Body {
30     Tag tag;
31     Foo named;
32 
operator ==Bar::Bazz_Body33     bool operator==(const Bazz_Body& aOther) const {
34       return named == aOther.named;
35     }
operator !=Bar::Bazz_Body36     bool operator!=(const Bazz_Body& aOther) const {
37       return named != aOther.named;
38     }
39   };
40 
41   struct FooNamed_Body {
42     Tag tag;
43     int32_t different;
44     uint32_t fields;
45 
operator ==Bar::FooNamed_Body46     bool operator==(const FooNamed_Body& aOther) const {
47       return different == aOther.different &&
48              fields == aOther.fields;
49     }
operator !=Bar::FooNamed_Body50     bool operator!=(const FooNamed_Body& aOther) const {
51       return different != aOther.different ||
52              fields != aOther.fields;
53     }
54   };
55 
56   struct FooParen_Body {
57     Tag tag;
58     int32_t _0;
59     Foo _1;
60 
operator ==Bar::FooParen_Body61     bool operator==(const FooParen_Body& aOther) const {
62       return _0 == aOther._0 &&
63              _1 == aOther._1;
64     }
operator !=Bar::FooParen_Body65     bool operator!=(const FooParen_Body& aOther) const {
66       return _0 != aOther._0 ||
67              _1 != aOther._1;
68     }
69   };
70 
71   struct {
72     Tag tag;
73   };
74   Bazz_Body bazz;
75   FooNamed_Body foo_named;
76   FooParen_Body foo_paren;
77 
operator ==(const Bar & aOther) const78   bool operator==(const Bar& aOther) const {
79     if (tag != aOther.tag) {
80       return false;
81     }
82     switch (tag) {
83       case Tag::Bazz: return bazz == aOther.bazz;
84       case Tag::FooNamed: return foo_named == aOther.foo_named;
85       case Tag::FooParen: return foo_paren == aOther.foo_paren;
86       default: break;
87     }
88     return true;
89   }
90 
operator !=(const Bar & aOther) const91   bool operator!=(const Bar& aOther) const {
92     return !(*this == aOther);
93   }
94 };
95 
96 extern "C" {
97 
98 Foo root(Bar aBar);
99 
100 } // extern "C"
101