diff mbox series

[3/6] qapi: Remove wrapper struct for simple unions

Message ID 20201023101222.250147-4-kwolf@redhat.com
State New
Headers show
Series qemu-storage-daemon: QAPIfy --chardev | expand

Commit Message

Kevin Wolf Oct. 23, 2020, 10:12 a.m. UTC
Variants of simple unions are always contained in a wrapper object
called 'data' that serves no real use. When mapping a QAPI object to the
command line, this becomes very visible to users because they have to
add one or more useless 'data.' to many option names.

As a first step towards avoiding this painful CLI experience, this gets
rid of the 'data' indirection internally: The QAPI parser doesn't use a
wrapper object as the variant type any more, so the indirection is
removed from the generated C types. As a result, the C type looks the
same for flat and simple unions now. A large part of this patch is
mechanical conversion of C code to remove the 'data' indirection.

Conceptually, the important change is that variants can now have flat
and wrapped representations. For a transitioning period, we'll allow
variants to support both representations in a later patch. Eventually,
the plan is to deprecate and remove wrapped representations entirely,
unifying simple and flat unions.

The externally visible interfaces stay unchanged: Visitors still expect
the 'data' wrappers, and introspection still shows it.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 docs/devel/qapi-code-gen.txt           | 32 ++++++++----
 backends/tpm/tpm_emulator.c            |  3 +-
 backends/tpm/tpm_passthrough.c         |  4 +-
 block/crypto.c                         |  3 +-
 block/qcow2.c                          |  9 ++--
 block/vmdk.c                           | 14 ++----
 blockdev.c                             | 36 ++++++-------
 chardev/char-file.c                    |  5 +-
 chardev/char-mux.c                     |  5 +-
 chardev/char-parallel.c                |  5 +-
 chardev/char-pipe.c                    |  7 ++-
 chardev/char-ringbuf.c                 |  5 +-
 chardev/char-serial.c                  |  5 +-
 chardev/char-socket.c                  | 13 ++---
 chardev/char-stdio.c                   |  5 +-
 chardev/char-udp.c                     | 11 ++--
 chardev/char.c                         | 10 ++--
 chardev/msmouse.c                      |  4 +-
 chardev/wctablet.c                     |  4 +-
 hw/core/numa.c                         |  6 +--
 hw/display/xenfb.c                     |  8 +--
 hw/input/hid.c                         |  8 +--
 hw/input/ps2.c                         |  6 +--
 hw/input/virtio-input-hid.c            |  8 +--
 hw/mem/pc-dimm.c                       | 18 +++----
 hw/virtio/virtio-mem-pci.c             |  3 +-
 hw/virtio/virtio-pmem-pci.c            |  3 +-
 monitor/hmp-cmds.c                     | 14 +++---
 qemu-keymap.c                          |  2 +-
 replay/replay-input.c                  | 46 +++++++----------
 tests/test-char.c                      | 12 ++---
 tests/test-clone-visitor.c             | 14 +++---
 tests/test-qmp-cmds.c                  |  2 +-
 tests/test-qobject-input-visitor.c     | 24 ++++-----
 tests/test-qobject-output-visitor.c    | 24 ++++-----
 ui/console.c                           |  5 +-
 ui/input-keymap.c                      | 12 ++---
 ui/input-legacy.c                      | 12 ++---
 ui/input.c                             | 43 ++++++++--------
 util/qemu-sockets.c                    |  8 +--
 scripts/qapi/introspect.py             |  7 ++-
 scripts/qapi/schema.py                 | 48 ++++++++++++++----
 scripts/qapi/visit.py                  | 28 +++++++++++
 tests/qapi-schema/doc-good.out         |  8 +--
 tests/qapi-schema/qapi-schema-test.out | 70 +++++++-------------------
 45 files changed, 308 insertions(+), 311 deletions(-)

Comments

Marc-André Lureau Oct. 23, 2020, 10:40 a.m. UTC | #1
Hi

On Fri, Oct 23, 2020 at 2:14 PM Kevin Wolf <kwolf@redhat.com> wrote:

> Variants of simple unions are always contained in a wrapper object

> called 'data' that serves no real use. When mapping a QAPI object to the

> command line, this becomes very visible to users because they have to

> add one or more useless 'data.' to many option names.

>

> As a first step towards avoiding this painful CLI experience, this gets

> rid of the 'data' indirection internally: The QAPI parser doesn't use a

> wrapper object as the variant type any more, so the indirection is

> removed from the generated C types. As a result, the C type looks the

> same for flat and simple unions now. A large part of this patch is

> mechanical conversion of C code to remove the 'data' indirection.

>

> Conceptually, the important change is that variants can now have flat

> and wrapped representations. For a transitioning period, we'll allow

> variants to support both representations in a later patch. Eventually,

> the plan is to deprecate and remove wrapped representations entirely,

> unifying simple and flat unions.

>

> The externally visible interfaces stay unchanged: Visitors still expect

> the 'data' wrappers, and introspection still shows it.

>

> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

>


breaks the build for me:

../chardev/spice.c: In function ‘qemu_chr_open_spice_vmc’:
../chardev/spice.c:261:56: error: ‘ChardevSpiceChannel’ has no member named
‘data’
  261 |     ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
      |                                                        ^
../chardev/spice.c: In function ‘qemu_chr_open_spice_port’:
../chardev/spice.c:297:55: error: ‘ChardevSpicePort’ has no member named
‘data’
  297 |     ChardevSpicePort *spiceport = backend->u.spiceport.data;
      |                                                       ^
../chardev/spice.c: In function ‘qemu_chr_parse_spice_vmc’:
../chardev/spice.c:331:35: error: ‘ChardevSpiceChannel’ has no member named
‘data’
  331 |     spicevmc = backend->u.spicevmc.data =
g_new0(ChardevSpiceChannel, 1);
      |                                   ^
../chardev/spice.c: In function ‘qemu_chr_parse_spice_port’:
../chardev/spice.c:347:37: error: ‘ChardevSpicePort’ has no member named
‘data’
  347 |     spiceport = backend->u.spiceport.data =
g_new0(ChardevSpicePort, 1);
      |                                     ^
../ui/spice-app.c: In function ‘chr_spice_backend_new’:
../ui/spice-app.c:63:20: error: ‘ChardevSpicePort’ has no member named
‘data’
   63 |     be->u.spiceport.data = g_new0(ChardevSpicePort, 1);
      |                    ^
../ui/spice-app.c: In function ‘vc_chr_open’:
../ui/spice-app.c:86:20: error: ‘ChardevSpicePort’ has no member named
‘data’
   86 |     be->u.spiceport.data->fqdn = fqdn ?
      |                    ^
../ui/spice-app.c: In function ‘spice_app_display_init’:
../ui/spice-app.c:185:20: error: ‘ChardevSpicePort’ has no member named
‘data’
  185 |     be->u.spiceport.data->fqdn = g_strdup("org.qemu.monitor.qmp.0");
      |                    ^


> ---

>  docs/devel/qapi-code-gen.txt           | 32 ++++++++----

>  backends/tpm/tpm_emulator.c            |  3 +-

>  backends/tpm/tpm_passthrough.c         |  4 +-

>  block/crypto.c                         |  3 +-

>  block/qcow2.c                          |  9 ++--

>  block/vmdk.c                           | 14 ++----

>  blockdev.c                             | 36 ++++++-------

>  chardev/char-file.c                    |  5 +-

>  chardev/char-mux.c                     |  5 +-

>  chardev/char-parallel.c                |  5 +-

>  chardev/char-pipe.c                    |  7 ++-

>  chardev/char-ringbuf.c                 |  5 +-

>  chardev/char-serial.c                  |  5 +-

>  chardev/char-socket.c                  | 13 ++---

>  chardev/char-stdio.c                   |  5 +-

>  chardev/char-udp.c                     | 11 ++--

>  chardev/char.c                         | 10 ++--

>  chardev/msmouse.c                      |  4 +-

>  chardev/wctablet.c                     |  4 +-

>  hw/core/numa.c                         |  6 +--

>  hw/display/xenfb.c                     |  8 +--

>  hw/input/hid.c                         |  8 +--

>  hw/input/ps2.c                         |  6 +--

>  hw/input/virtio-input-hid.c            |  8 +--

>  hw/mem/pc-dimm.c                       | 18 +++----

>  hw/virtio/virtio-mem-pci.c             |  3 +-

>  hw/virtio/virtio-pmem-pci.c            |  3 +-

>  monitor/hmp-cmds.c                     | 14 +++---

>  qemu-keymap.c                          |  2 +-

>  replay/replay-input.c                  | 46 +++++++----------

>  tests/test-char.c                      | 12 ++---

>  tests/test-clone-visitor.c             | 14 +++---

>  tests/test-qmp-cmds.c                  |  2 +-

>  tests/test-qobject-input-visitor.c     | 24 ++++-----

>  tests/test-qobject-output-visitor.c    | 24 ++++-----

>  ui/console.c                           |  5 +-

>  ui/input-keymap.c                      | 12 ++---

>  ui/input-legacy.c                      | 12 ++---

>  ui/input.c                             | 43 ++++++++--------

>  util/qemu-sockets.c                    |  8 +--

>  scripts/qapi/introspect.py             |  7 ++-

>  scripts/qapi/schema.py                 | 48 ++++++++++++++----

>  scripts/qapi/visit.py                  | 28 +++++++++++

>  tests/qapi-schema/doc-good.out         |  8 +--

>  tests/qapi-schema/qapi-schema-test.out | 70 +++++++-------------------

>  45 files changed, 308 insertions(+), 311 deletions(-)

>

> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt

> index c6438c6aa9..9722c1a204 100644

> --- a/docs/devel/qapi-code-gen.txt

> +++ b/docs/devel/qapi-code-gen.txt

> @@ -310,7 +310,20 @@ The BRANCH's STRING name is the branch name.

>  The BRANCH's value defines the branch's properties, in particular its

>  type.  The form TYPE-REF is shorthand for { 'type': TYPE-REF }.

>

> -A simple union type defines a mapping from automatic discriminator

> +Each branch can have flat or wrapped representation in the Client JSON

> +Protocol.

> +

> +Wrapped representation of a branch means that it is represented by a

> +'data' member that is of the specified data type corresponding to the

> +discriminator value.

> +

> +Flat representation means that the union forms a single object that

> +contains both common members (from the base type) and the selected

> +branch's members, without any additional nesting.  The two sets of

> +member names must be disjoint.

> +

> +A simple union type automatically contains the 'type' member as a

> +discriminator and defines a mapping from automatic discriminator

>  values to data types like in this example:

>

>   { 'struct': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } }

> @@ -321,10 +334,8 @@ values to data types like in this example:

>     'data': { 'file': 'BlockdevOptionsFile',

>               'qcow2': 'BlockdevOptionsQcow2' } }

>

> -In the Client JSON Protocol, a simple union is represented by an

> -object that contains the 'type' member as a discriminator, and a

> -'data' member that is of the specified data type corresponding to the

> -discriminator value, as in these examples:

> +In the Client JSON Protocol, all simple union branches have wrapped

> +representation, as in these examples:

>

>   { "type": "file", "data": { "filename": "/some/place/my-image" } }

>   { "type": "qcow2", "data": { "backing": "/some/place/my-image",

> @@ -344,13 +355,12 @@ object, it defines common members just like a struct

> type's 'data'

>  member defines struct type members.  If it is a STRING, it names a

>  struct type whose members are the common members.

>

> -All flat union branches must be of struct type.

> +Member 'discriminator' must name a non-optional enum-typed member of

> +the base struct and defines the option that should server as the

> +discrimiator.

>

> -In the Client JSON Protocol, a flat union is represented by an object

> -with the common members (from the base type) and the selected branch's

> -members.  The two sets of member names must be disjoint.  Member

> -'discriminator' must name a non-optional enum-typed member of the base

> -struct.

> +All flat union branches must be of struct type.  They have always flat

> +representation.

>

>  The following example enhances the above simple union example by

>  adding an optional common member 'read-only', renaming the

> diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c

> index 201cd38503..7d2dc2b19d 100644

> --- a/backends/tpm/tpm_emulator.c

> +++ b/backends/tpm/tpm_emulator.c

> @@ -629,7 +629,8 @@ static TpmTypeOptions

> *tpm_emulator_get_tpm_options(TPMBackend *tb)

>      TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);

>

>      options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;

> -    options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions,

> tpm_emu->options);

> +    QAPI_CLONE_MEMBERS(TPMEmulatorOptions, &options->u.emulator,

> +                       tpm_emu->options);

>

>      return options;

>  }

> diff --git a/backends/tpm/tpm_passthrough.c

> b/backends/tpm/tpm_passthrough.c

> index 8f6f4998a5..7fa7c84f5a 100644

> --- a/backends/tpm/tpm_passthrough.c

> +++ b/backends/tpm/tpm_passthrough.c

> @@ -322,8 +322,8 @@ static TpmTypeOptions

> *tpm_passthrough_get_tpm_options(TPMBackend *tb)

>      TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);

>

>      options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;

> -    options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,

> -

>  TPM_PASSTHROUGH(tb)->options);

> +    QAPI_CLONE_MEMBERS(TPMPassthroughOptions, &options->u.passthrough,

> +                       TPM_PASSTHROUGH(tb)->options);

>

>      return options;

>  }

> diff --git a/block/crypto.c b/block/crypto.c

> index 0807557763..0e7838d70a 100644

> --- a/block/crypto.c

> +++ b/block/crypto.c

> @@ -775,8 +775,7 @@ block_crypto_get_specific_info_luks(BlockDriverState

> *bs, Error **errp)

>

>      spec_info = g_new(ImageInfoSpecific, 1);

>      spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;

> -    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);

> -    *spec_info->u.luks.data = info->u.luks;

> +    spec_info->u.luks = info->u.luks;

>

>      /* Blank out pointers we've just stolen to avoid double free */

>      memset(&info->u.luks, 0, sizeof(info->u.luks));

> diff --git a/block/qcow2.c b/block/qcow2.c

> index b05512718c..104fd8ad06 100644

> --- a/block/qcow2.c

> +++ b/block/qcow2.c

> @@ -5052,10 +5052,9 @@ static ImageInfoSpecific

> *qcow2_get_specific_info(BlockDriverState *bs,

>      spec_info = g_new(ImageInfoSpecific, 1);

>      *spec_info = (ImageInfoSpecific){

>          .type  = IMAGE_INFO_SPECIFIC_KIND_QCOW2,

> -        .u.qcow2.data = g_new0(ImageInfoSpecificQCow2, 1),

>      };

>      if (s->qcow_version == 2) {

> -        *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){

> +        spec_info->u.qcow2 = (ImageInfoSpecificQCow2){

>              .compat             = g_strdup("0.10"),

>              .refcount_bits      = s->refcount_bits,

>          };

> @@ -5068,7 +5067,7 @@ static ImageInfoSpecific

> *qcow2_get_specific_info(BlockDriverState *bs,

>              qapi_free_QCryptoBlockInfo(encrypt_info);

>              return NULL;

>          }

> -        *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){

> +        spec_info->u.qcow2 = (ImageInfoSpecificQCow2){

>              .compat             = g_strdup("1.1"),

>              .lazy_refcounts     = s->compatible_features &

>                                    QCOW2_COMPAT_LAZY_REFCOUNTS,

> @@ -5112,8 +5111,8 @@ static ImageInfoSpecific

> *qcow2_get_specific_info(BlockDriverState *bs,

>          memset(&encrypt_info->u, 0, sizeof(encrypt_info->u));

>          qapi_free_QCryptoBlockInfo(encrypt_info);

>

> -        spec_info->u.qcow2.data->has_encrypt = true;

> -        spec_info->u.qcow2.data->encrypt = qencrypt;

> +        spec_info->u.qcow2.has_encrypt = true;

> +        spec_info->u.qcow2.encrypt = qencrypt;

>      }

>

>      return spec_info;

> diff --git a/block/vmdk.c b/block/vmdk.c

> index a00dc00eb4..fc4ddcc351 100644

> --- a/block/vmdk.c

> +++ b/block/vmdk.c

> @@ -2932,18 +2932,14 @@ static ImageInfoSpecific

> *vmdk_get_specific_info(BlockDriverState *bs,

>

>      *spec_info = (ImageInfoSpecific){

>          .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,

> -        .u = {

> -            .vmdk.data = g_new0(ImageInfoSpecificVmdk, 1),

> +        .u.vmdk = (ImageInfoSpecificVmdk) {

> +            .create_type = g_strdup(s->create_type),

> +            .cid = s->cid,

> +            .parent_cid = s->parent_cid,

>          },

>      };

>

> -    *spec_info->u.vmdk.data = (ImageInfoSpecificVmdk) {

> -        .create_type = g_strdup(s->create_type),

> -        .cid = s->cid,

> -        .parent_cid = s->parent_cid,

> -    };

> -

> -    next = &spec_info->u.vmdk.data->extents;

> +    next = &spec_info->u.vmdk.extents;

>      for (i = 0; i < s->num_extents; i++) {

>          *next = g_new0(ImageInfoList, 1);

>          (*next)->value = vmdk_get_extent_info(&s->extents[i]);

> diff --git a/blockdev.c b/blockdev.c

> index fe6fb5dc1d..2602298a26 100644

> --- a/blockdev.c

> +++ b/blockdev.c

> @@ -1090,7 +1090,7 @@ void qmp_blockdev_snapshot_sync(bool has_device,

> const char *device,

>      };

>      TransactionAction action = {

>          .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,

> -        .u.blockdev_snapshot_sync.data = &snapshot,

> +        .u.blockdev_snapshot_sync = snapshot,

>      };

>      blockdev_do_action(&action, errp);

>  }

> @@ -1104,7 +1104,7 @@ void qmp_blockdev_snapshot(const char *node, const

> char *overlay,

>      };

>      TransactionAction action = {

>          .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,

> -        .u.blockdev_snapshot.data = &snapshot_data,

> +        .u.blockdev_snapshot = snapshot_data,

>      };

>      blockdev_do_action(&action, errp);

>  }

> @@ -1119,7 +1119,7 @@ void qmp_blockdev_snapshot_internal_sync(const char

> *device,

>      };

>      TransactionAction action = {

>          .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,

> -        .u.blockdev_snapshot_internal_sync.data = &snapshot,

> +        .u.blockdev_snapshot_internal_sync = snapshot,

>      };

>      blockdev_do_action(&action, errp);

>  }

> @@ -1289,7 +1289,7 @@ static void internal_snapshot_prepare(BlkActionState

> *common,

>

>      g_assert(common->action->type ==

>               TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);

> -    internal = common->action->u.blockdev_snapshot_internal_sync.data;

> +    internal = &common->action->u.blockdev_snapshot_internal_sync;

>      state = DO_UPCAST(InternalSnapshotState, common, common);

>

>      /* 1. parse input */

> @@ -1453,7 +1453,7 @@ static void external_snapshot_prepare(BlkActionState

> *common,

>      switch (action->type) {

>      case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:

>          {

> -            BlockdevSnapshot *s = action->u.blockdev_snapshot.data;

> +            BlockdevSnapshot *s = &action->u.blockdev_snapshot;

>              device = s->node;

>              node_name = s->node;

>              new_image_file = NULL;

> @@ -1462,7 +1462,7 @@ static void external_snapshot_prepare(BlkActionState

> *common,

>          break;

>      case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:

>          {

> -            BlockdevSnapshotSync *s =

> action->u.blockdev_snapshot_sync.data;

> +            BlockdevSnapshotSync *s = &action->u.blockdev_snapshot_sync;

>              device = s->has_device ? s->device : NULL;

>              node_name = s->has_node_name ? s->node_name : NULL;

>              new_image_file = s->snapshot_file;

> @@ -1507,7 +1507,7 @@ static void external_snapshot_prepare(BlkActionState

> *common,

>      }

>

>      if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {

> -        BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync.data;

> +        BlockdevSnapshotSync *s = &action->u.blockdev_snapshot_sync;

>          const char *format = s->has_format ? s->format : "qcow2";

>          enum NewImageMode mode;

>          const char *snapshot_node_name =

> @@ -1712,7 +1712,7 @@ static void drive_backup_prepare(BlkActionState

> *common, Error **errp)

>      int ret;

>

>      assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);

> -    backup = common->action->u.drive_backup.data;

> +    backup = &common->action->u.drive_backup;

>

>      if (!backup->has_mode) {

>          backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

> @@ -1907,7 +1907,7 @@ static void blockdev_backup_prepare(BlkActionState

> *common, Error **errp)

>      int ret;

>

>      assert(common->action->type ==

> TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);

> -    backup = common->action->u.blockdev_backup.data;

> +    backup = &common->action->u.blockdev_backup;

>

>      bs = bdrv_lookup_bs(backup->device, backup->device, errp);

>      if (!bs) {

> @@ -2012,7 +2012,7 @@ static void

> block_dirty_bitmap_add_prepare(BlkActionState *common,

>          return;

>      }

>

> -    action = common->action->u.block_dirty_bitmap_add.data;

> +    action = &common->action->u.block_dirty_bitmap_add;

>      /* AIO context taken and released within qmp_block_dirty_bitmap_add */

>      qmp_block_dirty_bitmap_add(action->node, action->name,

>                                 action->has_granularity,

> action->granularity,

> @@ -2033,7 +2033,7 @@ static void

> block_dirty_bitmap_add_abort(BlkActionState *common)

>      BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,

>                                               common, common);

>

> -    action = common->action->u.block_dirty_bitmap_add.data;

> +    action = &common->action->u.block_dirty_bitmap_add;

>      /* Should not be able to fail: IF the bitmap was added via .prepare(),

>       * then the node reference and bitmap name must have been valid.

>       */

> @@ -2053,7 +2053,7 @@ static void

> block_dirty_bitmap_clear_prepare(BlkActionState *common,

>          return;

>      }

>

> -    action = common->action->u.block_dirty_bitmap_clear.data;

> +    action = &common->action->u.block_dirty_bitmap_clear;

>      state->bitmap = block_dirty_bitmap_lookup(action->node,

>                                                action->name,

>                                                &state->bs,

> @@ -2098,7 +2098,7 @@ static void

> block_dirty_bitmap_enable_prepare(BlkActionState *common,

>          return;

>      }

>

> -    action = common->action->u.block_dirty_bitmap_enable.data;

> +    action = &common->action->u.block_dirty_bitmap_enable;

>      state->bitmap = block_dirty_bitmap_lookup(action->node,

>                                                action->name,

>                                                NULL,

> @@ -2136,7 +2136,7 @@ static void

> block_dirty_bitmap_disable_prepare(BlkActionState *common,

>          return;

>      }

>

> -    action = common->action->u.block_dirty_bitmap_disable.data;

> +    action = &common->action->u.block_dirty_bitmap_disable;

>      state->bitmap = block_dirty_bitmap_lookup(action->node,

>                                                action->name,

>                                                NULL,

> @@ -2174,7 +2174,7 @@ static void

> block_dirty_bitmap_merge_prepare(BlkActionState *common,

>          return;

>      }

>

> -    action = common->action->u.block_dirty_bitmap_merge.data;

> +    action = &common->action->u.block_dirty_bitmap_merge;

>

>      state->bitmap = block_dirty_bitmap_merge(action->node, action->target,

>                                               action->bitmaps,

> &state->backup,

> @@ -2192,7 +2192,7 @@ static void

> block_dirty_bitmap_remove_prepare(BlkActionState *common,

>          return;

>      }

>

> -    action = common->action->u.block_dirty_bitmap_remove.data;

> +    action = &common->action->u.block_dirty_bitmap_remove;

>

>      state->bitmap = block_dirty_bitmap_remove(action->node, action->name,

>                                                false, &state->bs, errp);

> @@ -2895,7 +2895,7 @@ void qmp_drive_backup(DriveBackup *backup, Error

> **errp)

>  {

>      TransactionAction action = {

>          .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP,

> -        .u.drive_backup.data = backup,

> +        .u.drive_backup = *backup,

>      };

>      blockdev_do_action(&action, errp);

>  }

> @@ -2918,7 +2918,7 @@ void qmp_blockdev_backup(BlockdevBackup *backup,

> Error **errp)

>  {

>      TransactionAction action = {

>          .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP,

> -        .u.blockdev_backup.data = backup,

> +        .u.blockdev_backup = *backup,

>      };

>      blockdev_do_action(&action, errp);

>  }

> diff --git a/chardev/char-file.c b/chardev/char-file.c

> index 2fd80707e5..3f0f0b6045 100644

> --- a/chardev/char-file.c

> +++ b/chardev/char-file.c

> @@ -39,7 +39,7 @@ static void qmp_chardev_open_file(Chardev *chr,

>                                    bool *be_opened,

>                                    Error **errp)

>  {

> -    ChardevFile *file = backend->u.file.data;

> +    ChardevFile *file = &backend->u.file;

>  #ifdef _WIN32

>      HANDLE out;

>      DWORD accessmode;

> @@ -100,14 +100,13 @@ static void qemu_chr_parse_file_out(QemuOpts *opts,

> ChardevBackend *backend,

>                                      Error **errp)

>  {

>      const char *path = qemu_opt_get(opts, "path");

> -    ChardevFile *file;

> +    ChardevFile *file = &backend->u.file;

>

>      backend->type = CHARDEV_BACKEND_KIND_FILE;

>      if (path == NULL) {

>          error_setg(errp, "chardev: file: no filename given");

>          return;

>      }

> -    file = backend->u.file.data = g_new0(ChardevFile, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));

>      file->out = g_strdup(path);

>

> diff --git a/chardev/char-mux.c b/chardev/char-mux.c

> index 6f980bb836..bfb4bc6b8b 100644

> --- a/chardev/char-mux.c

> +++ b/chardev/char-mux.c

> @@ -314,7 +314,7 @@ static void qemu_chr_open_mux(Chardev *chr,

>                                bool *be_opened,

>                                Error **errp)

>  {

> -    ChardevMux *mux = backend->u.mux.data;

> +    ChardevMux *mux = &backend->u.mux;

>      Chardev *drv;

>      MuxChardev *d = MUX_CHARDEV(chr);

>

> @@ -336,14 +336,13 @@ static void qemu_chr_parse_mux(QemuOpts *opts,

> ChardevBackend *backend,

>                                 Error **errp)

>  {

>      const char *chardev = qemu_opt_get(opts, "chardev");

> -    ChardevMux *mux;

> +    ChardevMux *mux = &backend->u.mux;

>

>      if (chardev == NULL) {

>          error_setg(errp, "chardev: mux: no chardev given");

>          return;

>      }

>      backend->type = CHARDEV_BACKEND_KIND_MUX;

> -    mux = backend->u.mux.data = g_new0(ChardevMux, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));

>      mux->chardev = g_strdup(chardev);

>  }

> diff --git a/chardev/char-parallel.c b/chardev/char-parallel.c

> index 05e7efbd6c..a17157a3be 100644

> --- a/chardev/char-parallel.c

> +++ b/chardev/char-parallel.c

> @@ -244,7 +244,7 @@ static void qmp_chardev_open_parallel(Chardev *chr,

>                                        bool *be_opened,

>                                        Error **errp)

>  {

> -    ChardevHostdev *parallel = backend->u.parallel.data;

> +    ChardevHostdev *parallel = &backend->u.parallel;

>      int fd;

>

>      fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);

> @@ -258,14 +258,13 @@ static void qemu_chr_parse_parallel(QemuOpts *opts,

> ChardevBackend *backend,

>                                      Error **errp)

>  {

>      const char *device = qemu_opt_get(opts, "path");

> -    ChardevHostdev *parallel;

> +    ChardevHostdev *parallel = &backend->u.parallel;

>

>      if (device == NULL) {

>          error_setg(errp, "chardev: parallel: no device path given");

>          return;

>      }

>      backend->type = CHARDEV_BACKEND_KIND_PARALLEL;

> -    parallel = backend->u.parallel.data = g_new0(ChardevHostdev, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));

>      parallel->device = g_strdup(device);

>  }

> diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c

> index 7eca5d9a56..eb19d9a526 100644

> --- a/chardev/char-pipe.c

> +++ b/chardev/char-pipe.c

> @@ -109,7 +109,7 @@ static void qemu_chr_open_pipe(Chardev *chr,

>                                 bool *be_opened,

>                                 Error **errp)

>  {

> -    ChardevHostdev *opts = backend->u.pipe.data;

> +    ChardevHostdev *opts = &backend->u.pipe;

>      const char *filename = opts->device;

>

>      if (win_chr_pipe_init(chr, filename, errp) < 0) {

> @@ -124,7 +124,7 @@ static void qemu_chr_open_pipe(Chardev *chr,

>                                 bool *be_opened,

>                                 Error **errp)

>  {

> -    ChardevHostdev *opts = backend->u.pipe.data;

> +    ChardevHostdev *opts = &backend->u.pipe;

>      int fd_in, fd_out;

>      char *filename_in;

>      char *filename_out;

> @@ -158,14 +158,13 @@ static void qemu_chr_parse_pipe(QemuOpts *opts,

> ChardevBackend *backend,

>                                  Error **errp)

>  {

>      const char *device = qemu_opt_get(opts, "path");

> -    ChardevHostdev *dev;

> +    ChardevHostdev *dev = &backend->u.pipe;

>

>      if (device == NULL) {

>          error_setg(errp, "chardev: pipe: no device path given");

>          return;

>      }

>      backend->type = CHARDEV_BACKEND_KIND_PIPE;

> -    dev = backend->u.pipe.data = g_new0(ChardevHostdev, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));

>      dev->device = g_strdup(device);

>  }

> diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c

> index d40d21d3cf..0ef2a17f90 100644

> --- a/chardev/char-ringbuf.c

> +++ b/chardev/char-ringbuf.c

> @@ -97,7 +97,7 @@ static void qemu_chr_open_ringbuf(Chardev *chr,

>                                    bool *be_opened,

>                                    Error **errp)

>  {

> -    ChardevRingbuf *opts = backend->u.ringbuf.data;

> +    ChardevRingbuf *opts = &backend->u.ringbuf;

>      RingBufChardev *d = RINGBUF_CHARDEV(chr);

>

>      d->size = opts->has_size ? opts->size : 65536;

> @@ -210,10 +210,9 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts,

> ChardevBackend *backend,

>                                     Error **errp)

>  {

>      int val;

> -    ChardevRingbuf *ringbuf;

> +    ChardevRingbuf *ringbuf = &backend->u.ringbuf;

>

>      backend->type = CHARDEV_BACKEND_KIND_RINGBUF;

> -    ringbuf = backend->u.ringbuf.data = g_new0(ChardevRingbuf, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));

>

>      val = qemu_opt_get_size(opts, "size", 0);

> diff --git a/chardev/char-serial.c b/chardev/char-serial.c

> index 7c3d84ae24..baec955ecf 100644

> --- a/chardev/char-serial.c

> +++ b/chardev/char-serial.c

> @@ -263,7 +263,7 @@ static void qmp_chardev_open_serial(Chardev *chr,

>                                      bool *be_opened,

>                                      Error **errp)

>  {

> -    ChardevHostdev *serial = backend->u.serial.data;

> +    ChardevHostdev *serial = &backend->u.serial;

>      int fd;

>

>      fd = qmp_chardev_open_file_source(serial->device, O_RDWR | O_NONBLOCK,

> @@ -283,14 +283,13 @@ static void qemu_chr_parse_serial(QemuOpts *opts,

> ChardevBackend *backend,

>                                    Error **errp)

>  {

>      const char *device = qemu_opt_get(opts, "path");

> -    ChardevHostdev *serial;

> +    ChardevHostdev *serial = &backend->u.serial;

>

>      if (device == NULL) {

>          error_setg(errp, "chardev: serial/tty: no device path given");

>          return;

>      }

>      backend->type = CHARDEV_BACKEND_KIND_SERIAL;

> -    serial = backend->u.serial.data = g_new0(ChardevHostdev, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));

>      serial->device = g_strdup(device);

>  }

> diff --git a/chardev/char-socket.c b/chardev/char-socket.c

> index 95e45812d5..5332439d34 100644

> --- a/chardev/char-socket.c

> +++ b/chardev/char-socket.c

> @@ -1301,7 +1301,7 @@ static void qmp_chardev_open_socket(Chardev *chr,

>                                      Error **errp)

>  {

>      SocketChardev *s = SOCKET_CHARDEV(chr);

> -    ChardevSocket *sock = backend->u.socket.data;

> +    ChardevSocket *sock = &backend->u.socket;

>      bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;

>      bool is_listen      = sock->has_server  ? sock->server  : true;

>      bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;

> @@ -1403,7 +1403,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts,

> ChardevBackend *backend,

>      }

>

>      backend->type = CHARDEV_BACKEND_KIND_SOCKET;

> -    sock = backend->u.socket.data = g_new0(ChardevSocket, 1);

> +    sock = &backend->u.socket;

>      qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));

>

>      sock->has_nodelay = qemu_opt_get(opts, "delay");

> @@ -1435,16 +1435,14 @@ static void qemu_chr_parse_socket(QemuOpts *opts,

> ChardevBackend *backend,

>

>      addr = g_new0(SocketAddressLegacy, 1);

>      if (path) {

> -        UnixSocketAddress *q_unix;

> +        UnixSocketAddress *q_unix = &addr->u.q_unix;

>          addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;

> -        q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);

>          q_unix->path = g_strdup(path);

>          q_unix->tight = tight;

>          q_unix->abstract = abstract;

>      } else if (host) {

>          addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;

> -        addr->u.inet.data = g_new(InetSocketAddress, 1);

> -        *addr->u.inet.data = (InetSocketAddress) {

> +        addr->u.inet = (InetSocketAddress) {

>              .host = g_strdup(host),

>              .port = g_strdup(port),

>              .has_to = qemu_opt_get(opts, "to"),

> @@ -1456,8 +1454,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts,

> ChardevBackend *backend,

>          };

>      } else if (fd) {

>          addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;

> -        addr->u.fd.data = g_new(String, 1);

> -        addr->u.fd.data->str = g_strdup(fd);

> +        addr->u.fd.str = g_strdup(fd);

>      } else {

>          g_assert_not_reached();

>      }

> diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c

> index 403da308c9..81ee655a21 100644

> --- a/chardev/char-stdio.c

> +++ b/chardev/char-stdio.c

> @@ -87,7 +87,7 @@ static void qemu_chr_open_stdio(Chardev *chr,

>                                  bool *be_opened,

>                                  Error **errp)

>  {

> -    ChardevStdio *opts = backend->u.stdio.data;

> +    ChardevStdio *opts = &backend->u.stdio;

>      struct sigaction act;

>

>      if (is_daemonized()) {

> @@ -120,10 +120,9 @@ static void qemu_chr_open_stdio(Chardev *chr,

>  static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,

>                                   Error **errp)

>  {

> -    ChardevStdio *stdio;

> +    ChardevStdio *stdio = &backend->u.stdio;

>

>      backend->type = CHARDEV_BACKEND_KIND_STDIO;

> -    stdio = backend->u.stdio.data = g_new0(ChardevStdio, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));

>      stdio->has_signal = true;

>      stdio->signal = qemu_opt_get_bool(opts, "signal", true);

> diff --git a/chardev/char-udp.c b/chardev/char-udp.c

> index 16b5dbce58..3b1bdddbbd 100644

> --- a/chardev/char-udp.c

> +++ b/chardev/char-udp.c

> @@ -140,7 +140,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts,

> ChardevBackend *backend,

>      const char *localport = qemu_opt_get(opts, "localport");

>      bool has_local = false;

>      SocketAddressLegacy *addr;

> -    ChardevUdp *udp;

> +    ChardevUdp *udp = &backend->u.udp;

>

>      backend->type = CHARDEV_BACKEND_KIND_UDP;

>      if (host == NULL || strlen(host) == 0) {

> @@ -161,13 +161,11 @@ static void qemu_chr_parse_udp(QemuOpts *opts,

> ChardevBackend *backend,

>          has_local = true;

>      }

>

> -    udp = backend->u.udp.data = g_new0(ChardevUdp, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));

>

>      addr = g_new0(SocketAddressLegacy, 1);

>      addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;

> -    addr->u.inet.data = g_new(InetSocketAddress, 1);

> -    *addr->u.inet.data = (InetSocketAddress) {

> +    addr->u.inet = (InetSocketAddress) {

>          .host = g_strdup(host),

>          .port = g_strdup(port),

>          .has_ipv4 = qemu_opt_get(opts, "ipv4"),

> @@ -181,8 +179,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts,

> ChardevBackend *backend,

>          udp->has_local = true;

>          addr = g_new0(SocketAddressLegacy, 1);

>          addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;

> -        addr->u.inet.data = g_new(InetSocketAddress, 1);

> -        *addr->u.inet.data = (InetSocketAddress) {

> +        addr->u.inet = (InetSocketAddress) {

>              .host = g_strdup(localaddr),

>              .port = g_strdup(localport),

>          };

> @@ -195,7 +192,7 @@ static void qmp_chardev_open_udp(Chardev *chr,

>                                   bool *be_opened,

>                                   Error **errp)

>  {

> -    ChardevUdp *udp = backend->u.udp.data;

> +    ChardevUdp *udp = &backend->u.udp;

>      SocketAddress *local_addr = socket_address_flatten(udp->local);

>      SocketAddress *remote_addr = socket_address_flatten(udp->remote);

>      QIOChannelSocket *sioc = qio_channel_socket_new();

> diff --git a/chardev/char.c b/chardev/char.c

> index 028612c333..5192964694 100644

> --- a/chardev/char.c

> +++ b/chardev/char.c

> @@ -238,7 +238,7 @@ static void qemu_char_open(Chardev *chr,

> ChardevBackend *backend,

>  {

>      ChardevClass *cc = CHARDEV_GET_CLASS(chr);

>      /* Any ChardevCommon member would work */

> -    ChardevCommon *common = backend ? backend->u.null.data : NULL;

> +    ChardevCommon *common = backend ? &backend->u.null : NULL;

>

>      if (common && common->has_logfile) {

>          int flags = O_WRONLY | O_CREAT;

> @@ -625,9 +625,8 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts,

> Error **errp)

>              return NULL;

>          }

>      } else {

> -        ChardevCommon *ccom = g_new0(ChardevCommon, 1);

> -        qemu_chr_parse_common(opts, ccom);

> -        backend->u.null.data = ccom; /* Any ChardevCommon member would

> work */

> +        /* Any ChardevCommon member would work */

> +        qemu_chr_parse_common(opts, &backend->u.null);

>      }

>

>      return backend;

> @@ -690,8 +689,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,

> GMainContext *context,

>          qapi_free_ChardevBackend(backend);

>          backend = g_new0(ChardevBackend, 1);

>          backend->type = CHARDEV_BACKEND_KIND_MUX;

> -        backend->u.mux.data = g_new0(ChardevMux, 1);

> -        backend->u.mux.data->chardev = g_strdup(bid);

> +        backend->u.mux.chardev = g_strdup(bid);

>          mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context,

> errp);

>          if (mux == NULL) {

>              object_unparent(OBJECT(chr));

> diff --git a/chardev/msmouse.c b/chardev/msmouse.c

> index eb9231dcdb..98b0ef8cd7 100644

> --- a/chardev/msmouse.c

> +++ b/chardev/msmouse.c

> @@ -111,12 +111,12 @@ static void msmouse_input_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          mouse->axis[move->axis] += move->value;

>          break;

>

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          mouse->btns[btn->button] = btn->down;

>          mouse->btnc[btn->button] = true;

>          break;

> diff --git a/chardev/wctablet.c b/chardev/wctablet.c

> index 95e005f5a5..8479f59183 100644

> --- a/chardev/wctablet.c

> +++ b/chardev/wctablet.c

> @@ -154,12 +154,12 @@ static void wctablet_input_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          tablet->axis[move->axis] = move->value;

>          break;

>

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          tablet->btns[btn->button] = btn->down;

>          break;

>

> diff --git a/hw/core/numa.c b/hw/core/numa.c

> index 7c4dd4e68e..24fe0e11d8 100644

> --- a/hw/core/numa.c

> +++ b/hw/core/numa.c

> @@ -765,19 +765,19 @@ static void numa_stat_memory_devices(NumaNodeMem

> node_mem[])

>              case MEMORY_DEVICE_INFO_KIND_DIMM:

>              case MEMORY_DEVICE_INFO_KIND_NVDIMM:

>                  pcdimm_info = value->type == MEMORY_DEVICE_INFO_KIND_DIMM

> ?

> -                              value->u.dimm.data : value->u.nvdimm.data;

> +                              &value->u.dimm : &value->u.nvdimm;

>                  node_mem[pcdimm_info->node].node_mem += pcdimm_info->size;

>                  node_mem[pcdimm_info->node].node_plugged_mem +=

>                      pcdimm_info->size;

>                  break;

>              case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:

> -                vpi = value->u.virtio_pmem.data;

> +                vpi = &value->u.virtio_pmem;

>                  /* TODO: once we support numa, assign to right node */

>                  node_mem[0].node_mem += vpi->size;

>                  node_mem[0].node_plugged_mem += vpi->size;

>                  break;

>              case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM:

> -                vmi = value->u.virtio_mem.data;

> +                vmi = &value->u.virtio_mem;

>                  node_mem[vmi->node].node_mem += vmi->size;

>                  node_mem[vmi->node].node_plugged_mem += vmi->size;

>                  break;

> diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c

> index 838260b6ad..6aa6010774 100644

> --- a/hw/display/xenfb.c

> +++ b/hw/display/xenfb.c

> @@ -201,7 +201,7 @@ static void xenfb_key_event(DeviceState *dev,

> QemuConsole *src,

>                              InputEvent *evt)

>  {

>      struct XenInput *xenfb = (struct XenInput *)dev;

> -    InputKeyEvent *key = evt->u.key.data;

> +    InputKeyEvent *key = &evt->u.key;

>      int qcode = qemu_input_key_value_to_qcode(key->key);

>      int lnx;

>

> @@ -236,7 +236,7 @@ static void xenfb_mouse_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          switch (btn->button) {

>          case INPUT_BUTTON_LEFT:

>              xenfb_send_key(xenfb, btn->down, BTN_LEFT);

> @@ -263,7 +263,7 @@ static void xenfb_mouse_event(DeviceState *dev,

> QemuConsole *src,

>          break;

>

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          if (xenfb->raw_pointer_wanted) {

>              xenfb->axis[move->axis] = move->value;

>          } else {

> @@ -289,7 +289,7 @@ static void xenfb_mouse_event(DeviceState *dev,

> QemuConsole *src,

>          break;

>

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          xenfb->axis[move->axis] += move->value;

>          break;

>

> diff --git a/hw/input/hid.c b/hw/input/hid.c

> index 89239b5634..2472c5a902 100644

> --- a/hw/input/hid.c

> +++ b/hw/input/hid.c

> @@ -126,7 +126,7 @@ static void hid_pointer_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          if (move->axis == INPUT_AXIS_X) {

>              e->xdx += move->value;

>          } else if (move->axis == INPUT_AXIS_Y) {

> @@ -135,7 +135,7 @@ static void hid_pointer_event(DeviceState *dev,

> QemuConsole *src,

>          break;

>

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          if (move->axis == INPUT_AXIS_X) {

>              e->xdx = move->value;

>          } else if (move->axis == INPUT_AXIS_Y) {

> @@ -144,7 +144,7 @@ static void hid_pointer_event(DeviceState *dev,

> QemuConsole *src,

>          break;

>

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          if (btn->down) {

>              e->buttons_state |= bmap[btn->button];

>              if (btn->button == INPUT_BUTTON_WHEEL_UP) {

> @@ -230,7 +230,7 @@ static void hid_keyboard_event(DeviceState *dev,

> QemuConsole *src,

>      HIDState *hs = (HIDState *)dev;

>      int scancodes[3], i, count;

>      int slot;

> -    InputKeyEvent *key = evt->u.key.data;

> +    InputKeyEvent *key = &evt->u.key;

>

>      count = qemu_input_key_value_to_scancode(key->key,

>                                               key->down,

> diff --git a/hw/input/ps2.c b/hw/input/ps2.c

> index f8746d2f52..1176ccc88c 100644

> --- a/hw/input/ps2.c

> +++ b/hw/input/ps2.c

> @@ -284,7 +284,7 @@ static void ps2_keyboard_event(DeviceState *dev,

> QemuConsole *src,

>                                 InputEvent *evt)

>  {

>      PS2KbdState *s = (PS2KbdState *)dev;

> -    InputKeyEvent *key = evt->u.key.data;

> +    InputKeyEvent *key = &evt->u.key;

>      int qcode;

>      uint16_t keycode = 0;

>      int mod;

> @@ -727,7 +727,7 @@ static void ps2_mouse_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          if (move->axis == INPUT_AXIS_X) {

>              s->mouse_dx += move->value;

>          } else if (move->axis == INPUT_AXIS_Y) {

> @@ -736,7 +736,7 @@ static void ps2_mouse_event(DeviceState *dev,

> QemuConsole *src,

>          break;

>

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          if (btn->down) {

>              s->mouse_buttons |= bmap[btn->button];

>              if (btn->button == INPUT_BUTTON_WHEEL_UP) {

> diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c

> index a7a244a95d..1c7b07cf42 100644

> --- a/hw/input/virtio-input-hid.c

> +++ b/hw/input/virtio-input-hid.c

> @@ -83,7 +83,7 @@ static void virtio_input_handle_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_KEY:

> -        key = evt->u.key.data;

> +        key = &evt->u.key;

>          qcode = qemu_input_key_value_to_qcode(key->key);

>          if (qcode < qemu_input_map_qcode_to_linux_len &&

>              qemu_input_map_qcode_to_linux[qcode]) {

> @@ -99,7 +99,7 @@ static void virtio_input_handle_event(DeviceState *dev,

> QemuConsole *src,

>          }

>          break;

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          if (vhid->wheel_axis &&

>              (btn->button == INPUT_BUTTON_WHEEL_UP ||

>               btn->button == INPUT_BUTTON_WHEEL_DOWN) &&

> @@ -123,14 +123,14 @@ static void virtio_input_handle_event(DeviceState

> *dev, QemuConsole *src,

>          }

>          break;

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          event.type  = cpu_to_le16(EV_REL);

>          event.code  = cpu_to_le16(axismap_rel[move->axis]);

>          event.value = cpu_to_le32(move->value);

>          virtio_input_send(vinput, &event);

>          break;

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          event.type  = cpu_to_le16(EV_ABS);

>          event.code  = cpu_to_le16(axismap_abs[move->axis]);

>          event.value = cpu_to_le32(move->value);

> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c

> index c30351070b..3d6f836621 100644

> --- a/hw/mem/pc-dimm.c

> +++ b/hw/mem/pc-dimm.c

> @@ -236,11 +236,19 @@ static MemoryRegion

> *pc_dimm_md_get_memory_region(MemoryDeviceState *md,

>  static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,

>                                          MemoryDeviceInfo *info)

>  {

> -    PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);

> +    PCDIMMDeviceInfo *di;

>      const DeviceClass *dc = DEVICE_GET_CLASS(md);

>      const PCDIMMDevice *dimm = PC_DIMM(md);

>      const DeviceState *dev = DEVICE(md);

>

> +    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {

> +        di = &info->u.nvdimm;

> +        info->type = MEMORY_DEVICE_INFO_KIND_NVDIMM;

> +    } else {

> +        di = &info->u.dimm;

> +        info->type = MEMORY_DEVICE_INFO_KIND_DIMM;

> +    }

> +

>      if (dev->id) {

>          di->has_id = true;

>          di->id = g_strdup(dev->id);

> @@ -253,14 +261,6 @@ static void pc_dimm_md_fill_device_info(const

> MemoryDeviceState *md,

>      di->size = object_property_get_uint(OBJECT(dimm), PC_DIMM_SIZE_PROP,

>                                          NULL);

>      di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));

> -

> -    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {

> -        info->u.nvdimm.data = di;

> -        info->type = MEMORY_DEVICE_INFO_KIND_NVDIMM;

> -    } else {

> -        info->u.dimm.data = di;

> -        info->type = MEMORY_DEVICE_INFO_KIND_DIMM;

> -    }

>  }

>

>  static void pc_dimm_class_init(ObjectClass *oc, void *data)

> diff --git a/hw/virtio/virtio-mem-pci.c b/hw/virtio/virtio-mem-pci.c

> index 913f4a3326..f93572fc27 100644

> --- a/hw/virtio/virtio-mem-pci.c

> +++ b/hw/virtio/virtio-mem-pci.c

> @@ -58,7 +58,7 @@ static uint64_t virtio_mem_pci_get_plugged_size(const

> MemoryDeviceState *md,

>  static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,

>                                              MemoryDeviceInfo *info)

>  {

> -    VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);

> +    VirtioMEMDeviceInfo *vi = &info->u.virtio_mem;

>      VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);

>      VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev);

>      VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);

> @@ -72,7 +72,6 @@ static void virtio_mem_pci_fill_device_info(const

> MemoryDeviceState *md,

>      /* let the real device handle everything else */

>      vpc->fill_device_info(vmem, vi);

>

> -    info->u.virtio_mem.data = vi;

>      info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;

>  }

>

> diff --git a/hw/virtio/virtio-pmem-pci.c b/hw/virtio/virtio-pmem-pci.c

> index 2b2a0b1eae..adf17f873b 100644

> --- a/hw/virtio/virtio-pmem-pci.c

> +++ b/hw/virtio/virtio-pmem-pci.c

> @@ -63,7 +63,7 @@ static uint64_t virtio_pmem_pci_get_plugged_size(const

> MemoryDeviceState *md,

>  static void virtio_pmem_pci_fill_device_info(const MemoryDeviceState *md,

>                                               MemoryDeviceInfo *info)

>  {

> -    VirtioPMEMDeviceInfo *vi = g_new0(VirtioPMEMDeviceInfo, 1);

> +    VirtioPMEMDeviceInfo *vi = &info->u.virtio_pmem;

>      VirtIOPMEMPCI *pci_pmem = VIRTIO_PMEM_PCI(md);

>      VirtIOPMEM *pmem = VIRTIO_PMEM(&pci_pmem->vdev);

>      VirtIOPMEMClass *vpc = VIRTIO_PMEM_GET_CLASS(pmem);

> @@ -77,7 +77,6 @@ static void virtio_pmem_pci_fill_device_info(const

> MemoryDeviceState *md,

>      /* let the real device handle everything else */

>      vpc->fill_device_info(pmem, vi);

>

> -    info->u.virtio_pmem.data = vi;

>      info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM;

>  }

>

> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c

> index 9789f4277f..0324caa114 100644

> --- a/monitor/hmp-cmds.c

> +++ b/monitor/hmp-cmds.c

> @@ -918,7 +918,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)

>

>          switch (ti->options->type) {

>          case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:

> -            tpo = ti->options->u.passthrough.data;

> +            tpo = &ti->options->u.passthrough;

>              monitor_printf(mon, "%s%s%s%s",

>                             tpo->has_path ? ",path=" : "",

>                             tpo->has_path ? tpo->path : "",

> @@ -926,7 +926,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)

>                             tpo->has_cancel_path ? tpo->cancel_path : "");

>              break;

>          case TPM_TYPE_OPTIONS_KIND_EMULATOR:

> -            teo = ti->options->u.emulator.data;

> +            teo = &ti->options->u.emulator;

>              monitor_printf(mon, ",chardev=%s", teo->chardev);

>              break;

>          case TPM_TYPE_OPTIONS_KIND__MAX:

> @@ -1728,14 +1728,14 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)

>                  goto err_out;

>              }

>              keylist->value->type = KEY_VALUE_KIND_NUMBER;

> -            keylist->value->u.number.data = value;

> +            keylist->value->u.number = value;

>          } else {

>              int idx = index_from_key(keys, keyname_len);

>              if (idx == Q_KEY_CODE__MAX) {

>                  goto err_out;

>              }

>              keylist->value->type = KEY_VALUE_KIND_QCODE;

> -            keylist->value->u.qcode.data = idx;

> +            keylist->value->u.qcode = idx;

>          }

>

>          if (!*separator) {

> @@ -1860,7 +1860,7 @@ void hmp_info_memory_devices(Monitor *mon, const

> QDict *qdict)

>              case MEMORY_DEVICE_INFO_KIND_DIMM:

>              case MEMORY_DEVICE_INFO_KIND_NVDIMM:

>                  di = value->type == MEMORY_DEVICE_INFO_KIND_DIMM ?

> -                     value->u.dimm.data : value->u.nvdimm.data;

> +                     &value->u.dimm : &value->u.nvdimm;

>                  monitor_printf(mon, "Memory device [%s]: \"%s\"\n",

>                                 MemoryDeviceInfoKind_str(value->type),

>                                 di->id ? di->id : "");

> @@ -1875,7 +1875,7 @@ void hmp_info_memory_devices(Monitor *mon, const

> QDict *qdict)

>                                 di->hotpluggable ? "true" : "false");

>                  break;

>              case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:

> -                vpi = value->u.virtio_pmem.data;

> +                vpi = &value->u.virtio_pmem;

>                  monitor_printf(mon, "Memory device [%s]: \"%s\"\n",

>                                 MemoryDeviceInfoKind_str(value->type),

>                                 vpi->id ? vpi->id : "");

> @@ -1884,7 +1884,7 @@ void hmp_info_memory_devices(Monitor *mon, const

> QDict *qdict)

>                  monitor_printf(mon, "  memdev: %s\n", vpi->memdev);

>                  break;

>              case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM:

> -                vmi = value->u.virtio_mem.data;

> +                vmi = &value->u.virtio_mem;

>                  monitor_printf(mon, "Memory device [%s]: \"%s\"\n",

>                                 MemoryDeviceInfoKind_str(value->type),

>                                 vmi->id ? vmi->id : "");

> diff --git a/qemu-keymap.c b/qemu-keymap.c

> index 536e8f2385..52637c449c 100644

> --- a/qemu-keymap.c

> +++ b/qemu-keymap.c

> @@ -38,7 +38,7 @@ static uint32_t qcode_to_number(uint32_t qcode)

>      uint32_t number;

>

>      keyvalue.type = KEY_VALUE_KIND_QCODE;

> -    keyvalue.u.qcode.data = qcode;

> +    keyvalue.u.qcode = qcode;

>      number = qemu_input_key_value_to_number(&keyvalue);

>      assert(number != 0);

>      return number;

> diff --git a/replay/replay-input.c b/replay/replay-input.c

> index 1147e3d34e..c1eb1b79e1 100644

> --- a/replay/replay-input.c

> +++ b/replay/replay-input.c

> @@ -26,16 +26,16 @@ void replay_save_input_event(InputEvent *evt)

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_KEY:

> -        key = evt->u.key.data;

> +        key = &evt->u.key;

>          replay_put_dword(key->key->type);

>

>          switch (key->key->type) {

>          case KEY_VALUE_KIND_NUMBER:

> -            replay_put_qword(key->key->u.number.data);

> +            replay_put_qword(key->key->u.number);

>              replay_put_byte(key->down);

>              break;

>          case KEY_VALUE_KIND_QCODE:

> -            replay_put_dword(key->key->u.qcode.data);

> +            replay_put_dword(key->key->u.qcode);

>              replay_put_byte(key->down);

>              break;

>          case KEY_VALUE_KIND__MAX:

> @@ -44,17 +44,17 @@ void replay_save_input_event(InputEvent *evt)

>          }

>          break;

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          replay_put_dword(btn->button);

>          replay_put_byte(btn->down);

>          break;

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          replay_put_dword(move->axis);

>          replay_put_qword(move->value);

>          break;

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          replay_put_dword(move->axis);

>          replay_put_qword(move->value);

>          break;

> @@ -68,26 +68,21 @@ InputEvent *replay_read_input_event(void)

>  {

>      InputEvent evt;

>      KeyValue keyValue;

> -    InputKeyEvent key;

> -    key.key = &keyValue;

> -    InputBtnEvent btn;

> -    InputMoveEvent rel;

> -    InputMoveEvent abs;

> +    evt.u.key.key = &keyValue;

>

>      evt.type = replay_get_dword();

>      switch (evt.type) {

>      case INPUT_EVENT_KIND_KEY:

> -        evt.u.key.data = &key;

> -        evt.u.key.data->key->type = replay_get_dword();

> +        evt.u.key.key->type = replay_get_dword();

>

> -        switch (evt.u.key.data->key->type) {

> +        switch (evt.u.key.key->type) {

>          case KEY_VALUE_KIND_NUMBER:

> -            evt.u.key.data->key->u.number.data = replay_get_qword();

> -            evt.u.key.data->down = replay_get_byte();

> +            evt.u.key.key->u.number = replay_get_qword();

> +            evt.u.key.down = replay_get_byte();

>              break;

>          case KEY_VALUE_KIND_QCODE:

> -            evt.u.key.data->key->u.qcode.data =

> (QKeyCode)replay_get_dword();

> -            evt.u.key.data->down = replay_get_byte();

> +            evt.u.key.key->u.qcode = (QKeyCode)replay_get_dword();

> +            evt.u.key.down = replay_get_byte();

>              break;

>          case KEY_VALUE_KIND__MAX:

>              /* keep gcc happy */

> @@ -95,19 +90,16 @@ InputEvent *replay_read_input_event(void)

>          }

>          break;

>      case INPUT_EVENT_KIND_BTN:

> -        evt.u.btn.data = &btn;

> -        evt.u.btn.data->button = (InputButton)replay_get_dword();

> -        evt.u.btn.data->down = replay_get_byte();

> +        evt.u.btn.button = (InputButton)replay_get_dword();

> +        evt.u.btn.down = replay_get_byte();

>          break;

>      case INPUT_EVENT_KIND_REL:

> -        evt.u.rel.data = &rel;

> -        evt.u.rel.data->axis = (InputAxis)replay_get_dword();

> -        evt.u.rel.data->value = replay_get_qword();

> +        evt.u.rel.axis = (InputAxis)replay_get_dword();

> +        evt.u.rel.value = replay_get_qword();

>          break;

>      case INPUT_EVENT_KIND_ABS:

> -        evt.u.abs.data = &abs;

> -        evt.u.abs.data->axis = (InputAxis)replay_get_dword();

> -        evt.u.abs.data->value = replay_get_qword();

> +        evt.u.abs.axis = (InputAxis)replay_get_dword();

> +        evt.u.abs.value = replay_get_qword();

>          break;

>      case INPUT_EVENT_KIND__MAX:

>          /* keep gcc happy */

> diff --git a/tests/test-char.c b/tests/test-char.c

> index 9196e566e9..0e7a033a90 100644

> --- a/tests/test-char.c

> +++ b/tests/test-char.c

> @@ -1220,7 +1220,7 @@ static void char_file_fifo_test(void)

>                           .has_in = true,

>                           .out = out };

>      ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,

> -                               .u.file.data = &file };

> +                               .u.file = file };

>      FeHandler fe = { 0, };

>      int fd, ret;

>

> @@ -1273,19 +1273,17 @@ static void char_file_test_internal(Chardev

> *ext_chr, const char *filepath)

>      char *out;

>      Chardev *chr;

>      char *contents = NULL;

> -    ChardevFile file = {};

> -    ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,

> -                               .u.file.data = &file };

> +    ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE };

>      gsize length;

>      int ret;

>

>      if (ext_chr) {

>          chr = ext_chr;

>          out = g_strdup(filepath);

> -        file.out = out;

> +        backend.u.file.out = out;

>      } else {

>          out = g_build_filename(tmp_path, "out", NULL);

> -        file.out = out;

> +        backend.u.file.out = out;

>          chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,

>                                 NULL, &error_abort);

>      }

> @@ -1384,7 +1382,7 @@ static void char_hotswap_test(void)

>      char *filename = g_build_filename(tmp_path, "file", NULL);

>      ChardevFile file = { .out = filename };

>      ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,

> -                               .u.file.data = &file };

> +                               .u.file = file };

>      ChardevReturn *ret;

>

>      int port;

> diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c

> index 5e1e8b2f5e..0a62704bed 100644

> --- a/tests/test-clone-visitor.c

> +++ b/tests/test-clone-visitor.c

> @@ -110,7 +110,7 @@ static void test_clone_complex1(void)

>      dst = QAPI_CLONE(UserDefListUnion, src);

>      g_assert(dst);

>      g_assert_cmpint(dst->type, ==, src->type);

> -    g_assert(!dst->u.string.data);

> +    g_assert(!dst->u.string);

>

>      qapi_free_UserDefListUnion(src);

>      qapi_free_UserDefListUnion(dst);

> @@ -155,30 +155,30 @@ static void test_clone_complex3(void)

>      tmp = src->array = g_new0(__org_qemu_x_Union1List, 1);

>      tmp->value = g_new0(__org_qemu_x_Union1, 1);

>      tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;

> -    tmp->value->u.__org_qemu_x_branch.data = g_strdup("one");

> +    tmp->value->u.__org_qemu_x_branch = g_strdup("one");

>      tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);

>      tmp->value = g_new0(__org_qemu_x_Union1, 1);

>      tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;

> -    tmp->value->u.__org_qemu_x_branch.data = g_strdup("two");

> +    tmp->value->u.__org_qemu_x_branch = g_strdup("two");

>      tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);

>      tmp->value = g_new0(__org_qemu_x_Union1, 1);

>      tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;

> -    tmp->value->u.__org_qemu_x_branch.data = g_strdup("three");

> +    tmp->value->u.__org_qemu_x_branch = g_strdup("three");

>

>      dst = QAPI_CLONE(__org_qemu_x_Struct2, src);

>      g_assert(dst);

>      tmp = dst->array;

>      g_assert(tmp);

>      g_assert(tmp->value);

> -    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "one");

> +    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch, ==, "one");

>      tmp = tmp->next;

>      g_assert(tmp);

>      g_assert(tmp->value);

> -    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "two");

> +    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch, ==, "two");

>      tmp = tmp->next;

>      g_assert(tmp);

>      g_assert(tmp->value);

> -    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "three");

> +    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch, ==, "three");

>      tmp = tmp->next;

>      g_assert(!tmp);

>

> diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c

> index d3413bfef0..3d699fbb66 100644

> --- a/tests/test-qmp-cmds.c

> +++ b/tests/test-qmp-cmds.c

> @@ -136,7 +136,7 @@ __org_qemu_x_Union1

> *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,

>      __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);

>

>      ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;

> -    ret->u.__org_qemu_x_branch.data = strdup("blah1");

> +    ret->u.__org_qemu_x_branch = strdup("blah1");

>

>      /* Also test that 'wchar-t' was munged to 'q_wchar_t' */

>      if (b && b->value && !b->value->has_q_wchar_t) {

> diff --git a/tests/test-qobject-input-visitor.c

> b/tests/test-qobject-input-visitor.c

> index e41b91a2a6..b976ab9763 100644

> --- a/tests/test-qobject-input-visitor.c

> +++ b/tests/test-qobject-input-visitor.c

> @@ -710,7 +710,7 @@ static void

> test_list_union_integer_helper(TestInputVisitorData *data,

>      switch (kind) {

>      case USER_DEF_LIST_UNION_KIND_INTEGER: {

>          intList *elem = NULL;

> -        for (i = 0, elem = cvalue->u.integer.data;

> +        for (i = 0, elem = cvalue->u.integer;

>               elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

> @@ -718,56 +718,56 @@ static void

> test_list_union_integer_helper(TestInputVisitorData *data,

>      }

>      case USER_DEF_LIST_UNION_KIND_S8: {

>          int8List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.s8; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S16: {

>          int16List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.s16; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S32: {

>          int32List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.s32; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S64: {

>          int64List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.s64; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U8: {

>          uint8List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.u8; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U16: {

>          uint16List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.u16; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U32: {

>          uint32List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.u32; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U64: {

>          uint64List *elem = NULL;

> -        for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next,

> i++) {

> +        for (i = 0, elem = cvalue->u.u64; elem; elem = elem->next, i++) {

>              g_assert_cmpint(elem->value, ==, i);

>          }

>          break;

> @@ -868,7 +868,7 @@ static void

> test_visitor_in_list_union_bool(TestInputVisitorData *data,

>      g_assert(cvalue != NULL);

>      g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_BOOLEAN);

>

> -    for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next,

> i++) {

> +    for (i = 0, elem = cvalue->u.boolean; elem; elem = elem->next, i++) {

>          g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);

>      }

>

> @@ -900,7 +900,7 @@ static void

> test_visitor_in_list_union_string(TestInputVisitorData *data,

>      g_assert(cvalue != NULL);

>      g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_STRING);

>

> -    for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next,

> i++) {

> +    for (i = 0, elem = cvalue->u.string; elem; elem = elem->next, i++) {

>          gchar str[8];

>          sprintf(str, "%d", i);

>          g_assert_cmpstr(elem->value, ==, str);

> @@ -936,7 +936,7 @@ static void

> test_visitor_in_list_union_number(TestInputVisitorData *data,

>      g_assert(cvalue != NULL);

>      g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_NUMBER);

>

> -    for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next,

> i++) {

> +    for (i = 0, elem = cvalue->u.number; elem; elem = elem->next, i++) {

>          GString *double_expected = g_string_new("");

>          GString *double_actual = g_string_new("");

>

> diff --git a/tests/test-qobject-output-visitor.c

> b/tests/test-qobject-output-visitor.c

> index 1c856d9bd2..202f848062 100644

> --- a/tests/test-qobject-output-visitor.c

> +++ b/tests/test-qobject-output-visitor.c

> @@ -444,7 +444,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>      int i;

>      switch (cvalue->type) {

>      case USER_DEF_LIST_UNION_KIND_INTEGER: {

> -        intList **list = &cvalue->u.integer.data;

> +        intList **list = &cvalue->u.integer;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(intList, 1);

>              (*list)->value = i;

> @@ -454,7 +454,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S8: {

> -        int8List **list = &cvalue->u.s8.data;

> +        int8List **list = &cvalue->u.s8;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(int8List, 1);

>              (*list)->value = i;

> @@ -464,7 +464,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S16: {

> -        int16List **list = &cvalue->u.s16.data;

> +        int16List **list = &cvalue->u.s16;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(int16List, 1);

>              (*list)->value = i;

> @@ -474,7 +474,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S32: {

> -        int32List **list = &cvalue->u.s32.data;

> +        int32List **list = &cvalue->u.s32;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(int32List, 1);

>              (*list)->value = i;

> @@ -484,7 +484,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_S64: {

> -        int64List **list = &cvalue->u.s64.data;

> +        int64List **list = &cvalue->u.s64;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(int64List, 1);

>              (*list)->value = i;

> @@ -494,7 +494,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U8: {

> -        uint8List **list = &cvalue->u.u8.data;

> +        uint8List **list = &cvalue->u.u8;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(uint8List, 1);

>              (*list)->value = i;

> @@ -504,7 +504,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U16: {

> -        uint16List **list = &cvalue->u.u16.data;

> +        uint16List **list = &cvalue->u.u16;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(uint16List, 1);

>              (*list)->value = i;

> @@ -514,7 +514,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U32: {

> -        uint32List **list = &cvalue->u.u32.data;

> +        uint32List **list = &cvalue->u.u32;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(uint32List, 1);

>              (*list)->value = i;

> @@ -524,7 +524,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_U64: {

> -        uint64List **list = &cvalue->u.u64.data;

> +        uint64List **list = &cvalue->u.u64;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(uint64List, 1);

>              (*list)->value = i;

> @@ -534,7 +534,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_BOOLEAN: {

> -        boolList **list = &cvalue->u.boolean.data;

> +        boolList **list = &cvalue->u.boolean;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(boolList, 1);

>              (*list)->value = QEMU_IS_ALIGNED(i, 3);

> @@ -544,7 +544,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_STRING: {

> -        strList **list = &cvalue->u.string.data;

> +        strList **list = &cvalue->u.string;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(strList, 1);

>              (*list)->value = g_strdup_printf("%d", i);

> @@ -554,7 +554,7 @@ static void init_list_union(UserDefListUnion *cvalue)

>          break;

>      }

>      case USER_DEF_LIST_UNION_KIND_NUMBER: {

> -        numberList **list = &cvalue->u.number.data;

> +        numberList **list = &cvalue->u.number;

>          for (i = 0; i < 32; i++) {

>              *list = g_new0(numberList, 1);

>              (*list)->value = (double)i / 3;

> diff --git a/ui/console.c b/ui/console.c

> index 820e408170..2f93723ed6 100644

> --- a/ui/console.c

> +++ b/ui/console.c

> @@ -2212,7 +2212,7 @@ static void vc_chr_open(Chardev *chr,

>                          bool *be_opened,

>                          Error **errp)

>  {

> -    ChardevVC *vc = backend->u.vc.data;

> +    ChardevVC *vc = &backend->u.vc;

>      VCChardev *drv = VC_CHARDEV(chr);

>      QemuConsole *s;

>      unsigned width = 0;

> @@ -2362,10 +2362,9 @@ void qemu_display_help(void)

>  void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error

> **errp)

>  {

>      int val;

> -    ChardevVC *vc;

> +    ChardevVC *vc = &backend->u.vc;

>

>      backend->type = CHARDEV_BACKEND_KIND_VC;

> -    vc = backend->u.vc.data = g_new0(ChardevVC, 1);

>      qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));

>

>      val = qemu_opt_get_number(opts, "width", 0);

> diff --git a/ui/input-keymap.c b/ui/input-keymap.c

> index 1b756a6970..0232e25124 100644

> --- a/ui/input-keymap.c

> +++ b/ui/input-keymap.c

> @@ -33,13 +33,13 @@ int qemu_input_linux_to_qcode(unsigned int lnx)

>  int qemu_input_key_value_to_number(const KeyValue *value)

>  {

>      if (value->type == KEY_VALUE_KIND_QCODE) {

> -        if (value->u.qcode.data >= qemu_input_map_qcode_to_qnum_len) {

> +        if (value->u.qcode >= qemu_input_map_qcode_to_qnum_len) {

>              return 0;

>          }

> -        return qemu_input_map_qcode_to_qnum[value->u.qcode.data];

> +        return qemu_input_map_qcode_to_qnum[value->u.qcode];

>      } else {

>          assert(value->type == KEY_VALUE_KIND_NUMBER);

> -        return value->u.number.data;

> +        return value->u.number;

>      }

>  }

>

> @@ -54,10 +54,10 @@ int qemu_input_key_number_to_qcode(unsigned int nr)

>  int qemu_input_key_value_to_qcode(const KeyValue *value)

>  {

>      if (value->type == KEY_VALUE_KIND_QCODE) {

> -        return value->u.qcode.data;

> +        return value->u.qcode;

>      } else {

>          assert(value->type == KEY_VALUE_KIND_NUMBER);

> -        return qemu_input_key_number_to_qcode(value->u.number.data);

> +        return qemu_input_key_number_to_qcode(value->u.number);

>      }

>  }

>

> @@ -68,7 +68,7 @@ int qemu_input_key_value_to_scancode(const KeyValue

> *value, bool down,

>      int count = 0;

>

>      if (value->type == KEY_VALUE_KIND_QCODE &&

> -        value->u.qcode.data == Q_KEY_CODE_PAUSE) {

> +        value->u.qcode == Q_KEY_CODE_PAUSE) {

>          /* specific case */

>          int v = down ? 0 : 0x80;

>          codes[count++] = 0xe1;

> diff --git a/ui/input-legacy.c b/ui/input-legacy.c

> index 9fc78a639b..5a32b010d4 100644

> --- a/ui/input-legacy.c

> +++ b/ui/input-legacy.c

> @@ -75,9 +75,9 @@ static KeyValue *copy_key_value(KeyValue *src)

>      KeyValue *dst = g_new(KeyValue, 1);

>      memcpy(dst, src, sizeof(*src));

>      if (dst->type == KEY_VALUE_KIND_NUMBER) {

> -        QKeyCode code =

> qemu_input_key_number_to_qcode(dst->u.number.data);

> +        QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number);

>          dst->type = KEY_VALUE_KIND_QCODE;

> -        dst->u.qcode.data = code;

> +        dst->u.qcode = code;

>      }

>      return dst;

>  }

> @@ -113,7 +113,7 @@ static void legacy_kbd_event(DeviceState *dev,

> QemuConsole *src,

>  {

>      QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;

>      int scancodes[3], i, count;

> -    InputKeyEvent *key = evt->u.key.data;

> +    InputKeyEvent *key = &evt->u.key;

>

>      if (!entry || !entry->put_kbd) {

>          return;

> @@ -159,7 +159,7 @@ static void legacy_mouse_event(DeviceState *dev,

> QemuConsole *src,

>

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          if (btn->down) {

>              s->buttons |= bmap[btn->button];

>          } else {

> @@ -181,11 +181,11 @@ static void legacy_mouse_event(DeviceState *dev,

> QemuConsole *src,

>          }

>          break;

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          s->axis[move->axis] = move->value;

>          break;

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          s->axis[move->axis] += move->value;

>          break;

>      default:

> diff --git a/ui/input.c b/ui/input.c

> index 4791b089c7..a4078780ee 100644

> --- a/ui/input.c

> +++ b/ui/input.c

> @@ -164,10 +164,10 @@ void qmp_input_send_event(bool has_device, const

> char *device,

>          InputEvent *evt = e->value;

>

>          if (evt->type == INPUT_EVENT_KIND_KEY &&

> -            evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {

> -            KeyValue *key = evt->u.key.data->key;

> -            QKeyCode code =

> qemu_input_key_number_to_qcode(key->u.number.data);

> -            qemu_input_event_send_key_qcode(con, code,

> evt->u.key.data->down);

> +            evt->u.key.key->type == KEY_VALUE_KIND_NUMBER) {

> +            KeyValue *key = evt->u.key.key;

> +            QKeyCode code = qemu_input_key_number_to_qcode(key->u.number);

> +            qemu_input_event_send_key_qcode(con, code, evt->u.key.down);

>          } else {

>              qemu_input_event_send(con, evt);

>          }

> @@ -183,7 +183,7 @@ static int qemu_input_transform_invert_abs_value(int

> value)

>

>  static void qemu_input_transform_abs_rotate(InputEvent *evt)

>  {

> -    InputMoveEvent *move = evt->u.abs.data;

> +    InputMoveEvent *move = &evt->u.abs;

>      switch (graphic_rotate) {

>      case 90:

>          if (move->axis == INPUT_AXIS_X) {

> @@ -220,16 +220,16 @@ static void qemu_input_event_trace(QemuConsole *src,

> InputEvent *evt)

>      }

>      switch (evt->type) {

>      case INPUT_EVENT_KIND_KEY:

> -        key = evt->u.key.data;

> +        key = &evt->u.key;

>          switch (key->key->type) {

>          case KEY_VALUE_KIND_NUMBER:

> -            qcode =

> qemu_input_key_number_to_qcode(key->key->u.number.data);

> +            qcode = qemu_input_key_number_to_qcode(key->key->u.number);

>              name = QKeyCode_str(qcode);

> -            trace_input_event_key_number(idx, key->key->u.number.data,

> +            trace_input_event_key_number(idx, key->key->u.number,

>                                           name, key->down);

>              break;

>          case KEY_VALUE_KIND_QCODE:

> -            name = QKeyCode_str(key->key->u.qcode.data);

> +            name = QKeyCode_str(key->key->u.qcode);

>              trace_input_event_key_qcode(idx, name, key->down);

>              break;

>          case KEY_VALUE_KIND__MAX:

> @@ -238,17 +238,17 @@ static void qemu_input_event_trace(QemuConsole *src,

> InputEvent *evt)

>          }

>          break;

>      case INPUT_EVENT_KIND_BTN:

> -        btn = evt->u.btn.data;

> +        btn = &evt->u.btn;

>          name = InputButton_str(btn->button);

>          trace_input_event_btn(idx, name, btn->down);

>          break;

>      case INPUT_EVENT_KIND_REL:

> -        move = evt->u.rel.data;

> +        move = &evt->u.rel;

>          name = InputAxis_str(move->axis);

>          trace_input_event_rel(idx, name, move->value);

>          break;

>      case INPUT_EVENT_KIND_ABS:

> -        move = evt->u.abs.data;

> +        move = &evt->u.abs;

>          name = InputAxis_str(move->axis);

>          trace_input_event_abs(idx, name, move->value);

>          break;

> @@ -355,7 +355,7 @@ void qemu_input_event_send(QemuConsole *src,

> InputEvent *evt)

>      /* Expect all parts of QEMU to send events with QCodes exclusively.

>       * Key numbers are only supported as end-user input via QMP */

>      assert(!(evt->type == INPUT_EVENT_KIND_KEY &&

> -             evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));

> +             evt->u.key.key->type == KEY_VALUE_KIND_NUMBER));

>

>

>      /*

> @@ -367,8 +367,8 @@ void qemu_input_event_send(QemuConsole *src,

> InputEvent *evt)

>       * neeed to deal with this mistake

>       */

>      if (evt->type == INPUT_EVENT_KIND_KEY &&

> -        evt->u.key.data->key->u.qcode.data == Q_KEY_CODE_SYSRQ) {

> -        evt->u.key.data->key->u.qcode.data = Q_KEY_CODE_PRINT;

> +        evt->u.key.key->u.qcode == Q_KEY_CODE_SYSRQ) {

> +        evt->u.key.key->u.qcode = Q_KEY_CODE_PRINT;

>      }

>

>      if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {

> @@ -407,10 +407,9 @@ void qemu_input_event_sync(void)

>  static InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)

>  {

>      InputEvent *evt = g_new0(InputEvent, 1);

> -    evt->u.key.data = g_new0(InputKeyEvent, 1);

>      evt->type = INPUT_EVENT_KIND_KEY;

> -    evt->u.key.data->key = key;

> -    evt->u.key.data->down = down;

> +    evt->u.key.key = key;

> +    evt->u.key.down = down;

>      return evt;

>  }

>

> @@ -440,7 +439,7 @@ void qemu_input_event_send_key_qcode(QemuConsole *src,

> QKeyCode q, bool down)

>  {

>      KeyValue *key = g_new0(KeyValue, 1);

>      key->type = KEY_VALUE_KIND_QCODE;

> -    key->u.qcode.data = q;

> +    key->u.qcode = q;

>      qemu_input_event_send_key(src, key, down);

>  }

>

> @@ -469,7 +468,7 @@ void qemu_input_queue_btn(QemuConsole *src,

> InputButton btn, bool down)

>      };

>      InputEvent evt = {

>          .type = INPUT_EVENT_KIND_BTN,

> -        .u.btn.data = &bevt,

> +        .u.btn = bevt,

>      };

>

>      qemu_input_event_send(src, &evt);

> @@ -520,7 +519,7 @@ void qemu_input_queue_rel(QemuConsole *src, InputAxis

> axis, int value)

>      };

>      InputEvent evt = {

>          .type = INPUT_EVENT_KIND_REL,

> -        .u.rel.data = &move,

> +        .u.rel = move,

>      };

>

>      qemu_input_event_send(src, &evt);

> @@ -537,7 +536,7 @@ void qemu_input_queue_abs(QemuConsole *src, InputAxis

> axis, int value,

>      };

>      InputEvent evt = {

>          .type = INPUT_EVENT_KIND_ABS,

> -        .u.abs.data = &move,

> +        .u.abs = move,

>      };

>

>      qemu_input_event_send(src, &evt);

> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c

> index 05e5c73f9d..59e317cbb8 100644

> --- a/util/qemu-sockets.c

> +++ b/util/qemu-sockets.c

> @@ -1365,21 +1365,21 @@ SocketAddress

> *socket_address_flatten(SocketAddressLegacy *addr_legacy)

>      case SOCKET_ADDRESS_LEGACY_KIND_INET:

>          addr->type = SOCKET_ADDRESS_TYPE_INET;

>          QAPI_CLONE_MEMBERS(InetSocketAddress, &addr->u.inet,

> -                           addr_legacy->u.inet.data);

> +                           &addr_legacy->u.inet);

>          break;

>      case SOCKET_ADDRESS_LEGACY_KIND_UNIX:

>          addr->type = SOCKET_ADDRESS_TYPE_UNIX;

>          QAPI_CLONE_MEMBERS(UnixSocketAddress, &addr->u.q_unix,

> -                           addr_legacy->u.q_unix.data);

> +                           &addr_legacy->u.q_unix);

>          break;

>      case SOCKET_ADDRESS_LEGACY_KIND_VSOCK:

>          addr->type = SOCKET_ADDRESS_TYPE_VSOCK;

>          QAPI_CLONE_MEMBERS(VsockSocketAddress, &addr->u.vsock,

> -                           addr_legacy->u.vsock.data);

> +                           &addr_legacy->u.vsock);

>          break;

>      case SOCKET_ADDRESS_LEGACY_KIND_FD:

>          addr->type = SOCKET_ADDRESS_TYPE_FD;

> -        QAPI_CLONE_MEMBERS(String, &addr->u.fd, addr_legacy->u.fd.data);

> +        QAPI_CLONE_MEMBERS(String, &addr->u.fd, &addr_legacy->u.fd);

>          break;

>      default:

>          abort();

> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py

> index fafec94e02..1c4e3407a3 100644

> --- a/scripts/qapi/introspect.py

> +++ b/scripts/qapi/introspect.py

> @@ -188,7 +188,12 @@ const QLitObject %(c_name)s = %(c_string)s;

>                  'variants': [self._gen_variant(v) for v in variants]}

>

>      def _gen_variant(self, variant):

> -        obj = {'case': variant.name, 'type':

> self._use_type(variant.type)}

> +        if variant.wrapped:

> +            obj = {'case': variant.name,

> +                   'type': self._use_type(variant.wrapper_type)}

> +        else:

> +            obj = {'case': variant.name,

> +                   'type': self._use_type(variant.type)}

>          return _make_tree(obj, variant.ifcond, None)

>

>      def visit_builtin_type(self, name, info, json_type):

> diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py

> index 720449feee..17525b4216 100644

> --- a/scripts/qapi/schema.py

> +++ b/scripts/qapi/schema.py

> @@ -216,6 +216,11 @@ class QAPISchemaBuiltinType(QAPISchemaType):

>          self._json_type_name = json_type

>          self._c_type_name = c_type

>

> +    def check(self, schema):

> +        # Don't check twice, it would fail an assertion

> +        if not self._checked:

> +            super().check(schema)

> +

>      def c_name(self):

>          return self.name

>

> @@ -593,18 +598,21 @@ class QAPISchemaVariants:

>                          "branch '%s' is not a value of %s"

>                          % (v.name, self.tag_member.type.describe()))

>                  if (not isinstance(v.type, QAPISchemaObjectType)

> -                        or v.type.variants):

> +                        or v.type.variants) and v.flat:

>                      raise QAPISemError(

>                          self.info,

>                          "%s cannot use %s"

>                          % (v.describe(self.info), v.type.describe()))

> -                v.type.check(schema)

> +                if isinstance(v.type, QAPISchemaObjectType):

> +                    v.type.check(schema)

>

>      def check_clash(self, info, seen):

>          for v in self.variants:

>              # Reset seen map for each variant, since qapi names from one

> -            # branch do not affect another branch

> -            v.type.check_clash(info, dict(seen))

> +            # branch do not affect another branch.  Variants that are

> +            # never flat don't even conflict with the base.

> +            if isinstance(v.type, QAPISchemaObjectType):

> +                v.type.check_clash(info, dict(seen) if v.flat else {})

>

>

>  class QAPISchemaMember:

> @@ -705,9 +713,22 @@ class QAPISchemaObjectTypeMember(QAPISchemaMember):

>  class QAPISchemaVariant(QAPISchemaObjectTypeMember):

>      role = 'branch'

>

> -    def __init__(self, name, info, typ, ifcond=None):

> +    def __init__(self, name, info, typ, ifcond=None, flat=True,

> +                 wrapper_type=None):

>          super().__init__(name, info, typ, False, ifcond)

>

> +        self.flat = flat

> +        self.wrapped = bool(wrapper_type)

> +        self.wrapper_type = wrapper_type

> +

> +        # For now, unions are either flat or wrapped, never both

> +        assert self.flat or self.wrapped

> +        assert not (self.flat and self.wrapped)

> +

> +    def check(self, schema):

> +        super().check(schema)

> +        if self.wrapped:

> +            self.wrapper_type.check(schema)

>

>  class QAPISchemaCommand(QAPISchemaEntity):

>      meta = 'command'

> @@ -1017,14 +1038,19 @@ class QAPISchema:

>      def _make_variant(self, case, typ, ifcond, info):

>          return QAPISchemaVariant(case, info, typ, ifcond)

>

> -    def _make_simple_variant(self, case, typ, ifcond, info):

> +    def _make_simple_variant(self, union_name, case, typ, ifcond, info):

>          if isinstance(typ, list):

>              assert len(typ) == 1

>              typ = self._make_array_type(typ[0], info)

> -        typ = self._make_implicit_object_type(

> -            typ, info, self.lookup_type(typ),

> -            'wrapper', [self._make_member('data', typ, None, None, info)])

> -        return QAPISchemaVariant(case, info, typ, ifcond)

> +

> +        # The wrapper type is only used for introspection compatibility.

> +        # Don't add it to the entity list of the schema.

> +        wrapper_name = 'q_obj_%s-%s-wrapper' % (union_name, case)

> +        wrapper_member = self._make_member('data', typ, None, None, info)

> +        wrapper_type = QAPISchemaObjectType(wrapper_name, info, None,

> ifcond,

> +                                            None, None, [wrapper_member],

> None)

> +        return QAPISchemaVariant(case, info, typ, ifcond, flat=False,

> +                                 wrapper_type=wrapper_type)

>

>      def _def_union_type(self, expr, info, doc):

>          name = expr['union']

> @@ -1044,7 +1070,7 @@ class QAPISchema:

>                          for (key, value) in data.items()]

>              members = []

>          else:

> -            variants = [self._make_simple_variant(key, value['type'],

> +            variants = [self._make_simple_variant(name, key,

> value['type'],

>                                                    value.get('if'), info)

>                          for (key, value) in data.items()]

>              enum = [{'name': v.name, 'if': v.ifcond} for v in variants]

> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py

> index 339f152152..f72567cbcc 100644

> --- a/scripts/qapi/visit.py

> +++ b/scripts/qapi/visit.py

> @@ -118,6 +118,34 @@ bool visit_type_%(c_name)s_members(Visitor *v,

> %(c_name)s *obj, Error **errp)

>          break;

>  ''',

>                               case=case_str)

> +            elif not isinstance(var.type, QAPISchemaObjectType):

> +                assert not var.flat

> +                ret += mcgen('''

> +    case %(case)s:

> +        return visit_type_%(c_type)s(v, "data", &obj->u.%(c_name)s, errp);

> +''',

> +                             case=case_str,

> +                             c_type=var.type.c_name(), c_name=c_name(

> var.name))

> +            elif var.wrapped:

> +                ret += mcgen('''

> +    case %(case)s:

> +    {

> +        bool ok;

> +

> +        if (!visit_start_struct(v, "data", NULL, 0, errp)) {

> +            return false;

> +        }

> +        ok = visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, errp);

> +        if (ok) {

> +            ok = visit_check_struct(v, errp);

> +        }

> +        visit_end_struct(v, NULL);

> +        return ok;

> +    }

> +''',

> +                             case=case_str,

> +                             c_type=var.type.c_name(), c_name=c_name(

> var.name))

> +

>              else:

>                  ret += mcgen('''

>      case %(case)s:

> diff --git a/tests/qapi-schema/doc-good.out

> b/tests/qapi-schema/doc-good.out

> index 419284dae2..bcbcbd2fce 100644

> --- a/tests/qapi-schema/doc-good.out

> +++ b/tests/qapi-schema/doc-good.out

> @@ -31,10 +31,6 @@ object Object

>      case two: Variant2

>          if ['IFTWO']

>      feature union-feat1

> -object q_obj_Variant1-wrapper

> -    member data: Variant1 optional=False

> -object q_obj_Variant2-wrapper

> -    member data: Variant2 optional=False

>  enum SugaredUnionKind

>      member one

>      member two

> @@ -42,8 +38,8 @@ enum SugaredUnionKind

>  object SugaredUnion

>      member type: SugaredUnionKind optional=False

>      tag type

> -    case one: q_obj_Variant1-wrapper

> -    case two: q_obj_Variant2-wrapper

> +    case one: Variant1

> +    case two: Variant2

>          if ['IFTWO']

>      feature union-feat2

>  alternate Alternate

> diff --git a/tests/qapi-schema/qapi-schema-test.out

> b/tests/qapi-schema/qapi-schema-test.out

> index 8868ca0dca..a4e4051c61 100644

> --- a/tests/qapi-schema/qapi-schema-test.out

> +++ b/tests/qapi-schema/qapi-schema-test.out

> @@ -125,36 +125,6 @@ alternate AltStrObj

>      tag type

>      case s: str

>      case o: TestStruct

> -object q_obj_intList-wrapper

> -    member data: intList optional=False

> -object q_obj_int8List-wrapper

> -    member data: int8List optional=False

> -object q_obj_int16List-wrapper

> -    member data: int16List optional=False

> -object q_obj_int32List-wrapper

> -    member data: int32List optional=False

> -object q_obj_int64List-wrapper

> -    member data: int64List optional=False

> -object q_obj_uint8List-wrapper

> -    member data: uint8List optional=False

> -object q_obj_uint16List-wrapper

> -    member data: uint16List optional=False

> -object q_obj_uint32List-wrapper

> -    member data: uint32List optional=False

> -object q_obj_uint64List-wrapper

> -    member data: uint64List optional=False

> -object q_obj_numberList-wrapper

> -    member data: numberList optional=False

> -object q_obj_boolList-wrapper

> -    member data: boolList optional=False

> -object q_obj_strList-wrapper

> -    member data: strList optional=False

> -object q_obj_sizeList-wrapper

> -    member data: sizeList optional=False

> -object q_obj_anyList-wrapper

> -    member data: anyList optional=False

> -object q_obj_StatusList-wrapper

> -    member data: StatusList optional=False

>  enum UserDefListUnionKind

>      member integer

>      member s8

> @@ -174,21 +144,21 @@ enum UserDefListUnionKind

>  object UserDefListUnion

>      member type: UserDefListUnionKind optional=False

>      tag type

> -    case integer: q_obj_intList-wrapper

> -    case s8: q_obj_int8List-wrapper

> -    case s16: q_obj_int16List-wrapper

> -    case s32: q_obj_int32List-wrapper

> -    case s64: q_obj_int64List-wrapper

> -    case u8: q_obj_uint8List-wrapper

> -    case u16: q_obj_uint16List-wrapper

> -    case u32: q_obj_uint32List-wrapper

> -    case u64: q_obj_uint64List-wrapper

> -    case number: q_obj_numberList-wrapper

> -    case boolean: q_obj_boolList-wrapper

> -    case string: q_obj_strList-wrapper

> -    case sizes: q_obj_sizeList-wrapper

> -    case any: q_obj_anyList-wrapper

> -    case user: q_obj_StatusList-wrapper

> +    case integer: intList

> +    case s8: int8List

> +    case s16: int16List

> +    case s32: int32List

> +    case s64: int64List

> +    case u8: uint8List

> +    case u16: uint16List

> +    case u32: uint32List

> +    case u64: uint64List

> +    case number: numberList

> +    case boolean: boolList

> +    case string: strList

> +    case sizes: sizeList

> +    case any: anyList

> +    case user: StatusList

>  include include/sub-module.json

>  command user_def_cmd None -> None

>      gen=True success_response=True boxed=False oob=False preconfig=False

> @@ -263,14 +233,12 @@ object __org.qemu_x-Struct

>      base __org.qemu_x-Base

>      member __org.qemu_x-member2: str optional=False

>      member wchar-t: int optional=True

> -object q_obj_str-wrapper

> -    member data: str optional=False

>  enum __org.qemu_x-Union1Kind

>      member __org.qemu_x-branch

>  object __org.qemu_x-Union1

>      member type: __org.qemu_x-Union1Kind optional=False

>      tag type

> -    case __org.qemu_x-branch: q_obj_str-wrapper

> +    case __org.qemu_x-branch: str

>  alternate __org.qemu_x-Alt1

>      tag type

>      case __org.qemu_x-branch: str

> @@ -305,8 +273,6 @@ enum TestIfEnum

>      member bar

>          if ['defined(TEST_IF_ENUM_BAR)']

>      if ['defined(TEST_IF_ENUM)']

> -object q_obj_TestStruct-wrapper

> -    member data: TestStruct optional=False

>  enum TestIfUnionKind

>      member foo

>      member union_bar

> @@ -315,8 +281,8 @@ enum TestIfUnionKind

>  object TestIfUnion

>      member type: TestIfUnionKind optional=False

>      tag type

> -    case foo: q_obj_TestStruct-wrapper

> -    case union_bar: q_obj_str-wrapper

> +    case foo: TestStruct

> +    case union_bar: str

>          if ['defined(TEST_IF_UNION_BAR)']

>      if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']

>  object q_obj_TestIfUnionCmd-arg

> --

> 2.28.0

>

>

>


-- 
Marc-André Lureau
<div dir="ltr"><div dir="ltr">Hi<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Oct 23, 2020 at 2:14 PM Kevin Wolf &lt;<a href="mailto:kwolf@redhat.com">kwolf@redhat.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Variants of simple unions are always contained in a wrapper object<br>
called &#39;data&#39; that serves no real use. When mapping a QAPI object to the<br>
command line, this becomes very visible to users because they have to<br>
add one or more useless &#39;data.&#39; to many option names.<br>
<br>
As a first step towards avoiding this painful CLI experience, this gets<br>
rid of the &#39;data&#39; indirection internally: The QAPI parser doesn&#39;t use a<br>
wrapper object as the variant type any more, so the indirection is<br>
removed from the generated C types. As a result, the C type looks the<br>
same for flat and simple unions now. A large part of this patch is<br>
mechanical conversion of C code to remove the &#39;data&#39; indirection.<br>
<br>
Conceptually, the important change is that variants can now have flat<br>
and wrapped representations. For a transitioning period, we&#39;ll allow<br>
variants to support both representations in a later patch. Eventually,<br>
the plan is to deprecate and remove wrapped representations entirely,<br>
unifying simple and flat unions.<br>
<br>
The externally visible interfaces stay unchanged: Visitors still expect<br>
the &#39;data&#39; wrappers, and introspection still shows it.<br>
<br>
Signed-off-by: Kevin Wolf &lt;<a href="mailto:kwolf@redhat.com" target="_blank">kwolf@redhat.com</a>&gt;<br></blockquote><div><br></div><div>breaks the build for me:<br></div><div><br></div><div>../chardev/spice.c: In function ‘qemu_chr_open_spice_vmc’:<br>../chardev/spice.c:261:56: error: ‘ChardevSpiceChannel’ has no member named ‘data’<br>  261 |     ChardevSpiceChannel *spicevmc = backend-&gt;u.spicevmc.data;<br>      |                                                        ^<br>../chardev/spice.c: In function ‘qemu_chr_open_spice_port’:<br>../chardev/spice.c:297:55: error: ‘ChardevSpicePort’ has no member named ‘data’<br>  297 |     ChardevSpicePort *spiceport = backend-&gt;u.spiceport.data;<br>      |                                                       ^<br>../chardev/spice.c: In function ‘qemu_chr_parse_spice_vmc’:<br>../chardev/spice.c:331:35: error: ‘ChardevSpiceChannel’ has no member named ‘data’<br>  331 |     spicevmc = backend-&gt;u.spicevmc.data = g_new0(ChardevSpiceChannel, 1);<br>      |                                   ^<br>../chardev/spice.c: In function ‘qemu_chr_parse_spice_port’:<br>../chardev/spice.c:347:37: error: ‘ChardevSpicePort’ has no member named ‘data’<br>  347 |     spiceport = backend-&gt;u.spiceport.data = g_new0(ChardevSpicePort, 1);<br>      |                                     ^<br>../ui/spice-app.c: In function ‘chr_spice_backend_new’:<br>../ui/spice-app.c:63:20: error: ‘ChardevSpicePort’ has no member named ‘data’<br>   63 |     be-&gt;u.spiceport.data = g_new0(ChardevSpicePort, 1);<br>      |                    ^<br>../ui/spice-app.c: In function ‘vc_chr_open’:<br>../ui/spice-app.c:86:20: error: ‘ChardevSpicePort’ has no member named ‘data’<br>   86 |     be-&gt;u.spiceport.data-&gt;fqdn = fqdn ?<br>      |                    ^<br>../ui/spice-app.c: In function ‘spice_app_display_init’:<br>../ui/spice-app.c:185:20: error: ‘ChardevSpicePort’ has no member named ‘data’<br>  185 |     be-&gt;u.spiceport.data-&gt;fqdn = g_strdup(&quot;org.qemu.monitor.qmp.0&quot;);<br>      |                    ^<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

---<br>
 docs/devel/qapi-code-gen.txt           | 32 ++++++++----<br>
 backends/tpm/tpm_emulator.c            |  3 +-<br>
 backends/tpm/tpm_passthrough.c         |  4 +-<br>
 block/crypto.c                         |  3 +-<br>
 block/qcow2.c                          |  9 ++--<br>
 block/vmdk.c                           | 14 ++----<br>
 blockdev.c                             | 36 ++++++-------<br>
 chardev/char-file.c                    |  5 +-<br>
 chardev/char-mux.c                     |  5 +-<br>
 chardev/char-parallel.c                |  5 +-<br>
 chardev/char-pipe.c                    |  7 ++-<br>
 chardev/char-ringbuf.c                 |  5 +-<br>
 chardev/char-serial.c                  |  5 +-<br>
 chardev/char-socket.c                  | 13 ++---<br>
 chardev/char-stdio.c                   |  5 +-<br>
 chardev/char-udp.c                     | 11 ++--<br>
 chardev/char.c                         | 10 ++--<br>
 chardev/msmouse.c                      |  4 +-<br>
 chardev/wctablet.c                     |  4 +-<br>
 hw/core/numa.c                         |  6 +--<br>
 hw/display/xenfb.c                     |  8 +--<br>
 hw/input/hid.c                         |  8 +--<br>
 hw/input/ps2.c                         |  6 +--<br>
 hw/input/virtio-input-hid.c            |  8 +--<br>
 hw/mem/pc-dimm.c                       | 18 +++----<br>
 hw/virtio/virtio-mem-pci.c             |  3 +-<br>
 hw/virtio/virtio-pmem-pci.c            |  3 +-<br>
 monitor/hmp-cmds.c                     | 14 +++---<br>
 qemu-keymap.c                          |  2 +-<br>
 replay/replay-input.c                  | 46 +++++++----------<br>
 tests/test-char.c                      | 12 ++---<br>
 tests/test-clone-visitor.c             | 14 +++---<br>
 tests/test-qmp-cmds.c                  |  2 +-<br>
 tests/test-qobject-input-visitor.c     | 24 ++++-----<br>
 tests/test-qobject-output-visitor.c    | 24 ++++-----<br>
 ui/console.c                           |  5 +-<br>
 ui/input-keymap.c                      | 12 ++---<br>
 ui/input-legacy.c                      | 12 ++---<br>
 ui/input.c                             | 43 ++++++++--------<br>
 util/qemu-sockets.c                    |  8 +--<br>
 scripts/qapi/introspect.py             |  7 ++-<br>
 scripts/qapi/schema.py                 | 48 ++++++++++++++----<br>
 scripts/qapi/visit.py                  | 28 +++++++++++<br>
 tests/qapi-schema/doc-good.out         |  8 +--<br>
 tests/qapi-schema/qapi-schema-test.out | 70 +++++++-------------------<br>
 45 files changed, 308 insertions(+), 311 deletions(-)<br>
<br>
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt<br>
index c6438c6aa9..9722c1a204 100644<br>
--- a/docs/devel/qapi-code-gen.txt<br>
+++ b/docs/devel/qapi-code-gen.txt<br>
@@ -310,7 +310,20 @@ The BRANCH&#39;s STRING name is the branch name.<br>
 The BRANCH&#39;s value defines the branch&#39;s properties, in particular its<br>
 type.  The form TYPE-REF is shorthand for { &#39;type&#39;: TYPE-REF }.<br>
<br>
-A simple union type defines a mapping from automatic discriminator<br>
+Each branch can have flat or wrapped representation in the Client JSON<br>
+Protocol.<br>
+<br>
+Wrapped representation of a branch means that it is represented by a<br>
+&#39;data&#39; member that is of the specified data type corresponding to the<br>
+discriminator value.<br>
+<br>
+Flat representation means that the union forms a single object that<br>
+contains both common members (from the base type) and the selected<br>
+branch&#39;s members, without any additional nesting.  The two sets of<br>
+member names must be disjoint.<br>
+<br>
+A simple union type automatically contains the &#39;type&#39; member as a<br>
+discriminator and defines a mapping from automatic discriminator<br>
 values to data types like in this example:<br>
<br>
  { &#39;struct&#39;: &#39;BlockdevOptionsFile&#39;, &#39;data&#39;: { &#39;filename&#39;: &#39;str&#39; } }<br>
@@ -321,10 +334,8 @@ values to data types like in this example:<br>
    &#39;data&#39;: { &#39;file&#39;: &#39;BlockdevOptionsFile&#39;,<br>
              &#39;qcow2&#39;: &#39;BlockdevOptionsQcow2&#39; } }<br>
<br>
-In the Client JSON Protocol, a simple union is represented by an<br>
-object that contains the &#39;type&#39; member as a discriminator, and a<br>
-&#39;data&#39; member that is of the specified data type corresponding to the<br>
-discriminator value, as in these examples:<br>
+In the Client JSON Protocol, all simple union branches have wrapped<br>
+representation, as in these examples:<br>
<br>
  { &quot;type&quot;: &quot;file&quot;, &quot;data&quot;: { &quot;filename&quot;: &quot;/some/place/my-image&quot; } }<br>
  { &quot;type&quot;: &quot;qcow2&quot;, &quot;data&quot;: { &quot;backing&quot;: &quot;/some/place/my-image&quot;,<br>
@@ -344,13 +355,12 @@ object, it defines common members just like a struct type&#39;s &#39;data&#39;<br>
 member defines struct type members.  If it is a STRING, it names a<br>
 struct type whose members are the common members.<br>
<br>
-All flat union branches must be of struct type.<br>
+Member &#39;discriminator&#39; must name a non-optional enum-typed member of<br>
+the base struct and defines the option that should server as the<br>
+discrimiator.<br>
<br>
-In the Client JSON Protocol, a flat union is represented by an object<br>
-with the common members (from the base type) and the selected branch&#39;s<br>
-members.  The two sets of member names must be disjoint.  Member<br>
-&#39;discriminator&#39; must name a non-optional enum-typed member of the base<br>
-struct.<br>
+All flat union branches must be of struct type.  They have always flat<br>
+representation.<br>
<br>
 The following example enhances the above simple union example by<br>
 adding an optional common member &#39;read-only&#39;, renaming the<br>
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c<br>
index 201cd38503..7d2dc2b19d 100644<br>
--- a/backends/tpm/tpm_emulator.c<br>
+++ b/backends/tpm/tpm_emulator.c<br>
@@ -629,7 +629,8 @@ static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)<br>
     TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);<br>
<br>
     options-&gt;type = TPM_TYPE_OPTIONS_KIND_EMULATOR;<br>
-    options-&gt;u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu-&gt;options);<br>
+    QAPI_CLONE_MEMBERS(TPMEmulatorOptions, &amp;options-&gt;u.emulator,<br>
+                       tpm_emu-&gt;options);<br>
<br>
     return options;<br>
 }<br>
diff --git a/backends/tpm/tpm_passthrough.c b/backends/tpm/tpm_passthrough.c<br>
index 8f6f4998a5..7fa7c84f5a 100644<br>
--- a/backends/tpm/tpm_passthrough.c<br>
+++ b/backends/tpm/tpm_passthrough.c<br>
@@ -322,8 +322,8 @@ static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)<br>
     TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);<br>
<br>
     options-&gt;type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;<br>
-    options-&gt;u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,<br>
-                                             TPM_PASSTHROUGH(tb)-&gt;options);<br>
+    QAPI_CLONE_MEMBERS(TPMPassthroughOptions, &amp;options-&gt;u.passthrough,<br>
+                       TPM_PASSTHROUGH(tb)-&gt;options);<br>
<br>
     return options;<br>
 }<br>
diff --git a/block/crypto.c b/block/crypto.c<br>
index 0807557763..0e7838d70a 100644<br>
--- a/block/crypto.c<br>
+++ b/block/crypto.c<br>
@@ -775,8 +775,7 @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)<br>
<br>
     spec_info = g_new(ImageInfoSpecific, 1);<br>
     spec_info-&gt;type = IMAGE_INFO_SPECIFIC_KIND_LUKS;<br>
-    spec_info-&gt;u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);<br>
-    *spec_info-&gt;u.luks.data = info-&gt;u.luks;<br>
+    spec_info-&gt;u.luks = info-&gt;u.luks;<br>
<br>
     /* Blank out pointers we&#39;ve just stolen to avoid double free */<br>
     memset(&amp;info-&gt;u.luks, 0, sizeof(info-&gt;u.luks));<br>
diff --git a/block/qcow2.c b/block/qcow2.c<br>
index b05512718c..104fd8ad06 100644<br>
--- a/block/qcow2.c<br>
+++ b/block/qcow2.c<br>
@@ -5052,10 +5052,9 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,<br>
     spec_info = g_new(ImageInfoSpecific, 1);<br>
     *spec_info = (ImageInfoSpecific){<br>
         .type  = IMAGE_INFO_SPECIFIC_KIND_QCOW2,<br>
-        .u.qcow2.data = g_new0(ImageInfoSpecificQCow2, 1),<br>
     };<br>
     if (s-&gt;qcow_version == 2) {<br>
-        *spec_info-&gt;u.qcow2.data = (ImageInfoSpecificQCow2){<br>
+        spec_info-&gt;u.qcow2 = (ImageInfoSpecificQCow2){<br>
             .compat             = g_strdup(&quot;0.10&quot;),<br>
             .refcount_bits      = s-&gt;refcount_bits,<br>
         };<br>
@@ -5068,7 +5067,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,<br>
             qapi_free_QCryptoBlockInfo(encrypt_info);<br>
             return NULL;<br>
         }<br>
-        *spec_info-&gt;u.qcow2.data = (ImageInfoSpecificQCow2){<br>
+        spec_info-&gt;u.qcow2 = (ImageInfoSpecificQCow2){<br>
             .compat             = g_strdup(&quot;1.1&quot;),<br>
             .lazy_refcounts     = s-&gt;compatible_features &amp;<br>
                                   QCOW2_COMPAT_LAZY_REFCOUNTS,<br>
@@ -5112,8 +5111,8 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,<br>
         memset(&amp;encrypt_info-&gt;u, 0, sizeof(encrypt_info-&gt;u));<br>
         qapi_free_QCryptoBlockInfo(encrypt_info);<br>
<br>
-        spec_info-&gt;u.qcow2.data-&gt;has_encrypt = true;<br>
-        spec_info-&gt;u.qcow2.data-&gt;encrypt = qencrypt;<br>
+        spec_info-&gt;u.qcow2.has_encrypt = true;<br>
+        spec_info-&gt;u.qcow2.encrypt = qencrypt;<br>
     }<br>
<br>
     return spec_info;<br>
diff --git a/block/vmdk.c b/block/vmdk.c<br>
index a00dc00eb4..fc4ddcc351 100644<br>
--- a/block/vmdk.c<br>
+++ b/block/vmdk.c<br>
@@ -2932,18 +2932,14 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,<br>
<br>
     *spec_info = (ImageInfoSpecific){<br>
         .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,<br>
-        .u = {<br>
-            .vmdk.data = g_new0(ImageInfoSpecificVmdk, 1),<br>
+        .u.vmdk = (ImageInfoSpecificVmdk) {<br>
+            .create_type = g_strdup(s-&gt;create_type),<br>
+            .cid = s-&gt;cid,<br>
+            .parent_cid = s-&gt;parent_cid,<br>
         },<br>
     };<br>
<br>
-    *spec_info-&gt;u.vmdk.data = (ImageInfoSpecificVmdk) {<br>
-        .create_type = g_strdup(s-&gt;create_type),<br>
-        .cid = s-&gt;cid,<br>
-        .parent_cid = s-&gt;parent_cid,<br>
-    };<br>
-<br>
-    next = &amp;spec_info-&gt;u.vmdk.data-&gt;extents;<br>
+    next = &amp;spec_info-&gt;u.vmdk.extents;<br>
     for (i = 0; i &lt; s-&gt;num_extents; i++) {<br>
         *next = g_new0(ImageInfoList, 1);<br>
         (*next)-&gt;value = vmdk_get_extent_info(&amp;s-&gt;extents[i]);<br>
diff --git a/blockdev.c b/blockdev.c<br>
index fe6fb5dc1d..2602298a26 100644<br>
--- a/blockdev.c<br>
+++ b/blockdev.c<br>
@@ -1090,7 +1090,7 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,<br>
     };<br>
     TransactionAction action = {<br>
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,<br>
-        .u.blockdev_snapshot_sync.data = &amp;snapshot,<br>
+        .u.blockdev_snapshot_sync = snapshot,<br>
     };<br>
     blockdev_do_action(&amp;action, errp);<br>
 }<br>
@@ -1104,7 +1104,7 @@ void qmp_blockdev_snapshot(const char *node, const char *overlay,<br>
     };<br>
     TransactionAction action = {<br>
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,<br>
-        .u.blockdev_snapshot.data = &amp;snapshot_data,<br>
+        .u.blockdev_snapshot = snapshot_data,<br>
     };<br>
     blockdev_do_action(&amp;action, errp);<br>
 }<br>
@@ -1119,7 +1119,7 @@ void qmp_blockdev_snapshot_internal_sync(const char *device,<br>
     };<br>
     TransactionAction action = {<br>
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,<br>
-        .u.blockdev_snapshot_internal_sync.data = &amp;snapshot,<br>
+        .u.blockdev_snapshot_internal_sync = snapshot,<br>
     };<br>
     blockdev_do_action(&amp;action, errp);<br>
 }<br>
@@ -1289,7 +1289,7 @@ static void internal_snapshot_prepare(BlkActionState *common,<br>
<br>
     g_assert(common-&gt;action-&gt;type ==<br>
              TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);<br>
-    internal = common-&gt;action-&gt;u.blockdev_snapshot_internal_sync.data;<br>
+    internal = &amp;common-&gt;action-&gt;u.blockdev_snapshot_internal_sync;<br>
     state = DO_UPCAST(InternalSnapshotState, common, common);<br>
<br>
     /* 1. parse input */<br>
@@ -1453,7 +1453,7 @@ static void external_snapshot_prepare(BlkActionState *common,<br>
     switch (action-&gt;type) {<br>
     case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:<br>
         {<br>
-            BlockdevSnapshot *s = action-&gt;u.blockdev_snapshot.data;<br>
+            BlockdevSnapshot *s = &amp;action-&gt;u.blockdev_snapshot;<br>
             device = s-&gt;node;<br>
             node_name = s-&gt;node;<br>
             new_image_file = NULL;<br>
@@ -1462,7 +1462,7 @@ static void external_snapshot_prepare(BlkActionState *common,<br>
         break;<br>
     case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:<br>
         {<br>
-            BlockdevSnapshotSync *s = action-&gt;u.blockdev_snapshot_sync.data;<br>
+            BlockdevSnapshotSync *s = &amp;action-&gt;u.blockdev_snapshot_sync;<br>
             device = s-&gt;has_device ? s-&gt;device : NULL;<br>
             node_name = s-&gt;has_node_name ? s-&gt;node_name : NULL;<br>
             new_image_file = s-&gt;snapshot_file;<br>
@@ -1507,7 +1507,7 @@ static void external_snapshot_prepare(BlkActionState *common,<br>
     }<br>
<br>
     if (action-&gt;type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {<br>
-        BlockdevSnapshotSync *s = action-&gt;u.blockdev_snapshot_sync.data;<br>
+        BlockdevSnapshotSync *s = &amp;action-&gt;u.blockdev_snapshot_sync;<br>
         const char *format = s-&gt;has_format ? s-&gt;format : &quot;qcow2&quot;;<br>
         enum NewImageMode mode;<br>
         const char *snapshot_node_name =<br>
@@ -1712,7 +1712,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)<br>
     int ret;<br>
<br>
     assert(common-&gt;action-&gt;type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);<br>
-    backup = common-&gt;action-&gt;u.drive_backup.data;<br>
+    backup = &amp;common-&gt;action-&gt;u.drive_backup;<br>
<br>
     if (!backup-&gt;has_mode) {<br>
         backup-&gt;mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;<br>
@@ -1907,7 +1907,7 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)<br>
     int ret;<br>
<br>
     assert(common-&gt;action-&gt;type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);<br>
-    backup = common-&gt;action-&gt;u.blockdev_backup.data;<br>
+    backup = &amp;common-&gt;action-&gt;u.blockdev_backup;<br>
<br>
     bs = bdrv_lookup_bs(backup-&gt;device, backup-&gt;device, errp);<br>
     if (!bs) {<br>
@@ -2012,7 +2012,7 @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,<br>
         return;<br>
     }<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_add.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_add;<br>
     /* AIO context taken and released within qmp_block_dirty_bitmap_add */<br>
     qmp_block_dirty_bitmap_add(action-&gt;node, action-&gt;name,<br>
                                action-&gt;has_granularity, action-&gt;granularity,<br>
@@ -2033,7 +2033,7 @@ static void block_dirty_bitmap_add_abort(BlkActionState *common)<br>
     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,<br>
                                              common, common);<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_add.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_add;<br>
     /* Should not be able to fail: IF the bitmap was added via .prepare(),<br>
      * then the node reference and bitmap name must have been valid.<br>
      */<br>
@@ -2053,7 +2053,7 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,<br>
         return;<br>
     }<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_clear.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_clear;<br>
     state-&gt;bitmap = block_dirty_bitmap_lookup(action-&gt;node,<br>
                                               action-&gt;name,<br>
                                               &amp;state-&gt;bs,<br>
@@ -2098,7 +2098,7 @@ static void block_dirty_bitmap_enable_prepare(BlkActionState *common,<br>
         return;<br>
     }<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_enable.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_enable;<br>
     state-&gt;bitmap = block_dirty_bitmap_lookup(action-&gt;node,<br>
                                               action-&gt;name,<br>
                                               NULL,<br>
@@ -2136,7 +2136,7 @@ static void block_dirty_bitmap_disable_prepare(BlkActionState *common,<br>
         return;<br>
     }<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_disable.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_disable;<br>
     state-&gt;bitmap = block_dirty_bitmap_lookup(action-&gt;node,<br>
                                               action-&gt;name,<br>
                                               NULL,<br>
@@ -2174,7 +2174,7 @@ static void block_dirty_bitmap_merge_prepare(BlkActionState *common,<br>
         return;<br>
     }<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_merge.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_merge;<br>
<br>
     state-&gt;bitmap = block_dirty_bitmap_merge(action-&gt;node, action-&gt;target,<br>
                                              action-&gt;bitmaps, &amp;state-&gt;backup,<br>
@@ -2192,7 +2192,7 @@ static void block_dirty_bitmap_remove_prepare(BlkActionState *common,<br>
         return;<br>
     }<br>
<br>
-    action = common-&gt;action-&gt;u.block_dirty_bitmap_remove.data;<br>
+    action = &amp;common-&gt;action-&gt;u.block_dirty_bitmap_remove;<br>
<br>
     state-&gt;bitmap = block_dirty_bitmap_remove(action-&gt;node, action-&gt;name,<br>
                                               false, &amp;state-&gt;bs, errp);<br>
@@ -2895,7 +2895,7 @@ void qmp_drive_backup(DriveBackup *backup, Error **errp)<br>
 {<br>
     TransactionAction action = {<br>
         .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP,<br>
-        .u.drive_backup.data = backup,<br>
+        .u.drive_backup = *backup,<br>
     };<br>
     blockdev_do_action(&amp;action, errp);<br>
 }<br>
@@ -2918,7 +2918,7 @@ void qmp_blockdev_backup(BlockdevBackup *backup, Error **errp)<br>
 {<br>
     TransactionAction action = {<br>
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP,<br>
-        .u.blockdev_backup.data = backup,<br>
+        .u.blockdev_backup = *backup,<br>
     };<br>
     blockdev_do_action(&amp;action, errp);<br>
 }<br>
diff --git a/chardev/char-file.c b/chardev/char-file.c<br>
index 2fd80707e5..3f0f0b6045 100644<br>
--- a/chardev/char-file.c<br>
+++ b/chardev/char-file.c<br>
@@ -39,7 +39,7 @@ static void qmp_chardev_open_file(Chardev *chr,<br>
                                   bool *be_opened,<br>
                                   Error **errp)<br>
 {<br>
-    ChardevFile *file = backend-&gt;u.file.data;<br>
+    ChardevFile *file = &amp;backend-&gt;u.file;<br>
 #ifdef _WIN32<br>
     HANDLE out;<br>
     DWORD accessmode;<br>
@@ -100,14 +100,13 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,<br>
                                     Error **errp)<br>
 {<br>
     const char *path = qemu_opt_get(opts, &quot;path&quot;);<br>
-    ChardevFile *file;<br>
+    ChardevFile *file = &amp;backend-&gt;u.file;<br>
<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_FILE;<br>
     if (path == NULL) {<br>
         error_setg(errp, &quot;chardev: file: no filename given&quot;);<br>
         return;<br>
     }<br>
-    file = backend-&gt;u.file.data = g_new0(ChardevFile, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));<br>
     file-&gt;out = g_strdup(path);<br>
<br>
diff --git a/chardev/char-mux.c b/chardev/char-mux.c<br>
index 6f980bb836..bfb4bc6b8b 100644<br>
--- a/chardev/char-mux.c<br>
+++ b/chardev/char-mux.c<br>
@@ -314,7 +314,7 @@ static void qemu_chr_open_mux(Chardev *chr,<br>
                               bool *be_opened,<br>
                               Error **errp)<br>
 {<br>
-    ChardevMux *mux = backend-&gt;u.mux.data;<br>
+    ChardevMux *mux = &amp;backend-&gt;u.mux;<br>
     Chardev *drv;<br>
     MuxChardev *d = MUX_CHARDEV(chr);<br>
<br>
@@ -336,14 +336,13 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,<br>
                                Error **errp)<br>
 {<br>
     const char *chardev = qemu_opt_get(opts, &quot;chardev&quot;);<br>
-    ChardevMux *mux;<br>
+    ChardevMux *mux = &amp;backend-&gt;u.mux;<br>
<br>
     if (chardev == NULL) {<br>
         error_setg(errp, &quot;chardev: mux: no chardev given&quot;);<br>
         return;<br>
     }<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_MUX;<br>
-    mux = backend-&gt;u.mux.data = g_new0(ChardevMux, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));<br>
     mux-&gt;chardev = g_strdup(chardev);<br>
 }<br>
diff --git a/chardev/char-parallel.c b/chardev/char-parallel.c<br>
index 05e7efbd6c..a17157a3be 100644<br>
--- a/chardev/char-parallel.c<br>
+++ b/chardev/char-parallel.c<br>
@@ -244,7 +244,7 @@ static void qmp_chardev_open_parallel(Chardev *chr,<br>
                                       bool *be_opened,<br>
                                       Error **errp)<br>
 {<br>
-    ChardevHostdev *parallel = backend-&gt;u.parallel.data;<br>
+    ChardevHostdev *parallel = &amp;backend-&gt;u.parallel;<br>
     int fd;<br>
<br>
     fd = qmp_chardev_open_file_source(parallel-&gt;device, O_RDWR, errp);<br>
@@ -258,14 +258,13 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,<br>
                                     Error **errp)<br>
 {<br>
     const char *device = qemu_opt_get(opts, &quot;path&quot;);<br>
-    ChardevHostdev *parallel;<br>
+    ChardevHostdev *parallel = &amp;backend-&gt;u.parallel;<br>
<br>
     if (device == NULL) {<br>
         error_setg(errp, &quot;chardev: parallel: no device path given&quot;);<br>
         return;<br>
     }<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_PARALLEL;<br>
-    parallel = backend-&gt;u.parallel.data = g_new0(ChardevHostdev, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));<br>
     parallel-&gt;device = g_strdup(device);<br>
 }<br>
diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c<br>
index 7eca5d9a56..eb19d9a526 100644<br>
--- a/chardev/char-pipe.c<br>
+++ b/chardev/char-pipe.c<br>
@@ -109,7 +109,7 @@ static void qemu_chr_open_pipe(Chardev *chr,<br>
                                bool *be_opened,<br>
                                Error **errp)<br>
 {<br>
-    ChardevHostdev *opts = backend-&gt;u.pipe.data;<br>
+    ChardevHostdev *opts = &amp;backend-&gt;u.pipe;<br>
     const char *filename = opts-&gt;device;<br>
<br>
     if (win_chr_pipe_init(chr, filename, errp) &lt; 0) {<br>
@@ -124,7 +124,7 @@ static void qemu_chr_open_pipe(Chardev *chr,<br>
                                bool *be_opened,<br>
                                Error **errp)<br>
 {<br>
-    ChardevHostdev *opts = backend-&gt;u.pipe.data;<br>
+    ChardevHostdev *opts = &amp;backend-&gt;u.pipe;<br>
     int fd_in, fd_out;<br>
     char *filename_in;<br>
     char *filename_out;<br>
@@ -158,14 +158,13 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,<br>
                                 Error **errp)<br>
 {<br>
     const char *device = qemu_opt_get(opts, &quot;path&quot;);<br>
-    ChardevHostdev *dev;<br>
+    ChardevHostdev *dev = &amp;backend-&gt;u.pipe;<br>
<br>
     if (device == NULL) {<br>
         error_setg(errp, &quot;chardev: pipe: no device path given&quot;);<br>
         return;<br>
     }<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_PIPE;<br>
-    dev = backend-&gt;u.pipe.data = g_new0(ChardevHostdev, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));<br>
     dev-&gt;device = g_strdup(device);<br>
 }<br>
diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c<br>
index d40d21d3cf..0ef2a17f90 100644<br>
--- a/chardev/char-ringbuf.c<br>
+++ b/chardev/char-ringbuf.c<br>
@@ -97,7 +97,7 @@ static void qemu_chr_open_ringbuf(Chardev *chr,<br>
                                   bool *be_opened,<br>
                                   Error **errp)<br>
 {<br>
-    ChardevRingbuf *opts = backend-&gt;u.ringbuf.data;<br>
+    ChardevRingbuf *opts = &amp;backend-&gt;u.ringbuf;<br>
     RingBufChardev *d = RINGBUF_CHARDEV(chr);<br>
<br>
     d-&gt;size = opts-&gt;has_size ? opts-&gt;size : 65536;<br>
@@ -210,10 +210,9 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,<br>
                                    Error **errp)<br>
 {<br>
     int val;<br>
-    ChardevRingbuf *ringbuf;<br>
+    ChardevRingbuf *ringbuf = &amp;backend-&gt;u.ringbuf;<br>
<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_RINGBUF;<br>
-    ringbuf = backend-&gt;u.ringbuf.data = g_new0(ChardevRingbuf, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));<br>
<br>
     val = qemu_opt_get_size(opts, &quot;size&quot;, 0);<br>
diff --git a/chardev/char-serial.c b/chardev/char-serial.c<br>
index 7c3d84ae24..baec955ecf 100644<br>
--- a/chardev/char-serial.c<br>
+++ b/chardev/char-serial.c<br>
@@ -263,7 +263,7 @@ static void qmp_chardev_open_serial(Chardev *chr,<br>
                                     bool *be_opened,<br>
                                     Error **errp)<br>
 {<br>
-    ChardevHostdev *serial = backend-&gt;u.serial.data;<br>
+    ChardevHostdev *serial = &amp;backend-&gt;u.serial;<br>
     int fd;<br>
<br>
     fd = qmp_chardev_open_file_source(serial-&gt;device, O_RDWR | O_NONBLOCK,<br>
@@ -283,14 +283,13 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,<br>
                                   Error **errp)<br>
 {<br>
     const char *device = qemu_opt_get(opts, &quot;path&quot;);<br>
-    ChardevHostdev *serial;<br>
+    ChardevHostdev *serial = &amp;backend-&gt;u.serial;<br>
<br>
     if (device == NULL) {<br>
         error_setg(errp, &quot;chardev: serial/tty: no device path given&quot;);<br>
         return;<br>
     }<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_SERIAL;<br>
-    serial = backend-&gt;u.serial.data = g_new0(ChardevHostdev, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));<br>
     serial-&gt;device = g_strdup(device);<br>
 }<br>
diff --git a/chardev/char-socket.c b/chardev/char-socket.c<br>
index 95e45812d5..5332439d34 100644<br>
--- a/chardev/char-socket.c<br>
+++ b/chardev/char-socket.c<br>
@@ -1301,7 +1301,7 @@ static void qmp_chardev_open_socket(Chardev *chr,<br>
                                     Error **errp)<br>
 {<br>
     SocketChardev *s = SOCKET_CHARDEV(chr);<br>
-    ChardevSocket *sock = backend-&gt;u.socket.data;<br>
+    ChardevSocket *sock = &amp;backend-&gt;u.socket;<br>
     bool do_nodelay     = sock-&gt;has_nodelay ? sock-&gt;nodelay : false;<br>
     bool is_listen      = sock-&gt;has_server  ? sock-&gt;server  : true;<br>
     bool is_telnet      = sock-&gt;has_telnet  ? sock-&gt;telnet  : false;<br>
@@ -1403,7 +1403,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,<br>
     }<br>
<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_SOCKET;<br>
-    sock = backend-&gt;u.socket.data = g_new0(ChardevSocket, 1);<br>
+    sock = &amp;backend-&gt;u.socket;<br>
     qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));<br>
<br>
     sock-&gt;has_nodelay = qemu_opt_get(opts, &quot;delay&quot;);<br>
@@ -1435,16 +1435,14 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,<br>
<br>
     addr = g_new0(SocketAddressLegacy, 1);<br>
     if (path) {<br>
-        UnixSocketAddress *q_unix;<br>
+        UnixSocketAddress *q_unix = &amp;addr-&gt;u.q_unix;<br>
         addr-&gt;type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;<br>
-        q_unix = addr-&gt;u.q_unix.data = g_new0(UnixSocketAddress, 1);<br>
         q_unix-&gt;path = g_strdup(path);<br>
         q_unix-&gt;tight = tight;<br>
         q_unix-&gt;abstract = abstract;<br>
     } else if (host) {<br>
         addr-&gt;type = SOCKET_ADDRESS_LEGACY_KIND_INET;<br>
-        addr-&gt;u.inet.data = g_new(InetSocketAddress, 1);<br>
-        *addr-&gt;u.inet.data = (InetSocketAddress) {<br>
+        addr-&gt;u.inet = (InetSocketAddress) {<br>
             .host = g_strdup(host),<br>
             .port = g_strdup(port),<br>
             .has_to = qemu_opt_get(opts, &quot;to&quot;),<br>
@@ -1456,8 +1454,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,<br>
         };<br>
     } else if (fd) {<br>
         addr-&gt;type = SOCKET_ADDRESS_LEGACY_KIND_FD;<br>
-        addr-&gt;u.fd.data = g_new(String, 1);<br>
-        addr-&gt;u.fd.data-&gt;str = g_strdup(fd);<br>
+        addr-&gt;u.fd.str = g_strdup(fd);<br>
     } else {<br>
         g_assert_not_reached();<br>
     }<br>
diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c<br>
index 403da308c9..81ee655a21 100644<br>
--- a/chardev/char-stdio.c<br>
+++ b/chardev/char-stdio.c<br>
@@ -87,7 +87,7 @@ static void qemu_chr_open_stdio(Chardev *chr,<br>
                                 bool *be_opened,<br>
                                 Error **errp)<br>
 {<br>
-    ChardevStdio *opts = backend-&gt;u.stdio.data;<br>
+    ChardevStdio *opts = &amp;backend-&gt;u.stdio;<br>
     struct sigaction act;<br>
<br>
     if (is_daemonized()) {<br>
@@ -120,10 +120,9 @@ static void qemu_chr_open_stdio(Chardev *chr,<br>
 static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,<br>
                                  Error **errp)<br>
 {<br>
-    ChardevStdio *stdio;<br>
+    ChardevStdio *stdio = &amp;backend-&gt;u.stdio;<br>
<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_STDIO;<br>
-    stdio = backend-&gt;u.stdio.data = g_new0(ChardevStdio, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));<br>
     stdio-&gt;has_signal = true;<br>
     stdio-&gt;signal = qemu_opt_get_bool(opts, &quot;signal&quot;, true);<br>
diff --git a/chardev/char-udp.c b/chardev/char-udp.c<br>
index 16b5dbce58..3b1bdddbbd 100644<br>
--- a/chardev/char-udp.c<br>
+++ b/chardev/char-udp.c<br>
@@ -140,7 +140,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,<br>
     const char *localport = qemu_opt_get(opts, &quot;localport&quot;);<br>
     bool has_local = false;<br>
     SocketAddressLegacy *addr;<br>
-    ChardevUdp *udp;<br>
+    ChardevUdp *udp = &amp;backend-&gt;u.udp;<br>
<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_UDP;<br>
     if (host == NULL || strlen(host) == 0) {<br>
@@ -161,13 +161,11 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,<br>
         has_local = true;<br>
     }<br>
<br>
-    udp = backend-&gt;u.udp.data = g_new0(ChardevUdp, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));<br>
<br>
     addr = g_new0(SocketAddressLegacy, 1);<br>
     addr-&gt;type = SOCKET_ADDRESS_LEGACY_KIND_INET;<br>
-    addr-&gt;u.inet.data = g_new(InetSocketAddress, 1);<br>
-    *addr-&gt;u.inet.data = (InetSocketAddress) {<br>
+    addr-&gt;u.inet = (InetSocketAddress) {<br>
         .host = g_strdup(host),<br>
         .port = g_strdup(port),<br>
         .has_ipv4 = qemu_opt_get(opts, &quot;ipv4&quot;),<br>
@@ -181,8 +179,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,<br>
         udp-&gt;has_local = true;<br>
         addr = g_new0(SocketAddressLegacy, 1);<br>
         addr-&gt;type = SOCKET_ADDRESS_LEGACY_KIND_INET;<br>
-        addr-&gt;u.inet.data = g_new(InetSocketAddress, 1);<br>
-        *addr-&gt;u.inet.data = (InetSocketAddress) {<br>
+        addr-&gt;u.inet = (InetSocketAddress) {<br>
             .host = g_strdup(localaddr),<br>
             .port = g_strdup(localport),<br>
         };<br>
@@ -195,7 +192,7 @@ static void qmp_chardev_open_udp(Chardev *chr,<br>
                                  bool *be_opened,<br>
                                  Error **errp)<br>
 {<br>
-    ChardevUdp *udp = backend-&gt;u.udp.data;<br>
+    ChardevUdp *udp = &amp;backend-&gt;u.udp;<br>
     SocketAddress *local_addr = socket_address_flatten(udp-&gt;local);<br>
     SocketAddress *remote_addr = socket_address_flatten(udp-&gt;remote);<br>
     QIOChannelSocket *sioc = qio_channel_socket_new();<br>
diff --git a/chardev/char.c b/chardev/char.c<br>
index 028612c333..5192964694 100644<br>
--- a/chardev/char.c<br>
+++ b/chardev/char.c<br>
@@ -238,7 +238,7 @@ static void qemu_char_open(Chardev *chr, ChardevBackend *backend,<br>
 {<br>
     ChardevClass *cc = CHARDEV_GET_CLASS(chr);<br>
     /* Any ChardevCommon member would work */<br>
-    ChardevCommon *common = backend ? backend-&gt;u.null.data : NULL;<br>
+    ChardevCommon *common = backend ? &amp;backend-&gt;u.null : NULL;<br>
<br>
     if (common &amp;&amp; common-&gt;has_logfile) {<br>
         int flags = O_WRONLY | O_CREAT;<br>
@@ -625,9 +625,8 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)<br>
             return NULL;<br>
         }<br>
     } else {<br>
-        ChardevCommon *ccom = g_new0(ChardevCommon, 1);<br>
-        qemu_chr_parse_common(opts, ccom);<br>
-        backend-&gt;u.null.data = ccom; /* Any ChardevCommon member would work */<br>
+        /* Any ChardevCommon member would work */<br>
+        qemu_chr_parse_common(opts, &amp;backend-&gt;u.null);<br>
     }<br>
<br>
     return backend;<br>
@@ -690,8 +689,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context,<br>
         qapi_free_ChardevBackend(backend);<br>
         backend = g_new0(ChardevBackend, 1);<br>
         backend-&gt;type = CHARDEV_BACKEND_KIND_MUX;<br>
-        backend-&gt;u.mux.data = g_new0(ChardevMux, 1);<br>
-        backend-&gt;u.mux.data-&gt;chardev = g_strdup(bid);<br>
+        backend-&gt;u.mux.chardev = g_strdup(bid);<br>
         mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context, errp);<br>
         if (mux == NULL) {<br>
             object_unparent(OBJECT(chr));<br>
diff --git a/chardev/msmouse.c b/chardev/msmouse.c<br>
index eb9231dcdb..98b0ef8cd7 100644<br>
--- a/chardev/msmouse.c<br>
+++ b/chardev/msmouse.c<br>
@@ -111,12 +111,12 @@ static void msmouse_input_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         mouse-&gt;axis[move-&gt;axis] += move-&gt;value;<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         mouse-&gt;btns[btn-&gt;button] = btn-&gt;down;<br>
         mouse-&gt;btnc[btn-&gt;button] = true;<br>
         break;<br>
diff --git a/chardev/wctablet.c b/chardev/wctablet.c<br>
index 95e005f5a5..8479f59183 100644<br>
--- a/chardev/wctablet.c<br>
+++ b/chardev/wctablet.c<br>
@@ -154,12 +154,12 @@ static void wctablet_input_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         tablet-&gt;axis[move-&gt;axis] = move-&gt;value;<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         tablet-&gt;btns[btn-&gt;button] = btn-&gt;down;<br>
         break;<br>
<br>
diff --git a/hw/core/numa.c b/hw/core/numa.c<br>
index 7c4dd4e68e..24fe0e11d8 100644<br>
--- a/hw/core/numa.c<br>
+++ b/hw/core/numa.c<br>
@@ -765,19 +765,19 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])<br>
             case MEMORY_DEVICE_INFO_KIND_DIMM:<br>
             case MEMORY_DEVICE_INFO_KIND_NVDIMM:<br>
                 pcdimm_info = value-&gt;type == MEMORY_DEVICE_INFO_KIND_DIMM ?<br>
-                              value-&gt;u.dimm.data : value-&gt;u.nvdimm.data;<br>
+                              &amp;value-&gt;u.dimm : &amp;value-&gt;u.nvdimm;<br>
                 node_mem[pcdimm_info-&gt;node].node_mem += pcdimm_info-&gt;size;<br>
                 node_mem[pcdimm_info-&gt;node].node_plugged_mem +=<br>
                     pcdimm_info-&gt;size;<br>
                 break;<br>
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:<br>
-                vpi = value-&gt;u.virtio_pmem.data;<br>
+                vpi = &amp;value-&gt;u.virtio_pmem;<br>
                 /* TODO: once we support numa, assign to right node */<br>
                 node_mem[0].node_mem += vpi-&gt;size;<br>
                 node_mem[0].node_plugged_mem += vpi-&gt;size;<br>
                 break;<br>
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM:<br>
-                vmi = value-&gt;u.virtio_mem.data;<br>
+                vmi = &amp;value-&gt;u.virtio_mem;<br>
                 node_mem[vmi-&gt;node].node_mem += vmi-&gt;size;<br>
                 node_mem[vmi-&gt;node].node_plugged_mem += vmi-&gt;size;<br>
                 break;<br>
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c<br>
index 838260b6ad..6aa6010774 100644<br>
--- a/hw/display/xenfb.c<br>
+++ b/hw/display/xenfb.c<br>
@@ -201,7 +201,7 @@ static void xenfb_key_event(DeviceState *dev, QemuConsole *src,<br>
                             InputEvent *evt)<br>
 {<br>
     struct XenInput *xenfb = (struct XenInput *)dev;<br>
-    InputKeyEvent *key = evt-&gt;u.key.data;<br>
+    InputKeyEvent *key = &amp;evt-&gt;u.key;<br>
     int qcode = qemu_input_key_value_to_qcode(key-&gt;key);<br>
     int lnx;<br>
<br>
@@ -236,7 +236,7 @@ static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         switch (btn-&gt;button) {<br>
         case INPUT_BUTTON_LEFT:<br>
             xenfb_send_key(xenfb, btn-&gt;down, BTN_LEFT);<br>
@@ -263,7 +263,7 @@ static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         if (xenfb-&gt;raw_pointer_wanted) {<br>
             xenfb-&gt;axis[move-&gt;axis] = move-&gt;value;<br>
         } else {<br>
@@ -289,7 +289,7 @@ static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         xenfb-&gt;axis[move-&gt;axis] += move-&gt;value;<br>
         break;<br>
<br>
diff --git a/hw/input/hid.c b/hw/input/hid.c<br>
index 89239b5634..2472c5a902 100644<br>
--- a/hw/input/hid.c<br>
+++ b/hw/input/hid.c<br>
@@ -126,7 +126,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         if (move-&gt;axis == INPUT_AXIS_X) {<br>
             e-&gt;xdx += move-&gt;value;<br>
         } else if (move-&gt;axis == INPUT_AXIS_Y) {<br>
@@ -135,7 +135,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         if (move-&gt;axis == INPUT_AXIS_X) {<br>
             e-&gt;xdx = move-&gt;value;<br>
         } else if (move-&gt;axis == INPUT_AXIS_Y) {<br>
@@ -144,7 +144,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         if (btn-&gt;down) {<br>
             e-&gt;buttons_state |= bmap[btn-&gt;button];<br>
             if (btn-&gt;button == INPUT_BUTTON_WHEEL_UP) {<br>
@@ -230,7 +230,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,<br>
     HIDState *hs = (HIDState *)dev;<br>
     int scancodes[3], i, count;<br>
     int slot;<br>
-    InputKeyEvent *key = evt-&gt;u.key.data;<br>
+    InputKeyEvent *key = &amp;evt-&gt;u.key;<br>
<br>
     count = qemu_input_key_value_to_scancode(key-&gt;key,<br>
                                              key-&gt;down,<br>
diff --git a/hw/input/ps2.c b/hw/input/ps2.c<br>
index f8746d2f52..1176ccc88c 100644<br>
--- a/hw/input/ps2.c<br>
+++ b/hw/input/ps2.c<br>
@@ -284,7 +284,7 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,<br>
                                InputEvent *evt)<br>
 {<br>
     PS2KbdState *s = (PS2KbdState *)dev;<br>
-    InputKeyEvent *key = evt-&gt;u.key.data;<br>
+    InputKeyEvent *key = &amp;evt-&gt;u.key;<br>
     int qcode;<br>
     uint16_t keycode = 0;<br>
     int mod;<br>
@@ -727,7 +727,7 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         if (move-&gt;axis == INPUT_AXIS_X) {<br>
             s-&gt;mouse_dx += move-&gt;value;<br>
         } else if (move-&gt;axis == INPUT_AXIS_Y) {<br>
@@ -736,7 +736,7 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,<br>
         break;<br>
<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         if (btn-&gt;down) {<br>
             s-&gt;mouse_buttons |= bmap[btn-&gt;button];<br>
             if (btn-&gt;button == INPUT_BUTTON_WHEEL_UP) {<br>
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c<br>
index a7a244a95d..1c7b07cf42 100644<br>
--- a/hw/input/virtio-input-hid.c<br>
+++ b/hw/input/virtio-input-hid.c<br>
@@ -83,7 +83,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_KEY:<br>
-        key = evt-&gt;u.key.data;<br>
+        key = &amp;evt-&gt;u.key;<br>
         qcode = qemu_input_key_value_to_qcode(key-&gt;key);<br>
         if (qcode &lt; qemu_input_map_qcode_to_linux_len &amp;&amp;<br>
             qemu_input_map_qcode_to_linux[qcode]) {<br>
@@ -99,7 +99,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,<br>
         }<br>
         break;<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         if (vhid-&gt;wheel_axis &amp;&amp;<br>
             (btn-&gt;button == INPUT_BUTTON_WHEEL_UP ||<br>
              btn-&gt;button == INPUT_BUTTON_WHEEL_DOWN) &amp;&amp;<br>
@@ -123,14 +123,14 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,<br>
         }<br>
         break;<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         event.type  = cpu_to_le16(EV_REL);<br>
         event.code  = cpu_to_le16(axismap_rel[move-&gt;axis]);<br>
         event.value = cpu_to_le32(move-&gt;value);<br>
         virtio_input_send(vinput, &amp;event);<br>
         break;<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         event.type  = cpu_to_le16(EV_ABS);<br>
         event.code  = cpu_to_le16(axismap_abs[move-&gt;axis]);<br>
         event.value = cpu_to_le32(move-&gt;value);<br>
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c<br>
index c30351070b..3d6f836621 100644<br>
--- a/hw/mem/pc-dimm.c<br>
+++ b/hw/mem/pc-dimm.c<br>
@@ -236,11 +236,19 @@ static MemoryRegion *pc_dimm_md_get_memory_region(MemoryDeviceState *md,<br>
 static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,<br>
                                         MemoryDeviceInfo *info)<br>
 {<br>
-    PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);<br>
+    PCDIMMDeviceInfo *di;<br>
     const DeviceClass *dc = DEVICE_GET_CLASS(md);<br>
     const PCDIMMDevice *dimm = PC_DIMM(md);<br>
     const DeviceState *dev = DEVICE(md);<br>
<br>
+    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {<br>
+        di = &amp;info-&gt;u.nvdimm;<br>
+        info-&gt;type = MEMORY_DEVICE_INFO_KIND_NVDIMM;<br>
+    } else {<br>
+        di = &amp;info-&gt;u.dimm;<br>
+        info-&gt;type = MEMORY_DEVICE_INFO_KIND_DIMM;<br>
+    }<br>
+<br>
     if (dev-&gt;id) {<br>
         di-&gt;has_id = true;<br>
         di-&gt;id = g_strdup(dev-&gt;id);<br>
@@ -253,14 +261,6 @@ static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,<br>
     di-&gt;size = object_property_get_uint(OBJECT(dimm), PC_DIMM_SIZE_PROP,<br>
                                         NULL);<br>
     di-&gt;memdev = object_get_canonical_path(OBJECT(dimm-&gt;hostmem));<br>
-<br>
-    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {<br>
-        info-&gt;u.nvdimm.data = di;<br>
-        info-&gt;type = MEMORY_DEVICE_INFO_KIND_NVDIMM;<br>
-    } else {<br>
-        info-&gt;u.dimm.data = di;<br>
-        info-&gt;type = MEMORY_DEVICE_INFO_KIND_DIMM;<br>
-    }<br>
 }<br>
<br>
 static void pc_dimm_class_init(ObjectClass *oc, void *data)<br>
diff --git a/hw/virtio/virtio-mem-pci.c b/hw/virtio/virtio-mem-pci.c<br>
index 913f4a3326..f93572fc27 100644<br>
--- a/hw/virtio/virtio-mem-pci.c<br>
+++ b/hw/virtio/virtio-mem-pci.c<br>
@@ -58,7 +58,7 @@ static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState *md,<br>
 static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,<br>
                                             MemoryDeviceInfo *info)<br>
 {<br>
-    VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);<br>
+    VirtioMEMDeviceInfo *vi = &amp;info-&gt;u.virtio_mem;<br>
     VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);<br>
     VirtIOMEM *vmem = VIRTIO_MEM(&amp;pci_mem-&gt;vdev);<br>
     VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);<br>
@@ -72,7 +72,6 @@ static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,<br>
     /* let the real device handle everything else */<br>
     vpc-&gt;fill_device_info(vmem, vi);<br>
<br>
-    info-&gt;u.virtio_mem.data = vi;<br>
     info-&gt;type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;<br>
 }<br>
<br>
diff --git a/hw/virtio/virtio-pmem-pci.c b/hw/virtio/virtio-pmem-pci.c<br>
index 2b2a0b1eae..adf17f873b 100644<br>
--- a/hw/virtio/virtio-pmem-pci.c<br>
+++ b/hw/virtio/virtio-pmem-pci.c<br>
@@ -63,7 +63,7 @@ static uint64_t virtio_pmem_pci_get_plugged_size(const MemoryDeviceState *md,<br>
 static void virtio_pmem_pci_fill_device_info(const MemoryDeviceState *md,<br>
                                              MemoryDeviceInfo *info)<br>
 {<br>
-    VirtioPMEMDeviceInfo *vi = g_new0(VirtioPMEMDeviceInfo, 1);<br>
+    VirtioPMEMDeviceInfo *vi = &amp;info-&gt;u.virtio_pmem;<br>
     VirtIOPMEMPCI *pci_pmem = VIRTIO_PMEM_PCI(md);<br>
     VirtIOPMEM *pmem = VIRTIO_PMEM(&amp;pci_pmem-&gt;vdev);<br>
     VirtIOPMEMClass *vpc = VIRTIO_PMEM_GET_CLASS(pmem);<br>
@@ -77,7 +77,6 @@ static void virtio_pmem_pci_fill_device_info(const MemoryDeviceState *md,<br>
     /* let the real device handle everything else */<br>
     vpc-&gt;fill_device_info(pmem, vi);<br>
<br>
-    info-&gt;u.virtio_pmem.data = vi;<br>
     info-&gt;type = MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM;<br>
 }<br>
<br>
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c<br>
index 9789f4277f..0324caa114 100644<br>
--- a/monitor/hmp-cmds.c<br>
+++ b/monitor/hmp-cmds.c<br>
@@ -918,7 +918,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)<br>
<br>
         switch (ti-&gt;options-&gt;type) {<br>
         case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:<br>
-            tpo = ti-&gt;options-&gt;u.passthrough.data;<br>
+            tpo = &amp;ti-&gt;options-&gt;u.passthrough;<br>
             monitor_printf(mon, &quot;%s%s%s%s&quot;,<br>
                            tpo-&gt;has_path ? &quot;,path=&quot; : &quot;&quot;,<br>
                            tpo-&gt;has_path ? tpo-&gt;path : &quot;&quot;,<br>
@@ -926,7 +926,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)<br>
                            tpo-&gt;has_cancel_path ? tpo-&gt;cancel_path : &quot;&quot;);<br>
             break;<br>
         case TPM_TYPE_OPTIONS_KIND_EMULATOR:<br>
-            teo = ti-&gt;options-&gt;u.emulator.data;<br>
+            teo = &amp;ti-&gt;options-&gt;u.emulator;<br>
             monitor_printf(mon, &quot;,chardev=%s&quot;, teo-&gt;chardev);<br>
             break;<br>
         case TPM_TYPE_OPTIONS_KIND__MAX:<br>
@@ -1728,14 +1728,14 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)<br>
                 goto err_out;<br>
             }<br>
             keylist-&gt;value-&gt;type = KEY_VALUE_KIND_NUMBER;<br>
-            keylist-&gt;value-&gt;u.number.data = value;<br>
+            keylist-&gt;value-&gt;u.number = value;<br>
         } else {<br>
             int idx = index_from_key(keys, keyname_len);<br>
             if (idx == Q_KEY_CODE__MAX) {<br>
                 goto err_out;<br>
             }<br>
             keylist-&gt;value-&gt;type = KEY_VALUE_KIND_QCODE;<br>
-            keylist-&gt;value-&gt;u.qcode.data = idx;<br>
+            keylist-&gt;value-&gt;u.qcode = idx;<br>
         }<br>
<br>
         if (!*separator) {<br>
@@ -1860,7 +1860,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)<br>
             case MEMORY_DEVICE_INFO_KIND_DIMM:<br>
             case MEMORY_DEVICE_INFO_KIND_NVDIMM:<br>
                 di = value-&gt;type == MEMORY_DEVICE_INFO_KIND_DIMM ?<br>
-                     value-&gt;u.dimm.data : value-&gt;u.nvdimm.data;<br>
+                     &amp;value-&gt;u.dimm : &amp;value-&gt;u.nvdimm;<br>
                 monitor_printf(mon, &quot;Memory device [%s]: \&quot;%s\&quot;\n&quot;,<br>
                                MemoryDeviceInfoKind_str(value-&gt;type),<br>
                                di-&gt;id ? di-&gt;id : &quot;&quot;);<br>
@@ -1875,7 +1875,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)<br>
                                di-&gt;hotpluggable ? &quot;true&quot; : &quot;false&quot;);<br>
                 break;<br>
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:<br>
-                vpi = value-&gt;u.virtio_pmem.data;<br>
+                vpi = &amp;value-&gt;u.virtio_pmem;<br>
                 monitor_printf(mon, &quot;Memory device [%s]: \&quot;%s\&quot;\n&quot;,<br>
                                MemoryDeviceInfoKind_str(value-&gt;type),<br>
                                vpi-&gt;id ? vpi-&gt;id : &quot;&quot;);<br>
@@ -1884,7 +1884,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)<br>
                 monitor_printf(mon, &quot;  memdev: %s\n&quot;, vpi-&gt;memdev);<br>
                 break;<br>
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM:<br>
-                vmi = value-&gt;u.virtio_mem.data;<br>
+                vmi = &amp;value-&gt;u.virtio_mem;<br>
                 monitor_printf(mon, &quot;Memory device [%s]: \&quot;%s\&quot;\n&quot;,<br>
                                MemoryDeviceInfoKind_str(value-&gt;type),<br>
                                vmi-&gt;id ? vmi-&gt;id : &quot;&quot;);<br>
diff --git a/qemu-keymap.c b/qemu-keymap.c<br>
index 536e8f2385..52637c449c 100644<br>
--- a/qemu-keymap.c<br>
+++ b/qemu-keymap.c<br>
@@ -38,7 +38,7 @@ static uint32_t qcode_to_number(uint32_t qcode)<br>
     uint32_t number;<br>
<br>
     keyvalue.type = KEY_VALUE_KIND_QCODE;<br>
-    keyvalue.u.qcode.data = qcode;<br>
+    keyvalue.u.qcode = qcode;<br>
     number = qemu_input_key_value_to_number(&amp;keyvalue);<br>
     assert(number != 0);<br>
     return number;<br>
diff --git a/replay/replay-input.c b/replay/replay-input.c<br>
index 1147e3d34e..c1eb1b79e1 100644<br>
--- a/replay/replay-input.c<br>
+++ b/replay/replay-input.c<br>
@@ -26,16 +26,16 @@ void replay_save_input_event(InputEvent *evt)<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_KEY:<br>
-        key = evt-&gt;u.key.data;<br>
+        key = &amp;evt-&gt;u.key;<br>
         replay_put_dword(key-&gt;key-&gt;type);<br>
<br>
         switch (key-&gt;key-&gt;type) {<br>
         case KEY_VALUE_KIND_NUMBER:<br>
-            replay_put_qword(key-&gt;key-&gt;u.number.data);<br>
+            replay_put_qword(key-&gt;key-&gt;u.number);<br>
             replay_put_byte(key-&gt;down);<br>
             break;<br>
         case KEY_VALUE_KIND_QCODE:<br>
-            replay_put_dword(key-&gt;key-&gt;u.qcode.data);<br>
+            replay_put_dword(key-&gt;key-&gt;u.qcode);<br>
             replay_put_byte(key-&gt;down);<br>
             break;<br>
         case KEY_VALUE_KIND__MAX:<br>
@@ -44,17 +44,17 @@ void replay_save_input_event(InputEvent *evt)<br>
         }<br>
         break;<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         replay_put_dword(btn-&gt;button);<br>
         replay_put_byte(btn-&gt;down);<br>
         break;<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         replay_put_dword(move-&gt;axis);<br>
         replay_put_qword(move-&gt;value);<br>
         break;<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         replay_put_dword(move-&gt;axis);<br>
         replay_put_qword(move-&gt;value);<br>
         break;<br>
@@ -68,26 +68,21 @@ InputEvent *replay_read_input_event(void)<br>
 {<br>
     InputEvent evt;<br>
     KeyValue keyValue;<br>
-    InputKeyEvent key;<br>
-    key.key = &amp;keyValue;<br>
-    InputBtnEvent btn;<br>
-    InputMoveEvent rel;<br>
-    InputMoveEvent abs;<br>
+    evt.u.key.key = &amp;keyValue;<br>
<br>
     evt.type = replay_get_dword();<br>
     switch (evt.type) {<br>
     case INPUT_EVENT_KIND_KEY:<br>
-        evt.u.key.data = &amp;key;<br>
-        evt.u.key.data-&gt;key-&gt;type = replay_get_dword();<br>
+        evt.u.key.key-&gt;type = replay_get_dword();<br>
<br>
-        switch (evt.u.key.data-&gt;key-&gt;type) {<br>
+        switch (evt.u.key.key-&gt;type) {<br>
         case KEY_VALUE_KIND_NUMBER:<br>
-            evt.u.key.data-&gt;key-&gt;u.number.data = replay_get_qword();<br>
-            evt.u.key.data-&gt;down = replay_get_byte();<br>
+            evt.u.key.key-&gt;u.number = replay_get_qword();<br>
+            evt.u.key.down = replay_get_byte();<br>
             break;<br>
         case KEY_VALUE_KIND_QCODE:<br>
-            evt.u.key.data-&gt;key-&gt;u.qcode.data = (QKeyCode)replay_get_dword();<br>
-            evt.u.key.data-&gt;down = replay_get_byte();<br>
+            evt.u.key.key-&gt;u.qcode = (QKeyCode)replay_get_dword();<br>
+            evt.u.key.down = replay_get_byte();<br>
             break;<br>
         case KEY_VALUE_KIND__MAX:<br>
             /* keep gcc happy */<br>
@@ -95,19 +90,16 @@ InputEvent *replay_read_input_event(void)<br>
         }<br>
         break;<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        evt.u.btn.data = &amp;btn;<br>
-        evt.u.btn.data-&gt;button = (InputButton)replay_get_dword();<br>
-        evt.u.btn.data-&gt;down = replay_get_byte();<br>
+        evt.u.btn.button = (InputButton)replay_get_dword();<br>
+        evt.u.btn.down = replay_get_byte();<br>
         break;<br>
     case INPUT_EVENT_KIND_REL:<br>
-        evt.u.rel.data = &amp;rel;<br>
-        evt.u.rel.data-&gt;axis = (InputAxis)replay_get_dword();<br>
-        evt.u.rel.data-&gt;value = replay_get_qword();<br>
+        evt.u.rel.axis = (InputAxis)replay_get_dword();<br>
+        evt.u.rel.value = replay_get_qword();<br>
         break;<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        evt.u.abs.data = &amp;abs;<br>
-        evt.u.abs.data-&gt;axis = (InputAxis)replay_get_dword();<br>
-        evt.u.abs.data-&gt;value = replay_get_qword();<br>
+        evt.u.abs.axis = (InputAxis)replay_get_dword();<br>
+        evt.u.abs.value = replay_get_qword();<br>
         break;<br>
     case INPUT_EVENT_KIND__MAX:<br>
         /* keep gcc happy */<br>
diff --git a/tests/test-char.c b/tests/test-char.c<br>
index 9196e566e9..0e7a033a90 100644<br>
--- a/tests/test-char.c<br>
+++ b/tests/test-char.c<br>
@@ -1220,7 +1220,7 @@ static void char_file_fifo_test(void)<br>
                          .has_in = true,<br>
                          .out = out };<br>
     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,<br>
-                               .u.file.data = &amp;file };<br>
+                               .u.file = file };<br>
     FeHandler fe = { 0, };<br>
     int fd, ret;<br>
<br>
@@ -1273,19 +1273,17 @@ static void char_file_test_internal(Chardev *ext_chr, const char *filepath)<br>
     char *out;<br>
     Chardev *chr;<br>
     char *contents = NULL;<br>
-    ChardevFile file = {};<br>
-    ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,<br>
-                               .u.file.data = &amp;file };<br>
+    ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE };<br>
     gsize length;<br>
     int ret;<br>
<br>
     if (ext_chr) {<br>
         chr = ext_chr;<br>
         out = g_strdup(filepath);<br>
-        file.out = out;<br>
+        backend.u.file.out = out;<br>
     } else {<br>
         out = g_build_filename(tmp_path, &quot;out&quot;, NULL);<br>
-        file.out = out;<br>
+        backend.u.file.out = out;<br>
         chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &amp;backend,<br>
                                NULL, &amp;error_abort);<br>
     }<br>
@@ -1384,7 +1382,7 @@ static void char_hotswap_test(void)<br>
     char *filename = g_build_filename(tmp_path, &quot;file&quot;, NULL);<br>
     ChardevFile file = { .out = filename };<br>
     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,<br>
-                               .u.file.data = &amp;file };<br>
+                               .u.file = file };<br>
     ChardevReturn *ret;<br>
<br>
     int port;<br>
diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c<br>
index 5e1e8b2f5e..0a62704bed 100644<br>
--- a/tests/test-clone-visitor.c<br>
+++ b/tests/test-clone-visitor.c<br>
@@ -110,7 +110,7 @@ static void test_clone_complex1(void)<br>
     dst = QAPI_CLONE(UserDefListUnion, src);<br>
     g_assert(dst);<br>
     g_assert_cmpint(dst-&gt;type, ==, src-&gt;type);<br>
-    g_assert(!dst-&gt;u.string.data);<br>
+    g_assert(!dst-&gt;u.string);<br>
<br>
     qapi_free_UserDefListUnion(src);<br>
     qapi_free_UserDefListUnion(dst);<br>
@@ -155,30 +155,30 @@ static void test_clone_complex3(void)<br>
     tmp = src-&gt;array = g_new0(__org_qemu_x_Union1List, 1);<br>
     tmp-&gt;value = g_new0(__org_qemu_x_Union1, 1);<br>
     tmp-&gt;value-&gt;type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;<br>
-    tmp-&gt;value-&gt;u.__org_qemu_x_branch.data = g_strdup(&quot;one&quot;);<br>
+    tmp-&gt;value-&gt;u.__org_qemu_x_branch = g_strdup(&quot;one&quot;);<br>
     tmp = tmp-&gt;next = g_new0(__org_qemu_x_Union1List, 1);<br>
     tmp-&gt;value = g_new0(__org_qemu_x_Union1, 1);<br>
     tmp-&gt;value-&gt;type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;<br>
-    tmp-&gt;value-&gt;u.__org_qemu_x_branch.data = g_strdup(&quot;two&quot;);<br>
+    tmp-&gt;value-&gt;u.__org_qemu_x_branch = g_strdup(&quot;two&quot;);<br>
     tmp = tmp-&gt;next = g_new0(__org_qemu_x_Union1List, 1);<br>
     tmp-&gt;value = g_new0(__org_qemu_x_Union1, 1);<br>
     tmp-&gt;value-&gt;type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;<br>
-    tmp-&gt;value-&gt;u.__org_qemu_x_branch.data = g_strdup(&quot;three&quot;);<br>
+    tmp-&gt;value-&gt;u.__org_qemu_x_branch = g_strdup(&quot;three&quot;);<br>
<br>
     dst = QAPI_CLONE(__org_qemu_x_Struct2, src);<br>
     g_assert(dst);<br>
     tmp = dst-&gt;array;<br>
     g_assert(tmp);<br>
     g_assert(tmp-&gt;value);<br>
-    g_assert_cmpstr(tmp-&gt;value-&gt;u.__org_qemu_x_branch.data, ==, &quot;one&quot;);<br>
+    g_assert_cmpstr(tmp-&gt;value-&gt;u.__org_qemu_x_branch, ==, &quot;one&quot;);<br>
     tmp = tmp-&gt;next;<br>
     g_assert(tmp);<br>
     g_assert(tmp-&gt;value);<br>
-    g_assert_cmpstr(tmp-&gt;value-&gt;u.__org_qemu_x_branch.data, ==, &quot;two&quot;);<br>
+    g_assert_cmpstr(tmp-&gt;value-&gt;u.__org_qemu_x_branch, ==, &quot;two&quot;);<br>
     tmp = tmp-&gt;next;<br>
     g_assert(tmp);<br>
     g_assert(tmp-&gt;value);<br>
-    g_assert_cmpstr(tmp-&gt;value-&gt;u.__org_qemu_x_branch.data, ==, &quot;three&quot;);<br>
+    g_assert_cmpstr(tmp-&gt;value-&gt;u.__org_qemu_x_branch, ==, &quot;three&quot;);<br>
     tmp = tmp-&gt;next;<br>
     g_assert(!tmp);<br>
<br>
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c<br>
index d3413bfef0..3d699fbb66 100644<br>
--- a/tests/test-qmp-cmds.c<br>
+++ b/tests/test-qmp-cmds.c<br>
@@ -136,7 +136,7 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,<br>
     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);<br>
<br>
     ret-&gt;type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;<br>
-    ret-&gt;u.__org_qemu_x_branch.data = strdup(&quot;blah1&quot;);<br>
+    ret-&gt;u.__org_qemu_x_branch = strdup(&quot;blah1&quot;);<br>
<br>
     /* Also test that &#39;wchar-t&#39; was munged to &#39;q_wchar_t&#39; */<br>
     if (b &amp;&amp; b-&gt;value &amp;&amp; !b-&gt;value-&gt;has_q_wchar_t) {<br>
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c<br>
index e41b91a2a6..b976ab9763 100644<br>
--- a/tests/test-qobject-input-visitor.c<br>
+++ b/tests/test-qobject-input-visitor.c<br>
@@ -710,7 +710,7 @@ static void test_list_union_integer_helper(TestInputVisitorData *data,<br>
     switch (kind) {<br>
     case USER_DEF_LIST_UNION_KIND_INTEGER: {<br>
         intList *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.integer.data;<br>
+        for (i = 0, elem = cvalue-&gt;u.integer;<br>
              elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
@@ -718,56 +718,56 @@ static void test_list_union_integer_helper(TestInputVisitorData *data,<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S8: {<br>
         int8List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.s8.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.s8; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S16: {<br>
         int16List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.s16.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.s16; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S32: {<br>
         int32List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.s32.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.s32; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S64: {<br>
         int64List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.s64.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.s64; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U8: {<br>
         uint8List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.u8.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.u8; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U16: {<br>
         uint16List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.u16.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.u16; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U32: {<br>
         uint32List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.u32.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.u32; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U64: {<br>
         uint64List *elem = NULL;<br>
-        for (i = 0, elem = cvalue-&gt;u.u64.data; elem; elem = elem-&gt;next, i++) {<br>
+        for (i = 0, elem = cvalue-&gt;u.u64; elem; elem = elem-&gt;next, i++) {<br>
             g_assert_cmpint(elem-&gt;value, ==, i);<br>
         }<br>
         break;<br>
@@ -868,7 +868,7 @@ static void test_visitor_in_list_union_bool(TestInputVisitorData *data,<br>
     g_assert(cvalue != NULL);<br>
     g_assert_cmpint(cvalue-&gt;type, ==, USER_DEF_LIST_UNION_KIND_BOOLEAN);<br>
<br>
-    for (i = 0, elem = cvalue-&gt;u.boolean.data; elem; elem = elem-&gt;next, i++) {<br>
+    for (i = 0, elem = cvalue-&gt;u.boolean; elem; elem = elem-&gt;next, i++) {<br>
         g_assert_cmpint(elem-&gt;value, ==, (i % 3 == 0) ? 1 : 0);<br>
     }<br>
<br>
@@ -900,7 +900,7 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data,<br>
     g_assert(cvalue != NULL);<br>
     g_assert_cmpint(cvalue-&gt;type, ==, USER_DEF_LIST_UNION_KIND_STRING);<br>
<br>
-    for (i = 0, elem = cvalue-&gt;u.string.data; elem; elem = elem-&gt;next, i++) {<br>
+    for (i = 0, elem = cvalue-&gt;u.string; elem; elem = elem-&gt;next, i++) {<br>
         gchar str[8];<br>
         sprintf(str, &quot;%d&quot;, i);<br>
         g_assert_cmpstr(elem-&gt;value, ==, str);<br>
@@ -936,7 +936,7 @@ static void test_visitor_in_list_union_number(TestInputVisitorData *data,<br>
     g_assert(cvalue != NULL);<br>
     g_assert_cmpint(cvalue-&gt;type, ==, USER_DEF_LIST_UNION_KIND_NUMBER);<br>
<br>
-    for (i = 0, elem = cvalue-&gt;u.number.data; elem; elem = elem-&gt;next, i++) {<br>
+    for (i = 0, elem = cvalue-&gt;u.number; elem; elem = elem-&gt;next, i++) {<br>
         GString *double_expected = g_string_new(&quot;&quot;);<br>
         GString *double_actual = g_string_new(&quot;&quot;);<br>
<br>
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c<br>
index 1c856d9bd2..202f848062 100644<br>
--- a/tests/test-qobject-output-visitor.c<br>
+++ b/tests/test-qobject-output-visitor.c<br>
@@ -444,7 +444,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
     int i;<br>
     switch (cvalue-&gt;type) {<br>
     case USER_DEF_LIST_UNION_KIND_INTEGER: {<br>
-        intList **list = &amp;cvalue-&gt;u.integer.data;<br>
+        intList **list = &amp;cvalue-&gt;u.integer;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(intList, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -454,7 +454,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S8: {<br>
-        int8List **list = &amp;cvalue-&gt;u.s8.data;<br>
+        int8List **list = &amp;cvalue-&gt;u.s8;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(int8List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -464,7 +464,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S16: {<br>
-        int16List **list = &amp;cvalue-&gt;u.s16.data;<br>
+        int16List **list = &amp;cvalue-&gt;u.s16;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(int16List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -474,7 +474,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S32: {<br>
-        int32List **list = &amp;cvalue-&gt;u.s32.data;<br>
+        int32List **list = &amp;cvalue-&gt;u.s32;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(int32List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -484,7 +484,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_S64: {<br>
-        int64List **list = &amp;cvalue-&gt;u.s64.data;<br>
+        int64List **list = &amp;cvalue-&gt;u.s64;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(int64List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -494,7 +494,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U8: {<br>
-        uint8List **list = &amp;cvalue-&gt;u.u8.data;<br>
+        uint8List **list = &amp;cvalue-&gt;u.u8;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(uint8List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -504,7 +504,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U16: {<br>
-        uint16List **list = &amp;cvalue-&gt;u.u16.data;<br>
+        uint16List **list = &amp;cvalue-&gt;u.u16;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(uint16List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -514,7 +514,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U32: {<br>
-        uint32List **list = &amp;cvalue-&gt;u.u32.data;<br>
+        uint32List **list = &amp;cvalue-&gt;u.u32;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(uint32List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -524,7 +524,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_U64: {<br>
-        uint64List **list = &amp;cvalue-&gt;u.u64.data;<br>
+        uint64List **list = &amp;cvalue-&gt;u.u64;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(uint64List, 1);<br>
             (*list)-&gt;value = i;<br>
@@ -534,7 +534,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_BOOLEAN: {<br>
-        boolList **list = &amp;cvalue-&gt;u.boolean.data;<br>
+        boolList **list = &amp;cvalue-&gt;u.boolean;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(boolList, 1);<br>
             (*list)-&gt;value = QEMU_IS_ALIGNED(i, 3);<br>
@@ -544,7 +544,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_STRING: {<br>
-        strList **list = &amp;cvalue-&gt;u.string.data;<br>
+        strList **list = &amp;cvalue-&gt;u.string;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(strList, 1);<br>
             (*list)-&gt;value = g_strdup_printf(&quot;%d&quot;, i);<br>
@@ -554,7 +554,7 @@ static void init_list_union(UserDefListUnion *cvalue)<br>
         break;<br>
     }<br>
     case USER_DEF_LIST_UNION_KIND_NUMBER: {<br>
-        numberList **list = &amp;cvalue-&gt;u.number.data;<br>
+        numberList **list = &amp;cvalue-&gt;u.number;<br>
         for (i = 0; i &lt; 32; i++) {<br>
             *list = g_new0(numberList, 1);<br>
             (*list)-&gt;value = (double)i / 3;<br>
diff --git a/ui/console.c b/ui/console.c<br>
index 820e408170..2f93723ed6 100644<br>
--- a/ui/console.c<br>
+++ b/ui/console.c<br>
@@ -2212,7 +2212,7 @@ static void vc_chr_open(Chardev *chr,<br>
                         bool *be_opened,<br>
                         Error **errp)<br>
 {<br>
-    ChardevVC *vc = backend-&gt;u.vc.data;<br>
+    ChardevVC *vc = &amp;backend-&gt;<a href="http://u.vc" rel="noreferrer" target="_blank">u.vc</a>;<br>
     VCChardev *drv = VC_CHARDEV(chr);<br>
     QemuConsole *s;<br>
     unsigned width = 0;<br>
@@ -2362,10 +2362,9 @@ void qemu_display_help(void)<br>
 void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp)<br>
 {<br>
     int val;<br>
-    ChardevVC *vc;<br>
+    ChardevVC *vc = &amp;backend-&gt;<a href="http://u.vc" rel="noreferrer" target="_blank">u.vc</a>;<br>
<br>
     backend-&gt;type = CHARDEV_BACKEND_KIND_VC;<br>
-    vc = backend-&gt;u.vc.data = g_new0(ChardevVC, 1);<br>
     qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));<br>
<br>
     val = qemu_opt_get_number(opts, &quot;width&quot;, 0);<br>
diff --git a/ui/input-keymap.c b/ui/input-keymap.c<br>
index 1b756a6970..0232e25124 100644<br>
--- a/ui/input-keymap.c<br>
+++ b/ui/input-keymap.c<br>
@@ -33,13 +33,13 @@ int qemu_input_linux_to_qcode(unsigned int lnx)<br>
 int qemu_input_key_value_to_number(const KeyValue *value)<br>
 {<br>
     if (value-&gt;type == KEY_VALUE_KIND_QCODE) {<br>
-        if (value-&gt;u.qcode.data &gt;= qemu_input_map_qcode_to_qnum_len) {<br>
+        if (value-&gt;u.qcode &gt;= qemu_input_map_qcode_to_qnum_len) {<br>
             return 0;<br>
         }<br>
-        return qemu_input_map_qcode_to_qnum[value-&gt;u.qcode.data];<br>
+        return qemu_input_map_qcode_to_qnum[value-&gt;u.qcode];<br>
     } else {<br>
         assert(value-&gt;type == KEY_VALUE_KIND_NUMBER);<br>
-        return value-&gt;u.number.data;<br>
+        return value-&gt;u.number;<br>
     }<br>
 }<br>
<br>
@@ -54,10 +54,10 @@ int qemu_input_key_number_to_qcode(unsigned int nr)<br>
 int qemu_input_key_value_to_qcode(const KeyValue *value)<br>
 {<br>
     if (value-&gt;type == KEY_VALUE_KIND_QCODE) {<br>
-        return value-&gt;u.qcode.data;<br>
+        return value-&gt;u.qcode;<br>
     } else {<br>
         assert(value-&gt;type == KEY_VALUE_KIND_NUMBER);<br>
-        return qemu_input_key_number_to_qcode(value-&gt;u.number.data);<br>
+        return qemu_input_key_number_to_qcode(value-&gt;u.number);<br>
     }<br>
 }<br>
<br>
@@ -68,7 +68,7 @@ int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,<br>
     int count = 0;<br>
<br>
     if (value-&gt;type == KEY_VALUE_KIND_QCODE &amp;&amp;<br>
-        value-&gt;u.qcode.data == Q_KEY_CODE_PAUSE) {<br>
+        value-&gt;u.qcode == Q_KEY_CODE_PAUSE) {<br>
         /* specific case */<br>
         int v = down ? 0 : 0x80;<br>
         codes[count++] = 0xe1;<br>
diff --git a/ui/input-legacy.c b/ui/input-legacy.c<br>
index 9fc78a639b..5a32b010d4 100644<br>
--- a/ui/input-legacy.c<br>
+++ b/ui/input-legacy.c<br>
@@ -75,9 +75,9 @@ static KeyValue *copy_key_value(KeyValue *src)<br>
     KeyValue *dst = g_new(KeyValue, 1);<br>
     memcpy(dst, src, sizeof(*src));<br>
     if (dst-&gt;type == KEY_VALUE_KIND_NUMBER) {<br>
-        QKeyCode code = qemu_input_key_number_to_qcode(dst-&gt;u.number.data);<br>
+        QKeyCode code = qemu_input_key_number_to_qcode(dst-&gt;u.number);<br>
         dst-&gt;type = KEY_VALUE_KIND_QCODE;<br>
-        dst-&gt;u.qcode.data = code;<br>
+        dst-&gt;u.qcode = code;<br>
     }<br>
     return dst;<br>
 }<br>
@@ -113,7 +113,7 @@ static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,<br>
 {<br>
     QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;<br>
     int scancodes[3], i, count;<br>
-    InputKeyEvent *key = evt-&gt;u.key.data;<br>
+    InputKeyEvent *key = &amp;evt-&gt;u.key;<br>
<br>
     if (!entry || !entry-&gt;put_kbd) {<br>
         return;<br>
@@ -159,7 +159,7 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,<br>
<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         if (btn-&gt;down) {<br>
             s-&gt;buttons |= bmap[btn-&gt;button];<br>
         } else {<br>
@@ -181,11 +181,11 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,<br>
         }<br>
         break;<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         s-&gt;axis[move-&gt;axis] = move-&gt;value;<br>
         break;<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         s-&gt;axis[move-&gt;axis] += move-&gt;value;<br>
         break;<br>
     default:<br>
diff --git a/ui/input.c b/ui/input.c<br>
index 4791b089c7..a4078780ee 100644<br>
--- a/ui/input.c<br>
+++ b/ui/input.c<br>
@@ -164,10 +164,10 @@ void qmp_input_send_event(bool has_device, const char *device,<br>
         InputEvent *evt = e-&gt;value;<br>
<br>
         if (evt-&gt;type == INPUT_EVENT_KIND_KEY &amp;&amp;<br>
-            evt-&gt;u.key.data-&gt;key-&gt;type == KEY_VALUE_KIND_NUMBER) {<br>
-            KeyValue *key = evt-&gt;u.key.data-&gt;key;<br>
-            QKeyCode code = qemu_input_key_number_to_qcode(key-&gt;u.number.data);<br>
-            qemu_input_event_send_key_qcode(con, code, evt-&gt;u.key.data-&gt;down);<br>
+            evt-&gt;u.key.key-&gt;type == KEY_VALUE_KIND_NUMBER) {<br>
+            KeyValue *key = evt-&gt;u.key.key;<br>
+            QKeyCode code = qemu_input_key_number_to_qcode(key-&gt;u.number);<br>
+            qemu_input_event_send_key_qcode(con, code, evt-&gt;u.key.down);<br>
         } else {<br>
             qemu_input_event_send(con, evt);<br>
         }<br>
@@ -183,7 +183,7 @@ static int qemu_input_transform_invert_abs_value(int value)<br>
<br>
 static void qemu_input_transform_abs_rotate(InputEvent *evt)<br>
 {<br>
-    InputMoveEvent *move = evt-&gt;u.abs.data;<br>
+    InputMoveEvent *move = &amp;evt-&gt;u.abs;<br>
     switch (graphic_rotate) {<br>
     case 90:<br>
         if (move-&gt;axis == INPUT_AXIS_X) {<br>
@@ -220,16 +220,16 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)<br>
     }<br>
     switch (evt-&gt;type) {<br>
     case INPUT_EVENT_KIND_KEY:<br>
-        key = evt-&gt;u.key.data;<br>
+        key = &amp;evt-&gt;u.key;<br>
         switch (key-&gt;key-&gt;type) {<br>
         case KEY_VALUE_KIND_NUMBER:<br>
-            qcode = qemu_input_key_number_to_qcode(key-&gt;key-&gt;u.number.data);<br>
+            qcode = qemu_input_key_number_to_qcode(key-&gt;key-&gt;u.number);<br>
             name = QKeyCode_str(qcode);<br>
-            trace_input_event_key_number(idx, key-&gt;key-&gt;u.number.data,<br>
+            trace_input_event_key_number(idx, key-&gt;key-&gt;u.number,<br>
                                          name, key-&gt;down);<br>
             break;<br>
         case KEY_VALUE_KIND_QCODE:<br>
-            name = QKeyCode_str(key-&gt;key-&gt;u.qcode.data);<br>
+            name = QKeyCode_str(key-&gt;key-&gt;u.qcode);<br>
             trace_input_event_key_qcode(idx, name, key-&gt;down);<br>
             break;<br>
         case KEY_VALUE_KIND__MAX:<br>
@@ -238,17 +238,17 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)<br>
         }<br>
         break;<br>
     case INPUT_EVENT_KIND_BTN:<br>
-        btn = evt-&gt;u.btn.data;<br>
+        btn = &amp;evt-&gt;u.btn;<br>
         name = InputButton_str(btn-&gt;button);<br>
         trace_input_event_btn(idx, name, btn-&gt;down);<br>
         break;<br>
     case INPUT_EVENT_KIND_REL:<br>
-        move = evt-&gt;u.rel.data;<br>
+        move = &amp;evt-&gt;u.rel;<br>
         name = InputAxis_str(move-&gt;axis);<br>
         trace_input_event_rel(idx, name, move-&gt;value);<br>
         break;<br>
     case INPUT_EVENT_KIND_ABS:<br>
-        move = evt-&gt;u.abs.data;<br>
+        move = &amp;evt-&gt;u.abs;<br>
         name = InputAxis_str(move-&gt;axis);<br>
         trace_input_event_abs(idx, name, move-&gt;value);<br>
         break;<br>
@@ -355,7 +355,7 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)<br>
     /* Expect all parts of QEMU to send events with QCodes exclusively.<br>
      * Key numbers are only supported as end-user input via QMP */<br>
     assert(!(evt-&gt;type == INPUT_EVENT_KIND_KEY &amp;&amp;<br>
-             evt-&gt;u.key.data-&gt;key-&gt;type == KEY_VALUE_KIND_NUMBER));<br>
+             evt-&gt;u.key.key-&gt;type == KEY_VALUE_KIND_NUMBER));<br>
<br>
<br>
     /*<br>
@@ -367,8 +367,8 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)<br>
      * neeed to deal with this mistake<br>
      */<br>
     if (evt-&gt;type == INPUT_EVENT_KIND_KEY &amp;&amp;<br>
-        evt-&gt;u.key.data-&gt;key-&gt;u.qcode.data == Q_KEY_CODE_SYSRQ) {<br>
-        evt-&gt;u.key.data-&gt;key-&gt;u.qcode.data = Q_KEY_CODE_PRINT;<br>
+        evt-&gt;u.key.key-&gt;u.qcode == Q_KEY_CODE_SYSRQ) {<br>
+        evt-&gt;u.key.key-&gt;u.qcode = Q_KEY_CODE_PRINT;<br>
     }<br>
<br>
     if (!runstate_is_running() &amp;&amp; !runstate_check(RUN_STATE_SUSPENDED)) {<br>
@@ -407,10 +407,9 @@ void qemu_input_event_sync(void)<br>
 static InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)<br>
 {<br>
     InputEvent *evt = g_new0(InputEvent, 1);<br>
-    evt-&gt;u.key.data = g_new0(InputKeyEvent, 1);<br>
     evt-&gt;type = INPUT_EVENT_KIND_KEY;<br>
-    evt-&gt;u.key.data-&gt;key = key;<br>
-    evt-&gt;u.key.data-&gt;down = down;<br>
+    evt-&gt;u.key.key = key;<br>
+    evt-&gt;u.key.down = down;<br>
     return evt;<br>
 }<br>
<br>
@@ -440,7 +439,7 @@ void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)<br>
 {<br>
     KeyValue *key = g_new0(KeyValue, 1);<br>
     key-&gt;type = KEY_VALUE_KIND_QCODE;<br>
-    key-&gt;u.qcode.data = q;<br>
+    key-&gt;u.qcode = q;<br>
     qemu_input_event_send_key(src, key, down);<br>
 }<br>
<br>
@@ -469,7 +468,7 @@ void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)<br>
     };<br>
     InputEvent evt = {<br>
         .type = INPUT_EVENT_KIND_BTN,<br>
-        .u.btn.data = &amp;bevt,<br>
+        .u.btn = bevt,<br>
     };<br>
<br>
     qemu_input_event_send(src, &amp;evt);<br>
@@ -520,7 +519,7 @@ void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)<br>
     };<br>
     InputEvent evt = {<br>
         .type = INPUT_EVENT_KIND_REL,<br>
-        .u.rel.data = &amp;move,<br>
+        .u.rel = move,<br>
     };<br>
<br>
     qemu_input_event_send(src, &amp;evt);<br>
@@ -537,7 +536,7 @@ void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,<br>
     };<br>
     InputEvent evt = {<br>
         .type = INPUT_EVENT_KIND_ABS,<br>
-        .u.abs.data = &amp;move,<br>
+        .u.abs = move,<br>
     };<br>
<br>
     qemu_input_event_send(src, &amp;evt);<br>
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c<br>
index 05e5c73f9d..59e317cbb8 100644<br>
--- a/util/qemu-sockets.c<br>
+++ b/util/qemu-sockets.c<br>
@@ -1365,21 +1365,21 @@ SocketAddress *socket_address_flatten(SocketAddressLegacy *addr_legacy)<br>
     case SOCKET_ADDRESS_LEGACY_KIND_INET:<br>
         addr-&gt;type = SOCKET_ADDRESS_TYPE_INET;<br>
         QAPI_CLONE_MEMBERS(InetSocketAddress, &amp;addr-&gt;u.inet,<br>
-                           addr_legacy-&gt;u.inet.data);<br>
+                           &amp;addr_legacy-&gt;u.inet);<br>
         break;<br>
     case SOCKET_ADDRESS_LEGACY_KIND_UNIX:<br>
         addr-&gt;type = SOCKET_ADDRESS_TYPE_UNIX;<br>
         QAPI_CLONE_MEMBERS(UnixSocketAddress, &amp;addr-&gt;u.q_unix,<br>
-                           addr_legacy-&gt;u.q_unix.data);<br>
+                           &amp;addr_legacy-&gt;u.q_unix);<br>
         break;<br>
     case SOCKET_ADDRESS_LEGACY_KIND_VSOCK:<br>
         addr-&gt;type = SOCKET_ADDRESS_TYPE_VSOCK;<br>
         QAPI_CLONE_MEMBERS(VsockSocketAddress, &amp;addr-&gt;u.vsock,<br>
-                           addr_legacy-&gt;u.vsock.data);<br>
+                           &amp;addr_legacy-&gt;u.vsock);<br>
         break;<br>
     case SOCKET_ADDRESS_LEGACY_KIND_FD:<br>
         addr-&gt;type = SOCKET_ADDRESS_TYPE_FD;<br>
-        QAPI_CLONE_MEMBERS(String, &amp;addr-&gt;u.fd, addr_legacy-&gt;u.fd.data);<br>
+        QAPI_CLONE_MEMBERS(String, &amp;addr-&gt;u.fd, &amp;addr_legacy-&gt;u.fd);<br>
         break;<br>
     default:<br>
         abort();<br>
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py<br>
index fafec94e02..1c4e3407a3 100644<br>
--- a/scripts/qapi/introspect.py<br>
+++ b/scripts/qapi/introspect.py<br>
@@ -188,7 +188,12 @@ const QLitObject %(c_name)s = %(c_string)s;<br>
                 &#39;variants&#39;: [self._gen_variant(v) for v in variants]}<br>
<br>
     def _gen_variant(self, variant):<br>
-        obj = {&#39;case&#39;: <a href="http://variant.name" rel="noreferrer" target="_blank">variant.name</a>, &#39;type&#39;: self._use_type(variant.type)}<br>
+        if variant.wrapped:<br>
+            obj = {&#39;case&#39;: <a href="http://variant.name" rel="noreferrer" target="_blank">variant.name</a>,<br>
+                   &#39;type&#39;: self._use_type(variant.wrapper_type)}<br>
+        else:<br>
+            obj = {&#39;case&#39;: <a href="http://variant.name" rel="noreferrer" target="_blank">variant.name</a>,<br>
+                   &#39;type&#39;: self._use_type(variant.type)}<br>
         return _make_tree(obj, variant.ifcond, None)<br>
<br>
     def visit_builtin_type(self, name, info, json_type):<br>
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py<br>
index 720449feee..17525b4216 100644<br>
--- a/scripts/qapi/schema.py<br>
+++ b/scripts/qapi/schema.py<br>
@@ -216,6 +216,11 @@ class QAPISchemaBuiltinType(QAPISchemaType):<br>
         self._json_type_name = json_type<br>
         self._c_type_name = c_type<br>
<br>
+    def check(self, schema):<br>
+        # Don&#39;t check twice, it would fail an assertion<br>
+        if not self._checked:<br>
+            super().check(schema)<br>
+<br>
     def c_name(self):<br>
         return <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a><br>
<br>
@@ -593,18 +598,21 @@ class QAPISchemaVariants:<br>
                         &quot;branch &#39;%s&#39; is not a value of %s&quot;<br>
                         % (<a href="http://v.name" rel="noreferrer" target="_blank">v.name</a>, self.tag_member.type.describe()))<br>
                 if (not isinstance(v.type, QAPISchemaObjectType)<br>
-                        or v.type.variants):<br>
+                        or v.type.variants) and v.flat:<br>
                     raise QAPISemError(<br>
                         <a href="http://self.info" rel="noreferrer" target="_blank">self.info</a>,<br>
                         &quot;%s cannot use %s&quot;<br>
                         % (v.describe(<a href="http://self.info" rel="noreferrer" target="_blank">self.info</a>), v.type.describe()))<br>
-                v.type.check(schema)<br>
+                if isinstance(v.type, QAPISchemaObjectType):<br>
+                    v.type.check(schema)<br>
<br>
     def check_clash(self, info, seen):<br>
         for v in self.variants:<br>
             # Reset seen map for each variant, since qapi names from one<br>
-            # branch do not affect another branch<br>
-            v.type.check_clash(info, dict(seen))<br>
+            # branch do not affect another branch.  Variants that are<br>
+            # never flat don&#39;t even conflict with the base.<br>
+            if isinstance(v.type, QAPISchemaObjectType):<br>
+                v.type.check_clash(info, dict(seen) if v.flat else {})<br>
<br>
<br>
 class QAPISchemaMember:<br>
@@ -705,9 +713,22 @@ class QAPISchemaObjectTypeMember(QAPISchemaMember):<br>
 class QAPISchemaVariant(QAPISchemaObjectTypeMember):<br>
     role = &#39;branch&#39;<br>
<br>
-    def __init__(self, name, info, typ, ifcond=None):<br>
+    def __init__(self, name, info, typ, ifcond=None, flat=True,<br>
+                 wrapper_type=None):<br>
         super().__init__(name, info, typ, False, ifcond)<br>
<br>
+        self.flat = flat<br>
+        self.wrapped = bool(wrapper_type)<br>
+        self.wrapper_type = wrapper_type<br>
+<br>
+        # For now, unions are either flat or wrapped, never both<br>
+        assert self.flat or self.wrapped<br>
+        assert not (self.flat and self.wrapped)<br>
+<br>
+    def check(self, schema):<br>
+        super().check(schema)<br>
+        if self.wrapped:<br>
+            self.wrapper_type.check(schema)<br>
<br>
 class QAPISchemaCommand(QAPISchemaEntity):<br>
     meta = &#39;command&#39;<br>
@@ -1017,14 +1038,19 @@ class QAPISchema:<br>
     def _make_variant(self, case, typ, ifcond, info):<br>
         return QAPISchemaVariant(case, info, typ, ifcond)<br>
<br>
-    def _make_simple_variant(self, case, typ, ifcond, info):<br>
+    def _make_simple_variant(self, union_name, case, typ, ifcond, info):<br>
         if isinstance(typ, list):<br>
             assert len(typ) == 1<br>
             typ = self._make_array_type(typ[0], info)<br>
-        typ = self._make_implicit_object_type(<br>
-            typ, info, self.lookup_type(typ),<br>
-            &#39;wrapper&#39;, [self._make_member(&#39;data&#39;, typ, None, None, info)])<br>
-        return QAPISchemaVariant(case, info, typ, ifcond)<br>
+<br>
+        # The wrapper type is only used for introspection compatibility.<br>
+        # Don&#39;t add it to the entity list of the schema.<br>
+        wrapper_name = &#39;q_obj_%s-%s-wrapper&#39; % (union_name, case)<br>
+        wrapper_member = self._make_member(&#39;data&#39;, typ, None, None, info)<br>
+        wrapper_type = QAPISchemaObjectType(wrapper_name, info, None, ifcond,<br>
+                                            None, None, [wrapper_member], None)<br>
+        return QAPISchemaVariant(case, info, typ, ifcond, flat=False,<br>
+                                 wrapper_type=wrapper_type)<br>
<br>
     def _def_union_type(self, expr, info, doc):<br>
         name = expr[&#39;union&#39;]<br>
@@ -1044,7 +1070,7 @@ class QAPISchema:<br>
                         for (key, value) in data.items()]<br>
             members = []<br>
         else:<br>
-            variants = [self._make_simple_variant(key, value[&#39;type&#39;],<br>
+            variants = [self._make_simple_variant(name, key, value[&#39;type&#39;],<br>
                                                   value.get(&#39;if&#39;), info)<br>
                         for (key, value) in data.items()]<br>
             enum = [{&#39;name&#39;: <a href="http://v.name" rel="noreferrer" target="_blank">v.name</a>, &#39;if&#39;: v.ifcond} for v in variants]<br>
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py<br>
index 339f152152..f72567cbcc 100644<br>
--- a/scripts/qapi/visit.py<br>
+++ b/scripts/qapi/visit.py<br>
@@ -118,6 +118,34 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)<br>
         break;<br>
 &#39;&#39;&#39;,<br>
                              case=case_str)<br>
+            elif not isinstance(var.type, QAPISchemaObjectType):<br>
+                assert not var.flat<br>
+                ret += mcgen(&#39;&#39;&#39;<br>
+    case %(case)s:<br>
+        return visit_type_%(c_type)s(v, &quot;data&quot;, &amp;obj-&gt;u.%(c_name)s, errp);<br>
+&#39;&#39;&#39;,<br>
+                             case=case_str,<br>
+                             c_type=var.type.c_name(), c_name=c_name(<a href="http://var.name" rel="noreferrer" target="_blank">var.name</a>))<br>
+            elif var.wrapped:<br>
+                ret += mcgen(&#39;&#39;&#39;<br>
+    case %(case)s:<br>
+    {<br>
+        bool ok;<br>
+<br>
+        if (!visit_start_struct(v, &quot;data&quot;, NULL, 0, errp)) {<br>
+            return false;<br>
+        }<br>
+        ok = visit_type_%(c_type)s_members(v, &amp;obj-&gt;u.%(c_name)s, errp);<br>
+        if (ok) {<br>
+            ok = visit_check_struct(v, errp);<br>
+        }<br>
+        visit_end_struct(v, NULL);<br>
+        return ok;<br>
+    }<br>
+&#39;&#39;&#39;,<br>
+                             case=case_str,<br>
+                             c_type=var.type.c_name(), c_name=c_name(<a href="http://var.name" rel="noreferrer" target="_blank">var.name</a>))<br>
+<br>
             else:<br>
                 ret += mcgen(&#39;&#39;&#39;<br>
     case %(case)s:<br>
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out<br>
index 419284dae2..bcbcbd2fce 100644<br>
--- a/tests/qapi-schema/doc-good.out<br>
+++ b/tests/qapi-schema/doc-good.out<br>
@@ -31,10 +31,6 @@ object Object<br>
     case two: Variant2<br>
         if [&#39;IFTWO&#39;]<br>
     feature union-feat1<br>
-object q_obj_Variant1-wrapper<br>
-    member data: Variant1 optional=False<br>
-object q_obj_Variant2-wrapper<br>
-    member data: Variant2 optional=False<br>
 enum SugaredUnionKind<br>
     member one<br>
     member two<br>
@@ -42,8 +38,8 @@ enum SugaredUnionKind<br>
 object SugaredUnion<br>
     member type: SugaredUnionKind optional=False<br>
     tag type<br>
-    case one: q_obj_Variant1-wrapper<br>
-    case two: q_obj_Variant2-wrapper<br>
+    case one: Variant1<br>
+    case two: Variant2<br>
         if [&#39;IFTWO&#39;]<br>
     feature union-feat2<br>
 alternate Alternate<br>
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out<br>
index 8868ca0dca..a4e4051c61 100644<br>
--- a/tests/qapi-schema/qapi-schema-test.out<br>
+++ b/tests/qapi-schema/qapi-schema-test.out<br>
@@ -125,36 +125,6 @@ alternate AltStrObj<br>
     tag type<br>
     case s: str<br>
     case o: TestStruct<br>
-object q_obj_intList-wrapper<br>
-    member data: intList optional=False<br>
-object q_obj_int8List-wrapper<br>
-    member data: int8List optional=False<br>
-object q_obj_int16List-wrapper<br>
-    member data: int16List optional=False<br>
-object q_obj_int32List-wrapper<br>
-    member data: int32List optional=False<br>
-object q_obj_int64List-wrapper<br>
-    member data: int64List optional=False<br>
-object q_obj_uint8List-wrapper<br>
-    member data: uint8List optional=False<br>
-object q_obj_uint16List-wrapper<br>
-    member data: uint16List optional=False<br>
-object q_obj_uint32List-wrapper<br>
-    member data: uint32List optional=False<br>
-object q_obj_uint64List-wrapper<br>
-    member data: uint64List optional=False<br>
-object q_obj_numberList-wrapper<br>
-    member data: numberList optional=False<br>
-object q_obj_boolList-wrapper<br>
-    member data: boolList optional=False<br>
-object q_obj_strList-wrapper<br>
-    member data: strList optional=False<br>
-object q_obj_sizeList-wrapper<br>
-    member data: sizeList optional=False<br>
-object q_obj_anyList-wrapper<br>
-    member data: anyList optional=False<br>
-object q_obj_StatusList-wrapper<br>
-    member data: StatusList optional=False<br>
 enum UserDefListUnionKind<br>
     member integer<br>
     member s8<br>
@@ -174,21 +144,21 @@ enum UserDefListUnionKind<br>
 object UserDefListUnion<br>
     member type: UserDefListUnionKind optional=False<br>
     tag type<br>
-    case integer: q_obj_intList-wrapper<br>
-    case s8: q_obj_int8List-wrapper<br>
-    case s16: q_obj_int16List-wrapper<br>
-    case s32: q_obj_int32List-wrapper<br>
-    case s64: q_obj_int64List-wrapper<br>
-    case u8: q_obj_uint8List-wrapper<br>
-    case u16: q_obj_uint16List-wrapper<br>
-    case u32: q_obj_uint32List-wrapper<br>
-    case u64: q_obj_uint64List-wrapper<br>
-    case number: q_obj_numberList-wrapper<br>
-    case boolean: q_obj_boolList-wrapper<br>
-    case string: q_obj_strList-wrapper<br>
-    case sizes: q_obj_sizeList-wrapper<br>
-    case any: q_obj_anyList-wrapper<br>
-    case user: q_obj_StatusList-wrapper<br>
+    case integer: intList<br>
+    case s8: int8List<br>
+    case s16: int16List<br>
+    case s32: int32List<br>
+    case s64: int64List<br>
+    case u8: uint8List<br>
+    case u16: uint16List<br>
+    case u32: uint32List<br>
+    case u64: uint64List<br>
+    case number: numberList<br>
+    case boolean: boolList<br>
+    case string: strList<br>
+    case sizes: sizeList<br>
+    case any: anyList<br>
+    case user: StatusList<br>
 include include/sub-module.json<br>
 command user_def_cmd None -&gt; None<br>
     gen=True success_response=True boxed=False oob=False preconfig=False<br>
@@ -263,14 +233,12 @@ object __org.qemu_x-Struct<br>
     base __org.qemu_x-Base<br>
     member __org.qemu_x-member2: str optional=False<br>
     member wchar-t: int optional=True<br>
-object q_obj_str-wrapper<br>
-    member data: str optional=False<br>
 enum __org.qemu_x-Union1Kind<br>
     member __org.qemu_x-branch<br>
 object __org.qemu_x-Union1<br>
     member type: __org.qemu_x-Union1Kind optional=False<br>
     tag type<br>
-    case __org.qemu_x-branch: q_obj_str-wrapper<br>
+    case __org.qemu_x-branch: str<br>
 alternate __org.qemu_x-Alt1<br>
     tag type<br>
     case __org.qemu_x-branch: str<br>
@@ -305,8 +273,6 @@ enum TestIfEnum<br>
     member bar<br>
         if [&#39;defined(TEST_IF_ENUM_BAR)&#39;]<br>
     if [&#39;defined(TEST_IF_ENUM)&#39;]<br>
-object q_obj_TestStruct-wrapper<br>
-    member data: TestStruct optional=False<br>
 enum TestIfUnionKind<br>
     member foo<br>
     member union_bar<br>
@@ -315,8 +281,8 @@ enum TestIfUnionKind<br>
 object TestIfUnion<br>
     member type: TestIfUnionKind optional=False<br>
     tag type<br>
-    case foo: q_obj_TestStruct-wrapper<br>
-    case union_bar: q_obj_str-wrapper<br>
+    case foo: TestStruct<br>
+    case union_bar: str<br>
         if [&#39;defined(TEST_IF_UNION_BAR)&#39;]<br>
     if [&#39;defined(TEST_IF_UNION) &amp;&amp; defined(TEST_IF_STRUCT)&#39;]<br>
 object q_obj_TestIfUnionCmd-arg<br>
-- <br>
2.28.0<br>
<br>
<br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature">Marc-André Lureau<br></div></div>
diff mbox series

Patch

diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index c6438c6aa9..9722c1a204 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -310,7 +310,20 @@  The BRANCH's STRING name is the branch name.
 The BRANCH's value defines the branch's properties, in particular its
 type.  The form TYPE-REF is shorthand for { 'type': TYPE-REF }.
 
-A simple union type defines a mapping from automatic discriminator
+Each branch can have flat or wrapped representation in the Client JSON
+Protocol.
+
+Wrapped representation of a branch means that it is represented by a
+'data' member that is of the specified data type corresponding to the
+discriminator value.
+
+Flat representation means that the union forms a single object that
+contains both common members (from the base type) and the selected
+branch's members, without any additional nesting.  The two sets of
+member names must be disjoint.
+
+A simple union type automatically contains the 'type' member as a
+discriminator and defines a mapping from automatic discriminator
 values to data types like in this example:
 
  { 'struct': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } }
@@ -321,10 +334,8 @@  values to data types like in this example:
    'data': { 'file': 'BlockdevOptionsFile',
              'qcow2': 'BlockdevOptionsQcow2' } }
 
-In the Client JSON Protocol, a simple union is represented by an
-object that contains the 'type' member as a discriminator, and a
-'data' member that is of the specified data type corresponding to the
-discriminator value, as in these examples:
+In the Client JSON Protocol, all simple union branches have wrapped
+representation, as in these examples:
 
  { "type": "file", "data": { "filename": "/some/place/my-image" } }
  { "type": "qcow2", "data": { "backing": "/some/place/my-image",
@@ -344,13 +355,12 @@  object, it defines common members just like a struct type's 'data'
 member defines struct type members.  If it is a STRING, it names a
 struct type whose members are the common members.
 
-All flat union branches must be of struct type.
+Member 'discriminator' must name a non-optional enum-typed member of
+the base struct and defines the option that should server as the
+discrimiator.
 
-In the Client JSON Protocol, a flat union is represented by an object
-with the common members (from the base type) and the selected branch's
-members.  The two sets of member names must be disjoint.  Member
-'discriminator' must name a non-optional enum-typed member of the base
-struct.
+All flat union branches must be of struct type.  They have always flat
+representation.
 
 The following example enhances the above simple union example by
 adding an optional common member 'read-only', renaming the
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index 201cd38503..7d2dc2b19d 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -629,7 +629,8 @@  static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
     TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
 
     options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
-    options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
+    QAPI_CLONE_MEMBERS(TPMEmulatorOptions, &options->u.emulator,
+                       tpm_emu->options);
 
     return options;
 }
diff --git a/backends/tpm/tpm_passthrough.c b/backends/tpm/tpm_passthrough.c
index 8f6f4998a5..7fa7c84f5a 100644
--- a/backends/tpm/tpm_passthrough.c
+++ b/backends/tpm/tpm_passthrough.c
@@ -322,8 +322,8 @@  static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
     TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
 
     options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
-    options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
-                                             TPM_PASSTHROUGH(tb)->options);
+    QAPI_CLONE_MEMBERS(TPMPassthroughOptions, &options->u.passthrough,
+                       TPM_PASSTHROUGH(tb)->options);
 
     return options;
 }
diff --git a/block/crypto.c b/block/crypto.c
index 0807557763..0e7838d70a 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -775,8 +775,7 @@  block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
 
     spec_info = g_new(ImageInfoSpecific, 1);
     spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS;
-    spec_info->u.luks.data = g_new(QCryptoBlockInfoLUKS, 1);
-    *spec_info->u.luks.data = info->u.luks;
+    spec_info->u.luks = info->u.luks;
 
     /* Blank out pointers we've just stolen to avoid double free */
     memset(&info->u.luks, 0, sizeof(info->u.luks));
diff --git a/block/qcow2.c b/block/qcow2.c
index b05512718c..104fd8ad06 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5052,10 +5052,9 @@  static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
     spec_info = g_new(ImageInfoSpecific, 1);
     *spec_info = (ImageInfoSpecific){
         .type  = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
-        .u.qcow2.data = g_new0(ImageInfoSpecificQCow2, 1),
     };
     if (s->qcow_version == 2) {
-        *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
+        spec_info->u.qcow2 = (ImageInfoSpecificQCow2){
             .compat             = g_strdup("0.10"),
             .refcount_bits      = s->refcount_bits,
         };
@@ -5068,7 +5067,7 @@  static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
             qapi_free_QCryptoBlockInfo(encrypt_info);
             return NULL;
         }
-        *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
+        spec_info->u.qcow2 = (ImageInfoSpecificQCow2){
             .compat             = g_strdup("1.1"),
             .lazy_refcounts     = s->compatible_features &
                                   QCOW2_COMPAT_LAZY_REFCOUNTS,
@@ -5112,8 +5111,8 @@  static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
         memset(&encrypt_info->u, 0, sizeof(encrypt_info->u));
         qapi_free_QCryptoBlockInfo(encrypt_info);
 
-        spec_info->u.qcow2.data->has_encrypt = true;
-        spec_info->u.qcow2.data->encrypt = qencrypt;
+        spec_info->u.qcow2.has_encrypt = true;
+        spec_info->u.qcow2.encrypt = qencrypt;
     }
 
     return spec_info;
diff --git a/block/vmdk.c b/block/vmdk.c
index a00dc00eb4..fc4ddcc351 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -2932,18 +2932,14 @@  static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
 
     *spec_info = (ImageInfoSpecific){
         .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
-        .u = {
-            .vmdk.data = g_new0(ImageInfoSpecificVmdk, 1),
+        .u.vmdk = (ImageInfoSpecificVmdk) {
+            .create_type = g_strdup(s->create_type),
+            .cid = s->cid,
+            .parent_cid = s->parent_cid,
         },
     };
 
-    *spec_info->u.vmdk.data = (ImageInfoSpecificVmdk) {
-        .create_type = g_strdup(s->create_type),
-        .cid = s->cid,
-        .parent_cid = s->parent_cid,
-    };
-
-    next = &spec_info->u.vmdk.data->extents;
+    next = &spec_info->u.vmdk.extents;
     for (i = 0; i < s->num_extents; i++) {
         *next = g_new0(ImageInfoList, 1);
         (*next)->value = vmdk_get_extent_info(&s->extents[i]);
diff --git a/blockdev.c b/blockdev.c
index fe6fb5dc1d..2602298a26 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1090,7 +1090,7 @@  void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
     };
     TransactionAction action = {
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
-        .u.blockdev_snapshot_sync.data = &snapshot,
+        .u.blockdev_snapshot_sync = snapshot,
     };
     blockdev_do_action(&action, errp);
 }
@@ -1104,7 +1104,7 @@  void qmp_blockdev_snapshot(const char *node, const char *overlay,
     };
     TransactionAction action = {
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
-        .u.blockdev_snapshot.data = &snapshot_data,
+        .u.blockdev_snapshot = snapshot_data,
     };
     blockdev_do_action(&action, errp);
 }
@@ -1119,7 +1119,7 @@  void qmp_blockdev_snapshot_internal_sync(const char *device,
     };
     TransactionAction action = {
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
-        .u.blockdev_snapshot_internal_sync.data = &snapshot,
+        .u.blockdev_snapshot_internal_sync = snapshot,
     };
     blockdev_do_action(&action, errp);
 }
@@ -1289,7 +1289,7 @@  static void internal_snapshot_prepare(BlkActionState *common,
 
     g_assert(common->action->type ==
              TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
-    internal = common->action->u.blockdev_snapshot_internal_sync.data;
+    internal = &common->action->u.blockdev_snapshot_internal_sync;
     state = DO_UPCAST(InternalSnapshotState, common, common);
 
     /* 1. parse input */
@@ -1453,7 +1453,7 @@  static void external_snapshot_prepare(BlkActionState *common,
     switch (action->type) {
     case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:
         {
-            BlockdevSnapshot *s = action->u.blockdev_snapshot.data;
+            BlockdevSnapshot *s = &action->u.blockdev_snapshot;
             device = s->node;
             node_name = s->node;
             new_image_file = NULL;
@@ -1462,7 +1462,7 @@  static void external_snapshot_prepare(BlkActionState *common,
         break;
     case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
         {
-            BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync.data;
+            BlockdevSnapshotSync *s = &action->u.blockdev_snapshot_sync;
             device = s->has_device ? s->device : NULL;
             node_name = s->has_node_name ? s->node_name : NULL;
             new_image_file = s->snapshot_file;
@@ -1507,7 +1507,7 @@  static void external_snapshot_prepare(BlkActionState *common,
     }
 
     if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
-        BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync.data;
+        BlockdevSnapshotSync *s = &action->u.blockdev_snapshot_sync;
         const char *format = s->has_format ? s->format : "qcow2";
         enum NewImageMode mode;
         const char *snapshot_node_name =
@@ -1712,7 +1712,7 @@  static void drive_backup_prepare(BlkActionState *common, Error **errp)
     int ret;
 
     assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
-    backup = common->action->u.drive_backup.data;
+    backup = &common->action->u.drive_backup;
 
     if (!backup->has_mode) {
         backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
@@ -1907,7 +1907,7 @@  static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
     int ret;
 
     assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
-    backup = common->action->u.blockdev_backup.data;
+    backup = &common->action->u.blockdev_backup;
 
     bs = bdrv_lookup_bs(backup->device, backup->device, errp);
     if (!bs) {
@@ -2012,7 +2012,7 @@  static void block_dirty_bitmap_add_prepare(BlkActionState *common,
         return;
     }
 
-    action = common->action->u.block_dirty_bitmap_add.data;
+    action = &common->action->u.block_dirty_bitmap_add;
     /* AIO context taken and released within qmp_block_dirty_bitmap_add */
     qmp_block_dirty_bitmap_add(action->node, action->name,
                                action->has_granularity, action->granularity,
@@ -2033,7 +2033,7 @@  static void block_dirty_bitmap_add_abort(BlkActionState *common)
     BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
                                              common, common);
 
-    action = common->action->u.block_dirty_bitmap_add.data;
+    action = &common->action->u.block_dirty_bitmap_add;
     /* Should not be able to fail: IF the bitmap was added via .prepare(),
      * then the node reference and bitmap name must have been valid.
      */
@@ -2053,7 +2053,7 @@  static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
         return;
     }
 
-    action = common->action->u.block_dirty_bitmap_clear.data;
+    action = &common->action->u.block_dirty_bitmap_clear;
     state->bitmap = block_dirty_bitmap_lookup(action->node,
                                               action->name,
                                               &state->bs,
@@ -2098,7 +2098,7 @@  static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
         return;
     }
 
-    action = common->action->u.block_dirty_bitmap_enable.data;
+    action = &common->action->u.block_dirty_bitmap_enable;
     state->bitmap = block_dirty_bitmap_lookup(action->node,
                                               action->name,
                                               NULL,
@@ -2136,7 +2136,7 @@  static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
         return;
     }
 
-    action = common->action->u.block_dirty_bitmap_disable.data;
+    action = &common->action->u.block_dirty_bitmap_disable;
     state->bitmap = block_dirty_bitmap_lookup(action->node,
                                               action->name,
                                               NULL,
@@ -2174,7 +2174,7 @@  static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
         return;
     }
 
-    action = common->action->u.block_dirty_bitmap_merge.data;
+    action = &common->action->u.block_dirty_bitmap_merge;
 
     state->bitmap = block_dirty_bitmap_merge(action->node, action->target,
                                              action->bitmaps, &state->backup,
@@ -2192,7 +2192,7 @@  static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
         return;
     }
 
-    action = common->action->u.block_dirty_bitmap_remove.data;
+    action = &common->action->u.block_dirty_bitmap_remove;
 
     state->bitmap = block_dirty_bitmap_remove(action->node, action->name,
                                               false, &state->bs, errp);
@@ -2895,7 +2895,7 @@  void qmp_drive_backup(DriveBackup *backup, Error **errp)
 {
     TransactionAction action = {
         .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP,
-        .u.drive_backup.data = backup,
+        .u.drive_backup = *backup,
     };
     blockdev_do_action(&action, errp);
 }
@@ -2918,7 +2918,7 @@  void qmp_blockdev_backup(BlockdevBackup *backup, Error **errp)
 {
     TransactionAction action = {
         .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP,
-        .u.blockdev_backup.data = backup,
+        .u.blockdev_backup = *backup,
     };
     blockdev_do_action(&action, errp);
 }
diff --git a/chardev/char-file.c b/chardev/char-file.c
index 2fd80707e5..3f0f0b6045 100644
--- a/chardev/char-file.c
+++ b/chardev/char-file.c
@@ -39,7 +39,7 @@  static void qmp_chardev_open_file(Chardev *chr,
                                   bool *be_opened,
                                   Error **errp)
 {
-    ChardevFile *file = backend->u.file.data;
+    ChardevFile *file = &backend->u.file;
 #ifdef _WIN32
     HANDLE out;
     DWORD accessmode;
@@ -100,14 +100,13 @@  static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
                                     Error **errp)
 {
     const char *path = qemu_opt_get(opts, "path");
-    ChardevFile *file;
+    ChardevFile *file = &backend->u.file;
 
     backend->type = CHARDEV_BACKEND_KIND_FILE;
     if (path == NULL) {
         error_setg(errp, "chardev: file: no filename given");
         return;
     }
-    file = backend->u.file.data = g_new0(ChardevFile, 1);
     qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
     file->out = g_strdup(path);
 
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index 6f980bb836..bfb4bc6b8b 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -314,7 +314,7 @@  static void qemu_chr_open_mux(Chardev *chr,
                               bool *be_opened,
                               Error **errp)
 {
-    ChardevMux *mux = backend->u.mux.data;
+    ChardevMux *mux = &backend->u.mux;
     Chardev *drv;
     MuxChardev *d = MUX_CHARDEV(chr);
 
@@ -336,14 +336,13 @@  static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
                                Error **errp)
 {
     const char *chardev = qemu_opt_get(opts, "chardev");
-    ChardevMux *mux;
+    ChardevMux *mux = &backend->u.mux;
 
     if (chardev == NULL) {
         error_setg(errp, "chardev: mux: no chardev given");
         return;
     }
     backend->type = CHARDEV_BACKEND_KIND_MUX;
-    mux = backend->u.mux.data = g_new0(ChardevMux, 1);
     qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));
     mux->chardev = g_strdup(chardev);
 }
diff --git a/chardev/char-parallel.c b/chardev/char-parallel.c
index 05e7efbd6c..a17157a3be 100644
--- a/chardev/char-parallel.c
+++ b/chardev/char-parallel.c
@@ -244,7 +244,7 @@  static void qmp_chardev_open_parallel(Chardev *chr,
                                       bool *be_opened,
                                       Error **errp)
 {
-    ChardevHostdev *parallel = backend->u.parallel.data;
+    ChardevHostdev *parallel = &backend->u.parallel;
     int fd;
 
     fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
@@ -258,14 +258,13 @@  static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
                                     Error **errp)
 {
     const char *device = qemu_opt_get(opts, "path");
-    ChardevHostdev *parallel;
+    ChardevHostdev *parallel = &backend->u.parallel;
 
     if (device == NULL) {
         error_setg(errp, "chardev: parallel: no device path given");
         return;
     }
     backend->type = CHARDEV_BACKEND_KIND_PARALLEL;
-    parallel = backend->u.parallel.data = g_new0(ChardevHostdev, 1);
     qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));
     parallel->device = g_strdup(device);
 }
diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
index 7eca5d9a56..eb19d9a526 100644
--- a/chardev/char-pipe.c
+++ b/chardev/char-pipe.c
@@ -109,7 +109,7 @@  static void qemu_chr_open_pipe(Chardev *chr,
                                bool *be_opened,
                                Error **errp)
 {
-    ChardevHostdev *opts = backend->u.pipe.data;
+    ChardevHostdev *opts = &backend->u.pipe;
     const char *filename = opts->device;
 
     if (win_chr_pipe_init(chr, filename, errp) < 0) {
@@ -124,7 +124,7 @@  static void qemu_chr_open_pipe(Chardev *chr,
                                bool *be_opened,
                                Error **errp)
 {
-    ChardevHostdev *opts = backend->u.pipe.data;
+    ChardevHostdev *opts = &backend->u.pipe;
     int fd_in, fd_out;
     char *filename_in;
     char *filename_out;
@@ -158,14 +158,13 @@  static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
                                 Error **errp)
 {
     const char *device = qemu_opt_get(opts, "path");
-    ChardevHostdev *dev;
+    ChardevHostdev *dev = &backend->u.pipe;
 
     if (device == NULL) {
         error_setg(errp, "chardev: pipe: no device path given");
         return;
     }
     backend->type = CHARDEV_BACKEND_KIND_PIPE;
-    dev = backend->u.pipe.data = g_new0(ChardevHostdev, 1);
     qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
     dev->device = g_strdup(device);
 }
diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c
index d40d21d3cf..0ef2a17f90 100644
--- a/chardev/char-ringbuf.c
+++ b/chardev/char-ringbuf.c
@@ -97,7 +97,7 @@  static void qemu_chr_open_ringbuf(Chardev *chr,
                                   bool *be_opened,
                                   Error **errp)
 {
-    ChardevRingbuf *opts = backend->u.ringbuf.data;
+    ChardevRingbuf *opts = &backend->u.ringbuf;
     RingBufChardev *d = RINGBUF_CHARDEV(chr);
 
     d->size = opts->has_size ? opts->size : 65536;
@@ -210,10 +210,9 @@  static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
                                    Error **errp)
 {
     int val;
-    ChardevRingbuf *ringbuf;
+    ChardevRingbuf *ringbuf = &backend->u.ringbuf;
 
     backend->type = CHARDEV_BACKEND_KIND_RINGBUF;
-    ringbuf = backend->u.ringbuf.data = g_new0(ChardevRingbuf, 1);
     qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
 
     val = qemu_opt_get_size(opts, "size", 0);
diff --git a/chardev/char-serial.c b/chardev/char-serial.c
index 7c3d84ae24..baec955ecf 100644
--- a/chardev/char-serial.c
+++ b/chardev/char-serial.c
@@ -263,7 +263,7 @@  static void qmp_chardev_open_serial(Chardev *chr,
                                     bool *be_opened,
                                     Error **errp)
 {
-    ChardevHostdev *serial = backend->u.serial.data;
+    ChardevHostdev *serial = &backend->u.serial;
     int fd;
 
     fd = qmp_chardev_open_file_source(serial->device, O_RDWR | O_NONBLOCK,
@@ -283,14 +283,13 @@  static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
                                   Error **errp)
 {
     const char *device = qemu_opt_get(opts, "path");
-    ChardevHostdev *serial;
+    ChardevHostdev *serial = &backend->u.serial;
 
     if (device == NULL) {
         error_setg(errp, "chardev: serial/tty: no device path given");
         return;
     }
     backend->type = CHARDEV_BACKEND_KIND_SERIAL;
-    serial = backend->u.serial.data = g_new0(ChardevHostdev, 1);
     qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
     serial->device = g_strdup(device);
 }
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 95e45812d5..5332439d34 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -1301,7 +1301,7 @@  static void qmp_chardev_open_socket(Chardev *chr,
                                     Error **errp)
 {
     SocketChardev *s = SOCKET_CHARDEV(chr);
-    ChardevSocket *sock = backend->u.socket.data;
+    ChardevSocket *sock = &backend->u.socket;
     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
     bool is_listen      = sock->has_server  ? sock->server  : true;
     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
@@ -1403,7 +1403,7 @@  static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
     }
 
     backend->type = CHARDEV_BACKEND_KIND_SOCKET;
-    sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
+    sock = &backend->u.socket;
     qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
 
     sock->has_nodelay = qemu_opt_get(opts, "delay");
@@ -1435,16 +1435,14 @@  static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
 
     addr = g_new0(SocketAddressLegacy, 1);
     if (path) {
-        UnixSocketAddress *q_unix;
+        UnixSocketAddress *q_unix = &addr->u.q_unix;
         addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
-        q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
         q_unix->path = g_strdup(path);
         q_unix->tight = tight;
         q_unix->abstract = abstract;
     } else if (host) {
         addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
-        addr->u.inet.data = g_new(InetSocketAddress, 1);
-        *addr->u.inet.data = (InetSocketAddress) {
+        addr->u.inet = (InetSocketAddress) {
             .host = g_strdup(host),
             .port = g_strdup(port),
             .has_to = qemu_opt_get(opts, "to"),
@@ -1456,8 +1454,7 @@  static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
         };
     } else if (fd) {
         addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
-        addr->u.fd.data = g_new(String, 1);
-        addr->u.fd.data->str = g_strdup(fd);
+        addr->u.fd.str = g_strdup(fd);
     } else {
         g_assert_not_reached();
     }
diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c
index 403da308c9..81ee655a21 100644
--- a/chardev/char-stdio.c
+++ b/chardev/char-stdio.c
@@ -87,7 +87,7 @@  static void qemu_chr_open_stdio(Chardev *chr,
                                 bool *be_opened,
                                 Error **errp)
 {
-    ChardevStdio *opts = backend->u.stdio.data;
+    ChardevStdio *opts = &backend->u.stdio;
     struct sigaction act;
 
     if (is_daemonized()) {
@@ -120,10 +120,9 @@  static void qemu_chr_open_stdio(Chardev *chr,
 static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
                                  Error **errp)
 {
-    ChardevStdio *stdio;
+    ChardevStdio *stdio = &backend->u.stdio;
 
     backend->type = CHARDEV_BACKEND_KIND_STDIO;
-    stdio = backend->u.stdio.data = g_new0(ChardevStdio, 1);
     qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));
     stdio->has_signal = true;
     stdio->signal = qemu_opt_get_bool(opts, "signal", true);
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index 16b5dbce58..3b1bdddbbd 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -140,7 +140,7 @@  static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
     const char *localport = qemu_opt_get(opts, "localport");
     bool has_local = false;
     SocketAddressLegacy *addr;
-    ChardevUdp *udp;
+    ChardevUdp *udp = &backend->u.udp;
 
     backend->type = CHARDEV_BACKEND_KIND_UDP;
     if (host == NULL || strlen(host) == 0) {
@@ -161,13 +161,11 @@  static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
         has_local = true;
     }
 
-    udp = backend->u.udp.data = g_new0(ChardevUdp, 1);
     qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
 
     addr = g_new0(SocketAddressLegacy, 1);
     addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
-    addr->u.inet.data = g_new(InetSocketAddress, 1);
-    *addr->u.inet.data = (InetSocketAddress) {
+    addr->u.inet = (InetSocketAddress) {
         .host = g_strdup(host),
         .port = g_strdup(port),
         .has_ipv4 = qemu_opt_get(opts, "ipv4"),
@@ -181,8 +179,7 @@  static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
         udp->has_local = true;
         addr = g_new0(SocketAddressLegacy, 1);
         addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
-        addr->u.inet.data = g_new(InetSocketAddress, 1);
-        *addr->u.inet.data = (InetSocketAddress) {
+        addr->u.inet = (InetSocketAddress) {
             .host = g_strdup(localaddr),
             .port = g_strdup(localport),
         };
@@ -195,7 +192,7 @@  static void qmp_chardev_open_udp(Chardev *chr,
                                  bool *be_opened,
                                  Error **errp)
 {
-    ChardevUdp *udp = backend->u.udp.data;
+    ChardevUdp *udp = &backend->u.udp;
     SocketAddress *local_addr = socket_address_flatten(udp->local);
     SocketAddress *remote_addr = socket_address_flatten(udp->remote);
     QIOChannelSocket *sioc = qio_channel_socket_new();
diff --git a/chardev/char.c b/chardev/char.c
index 028612c333..5192964694 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -238,7 +238,7 @@  static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
 {
     ChardevClass *cc = CHARDEV_GET_CLASS(chr);
     /* Any ChardevCommon member would work */
-    ChardevCommon *common = backend ? backend->u.null.data : NULL;
+    ChardevCommon *common = backend ? &backend->u.null : NULL;
 
     if (common && common->has_logfile) {
         int flags = O_WRONLY | O_CREAT;
@@ -625,9 +625,8 @@  ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
             return NULL;
         }
     } else {
-        ChardevCommon *ccom = g_new0(ChardevCommon, 1);
-        qemu_chr_parse_common(opts, ccom);
-        backend->u.null.data = ccom; /* Any ChardevCommon member would work */
+        /* Any ChardevCommon member would work */
+        qemu_chr_parse_common(opts, &backend->u.null);
     }
 
     return backend;
@@ -690,8 +689,7 @@  Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context,
         qapi_free_ChardevBackend(backend);
         backend = g_new0(ChardevBackend, 1);
         backend->type = CHARDEV_BACKEND_KIND_MUX;
-        backend->u.mux.data = g_new0(ChardevMux, 1);
-        backend->u.mux.data->chardev = g_strdup(bid);
+        backend->u.mux.chardev = g_strdup(bid);
         mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context, errp);
         if (mux == NULL) {
             object_unparent(OBJECT(chr));
diff --git a/chardev/msmouse.c b/chardev/msmouse.c
index eb9231dcdb..98b0ef8cd7 100644
--- a/chardev/msmouse.c
+++ b/chardev/msmouse.c
@@ -111,12 +111,12 @@  static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         mouse->axis[move->axis] += move->value;
         break;
 
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         mouse->btns[btn->button] = btn->down;
         mouse->btnc[btn->button] = true;
         break;
diff --git a/chardev/wctablet.c b/chardev/wctablet.c
index 95e005f5a5..8479f59183 100644
--- a/chardev/wctablet.c
+++ b/chardev/wctablet.c
@@ -154,12 +154,12 @@  static void wctablet_input_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         tablet->axis[move->axis] = move->value;
         break;
 
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         tablet->btns[btn->button] = btn->down;
         break;
 
diff --git a/hw/core/numa.c b/hw/core/numa.c
index 7c4dd4e68e..24fe0e11d8 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -765,19 +765,19 @@  static void numa_stat_memory_devices(NumaNodeMem node_mem[])
             case MEMORY_DEVICE_INFO_KIND_DIMM:
             case MEMORY_DEVICE_INFO_KIND_NVDIMM:
                 pcdimm_info = value->type == MEMORY_DEVICE_INFO_KIND_DIMM ?
-                              value->u.dimm.data : value->u.nvdimm.data;
+                              &value->u.dimm : &value->u.nvdimm;
                 node_mem[pcdimm_info->node].node_mem += pcdimm_info->size;
                 node_mem[pcdimm_info->node].node_plugged_mem +=
                     pcdimm_info->size;
                 break;
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:
-                vpi = value->u.virtio_pmem.data;
+                vpi = &value->u.virtio_pmem;
                 /* TODO: once we support numa, assign to right node */
                 node_mem[0].node_mem += vpi->size;
                 node_mem[0].node_plugged_mem += vpi->size;
                 break;
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM:
-                vmi = value->u.virtio_mem.data;
+                vmi = &value->u.virtio_mem;
                 node_mem[vmi->node].node_mem += vmi->size;
                 node_mem[vmi->node].node_plugged_mem += vmi->size;
                 break;
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 838260b6ad..6aa6010774 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -201,7 +201,7 @@  static void xenfb_key_event(DeviceState *dev, QemuConsole *src,
                             InputEvent *evt)
 {
     struct XenInput *xenfb = (struct XenInput *)dev;
-    InputKeyEvent *key = evt->u.key.data;
+    InputKeyEvent *key = &evt->u.key;
     int qcode = qemu_input_key_value_to_qcode(key->key);
     int lnx;
 
@@ -236,7 +236,7 @@  static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         switch (btn->button) {
         case INPUT_BUTTON_LEFT:
             xenfb_send_key(xenfb, btn->down, BTN_LEFT);
@@ -263,7 +263,7 @@  static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,
         break;
 
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         if (xenfb->raw_pointer_wanted) {
             xenfb->axis[move->axis] = move->value;
         } else {
@@ -289,7 +289,7 @@  static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,
         break;
 
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         xenfb->axis[move->axis] += move->value;
         break;
 
diff --git a/hw/input/hid.c b/hw/input/hid.c
index 89239b5634..2472c5a902 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -126,7 +126,7 @@  static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         if (move->axis == INPUT_AXIS_X) {
             e->xdx += move->value;
         } else if (move->axis == INPUT_AXIS_Y) {
@@ -135,7 +135,7 @@  static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
         break;
 
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         if (move->axis == INPUT_AXIS_X) {
             e->xdx = move->value;
         } else if (move->axis == INPUT_AXIS_Y) {
@@ -144,7 +144,7 @@  static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
         break;
 
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         if (btn->down) {
             e->buttons_state |= bmap[btn->button];
             if (btn->button == INPUT_BUTTON_WHEEL_UP) {
@@ -230,7 +230,7 @@  static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
     HIDState *hs = (HIDState *)dev;
     int scancodes[3], i, count;
     int slot;
-    InputKeyEvent *key = evt->u.key.data;
+    InputKeyEvent *key = &evt->u.key;
 
     count = qemu_input_key_value_to_scancode(key->key,
                                              key->down,
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index f8746d2f52..1176ccc88c 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -284,7 +284,7 @@  static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
                                InputEvent *evt)
 {
     PS2KbdState *s = (PS2KbdState *)dev;
-    InputKeyEvent *key = evt->u.key.data;
+    InputKeyEvent *key = &evt->u.key;
     int qcode;
     uint16_t keycode = 0;
     int mod;
@@ -727,7 +727,7 @@  static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         if (move->axis == INPUT_AXIS_X) {
             s->mouse_dx += move->value;
         } else if (move->axis == INPUT_AXIS_Y) {
@@ -736,7 +736,7 @@  static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
         break;
 
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         if (btn->down) {
             s->mouse_buttons |= bmap[btn->button];
             if (btn->button == INPUT_BUTTON_WHEEL_UP) {
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index a7a244a95d..1c7b07cf42 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -83,7 +83,7 @@  static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
-        key = evt->u.key.data;
+        key = &evt->u.key;
         qcode = qemu_input_key_value_to_qcode(key->key);
         if (qcode < qemu_input_map_qcode_to_linux_len &&
             qemu_input_map_qcode_to_linux[qcode]) {
@@ -99,7 +99,7 @@  static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
         }
         break;
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         if (vhid->wheel_axis &&
             (btn->button == INPUT_BUTTON_WHEEL_UP ||
              btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
@@ -123,14 +123,14 @@  static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
         }
         break;
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         event.type  = cpu_to_le16(EV_REL);
         event.code  = cpu_to_le16(axismap_rel[move->axis]);
         event.value = cpu_to_le32(move->value);
         virtio_input_send(vinput, &event);
         break;
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         event.type  = cpu_to_le16(EV_ABS);
         event.code  = cpu_to_le16(axismap_abs[move->axis]);
         event.value = cpu_to_le32(move->value);
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index c30351070b..3d6f836621 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -236,11 +236,19 @@  static MemoryRegion *pc_dimm_md_get_memory_region(MemoryDeviceState *md,
 static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,
                                         MemoryDeviceInfo *info)
 {
-    PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);
+    PCDIMMDeviceInfo *di;
     const DeviceClass *dc = DEVICE_GET_CLASS(md);
     const PCDIMMDevice *dimm = PC_DIMM(md);
     const DeviceState *dev = DEVICE(md);
 
+    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
+        di = &info->u.nvdimm;
+        info->type = MEMORY_DEVICE_INFO_KIND_NVDIMM;
+    } else {
+        di = &info->u.dimm;
+        info->type = MEMORY_DEVICE_INFO_KIND_DIMM;
+    }
+
     if (dev->id) {
         di->has_id = true;
         di->id = g_strdup(dev->id);
@@ -253,14 +261,6 @@  static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md,
     di->size = object_property_get_uint(OBJECT(dimm), PC_DIMM_SIZE_PROP,
                                         NULL);
     di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));
-
-    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
-        info->u.nvdimm.data = di;
-        info->type = MEMORY_DEVICE_INFO_KIND_NVDIMM;
-    } else {
-        info->u.dimm.data = di;
-        info->type = MEMORY_DEVICE_INFO_KIND_DIMM;
-    }
 }
 
 static void pc_dimm_class_init(ObjectClass *oc, void *data)
diff --git a/hw/virtio/virtio-mem-pci.c b/hw/virtio/virtio-mem-pci.c
index 913f4a3326..f93572fc27 100644
--- a/hw/virtio/virtio-mem-pci.c
+++ b/hw/virtio/virtio-mem-pci.c
@@ -58,7 +58,7 @@  static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState *md,
 static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,
                                             MemoryDeviceInfo *info)
 {
-    VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);
+    VirtioMEMDeviceInfo *vi = &info->u.virtio_mem;
     VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);
     VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev);
     VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
@@ -72,7 +72,6 @@  static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,
     /* let the real device handle everything else */
     vpc->fill_device_info(vmem, vi);
 
-    info->u.virtio_mem.data = vi;
     info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;
 }
 
diff --git a/hw/virtio/virtio-pmem-pci.c b/hw/virtio/virtio-pmem-pci.c
index 2b2a0b1eae..adf17f873b 100644
--- a/hw/virtio/virtio-pmem-pci.c
+++ b/hw/virtio/virtio-pmem-pci.c
@@ -63,7 +63,7 @@  static uint64_t virtio_pmem_pci_get_plugged_size(const MemoryDeviceState *md,
 static void virtio_pmem_pci_fill_device_info(const MemoryDeviceState *md,
                                              MemoryDeviceInfo *info)
 {
-    VirtioPMEMDeviceInfo *vi = g_new0(VirtioPMEMDeviceInfo, 1);
+    VirtioPMEMDeviceInfo *vi = &info->u.virtio_pmem;
     VirtIOPMEMPCI *pci_pmem = VIRTIO_PMEM_PCI(md);
     VirtIOPMEM *pmem = VIRTIO_PMEM(&pci_pmem->vdev);
     VirtIOPMEMClass *vpc = VIRTIO_PMEM_GET_CLASS(pmem);
@@ -77,7 +77,6 @@  static void virtio_pmem_pci_fill_device_info(const MemoryDeviceState *md,
     /* let the real device handle everything else */
     vpc->fill_device_info(pmem, vi);
 
-    info->u.virtio_pmem.data = vi;
     info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM;
 }
 
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 9789f4277f..0324caa114 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -918,7 +918,7 @@  void hmp_info_tpm(Monitor *mon, const QDict *qdict)
 
         switch (ti->options->type) {
         case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
-            tpo = ti->options->u.passthrough.data;
+            tpo = &ti->options->u.passthrough;
             monitor_printf(mon, "%s%s%s%s",
                            tpo->has_path ? ",path=" : "",
                            tpo->has_path ? tpo->path : "",
@@ -926,7 +926,7 @@  void hmp_info_tpm(Monitor *mon, const QDict *qdict)
                            tpo->has_cancel_path ? tpo->cancel_path : "");
             break;
         case TPM_TYPE_OPTIONS_KIND_EMULATOR:
-            teo = ti->options->u.emulator.data;
+            teo = &ti->options->u.emulator;
             monitor_printf(mon, ",chardev=%s", teo->chardev);
             break;
         case TPM_TYPE_OPTIONS_KIND__MAX:
@@ -1728,14 +1728,14 @@  void hmp_sendkey(Monitor *mon, const QDict *qdict)
                 goto err_out;
             }
             keylist->value->type = KEY_VALUE_KIND_NUMBER;
-            keylist->value->u.number.data = value;
+            keylist->value->u.number = value;
         } else {
             int idx = index_from_key(keys, keyname_len);
             if (idx == Q_KEY_CODE__MAX) {
                 goto err_out;
             }
             keylist->value->type = KEY_VALUE_KIND_QCODE;
-            keylist->value->u.qcode.data = idx;
+            keylist->value->u.qcode = idx;
         }
 
         if (!*separator) {
@@ -1860,7 +1860,7 @@  void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
             case MEMORY_DEVICE_INFO_KIND_DIMM:
             case MEMORY_DEVICE_INFO_KIND_NVDIMM:
                 di = value->type == MEMORY_DEVICE_INFO_KIND_DIMM ?
-                     value->u.dimm.data : value->u.nvdimm.data;
+                     &value->u.dimm : &value->u.nvdimm;
                 monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
                                MemoryDeviceInfoKind_str(value->type),
                                di->id ? di->id : "");
@@ -1875,7 +1875,7 @@  void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
                                di->hotpluggable ? "true" : "false");
                 break;
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM:
-                vpi = value->u.virtio_pmem.data;
+                vpi = &value->u.virtio_pmem;
                 monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
                                MemoryDeviceInfoKind_str(value->type),
                                vpi->id ? vpi->id : "");
@@ -1884,7 +1884,7 @@  void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
                 monitor_printf(mon, "  memdev: %s\n", vpi->memdev);
                 break;
             case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM:
-                vmi = value->u.virtio_mem.data;
+                vmi = &value->u.virtio_mem;
                 monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
                                MemoryDeviceInfoKind_str(value->type),
                                vmi->id ? vmi->id : "");
diff --git a/qemu-keymap.c b/qemu-keymap.c
index 536e8f2385..52637c449c 100644
--- a/qemu-keymap.c
+++ b/qemu-keymap.c
@@ -38,7 +38,7 @@  static uint32_t qcode_to_number(uint32_t qcode)
     uint32_t number;
 
     keyvalue.type = KEY_VALUE_KIND_QCODE;
-    keyvalue.u.qcode.data = qcode;
+    keyvalue.u.qcode = qcode;
     number = qemu_input_key_value_to_number(&keyvalue);
     assert(number != 0);
     return number;
diff --git a/replay/replay-input.c b/replay/replay-input.c
index 1147e3d34e..c1eb1b79e1 100644
--- a/replay/replay-input.c
+++ b/replay/replay-input.c
@@ -26,16 +26,16 @@  void replay_save_input_event(InputEvent *evt)
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
-        key = evt->u.key.data;
+        key = &evt->u.key;
         replay_put_dword(key->key->type);
 
         switch (key->key->type) {
         case KEY_VALUE_KIND_NUMBER:
-            replay_put_qword(key->key->u.number.data);
+            replay_put_qword(key->key->u.number);
             replay_put_byte(key->down);
             break;
         case KEY_VALUE_KIND_QCODE:
-            replay_put_dword(key->key->u.qcode.data);
+            replay_put_dword(key->key->u.qcode);
             replay_put_byte(key->down);
             break;
         case KEY_VALUE_KIND__MAX:
@@ -44,17 +44,17 @@  void replay_save_input_event(InputEvent *evt)
         }
         break;
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         replay_put_dword(btn->button);
         replay_put_byte(btn->down);
         break;
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         replay_put_dword(move->axis);
         replay_put_qword(move->value);
         break;
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         replay_put_dword(move->axis);
         replay_put_qword(move->value);
         break;
@@ -68,26 +68,21 @@  InputEvent *replay_read_input_event(void)
 {
     InputEvent evt;
     KeyValue keyValue;
-    InputKeyEvent key;
-    key.key = &keyValue;
-    InputBtnEvent btn;
-    InputMoveEvent rel;
-    InputMoveEvent abs;
+    evt.u.key.key = &keyValue;
 
     evt.type = replay_get_dword();
     switch (evt.type) {
     case INPUT_EVENT_KIND_KEY:
-        evt.u.key.data = &key;
-        evt.u.key.data->key->type = replay_get_dword();
+        evt.u.key.key->type = replay_get_dword();
 
-        switch (evt.u.key.data->key->type) {
+        switch (evt.u.key.key->type) {
         case KEY_VALUE_KIND_NUMBER:
-            evt.u.key.data->key->u.number.data = replay_get_qword();
-            evt.u.key.data->down = replay_get_byte();
+            evt.u.key.key->u.number = replay_get_qword();
+            evt.u.key.down = replay_get_byte();
             break;
         case KEY_VALUE_KIND_QCODE:
-            evt.u.key.data->key->u.qcode.data = (QKeyCode)replay_get_dword();
-            evt.u.key.data->down = replay_get_byte();
+            evt.u.key.key->u.qcode = (QKeyCode)replay_get_dword();
+            evt.u.key.down = replay_get_byte();
             break;
         case KEY_VALUE_KIND__MAX:
             /* keep gcc happy */
@@ -95,19 +90,16 @@  InputEvent *replay_read_input_event(void)
         }
         break;
     case INPUT_EVENT_KIND_BTN:
-        evt.u.btn.data = &btn;
-        evt.u.btn.data->button = (InputButton)replay_get_dword();
-        evt.u.btn.data->down = replay_get_byte();
+        evt.u.btn.button = (InputButton)replay_get_dword();
+        evt.u.btn.down = replay_get_byte();
         break;
     case INPUT_EVENT_KIND_REL:
-        evt.u.rel.data = &rel;
-        evt.u.rel.data->axis = (InputAxis)replay_get_dword();
-        evt.u.rel.data->value = replay_get_qword();
+        evt.u.rel.axis = (InputAxis)replay_get_dword();
+        evt.u.rel.value = replay_get_qword();
         break;
     case INPUT_EVENT_KIND_ABS:
-        evt.u.abs.data = &abs;
-        evt.u.abs.data->axis = (InputAxis)replay_get_dword();
-        evt.u.abs.data->value = replay_get_qword();
+        evt.u.abs.axis = (InputAxis)replay_get_dword();
+        evt.u.abs.value = replay_get_qword();
         break;
     case INPUT_EVENT_KIND__MAX:
         /* keep gcc happy */
diff --git a/tests/test-char.c b/tests/test-char.c
index 9196e566e9..0e7a033a90 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -1220,7 +1220,7 @@  static void char_file_fifo_test(void)
                          .has_in = true,
                          .out = out };
     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
-                               .u.file.data = &file };
+                               .u.file = file };
     FeHandler fe = { 0, };
     int fd, ret;
 
@@ -1273,19 +1273,17 @@  static void char_file_test_internal(Chardev *ext_chr, const char *filepath)
     char *out;
     Chardev *chr;
     char *contents = NULL;
-    ChardevFile file = {};
-    ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
-                               .u.file.data = &file };
+    ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE };
     gsize length;
     int ret;
 
     if (ext_chr) {
         chr = ext_chr;
         out = g_strdup(filepath);
-        file.out = out;
+        backend.u.file.out = out;
     } else {
         out = g_build_filename(tmp_path, "out", NULL);
-        file.out = out;
+        backend.u.file.out = out;
         chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
                                NULL, &error_abort);
     }
@@ -1384,7 +1382,7 @@  static void char_hotswap_test(void)
     char *filename = g_build_filename(tmp_path, "file", NULL);
     ChardevFile file = { .out = filename };
     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
-                               .u.file.data = &file };
+                               .u.file = file };
     ChardevReturn *ret;
 
     int port;
diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c
index 5e1e8b2f5e..0a62704bed 100644
--- a/tests/test-clone-visitor.c
+++ b/tests/test-clone-visitor.c
@@ -110,7 +110,7 @@  static void test_clone_complex1(void)
     dst = QAPI_CLONE(UserDefListUnion, src);
     g_assert(dst);
     g_assert_cmpint(dst->type, ==, src->type);
-    g_assert(!dst->u.string.data);
+    g_assert(!dst->u.string);
 
     qapi_free_UserDefListUnion(src);
     qapi_free_UserDefListUnion(dst);
@@ -155,30 +155,30 @@  static void test_clone_complex3(void)
     tmp = src->array = g_new0(__org_qemu_x_Union1List, 1);
     tmp->value = g_new0(__org_qemu_x_Union1, 1);
     tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-    tmp->value->u.__org_qemu_x_branch.data = g_strdup("one");
+    tmp->value->u.__org_qemu_x_branch = g_strdup("one");
     tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);
     tmp->value = g_new0(__org_qemu_x_Union1, 1);
     tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-    tmp->value->u.__org_qemu_x_branch.data = g_strdup("two");
+    tmp->value->u.__org_qemu_x_branch = g_strdup("two");
     tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);
     tmp->value = g_new0(__org_qemu_x_Union1, 1);
     tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-    tmp->value->u.__org_qemu_x_branch.data = g_strdup("three");
+    tmp->value->u.__org_qemu_x_branch = g_strdup("three");
 
     dst = QAPI_CLONE(__org_qemu_x_Struct2, src);
     g_assert(dst);
     tmp = dst->array;
     g_assert(tmp);
     g_assert(tmp->value);
-    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "one");
+    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch, ==, "one");
     tmp = tmp->next;
     g_assert(tmp);
     g_assert(tmp->value);
-    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "two");
+    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch, ==, "two");
     tmp = tmp->next;
     g_assert(tmp);
     g_assert(tmp->value);
-    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "three");
+    g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch, ==, "three");
     tmp = tmp->next;
     g_assert(!tmp);
 
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index d3413bfef0..3d699fbb66 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -136,7 +136,7 @@  __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
 
     ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-    ret->u.__org_qemu_x_branch.data = strdup("blah1");
+    ret->u.__org_qemu_x_branch = strdup("blah1");
 
     /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
     if (b && b->value && !b->value->has_q_wchar_t) {
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index e41b91a2a6..b976ab9763 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -710,7 +710,7 @@  static void test_list_union_integer_helper(TestInputVisitorData *data,
     switch (kind) {
     case USER_DEF_LIST_UNION_KIND_INTEGER: {
         intList *elem = NULL;
-        for (i = 0, elem = cvalue->u.integer.data;
+        for (i = 0, elem = cvalue->u.integer;
              elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
@@ -718,56 +718,56 @@  static void test_list_union_integer_helper(TestInputVisitorData *data,
     }
     case USER_DEF_LIST_UNION_KIND_S8: {
         int8List *elem = NULL;
-        for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.s8; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S16: {
         int16List *elem = NULL;
-        for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.s16; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S32: {
         int32List *elem = NULL;
-        for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.s32; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S64: {
         int64List *elem = NULL;
-        for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.s64; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U8: {
         uint8List *elem = NULL;
-        for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.u8; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U16: {
         uint16List *elem = NULL;
-        for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.u16; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U32: {
         uint32List *elem = NULL;
-        for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.u32; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U64: {
         uint64List *elem = NULL;
-        for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
+        for (i = 0, elem = cvalue->u.u64; elem; elem = elem->next, i++) {
             g_assert_cmpint(elem->value, ==, i);
         }
         break;
@@ -868,7 +868,7 @@  static void test_visitor_in_list_union_bool(TestInputVisitorData *data,
     g_assert(cvalue != NULL);
     g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_BOOLEAN);
 
-    for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
+    for (i = 0, elem = cvalue->u.boolean; elem; elem = elem->next, i++) {
         g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
     }
 
@@ -900,7 +900,7 @@  static void test_visitor_in_list_union_string(TestInputVisitorData *data,
     g_assert(cvalue != NULL);
     g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_STRING);
 
-    for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
+    for (i = 0, elem = cvalue->u.string; elem; elem = elem->next, i++) {
         gchar str[8];
         sprintf(str, "%d", i);
         g_assert_cmpstr(elem->value, ==, str);
@@ -936,7 +936,7 @@  static void test_visitor_in_list_union_number(TestInputVisitorData *data,
     g_assert(cvalue != NULL);
     g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_NUMBER);
 
-    for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
+    for (i = 0, elem = cvalue->u.number; elem; elem = elem->next, i++) {
         GString *double_expected = g_string_new("");
         GString *double_actual = g_string_new("");
 
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 1c856d9bd2..202f848062 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -444,7 +444,7 @@  static void init_list_union(UserDefListUnion *cvalue)
     int i;
     switch (cvalue->type) {
     case USER_DEF_LIST_UNION_KIND_INTEGER: {
-        intList **list = &cvalue->u.integer.data;
+        intList **list = &cvalue->u.integer;
         for (i = 0; i < 32; i++) {
             *list = g_new0(intList, 1);
             (*list)->value = i;
@@ -454,7 +454,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S8: {
-        int8List **list = &cvalue->u.s8.data;
+        int8List **list = &cvalue->u.s8;
         for (i = 0; i < 32; i++) {
             *list = g_new0(int8List, 1);
             (*list)->value = i;
@@ -464,7 +464,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S16: {
-        int16List **list = &cvalue->u.s16.data;
+        int16List **list = &cvalue->u.s16;
         for (i = 0; i < 32; i++) {
             *list = g_new0(int16List, 1);
             (*list)->value = i;
@@ -474,7 +474,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S32: {
-        int32List **list = &cvalue->u.s32.data;
+        int32List **list = &cvalue->u.s32;
         for (i = 0; i < 32; i++) {
             *list = g_new0(int32List, 1);
             (*list)->value = i;
@@ -484,7 +484,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_S64: {
-        int64List **list = &cvalue->u.s64.data;
+        int64List **list = &cvalue->u.s64;
         for (i = 0; i < 32; i++) {
             *list = g_new0(int64List, 1);
             (*list)->value = i;
@@ -494,7 +494,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U8: {
-        uint8List **list = &cvalue->u.u8.data;
+        uint8List **list = &cvalue->u.u8;
         for (i = 0; i < 32; i++) {
             *list = g_new0(uint8List, 1);
             (*list)->value = i;
@@ -504,7 +504,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U16: {
-        uint16List **list = &cvalue->u.u16.data;
+        uint16List **list = &cvalue->u.u16;
         for (i = 0; i < 32; i++) {
             *list = g_new0(uint16List, 1);
             (*list)->value = i;
@@ -514,7 +514,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U32: {
-        uint32List **list = &cvalue->u.u32.data;
+        uint32List **list = &cvalue->u.u32;
         for (i = 0; i < 32; i++) {
             *list = g_new0(uint32List, 1);
             (*list)->value = i;
@@ -524,7 +524,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_U64: {
-        uint64List **list = &cvalue->u.u64.data;
+        uint64List **list = &cvalue->u.u64;
         for (i = 0; i < 32; i++) {
             *list = g_new0(uint64List, 1);
             (*list)->value = i;
@@ -534,7 +534,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_BOOLEAN: {
-        boolList **list = &cvalue->u.boolean.data;
+        boolList **list = &cvalue->u.boolean;
         for (i = 0; i < 32; i++) {
             *list = g_new0(boolList, 1);
             (*list)->value = QEMU_IS_ALIGNED(i, 3);
@@ -544,7 +544,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_STRING: {
-        strList **list = &cvalue->u.string.data;
+        strList **list = &cvalue->u.string;
         for (i = 0; i < 32; i++) {
             *list = g_new0(strList, 1);
             (*list)->value = g_strdup_printf("%d", i);
@@ -554,7 +554,7 @@  static void init_list_union(UserDefListUnion *cvalue)
         break;
     }
     case USER_DEF_LIST_UNION_KIND_NUMBER: {
-        numberList **list = &cvalue->u.number.data;
+        numberList **list = &cvalue->u.number;
         for (i = 0; i < 32; i++) {
             *list = g_new0(numberList, 1);
             (*list)->value = (double)i / 3;
diff --git a/ui/console.c b/ui/console.c
index 820e408170..2f93723ed6 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -2212,7 +2212,7 @@  static void vc_chr_open(Chardev *chr,
                         bool *be_opened,
                         Error **errp)
 {
-    ChardevVC *vc = backend->u.vc.data;
+    ChardevVC *vc = &backend->u.vc;
     VCChardev *drv = VC_CHARDEV(chr);
     QemuConsole *s;
     unsigned width = 0;
@@ -2362,10 +2362,9 @@  void qemu_display_help(void)
 void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp)
 {
     int val;
-    ChardevVC *vc;
+    ChardevVC *vc = &backend->u.vc;
 
     backend->type = CHARDEV_BACKEND_KIND_VC;
-    vc = backend->u.vc.data = g_new0(ChardevVC, 1);
     qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));
 
     val = qemu_opt_get_number(opts, "width", 0);
diff --git a/ui/input-keymap.c b/ui/input-keymap.c
index 1b756a6970..0232e25124 100644
--- a/ui/input-keymap.c
+++ b/ui/input-keymap.c
@@ -33,13 +33,13 @@  int qemu_input_linux_to_qcode(unsigned int lnx)
 int qemu_input_key_value_to_number(const KeyValue *value)
 {
     if (value->type == KEY_VALUE_KIND_QCODE) {
-        if (value->u.qcode.data >= qemu_input_map_qcode_to_qnum_len) {
+        if (value->u.qcode >= qemu_input_map_qcode_to_qnum_len) {
             return 0;
         }
-        return qemu_input_map_qcode_to_qnum[value->u.qcode.data];
+        return qemu_input_map_qcode_to_qnum[value->u.qcode];
     } else {
         assert(value->type == KEY_VALUE_KIND_NUMBER);
-        return value->u.number.data;
+        return value->u.number;
     }
 }
 
@@ -54,10 +54,10 @@  int qemu_input_key_number_to_qcode(unsigned int nr)
 int qemu_input_key_value_to_qcode(const KeyValue *value)
 {
     if (value->type == KEY_VALUE_KIND_QCODE) {
-        return value->u.qcode.data;
+        return value->u.qcode;
     } else {
         assert(value->type == KEY_VALUE_KIND_NUMBER);
-        return qemu_input_key_number_to_qcode(value->u.number.data);
+        return qemu_input_key_number_to_qcode(value->u.number);
     }
 }
 
@@ -68,7 +68,7 @@  int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
     int count = 0;
 
     if (value->type == KEY_VALUE_KIND_QCODE &&
-        value->u.qcode.data == Q_KEY_CODE_PAUSE) {
+        value->u.qcode == Q_KEY_CODE_PAUSE) {
         /* specific case */
         int v = down ? 0 : 0x80;
         codes[count++] = 0xe1;
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index 9fc78a639b..5a32b010d4 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -75,9 +75,9 @@  static KeyValue *copy_key_value(KeyValue *src)
     KeyValue *dst = g_new(KeyValue, 1);
     memcpy(dst, src, sizeof(*src));
     if (dst->type == KEY_VALUE_KIND_NUMBER) {
-        QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number.data);
+        QKeyCode code = qemu_input_key_number_to_qcode(dst->u.number);
         dst->type = KEY_VALUE_KIND_QCODE;
-        dst->u.qcode.data = code;
+        dst->u.qcode = code;
     }
     return dst;
 }
@@ -113,7 +113,7 @@  static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
 {
     QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
     int scancodes[3], i, count;
-    InputKeyEvent *key = evt->u.key.data;
+    InputKeyEvent *key = &evt->u.key;
 
     if (!entry || !entry->put_kbd) {
         return;
@@ -159,7 +159,7 @@  static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         if (btn->down) {
             s->buttons |= bmap[btn->button];
         } else {
@@ -181,11 +181,11 @@  static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
         }
         break;
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         s->axis[move->axis] = move->value;
         break;
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         s->axis[move->axis] += move->value;
         break;
     default:
diff --git a/ui/input.c b/ui/input.c
index 4791b089c7..a4078780ee 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -164,10 +164,10 @@  void qmp_input_send_event(bool has_device, const char *device,
         InputEvent *evt = e->value;
 
         if (evt->type == INPUT_EVENT_KIND_KEY &&
-            evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER) {
-            KeyValue *key = evt->u.key.data->key;
-            QKeyCode code = qemu_input_key_number_to_qcode(key->u.number.data);
-            qemu_input_event_send_key_qcode(con, code, evt->u.key.data->down);
+            evt->u.key.key->type == KEY_VALUE_KIND_NUMBER) {
+            KeyValue *key = evt->u.key.key;
+            QKeyCode code = qemu_input_key_number_to_qcode(key->u.number);
+            qemu_input_event_send_key_qcode(con, code, evt->u.key.down);
         } else {
             qemu_input_event_send(con, evt);
         }
@@ -183,7 +183,7 @@  static int qemu_input_transform_invert_abs_value(int value)
 
 static void qemu_input_transform_abs_rotate(InputEvent *evt)
 {
-    InputMoveEvent *move = evt->u.abs.data;
+    InputMoveEvent *move = &evt->u.abs;
     switch (graphic_rotate) {
     case 90:
         if (move->axis == INPUT_AXIS_X) {
@@ -220,16 +220,16 @@  static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
     }
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
-        key = evt->u.key.data;
+        key = &evt->u.key;
         switch (key->key->type) {
         case KEY_VALUE_KIND_NUMBER:
-            qcode = qemu_input_key_number_to_qcode(key->key->u.number.data);
+            qcode = qemu_input_key_number_to_qcode(key->key->u.number);
             name = QKeyCode_str(qcode);
-            trace_input_event_key_number(idx, key->key->u.number.data,
+            trace_input_event_key_number(idx, key->key->u.number,
                                          name, key->down);
             break;
         case KEY_VALUE_KIND_QCODE:
-            name = QKeyCode_str(key->key->u.qcode.data);
+            name = QKeyCode_str(key->key->u.qcode);
             trace_input_event_key_qcode(idx, name, key->down);
             break;
         case KEY_VALUE_KIND__MAX:
@@ -238,17 +238,17 @@  static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
         }
         break;
     case INPUT_EVENT_KIND_BTN:
-        btn = evt->u.btn.data;
+        btn = &evt->u.btn;
         name = InputButton_str(btn->button);
         trace_input_event_btn(idx, name, btn->down);
         break;
     case INPUT_EVENT_KIND_REL:
-        move = evt->u.rel.data;
+        move = &evt->u.rel;
         name = InputAxis_str(move->axis);
         trace_input_event_rel(idx, name, move->value);
         break;
     case INPUT_EVENT_KIND_ABS:
-        move = evt->u.abs.data;
+        move = &evt->u.abs;
         name = InputAxis_str(move->axis);
         trace_input_event_abs(idx, name, move->value);
         break;
@@ -355,7 +355,7 @@  void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
     /* Expect all parts of QEMU to send events with QCodes exclusively.
      * Key numbers are only supported as end-user input via QMP */
     assert(!(evt->type == INPUT_EVENT_KIND_KEY &&
-             evt->u.key.data->key->type == KEY_VALUE_KIND_NUMBER));
+             evt->u.key.key->type == KEY_VALUE_KIND_NUMBER));
 
 
     /*
@@ -367,8 +367,8 @@  void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
      * neeed to deal with this mistake
      */
     if (evt->type == INPUT_EVENT_KIND_KEY &&
-        evt->u.key.data->key->u.qcode.data == Q_KEY_CODE_SYSRQ) {
-        evt->u.key.data->key->u.qcode.data = Q_KEY_CODE_PRINT;
+        evt->u.key.key->u.qcode == Q_KEY_CODE_SYSRQ) {
+        evt->u.key.key->u.qcode = Q_KEY_CODE_PRINT;
     }
 
     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
@@ -407,10 +407,9 @@  void qemu_input_event_sync(void)
 static InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
 {
     InputEvent *evt = g_new0(InputEvent, 1);
-    evt->u.key.data = g_new0(InputKeyEvent, 1);
     evt->type = INPUT_EVENT_KIND_KEY;
-    evt->u.key.data->key = key;
-    evt->u.key.data->down = down;
+    evt->u.key.key = key;
+    evt->u.key.down = down;
     return evt;
 }
 
@@ -440,7 +439,7 @@  void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
 {
     KeyValue *key = g_new0(KeyValue, 1);
     key->type = KEY_VALUE_KIND_QCODE;
-    key->u.qcode.data = q;
+    key->u.qcode = q;
     qemu_input_event_send_key(src, key, down);
 }
 
@@ -469,7 +468,7 @@  void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down)
     };
     InputEvent evt = {
         .type = INPUT_EVENT_KIND_BTN,
-        .u.btn.data = &bevt,
+        .u.btn = bevt,
     };
 
     qemu_input_event_send(src, &evt);
@@ -520,7 +519,7 @@  void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
     };
     InputEvent evt = {
         .type = INPUT_EVENT_KIND_REL,
-        .u.rel.data = &move,
+        .u.rel = move,
     };
 
     qemu_input_event_send(src, &evt);
@@ -537,7 +536,7 @@  void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
     };
     InputEvent evt = {
         .type = INPUT_EVENT_KIND_ABS,
-        .u.abs.data = &move,
+        .u.abs = move,
     };
 
     qemu_input_event_send(src, &evt);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 05e5c73f9d..59e317cbb8 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -1365,21 +1365,21 @@  SocketAddress *socket_address_flatten(SocketAddressLegacy *addr_legacy)
     case SOCKET_ADDRESS_LEGACY_KIND_INET:
         addr->type = SOCKET_ADDRESS_TYPE_INET;
         QAPI_CLONE_MEMBERS(InetSocketAddress, &addr->u.inet,
-                           addr_legacy->u.inet.data);
+                           &addr_legacy->u.inet);
         break;
     case SOCKET_ADDRESS_LEGACY_KIND_UNIX:
         addr->type = SOCKET_ADDRESS_TYPE_UNIX;
         QAPI_CLONE_MEMBERS(UnixSocketAddress, &addr->u.q_unix,
-                           addr_legacy->u.q_unix.data);
+                           &addr_legacy->u.q_unix);
         break;
     case SOCKET_ADDRESS_LEGACY_KIND_VSOCK:
         addr->type = SOCKET_ADDRESS_TYPE_VSOCK;
         QAPI_CLONE_MEMBERS(VsockSocketAddress, &addr->u.vsock,
-                           addr_legacy->u.vsock.data);
+                           &addr_legacy->u.vsock);
         break;
     case SOCKET_ADDRESS_LEGACY_KIND_FD:
         addr->type = SOCKET_ADDRESS_TYPE_FD;
-        QAPI_CLONE_MEMBERS(String, &addr->u.fd, addr_legacy->u.fd.data);
+        QAPI_CLONE_MEMBERS(String, &addr->u.fd, &addr_legacy->u.fd);
         break;
     default:
         abort();
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index fafec94e02..1c4e3407a3 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -188,7 +188,12 @@  const QLitObject %(c_name)s = %(c_string)s;
                 'variants': [self._gen_variant(v) for v in variants]}
 
     def _gen_variant(self, variant):
-        obj = {'case': variant.name, 'type': self._use_type(variant.type)}
+        if variant.wrapped:
+            obj = {'case': variant.name,
+                   'type': self._use_type(variant.wrapper_type)}
+        else:
+            obj = {'case': variant.name,
+                   'type': self._use_type(variant.type)}
         return _make_tree(obj, variant.ifcond, None)
 
     def visit_builtin_type(self, name, info, json_type):
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 720449feee..17525b4216 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -216,6 +216,11 @@  class QAPISchemaBuiltinType(QAPISchemaType):
         self._json_type_name = json_type
         self._c_type_name = c_type
 
+    def check(self, schema):
+        # Don't check twice, it would fail an assertion
+        if not self._checked:
+            super().check(schema)
+
     def c_name(self):
         return self.name
 
@@ -593,18 +598,21 @@  class QAPISchemaVariants:
                         "branch '%s' is not a value of %s"
                         % (v.name, self.tag_member.type.describe()))
                 if (not isinstance(v.type, QAPISchemaObjectType)
-                        or v.type.variants):
+                        or v.type.variants) and v.flat:
                     raise QAPISemError(
                         self.info,
                         "%s cannot use %s"
                         % (v.describe(self.info), v.type.describe()))
-                v.type.check(schema)
+                if isinstance(v.type, QAPISchemaObjectType):
+                    v.type.check(schema)
 
     def check_clash(self, info, seen):
         for v in self.variants:
             # Reset seen map for each variant, since qapi names from one
-            # branch do not affect another branch
-            v.type.check_clash(info, dict(seen))
+            # branch do not affect another branch.  Variants that are
+            # never flat don't even conflict with the base.
+            if isinstance(v.type, QAPISchemaObjectType):
+                v.type.check_clash(info, dict(seen) if v.flat else {})
 
 
 class QAPISchemaMember:
@@ -705,9 +713,22 @@  class QAPISchemaObjectTypeMember(QAPISchemaMember):
 class QAPISchemaVariant(QAPISchemaObjectTypeMember):
     role = 'branch'
 
-    def __init__(self, name, info, typ, ifcond=None):
+    def __init__(self, name, info, typ, ifcond=None, flat=True,
+                 wrapper_type=None):
         super().__init__(name, info, typ, False, ifcond)
 
+        self.flat = flat
+        self.wrapped = bool(wrapper_type)
+        self.wrapper_type = wrapper_type
+
+        # For now, unions are either flat or wrapped, never both
+        assert self.flat or self.wrapped
+        assert not (self.flat and self.wrapped)
+
+    def check(self, schema):
+        super().check(schema)
+        if self.wrapped:
+            self.wrapper_type.check(schema)
 
 class QAPISchemaCommand(QAPISchemaEntity):
     meta = 'command'
@@ -1017,14 +1038,19 @@  class QAPISchema:
     def _make_variant(self, case, typ, ifcond, info):
         return QAPISchemaVariant(case, info, typ, ifcond)
 
-    def _make_simple_variant(self, case, typ, ifcond, info):
+    def _make_simple_variant(self, union_name, case, typ, ifcond, info):
         if isinstance(typ, list):
             assert len(typ) == 1
             typ = self._make_array_type(typ[0], info)
-        typ = self._make_implicit_object_type(
-            typ, info, self.lookup_type(typ),
-            'wrapper', [self._make_member('data', typ, None, None, info)])
-        return QAPISchemaVariant(case, info, typ, ifcond)
+
+        # The wrapper type is only used for introspection compatibility.
+        # Don't add it to the entity list of the schema.
+        wrapper_name = 'q_obj_%s-%s-wrapper' % (union_name, case)
+        wrapper_member = self._make_member('data', typ, None, None, info)
+        wrapper_type = QAPISchemaObjectType(wrapper_name, info, None, ifcond,
+                                            None, None, [wrapper_member], None)
+        return QAPISchemaVariant(case, info, typ, ifcond, flat=False,
+                                 wrapper_type=wrapper_type)
 
     def _def_union_type(self, expr, info, doc):
         name = expr['union']
@@ -1044,7 +1070,7 @@  class QAPISchema:
                         for (key, value) in data.items()]
             members = []
         else:
-            variants = [self._make_simple_variant(key, value['type'],
+            variants = [self._make_simple_variant(name, key, value['type'],
                                                   value.get('if'), info)
                         for (key, value) in data.items()]
             enum = [{'name': v.name, 'if': v.ifcond} for v in variants]
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 339f152152..f72567cbcc 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -118,6 +118,34 @@  bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
         break;
 ''',
                              case=case_str)
+            elif not isinstance(var.type, QAPISchemaObjectType):
+                assert not var.flat
+                ret += mcgen('''
+    case %(case)s:
+        return visit_type_%(c_type)s(v, "data", &obj->u.%(c_name)s, errp);
+''',
+                             case=case_str,
+                             c_type=var.type.c_name(), c_name=c_name(var.name))
+            elif var.wrapped:
+                ret += mcgen('''
+    case %(case)s:
+    {
+        bool ok;
+
+        if (!visit_start_struct(v, "data", NULL, 0, errp)) {
+            return false;
+        }
+        ok = visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, errp);
+        if (ok) {
+            ok = visit_check_struct(v, errp);
+        }
+        visit_end_struct(v, NULL);
+        return ok;
+    }
+''',
+                             case=case_str,
+                             c_type=var.type.c_name(), c_name=c_name(var.name))
+
             else:
                 ret += mcgen('''
     case %(case)s:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 419284dae2..bcbcbd2fce 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -31,10 +31,6 @@  object Object
     case two: Variant2
         if ['IFTWO']
     feature union-feat1
-object q_obj_Variant1-wrapper
-    member data: Variant1 optional=False
-object q_obj_Variant2-wrapper
-    member data: Variant2 optional=False
 enum SugaredUnionKind
     member one
     member two
@@ -42,8 +38,8 @@  enum SugaredUnionKind
 object SugaredUnion
     member type: SugaredUnionKind optional=False
     tag type
-    case one: q_obj_Variant1-wrapper
-    case two: q_obj_Variant2-wrapper
+    case one: Variant1
+    case two: Variant2
         if ['IFTWO']
     feature union-feat2
 alternate Alternate
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 8868ca0dca..a4e4051c61 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -125,36 +125,6 @@  alternate AltStrObj
     tag type
     case s: str
     case o: TestStruct
-object q_obj_intList-wrapper
-    member data: intList optional=False
-object q_obj_int8List-wrapper
-    member data: int8List optional=False
-object q_obj_int16List-wrapper
-    member data: int16List optional=False
-object q_obj_int32List-wrapper
-    member data: int32List optional=False
-object q_obj_int64List-wrapper
-    member data: int64List optional=False
-object q_obj_uint8List-wrapper
-    member data: uint8List optional=False
-object q_obj_uint16List-wrapper
-    member data: uint16List optional=False
-object q_obj_uint32List-wrapper
-    member data: uint32List optional=False
-object q_obj_uint64List-wrapper
-    member data: uint64List optional=False
-object q_obj_numberList-wrapper
-    member data: numberList optional=False
-object q_obj_boolList-wrapper
-    member data: boolList optional=False
-object q_obj_strList-wrapper
-    member data: strList optional=False
-object q_obj_sizeList-wrapper
-    member data: sizeList optional=False
-object q_obj_anyList-wrapper
-    member data: anyList optional=False
-object q_obj_StatusList-wrapper
-    member data: StatusList optional=False
 enum UserDefListUnionKind
     member integer
     member s8
@@ -174,21 +144,21 @@  enum UserDefListUnionKind
 object UserDefListUnion
     member type: UserDefListUnionKind optional=False
     tag type
-    case integer: q_obj_intList-wrapper
-    case s8: q_obj_int8List-wrapper
-    case s16: q_obj_int16List-wrapper
-    case s32: q_obj_int32List-wrapper
-    case s64: q_obj_int64List-wrapper
-    case u8: q_obj_uint8List-wrapper
-    case u16: q_obj_uint16List-wrapper
-    case u32: q_obj_uint32List-wrapper
-    case u64: q_obj_uint64List-wrapper
-    case number: q_obj_numberList-wrapper
-    case boolean: q_obj_boolList-wrapper
-    case string: q_obj_strList-wrapper
-    case sizes: q_obj_sizeList-wrapper
-    case any: q_obj_anyList-wrapper
-    case user: q_obj_StatusList-wrapper
+    case integer: intList
+    case s8: int8List
+    case s16: int16List
+    case s32: int32List
+    case s64: int64List
+    case u8: uint8List
+    case u16: uint16List
+    case u32: uint32List
+    case u64: uint64List
+    case number: numberList
+    case boolean: boolList
+    case string: strList
+    case sizes: sizeList
+    case any: anyList
+    case user: StatusList
 include include/sub-module.json
 command user_def_cmd None -> None
     gen=True success_response=True boxed=False oob=False preconfig=False
@@ -263,14 +233,12 @@  object __org.qemu_x-Struct
     base __org.qemu_x-Base
     member __org.qemu_x-member2: str optional=False
     member wchar-t: int optional=True
-object q_obj_str-wrapper
-    member data: str optional=False
 enum __org.qemu_x-Union1Kind
     member __org.qemu_x-branch
 object __org.qemu_x-Union1
     member type: __org.qemu_x-Union1Kind optional=False
     tag type
-    case __org.qemu_x-branch: q_obj_str-wrapper
+    case __org.qemu_x-branch: str
 alternate __org.qemu_x-Alt1
     tag type
     case __org.qemu_x-branch: str
@@ -305,8 +273,6 @@  enum TestIfEnum
     member bar
         if ['defined(TEST_IF_ENUM_BAR)']
     if ['defined(TEST_IF_ENUM)']
-object q_obj_TestStruct-wrapper
-    member data: TestStruct optional=False
 enum TestIfUnionKind
     member foo
     member union_bar
@@ -315,8 +281,8 @@  enum TestIfUnionKind
 object TestIfUnion
     member type: TestIfUnionKind optional=False
     tag type
-    case foo: q_obj_TestStruct-wrapper
-    case union_bar: q_obj_str-wrapper
+    case foo: TestStruct
+    case union_bar: str
         if ['defined(TEST_IF_UNION_BAR)']
     if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
 object q_obj_TestIfUnionCmd-arg