diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 40e9f79b63..f9fcf150a4 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -98,6 +98,19 @@ struct %(c_name)s { return ret +def gen_upcast(name, base): + # C makes const-correctness ugly. We have to cast away const to let + # this function work for both const and non-const obj. + return mcgen(''' + +static inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj) +{ + return (%(base)s *)obj; +} +''', + c_name=c_name(name), base=base.c_name()) + + def gen_alternate_qtypes_decl(name): return mcgen(''' @@ -267,6 +280,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor): if variants: assert not members # not implemented self.decl += gen_union(name, base, variants) + # TODO Use gen_upcast on structs too, once they have sane layout + if base: + self.decl += gen_upcast(name, base) else: self.decl += gen_struct(name, base, members) self._gen_type_cleanup(name) diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 8941963c8d..da21709714 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -347,6 +347,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, Visitor *v; Error *err = NULL; UserDefFlatUnion *tmp; + UserDefUnionBase *base; v = visitor_input_test_init(data, "{ 'enum1': 'value1', " @@ -360,6 +361,10 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, g_assert_cmpstr(tmp->string, ==, "str"); g_assert_cmpint(tmp->integer, ==, 41); g_assert_cmpint(tmp->value1->boolean, ==, true); + + base = qapi_UserDefFlatUnion_base(tmp); + g_assert(&base->enum1 == &tmp->enum1); + qapi_free_UserDefFlatUnion(tmp); }