aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-06-22 17:08:57 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-06-22 17:08:58 +0100
commit7ed14cbf3cf083f125c079bd02b3215941853830 (patch)
treea845e5314ea1b5af5aa4a4b9c9af7d9c2aa9605c
parent5fce31220003bbe1b4c7faa0dbf92d131b0a413b (diff)
parentbe25fcc4d2faeb3ffa8db813272963bae659c4c2 (diff)
downloadqemu-7ed14cbf3cf083f125c079bd02b3215941853830.zip
qemu-7ed14cbf3cf083f125c079bd02b3215941853830.tar.gz
qemu-7ed14cbf3cf083f125c079bd02b3215941853830.tar.bz2
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2018-06-22' into staging
QAPI patches for 2018-06-22 # gpg: Signature made Fri 22 Jun 2018 15:36:22 BST # gpg: using RSA key 3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2018-06-22: MAINTAINERS: Update QAPI stanza for commit fb0bc835e56 qapi/introspect: Eliminate pointless variable in .visit_end() Revert commit d4e5ec877ca qapi: Open files with encoding='utf-8' qapi: remove empty flat union branches and types qapi: allow empty branches in flat unions tests: Add QDict clone-flatten test qdict: Make qdict_flatten() shallow-clone-friendly qapi/events: generate event enum in main module qapi/visit: remove useless prefix argument Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile6
-rw-r--r--block/qcow2.c1
-rw-r--r--cpus.c2
-rw-r--r--docs/devel/qapi-code-gen.txt8
-rw-r--r--qapi/block-core.json52
-rw-r--r--qapi/crypto.json13
-rw-r--r--qapi/misc.json46
-rw-r--r--qapi/net.json12
-rw-r--r--qapi/ui.json19
-rw-r--r--qobject/block-qdict.c19
-rw-r--r--scripts/qapi/common.py32
-rw-r--r--scripts/qapi/events.py5
-rw-r--r--scripts/qapi/introspect.py5
-rw-r--r--scripts/qapi/types.py2
-rw-r--r--scripts/qapi/visit.py21
-rw-r--r--tests/Makefile.include7
-rw-r--r--tests/check-block-qdict.c33
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.err1
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.exit1
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.json9
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.out0
-rw-r--r--tests/qapi-schema/qapi-schema-test.json6
-rw-r--r--tests/qapi-schema/qapi-schema-test.out3
24 files changed, 116 insertions, 190 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index b8b4e60..2874ddc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1625,7 +1625,8 @@ F: tests/test-*-visitor.c
F: tests/test-qapi-*.c
F: tests/test-qmp-*.c
F: tests/test-visitor-serialization.c
-F: scripts/qapi*
+F: scripts/qapi-gen.py
+F: scripts/qapi/*
F: docs/devel/qapi*
T: git git://repo.or.cz/qemu/armbru.git qapi-next
diff --git a/Makefile b/Makefile
index e46f2b6..7ed9cc4 100644
--- a/Makefile
+++ b/Makefile
@@ -20,8 +20,6 @@ ifneq ($(wildcard config-host.mak),)
all:
include config-host.mak
-PYTHON_UTF8 = LC_ALL= LANG=C LC_CTYPE=en_US.UTF-8 $(PYTHON)
-
git-submodule-update:
.PHONY: git-submodule-update
@@ -576,7 +574,7 @@ qga/qapi-generated/qga-qapi-commands.h qga/qapi-generated/qga-qapi-commands.c \
qga/qapi-generated/qga-qapi-doc.texi: \
qga/qapi-generated/qapi-gen-timestamp ;
qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
- $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
-o qga/qapi-generated -p "qga-" $<, \
"GEN","$(@:%-timestamp=%)")
@>$@
@@ -676,7 +674,7 @@ qapi/qapi-introspect.h qapi/qapi-introspect.c \
qapi/qapi-doc.texi: \
qapi-gen-timestamp ;
qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
- $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
-o "qapi" -b $<, \
"GEN","$(@:%-timestamp=%)")
@>$@
diff --git a/block/qcow2.c b/block/qcow2.c
index 945132f..a3a3aa2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4166,7 +4166,6 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
switch (encrypt_info->format) {
case Q_CRYPTO_BLOCK_FORMAT_QCOW:
qencrypt->format = BLOCKDEV_QCOW2_ENCRYPTION_FORMAT_AES;
- qencrypt->u.aes = encrypt_info->u.qcow;
break;
case Q_CRYPTO_BLOCK_FORMAT_LUKS:
qencrypt->format = BLOCKDEV_QCOW2_ENCRYPTION_FORMAT_LUKS;
diff --git a/cpus.c b/cpus.c
index d1f1629..19c5d37 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2273,8 +2273,6 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
info->value->target = target;
if (target == SYS_EMU_TARGET_S390X) {
cpustate_to_cpuinfo_s390(&info->value->u.s390x, cpu);
- } else {
- /* do nothing for @CpuInfoOther */
}
if (!cur_item) {
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 1366228..88a70e4 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -496,9 +496,11 @@ Resulting in these JSON objects:
Notice that in a flat union, the discriminator name is controlled by
the user, but because it must map to a base member with enum type, the
-code generator can ensure that branches exist for all values of the
-enum (although the order of the keys need not match the declaration of
-the enum). In the resulting generated C data types, a flat union is
+code generator ensures that branches match the existing values of the
+enum. The order of the keys need not match the declaration of the enum.
+The keys need not cover all possible enum values. Omitted enum values
+are still valid branches that add no additional members to the data type.
+In the resulting generated C data types, a flat union is
represented as a struct with the base members included directly, and
then a union of structures for each branch of the struct.
diff --git a/qapi/block-core.json b/qapi/block-core.json
index cc3ede0..577ce5e 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -52,8 +52,7 @@
{ 'union': 'ImageInfoSpecificQCow2Encryption',
'base': 'ImageInfoSpecificQCow2EncryptionBase',
'discriminator': 'format',
- 'data': { 'aes': 'QCryptoBlockInfoQCow',
- 'luks': 'QCryptoBlockInfoLUKS' } }
+ 'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
##
# @ImageInfoSpecificQCow2:
@@ -2878,16 +2877,6 @@
'hash': 'str' }}
##
-# @SshHostKeyDummy:
-#
-# For those union branches that don't need additional fields.
-#
-# Since: 2.12
-##
-{ 'struct': 'SshHostKeyDummy',
- 'data': {} }
-
-##
# @SshHostKeyCheck:
#
# Since: 2.12
@@ -2895,9 +2884,7 @@
{ 'union': 'SshHostKeyCheck',
'base': { 'mode': 'SshHostKeyCheckMode' },
'discriminator': 'mode',
- 'data': { 'none': 'SshHostKeyDummy',
- 'hash': 'SshHostKeyHash',
- 'known_hosts': 'SshHostKeyDummy' } }
+ 'data': { 'hash': 'SshHostKeyHash' } }
##
# @BlockdevOptionsSsh:
@@ -4076,15 +4063,6 @@
'*force-size': 'bool' } }
##
-# @BlockdevCreateNotSupported:
-#
-# This is used for all drivers that don't support creating images.
-#
-# Since: 2.12
-##
-{ 'struct': 'BlockdevCreateNotSupported', 'data': {}}
-
-##
# @BlockdevCreateOptions:
#
# Options for creating an image format on a given node.
@@ -4098,44 +4076,20 @@
'driver': 'BlockdevDriver' },
'discriminator': 'driver',
'data': {
- 'blkdebug': 'BlockdevCreateNotSupported',
- 'blkverify': 'BlockdevCreateNotSupported',
- 'bochs': 'BlockdevCreateNotSupported',
- 'cloop': 'BlockdevCreateNotSupported',
- 'copy-on-read': 'BlockdevCreateNotSupported',
- 'dmg': 'BlockdevCreateNotSupported',
'file': 'BlockdevCreateOptionsFile',
- 'ftp': 'BlockdevCreateNotSupported',
- 'ftps': 'BlockdevCreateNotSupported',
'gluster': 'BlockdevCreateOptionsGluster',
- 'host_cdrom': 'BlockdevCreateNotSupported',
- 'host_device': 'BlockdevCreateNotSupported',
- 'http': 'BlockdevCreateNotSupported',
- 'https': 'BlockdevCreateNotSupported',
- 'iscsi': 'BlockdevCreateNotSupported',
'luks': 'BlockdevCreateOptionsLUKS',
- 'nbd': 'BlockdevCreateNotSupported',
'nfs': 'BlockdevCreateOptionsNfs',
- 'null-aio': 'BlockdevCreateNotSupported',
- 'null-co': 'BlockdevCreateNotSupported',
- 'nvme': 'BlockdevCreateNotSupported',
'parallels': 'BlockdevCreateOptionsParallels',
'qcow': 'BlockdevCreateOptionsQcow',
'qcow2': 'BlockdevCreateOptionsQcow2',
'qed': 'BlockdevCreateOptionsQed',
- 'quorum': 'BlockdevCreateNotSupported',
- 'raw': 'BlockdevCreateNotSupported',
'rbd': 'BlockdevCreateOptionsRbd',
- 'replication': 'BlockdevCreateNotSupported',
'sheepdog': 'BlockdevCreateOptionsSheepdog',
'ssh': 'BlockdevCreateOptionsSsh',
- 'throttle': 'BlockdevCreateNotSupported',
'vdi': 'BlockdevCreateOptionsVdi',
'vhdx': 'BlockdevCreateOptionsVhdx',
- 'vmdk': 'BlockdevCreateNotSupported',
- 'vpc': 'BlockdevCreateOptionsVpc',
- 'vvfat': 'BlockdevCreateNotSupported',
- 'vxhs': 'BlockdevCreateNotSupported'
+ 'vpc': 'BlockdevCreateOptionsVpc'
} }
##
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 288bc05..a51b434 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -297,16 +297,6 @@
'uuid': 'str',
'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }}
-##
-# @QCryptoBlockInfoQCow:
-#
-# Information about the QCow block encryption options
-#
-# Since: 2.7
-##
-{ 'struct': 'QCryptoBlockInfoQCow',
- 'data': { }}
-
##
# @QCryptoBlockInfo:
@@ -318,5 +308,4 @@
{ 'union': 'QCryptoBlockInfo',
'base': 'QCryptoBlockInfoBase',
'discriminator': 'format',
- 'data': { 'qcow': 'QCryptoBlockInfoQCow',
- 'luks': 'QCryptoBlockInfoLUKS' } }
+ 'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
diff --git a/qapi/misc.json b/qapi/misc.json
index fa86831..c6bc18a 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -396,8 +396,7 @@
'mips': 'CpuInfoMIPS',
'tricore': 'CpuInfoTricore',
's390': 'CpuInfoS390',
- 'riscv': 'CpuInfoRISCV',
- 'other': 'CpuInfoOther' } }
+ 'riscv': 'CpuInfoRISCV' } }
##
# @CpuInfoX86:
@@ -468,16 +467,6 @@
{ 'struct': 'CpuInfoRISCV', 'data': { 'pc': 'int' } }
##
-# @CpuInfoOther:
-#
-# No additional information is available about the virtual CPU
-#
-# Since: 2.6
-#
-##
-{ 'struct': 'CpuInfoOther', 'data': { } }
-
-##
# @CpuS390State:
#
# An enumeration of cpu states that can be assumed by a virtual
@@ -578,38 +567,7 @@
'arch' : 'CpuInfoArch',
'target' : 'SysEmuTarget' },
'discriminator' : 'target',
- 'data' : { 'aarch64' : 'CpuInfoOther',
- 'alpha' : 'CpuInfoOther',
- 'arm' : 'CpuInfoOther',
- 'cris' : 'CpuInfoOther',
- 'hppa' : 'CpuInfoOther',
- 'i386' : 'CpuInfoOther',
- 'lm32' : 'CpuInfoOther',
- 'm68k' : 'CpuInfoOther',
- 'microblaze' : 'CpuInfoOther',
- 'microblazeel' : 'CpuInfoOther',
- 'mips' : 'CpuInfoOther',
- 'mips64' : 'CpuInfoOther',
- 'mips64el' : 'CpuInfoOther',
- 'mipsel' : 'CpuInfoOther',
- 'moxie' : 'CpuInfoOther',
- 'nios2' : 'CpuInfoOther',
- 'or1k' : 'CpuInfoOther',
- 'ppc' : 'CpuInfoOther',
- 'ppc64' : 'CpuInfoOther',
- 'ppcemb' : 'CpuInfoOther',
- 'riscv32' : 'CpuInfoOther',
- 'riscv64' : 'CpuInfoOther',
- 's390x' : 'CpuInfoS390',
- 'sh4' : 'CpuInfoOther',
- 'sh4eb' : 'CpuInfoOther',
- 'sparc' : 'CpuInfoOther',
- 'sparc64' : 'CpuInfoOther',
- 'tricore' : 'CpuInfoOther',
- 'unicore32' : 'CpuInfoOther',
- 'x86_64' : 'CpuInfoOther',
- 'xtensa' : 'CpuInfoOther',
- 'xtensaeb' : 'CpuInfoOther' } }
+ 'data' : { 's390x' : 'CpuInfoS390' } }
##
# @query-cpus-fast:
diff --git a/qapi/net.json b/qapi/net.json
index 6b7d93c..c86f351 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -89,16 +89,6 @@
{ 'command': 'netdev_del', 'data': {'id': 'str'} }
##
-# @NetdevNoneOptions:
-#
-# Use it alone to have zero network devices.
-#
-# Since: 1.2
-##
-{ 'struct': 'NetdevNoneOptions',
- 'data': { } }
-
-##
# @NetLegacyNicOptions:
#
# Create a new Network Interface Card.
@@ -477,7 +467,6 @@
'base': { 'id': 'str', 'type': 'NetClientDriver' },
'discriminator': 'type',
'data': {
- 'none': 'NetdevNoneOptions',
'nic': 'NetLegacyNicOptions',
'user': 'NetdevUserOptions',
'tap': 'NetdevTapOptions',
@@ -530,7 +519,6 @@
'base': { 'type': 'NetLegacyOptionsType' },
'discriminator': 'type',
'data': {
- 'none': 'NetdevNoneOptions',
'nic': 'NetLegacyNicOptions',
'user': 'NetdevUserOptions',
'tap': 'NetdevTapOptions',
diff --git a/qapi/ui.json b/qapi/ui.json
index fc18a05..f48d2a0 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -996,17 +996,6 @@
##
-# @DisplayNoOpts:
-#
-# Empty struct for displays without config options.
-#
-# Since: 2.12
-#
-##
-{ 'struct' : 'DisplayNoOpts',
- 'data' : { } }
-
-##
# @DisplayGTK:
#
# GTK display options.
@@ -1068,10 +1057,4 @@
'*window-close' : 'bool',
'*gl' : 'DisplayGLMode' },
'discriminator' : 'type',
- 'data' : { 'default' : 'DisplayNoOpts',
- 'none' : 'DisplayNoOpts',
- 'gtk' : 'DisplayGTK',
- 'sdl' : 'DisplayNoOpts',
- 'egl-headless' : 'DisplayNoOpts',
- 'curses' : 'DisplayNoOpts',
- 'cocoa' : 'DisplayNoOpts' } }
+ 'data' : { 'gtk' : 'DisplayGTK' } }
diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c
index df83308..36129e7 100644
--- a/qobject/block-qdict.c
+++ b/qobject/block-qdict.c
@@ -114,19 +114,30 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
/*
* Flatten non-empty QDict and QList recursively into @target,
- * copy other objects to @target
+ * copy other objects to @target.
+ * On the root level (if @qdict == @target), remove flattened
+ * nested QDicts and QLists from @qdict.
+ *
+ * (Note that we do not need to remove entries from nested
+ * dicts or lists. Their reference count is decremented on
+ * the root level, so there are no leaks. In fact, if they
+ * have a reference count greater than one, we are probably
+ * well advised not to modify them altogether.)
*/
if (dict_val && qdict_size(dict_val)) {
qdict_flatten_qdict(dict_val, target,
new_key ? new_key : entry->key);
- qdict_del(qdict, entry->key);
+ if (target == qdict) {
+ qdict_del(qdict, entry->key);
+ }
} else if (list_val && !qlist_empty(list_val)) {
qdict_flatten_qlist(list_val, target,
new_key ? new_key : entry->key);
- qdict_del(qdict, entry->key);
+ if (target == qdict) {
+ qdict_del(qdict, entry->key);
+ }
} else if (target != qdict) {
qdict_put_obj(target, new_key, qobject_ref(value));
- qdict_del(qdict, entry->key);
}
g_free(new_key);
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 2462fc0..8b6708d 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -16,6 +16,7 @@ import errno
import os
import re
import string
+import sys
from collections import OrderedDict
builtin_types = {
@@ -340,7 +341,10 @@ class QAPISchemaParser(object):
return None
try:
- fobj = open(incl_fname, 'r')
+ if sys.version_info[0] >= 3:
+ fobj = open(incl_fname, 'r', encoding='utf-8')
+ else:
+ fobj = open(incl_fname, 'r')
except IOError as e:
raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname))
return QAPISchemaParser(fobj, previously_included, info)
@@ -779,13 +783,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 +1354,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
@@ -1492,7 +1497,11 @@ class QAPISchemaEvent(QAPISchemaEntity):
class QAPISchema(object):
def __init__(self, fname):
self._fname = fname
- parser = QAPISchemaParser(open(fname, 'r'))
+ if sys.version_info[0] >= 3:
+ f = open(fname, 'r', encoding='utf-8')
+ else:
+ f = open(fname, 'r')
+ parser = QAPISchemaParser(f)
exprs = check_exprs(parser.exprs)
self.docs = parser.docs
self._entity_list = []
@@ -2006,7 +2015,10 @@ class QAPIGen(object):
if e.errno != errno.EEXIST:
raise
fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0o666)
- f = os.fdopen(fd, 'r+')
+ if sys.version_info[0] >= 3:
+ f = open(fd, 'r+', encoding='utf-8')
+ else:
+ f = os.fdopen(fd, 'r+')
text = (self._top(fname) + self._preamble + self._body
+ self._bottom(fname))
oldtext = f.read(len(text) + 1)
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 4426861..5657524 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -180,8 +180,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
types=types))
def visit_end(self):
- self._genh.add(gen_enum(self._enum_name, self._event_names))
- self._genc.add(gen_enum_lookup(self._enum_name, self._event_names))
+ (genc, genh) = self._module[self._main_module]
+ genh.add(gen_enum(self._enum_name, self._event_names))
+ genc.add(gen_enum_lookup(self._enum_name, self._event_names))
def visit_event(self, name, info, arg_type, boxed):
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 5b6c72c..6ad198a 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -75,13 +75,10 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
def visit_end(self):
# visit the types that are actually used
- qlits = self._qlits
- self._qlits = []
for typ in self._used_types:
typ.visit(self)
# generate C
# TODO can generate awfully long lines
- qlits.extend(self._qlits)
name = c_name(self._prefix, protect=False) + 'qmp_schema_qlit'
self._genh.add(mcgen('''
#include "qapi/qmp/qlit.h"
@@ -93,7 +90,7 @@ extern const QLitObject %(c_name)s;
const QLitObject %(c_name)s = %(c_string)s;
''',
c_name=c_name(name),
- c_string=to_qlit(qlits)))
+ c_string=to_qlit(self._qlits)))
self._schema = None
self._qlits = []
self._used_types = []
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 64d9c0f..a599352 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 5d72d89..bdcafb6 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:
@@ -293,7 +302,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
#include "qapi/qmp/qerror.h"
#include "%(visit)s.h"
''',
- visit=visit, prefix=self._prefix))
+ visit=visit))
self._genh.preamble_add(mcgen('''
#include "qapi/qapi-builtin-visit.h"
#include "%(types)s.h"
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 7c48cfe..e8bb2d8 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -499,7 +499,6 @@ qapi-schema += flat-union-base-any.json
qapi-schema += flat-union-base-union.json
qapi-schema += flat-union-clash-member.json
qapi-schema += flat-union-empty.json
-qapi-schema += flat-union-incomplete-branch.json
qapi-schema += flat-union-inline.json
qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json
@@ -679,13 +678,13 @@ tests/test-qapi-events.c tests/test-qapi-events.h \
tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \
tests/test-qapi-gen-timestamp ;
tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
- $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
-o tests -p "test-" $<, \
"GEN","$(@:%-timestamp=%)")
@>$@
tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(qapi-py)
- $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
-o tests/qapi-schema -p "doc-good-" $<, \
"GEN","$@")
@mv tests/qapi-schema/doc-good-qapi-doc.texi $@
@@ -979,7 +978,7 @@ check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF)
.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
$(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts \
- $(PYTHON_UTF8) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \
+ $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \
$^ >$*.test.out 2>$*.test.err; \
echo $$? >$*.test.exit, \
"TEST","$*.out")
diff --git a/tests/check-block-qdict.c b/tests/check-block-qdict.c
index 1d20fcc..478807f 100644
--- a/tests/check-block-qdict.c
+++ b/tests/check-block-qdict.c
@@ -125,6 +125,38 @@ static void qdict_flatten_test(void)
qobject_unref(root);
}
+static void qdict_clone_flatten_test(void)
+{
+ QDict *dict1 = qdict_new();
+ QDict *dict2 = qdict_new();
+ QDict *cloned_dict1;
+
+ /*
+ * Test that we can clone and flatten
+ * { "a": { "b": 42 } }
+ * without modifying the clone.
+ */
+
+ qdict_put_int(dict2, "b", 42);
+ qdict_put(dict1, "a", dict2);
+
+ cloned_dict1 = qdict_clone_shallow(dict1);
+
+ qdict_flatten(dict1);
+
+ g_assert(qdict_size(dict1) == 1);
+ g_assert(qdict_get_int(dict1, "a.b") == 42);
+
+ g_assert(qdict_size(cloned_dict1) == 1);
+ g_assert(qdict_get_qdict(cloned_dict1, "a") == dict2);
+
+ g_assert(qdict_size(dict2) == 1);
+ g_assert(qdict_get_int(dict2, "b") == 42);
+
+ qobject_unref(dict1);
+ qobject_unref(cloned_dict1);
+}
+
static void qdict_array_split_test(void)
{
QDict *test_dict = qdict_new();
@@ -674,6 +706,7 @@ int main(int argc, char **argv)
g_test_add_func("/public/defaults", qdict_defaults_test);
g_test_add_func("/public/flatten", qdict_flatten_test);
+ g_test_add_func("/public/clone_flatten", qdict_clone_flatten_test);
g_test_add_func("/public/array_split", qdict_array_split_test);
g_test_add_func("/public/array_entries", qdict_array_entries_test);
g_test_add_func("/public/join", qdict_join_test);
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.err b/tests/qapi-schema/flat-union-incomplete-branch.err
deleted file mode 100644
index e826bf0..0000000
--- a/tests/qapi-schema/flat-union-incomplete-branch.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/flat-union-incomplete-branch.json:6: Union 'TestUnion' data missing 'value2' branch
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.exit b/tests/qapi-schema/flat-union-incomplete-branch.exit
deleted file mode 100644
index d00491f..0000000
--- a/tests/qapi-schema/flat-union-incomplete-branch.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.json b/tests/qapi-schema/flat-union-incomplete-branch.json
deleted file mode 100644
index 25a411b..0000000
--- a/tests/qapi-schema/flat-union-incomplete-branch.json
+++ /dev/null
@@ -1,9 +0,0 @@
-# we require all branches of the union to be covered
-{ 'enum': 'TestEnum',
- 'data': [ 'value1', 'value2' ] }
-{ 'struct': 'TestTypeA',
- 'data': { 'string': 'str' } }
-{ 'union': 'TestUnion',
- 'base': { 'type': 'TestEnum' },
- 'discriminator': 'type',
- 'data': { 'value1': 'TestTypeA' } }
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.out b/tests/qapi-schema/flat-union-incomplete-branch.out
deleted file mode 100644
index e69de29..0000000
--- a/tests/qapi-schema/flat-union-incomplete-branch.out
+++ /dev/null
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 46c7282..7b59817 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -39,7 +39,7 @@
'*enum1': 'EnumOne' } } # intentional forward reference
{ 'enum': 'EnumOne',
- 'data': [ 'value1', 'value2', 'value3' ] }
+ 'data': [ 'value1', 'value2', 'value3', 'value4' ] }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
@@ -76,7 +76,9 @@
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
- 'value3' : 'UserDefB' } }
+ 'value3' : 'UserDefB'
+ # 'value4' defaults to empty
+ } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 542a19c..0dbcdaf 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -23,7 +23,7 @@ object UserDefOne
base UserDefZero
member string: str optional=False
member enum1: EnumOne optional=True
-enum EnumOne ['value1', 'value2', 'value3']
+enum EnumOne ['value1', 'value2', 'value3', 'value4']
object UserDefZero
member integer: int optional=False
object UserDefTwoDictDict
@@ -52,6 +52,7 @@ object UserDefFlatUnion
case value1: UserDefA
case value2: UserDefB
case value3: UserDefB
+ case value4: q_empty
object UserDefUnionBase
base UserDefZero
member string: str optional=False