All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link
@ 2018-01-20 15:44 Max Reitz
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to() Max Reitz
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

Currently, we try to rewrite every occurrence of "backing": null into
"backing": "" in qmp_blockdev_add().  However, that breaks using the
same "backing": null construction in json:{} file names (which do not go
through qmp_blockdev_add()).  Currently, these then just behave as if
the option has not been specified.

Since there is actually only one place where we evaluate the @backing
option to find out whether not to use a backing file, we can instead
just check for null there.  It doesn't matter that this changes the
runtime state of the option from "" to null, because nobody really does
anything with that runtime state anyway (except put it into qemu again,
but qemu doesn't care whether it's "" or null).

And in the future, it's much better if we get it to be null in that
runtime state sooner than later -- see patch 6.


v2: Add qobject_to() macro instead of qdict_is_null() (and then we can
    do qobject_to(qdict_get(...), QNull) != NULL instead) [Markus]
    - I'm not sure what I came up with is what Markus intended me to,
      and if it is not, I'm inclined to go back to qdict_is_null() (or
      qdict_entry_is_null(), as Berto has proposed);
      or, alternatively, add a qobject_to_qnull() function and drop
      patches 2 through 4.


git-backport-diff against v1:

Key:
[----] : patches are identical
[####] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/6:[down] 'qapi: Add qobject_to()'
002/6:[down] 'qapi: Replace qobject_to_X(o) by qobject_to(o, X)'
003/6:[down] 'qapi: Remove qobject_to_X() functions'
004/6:[down] 'qapi: Make more of qobject_to()'
005/6:[0004] [FC] 'block: Handle null backing link'
006/6:[----] [-C] 'block: Deprecate "backing": ""'


Max Reitz (6):
  qapi: Add qobject_to()
  qapi: Replace qobject_to_X(o) by qobject_to(o, X)
  qapi: Remove qobject_to_X() functions
  qapi: Make more of qobject_to()
  block: Handle null backing link
  block: Deprecate "backing": ""

 qapi/block-core.json                |  4 +--
 include/qapi/qmp/qbool.h            |  1 -
 include/qapi/qmp/qdict.h            |  1 -
 include/qapi/qmp/qlist.h            |  1 -
 include/qapi/qmp/qnum.h             |  1 -
 include/qapi/qmp/qobject.h          | 32 ++++++++++++++++++
 include/qapi/qmp/qstring.h          |  1 -
 block.c                             | 10 ++++--
 block/qapi.c                        | 12 +++----
 block/rbd.c                         |  8 ++---
 blockdev.c                          | 21 +++---------
 hw/i386/acpi-build.c                | 14 ++++----
 monitor.c                           |  8 ++---
 qapi/qmp-dispatch.c                 |  2 +-
 qapi/qobject-input-visitor.c        | 24 +++++++-------
 qapi/qobject-output-visitor.c       |  4 +--
 qga/main.c                          |  2 +-
 qmp.c                               |  2 +-
 qobject/json-parser.c               | 13 ++++----
 qobject/qbool.c                     | 15 ++-------
 qobject/qdict.c                     | 65 ++++++++++++++++---------------------
 qobject/qjson.c                     | 10 +++---
 qobject/qlist.c                     | 17 ++--------
 qobject/qlit.c                      | 10 +++---
 qobject/qnum.c                      | 17 ++--------
 qobject/qstring.c                   | 17 ++--------
 qom/object.c                        |  8 ++---
 target/i386/cpu.c                   |  2 +-
 target/s390x/cpu_models.c           |  2 +-
 tests/check-qdict.c                 | 20 ++++++------
 tests/check-qjson.c                 | 41 +++++++++++------------
 tests/check-qlist.c                 |  4 +--
 tests/check-qlit.c                  |  2 +-
 tests/check-qnum.c                  |  4 +--
 tests/check-qobject.c               |  2 +-
 tests/check-qstring.c               |  2 +-
 tests/device-introspect-test.c      | 14 ++++----
 tests/libqtest.c                    |  6 ++--
 tests/numa-test.c                   |  8 ++---
 tests/qom-test.c                    |  4 +--
 tests/test-char.c                   |  2 +-
 tests/test-keyval.c                 |  8 ++---
 tests/test-qga.c                    | 19 ++++++-----
 tests/test-qmp-commands.c           | 12 +++----
 tests/test-qmp-event.c              | 16 ++++-----
 tests/test-qobject-input-visitor.c  | 10 +++---
 tests/test-qobject-output-visitor.c | 54 +++++++++++++++---------------
 tests/test-x86-cpuid-compat.c       | 17 +++++-----
 util/keyval.c                       |  4 +--
 util/qemu-config.c                  |  2 +-
 util/qemu-option.c                  |  6 ++--
 qemu-doc.texi                       |  7 ++++
 qemu-options.hx                     |  4 +--
 tests/qemu-iotests/089              | 20 ++++++++++++
 tests/qemu-iotests/089.out          |  8 +++++
 55 files changed, 313 insertions(+), 307 deletions(-)

-- 
2.14.3

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to()
  2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
@ 2018-01-20 15:44 ` Max Reitz
  2018-01-22 15:33   ` Eric Blake
  2018-01-31 16:02   ` Alberto Garcia
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X) Max Reitz
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

This is a dynamic casting macro that, given a QObject type, returns an
object as that type or NULL if the object is of a different type (or
NULL itself).

The macro uses lower-case letters because:
1. There does not seem to be a hard rule on whether qemu macros have to
   be upper-cased,
2. The current situation in qapi/qmp is inconsistent (compare e.g.
   QINCREF() vs. qdict_put()),
3. qobject_to() will evaluate its @obj parameter only once, thus it is
   generally not important to the caller whether it is a macro or not,
4. I prefer it aesthetically.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
You're more than welcome to convince me to call it QOBJECT_TO()!
---
 include/qapi/qmp/qobject.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index 38ac68845c..1211989ca0 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -50,6 +50,24 @@ struct QObject {
 #define QDECREF(obj)              \
     qobject_decref(obj ? QOBJECT(obj) : NULL)
 
+/* Required for qobject_to() */
+#define QTYPE_CAST_TO_QNull     QTYPE_QNULL
+#define QTYPE_CAST_TO_QNum      QTYPE_QNUM
+#define QTYPE_CAST_TO_QString   QTYPE_QSTRING
+#define QTYPE_CAST_TO_QDict     QTYPE_QDICT
+#define QTYPE_CAST_TO_QList     QTYPE_QLIST
+#define QTYPE_CAST_TO_QBool     QTYPE_QBOOL
+
+#ifdef CONFIG_STATIC_ASSERT
+_Static_assert(QTYPE__MAX == 7,
+               "The QTYPE_CAST_TO_* list needs to be extended");
+#endif
+
+#define qobject_to(obj, type) \
+    container_of(qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)) ?: \
+                     QOBJECT((type *)NULL), \
+                 type, base)
+
 /* Initialize an object to default values */
 static inline void qobject_init(QObject *obj, QType type)
 {
@@ -102,4 +120,18 @@ static inline QType qobject_type(const QObject *obj)
     return obj->type;
 }
 
+/**
+ * qobject_check_type(): Helper function for the qobject_to() macro.
+ * Return @obj, but only if @obj is not NULL and @type is equal to
+ * @obj's type.  Return NULL otherwise.
+ */
+static inline QObject *qobject_check_type(const QObject *obj, QType type)
+{
+    if (obj && qobject_type(obj) == type) {
+        return (QObject *)obj;
+    } else {
+        return NULL;
+    }
+}
+
 #endif /* QOBJECT_H */
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X)
  2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to() Max Reitz
@ 2018-01-20 15:44 ` Max Reitz
  2018-01-31 16:05   ` Alberto Garcia
  2018-01-31 16:11   ` Eric Blake
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 3/6] qapi: Remove qobject_to_X() functions Max Reitz
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

This patch was generated using the following Coccinelle script:

@@
expression Obj;
@@
(
- qobject_to_qnum(Obj)
+ qobject_to(Obj, QNum)
|
- qobject_to_qstring(Obj)
+ qobject_to(Obj, QString)
|
- qobject_to_qdict(Obj)
+ qobject_to(Obj, QDict)
|
- qobject_to_qlist(Obj)
+ qobject_to(Obj, QList)
|
- qobject_to_qbool(Obj)
+ qobject_to(Obj, QBool)
)

and a bit of manual fix-up for overly long lines and three places in
tests/check-qjson.c that Coccinelle did not find.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                             |  2 +-
 block/qapi.c                        | 12 ++++-----
 block/rbd.c                         |  8 +++---
 blockdev.c                          |  7 ++---
 hw/i386/acpi-build.c                | 14 +++++-----
 monitor.c                           |  8 +++---
 qapi/qmp-dispatch.c                 |  2 +-
 qapi/qobject-input-visitor.c        | 20 +++++++-------
 qapi/qobject-output-visitor.c       |  4 +--
 qga/main.c                          |  2 +-
 qmp.c                               |  2 +-
 qobject/json-parser.c               |  2 +-
 qobject/qbool.c                     |  4 +--
 qobject/qdict.c                     | 38 +++++++++++++-------------
 qobject/qjson.c                     | 10 +++----
 qobject/qlist.c                     |  6 ++---
 qobject/qlit.c                      | 10 +++----
 qobject/qnum.c                      |  6 ++---
 qobject/qstring.c                   |  6 ++---
 qom/object.c                        |  8 +++---
 target/i386/cpu.c                   |  2 +-
 target/s390x/cpu_models.c           |  2 +-
 tests/check-qdict.c                 | 20 +++++++-------
 tests/check-qjson.c                 | 41 ++++++++++++++--------------
 tests/check-qlist.c                 |  4 +--
 tests/check-qlit.c                  |  2 +-
 tests/check-qnum.c                  |  4 +--
 tests/check-qobject.c               |  2 +-
 tests/check-qstring.c               |  2 +-
 tests/device-introspect-test.c      | 14 +++++-----
 tests/libqtest.c                    |  6 ++---
 tests/numa-test.c                   |  8 +++---
 tests/qom-test.c                    |  4 +--
 tests/test-char.c                   |  2 +-
 tests/test-keyval.c                 |  8 +++---
 tests/test-qga.c                    | 19 ++++++-------
 tests/test-qmp-commands.c           | 12 ++++-----
 tests/test-qmp-event.c              | 16 +++++------
 tests/test-qobject-input-visitor.c  | 10 +++----
 tests/test-qobject-output-visitor.c | 54 ++++++++++++++++++-------------------
 tests/test-x86-cpuid-compat.c       | 17 ++++++------
 util/keyval.c                       |  4 +--
 util/qemu-config.c                  |  2 +-
 util/qemu-option.c                  |  6 ++---
 44 files changed, 218 insertions(+), 214 deletions(-)

diff --git a/block.c b/block.c
index a8da4f2b25..909cf076b7 100644
--- a/block.c
+++ b/block.c
@@ -1454,7 +1454,7 @@ static QDict *parse_json_filename(const char *filename, Error **errp)
         return NULL;
     }
 
-    options = qobject_to_qdict(options_obj);
+    options = qobject_to(options_obj, QDict);
     if (!options) {
         qobject_decref(options_obj);
         error_setg(errp, "Invalid JSON object given");
diff --git a/block/qapi.c b/block/qapi.c
index fc10f0a565..3d0e11ccb3 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -642,29 +642,29 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
 {
     switch (qobject_type(obj)) {
         case QTYPE_QNUM: {
-            QNum *value = qobject_to_qnum(obj);
+            QNum *value = qobject_to(obj, QNum);
             char *tmp = qnum_to_string(value);
             func_fprintf(f, "%s", tmp);
             g_free(tmp);
             break;
         }
         case QTYPE_QSTRING: {
-            QString *value = qobject_to_qstring(obj);
+            QString *value = qobject_to(obj, QString);
             func_fprintf(f, "%s", qstring_get_str(value));
             break;
         }
         case QTYPE_QDICT: {
-            QDict *value = qobject_to_qdict(obj);
+            QDict *value = qobject_to(obj, QDict);
             dump_qdict(func_fprintf, f, comp_indent, value);
             break;
         }
         case QTYPE_QLIST: {
-            QList *value = qobject_to_qlist(obj);
+            QList *value = qobject_to(obj, QList);
             dump_qlist(func_fprintf, f, comp_indent, value);
             break;
         }
         case QTYPE_QBOOL: {
-            QBool *value = qobject_to_qbool(obj);
+            QBool *value = qobject_to(obj, QBool);
             func_fprintf(f, "%s", qbool_get_bool(value) ? "true" : "false");
             break;
         }
@@ -725,7 +725,7 @@ void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
 
     visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
     visit_complete(v, &obj);
-    data = qdict_get(qobject_to_qdict(obj), "data");
+    data = qdict_get(qobject_to(obj, QDict), "data");
     dump_qobject(func_fprintf, f, 1, data);
     qobject_decref(obj);
     visit_free(v);
diff --git a/block/rbd.c b/block/rbd.c
index a76a5e8755..5f1e4d2d9b 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -253,14 +253,14 @@ static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs_json,
     if (!keypairs_json) {
         return ret;
     }
-    keypairs = qobject_to_qlist(qobject_from_json(keypairs_json,
-                                                  &error_abort));
+    keypairs = qobject_to(qobject_from_json(keypairs_json, &error_abort),
+                          QList);
     remaining = qlist_size(keypairs) / 2;
     assert(remaining);
 
     while (remaining--) {
-        name = qobject_to_qstring(qlist_pop(keypairs));
-        value = qobject_to_qstring(qlist_pop(keypairs));
+        name = qobject_to(qlist_pop(keypairs), QString);
+        value = qobject_to(qlist_pop(keypairs), QString);
         assert(name && value);
         key = qstring_get_str(name);
 
diff --git a/blockdev.c b/blockdev.c
index 8e977eef11..2dce231c98 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -329,7 +329,8 @@ static bool parse_stats_intervals(BlockAcctStats *stats, QList *intervals,
 
         case QTYPE_QSTRING: {
             unsigned long long length;
-            const char *str = qstring_get_str(qobject_to_qstring(entry->value));
+            const char *str =
+                qstring_get_str(qobject_to(entry->value, QString));
             if (parse_uint_full(str, &length, 10) == 0 &&
                 length > 0 && length <= UINT_MAX) {
                 block_acct_add_interval(stats, (unsigned) length);
@@ -341,7 +342,7 @@ static bool parse_stats_intervals(BlockAcctStats *stats, QList *intervals,
         }
 
         case QTYPE_QNUM: {
-            int64_t length = qnum_get_int(qobject_to_qnum(entry->value));
+            int64_t length = qnum_get_int(qobject_to(entry->value, QNum));
 
             if (length > 0 && length <= UINT_MAX) {
                 block_acct_add_interval(stats, (unsigned) length);
@@ -3978,7 +3979,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
     }
 
     visit_complete(v, &obj);
-    qdict = qobject_to_qdict(obj);
+    qdict = qobject_to(obj, QDict);
 
     qdict_flatten(qdict);
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index dc4b2b9ffe..d30bb5d36b 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -153,21 +153,21 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
     /* Fill in optional s3/s4 related properties */
     o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
     if (o) {
-        pm->s3_disabled = qnum_get_uint(qobject_to_qnum(o));
+        pm->s3_disabled = qnum_get_uint(qobject_to(o, QNum));
     } else {
         pm->s3_disabled = false;
     }
     qobject_decref(o);
     o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_DISABLED, NULL);
     if (o) {
-        pm->s4_disabled = qnum_get_uint(qobject_to_qnum(o));
+        pm->s4_disabled = qnum_get_uint(qobject_to(o, QNum));
     } else {
         pm->s4_disabled = false;
     }
     qobject_decref(o);
     o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_VAL, NULL);
     if (o) {
-        pm->s4_val = qnum_get_uint(qobject_to_qnum(o));
+        pm->s4_val = qnum_get_uint(qobject_to(o, QNum));
     } else {
         pm->s4_val = false;
     }
@@ -513,7 +513,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
 
     bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
     if (bsel) {
-        uint64_t bsel_val = qnum_get_uint(qobject_to_qnum(bsel));
+        uint64_t bsel_val = qnum_get_uint(qobject_to(bsel, QNum));
 
         aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
         notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
@@ -623,7 +623,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
 
     /* If bus supports hotplug select it and notify about local events */
     if (bsel) {
-        uint64_t bsel_val = qnum_get_uint(qobject_to_qnum(bsel));
+        uint64_t bsel_val = qnum_get_uint(qobject_to(bsel, QNum));
 
         aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
         aml_append(method,
@@ -2619,12 +2619,12 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
     if (!o) {
         return false;
     }
-    mcfg->mcfg_base = qnum_get_uint(qobject_to_qnum(o));
+    mcfg->mcfg_base = qnum_get_uint(qobject_to(o, QNum));
     qobject_decref(o);
 
     o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
     assert(o);
-    mcfg->mcfg_size = qnum_get_uint(qobject_to_qnum(o));
+    mcfg->mcfg_size = qnum_get_uint(qobject_to(o, QNum));
     qobject_decref(o);
     return true;
 }
diff --git a/monitor.c b/monitor.c
index b9da5e20d1..66a1c0cb79 100644
--- a/monitor.c
+++ b/monitor.c
@@ -444,7 +444,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
         /* Unthrottled event */
         monitor_qapi_event_emit(event, qdict);
     } else {
-        QDict *data = qobject_to_qdict(qdict_get(qdict, "data"));
+        QDict *data = qobject_to(qdict_get(qdict, "data"), QDict);
         MonitorQAPIEventState key = { .event = event, .data = data };
 
         evstate = g_hash_table_lookup(monitor_qapi_event_state, &key);
@@ -3823,7 +3823,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
         goto err_out;
     }
 
-    qdict = qobject_to_qdict(req);
+    qdict = qobject_to(req, QDict);
     if (qdict) {
         id = qdict_get(qdict, "id");
         qobject_incref(id);
@@ -3839,7 +3839,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
     rsp = qmp_dispatch(cur_mon->qmp.commands, req);
 
     if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
-        qdict = qdict_get_qdict(qobject_to_qdict(rsp), "error");
+        qdict = qdict_get_qdict(qobject_to(rsp, QDict), "error");
         if (qdict
             && !g_strcmp0(qdict_get_try_str(qdict, "class"),
                     QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) {
@@ -3860,7 +3860,7 @@ err_out:
 
     if (rsp) {
         if (id) {
-            qdict_put_obj(qobject_to_qdict(rsp), "id", id);
+            qdict_put_obj(qobject_to(rsp, QDict), "id", id);
             id = NULL;
         }
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index b41fa174fe..8c53cabe62 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -28,7 +28,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
     bool has_exec_key = false;
     QDict *dict = NULL;
 
-    dict = qobject_to_qdict(request);
+    dict = qobject_to(request, QDict);
     if (!dict) {
         error_setg(errp, "QMP input must be a JSON object");
         return NULL;
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index ee9e47d911..45e6160b21 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -132,7 +132,7 @@ static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv,
 
     if (qobject_type(qobj) == QTYPE_QDICT) {
         assert(name);
-        ret = qdict_get(qobject_to_qdict(qobj), name);
+        ret = qdict_get(qobject_to(qobj, QDict), name);
         if (tos->h && consume && ret) {
             bool removed = g_hash_table_remove(tos->h, name);
             assert(removed);
@@ -180,7 +180,7 @@ static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv,
         return NULL;
     }
 
-    qstr = qobject_to_qstring(qobj);
+    qstr = qobject_to(qobj, QString);
     if (!qstr) {
         switch (qobject_type(qobj)) {
         case QTYPE_QDICT:
@@ -219,11 +219,11 @@ static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
 
     if (qobject_type(obj) == QTYPE_QDICT) {
         h = g_hash_table_new(g_str_hash, g_str_equal);
-        qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
+        qdict_iter(qobject_to(obj, QDict), qdict_add_key, h);
         tos->h = h;
     } else {
         assert(qobject_type(obj) == QTYPE_QLIST);
-        tos->entry = qlist_first(qobject_to_qlist(obj));
+        tos->entry = qlist_first(qobject_to(obj, QList));
         tos->index = -1;
     }
 
@@ -390,7 +390,7 @@ static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
     if (!qobj) {
         return;
     }
-    qnum = qobject_to_qnum(qobj);
+    qnum = qobject_to(qobj, QNum);
     if (!qnum || !qnum_get_try_int(qnum, obj)) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                    full_name(qiv, name), "integer");
@@ -425,7 +425,7 @@ static void qobject_input_type_uint64(Visitor *v, const char *name,
     if (!qobj) {
         return;
     }
-    qnum = qobject_to_qnum(qobj);
+    qnum = qobject_to(qobj, QNum);
     if (!qnum) {
         goto err;
     }
@@ -472,7 +472,7 @@ static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
     if (!qobj) {
         return;
     }
-    qbool = qobject_to_qbool(qobj);
+    qbool = qobject_to(qobj, QBool);
     if (!qbool) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                    full_name(qiv, name), "boolean");
@@ -513,7 +513,7 @@ static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
     if (!qobj) {
         return;
     }
-    qstr = qobject_to_qstring(qobj);
+    qstr = qobject_to(qobj, QString);
     if (!qstr) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                    full_name(qiv, name), "string");
@@ -542,7 +542,7 @@ static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
     if (!qobj) {
         return;
     }
-    qnum = qobject_to_qnum(qobj);
+    qnum = qobject_to(qobj, QNum);
     if (!qnum) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                    full_name(qiv, name), "number");
@@ -729,7 +729,7 @@ Visitor *qobject_input_visitor_new_str(const char *str,
             }
             return NULL;
         }
-        args = qobject_to_qdict(obj);
+        args = qobject_to(obj, QDict);
         assert(args);
         v = qobject_input_visitor_new(QOBJECT(args));
     } else {
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
index d325163e55..ff044d3c4b 100644
--- a/qapi/qobject-output-visitor.c
+++ b/qapi/qobject-output-visitor.c
@@ -87,11 +87,11 @@ static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
         switch (qobject_type(cur)) {
         case QTYPE_QDICT:
             assert(name);
-            qdict_put_obj(qobject_to_qdict(cur), name, value);
+            qdict_put_obj(qobject_to(cur, QDict), name, value);
             break;
         case QTYPE_QLIST:
             assert(!name);
-            qlist_append_obj(qobject_to_qlist(cur), value);
+            qlist_append_obj(qobject_to(cur, QList), value);
             break;
         default:
             g_assert_not_reached();
diff --git a/qga/main.c b/qga/main.c
index 62a62755bd..7ecce12ea7 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -603,7 +603,7 @@ static void process_event(JSONMessageParser *parser, GQueue *tokens)
     g_assert(s && parser);
 
     g_debug("process_event: called");
-    qdict = qobject_to_qdict(json_parser_parse_err(tokens, NULL, &err));
+    qdict = qobject_to(json_parser_parse_err(tokens, NULL, &err), QDict);
     if (err || !qdict) {
         QDECREF(qdict);
         qdict = qdict_new();
diff --git a/qmp.c b/qmp.c
index 52cfd2d81c..c77f9ceb3c 100644
--- a/qmp.c
+++ b/qmp.c
@@ -652,7 +652,7 @@ void qmp_object_add(const char *type, const char *id,
     Object *obj;
 
     if (props) {
-        pdict = qobject_to_qdict(props);
+        pdict = qobject_to(props, QDict);
         if (!pdict) {
             error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
             return;
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index 724ca240e4..885039e94b 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -303,7 +303,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
         goto out;
     }
 
-    qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value);
+    qdict_put_obj(dict, qstring_get_str(qobject_to(key, QString)), value);
 
     qobject_decref(key);
 
diff --git a/qobject/qbool.c b/qobject/qbool.c
index ac825fc5a2..683d2b9b3f 100644
--- a/qobject/qbool.c
+++ b/qobject/qbool.c
@@ -56,7 +56,7 @@ QBool *qobject_to_qbool(const QObject *obj)
  */
 bool qbool_is_equal(const QObject *x, const QObject *y)
 {
-    return qobject_to_qbool(x)->value == qobject_to_qbool(y)->value;
+    return qobject_to(x, QBool)->value == qobject_to(y, QBool)->value;
 }
 
 /**
@@ -66,5 +66,5 @@ bool qbool_is_equal(const QObject *x, const QObject *y)
 void qbool_destroy_obj(QObject *obj)
 {
     assert(obj != NULL);
-    g_free(qobject_to_qbool(obj));
+    g_free(qobject_to(obj, QBool));
 }
diff --git a/qobject/qdict.c b/qobject/qdict.c
index e8f15f1132..472d989a67 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -185,7 +185,7 @@ size_t qdict_size(const QDict *qdict)
  */
 double qdict_get_double(const QDict *qdict, const char *key)
 {
-    return qnum_get_double(qobject_to_qnum(qdict_get(qdict, key)));
+    return qnum_get_double(qobject_to(qdict_get(qdict, key), QNum));
 }
 
 /**
@@ -198,7 +198,7 @@ double qdict_get_double(const QDict *qdict, const char *key)
  */
 int64_t qdict_get_int(const QDict *qdict, const char *key)
 {
-    return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)));
+    return qnum_get_int(qobject_to(qdict_get(qdict, key), QNum));
 }
 
 /**
@@ -211,7 +211,7 @@ int64_t qdict_get_int(const QDict *qdict, const char *key)
  */
 bool qdict_get_bool(const QDict *qdict, const char *key)
 {
-    return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key)));
+    return qbool_get_bool(qobject_to(qdict_get(qdict, key), QBool));
 }
 
 /**
@@ -219,7 +219,7 @@ bool qdict_get_bool(const QDict *qdict, const char *key)
  */
 QList *qdict_get_qlist(const QDict *qdict, const char *key)
 {
-    return qobject_to_qlist(qdict_get(qdict, key));
+    return qobject_to(qdict_get(qdict, key), QList);
 }
 
 /**
@@ -227,7 +227,7 @@ QList *qdict_get_qlist(const QDict *qdict, const char *key)
  */
 QDict *qdict_get_qdict(const QDict *qdict, const char *key)
 {
-    return qobject_to_qdict(qdict_get(qdict, key));
+    return qobject_to(qdict_get(qdict, key), QDict);
 }
 
 /**
@@ -241,7 +241,7 @@ QDict *qdict_get_qdict(const QDict *qdict, const char *key)
  */
 const char *qdict_get_str(const QDict *qdict, const char *key)
 {
-    return qstring_get_str(qobject_to_qstring(qdict_get(qdict, key)));
+    return qstring_get_str(qobject_to(qdict_get(qdict, key), QString));
 }
 
 /**
@@ -254,7 +254,7 @@ const char *qdict_get_str(const QDict *qdict, const char *key)
 int64_t qdict_get_try_int(const QDict *qdict, const char *key,
                           int64_t def_value)
 {
-    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
+    QNum *qnum = qobject_to(qdict_get(qdict, key), QNum);
     int64_t val;
 
     if (!qnum || !qnum_get_try_int(qnum, &val)) {
@@ -273,7 +273,7 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key,
  */
 bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
 {
-    QBool *qbool = qobject_to_qbool(qdict_get(qdict, key));
+    QBool *qbool = qobject_to(qdict_get(qdict, key), QBool);
 
     return qbool ? qbool_get_bool(qbool) : def_value;
 }
@@ -288,7 +288,7 @@ bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
  */
 const char *qdict_get_try_str(const QDict *qdict, const char *key)
 {
-    QString *qstr = qobject_to_qstring(qdict_get(qdict, key));
+    QString *qstr = qobject_to(qdict_get(qdict, key), QString);
 
     return qstr ? qstring_get_str(qstr) : NULL;
 }
@@ -411,8 +411,8 @@ void qdict_del(QDict *qdict, const char *key)
  */
 bool qdict_is_equal(const QObject *x, const QObject *y)
 {
-    const QDict *dict_x = qobject_to_qdict(x);
-    const QDict *dict_y = qobject_to_qdict(y);
+    const QDict *dict_x = qobject_to(x, QDict);
+    const QDict *dict_y = qobject_to(y, QDict);
     const QDictEntry *e;
 
     if (qdict_size(dict_x) != qdict_size(dict_y)) {
@@ -440,7 +440,7 @@ void qdict_destroy_obj(QObject *obj)
     QDict *qdict;
 
     assert(obj != NULL);
-    qdict = qobject_to_qdict(obj);
+    qdict = qobject_to(obj, QDict);
 
     for (i = 0; i < QDICT_BUCKET_MAX; i++) {
         QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
@@ -511,9 +511,9 @@ static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix)
         new_key = g_strdup_printf("%s.%i", prefix, i);
 
         if (qobject_type(value) == QTYPE_QDICT) {
-            qdict_flatten_qdict(qobject_to_qdict(value), target, new_key);
+            qdict_flatten_qdict(qobject_to(value, QDict), target, new_key);
         } else if (qobject_type(value) == QTYPE_QLIST) {
-            qdict_flatten_qlist(qobject_to_qlist(value), target, new_key);
+            qdict_flatten_qlist(qobject_to(value, QList), target, new_key);
         } else {
             /* All other types are moved to the target unchanged. */
             qobject_incref(value);
@@ -547,11 +547,11 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
         if (qobject_type(value) == QTYPE_QDICT) {
             /* Entries of QDicts are processed recursively, the QDict object
              * itself disappears. */
-            qdict_flatten_qdict(qobject_to_qdict(value), target,
+            qdict_flatten_qdict(qobject_to(value, QDict), target,
                                 new_key ? new_key : entry->key);
             delete = true;
         } else if (qobject_type(value) == QTYPE_QLIST) {
-            qdict_flatten_qlist(qobject_to_qlist(value), target,
+            qdict_flatten_qlist(qobject_to(value, QList), target,
                                 new_key ? new_key : entry->key);
             delete = true;
         } else if (prefix) {
@@ -883,7 +883,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp)
                 qdict_put_obj(two_level, prefix, child);
             }
             qobject_incref(ent->value);
-            qdict_put_obj(qobject_to_qdict(child), suffix, ent->value);
+            qdict_put_obj(qobject_to(child, QDict), suffix, ent->value);
         } else {
             if (child) {
                 error_setg(errp, "Key %s prefix is already set as a dict",
@@ -905,7 +905,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp)
          ent = qdict_next(two_level, ent)) {
 
         if (qobject_type(ent->value) == QTYPE_QDICT) {
-            child = qdict_crumple(qobject_to_qdict(ent->value), errp);
+            child = qdict_crumple(qobject_to(ent->value, QDict), errp);
             if (!child) {
                 goto error;
             }
@@ -940,7 +940,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp)
             }
 
             qobject_incref(child);
-            qlist_append_obj(qobject_to_qlist(dst), child);
+            qlist_append_obj(qobject_to(dst, QList), child);
         }
         QDECREF(multi_level);
         multi_level = NULL;
diff --git a/qobject/qjson.c b/qobject/qjson.c
index 2e0930884e..722f459910 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -133,14 +133,14 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
         qstring_append(str, "null");
         break;
     case QTYPE_QNUM: {
-        QNum *val = qobject_to_qnum(obj);
+        QNum *val = qobject_to(obj, QNum);
         char *buffer = qnum_to_string(val);
         qstring_append(str, buffer);
         g_free(buffer);
         break;
     }
     case QTYPE_QSTRING: {
-        QString *val = qobject_to_qstring(obj);
+        QString *val = qobject_to(obj, QString);
         const char *ptr;
         int cp;
         char buf[16];
@@ -197,7 +197,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
     }
     case QTYPE_QDICT: {
         ToJsonIterState s;
-        QDict *val = qobject_to_qdict(obj);
+        QDict *val = qobject_to(obj, QDict);
 
         s.count = 0;
         s.str = str;
@@ -216,7 +216,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
     }
     case QTYPE_QLIST: {
         ToJsonIterState s;
-        QList *val = qobject_to_qlist(obj);
+        QList *val = qobject_to(obj, QList);
 
         s.count = 0;
         s.str = str;
@@ -234,7 +234,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
         break;
     }
     case QTYPE_QBOOL: {
-        QBool *val = qobject_to_qbool(obj);
+        QBool *val = qobject_to(obj, QBool);
 
         if (qbool_get_bool(val)) {
             qstring_append(str, "true");
diff --git a/qobject/qlist.c b/qobject/qlist.c
index 3ef57d31d1..a8bd42e3de 100644
--- a/qobject/qlist.c
+++ b/qobject/qlist.c
@@ -150,8 +150,8 @@ QList *qobject_to_qlist(const QObject *obj)
  */
 bool qlist_is_equal(const QObject *x, const QObject *y)
 {
-    const QList *list_x = qobject_to_qlist(x);
-    const QList *list_y = qobject_to_qlist(y);
+    const QList *list_x = qobject_to(x, QList);
+    const QList *list_y = qobject_to(y, QList);
     const QListEntry *entry_x, *entry_y;
 
     entry_x = qlist_first(list_x);
@@ -180,7 +180,7 @@ void qlist_destroy_obj(QObject *obj)
     QListEntry *entry, *next_entry;
 
     assert(obj != NULL);
-    qlist = qobject_to_qlist(obj);
+    qlist = qobject_to(obj, QList);
 
     QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) {
         QTAILQ_REMOVE(&qlist->head, entry, next);
diff --git a/qobject/qlit.c b/qobject/qlit.c
index 3c4882c784..46989a1a5e 100644
--- a/qobject/qlit.c
+++ b/qobject/qlit.c
@@ -64,16 +64,16 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
 
     switch (lhs->type) {
     case QTYPE_QBOOL:
-        return lhs->value.qbool == qbool_get_bool(qobject_to_qbool(rhs));
+        return lhs->value.qbool == qbool_get_bool(qobject_to(rhs, QBool));
     case QTYPE_QNUM:
-        return lhs->value.qnum ==  qnum_get_int(qobject_to_qnum(rhs));
+        return lhs->value.qnum ==  qnum_get_int(qobject_to(rhs, QNum));
     case QTYPE_QSTRING:
         return (strcmp(lhs->value.qstr,
-                       qstring_get_str(qobject_to_qstring(rhs))) == 0);
+                       qstring_get_str(qobject_to(rhs, QString))) == 0);
     case QTYPE_QDICT:
-        return qlit_equal_qdict(lhs, qobject_to_qdict(rhs));
+        return qlit_equal_qdict(lhs, qobject_to(rhs, QDict));
     case QTYPE_QLIST:
-        return qlit_equal_qlist(lhs, qobject_to_qlist(rhs));
+        return qlit_equal_qlist(lhs, qobject_to(rhs, QList));
     case QTYPE_QNULL:
         return true;
     default:
diff --git a/qobject/qnum.c b/qobject/qnum.c
index 410686a611..18dcf27582 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -223,8 +223,8 @@ QNum *qobject_to_qnum(const QObject *obj)
  */
 bool qnum_is_equal(const QObject *x, const QObject *y)
 {
-    QNum *num_x = qobject_to_qnum(x);
-    QNum *num_y = qobject_to_qnum(y);
+    QNum *num_x = qobject_to(x, QNum);
+    QNum *num_y = qobject_to(y, QNum);
 
     switch (num_x->kind) {
     case QNUM_I64:
@@ -273,5 +273,5 @@ bool qnum_is_equal(const QObject *x, const QObject *y)
 void qnum_destroy_obj(QObject *obj)
 {
     assert(obj != NULL);
-    g_free(qobject_to_qnum(obj));
+    g_free(qobject_to(obj, QNum));
 }
diff --git a/qobject/qstring.c b/qobject/qstring.c
index 74182a1c02..ddfa8714dc 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -133,8 +133,8 @@ const char *qstring_get_str(const QString *qstring)
  */
 bool qstring_is_equal(const QObject *x, const QObject *y)
 {
-    return !strcmp(qobject_to_qstring(x)->string,
-                   qobject_to_qstring(y)->string);
+    return !strcmp(qobject_to(x, QString)->string,
+                   qobject_to(y, QString)->string);
 }
 
 /**
@@ -146,7 +146,7 @@ void qstring_destroy_obj(QObject *obj)
     QString *qs;
 
     assert(obj != NULL);
-    qs = qobject_to_qstring(obj);
+    qs = qobject_to(obj, QString);
     g_free(qs->string);
     g_free(qs);
 }
diff --git a/qom/object.c b/qom/object.c
index c58c52d518..49ba175553 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1122,7 +1122,7 @@ char *object_property_get_str(Object *obj, const char *name,
     if (!ret) {
         return NULL;
     }
-    qstring = qobject_to_qstring(ret);
+    qstring = qobject_to(ret, QString);
     if (!qstring) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
         retval = NULL;
@@ -1183,7 +1183,7 @@ bool object_property_get_bool(Object *obj, const char *name,
     if (!ret) {
         return false;
     }
-    qbool = qobject_to_qbool(ret);
+    qbool = qobject_to(ret, QBool);
     if (!qbool) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
         retval = false;
@@ -1215,7 +1215,7 @@ int64_t object_property_get_int(Object *obj, const char *name,
         return -1;
     }
 
-    qnum = qobject_to_qnum(ret);
+    qnum = qobject_to(ret, QNum);
     if (!qnum || !qnum_get_try_int(qnum, &retval)) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
         retval = -1;
@@ -1244,7 +1244,7 @@ uint64_t object_property_get_uint(Object *obj, const char *name,
     if (!ret) {
         return 0;
     }
-    qnum = qobject_to_qnum(ret);
+    qnum = qobject_to(ret, QNum);
     if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
         retval = 0;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index a49d2221ad..7f3cfe69dd 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -3100,7 +3100,7 @@ arch_query_cpu_model_expansion(CpuModelExpansionType type,
 
     xc = x86_cpu_from_model(model->name,
                             model->has_props ?
-                                qobject_to_qdict(model->props) :
+                                qobject_to(model->props, QDict) :
                                 NULL, &err);
     if (err) {
         goto out;
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 212a5f0697..cd4e5e6d7c 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -452,7 +452,7 @@ static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
     Object *obj;
 
     if (info->props) {
-        qdict = qobject_to_qdict(info->props);
+        qdict = qobject_to(info->props, QDict);
         if (!qdict) {
             error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
             return;
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index 35405778cc..f4573a46f6 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -49,7 +49,7 @@ static void qdict_put_obj_test(void)
 
     g_assert(qdict_size(qdict) == 1);
     ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
-    qn = qobject_to_qnum(ent->value);
+    qn = qobject_to(ent->value, QNum);
     g_assert_cmpint(qnum_get_int(qn), ==, num);
 
     QDECREF(qdict);
@@ -79,7 +79,7 @@ static void qdict_get_test(void)
     obj = qdict_get(tests_dict, key);
     g_assert(obj != NULL);
 
-    qn = qobject_to_qnum(obj);
+    qn = qobject_to(obj, QNum);
     g_assert_cmpint(qnum_get_int(qn), ==, value);
 
     QDECREF(tests_dict);
@@ -214,7 +214,7 @@ static void qdict_del_test(void)
 static void qobject_to_qdict_test(void)
 {
     QDict *tests_dict = qdict_new();
-    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
+    g_assert(qobject_to(QOBJECT(tests_dict), QDict) == tests_dict);
 
     QDECREF(tests_dict);
 }
@@ -379,9 +379,9 @@ static void qdict_array_split_test(void)
 
     qdict_array_split(test_dict, &test_list);
 
-    dict1 = qobject_to_qdict(qlist_pop(test_list));
-    dict2 = qobject_to_qdict(qlist_pop(test_list));
-    int1 = qobject_to_qnum(qlist_pop(test_list));
+    dict1 = qobject_to(qlist_pop(test_list), QDict);
+    dict2 = qobject_to(qlist_pop(test_list), QDict);
+    int1 = qobject_to(qlist_pop(test_list), QNum);
 
     g_assert(dict1);
     g_assert(dict2);
@@ -448,7 +448,7 @@ static void qdict_array_split_test(void)
 
     qdict_array_split(test_dict, &test_list);
 
-    int1 = qobject_to_qnum(qlist_pop(test_list));
+    int1 = qobject_to(qlist_pop(test_list), QNum);
 
     g_assert(int1);
     g_assert(qlist_empty(test_list));
@@ -605,7 +605,7 @@ static void qdict_crumple_test_recursive(void)
     qdict_put_str(src, "vnc.acl..name", "acl0");
     qdict_put_str(src, "vnc.acl.rule..name", "acl0");
 
-    dst = qobject_to_qdict(qdict_crumple(src, &error_abort));
+    dst = qobject_to(qdict_crumple(src, &error_abort), QDict);
     g_assert(dst);
     g_assert_cmpint(qdict_size(dst), ==, 1);
 
@@ -627,14 +627,14 @@ static void qdict_crumple_test_recursive(void)
     g_assert(rules);
     g_assert_cmpint(qlist_size(rules), ==, 2);
 
-    rule = qobject_to_qdict(qlist_pop(rules));
+    rule = qobject_to(qlist_pop(rules), QDict);
     g_assert(rule);
     g_assert_cmpint(qdict_size(rule), ==, 2);
     g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
     g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
     QDECREF(rule);
 
-    rule = qobject_to_qdict(qlist_pop(rules));
+    rule = qobject_to(qlist_pop(rules), QDict);
     g_assert(rule);
     g_assert_cmpint(qdict_size(rule), ==, 2);
     g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 59227934ce..ed9ad580f3 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -57,7 +57,7 @@ static void escaped_string(void)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        str = qobject_to_qstring(obj);
+        str = qobject_to(obj, QString);
         g_assert(str);
         g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
 
@@ -89,7 +89,7 @@ static void simple_string(void)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        str = qobject_to_qstring(obj);
+        str = qobject_to(obj, QString);
         g_assert(str);
         g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
@@ -120,7 +120,7 @@ static void single_quote_string(void)
         QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        str = qobject_to_qstring(obj);
+        str = qobject_to(obj, QString);
         g_assert(str);
         g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
@@ -814,7 +814,7 @@ static void utf8_string(void)
 
         obj = qobject_from_json(json_in, utf8_out ? &error_abort : NULL);
         if (utf8_out) {
-            str = qobject_to_qstring(obj);
+            str = qobject_to(obj, QString);
             g_assert(str);
             g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
         } else {
@@ -840,7 +840,7 @@ static void utf8_string(void)
          */
         if (0 && json_out != json_in) {
             obj = qobject_from_json(json_out, &error_abort);
-            str = qobject_to_qstring(obj);
+            str = qobject_to(obj, QString);
             g_assert(str);
             g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
         }
@@ -861,8 +861,8 @@ static void vararg_string(void)
     for (i = 0; test_cases[i].decoded; i++) {
         QString *str;
 
-        str = qobject_to_qstring(qobject_from_jsonf("%s",
-                                                    test_cases[i].decoded));
+        str = qobject_to(qobject_from_jsonf("%s", test_cases[i].decoded),
+                         QString);
         g_assert(str);
         g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
@@ -890,8 +890,9 @@ static void simple_number(void)
         QNum *qnum;
         int64_t val;
 
-        qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
-                                                 &error_abort));
+        qnum = qobject_to(qobject_from_json(test_cases[i].encoded,
+                                            &error_abort),
+                          QNum);
         g_assert(qnum);
         g_assert(qnum_get_try_int(qnum, &val));
         g_assert_cmpint(val, ==, test_cases[i].decoded);
@@ -917,7 +918,7 @@ static void large_number(void)
     uint64_t val;
     int64_t ival;
 
-    qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
+    qnum = qobject_to(qobject_from_json(maxu64, &error_abort), QNum);
     g_assert(qnum);
     g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
     g_assert(!qnum_get_try_int(qnum, &ival));
@@ -927,7 +928,7 @@ static void large_number(void)
     QDECREF(str);
     QDECREF(qnum);
 
-    qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
+    qnum = qobject_to(qobject_from_json(gtu64, &error_abort), QNum);
     g_assert(qnum);
     g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
     g_assert(!qnum_get_try_uint(qnum, &val));
@@ -938,7 +939,7 @@ static void large_number(void)
     QDECREF(str);
     QDECREF(qnum);
 
-    qnum = qobject_to_qnum(qobject_from_json(lti64, &error_abort));
+    qnum = qobject_to(qobject_from_json(lti64, &error_abort), QNum);
     g_assert(qnum);
     g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
     g_assert(!qnum_get_try_uint(qnum, &val));
@@ -970,7 +971,7 @@ static void float_number(void)
         QNum *qnum;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        qnum = qobject_to_qnum(obj);
+        qnum = qobject_to(obj, QNum);
         g_assert(qnum);
         g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
 
@@ -994,17 +995,17 @@ static void vararg_number(void)
     double valuef = 2.323423423;
     int64_t val;
 
-    qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
+    qnum = qobject_to(qobject_from_jsonf("%d", value), QNum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, value);
     QDECREF(qnum);
 
-    qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
+    qnum = qobject_to(qobject_from_jsonf("%lld", value_ll), QNum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, value_ll);
     QDECREF(qnum);
 
-    qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
+    qnum = qobject_to(qobject_from_jsonf("%f", valuef), QNum);
     g_assert(qnum_get_double(qnum) == valuef);
     QDECREF(qnum);
 }
@@ -1017,7 +1018,7 @@ static void keyword_literal(void)
     QString *str;
 
     obj = qobject_from_json("true", &error_abort);
-    qbool = qobject_to_qbool(obj);
+    qbool = qobject_to(obj, QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == true);
 
@@ -1028,7 +1029,7 @@ static void keyword_literal(void)
     QDECREF(qbool);
 
     obj = qobject_from_json("false", &error_abort);
-    qbool = qobject_to_qbool(obj);
+    qbool = qobject_to(obj, QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == false);
 
@@ -1038,13 +1039,13 @@ static void keyword_literal(void)
 
     QDECREF(qbool);
 
-    qbool = qobject_to_qbool(qobject_from_jsonf("%i", false));
+    qbool = qobject_to(qobject_from_jsonf("%i", false), QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == false);
     QDECREF(qbool);
 
     /* Test that non-zero values other than 1 get collapsed to true */
-    qbool = qobject_to_qbool(qobject_from_jsonf("%i", 2));
+    qbool = qobject_to(qobject_from_jsonf("%i", 2), QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == true);
     QDECREF(qbool);
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
index 894e9915e5..0d1cd13920 100644
--- a/tests/check-qlist.c
+++ b/tests/check-qlist.c
@@ -57,7 +57,7 @@ static void qobject_to_qlist_test(void)
 
     qlist = qlist_new();
 
-    g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
+    g_assert(qobject_to(QOBJECT(qlist), QList) == qlist);
 
     QDECREF(qlist);
 }
@@ -72,7 +72,7 @@ static void iter_func(QObject *obj, void *opaque)
 
     g_assert(opaque == NULL);
 
-    qi = qobject_to_qnum(obj);
+    qi = qobject_to(obj, QNum);
     g_assert(qi != NULL);
 
     g_assert(qnum_get_try_int(qi, &val));
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
index c59ec1ab88..ce5d93296a 100644
--- a/tests/check-qlit.c
+++ b/tests/check-qlit.c
@@ -58,7 +58,7 @@ static void qlit_equal_qobject_test(void)
 
     g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
 
-    qdict_put(qobject_to_qdict(qobj), "bee", qlist_new());
+    qdict_put(qobject_to(qobj, QDict), "bee", qlist_new());
     g_assert(!qlit_equal_qobject(&qlit, qobj));
 
     qobject_decref(qobj);
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index d702d5da9c..75cbbd8ef8 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -127,11 +127,11 @@ static void qobject_to_qnum_test(void)
     QNum *qn;
 
     qn = qnum_from_int(0);
-    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
+    g_assert(qobject_to(QOBJECT(qn), QNum) == qn);
     QDECREF(qn);
 
     qn = qnum_from_double(0);
-    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
+    g_assert(qobject_to(QOBJECT(qn), QNum) == qn);
     QDECREF(qn);
 }
 
diff --git a/tests/check-qobject.c b/tests/check-qobject.c
index 710f9e6b0a..146000bb3f 100644
--- a/tests/check-qobject.c
+++ b/tests/check-qobject.c
@@ -270,7 +270,7 @@ static void qobject_is_equal_dict_test(void)
                   dict_different_null_key, dict_longer, dict_shorter,
                   dict_nested);
 
-    dict_crumpled = qobject_to_qdict(qdict_crumple(dict_1, &local_err));
+    dict_crumpled = qobject_to(qdict_crumple(dict_1, &local_err), QDict);
     g_assert(!local_err);
     check_equal(dict_crumpled, dict_nested);
 
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
index 112ec08967..1118b8db5a 100644
--- a/tests/check-qstring.c
+++ b/tests/check-qstring.c
@@ -79,7 +79,7 @@ static void qobject_to_qstring_test(void)
     QString *qstring;
 
     qstring = qstring_from_str("foo");
-    g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
+    g_assert(qobject_to(QOBJECT(qstring), QString) == qstring);
 
     QDECREF(qstring);
 }
diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c
index f7162c023f..55787feabc 100644
--- a/tests/device-introspect-test.c
+++ b/tests/device-introspect-test.c
@@ -52,7 +52,7 @@ static QDict *qom_type_index(QList *types)
     QListEntry *e;
 
     QLIST_FOREACH_ENTRY(types, e) {
-        QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+        QDict *d = qobject_to(qlist_entry_obj(e), QDict);
         const char *name = qdict_get_str(d, "name");
         QINCREF(d);
         qdict_put(index, name, d);
@@ -85,7 +85,7 @@ static QDict *type_list_find(QList *types, const char *name)
     QListEntry *e;
 
     QLIST_FOREACH_ENTRY(types, e) {
-        QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+        QDict *d = qobject_to(qlist_entry_obj(e), QDict);
         const char *ename = qdict_get_str(d, "name");
         if (!strcmp(ename, name)) {
             return d;
@@ -151,7 +151,7 @@ static void test_qom_list_parents(const char *parent)
     index = qom_type_index(types);
 
     QLIST_FOREACH_ENTRY(types, e) {
-        QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+        QDict *d = qobject_to(qlist_entry_obj(e), QDict);
         const char *name = qdict_get_str(d, "name");
 
         g_assert(qom_has_parent(index, name, parent));
@@ -173,7 +173,7 @@ static void test_qom_list_fields(void)
     non_abstract = qom_list_types(NULL, false);
 
     QLIST_FOREACH_ENTRY(all_types, e) {
-        QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+        QDict *d = qobject_to(qlist_entry_obj(e), QDict);
         const char *name = qdict_get_str(d, "name");
         bool abstract = qdict_haskey(d, "abstract") ?
                         qdict_get_bool(d, "abstract") :
@@ -216,8 +216,8 @@ static void test_device_intro_concrete(void)
     types = device_type_list(false);
 
     QLIST_FOREACH_ENTRY(types, entry) {
-        type = qdict_get_try_str(qobject_to_qdict(qlist_entry_obj(entry)),
-                                "name");
+        type = qdict_get_try_str(qobject_to(qlist_entry_obj(entry), QDict),
+                                 "name");
         g_assert(type);
         test_one_device(type);
     }
@@ -238,7 +238,7 @@ static void test_abstract_interfaces(void)
     index = qom_type_index(all_types);
 
     QLIST_FOREACH_ENTRY(all_types, e) {
-        QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+        QDict *d = qobject_to(qlist_entry_obj(e), QDict);
         const char *name = qdict_get_str(d, "name");
 
         /*
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 0ec8af2923..f5405e1734 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -424,7 +424,7 @@ static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
     }
 
     g_assert(!qmp->response);
-    qmp->response = qobject_to_qdict(obj);
+    qmp->response = qobject_to(obj, QDict);
     g_assert(qmp->response);
 }
 
@@ -998,11 +998,11 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine))
     g_assert(list);
 
     for (p = qlist_first(list); p; p = qlist_next(p)) {
-        minfo = qobject_to_qdict(qlist_entry_obj(p));
+        minfo = qobject_to(qlist_entry_obj(p), QDict);
         g_assert(minfo);
         qobj = qdict_get(minfo, "name");
         g_assert(qobj);
-        qstr = qobject_to_qstring(qobj);
+        qstr = qobject_to(qobj, QString);
         g_assert(qstr);
         mname = qstring_get_str(qstr);
         cb(mname);
diff --git a/tests/numa-test.c b/tests/numa-test.c
index e1b6152244..549dd16cb8 100644
--- a/tests/numa-test.c
+++ b/tests/numa-test.c
@@ -96,7 +96,7 @@ static void test_query_cpus(const void *data)
         QDict *cpu, *props;
         int64_t cpu_idx, node;
 
-        cpu = qobject_to_qdict(e);
+        cpu = qobject_to(e, QDict);
         g_assert(qdict_haskey(cpu, "CPU"));
         g_assert(qdict_haskey(cpu, "props"));
 
@@ -138,7 +138,7 @@ static void pc_numa_cpu(const void *data)
         QDict *cpu, *props;
         int64_t socket, core, thread, node;
 
-        cpu = qobject_to_qdict(e);
+        cpu = qobject_to(e, QDict);
         g_assert(qdict_haskey(cpu, "props"));
         props = qdict_get_qdict(cpu, "props");
 
@@ -191,7 +191,7 @@ static void spapr_numa_cpu(const void *data)
         QDict *cpu, *props;
         int64_t core, node;
 
-        cpu = qobject_to_qdict(e);
+        cpu = qobject_to(e, QDict);
         g_assert(qdict_haskey(cpu, "props"));
         props = qdict_get_qdict(cpu, "props");
 
@@ -234,7 +234,7 @@ static void aarch64_numa_cpu(const void *data)
         QDict *cpu, *props;
         int64_t thread, node;
 
-        cpu = qobject_to_qdict(e);
+        cpu = qobject_to(e, QDict);
         g_assert(qdict_haskey(cpu, "props"));
         props = qdict_get_qdict(cpu, "props");
 
diff --git a/tests/qom-test.c b/tests/qom-test.c
index ab0595dc75..37d08eac46 100644
--- a/tests/qom-test.c
+++ b/tests/qom-test.c
@@ -61,9 +61,9 @@ static void test_properties(const char *path, bool recurse)
     }
 
     g_assert(qdict_haskey(response, "return"));
-    list = qobject_to_qlist(qdict_get(response, "return"));
+    list = qobject_to(qdict_get(response, "return"), QList);
     QLIST_FOREACH_ENTRY(list, entry) {
-        tuple = qobject_to_qdict(qlist_entry_obj(entry));
+        tuple = qobject_to(qlist_entry_obj(entry), QDict);
         bool is_child = strstart(qdict_get_str(tuple, "type"), "child<", NULL);
         bool is_link = strstart(qdict_get_str(tuple, "type"), "link<", NULL);
 
diff --git a/tests/test-char.c b/tests/test-char.c
index 911e3f6e8d..fbf18cf593 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -320,7 +320,7 @@ static void char_socket_test(void)
     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
 
     addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
-    qdict = qobject_to_qdict(addr);
+    qdict = qobject_to(addr, QDict);
     port = qdict_get_str(qdict, "port");
     tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);
     QDECREF(qdict);
diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index baf7e339ab..7cee296871 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -193,7 +193,7 @@ static void check_list012(QList *qlist)
 
     g_assert(qlist);
     for (i = 0; i < ARRAY_SIZE(expected); i++) {
-        qstr = qobject_to_qstring(qlist_pop(qlist));
+        qstr = qobject_to(qlist_pop(qlist), QString);
         g_assert(qstr);
         g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]);
         QDECREF(qstr);
@@ -652,12 +652,12 @@ static void test_keyval_visit_any(void)
     QDECREF(qdict);
     visit_start_struct(v, NULL, NULL, 0, &error_abort);
     visit_type_any(v, "a", &any, &error_abort);
-    qlist = qobject_to_qlist(any);
+    qlist = qobject_to(any, QList);
     g_assert(qlist);
-    qstr = qobject_to_qstring(qlist_pop(qlist));
+    qstr = qobject_to(qlist_pop(qlist), QString);
     g_assert_cmpstr(qstring_get_str(qstr), ==, "null");
     QDECREF(qstr);
-    qstr = qobject_to_qstring(qlist_pop(qlist));
+    qstr = qobject_to(qlist_pop(qlist), QString);
     g_assert_cmpstr(qstring_get_str(qstr), ==, "1");
     g_assert(qlist_empty(qlist));
     QDECREF(qstr);
diff --git a/tests/test-qga.c b/tests/test-qga.c
index fd6bc7690f..934c20d41f 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -295,8 +295,8 @@ static void test_qga_get_vcpus(gconstpointer fix)
     /* check there is at least a cpu */
     list = qdict_get_qlist(ret, "return");
     entry = qlist_first(list);
-    g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
-    g_assert(qdict_haskey(qobject_to_qdict(entry->value), "logical-id"));
+    g_assert(qdict_haskey(qobject_to(entry->value, QDict), "online"));
+    g_assert(qdict_haskey(qobject_to(entry->value, QDict), "logical-id"));
 
     QDECREF(ret);
 }
@@ -316,10 +316,10 @@ static void test_qga_get_fsinfo(gconstpointer fix)
     list = qdict_get_qlist(ret, "return");
     entry = qlist_first(list);
     if (entry) {
-        g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
-        g_assert(qdict_haskey(qobject_to_qdict(entry->value), "mountpoint"));
-        g_assert(qdict_haskey(qobject_to_qdict(entry->value), "type"));
-        g_assert(qdict_haskey(qobject_to_qdict(entry->value), "disk"));
+        g_assert(qdict_haskey(qobject_to(entry->value, QDict), "name"));
+        g_assert(qdict_haskey(qobject_to(entry->value, QDict), "mountpoint"));
+        g_assert(qdict_haskey(qobject_to(entry->value, QDict), "type"));
+        g_assert(qdict_haskey(qobject_to(entry->value, QDict), "disk"));
     }
 
     QDECREF(ret);
@@ -361,8 +361,9 @@ static void test_qga_get_memory_blocks(gconstpointer fix)
         entry = qlist_first(list);
         /* newer versions of qga may return empty list without error */
         if (entry) {
-            g_assert(qdict_haskey(qobject_to_qdict(entry->value), "phys-index"));
-            g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
+            g_assert(qdict_haskey(qobject_to(entry->value, QDict),
+                                  "phys-index"));
+            g_assert(qdict_haskey(qobject_to(entry->value, QDict), "online"));
         }
     }
 
@@ -383,7 +384,7 @@ static void test_qga_network_get_interfaces(gconstpointer fix)
     /* check there is at least an interface */
     list = qdict_get_qlist(ret, "return");
     entry = qlist_first(list);
-    g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
+    g_assert(qdict_haskey(qobject_to(entry->value, QDict), "name"));
 
     QDECREF(ret);
 }
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 904c89d4d4..efdfd0ed3d 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -98,7 +98,7 @@ static void test_dispatch_cmd(void)
 
     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
     assert(resp != NULL);
-    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+    assert(!qdict_haskey(qobject_to(resp, QDict), "error"));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -115,7 +115,7 @@ static void test_dispatch_cmd_failure(void)
 
     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
     assert(resp != NULL);
-    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+    assert(qdict_haskey(qobject_to(resp, QDict), "error"));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -129,7 +129,7 @@ static void test_dispatch_cmd_failure(void)
 
     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
     assert(resp != NULL);
-    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+    assert(qdict_haskey(qobject_to(resp, QDict), "error"));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -143,7 +143,7 @@ static QObject *test_qmp_dispatch(QDict *req)
 
     resp_obj = qmp_dispatch(&qmp_commands, QOBJECT(req));
     assert(resp_obj);
-    resp = qobject_to_qdict(resp_obj);
+    resp = qobject_to(resp_obj, QDict);
     assert(resp && !qdict_haskey(resp, "error"));
     ret = qdict_get(resp, "return");
     assert(ret);
@@ -174,7 +174,7 @@ static void test_dispatch_cmd_io(void)
     qdict_put(req, "arguments", args);
     qdict_put_str(req, "execute", "user_def_cmd2");
 
-    ret = qobject_to_qdict(test_qmp_dispatch(req));
+    ret = qobject_to(test_qmp_dispatch(req), QDict);
 
     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
     ret_dict = qdict_get_qdict(ret, "dict1");
@@ -195,7 +195,7 @@ static void test_dispatch_cmd_io(void)
     qdict_put(req, "arguments", args3);
     qdict_put_str(req, "execute", "guest-get-time");
 
-    ret3 = qobject_to_qnum(test_qmp_dispatch(req));
+    ret3 = qobject_to(test_qmp_dispatch(req), QNum);
     g_assert(qnum_get_try_int(ret3, &val));
     g_assert_cmpint(val, ==, 66);
     QDECREF(ret3);
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 9fb3c5e81e..c564e430e8 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -59,22 +59,22 @@ void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
 
     switch (qobject_type(obj1)) {
     case QTYPE_QBOOL:
-        d->result = (qbool_get_bool(qobject_to_qbool(obj1)) ==
-                     qbool_get_bool(qobject_to_qbool(obj2)));
+        d->result = (qbool_get_bool(qobject_to(obj1, QBool)) ==
+                     qbool_get_bool(qobject_to(obj2, QBool)));
         return;
     case QTYPE_QNUM:
-        g_assert(qnum_get_try_int(qobject_to_qnum(obj1), &val1));
-        g_assert(qnum_get_try_int(qobject_to_qnum(obj2), &val2));
+        g_assert(qnum_get_try_int(qobject_to(obj1, QNum), &val1));
+        g_assert(qnum_get_try_int(qobject_to(obj2, QNum), &val2));
         d->result = val1 == val2;
         return;
     case QTYPE_QSTRING:
-        d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
-                              qstring_get_str(qobject_to_qstring(obj2))) == 0;
+        d->result = g_strcmp0(qstring_get_str(qobject_to(obj1, QString)),
+                              qstring_get_str(qobject_to(obj2, QString))) == 0;
         return;
     case QTYPE_QDICT:
-        d_new.expect = qobject_to_qdict(obj2);
+        d_new.expect = qobject_to(obj2, QDict);
         d_new.result = true;
-        qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new);
+        qdict_iter(qobject_to(obj1, QDict), qdict_cmp_do_simple, &d_new);
         d->result = d_new.result;
         return;
     default:
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index fe591814e4..39bbdccedc 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -476,7 +476,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "-42");
     visit_type_any(v, NULL, &res, &error_abort);
-    qnum = qobject_to_qnum(res);
+    qnum = qobject_to(res, QNum);
     g_assert(qnum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, -42);
@@ -484,22 +484,22 @@ static void test_visitor_in_any(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
     visit_type_any(v, NULL, &res, &error_abort);
-    qdict = qobject_to_qdict(res);
+    qdict = qobject_to(res, QDict);
     g_assert(qdict && qdict_size(qdict) == 3);
     qobj = qdict_get(qdict, "integer");
     g_assert(qobj);
-    qnum = qobject_to_qnum(qobj);
+    qnum = qobject_to(qobj, QNum);
     g_assert(qnum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, -42);
     qobj = qdict_get(qdict, "boolean");
     g_assert(qobj);
-    qbool = qobject_to_qbool(qobj);
+    qbool = qobject_to(qobj, QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == true);
     qobj = qdict_get(qdict, "string");
     g_assert(qobj);
-    qstring = qobject_to_qstring(qobj);
+    qstring = qobject_to(qobj, QString);
     g_assert(qstring);
     g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
     qobject_decref(res);
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index d375100a52..6acd9ba592 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -63,7 +63,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
 
     visit_type_int(data->ov, NULL, &value, &error_abort);
 
-    qnum = qobject_to_qnum(visitor_get(data));
+    qnum = qobject_to(visitor_get(data), QNum);
     g_assert(qnum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, value);
@@ -77,7 +77,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
 
     visit_type_bool(data->ov, NULL, &value, &error_abort);
 
-    qbool = qobject_to_qbool(visitor_get(data));
+    qbool = qobject_to(visitor_get(data), QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == value);
 }
@@ -90,7 +90,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
 
     visit_type_number(data->ov, NULL, &value, &error_abort);
 
-    qnum = qobject_to_qnum(visitor_get(data));
+    qnum = qobject_to(visitor_get(data), QNum);
     g_assert(qnum);
     g_assert(qnum_get_double(qnum) == value);
 }
@@ -103,7 +103,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
 
     visit_type_str(data->ov, NULL, &string, &error_abort);
 
-    qstr = qobject_to_qstring(visitor_get(data));
+    qstr = qobject_to(visitor_get(data), QString);
     g_assert(qstr);
     g_assert_cmpstr(qstring_get_str(qstr), ==, string);
 }
@@ -117,7 +117,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
     /* A null string should return "" */
     visit_type_str(data->ov, NULL, &string, &error_abort);
 
-    qstr = qobject_to_qstring(visitor_get(data));
+    qstr = qobject_to(visitor_get(data), QString);
     g_assert(qstr);
     g_assert_cmpstr(qstring_get_str(qstr), ==, "");
 }
@@ -131,7 +131,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
     for (i = 0; i < ENUM_ONE__MAX; i++) {
         visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
 
-        qstr = qobject_to_qstring(visitor_get(data));
+        qstr = qobject_to(visitor_get(data), QString);
         g_assert(qstr);
         g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i));
         visitor_reset(data);
@@ -164,7 +164,7 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
 
     visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
 
-    qdict = qobject_to_qdict(visitor_get(data));
+    qdict = qobject_to(visitor_get(data), QDict);
     g_assert(qdict);
     g_assert_cmpint(qdict_size(qdict), ==, 3);
     g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
@@ -203,7 +203,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
 
     visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
 
-    qdict = qobject_to_qdict(visitor_get(data));
+    qdict = qobject_to(visitor_get(data), QDict);
     g_assert(qdict);
     g_assert_cmpint(qdict_size(qdict), ==, 2);
     g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
@@ -277,7 +277,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
 
     visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
 
-    qlist = qobject_to_qlist(visitor_get(data));
+    qlist = qobject_to(visitor_get(data), QList);
     g_assert(qlist);
     g_assert(!qlist_empty(qlist));
 
@@ -286,7 +286,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
     QLIST_FOREACH_ENTRY(qlist, entry) {
         QDict *qdict;
 
-        qdict = qobject_to_qdict(entry->value);
+        qdict = qobject_to(entry->value, QDict);
         g_assert(qdict);
         g_assert_cmpint(qdict_size(qdict), ==, 3);
         g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
@@ -339,7 +339,7 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
 
     qobj = QOBJECT(qnum_from_int(-42));
     visit_type_any(data->ov, NULL, &qobj, &error_abort);
-    qnum = qobject_to_qnum(visitor_get(data));
+    qnum = qobject_to(visitor_get(data), QNum);
     g_assert(qnum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, -42);
@@ -353,16 +353,16 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
     qobj = QOBJECT(qdict);
     visit_type_any(data->ov, NULL, &qobj, &error_abort);
     qobject_decref(qobj);
-    qdict = qobject_to_qdict(visitor_get(data));
+    qdict = qobject_to(visitor_get(data), QDict);
     g_assert(qdict);
-    qnum = qobject_to_qnum(qdict_get(qdict, "integer"));
+    qnum = qobject_to(qdict_get(qdict, "integer"), QNum);
     g_assert(qnum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, -42);
-    qbool = qobject_to_qbool(qdict_get(qdict, "boolean"));
+    qbool = qobject_to(qdict_get(qdict, "boolean"), QBool);
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == true);
-    qstring = qobject_to_qstring(qdict_get(qdict, "string"));
+    qstring = qobject_to(qdict_get(qdict, "string"), QString);
     g_assert(qstring);
     g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
 }
@@ -379,7 +379,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
     tmp->u.value1.boolean = true;
 
     visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
-    qdict = qobject_to_qdict(visitor_get(data));
+    qdict = qobject_to(visitor_get(data), QDict);
     g_assert(qdict);
     g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
     g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
@@ -403,7 +403,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
     tmp->u.i = 42;
 
     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
-    qnum = qobject_to_qnum(visitor_get(data));
+    qnum = qobject_to(visitor_get(data), QNum);
     g_assert(qnum);
     g_assert(qnum_get_try_int(qnum, &val));
     g_assert_cmpint(val, ==, 42);
@@ -416,7 +416,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
     tmp->u.e = ENUM_ONE_VALUE1;
 
     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
-    qstr = qobject_to_qstring(visitor_get(data));
+    qstr = qobject_to(visitor_get(data), QString);
     g_assert(qstr);
     g_assert_cmpstr(qstring_get_str(qstr), ==, "value1");
 
@@ -441,7 +441,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
     tmp->u.udfu.u.value1.boolean = true;
 
     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
-    qdict = qobject_to_qdict(visitor_get(data));
+    qdict = qobject_to(visitor_get(data), QDict);
     g_assert(qdict);
     g_assert_cmpint(qdict_size(qdict), ==, 4);
     g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
@@ -463,7 +463,7 @@ static void test_visitor_out_null(TestOutputVisitorData *data,
     visit_type_null(data->ov, "a", &null, &error_abort);
     visit_check_struct(data->ov, &error_abort);
     visit_end_struct(data->ov, NULL);
-    qdict = qobject_to_qdict(visitor_get(data));
+    qdict = qobject_to(visitor_get(data), QDict);
     g_assert(qdict);
     g_assert_cmpint(qdict_size(qdict), ==, 1);
     nil = qdict_get(qdict, "a");
@@ -607,10 +607,10 @@ static void check_native_list(QObject *qobj,
     QList *qlist;
     int i;
 
-    qdict = qobject_to_qdict(qobj);
+    qdict = qobject_to(qobj, QDict);
     g_assert(qdict);
     g_assert(qdict_haskey(qdict, "data"));
-    qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
+    qlist = qlist_copy(qobject_to(qdict_get(qdict, "data"), QList));
 
     switch (kind) {
     case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
@@ -624,7 +624,7 @@ static void check_native_list(QObject *qobj,
 
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qnum(tmp);
+            qvalue = qobject_to(tmp, QNum);
             g_assert(qnum_get_try_uint(qvalue, &val));
             g_assert_cmpint(val, ==, i);
             qobject_decref(qlist_pop(qlist));
@@ -648,7 +648,7 @@ static void check_native_list(QObject *qobj,
 
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qnum(tmp);
+            qvalue = qobject_to(tmp, QNum);
             g_assert(qnum_get_try_int(qvalue, &val));
             g_assert_cmpint(val, ==, i);
             qobject_decref(qlist_pop(qlist));
@@ -660,7 +660,7 @@ static void check_native_list(QObject *qobj,
             QBool *qvalue;
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qbool(tmp);
+            qvalue = qobject_to(tmp, QBool);
             g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0);
             qobject_decref(qlist_pop(qlist));
         }
@@ -672,7 +672,7 @@ static void check_native_list(QObject *qobj,
             gchar str[8];
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qstring(tmp);
+            qvalue = qobject_to(tmp, QString);
             sprintf(str, "%d", i);
             g_assert_cmpstr(qstring_get_str(qvalue), ==, str);
             qobject_decref(qlist_pop(qlist));
@@ -687,7 +687,7 @@ static void check_native_list(QObject *qobj,
 
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qnum(tmp);
+            qvalue = qobject_to(tmp, QNum);
             g_string_printf(double_expected, "%.6f", (double)i / 3);
             g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue));
             g_assert_cmpstr(double_actual->str, ==, double_expected->str);
diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
index 58a2dd9fe8..c1b7498013 100644
--- a/tests/test-x86-cpuid-compat.c
+++ b/tests/test-x86-cpuid-compat.c
@@ -17,7 +17,7 @@ static char *get_cpu0_qom_path(void)
     g_assert(qdict_haskey(resp, "return"));
     ret = qdict_get_qlist(resp, "return");
 
-    cpu0 = qobject_to_qdict(qlist_peek(ret));
+    cpu0 = qobject_to(qlist_peek(ret), QDict);
     path = g_strdup(qdict_get_str(cpu0, "qom_path"));
     QDECREF(resp);
     return path;
@@ -38,7 +38,7 @@ static QObject *qom_get(const char *path, const char *prop)
 #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
 static bool qom_get_bool(const char *path, const char *prop)
 {
-    QBool *value = qobject_to_qbool(qom_get(path, prop));
+    QBool *value = qobject_to(qom_get(path, prop), QBool);
     bool b = qbool_get_bool(value);
 
     QDECREF(value);
@@ -61,7 +61,7 @@ static void test_cpuid_prop(const void *data)
 
     qtest_start(args->cmdline);
     path = get_cpu0_qom_path();
-    value = qobject_to_qnum(qom_get(path, args->property));
+    value = qobject_to(qom_get(path, args->property), QNum);
     g_assert(qnum_get_try_int(value, &val));
     g_assert_cmpint(val, ==, args->expected_value);
     qtest_end();
@@ -105,7 +105,7 @@ static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx,
     const QListEntry *e;
 
     for (e = qlist_first(features); e; e = qlist_next(e)) {
-        QDict *w = qobject_to_qdict(qlist_entry_obj(e));
+        QDict *w = qobject_to(qlist_entry_obj(e), QDict);
         const char *rreg = qdict_get_str(w, "cpuid-register");
         uint32_t reax = qdict_get_int(w, "cpuid-input-eax");
         bool has_ecx = qdict_haskey(w, "cpuid-input-ecx");
@@ -116,8 +116,9 @@ static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx,
             recx = qdict_get_int(w, "cpuid-input-ecx");
         }
         if (eax == reax && (!has_ecx || ecx == recx) && !strcmp(rreg, reg)) {
-            g_assert(qnum_get_try_int(qobject_to_qnum(qdict_get(w, "features")),
-                                  &val));
+            g_assert(qnum_get_try_int(qobject_to(qdict_get(w, "features"),
+                                                 QNum),
+                                      &val));
             return val;
         }
     }
@@ -133,8 +134,8 @@ static void test_feature_flag(const void *data)
 
     qtest_start(args->cmdline);
     path = get_cpu0_qom_path();
-    present = qobject_to_qlist(qom_get(path, "feature-words"));
-    filtered = qobject_to_qlist(qom_get(path, "filtered-features"));
+    present = qobject_to(qom_get(path, "feature-words"), QList);
+    filtered = qobject_to(qom_get(path, "filtered-features"), QList);
     value = get_feature_word(present, args->in_eax, args->in_ecx, args->reg);
     value |= get_feature_word(filtered, args->in_eax, args->in_ecx, args->reg);
     qtest_end();
diff --git a/util/keyval.c b/util/keyval.c
index 7dfc75cf01..e19150ece0 100644
--- a/util/keyval.c
+++ b/util/keyval.c
@@ -219,7 +219,7 @@ static const char *keyval_parse_one(QDict *qdict, const char *params,
             if (!next) {
                 return NULL;
             }
-            cur = qobject_to_qdict(next);
+            cur = qobject_to(next, QDict);
             assert(cur);
         }
 
@@ -312,7 +312,7 @@ static QObject *keyval_listify(QDict *cur, GSList *key_of_cur, Error **errp)
             has_member = true;
         }
 
-        qdict = qobject_to_qdict(ent->value);
+        qdict = qobject_to(ent->value, QDict);
         if (!qdict) {
             continue;
         }
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 029fec53a9..dab5cbf55f 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -525,7 +525,7 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
         }
 
         QLIST_FOREACH_ENTRY(list, list_entry) {
-            QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry));
+            QDict *section = qobject_to(qlist_entry_obj(list_entry), QDict);
             char *opt_name;
 
             if (!section) {
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 553d3dc552..0fe7a21ffe 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -916,15 +916,15 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 
     switch (qobject_type(obj)) {
     case QTYPE_QSTRING:
-        value = qstring_get_str(qobject_to_qstring(obj));
+        value = qstring_get_str(qobject_to(obj, QString));
         break;
     case QTYPE_QNUM:
-        tmp = qnum_to_string(qobject_to_qnum(obj));
+        tmp = qnum_to_string(qobject_to(obj, QNum));
         value = tmp;
         break;
     case QTYPE_QBOOL:
         pstrcpy(buf, sizeof(buf),
-                qbool_get_bool(qobject_to_qbool(obj)) ? "on" : "off");
+                qbool_get_bool(qobject_to(obj, QBool)) ? "on" : "off");
         value = buf;
         break;
     default:
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH v2 3/6] qapi: Remove qobject_to_X() functions
  2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to() Max Reitz
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X) Max Reitz
@ 2018-01-20 15:44 ` Max Reitz
  2018-01-31 16:05   ` Alberto Garcia
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 4/6] qapi: Make more of qobject_to() Max Reitz
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

They are no longer needed now.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 include/qapi/qmp/qbool.h   |  1 -
 include/qapi/qmp/qdict.h   |  1 -
 include/qapi/qmp/qlist.h   |  1 -
 include/qapi/qmp/qnum.h    |  1 -
 include/qapi/qmp/qstring.h |  1 -
 qobject/qbool.c            | 11 -----------
 qobject/qdict.c            | 11 -----------
 qobject/qlist.c            | 11 -----------
 qobject/qnum.c             | 11 -----------
 qobject/qstring.c          | 11 -----------
 10 files changed, 60 deletions(-)

diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h
index f77ea86c4e..63e2918041 100644
--- a/include/qapi/qmp/qbool.h
+++ b/include/qapi/qmp/qbool.h
@@ -23,7 +23,6 @@ typedef struct QBool {
 
 QBool *qbool_from_bool(bool value);
 bool qbool_get_bool(const QBool *qb);
-QBool *qobject_to_qbool(const QObject *obj);
 bool qbool_is_equal(const QObject *x, const QObject *y);
 void qbool_destroy_obj(QObject *obj);
 
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index fc218e7be6..7dbe07dd85 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -42,7 +42,6 @@ void qdict_put_obj(QDict *qdict, const char *key, QObject *value);
 void qdict_del(QDict *qdict, const char *key);
 int qdict_haskey(const QDict *qdict, const char *key);
 QObject *qdict_get(const QDict *qdict, const char *key);
-QDict *qobject_to_qdict(const QObject *obj);
 bool qdict_is_equal(const QObject *x, const QObject *y);
 void qdict_iter(const QDict *qdict,
                 void (*iter)(const char *key, QObject *obj, void *opaque),
diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
index ec3fcc1a4c..979da8bc14 100644
--- a/include/qapi/qmp/qlist.h
+++ b/include/qapi/qmp/qlist.h
@@ -60,7 +60,6 @@ QObject *qlist_pop(QList *qlist);
 QObject *qlist_peek(QList *qlist);
 int qlist_empty(const QList *qlist);
 size_t qlist_size(const QList *qlist);
-QList *qobject_to_qlist(const QObject *obj);
 bool qlist_is_equal(const QObject *x, const QObject *y);
 void qlist_destroy_obj(QObject *obj);
 
diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h
index c3d86794bb..56ca3c4658 100644
--- a/include/qapi/qmp/qnum.h
+++ b/include/qapi/qmp/qnum.h
@@ -68,7 +68,6 @@ double qnum_get_double(QNum *qn);
 
 char *qnum_to_string(QNum *qn);
 
-QNum *qobject_to_qnum(const QObject *obj);
 bool qnum_is_equal(const QObject *x, const QObject *y);
 void qnum_destroy_obj(QObject *obj);
 
diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index 65c05a9be5..9293af9ac6 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -30,7 +30,6 @@ const char *qstring_get_str(const QString *qstring);
 void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
 void qstring_append_chr(QString *qstring, int c);
-QString *qobject_to_qstring(const QObject *obj);
 bool qstring_is_equal(const QObject *x, const QObject *y);
 void qstring_destroy_obj(QObject *obj);
 
diff --git a/qobject/qbool.c b/qobject/qbool.c
index 683d2b9b3f..91fc2ddcbb 100644
--- a/qobject/qbool.c
+++ b/qobject/qbool.c
@@ -40,17 +40,6 @@ bool qbool_get_bool(const QBool *qb)
     return qb->value;
 }
 
-/**
- * qobject_to_qbool(): Convert a QObject into a QBool
- */
-QBool *qobject_to_qbool(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QBOOL) {
-        return NULL;
-    }
-    return container_of(obj, QBool, base);
-}
-
 /**
  * qbool_is_equal(): Test whether the two QBools are equal
  */
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 472d989a67..ca84455883 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -36,17 +36,6 @@ QDict *qdict_new(void)
     return qdict;
 }
 
-/**
- * qobject_to_qdict(): Convert a QObject into a QDict
- */
-QDict *qobject_to_qdict(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QDICT) {
-        return NULL;
-    }
-    return container_of(obj, QDict, base);
-}
-
 /**
  * tdb_hash(): based on the hash agorithm from gdbm, via tdb
  * (from module-init-tools)
diff --git a/qobject/qlist.c b/qobject/qlist.c
index a8bd42e3de..b13a392fd5 100644
--- a/qobject/qlist.c
+++ b/qobject/qlist.c
@@ -128,17 +128,6 @@ size_t qlist_size(const QList *qlist)
     return count;
 }
 
-/**
- * qobject_to_qlist(): Convert a QObject into a QList
- */
-QList *qobject_to_qlist(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QLIST) {
-        return NULL;
-    }
-    return container_of(obj, QList, base);
-}
-
 /**
  * qlist_is_equal(): Test whether the two QLists are equal
  *
diff --git a/qobject/qnum.c b/qobject/qnum.c
index 18dcf27582..98893e06fb 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -201,17 +201,6 @@ char *qnum_to_string(QNum *qn)
     return NULL;
 }
 
-/**
- * qobject_to_qnum(): Convert a QObject into a QNum
- */
-QNum *qobject_to_qnum(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QNUM) {
-        return NULL;
-    }
-    return container_of(obj, QNum, base);
-}
-
 /**
  * qnum_is_equal(): Test whether the two QNums are equal
  *
diff --git a/qobject/qstring.c b/qobject/qstring.c
index ddfa8714dc..93b5f1814e 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -106,17 +106,6 @@ void qstring_append_chr(QString *qstring, int c)
     qstring->string[qstring->length] = 0;
 }
 
-/**
- * qobject_to_qstring(): Convert a QObject to a QString
- */
-QString *qobject_to_qstring(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QSTRING) {
-        return NULL;
-    }
-    return container_of(obj, QString, base);
-}
-
 /**
  * qstring_get_str(): Return a pointer to the stored string
  *
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH v2 4/6] qapi: Make more of qobject_to()
  2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
                   ` (2 preceding siblings ...)
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 3/6] qapi: Remove qobject_to_X() functions Max Reitz
@ 2018-01-20 15:44 ` Max Reitz
  2018-01-31 16:16   ` Alberto Garcia
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 5/6] block: Handle null backing link Max Reitz
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": "" Max Reitz
  5 siblings, 1 reply; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

This patch reworks some places which use either qobject_type() checks
plus qobject_to(), where the latter alone is sufficient, or NULL checks
plus qobject_type() checks where we can simply do a qobject_to() != NULL
check.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 qapi/qobject-input-visitor.c |  4 ++--
 qobject/json-parser.c        | 13 +++++++------
 qobject/qdict.c              | 20 +++++++++++---------
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 45e6160b21..fa6b92d9f6 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -334,7 +334,7 @@ static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
     QObjectInputVisitor *qiv = to_qiv(v);
     StackObject *tos = QSLIST_FIRST(&qiv->stack);
 
-    assert(tos && tos->obj && qobject_type(tos->obj) == QTYPE_QLIST);
+    assert(tos && qobject_to(tos->obj, QList));
 
     if (!tos->entry) {
         return NULL;
@@ -348,7 +348,7 @@ static void qobject_input_check_list(Visitor *v, Error **errp)
     QObjectInputVisitor *qiv = to_qiv(v);
     StackObject *tos = QSLIST_FIRST(&qiv->stack);
 
-    assert(tos && tos->obj && qobject_type(tos->obj) == QTYPE_QLIST);
+    assert(tos && qobject_to(tos->obj, QList));
 
     if (tos->entry) {
         error_setg(errp, "Only %u list elements expected in %s",
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index 885039e94b..c4d1f0d8de 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -271,7 +271,8 @@ static void parser_context_free(JSONParserContext *ctxt)
  */
 static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
 {
-    QObject *key = NULL, *value;
+    QObject *value;
+    QString *key = NULL;
     JSONToken *peek, *token;
 
     peek = parser_context_peek_token(ctxt);
@@ -280,8 +281,8 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
         goto out;
     }
 
-    key = parse_value(ctxt, ap);
-    if (!key || qobject_type(key) != QTYPE_QSTRING) {
+    key = qobject_to(parse_value(ctxt, ap), QString);
+    if (!key) {
         parse_error(ctxt, peek, "key is not a string in object");
         goto out;
     }
@@ -303,14 +304,14 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
         goto out;
     }
 
-    qdict_put_obj(dict, qstring_get_str(qobject_to(key, QString)), value);
+    qdict_put_obj(dict, qstring_get_str(key), value);
 
-    qobject_decref(key);
+    QDECREF(key);
 
     return 0;
 
 out:
-    qobject_decref(key);
+    QDECREF(key);
 
     return -1;
 }
diff --git a/qobject/qdict.c b/qobject/qdict.c
index ca84455883..3e97c2d3bc 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -861,18 +861,20 @@ QObject *qdict_crumple(const QDict *src, Error **errp)
 
         child = qdict_get(two_level, prefix);
         if (suffix) {
-            if (child) {
-                if (qobject_type(child) != QTYPE_QDICT) {
+            QDict *child_dict = qobject_to(child, QDict);
+            if (!child_dict) {
+                if (child) {
                     error_setg(errp, "Key %s prefix is already set as a scalar",
                                prefix);
                     goto error;
                 }
-            } else {
-                child = QOBJECT(qdict_new());
-                qdict_put_obj(two_level, prefix, child);
+
+                child_dict = qdict_new();
+                qdict_put_obj(two_level, prefix, QOBJECT(child_dict));
             }
+
             qobject_incref(ent->value);
-            qdict_put_obj(qobject_to(child, QDict), suffix, ent->value);
+            qdict_put_obj(child_dict, suffix, ent->value);
         } else {
             if (child) {
                 error_setg(errp, "Key %s prefix is already set as a dict",
@@ -892,9 +894,9 @@ QObject *qdict_crumple(const QDict *src, Error **errp)
     multi_level = qdict_new();
     for (ent = qdict_first(two_level); ent != NULL;
          ent = qdict_next(two_level, ent)) {
-
-        if (qobject_type(ent->value) == QTYPE_QDICT) {
-            child = qdict_crumple(qobject_to(ent->value, QDict), errp);
+        QDict *dict = qobject_to(ent->value, QDict);
+        if (dict) {
+            child = qdict_crumple(dict, errp);
             if (!child) {
                 goto error;
             }
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH v2 5/6] block: Handle null backing link
  2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
                   ` (3 preceding siblings ...)
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 4/6] qapi: Make more of qobject_to() Max Reitz
@ 2018-01-20 15:44 ` Max Reitz
  2018-02-01 14:17   ` Alberto Garcia
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": "" Max Reitz
  5 siblings, 1 reply; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

Instead of converting all "backing": null instances into "backing": "",
handle a null value directly in bdrv_open_inherit().

This enables explicitly null backing links for json:{} filenames.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block.c                    |  4 +++-
 blockdev.c                 | 14 --------------
 tests/qemu-iotests/089     | 20 ++++++++++++++++++++
 tests/qemu-iotests/089.out |  8 ++++++++
 4 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/block.c b/block.c
index 909cf076b7..32b7887651 100644
--- a/block.c
+++ b/block.c
@@ -2597,7 +2597,9 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 
     /* See cautionary note on accessing @options above */
     backing = qdict_get_try_str(options, "backing");
-    if (backing && *backing == '\0') {
+    if (qobject_to(qdict_get(options, "backing"), QNull) != NULL ||
+        (backing && *backing == '\0'))
+    {
         flags |= BDRV_O_NO_BACKING;
         qdict_del(options, "backing");
     }
diff --git a/blockdev.c b/blockdev.c
index 2dce231c98..5aac920eae 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3969,7 +3969,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
     QObject *obj;
     Visitor *v = qobject_output_visitor_new(&obj);
     QDict *qdict;
-    const QDictEntry *ent;
     Error *local_err = NULL;
 
     visit_type_BlockdevOptions(v, NULL, &options, &local_err);
@@ -3983,19 +3982,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    /*
-     * Rewrite "backing": null to "backing": ""
-     * TODO Rewrite "" to null instead, and perhaps not even here
-     */
-    for (ent = qdict_first(qdict); ent; ent = qdict_next(qdict, ent)) {
-        char *dot = strrchr(ent->key, '.');
-
-        if (!strcmp(dot ? dot + 1 : ent->key, "backing")
-            && qobject_type(ent->value) == QTYPE_QNULL) {
-            qdict_put(qdict, ent->key, qstring_new());
-        }
-    }
-
     if (!qdict_get_try_str(qdict, "node-name")) {
         error_setg(errp, "'node-name' must be specified for the root node");
         goto fail;
diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089
index 0b059aba90..aa1ba4a98e 100755
--- a/tests/qemu-iotests/089
+++ b/tests/qemu-iotests/089
@@ -82,6 +82,26 @@ $QEMU_IO_PROG --cache $CACHEMODE \
 $QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
 
 
+echo
+echo "=== Testing correct handling of 'backing':null ==="
+echo
+
+_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
+
+# This should read 42
+$QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+
+# This should read 0
+$QEMU_IO -c 'read -P 0 0 512' "json:{\
+    'driver': '$IMGFMT',
+    'file': {
+        'driver': 'file',
+        'filename': '$TEST_IMG'
+    },
+    'backing': null
+}" | _filter_qemu_io
+
+
 # Taken from test 071
 echo
 echo "=== Testing blkdebug ==="
diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
index 0bf5a13ec1..89e3e4340a 100644
--- a/tests/qemu-iotests/089.out
+++ b/tests/qemu-iotests/089.out
@@ -19,6 +19,14 @@ Pattern verification failed at offset 0, 512 bytes
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
+=== Testing correct handling of 'backing':null ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
 === Testing blkdebug ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": ""
  2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
                   ` (4 preceding siblings ...)
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 5/6] block: Handle null backing link Max Reitz
@ 2018-01-20 15:44 ` Max Reitz
  2018-01-31 16:22   ` Eric Blake
  2018-02-01 14:18   ` Alberto Garcia
  5 siblings, 2 replies; 18+ messages in thread
From: Max Reitz @ 2018-01-20 15:44 UTC (permalink / raw)
  To: qemu-block
  Cc: qemu-devel, Max Reitz, Markus Armbruster, Eric Blake,
	Alberto Garcia, Kevin Wolf

We have a clear replacement, so let's deprecate it.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 qapi/block-core.json | 4 ++--
 block.c              | 4 ++++
 qemu-doc.texi        | 7 +++++++
 qemu-options.hx      | 4 ++--
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 89ed2bc6a4..78de8eff63 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1090,7 +1090,7 @@
 # @overlay: reference to the existing block device that will become
 #           the overlay of @node, as part of creating the snapshot.
 #           It must not have a current backing file (this can be
-#           achieved by passing "backing": "" to blockdev-add).
+#           achieved by passing "backing": null to blockdev-add).
 #
 # Since: 2.5
 ##
@@ -1238,7 +1238,7 @@
 #                     "node-name": "node1534",
 #                     "file": { "driver": "file",
 #                               "filename": "hd1.qcow2" },
-#                     "backing": "" } }
+#                     "backing": null } }
 #
 # <- { "return": {} }
 #
diff --git a/block.c b/block.c
index 32b7887651..5ac0aba638 100644
--- a/block.c
+++ b/block.c
@@ -2600,6 +2600,10 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
     if (qobject_to(qdict_get(options, "backing"), QNull) != NULL ||
         (backing && *backing == '\0'))
     {
+        if (backing) {
+            warn_report("Use of \"backing\": \"\" is deprecated; "
+                        "use \"backing\": null instead");
+        }
         flags |= BDRV_O_NO_BACKING;
         qdict_del(options, "backing");
     }
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 3e9eb819a6..d321908da8 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2773,6 +2773,13 @@ or ``ivshmem-doorbell`` device types.
 The ``xlnx-ep108'' machine has been replaced by the ``xlnx-zcu102'' machine.
 The ``xlnx-zcu102'' machine has the same features and capabilites in QEMU.
 
+@section Block device options
+
+@subsection "backing": "" (since 2.12.0)
+
+In order to prevent QEMU from automatically opening an image's backing
+chain, use ``"backing": null'' instead.
+
 @node License
 @appendix License
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 5ff741a4af..76e9a5b06b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -743,8 +743,8 @@ Reference to or definition of the data source block driver node
 
 @item backing
 Reference to or definition of the backing file block device (default is taken
-from the image file). It is allowed to pass an empty string here in order to
-disable the default backing file.
+from the image file). It is allowed to pass @code{null} here in order to disable
+the default backing file.
 
 @item lazy-refcounts
 Whether to enable the lazy refcounts feature (on/off; default is taken from the
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to()
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to() Max Reitz
@ 2018-01-22 15:33   ` Eric Blake
  2018-01-22 16:53     ` Max Reitz
  2018-01-31 16:02   ` Alberto Garcia
  1 sibling, 1 reply; 18+ messages in thread
From: Eric Blake @ 2018-01-22 15:33 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Alberto Garcia, Kevin Wolf

[-- Attachment #1: Type: text/plain, Size: 2332 bytes --]

On 01/20/2018 09:44 AM, Max Reitz wrote:
> This is a dynamic casting macro that, given a QObject type, returns an
> object as that type or NULL if the object is of a different type (or
> NULL itself).
> 
> The macro uses lower-case letters because:
> 1. There does not seem to be a hard rule on whether qemu macros have to
>    be upper-cased,
> 2. The current situation in qapi/qmp is inconsistent (compare e.g.
>    QINCREF() vs. qdict_put()),
> 3. qobject_to() will evaluate its @obj parameter only once, thus it is
>    generally not important to the caller whether it is a macro or not,
> 4. I prefer it aesthetically.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> You're more than welcome to convince me to call it QOBJECT_TO()!

I can live with the lower-case version; especially with your good list
of reasons for it ;)

> ---
>  include/qapi/qmp/qobject.h | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
> index 38ac68845c..1211989ca0 100644
> --- a/include/qapi/qmp/qobject.h
> +++ b/include/qapi/qmp/qobject.h
> @@ -50,6 +50,24 @@ struct QObject {
>  #define QDECREF(obj)              \
>      qobject_decref(obj ? QOBJECT(obj) : NULL)
>  
> +/* Required for qobject_to() */
> +#define QTYPE_CAST_TO_QNull     QTYPE_QNULL
> +#define QTYPE_CAST_TO_QNum      QTYPE_QNUM
> +#define QTYPE_CAST_TO_QString   QTYPE_QSTRING
> +#define QTYPE_CAST_TO_QDict     QTYPE_QDICT
> +#define QTYPE_CAST_TO_QList     QTYPE_QLIST
> +#define QTYPE_CAST_TO_QBool     QTYPE_QBOOL
> +
> +#ifdef CONFIG_STATIC_ASSERT
> +_Static_assert(QTYPE__MAX == 7,
> +               "The QTYPE_CAST_TO_* list needs to be extended");
> +#endif

Why not use QEMU_BUILD_BUG_ON() instead of _Static_assert?  That way,
this check will break the build even on older compilers that lack
_Static_assert but where we still know how to trigger a build failure.

> +
> +#define qobject_to(obj, type) \
> +    container_of(qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)) ?: \
> +                     QOBJECT((type *)NULL), \
> +                 type, base)

Slick!

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to()
  2018-01-22 15:33   ` Eric Blake
@ 2018-01-22 16:53     ` Max Reitz
  0 siblings, 0 replies; 18+ messages in thread
From: Max Reitz @ 2018-01-22 16:53 UTC (permalink / raw)
  To: Eric Blake, qemu-block
  Cc: qemu-devel, Markus Armbruster, Alberto Garcia, Kevin Wolf

[-- Attachment #1: Type: text/plain, Size: 3125 bytes --]

On 2018-01-22 16:33, Eric Blake wrote:
> On 01/20/2018 09:44 AM, Max Reitz wrote:
>> This is a dynamic casting macro that, given a QObject type, returns an
>> object as that type or NULL if the object is of a different type (or
>> NULL itself).
>>
>> The macro uses lower-case letters because:
>> 1. There does not seem to be a hard rule on whether qemu macros have to
>>    be upper-cased,
>> 2. The current situation in qapi/qmp is inconsistent (compare e.g.
>>    QINCREF() vs. qdict_put()),
>> 3. qobject_to() will evaluate its @obj parameter only once, thus it is
>>    generally not important to the caller whether it is a macro or not,
>> 4. I prefer it aesthetically.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>> You're more than welcome to convince me to call it QOBJECT_TO()!
> 
> I can live with the lower-case version; especially with your good list
> of reasons for it ;)
> 
>> ---
>>  include/qapi/qmp/qobject.h | 32 ++++++++++++++++++++++++++++++++
>>  1 file changed, 32 insertions(+)
>>
>> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
>> index 38ac68845c..1211989ca0 100644
>> --- a/include/qapi/qmp/qobject.h
>> +++ b/include/qapi/qmp/qobject.h
>> @@ -50,6 +50,24 @@ struct QObject {
>>  #define QDECREF(obj)              \
>>      qobject_decref(obj ? QOBJECT(obj) : NULL)
>>  
>> +/* Required for qobject_to() */
>> +#define QTYPE_CAST_TO_QNull     QTYPE_QNULL
>> +#define QTYPE_CAST_TO_QNum      QTYPE_QNUM
>> +#define QTYPE_CAST_TO_QString   QTYPE_QSTRING
>> +#define QTYPE_CAST_TO_QDict     QTYPE_QDICT
>> +#define QTYPE_CAST_TO_QList     QTYPE_QLIST
>> +#define QTYPE_CAST_TO_QBool     QTYPE_QBOOL
>> +
>> +#ifdef CONFIG_STATIC_ASSERT
>> +_Static_assert(QTYPE__MAX == 7,
>> +               "The QTYPE_CAST_TO_* list needs to be extended");
>> +#endif
> 
> Why not use QEMU_BUILD_BUG_ON() instead of _Static_assert?  That way,
> this check will break the build even on older compilers that lack
> _Static_assert but where we still know how to trigger a build failure.

One reason would be because _Static_assert() allows me to give a nice
warning message -- I could add a comment above the QEMU_BUILD_BUG_ON()
line and hope for the best, but still, I like that better.

The other is that I assumed most people would be using C11 compilers
now, so the omission would be spotted sufficiently early.
"Sufficiently" because it's actually not that bad for this list to be
incomplete.  The worst is that you can't use qobject_to() for your
desired target type, but that's hardly catastrophic.

I could add an #else branch with QEMU_BUILD_BUG_ON().  Or I could add a
QEMU_BUILD_BUG_MSG() macro that takes a message (which is omitted if you
don't have _Static_assert() but would still make for a nice comment).  I
guess the latter would be a nice idea in general...?

Max

>> +
>> +#define qobject_to(obj, type) \
>> +    container_of(qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)) ?: \
>> +                     QOBJECT((type *)NULL), \
>> +                 type, base)
> 
> Slick!
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 512 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to()
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to() Max Reitz
  2018-01-22 15:33   ` Eric Blake
@ 2018-01-31 16:02   ` Alberto Garcia
  1 sibling, 0 replies; 18+ messages in thread
From: Alberto Garcia @ 2018-01-31 16:02 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Eric Blake, Kevin Wolf

On Sat 20 Jan 2018 04:44:07 PM CET, Max Reitz wrote:
> This is a dynamic casting macro that, given a QObject type, returns an
> object as that type or NULL if the object is of a different type (or
> NULL itself).
>
> The macro uses lower-case letters because:
> 1. There does not seem to be a hard rule on whether qemu macros have to
>    be upper-cased,
> 2. The current situation in qapi/qmp is inconsistent (compare e.g.
>    QINCREF() vs. qdict_put()),
> 3. qobject_to() will evaluate its @obj parameter only once, thus it is
>    generally not important to the caller whether it is a macro or not,
> 4. I prefer it aesthetically.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X)
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X) Max Reitz
@ 2018-01-31 16:05   ` Alberto Garcia
  2018-01-31 16:11   ` Eric Blake
  1 sibling, 0 replies; 18+ messages in thread
From: Alberto Garcia @ 2018-01-31 16:05 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Eric Blake, Kevin Wolf

On Sat 20 Jan 2018 04:44:08 PM CET, Max Reitz wrote:
> This patch was generated using the following Coccinelle script:
>
> @@
> expression Obj;
> @@
> (
> - qobject_to_qnum(Obj)
> + qobject_to(Obj, QNum)
> |
> - qobject_to_qstring(Obj)
> + qobject_to(Obj, QString)
> |
> - qobject_to_qdict(Obj)
> + qobject_to(Obj, QDict)
> |
> - qobject_to_qlist(Obj)
> + qobject_to(Obj, QList)
> |
> - qobject_to_qbool(Obj)
> + qobject_to(Obj, QBool)
> )
>
> and a bit of manual fix-up for overly long lines and three places in
> tests/check-qjson.c that Coccinelle did not find.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/6] qapi: Remove qobject_to_X() functions
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 3/6] qapi: Remove qobject_to_X() functions Max Reitz
@ 2018-01-31 16:05   ` Alberto Garcia
  0 siblings, 0 replies; 18+ messages in thread
From: Alberto Garcia @ 2018-01-31 16:05 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Eric Blake, Kevin Wolf

On Sat 20 Jan 2018 04:44:09 PM CET, Max Reitz wrote:
> They are no longer needed now.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X)
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X) Max Reitz
  2018-01-31 16:05   ` Alberto Garcia
@ 2018-01-31 16:11   ` Eric Blake
  2018-01-31 16:14     ` Eric Blake
  1 sibling, 1 reply; 18+ messages in thread
From: Eric Blake @ 2018-01-31 16:11 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Alberto Garcia, Kevin Wolf

[-- Attachment #1: Type: text/plain, Size: 642 bytes --]

On 01/20/2018 09:44 AM, Max Reitz wrote:
> This patch was generated using the following Coccinelle script:
> 
> @@
> expression Obj;
> @@
> (
> - qobject_to_qnum(Obj)
> + qobject_to(Obj, QNum)
> |
> - qobject_to_qstring(Obj)
> + qobject_to(Obj, QString)
> |
> - qobject_to_qdict(Obj)
> + qobject_to(Obj, QDict)
> |
> - qobject_to_qlist(Obj)
> + qobject_to(Obj, QList)
> |
> - qobject_to_qbool(Obj)
> + qobject_to(Obj, QBool)
> )

Worth adding these to scripts/coccinelle/qobject.cocci?

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X)
  2018-01-31 16:11   ` Eric Blake
@ 2018-01-31 16:14     ` Eric Blake
  0 siblings, 0 replies; 18+ messages in thread
From: Eric Blake @ 2018-01-31 16:14 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Markus Armbruster

[-- Attachment #1: Type: text/plain, Size: 850 bytes --]

On 01/31/2018 10:11 AM, Eric Blake wrote:
> On 01/20/2018 09:44 AM, Max Reitz wrote:
>> This patch was generated using the following Coccinelle script:
>>
>> @@
>> expression Obj;
>> @@
>> (
>> - qobject_to_qnum(Obj)
>> + qobject_to(Obj, QNum)
>> |
>> - qobject_to_qstring(Obj)
>> + qobject_to(Obj, QString)
>> |
>> - qobject_to_qdict(Obj)
>> + qobject_to(Obj, QDict)
>> |
>> - qobject_to_qlist(Obj)
>> + qobject_to(Obj, QList)
>> |
>> - qobject_to_qbool(Obj)
>> + qobject_to(Obj, QBool)
>> )
> 
> Worth adding these to scripts/coccinelle/qobject.cocci?

Answering myself - perhaps not, since 3/6 deletes the functions meaning
they won't reappear as something we need to keep checking for.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/6] qapi: Make more of qobject_to()
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 4/6] qapi: Make more of qobject_to() Max Reitz
@ 2018-01-31 16:16   ` Alberto Garcia
  0 siblings, 0 replies; 18+ messages in thread
From: Alberto Garcia @ 2018-01-31 16:16 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Eric Blake, Kevin Wolf

On Sat 20 Jan 2018 04:44:10 PM CET, Max Reitz wrote:
> This patch reworks some places which use either qobject_type() checks
> plus qobject_to(), where the latter alone is sufficient, or NULL checks
> plus qobject_type() checks where we can simply do a qobject_to() != NULL
> check.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": ""
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": "" Max Reitz
@ 2018-01-31 16:22   ` Eric Blake
  2018-02-01 14:18   ` Alberto Garcia
  1 sibling, 0 replies; 18+ messages in thread
From: Eric Blake @ 2018-01-31 16:22 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Alberto Garcia, Kevin Wolf

[-- Attachment #1: Type: text/plain, Size: 528 bytes --]

On 01/20/2018 09:44 AM, Max Reitz wrote:
> We have a clear replacement, so let's deprecate it.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
>  qapi/block-core.json | 4 ++--
>  block.c              | 4 ++++
>  qemu-doc.texi        | 7 +++++++
>  qemu-options.hx      | 4 ++--
>  4 files changed, 15 insertions(+), 4 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/6] block: Handle null backing link
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 5/6] block: Handle null backing link Max Reitz
@ 2018-02-01 14:17   ` Alberto Garcia
  0 siblings, 0 replies; 18+ messages in thread
From: Alberto Garcia @ 2018-02-01 14:17 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Eric Blake, Kevin Wolf

On Sat 20 Jan 2018 04:44:11 PM CET, Max Reitz wrote:
> Instead of converting all "backing": null instances into "backing": "",
> handle a null value directly in bdrv_open_inherit().
>
> This enables explicitly null backing links for json:{} filenames.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": ""
  2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": "" Max Reitz
  2018-01-31 16:22   ` Eric Blake
@ 2018-02-01 14:18   ` Alberto Garcia
  1 sibling, 0 replies; 18+ messages in thread
From: Alberto Garcia @ 2018-02-01 14:18 UTC (permalink / raw)
  To: Max Reitz, qemu-block
  Cc: qemu-devel, Markus Armbruster, Eric Blake, Kevin Wolf

On Sat 20 Jan 2018 04:44:12 PM CET, Max Reitz wrote:
> We have a clear replacement, so let's deprecate it.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2018-02-01 14:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-20 15:44 [Qemu-devel] [PATCH v2 0/6] block: Handle null backing link Max Reitz
2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 1/6] qapi: Add qobject_to() Max Reitz
2018-01-22 15:33   ` Eric Blake
2018-01-22 16:53     ` Max Reitz
2018-01-31 16:02   ` Alberto Garcia
2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 2/6] qapi: Replace qobject_to_X(o) by qobject_to(o, X) Max Reitz
2018-01-31 16:05   ` Alberto Garcia
2018-01-31 16:11   ` Eric Blake
2018-01-31 16:14     ` Eric Blake
2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 3/6] qapi: Remove qobject_to_X() functions Max Reitz
2018-01-31 16:05   ` Alberto Garcia
2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 4/6] qapi: Make more of qobject_to() Max Reitz
2018-01-31 16:16   ` Alberto Garcia
2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 5/6] block: Handle null backing link Max Reitz
2018-02-01 14:17   ` Alberto Garcia
2018-01-20 15:44 ` [Qemu-devel] [PATCH v2 6/6] block: Deprecate "backing": "" Max Reitz
2018-01-31 16:22   ` Eric Blake
2018-02-01 14:18   ` Alberto Garcia

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.