qapi: Permit 'boxed' with empty type
authorMarkus Armbruster <armbru@redhat.com>
Fri, 13 Sep 2019 20:13:41 +0000 (22:13 +0200)
committerMarkus Armbruster <armbru@redhat.com>
Tue, 24 Sep 2019 12:07:22 +0000 (14:07 +0200)
We reject empty types with 'boxed': true.  We don't really need that
to work, but making it work is actually simpler than rejecting it, so
do that.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190913201349.24332-9-armbru@redhat.com>

scripts/qapi/commands.py
scripts/qapi/common.py
scripts/qapi/events.py
tests/Makefile.include
tests/qapi-schema/args-boxed-empty.err [deleted file]
tests/qapi-schema/args-boxed-empty.exit [deleted file]
tests/qapi-schema/args-boxed-empty.json [deleted file]
tests/qapi-schema/args-boxed-empty.out [deleted file]
tests/qapi-schema/qapi-schema-test.json
tests/qapi-schema/qapi-schema-test.out
tests/test-qmp-cmds.c

index b929e07be440f70a5384f185179e840a4de97ba0..7e3dd1068a12179c5779540e6830df677cc1f630 100644 (file)
@@ -30,7 +30,7 @@ def gen_call(name, arg_type, boxed, ret_type):
 
     argstr = ''
     if boxed:
-        assert arg_type and not arg_type.is_empty()
+        assert arg_type
         argstr = '&arg, '
     elif arg_type:
         assert not arg_type.variants
@@ -96,7 +96,7 @@ def gen_marshal_decl(name):
 
 
 def gen_marshal(name, arg_type, boxed, ret_type):
-    have_args = arg_type and not arg_type.is_empty()
+    have_args = boxed or (arg_type and not arg_type.is_empty())
 
     ret = mcgen('''
 
index 0fb1d1956a5821ea63c250fa1f675c18397a48f5..c5c71287c3ed008000d792163cef3bb61d3b6776 100644 (file)
@@ -1687,12 +1687,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
             self.arg_type = schema.lookup_type(self._arg_type_name)
             assert isinstance(self.arg_type, QAPISchemaObjectType)
             self.arg_type.check(schema)
-            if self.boxed:
-                if self.arg_type.is_empty():
-                    raise QAPISemError(self.info,
-                                       "Cannot use 'boxed' with empty type")
-            else:
-                assert not self.arg_type.variants
+            assert not self.arg_type.variants or self.boxed
         elif self.boxed:
             raise QAPISemError(self.info, "Use of 'boxed' requires 'data'")
         if self._ret_type_name:
@@ -1721,12 +1716,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
             self.arg_type = schema.lookup_type(self._arg_type_name)
             assert isinstance(self.arg_type, QAPISchemaObjectType)
             self.arg_type.check(schema)
-            if self.boxed:
-                if self.arg_type.is_empty():
-                    raise QAPISemError(self.info,
-                                       "Cannot use 'boxed' with empty type")
-            else:
-                assert not self.arg_type.variants
+            assert not self.arg_type.variants or self.boxed
         elif self.boxed:
             raise QAPISemError(self.info, "Use of 'boxed' requires 'data'")
 
index b732581046aa05074aaaec4d84a72ae2ea1c2633..e0abfef7b05ff7b5bfb89e3e786101bd13b86fe1 100644 (file)
@@ -65,6 +65,8 @@ def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit):
     # practice, we can rename our local variables with a leading _ prefix,
     # or split the code into a wrapper function that creates a boxed
     # 'param' object then calls another to do the real work.
+    have_args = boxed or (arg_type and not arg_type.is_empty())
+
     ret = mcgen('''
 
 %(proto)s
@@ -73,15 +75,13 @@ def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit):
 ''',
                 proto=build_event_send_proto(name, arg_type, boxed))
 
-    if arg_type and not arg_type.is_empty():
+    if have_args:
         ret += mcgen('''
     QObject *obj;
     Visitor *v;
 ''')
         if not boxed:
             ret += gen_param_var(arg_type)
-    else:
-        assert not boxed
 
     ret += mcgen('''
 
@@ -90,7 +90,7 @@ def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit):
 ''',
                  name=name)
 
-    if arg_type and not arg_type.is_empty():
+    if have_args:
         ret += mcgen('''
     v = qobject_output_visitor_new(&obj);
 ''')
@@ -121,7 +121,7 @@ def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit):
                  event_emit=event_emit,
                  c_enum=c_enum_const(event_enum_name, name))
 
-    if arg_type and not arg_type.is_empty():
+    if have_args:
         ret += mcgen('''
     visit_free(v);
 ''')
index 8585e7ed26b8f49ff8ef8172e016d0680a641829..2c3adb15307f49b2ecbdf62f59465b86010c316f 100644 (file)
@@ -311,7 +311,6 @@ qapi-schema += args-array-empty.json
 qapi-schema += args-array-unknown.json
 qapi-schema += args-bad-boxed.json
 qapi-schema += args-boxed-anon.json
-qapi-schema += args-boxed-empty.json
 qapi-schema += args-boxed-string.json
 qapi-schema += args-int.json
 qapi-schema += args-invalid.json
diff --git a/tests/qapi-schema/args-boxed-empty.err b/tests/qapi-schema/args-boxed-empty.err
deleted file mode 100644 (file)
index 039603e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type
diff --git a/tests/qapi-schema/args-boxed-empty.exit b/tests/qapi-schema/args-boxed-empty.exit
deleted file mode 100644 (file)
index d00491f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-boxed-empty.json b/tests/qapi-schema/args-boxed-empty.json
deleted file mode 100644 (file)
index 52717e0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# 'boxed' requires a non-empty type
-{ 'struct': 'Empty', 'data': {} }
-{ 'command': 'foo', 'boxed': true, 'data': 'Empty' }
diff --git a/tests/qapi-schema/args-boxed-empty.out b/tests/qapi-schema/args-boxed-empty.out
deleted file mode 100644 (file)
index e69de29..0000000
index 0fadb4ddd7c05275cc4a9447fc7007cbe1b67e52..e6dbbbd328aac09295d6e733e599f4888e2af0d5 100644 (file)
 { 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
 { 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
 { 'command': 'boxed-union', 'data': 'UserDefListUnion', 'boxed': true }
+{ 'command': 'boxed-empty', 'boxed': true, 'data': 'Empty1' }
 
 # Smoke test on out-of-band and allow-preconfig-test
 { 'command': 'test-flags-command', 'allow-oob': true, 'allow-preconfig': true }
   'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
 { 'event': 'EVENT_E', 'boxed': true, 'data': 'UserDefZero' }
 { 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefFlatUnion' }
+{ 'event': 'EVENT_G', 'boxed': true, 'data': 'Empty1' }
 
 # test that we correctly compile downstream extensions, as well as munge
 # ticklish names
index 5470a525f553ce7c0b4ae3ad1addd0f6c55af4c1..fb00a2199698408424504691ec865f0a53ce2581 100644 (file)
@@ -221,6 +221,8 @@ command boxed-struct UserDefZero -> None
    gen=True success_response=True boxed=True oob=False preconfig=False
 command boxed-union UserDefListUnion -> None
    gen=True success_response=True boxed=True oob=False preconfig=False
+command boxed-empty Empty1 -> None
+   gen=True success_response=True boxed=True oob=False preconfig=False
 command test-flags-command None -> None
    gen=True success_response=True boxed=False oob=True preconfig=True
 object UserDefOptions
@@ -254,6 +256,8 @@ event EVENT_E UserDefZero
    boxed=True
 event EVENT_F UserDefFlatUnion
    boxed=True
+event EVENT_G Empty1
+   boxed=True
 enum __org.qemu_x-Enum
     member __org.qemu_x-value
 object __org.qemu_x-Base
index ab389f42da8304757c653039a855c9310fff8e89..36fdf5b1154f8275da77be04e8e159e4e04747b6 100644 (file)
@@ -97,6 +97,10 @@ void qmp_boxed_union(UserDefListUnion *arg, Error **errp)
 {
 }
 
+void qmp_boxed_empty(Empty1 *arg, Error **errp)
+{
+}
+
 __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
                                               __org_qemu_x_StructList *b,
                                               __org_qemu_x_Union2 *c,