[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v5 14/46] qapi: Detect collisions in C member names
From: |
Eric Blake |
Subject: |
[Qemu-devel] [PATCH v5 14/46] qapi: Detect collisions in C member names |
Date: |
Mon, 21 Sep 2015 15:57:30 -0600 |
Detect attempts to declare two object members that would result
in the same C member name, by keying the 'seen' dictionary off
of the C name rather than the qapi name. As this is the first
error raised within the QapiSchema check() methods, we also have
to pass 'info' around through the call stack, and fix the overall
'try' to check for errors detected during the check() phase.
The resulting error messages demonstrate the utility of the
.describe() method added previously.
Signed-off-by: Eric Blake <address@hidden>
---
scripts/qapi.py | 44 +++++++++++++++----------
tests/qapi-schema/args-name-clash.err | 1 +
tests/qapi-schema/args-name-clash.exit | 2 +-
tests/qapi-schema/args-name-clash.json | 2 +-
tests/qapi-schema/args-name-clash.out | 6 ----
tests/qapi-schema/flat-union-branch-clash2.err | 1 +
tests/qapi-schema/flat-union-branch-clash2.exit | 2 +-
tests/qapi-schema/flat-union-branch-clash2.json | 2 +-
tests/qapi-schema/flat-union-branch-clash2.out | 14 --------
9 files changed, 33 insertions(+), 41 deletions(-)
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 6bc13f1..0a0ac90 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -103,6 +103,7 @@ class QAPISchemaError(Exception):
class QAPIExprError(Exception):
def __init__(self, expr_info, msg):
Exception.__init__(self)
+ assert expr_info
self.info = expr_info
self.msg = msg
@@ -956,11 +957,12 @@ class QAPISchemaObjectType(QAPISchemaType):
members = []
seen = {}
for m in members:
- seen[m.name] = m
+ assert m.c_name() not in seen
+ seen[m.c_name()] = m
for m in self.local_members:
- m.check(schema, members, seen)
+ m.check(schema, self._info, members, seen)
if self.variants:
- self.variants.check(schema, members, seen)
+ self.variants.check(schema, self._info, members, seen)
self.members = members
def is_implicit(self):
@@ -997,12 +999,19 @@ class QAPISchemaObjectTypeMember(object):
self.optional = optional
self._owner = owner
- def check(self, schema, all_members, seen):
- assert self.name not in seen
+ def check(self, schema, info, all_members, seen):
+ if self.c_name() in seen:
+ raise QAPIExprError(info,
+ "%s collides with %s"
+ % (self.describe(),
+ seen[self.c_name()].describe()))
self.type = schema.lookup_type(self._type_name)
assert self.type
all_members.append(self)
- seen[self.name] = self
+ seen[self.c_name()] = self
+
+ def c_name(self):
+ return c_name(self.name)
def describe(self):
return "'%s' (member of %s)" % (self.name, self._owner)
@@ -1024,23 +1033,24 @@ class QAPISchemaObjectTypeVariants(object):
'(implicit)')
self.variants = variants
- def check(self, schema, members, seen):
+ def check(self, schema, info, members, seen):
if self.tag_name:
- self.tag_member = seen[self.tag_name]
+ self.tag_member = seen[c_name(self.tag_name)]
+ assert self.tag_name == self.tag_member.name
else:
- self.tag_member.check(schema, members, seen)
+ self.tag_member.check(schema, info, members, seen)
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
for v in self.variants:
vseen = dict(seen)
- v.check(schema, self.tag_member.type, vseen)
+ v.check(schema, info, self.tag_member.type, vseen)
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
def __init__(self, name, typ, owner):
QAPISchemaObjectTypeMember.__init__(self, name, typ, False, owner)
- def check(self, schema, tag_type, seen):
- QAPISchemaObjectTypeMember.check(self, schema, [], seen)
+ def check(self, schema, info, tag_type, seen):
+ QAPISchemaObjectTypeMember.check(self, schema, info, [], seen)
assert self.name in tag_type.values
def describe(self):
@@ -1065,7 +1075,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
self.variants = variants
def check(self, schema):
- self.variants.check(schema, [], {})
+ self.variants.check(schema, self._info, [], {})
def json_type(self):
return 'value'
@@ -1122,13 +1132,13 @@ class QAPISchema(object):
def __init__(self, fname):
try:
self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
+ self._entity_dict = {}
+ self._def_predefineds()
+ self._def_exprs()
+ self.check()
except (QAPISchemaError, QAPIExprError), err:
print >>sys.stderr, err
exit(1)
- self._entity_dict = {}
- self._def_predefineds()
- self._def_exprs()
- self.check()
def _def_entity(self, ent):
assert ent.name not in self._entity_dict
diff --git a/tests/qapi-schema/args-name-clash.err
b/tests/qapi-schema/args-name-clash.err
index e69de29..743afdb 100644
--- a/tests/qapi-schema/args-name-clash.err
+++ b/tests/qapi-schema/args-name-clash.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-name-clash.json:2: 'a_b' (member of oops arguments)
collides with 'a-b' (member of oops arguments)
diff --git a/tests/qapi-schema/args-name-clash.exit
b/tests/qapi-schema/args-name-clash.exit
index 573541a..d00491f 100644
--- a/tests/qapi-schema/args-name-clash.exit
+++ b/tests/qapi-schema/args-name-clash.exit
@@ -1 +1 @@
-0
+1
diff --git a/tests/qapi-schema/args-name-clash.json
b/tests/qapi-schema/args-name-clash.json
index 19bf792..602db6a 100644
--- a/tests/qapi-schema/args-name-clash.json
+++ b/tests/qapi-schema/args-name-clash.json
@@ -1,2 +1,2 @@
-# FIXME - we should reject data with members that clash when mapped to C names
+# we reject data with members that clash when mapped to C names
{ 'command': 'oops', 'data': { 'a-b': 'str', 'a_b': 'str' } }
diff --git a/tests/qapi-schema/args-name-clash.out
b/tests/qapi-schema/args-name-clash.out
index 9b2f6e4..e69de29 100644
--- a/tests/qapi-schema/args-name-clash.out
+++ b/tests/qapi-schema/args-name-clash.out
@@ -1,6 +0,0 @@
-object :empty
-object :obj-oops-arg
- member a-b: str optional=False
- member a_b: str optional=False
-command oops :obj-oops-arg -> None
- gen=True success_response=True
diff --git a/tests/qapi-schema/flat-union-branch-clash2.err
b/tests/qapi-schema/flat-union-branch-clash2.err
index e69de29..99eacd2 100644
--- a/tests/qapi-schema/flat-union-branch-clash2.err
+++ b/tests/qapi-schema/flat-union-branch-clash2.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-branch-clash2.json:10: 'c-d' (branch of
TestUnion)' collides with 'c_d' (member of Base)
diff --git a/tests/qapi-schema/flat-union-branch-clash2.exit
b/tests/qapi-schema/flat-union-branch-clash2.exit
index 573541a..d00491f 100644
--- a/tests/qapi-schema/flat-union-branch-clash2.exit
+++ b/tests/qapi-schema/flat-union-branch-clash2.exit
@@ -1 +1 @@
-0
+1
diff --git a/tests/qapi-schema/flat-union-branch-clash2.json
b/tests/qapi-schema/flat-union-branch-clash2.json
index b3eefb3..b0dd85e 100644
--- a/tests/qapi-schema/flat-union-branch-clash2.json
+++ b/tests/qapi-schema/flat-union-branch-clash2.json
@@ -1,4 +1,4 @@
-# FIXME: we should check for no duplicate C names between branches and base
+# we check for no duplicate C names between branches and base
{ 'enum': 'TestEnum',
'data': [ 'base', 'c-d' ] }
{ 'struct': 'Base',
diff --git a/tests/qapi-schema/flat-union-branch-clash2.out
b/tests/qapi-schema/flat-union-branch-clash2.out
index 8e0da73..e69de29 100644
--- a/tests/qapi-schema/flat-union-branch-clash2.out
+++ b/tests/qapi-schema/flat-union-branch-clash2.out
@@ -1,14 +0,0 @@
-object :empty
-object Base
- member enum1: TestEnum optional=False
- member c_d: str optional=True
-object Branch1
- member string: str optional=False
-object Branch2
- member value: int optional=False
-enum TestEnum ['base', 'c-d']
-object TestUnion
- base Base
- tag enum1
- case base: Branch1
- case c-d: Branch2
--
2.4.3
- Re: [Qemu-devel] [PATCH v5 09/46] qapi: Use consistent generated code patterns, (continued)
- [Qemu-devel] [PATCH v5 10/46] qapi: Merge generation of per-member visits, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 11/46] qapi: Don't use info as witness of implicit object type, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 12/46] qapi: Track location that created an implicit type, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 14/46] qapi: Detect collisions in C member names,
Eric Blake <=
- [Qemu-devel] [PATCH v5 16/46] qapi: Detect base class loops, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 15/46] qapi: Defer duplicate member checks to schema check(), Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 13/46] qapi: Track owner of each object member, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 17/46] qapi: Provide nicer array names in introspection, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 18/46] qapi-introspect: Guarantee particular sorting, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 20/46] qapi: Fix alternates that accept 'number' but not 'int', Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 21/46] qmp: Fix reference-counting of qnull on empty output visit, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 19/46] qapi: Simplify visiting of alternate types, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 22/46] qapi: Don't abuse stack to track qmp-output root, Eric Blake, 2015/09/21
- [Qemu-devel] [PATCH v5 26/46] qapi: Test failure in middle of array parse, Eric Blake, 2015/09/21