qapi-visit: Remove redundant functions for flat union base

The code for visiting the base class of a child struct created
visit_type_Base_fields() which covers all fields of Base; while
the code for visiting the base class of a flat union created
visit_type_Union_fields() covering all fields of the base
except the discriminator. But since the base class includes
the discriminator of a flat union, we can just visit the entire
base, without needing a separate visit of the discriminator.
Not only is consistently visiting all fields easier to
understand, it lets us share code.

The generated code in qapi-visit.c loses several now-unused
visit_type_UNION_fields(), along with changes like:

|@@ -1654,11 +1557,7 @@ void visit_type_BlockdevOptions(Visitor
| if (!*obj) {
| goto out_obj;
| }
|- visit_type_BlockdevOptions_fields(v, obj, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockdevDriver(v, &(*obj)->driver, "driver", &err);
|+ visit_type_BlockdevOptionsBase_fields(v, (BlockdevOptionsBase **)obj, &err);
| if (err) {
| goto out_obj;
| }

and forward declarations where needed. Note that the cast of obj
to BASE ** is necessary to call visit_type_BASE_fields() (and we
can't use our upcast wrappers, because those work on pointers while
we have a pointer-to-pointer).

Backports commit 5c5e51a05b567fd48fb155d94ca6f7679dd0d478 from qemu
This commit is contained in:
Eric Blake 2018-02-19 19:18:49 -05:00 committed by Lioncash
parent 6a9cbbeaed
commit 7be2bc687d
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -225,8 +225,7 @@ def gen_visit_union(name, base, variants):
ret = ''
if base:
members = [m for m in base.members if m != variants.tag_member]
ret += gen_visit_struct_fields(name, None, members)
ret += gen_visit_fields_decl(base)
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
@ -251,31 +250,30 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error
if base:
ret += mcgen('''
visit_type_%(c_name)s_fields(v, obj, &err);
visit_type_%(c_name)s_fields(v, (%(c_name)s **)obj, &err);
''',
c_name=c_name(name))
ret += gen_err_check(label='out_obj')
tag_key = variants.tag_member.name
if not variants.tag_name:
# we pointlessly use a different key for simple unions
tag_key = 'type'
c_name=base.c_name())
else:
ret += mcgen('''
visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err);
if (err) {
goto out_obj;
}
if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
goto out_obj;
}
switch ((*obj)->%(c_name)s) {
''',
c_type=variants.tag_member.type.c_name(),
# TODO ugly special case for simple union
# Use same tag name in C as on the wire to get rid of
# it, then: c_name=c_name(variants.tag_member.name)
c_name=c_name(variants.tag_name or 'kind'),
name=tag_key)
c_name='kind',
name=variants.tag_member.name)
ret += gen_err_check(label='out_obj')
ret += mcgen('''
if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
goto out_obj;
}
switch ((*obj)->%(c_name)s) {
''',
# TODO ugly special case for simple union
# Use same tag name in C as on the wire to get rid of
# it, then: c_name=c_name(variants.tag_member.name)
c_name=c_name(variants.tag_name or 'kind'))
for var in variants.variants:
# TODO ugly special case for simple union