summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2015-09-29 16:21:04 -0600
committerMarkus Armbruster <armbru@redhat.com>2015-10-12 18:44:54 +0200
commit7b2a5c2f9a52c4a08630fa741052f03fe5d3cc8a (patch)
tree30675534061aa56e73166eadfd0ebad57113a16b /scripts
parentd220fbcd1db2097de5ff3037e85317fcb5433e4e (diff)
qapi: Avoid assertion failure on union 'type' collision
The previous commit added two tests that triggered an assertion failure. It's fairly straightforward to avoid the failure by just outright forbidding the collision between a union's tag values and its discriminator name (including the implicit name 'kind' supplied for simple unions [*]). Ultimately, we'd like to move the collision detection into QAPISchema*.check(), but for now it is easier just to enhance the existing checks. [*] Of course, down the road, we have plans to rename the simple union tag name to 'type' to match the QMP wire name, but the idea of the collision will still be present even then. Technically, we could avoid the collision by naming the C union members representing each enum value as '_case_value' rather than 'value'; but until we have an actual qapi client (and not just our testsuite) that has a legitimate reason to match a case label to the name of a QMP key and needs the name munging to satisfy the compiler, it's easier to just reject the qapi as invalid. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1443565276-4535-7-git-send-email-eblake@redhat.com> [Polished a few comments] Signed-off-by: Markus Armbruster <armbru@redhat.com>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi.py10
1 files changed, 8 insertions, 2 deletions
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 4b5d574e0d..8d2681b24b 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -544,7 +544,7 @@ def check_union(expr, expr_info):
base = expr.get('base')
discriminator = expr.get('discriminator')
members = expr['data']
- values = {'MAX': '(automatic)'}
+ values = {'MAX': '(automatic)', 'KIND': '(automatic)'}
# Two types of unions, determined by discriminator.
@@ -603,13 +603,19 @@ def check_union(expr, expr_info):
" of branch '%s'" % key)
# If the discriminator names an enum type, then all members
- # of 'data' must also be members of the enum type.
+ # of 'data' must also be members of the enum type, which in turn
+ # must not collide with the discriminator name.
if enum_define:
if key not in enum_define['enum_values']:
raise QAPIExprError(expr_info,
"Discriminator value '%s' is not found in "
"enum '%s'" %
(key, enum_define["enum_name"]))
+ if discriminator in enum_define['enum_values']:
+ raise QAPIExprError(expr_info,
+ "Discriminator name '%s' collides with "
+ "enum value in '%s'" %
+ (discriminator, enum_define["enum_name"]))
# Otherwise, check for conflicts in the generated enum
else: