qapi: Generate a nicer struct for flat unions
The struct generated for a flat union is weird: the members of its base are at the end, except for the union tag, which is at the beginning. Example: qapi-schema-test.json has { 'struct': 'UserDefUnionBase', 'data': { 'string': 'str', 'enum1': 'EnumOne' } } { 'union': 'UserDefFlatUnion', 'base': 'UserDefUnionBase', 'discriminator': 'enum1', 'data': { 'value1' : 'UserDefA', 'value2' : 'UserDefB', 'value3' : 'UserDefB' } } We generate: struct UserDefFlatUnion { EnumOne enum1; union { void *data; UserDefA *value1; UserDefB *value2; UserDefB *value3; }; char *string; }; Change to put all base members at the beginning, unadulterated. Not only is this easier to understand, it also permits casting the flat union to its base, if that should become useful. We now generate: struct UserDefFlatUnion { /* Members inherited from UserDefUnionBase: */ char *string; EnumOne enum1; /* Own members: */ union { /* union tag is @enum1 */ void *data; UserDefA *value1; UserDefB *value2; UserDefB *value3; }; }; Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
0f61af3eb3
commit
1e6c1616a9
|
@ -200,13 +200,30 @@ def generate_union(expr, meta):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
struct %(name)s
|
struct %(name)s
|
||||||
{
|
{
|
||||||
%(discriminator_type_name)s %(discriminator)s;
|
''',
|
||||||
union {
|
name=name)
|
||||||
|
if base:
|
||||||
|
ret += mcgen('''
|
||||||
|
/* Members inherited from %(c_name)s: */
|
||||||
|
''',
|
||||||
|
c_name=c_name(base))
|
||||||
|
base_fields = find_struct(base)['data']
|
||||||
|
ret += generate_struct_fields(base_fields)
|
||||||
|
ret += mcgen('''
|
||||||
|
/* Own members: */
|
||||||
|
''')
|
||||||
|
else:
|
||||||
|
assert not discriminator
|
||||||
|
ret += mcgen('''
|
||||||
|
%(discriminator_type_name)s kind;
|
||||||
|
''',
|
||||||
|
discriminator_type_name=c_name(discriminator_type_name))
|
||||||
|
|
||||||
|
ret += mcgen('''
|
||||||
|
union { /* union tag is @%(c_name)s */
|
||||||
void *data;
|
void *data;
|
||||||
''',
|
''',
|
||||||
name=name,
|
c_name=c_name(discriminator or 'kind'))
|
||||||
discriminator=c_name(discriminator or 'kind'),
|
|
||||||
discriminator_type_name=c_name(discriminator_type_name))
|
|
||||||
|
|
||||||
for key in typeinfo:
|
for key in typeinfo:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -217,17 +234,6 @@ struct %(name)s
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
};
|
};
|
||||||
''')
|
|
||||||
|
|
||||||
if base:
|
|
||||||
assert discriminator
|
|
||||||
base_fields = find_struct(base)['data'].copy()
|
|
||||||
del base_fields[discriminator]
|
|
||||||
ret += generate_struct_fields(base_fields)
|
|
||||||
else:
|
|
||||||
assert not discriminator
|
|
||||||
|
|
||||||
ret += mcgen('''
|
|
||||||
};
|
};
|
||||||
''')
|
''')
|
||||||
if meta == 'alternate':
|
if meta == 'alternate':
|
||||||
|
|
Loading…
Reference in a new issue