qapi: Require boxed for conditional command and event arguments
The C code generator fails to honor 'if' conditions of command and
event arguments.
For instance, tests/qapi-schema/qapi-schema-test.json has
{ 'event': 'TEST_IF_EVENT',
'data': { 'foo': 'TestIfStruct',
'bar': { 'type': ['str'], 'if': 'TEST_IF_EVT_ARG' } },
'if': { 'all': ['TEST_IF_EVT', 'TEST_IF_STRUCT'] } }
Generated tests/test-qapi-events.h fails to honor the TEST_IF_EVT_ARG
condition:
#if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
void qapi_event_send_test_if_event(TestIfStruct *foo, strList *bar);
#endif /* defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT) */
Only uses so far are in tests/.
We could fix the generator to emit something like
#if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)
void qapi_event_send_test_if_event(TestIfStruct *foo
#if defined(TEST_IF_EVT_ARG)
, strList *bar
#endif
);
#endif /* defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT) */
Ugly. Calls become similarly ugly. Not worth fixing.
Conditional arguments work fine with 'boxed': true, simply because
complex types with conditional members work fine. Not worth breaking.
Reject conditional arguments unless boxed.
Move the tests cases covering unboxed conditional arguments out of
tests/qapi-schema/qapi-schema-test.json. Cover boxed conditional
arguments there instead.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20230316071325.492471-15-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
@@ -486,6 +486,10 @@ class QAPISchemaObjectType(QAPISchemaType):
|
||||
assert self.members is not None
|
||||
return not self.members and not self.variants
|
||||
|
||||
def has_conditional_members(self):
|
||||
assert self.members is not None
|
||||
return any(m.ifcond.is_present() for m in self.members)
|
||||
|
||||
def c_name(self):
|
||||
assert self.name != 'q_empty'
|
||||
return super().c_name()
|
||||
@@ -817,6 +821,11 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
||||
self.info,
|
||||
"command's 'data' can take %s only with 'boxed': true"
|
||||
% self.arg_type.describe())
|
||||
self.arg_type.check(schema)
|
||||
if self.arg_type.has_conditional_members() and not self.boxed:
|
||||
raise QAPISemError(
|
||||
self.info,
|
||||
"conditional command arguments require 'boxed': true")
|
||||
if self._ret_type_name:
|
||||
self.ret_type = schema.resolve_type(
|
||||
self._ret_type_name, self.info, "command's 'returns'")
|
||||
@@ -872,6 +881,11 @@ class QAPISchemaEvent(QAPISchemaEntity):
|
||||
self.info,
|
||||
"event's 'data' can take %s only with 'boxed': true"
|
||||
% self.arg_type.describe())
|
||||
self.arg_type.check(schema)
|
||||
if self.arg_type.has_conditional_members() and not self.boxed:
|
||||
raise QAPISemError(
|
||||
self.info,
|
||||
"conditional event arguments require 'boxed': true")
|
||||
|
||||
def connect_doc(self, doc=None):
|
||||
super().connect_doc(doc)
|
||||
|
||||
Reference in New Issue
Block a user