aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi/common.py15
-rw-r--r--scripts/qapi/types.py2
-rw-r--r--scripts/qapi/visit.py19
3 files changed, 24 insertions, 12 deletions
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 2462fc0291..4b53f08627 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -779,13 +779,6 @@ def check_union(expr, info):
"enum '%s'"
% (key, enum_define['enum']))
- # If discriminator is user-defined, ensure all values are covered
- if enum_define:
- for value in enum_define['data']:
- if value not in members.keys():
- raise QAPISemError(info, "Union '%s' data missing '%s' branch"
- % (name, value))
-
def check_alternate(expr, info):
name = expr['alternate']
@@ -1357,6 +1350,14 @@ class QAPISchemaObjectTypeVariants(object):
self.tag_member = seen[c_name(self._tag_name)]
assert self._tag_name == self.tag_member.name
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
+ if self._tag_name: # flat union
+ # branches that are not explicitly covered get an empty type
+ cases = set([v.name for v in self.variants])
+ for val in self.tag_member.type.values:
+ if val.name not in cases:
+ v = QAPISchemaObjectTypeVariant(val.name, 'q_empty')
+ v.set_owner(self.tag_member.owner)
+ self.variants.append(v)
for v in self.variants:
v.check(schema)
# Union names must match enum values; alternate names are
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 64d9c0fb37..a599352e59 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -125,6 +125,8 @@ def gen_variants(variants):
c_name=c_name(variants.tag_member.name))
for var in variants.variants:
+ if var.type.name == 'q_empty':
+ continue
ret += mcgen('''
%(c_type)s %(c_name)s;
''',
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 3c5ea1289e..bdcafb64ee 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -81,15 +81,24 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
c_name=c_name(variants.tag_member.name))
for var in variants.variants:
- ret += mcgen('''
+ case_str = c_enum_const(variants.tag_member.type.name,
+ var.name,
+ variants.tag_member.type.prefix)
+ if var.type.name == 'q_empty':
+ # valid variant and nothing to do
+ ret += mcgen('''
+ case %(case)s:
+ break;
+''',
+ case=case_str)
+ else:
+ ret += mcgen('''
case %(case)s:
visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err);
break;
''',
- case=c_enum_const(variants.tag_member.type.name,
- var.name,
- variants.tag_member.type.prefix),
- c_type=var.type.c_name(), c_name=c_name(var.name))
+ case=case_str,
+ c_type=var.type.c_name(), c_name=c_name(var.name))
ret += mcgen('''
default: