All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type
@ 2017-05-09 17:35 Marc-André Lureau
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field Marc-André Lureau
                   ` (18 more replies)
  0 siblings, 19 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Hi,

In previously sent series "[PATCH 00/21] WIP: dump: add kaslr support
(for after 2.9)", I proposed changes to accept uint64 values from
json, by adding a QUint type. During review, it was suggested to
introduce a QNum type to hold various number representations.

This series introduces the QNum type, adds uint representation to it,
and make uint64 values over json possible (while keeping json negative
int for values >INT64_MAX to unsigned cast compatibility). It also
improves some int vs uint usage for object properties and other
QObject related clean-ups.

The series is on top of http://repo.or.cz/qemu/armbru.git qapi-next

Marc-André Lureau (17):
  qdev: remove PropertyInfo.qtype field
  object: fix potential leak in getters
  tests: remove alt num-int cases
  qapi: merge QInt and QFloat in QNum
  qapi: remove promote_int
  qnum: add uint type
  json: learn to parse uint64 numbers
  qapi: update the qobject visitor to use QUInt
  qnum: fix get_int() with values > INT64_MAX
  object: add uint property setter/getter
  object: use more specific property type names
  qdev: use int and uint properties as appropriate
  qdev: use appropriate getter/setters type
  acpi: fix s3/s4 disabled type
  Use uint property getter/setter where appropriate
  RFC: qdict: add uint
  qobject: move dump_qobject() from block/ to qobject/

 include/qapi/visitor.h                   |   4 +-
 include/qapi/visitor-impl.h              |   2 +-
 scripts/qapi.py                          |  30 ++---
 scripts/qapi-visit.py                    |  12 +-
 include/hw/isa/isa.h                     |   2 +-
 include/hw/qdev-core.h                   |   6 +-
 include/hw/qdev-properties.h             |  72 ++++++------
 include/qapi/qmp/qdict.h                 |  10 +-
 include/qapi/qmp/qfloat.h                |  29 -----
 include/qapi/qmp/qint.h                  |  28 -----
 include/qapi/qmp/qlist.h                 |   4 +-
 include/qapi/qmp/qnum.h                  |  47 ++++++++
 include/qapi/qmp/qobject.h               |   7 ++
 include/qapi/qmp/types.h                 |   3 +-
 include/qapi/qobject-input-visitor.h     |   2 +-
 include/qapi/qobject-output-visitor.h    |   8 +-
 include/qom/object.h                     |  23 ++++
 qapi/qapi-visit-core.c                   |   6 +-
 backends/cryptodev.c                     |   2 +-
 block/blkdebug.c                         |   1 -
 block/nbd.c                              |   1 -
 block/nfs.c                              |   1 -
 block/qapi.c                             |  93 +--------------
 block/quorum.c                           |   1 -
 block/sheepdog.c                         |   1 -
 block/ssh.c                              |   1 -
 block/vvfat.c                            |   1 -
 blockdev.c                               |   5 +-
 hw/acpi/ich9.c                           |  24 ++--
 hw/acpi/memory_hotplug.c                 |  10 +-
 hw/acpi/nvdimm.c                         |  10 +-
 hw/acpi/pcihp.c                          |   7 +-
 hw/acpi/piix4.c                          |   8 +-
 hw/arm/aspeed.c                          |   4 +-
 hw/arm/bcm2835_peripherals.c             |   9 +-
 hw/arm/raspi.c                           |   4 +-
 hw/block/fdc.c                           |  54 ++++-----
 hw/core/platform-bus.c                   |   2 +-
 hw/core/qdev-properties.c                |   8 +-
 hw/core/qdev.c                           |  44 ++++++--
 hw/i386/acpi-build.c                     |  71 ++++++------
 hw/i386/pc.c                             |   6 +-
 hw/i386/xen/xen-hvm.c                    |   6 +-
 hw/intc/arm_gicv3_common.c               |   2 +-
 hw/mem/pc-dimm.c                         |   5 +-
 hw/misc/auxbus.c                         |   2 +-
 hw/misc/pvpanic.c                        |   2 +-
 hw/net/e1000e.c                          |  14 +--
 hw/pci-host/gpex.c                       |   2 +-
 hw/pci-host/piix.c                       |   8 +-
 hw/pci-host/q35.c                        |  12 +-
 hw/pci-host/xilinx-pcie.c                |   2 +-
 hw/ppc/pnv.c                             |   2 +-
 hw/ppc/pnv_core.c                        |   2 +-
 hw/ppc/spapr.c                           |   8 +-
 hw/usb/xen-usb.c                         |   1 -
 monitor.c                                |   2 +-
 net/dump.c                               |   2 +-
 net/filter-buffer.c                      |   2 +-
 numa.c                                   |   6 +-
 qapi/qapi-clone-visitor.c                |   2 +-
 qapi/qapi-dealloc-visitor.c              |   2 +-
 qapi/qobject-input-visitor.c             |  47 ++++----
 qapi/qobject-output-visitor.c            |   7 +-
 qga/commands.c                           |   2 +-
 qga/main.c                               |   1 -
 qobject/json-lexer.c                     |   4 +
 qobject/json-parser.c                    |  42 ++++---
 qobject/qdict.c                          | 106 ++++++++++++++----
 qobject/qfloat.c                         |  62 ----------
 qobject/qint.c                           |  61 ----------
 qobject/qjson.c                          |  37 +-----
 qobject/qlist.c                          |  23 ++++
 qobject/qnum.c                           | 187 +++++++++++++++++++++++++++++++
 qobject/qobject.c                        |  22 +++-
 qom/object.c                             |  60 ++++++++--
 target/i386/cpu.c                        |  12 +-
 tests/check-qdict.c                      |  55 +++++++--
 tests/check-qfloat.c                     |  53 ---------
 tests/check-qint.c                       |  87 --------------
 tests/check-qjson.c                      | 131 +++++++++++++++-------
 tests/check-qlist.c                      |  15 +--
 tests/check-qnum.c                       | 182 ++++++++++++++++++++++++++++++
 tests/test-keyval.c                      |   4 -
 tests/test-qmp-commands.c                |   6 +-
 tests/test-qmp-event.c                   |   7 +-
 tests/test-qobject-input-visitor.c       |  65 +++--------
 tests/test-qobject-output-visitor.c      |  73 +++++++-----
 tests/test-x86-cpuid-compat.c            |  13 +--
 ui/console.c                             |   4 +-
 ui/spice-core.c                          |   1 -
 ui/vnc-enc-tight.c                       |   1 -
 util/qemu-option.c                       |  20 +---
 MAINTAINERS                              |   3 +-
 qapi/trace-events                        |   2 +-
 qobject/Makefile.objs                    |   2 +-
 scripts/coccinelle/qobject.cocci         |   4 +-
 tests/.gitignore                         |   3 +-
 tests/Makefile.include                   |  13 +--
 tests/qapi-schema/comments.out           |   2 +-
 tests/qapi-schema/doc-good.out           |   2 +-
 tests/qapi-schema/empty.out              |   2 +-
 tests/qapi-schema/event-case.out         |   2 +-
 tests/qapi-schema/ident-with-escape.out  |   2 +-
 tests/qapi-schema/include-relpath.out    |   2 +-
 tests/qapi-schema/include-repetition.out |   2 +-
 tests/qapi-schema/include-simple.out     |   2 +-
 tests/qapi-schema/indented-expr.out      |   2 +-
 tests/qapi-schema/qapi-schema-test.json  |   2 -
 tests/qapi-schema/qapi-schema-test.out   |  10 +-
 110 files changed, 1211 insertions(+), 983 deletions(-)
 delete mode 100644 include/qapi/qmp/qfloat.h
 delete mode 100644 include/qapi/qmp/qint.h
 create mode 100644 include/qapi/qmp/qnum.h
 delete mode 100644 qobject/qfloat.c
 delete mode 100644 qobject/qint.c
 create mode 100644 qobject/qnum.c
 delete mode 100644 tests/check-qfloat.c
 delete mode 100644 tests/check-qint.c
 create mode 100644 tests/check-qnum.c

-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-09 18:40   ` Eric Blake
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters Marc-André Lureau
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Remove dependency on qapi qtype, replace a field by a few helper
functions to determine the default value type (introduced in commit
4f2d3d7).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/hw/qdev-core.h       |  1 -
 include/hw/qdev-properties.h |  5 -----
 hw/core/qdev.c               | 32 ++++++++++++++++++++++++++------
 3 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 4bf86b0ad8..0f21a500cd 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -225,7 +225,6 @@ struct Property {
     PropertyInfo *info;
     ptrdiff_t    offset;
     uint8_t      bitnr;
-    QType        qtype;
     int64_t      defval;
     int          arrayoffset;
     PropertyInfo *arrayinfo;
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 1d69fa7a8f..16d5d0629b 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -42,7 +42,6 @@ extern PropertyInfo qdev_prop_arraylen;
         .info      = &(_prop),                                          \
         .offset    = offsetof(_state, _field)                           \
             + type_check(_type,typeof_field(_state, _field)),           \
-        .qtype     = QTYPE_QINT,                                        \
         .defval    = (_type)_defval,                                    \
         }
 #define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
@@ -51,7 +50,6 @@ extern PropertyInfo qdev_prop_arraylen;
         .bitnr    = (_bit),                                      \
         .offset    = offsetof(_state, _field)                    \
             + type_check(uint32_t,typeof_field(_state, _field)), \
-        .qtype     = QTYPE_QBOOL,                                \
         .defval    = (bool)_defval,                              \
         }
 #define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) {       \
@@ -60,7 +58,6 @@ extern PropertyInfo qdev_prop_arraylen;
         .bitnr    = (_bit),                                             \
         .offset    = offsetof(_state, _field)                           \
             + type_check(uint64_t, typeof_field(_state, _field)),       \
-        .qtype     = QTYPE_QBOOL,                                       \
         .defval    = (bool)_defval,                                     \
         }
 
@@ -69,7 +66,6 @@ extern PropertyInfo qdev_prop_arraylen;
         .info      = &(qdev_prop_bool),                          \
         .offset    = offsetof(_state, _field)                    \
             + type_check(bool, typeof_field(_state, _field)),    \
-        .qtype     = QTYPE_QBOOL,                                \
         .defval    = (bool)_defval,                              \
         }
 
@@ -105,7 +101,6 @@ extern PropertyInfo qdev_prop_arraylen;
         .info = &(qdev_prop_arraylen),                                  \
         .offset = offsetof(_state, _field)                              \
             + type_check(uint32_t, typeof_field(_state, _field)),       \
-        .qtype = QTYPE_QINT,                                            \
         .arrayinfo = &(_arrayprop),                                     \
         .arrayfieldsize = sizeof(_arraytype),                           \
         .arrayoffset = offsetof(_state, _arrayfield),                   \
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 02b632f6b3..83b0297755 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -755,6 +755,30 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
     g_free(name);
 }
 
+static bool prop_info_is_bool(const PropertyInfo *info)
+{
+    return info == &qdev_prop_bit
+        || info == &qdev_prop_bit64
+        || info == &qdev_prop_bool;
+}
+
+static bool prop_info_is_int(const PropertyInfo *info)
+{
+    return info == &qdev_prop_uint8
+        || info == &qdev_prop_uint16
+        || info == &qdev_prop_uint32
+        || info == &qdev_prop_int32
+        || info == &qdev_prop_uint64
+        || info == &qdev_prop_size
+        || info == &qdev_prop_pci_devfn
+        || info == &qdev_prop_on_off_auto
+        || info == &qdev_prop_losttickpolicy
+        || info == &qdev_prop_blockdev_on_error
+        || info == &qdev_prop_bios_chs_trans
+        || info == &qdev_prop_blocksize
+        || info == &qdev_prop_arraylen;
+}
+
 /**
  * qdev_property_add_static:
  * @dev: Device to add the property to.
@@ -794,16 +818,12 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
                                     prop->info->description,
                                     &error_abort);
 
-    if (prop->qtype == QTYPE_NONE) {
-        return;
-    }
-
-    if (prop->qtype == QTYPE_QBOOL) {
+    if (prop_info_is_bool(prop->info)) {
         object_property_set_bool(obj, prop->defval, prop->name, &error_abort);
     } else if (prop->info->enum_table) {
         object_property_set_str(obj, prop->info->enum_table[prop->defval],
                                 prop->name, &error_abort);
-    } else if (prop->qtype == QTYPE_QINT) {
+    } else if (prop_info_is_int(prop->info)) {
         object_property_set_int(obj, prop->defval, prop->name, &error_abort);
     }
 }
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-09 18:44   ` Eric Blake
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases Marc-André Lureau
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

If the property is not of the requested type, the getters will leak a
QObject.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qom/object.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/qom/object.c b/qom/object.c
index eb4bc924ff..c7b8079df6 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1122,7 +1122,7 @@ char *object_property_get_str(Object *obj, const char *name,
         retval = g_strdup(qstring_get_str(qstring));
     }
 
-    QDECREF(qstring);
+    qobject_decref(ret);
     return retval;
 }
 
@@ -1183,7 +1183,7 @@ bool object_property_get_bool(Object *obj, const char *name,
         retval = qbool_get_bool(qbool);
     }
 
-    QDECREF(qbool);
+    qobject_decref(ret);
     return retval;
 }
 
@@ -1214,7 +1214,7 @@ int64_t object_property_get_int(Object *obj, const char *name,
         retval = qint_get_int(qint);
     }
 
-    QDECREF(qint);
+    qobject_decref(ret);
     return retval;
 }
 
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field Marc-André Lureau
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-09 18:51   ` Eric Blake
  2017-05-22 17:03   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
                   ` (15 subsequent siblings)
  18 siblings, 2 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

There are no real users of this case, and it's going to be invalid after
merging of QFloat and QInt use the same QNum type in the following patch.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/test-keyval.c                     |  3 ---
 tests/test-qobject-input-visitor.c      | 26 --------------------------
 tests/qapi-schema/qapi-schema-test.json |  2 --
 tests/qapi-schema/qapi-schema-test.out  |  8 --------
 4 files changed, 39 deletions(-)

diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index c556b1b117..df0ff831b5 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -615,7 +615,6 @@ static void test_keyval_visit_alternate(void)
     Visitor *v;
     QDict *qdict;
     AltNumStr *ans;
-    AltNumInt *ani;
 
     /*
      * Can't do scalar alternate variants other than string.  You get
@@ -629,8 +628,6 @@ static void test_keyval_visit_alternate(void)
     g_assert_cmpint(ans->type, ==, QTYPE_QSTRING);
     g_assert_cmpstr(ans->u.s, ==, "1");
     qapi_free_AltNumStr(ans);
-    visit_type_AltNumInt(v, "a", &ani, &err);
-    error_free_or_abort(&err);
     visit_end_struct(v, NULL);
     visit_free(v);
 }
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index f965743b6e..a30e2d5e95 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -586,8 +586,6 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
     AltStrNum *asn;
     AltNumStr *ans;
     AltStrInt *asi;
-    AltIntNum *ain;
-    AltNumInt *ani;
 
     /* Parsing an int */
 
@@ -614,18 +612,6 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
     g_assert_cmpint(asi->u.i, ==, 42);
     qapi_free_AltStrInt(asi);
 
-    v = visitor_input_test_init(data, "42");
-    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
-    g_assert_cmpint(ain->type, ==, QTYPE_QINT);
-    g_assert_cmpint(ain->u.i, ==, 42);
-    qapi_free_AltIntNum(ain);
-
-    v = visitor_input_test_init(data, "42");
-    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
-    g_assert_cmpint(ani->type, ==, QTYPE_QINT);
-    g_assert_cmpint(ani->u.i, ==, 42);
-    qapi_free_AltNumInt(ani);
-
     /* Parsing a double */
 
     v = visitor_input_test_init(data, "42.5");
@@ -649,18 +635,6 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
     visit_type_AltStrInt(v, NULL, &asi, &err);
     error_free_or_abort(&err);
     qapi_free_AltStrInt(asi);
-
-    v = visitor_input_test_init(data, "42.5");
-    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
-    g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
-    g_assert_cmpfloat(ain->u.n, ==, 42.5);
-    qapi_free_AltIntNum(ain);
-
-    v = visitor_input_test_init(data, "42.5");
-    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
-    g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
-    g_assert_cmpfloat(ani->u.n, ==, 42.5);
-    qapi_free_AltNumInt(ani);
 }
 
 static void test_native_list_integer_helper(TestInputVisitorData *data,
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 842ea3c5e3..9ad09e3758 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -103,8 +103,6 @@
 { 'alternate': 'AltStrNum', 'data': { 's': 'str', 'n': 'number' } }
 { 'alternate': 'AltNumStr', 'data': { 'n': 'number', 's': 'str' } }
 { 'alternate': 'AltStrInt', 'data': { 's': 'str', 'i': 'int' } }
-{ 'alternate': 'AltIntNum', 'data': { 'i': 'int', 'n': 'number' } }
-{ 'alternate': 'AltNumInt', 'data': { 'n': 'number', 'i': 'int' } }
 
 # for testing native lists
 { 'union': 'UserDefNativeListUnion',
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 9d99c4eebb..5c6655a5c3 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -1,11 +1,3 @@
-alternate AltIntNum
-    tag type
-    case i: int
-    case n: number
-alternate AltNumInt
-    tag type
-    case n: number
-    case i: int
 alternate AltNumStr
     tag type
     case n: number
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (2 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-11 14:29   ` Markus Armbruster
                     ` (2 more replies)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 05/17] qapi: remove promote_int Marc-André Lureau
                   ` (14 subsequent siblings)
  18 siblings, 3 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

We would like to use a same QObject type to represent numbers, whether
they are int, uint, or floats. getters will allow some compatibility
between the various types if the number fits other representations

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                          |  30 +++----
 scripts/qapi-visit.py                    |   2 +-
 include/qapi/qmp/qdict.h                 |   3 +-
 include/qapi/qmp/qfloat.h                |  29 -------
 include/qapi/qmp/qint.h                  |  28 -------
 include/qapi/qmp/qlist.h                 |   2 +-
 include/qapi/qmp/qnum.h                  |  43 ++++++++++
 include/qapi/qmp/types.h                 |   3 +-
 include/qapi/qobject-input-visitor.h     |   2 +-
 include/qapi/qobject-output-visitor.h    |   8 +-
 block/blkdebug.c                         |   1 -
 block/nbd.c                              |   1 -
 block/nfs.c                              |   1 -
 block/qapi.c                             |  13 ++-
 block/quorum.c                           |   1 -
 block/sheepdog.c                         |   1 -
 block/ssh.c                              |   1 -
 block/vvfat.c                            |   1 -
 blockdev.c                               |   5 +-
 hw/acpi/pcihp.c                          |   1 -
 hw/i386/acpi-build.c                     |  15 ++--
 hw/usb/xen-usb.c                         |   1 -
 monitor.c                                |   2 +-
 qapi/qobject-input-visitor.c             |  36 +++-----
 qapi/qobject-output-visitor.c            |   6 +-
 qga/commands.c                           |   2 +-
 qga/main.c                               |   1 -
 qobject/json-parser.c                    |  18 ++--
 qobject/qdict.c                          |  38 ++++-----
 qobject/qfloat.c                         |  62 --------------
 qobject/qint.c                           |  61 --------------
 qobject/qjson.c                          |  37 +--------
 qobject/qnum.c                           | 138 +++++++++++++++++++++++++++++++
 qobject/qobject.c                        |   3 +-
 qom/object.c                             |  21 +++--
 target/i386/cpu.c                        |   6 +-
 tests/check-qdict.c                      |  23 +++---
 tests/check-qfloat.c                     |  53 ------------
 tests/check-qint.c                       |  87 -------------------
 tests/check-qjson.c                      |  84 +++++++++----------
 tests/check-qlist.c                      |  15 ++--
 tests/check-qnum.c                       | 131 +++++++++++++++++++++++++++++
 tests/test-keyval.c                      |   1 -
 tests/test-qmp-commands.c                |   6 +-
 tests/test-qmp-event.c                   |   7 +-
 tests/test-qobject-input-visitor.c       |  30 +++----
 tests/test-qobject-output-visitor.c      |  56 ++++++-------
 tests/test-x86-cpuid-compat.c            |  13 ++-
 ui/spice-core.c                          |   1 -
 ui/vnc-enc-tight.c                       |   1 -
 util/qemu-option.c                       |  20 ++---
 MAINTAINERS                              |   3 +-
 qobject/Makefile.objs                    |   2 +-
 scripts/coccinelle/qobject.cocci         |   4 +-
 tests/.gitignore                         |   3 +-
 tests/Makefile.include                   |  13 ++-
 tests/qapi-schema/comments.out           |   2 +-
 tests/qapi-schema/doc-good.out           |   2 +-
 tests/qapi-schema/empty.out              |   2 +-
 tests/qapi-schema/event-case.out         |   2 +-
 tests/qapi-schema/ident-with-escape.out  |   2 +-
 tests/qapi-schema/include-relpath.out    |   2 +-
 tests/qapi-schema/include-repetition.out |   2 +-
 tests/qapi-schema/include-simple.out     |   2 +-
 tests/qapi-schema/indented-expr.out      |   2 +-
 tests/qapi-schema/qapi-schema-test.out   |   2 +-
 66 files changed, 557 insertions(+), 639 deletions(-)
 delete mode 100644 include/qapi/qmp/qfloat.h
 delete mode 100644 include/qapi/qmp/qint.h
 create mode 100644 include/qapi/qmp/qnum.h
 delete mode 100644 qobject/qfloat.c
 delete mode 100644 qobject/qint.c
 create mode 100644 qobject/qnum.c
 delete mode 100644 tests/check-qfloat.c
 delete mode 100644 tests/check-qint.c
 create mode 100644 tests/check-qnum.c

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 6c4d554165..01fd0027a5 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -21,18 +21,18 @@ from ordereddict import OrderedDict
 
 builtin_types = {
     'str':      'QTYPE_QSTRING',
-    'int':      'QTYPE_QINT',
-    'number':   'QTYPE_QFLOAT',
+    'int':      'QTYPE_QNUM',
+    'number':   'QTYPE_QNUM',
     'bool':     'QTYPE_QBOOL',
-    'int8':     'QTYPE_QINT',
-    'int16':    'QTYPE_QINT',
-    'int32':    'QTYPE_QINT',
-    'int64':    'QTYPE_QINT',
-    'uint8':    'QTYPE_QINT',
-    'uint16':   'QTYPE_QINT',
-    'uint32':   'QTYPE_QINT',
-    'uint64':   'QTYPE_QINT',
-    'size':     'QTYPE_QINT',
+    'int8':     'QTYPE_QNUM',
+    'int16':    'QTYPE_QNUM',
+    'int32':    'QTYPE_QNUM',
+    'int64':    'QTYPE_QNUM',
+    'uint8':    'QTYPE_QNUM',
+    'uint16':   'QTYPE_QNUM',
+    'uint32':   'QTYPE_QNUM',
+    'uint64':   'QTYPE_QNUM',
+    'size':     'QTYPE_QNUM',
     'any':      None,           # any QType possible, actually
     'QType':    'QTYPE_QSTRING',
 }
@@ -1044,8 +1044,8 @@ class QAPISchemaType(QAPISchemaEntity):
     def alternate_qtype(self):
         json2qtype = {
             'string':  'QTYPE_QSTRING',
-            'number':  'QTYPE_QFLOAT',
-            'int':     'QTYPE_QINT',
+            'number':  'QTYPE_QNUM',
+            'int':     'QTYPE_QNUM',
             'boolean': 'QTYPE_QBOOL',
             'object':  'QTYPE_QDICT'
         }
@@ -1507,9 +1507,9 @@ class QAPISchema(object):
         self.the_empty_object_type = QAPISchemaObjectType(
             'q_empty', None, None, None, [], None)
         self._def_entity(self.the_empty_object_type)
-        qtype_values = self._make_enum_members(['none', 'qnull', 'qint',
+        qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
                                                 'qstring', 'qdict', 'qlist',
-                                                'qfloat', 'qbool'])
+                                                'qbool'])
         self._def_entity(QAPISchemaEnumType('QType', None, None,
                                             qtype_values, 'QTYPE'))
 
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 5737aefa05..cc447ecacc 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -164,7 +164,7 @@ def gen_visit_alternate(name, variants):
     promote_int = 'true'
     ret = ''
     for var in variants.variants:
-        if var.type.alternate_qtype() == 'QTYPE_QINT':
+        if var.type.alternate_qtype() == 'QTYPE_QNUM':
             promote_int = 'false'
 
     ret += mcgen('''
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 188440a6a8..363e431106 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -15,6 +15,7 @@
 
 #include "qapi/qmp/qobject.h"
 #include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qnum.h"
 #include "qemu/queue.h"
 
 #define QDICT_BUCKET_MAX 512
@@ -54,7 +55,7 @@ void qdict_destroy_obj(QObject *obj);
 
 /* Helpers for int, bool, and string */
 #define qdict_put_int(qdict, key, value) \
-        qdict_put(qdict, key, qint_from_int(value))
+        qdict_put(qdict, key, qnum_from_int(value))
 #define qdict_put_bool(qdict, key, value) \
         qdict_put(qdict, key, qbool_from_bool(value))
 #define qdict_put_str(qdict, key, value) \
diff --git a/include/qapi/qmp/qfloat.h b/include/qapi/qmp/qfloat.h
deleted file mode 100644
index b5d15836b5..0000000000
--- a/include/qapi/qmp/qfloat.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * QFloat Module
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#ifndef QFLOAT_H
-#define QFLOAT_H
-
-#include "qapi/qmp/qobject.h"
-
-typedef struct QFloat {
-    QObject base;
-    double value;
-} QFloat;
-
-QFloat *qfloat_from_double(double value);
-double qfloat_get_double(const QFloat *qi);
-QFloat *qobject_to_qfloat(const QObject *obj);
-void qfloat_destroy_obj(QObject *obj);
-
-#endif /* QFLOAT_H */
diff --git a/include/qapi/qmp/qint.h b/include/qapi/qmp/qint.h
deleted file mode 100644
index 3aaff768dd..0000000000
--- a/include/qapi/qmp/qint.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * QInt Module
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef QINT_H
-#define QINT_H
-
-#include "qapi/qmp/qobject.h"
-
-typedef struct QInt {
-    QObject base;
-    int64_t value;
-} QInt;
-
-QInt *qint_from_int(int64_t value);
-int64_t qint_get_int(const QInt *qi);
-QInt *qobject_to_qint(const QObject *obj);
-void qint_destroy_obj(QObject *obj);
-
-#endif /* QINT_H */
diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
index 5dc4ed9616..2f2c199632 100644
--- a/include/qapi/qmp/qlist.h
+++ b/include/qapi/qmp/qlist.h
@@ -31,7 +31,7 @@ typedef struct QList {
 
 /* Helpers for int, bool, and string */
 #define qlist_append_int(qlist, value) \
-        qlist_append(qlist, qint_from_int(value))
+        qlist_append(qlist, qnum_from_int(value))
 #define qlist_append_bool(qlist, value) \
         qlist_append(qlist, qbool_from_bool(value))
 #define qlist_append_str(qlist, value) \
diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h
new file mode 100644
index 0000000000..0e51427821
--- /dev/null
+++ b/include/qapi/qmp/qnum.h
@@ -0,0 +1,43 @@
+/*
+ * QNum Module
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef QNUM_H
+#define QNUM_H
+
+#include "qapi/qmp/qobject.h"
+
+typedef enum {
+    QNUM_I64,
+    QNUM_DOUBLE
+} QNumType;
+
+typedef struct QNum {
+    QObject base;
+    QNumType type;
+    union {
+        int64_t i64;
+        double dbl;
+    } u;
+} QNum;
+
+QNum *qnum_from_int(int64_t value);
+QNum *qnum_from_double(double value);
+
+int64_t qnum_get_int(const QNum *qi, Error **errp);
+double qnum_get_double(QNum *qn);
+
+char *qnum_to_string(QNum *qn);
+
+QNum *qobject_to_qnum(const QObject *obj);
+void qnum_destroy_obj(QObject *obj);
+
+#endif /* QNUM_H */
diff --git a/include/qapi/qmp/types.h b/include/qapi/qmp/types.h
index 27cfbd84e5..a4bc662bfb 100644
--- a/include/qapi/qmp/types.h
+++ b/include/qapi/qmp/types.h
@@ -14,8 +14,7 @@
 #define QAPI_QMP_TYPES_H
 
 #include "qapi/qmp/qobject.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qfloat.h"
+#include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qmp/qdict.h"
diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-input-visitor.h
index b399285c43..5a6fe83f8f 100644
--- a/include/qapi/qobject-input-visitor.h
+++ b/include/qapi/qobject-input-visitor.h
@@ -30,7 +30,7 @@ typedef struct QObjectInputVisitor QObjectInputVisitor;
  * visit_type_FOO() creates an instance of QAPI type FOO.  The visited
  * QObject must match FOO.  QDict matches struct/union types, QList
  * matches list types, QString matches type 'str' and enumeration
- * types, QInt matches integer types, QFloat matches type 'number',
+ * types, QNum matches integer and float types,
  * QBool matches type 'bool'.  Type 'any' is matched by QObject.  A
  * QAPI alternate type is matched when one of its member types is.
  *
diff --git a/include/qapi/qobject-output-visitor.h b/include/qapi/qobject-output-visitor.h
index 9b990c318e..e5a3490812 100644
--- a/include/qapi/qobject-output-visitor.h
+++ b/include/qapi/qobject-output-visitor.h
@@ -28,10 +28,10 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor;
  *
  * visit_type_FOO() creates a QObject for QAPI type FOO.  It creates a
  * QDict for struct/union types, a QList for list types, QString for
- * type 'str' and enumeration types, QInt for integer types, QFloat
- * for type 'number', QBool for type 'bool'.  For type 'any', it
- * increments the QObject's reference count.  For QAPI alternate
- * types, it creates the QObject for the member that is in use.
+ * type 'str' and enumeration types, QNum for integer and float
+ * types, QBool for type 'bool'.  For type 'any', it increments the
+ * QObject's reference count.  For QAPI alternate types, it creates
+ * the QObject for the member that is in use.
  *
  * visit_start_struct() ... visit_end_struct() visits a QAPI
  * struct/union and creates a QDict.  Visits in between visit the
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 3c088934db..b3032c3ad7 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -30,7 +30,6 @@
 #include "qemu/module.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 #include "sysemu/qtest.h"
 
diff --git a/block/nbd.c b/block/nbd.c
index 975faab2c5..e946ea944d 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -37,7 +37,6 @@
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qjson.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 #include "qemu/cutils.h"
 
diff --git a/block/nfs.c b/block/nfs.c
index 848b2c0bb0..decefd15f1 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -36,7 +36,6 @@
 #include "qemu/cutils.h"
 #include "sysemu/sysemu.h"
 #include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi-visit.h"
 #include "qapi/qobject-input-visitor.h"
diff --git a/block/qapi.c b/block/qapi.c
index a40922ea26..2050df29e4 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -595,9 +595,11 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
                          int comp_indent, QObject *obj)
 {
     switch (qobject_type(obj)) {
-        case QTYPE_QINT: {
-            QInt *value = qobject_to_qint(obj);
-            func_fprintf(f, "%" PRId64, qint_get_int(value));
+        case QTYPE_QNUM: {
+            QNum *value = qobject_to_qnum(obj);
+            char *tmp = qnum_to_string(value);
+            func_fprintf(f, "%s", tmp);
+            g_free(tmp);
             break;
         }
         case QTYPE_QSTRING: {
@@ -615,11 +617,6 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
             dump_qlist(func_fprintf, f, comp_indent, value);
             break;
         }
-        case QTYPE_QFLOAT: {
-            QFloat *value = qobject_to_qfloat(obj);
-            func_fprintf(f, "%g", qfloat_get_double(value));
-            break;
-        }
         case QTYPE_QBOOL: {
             QBool *value = qobject_to_qbool(obj);
             func_fprintf(f, "%s", qbool_get_bool(value) ? "true" : "false");
diff --git a/block/quorum.c b/block/quorum.c
index 1b2a8c3937..55ba916655 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -19,7 +19,6 @@
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/qlist.h"
 #include "qapi/qmp/qstring.h"
diff --git a/block/sheepdog.c b/block/sheepdog.c
index a18315a1ca..dea9000bdd 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -16,7 +16,6 @@
 #include "qapi-visit.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qemu/uri.h"
 #include "qemu/error-report.h"
diff --git a/block/ssh.c b/block/ssh.c
index 11203fc5a2..bac3453c3e 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -34,7 +34,6 @@
 #include "qemu/sockets.h"
 #include "qemu/uri.h"
 #include "qapi-visit.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-output-visitor.h"
diff --git a/block/vvfat.c b/block/vvfat.c
index 9c82371360..6089bba774 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -29,7 +29,6 @@
 #include "qemu/module.h"
 #include "qemu/bswap.h"
 #include "migration/migration.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qstring.h"
 #include "qemu/cutils.h"
diff --git a/blockdev.c b/blockdev.c
index 0b38c3df71..ed9b839dd2 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -334,8 +334,9 @@ static bool parse_stats_intervals(BlockAcctStats *stats, QList *intervals,
             break;
         }
 
-        case QTYPE_QINT: {
-            int64_t length = qint_get_int(qobject_to_qint(entry->value));
+        case QTYPE_QNUM: {
+            int64_t length = qnum_get_int(qobject_to_qnum(entry->value),
+                                          &error_abort);
             if (length > 0 && length <= UINT_MAX) {
                 block_acct_add_interval(stats, (unsigned) length);
             } else {
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 2b0f3e1bfb..3a531a4416 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -37,7 +37,6 @@
 #include "hw/pci/pci_bus.h"
 #include "qapi/error.h"
 #include "qom/qom-qobject.h"
-#include "qapi/qmp/qint.h"
 
 //#define DEBUG
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 2073108577..ec3ae7fa85 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -57,7 +57,6 @@
 
 #include "hw/acpi/aml-build.h"
 
-#include "qapi/qmp/qint.h"
 #include "qom/qom-qobject.h"
 #include "hw/i386/amd_iommu.h"
 #include "hw/i386/intel_iommu.h"
@@ -150,21 +149,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 = qint_get_int(qobject_to_qint(o));
+        pm->s3_disabled = qnum_get_int(qobject_to_qnum(o), &error_abort);
     } 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 = qint_get_int(qobject_to_qint(o));
+        pm->s4_disabled = qnum_get_int(qobject_to_qnum(o), &error_abort);
     } 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 = qint_get_int(qobject_to_qint(o));
+        pm->s4_val = qnum_get_int(qobject_to_qnum(o), &error_abort);
     } else {
         pm->s4_val = false;
     }
@@ -500,7 +499,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) {
-        int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
+        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
 
         aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
         notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
@@ -610,7 +609,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) {
-        int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
+        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
         aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
         aml_append(method,
             aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
@@ -2586,12 +2585,12 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
     if (!o) {
         return false;
     }
-    mcfg->mcfg_base = qint_get_int(qobject_to_qint(o));
+    mcfg->mcfg_base = qnum_get_int(qobject_to_qnum(o), &error_abort);
     qobject_decref(o);
 
     o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
     assert(o);
-    mcfg->mcfg_size = qint_get_int(qobject_to_qint(o));
+    mcfg->mcfg_size = qnum_get_int(qobject_to_qnum(o), &error_abort);
     qobject_decref(o);
     return true;
 }
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index fe62183fe3..584a6f2442 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -30,7 +30,6 @@
 #include "hw/xen/xen_backend.h"
 #include "monitor/qdev.h"
 #include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 
 #include "hw/xen/io/ring.h"
diff --git a/monitor.c b/monitor.c
index 078cba5c86..7a640f0f65 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2972,7 +2972,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
                     monitor_printf(mon, "Unknown unit suffix\n");
                     goto fail;
                 }
-                qdict_put(qdict, key, qfloat_from_double(val));
+                qdict_put(qdict, key, qnum_from_double(val));
             }
             break;
         case 'b':
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index d0f0002317..78425a4369 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -377,9 +377,6 @@ static void qobject_input_start_alternate(Visitor *v, const char *name,
     }
     *obj = g_malloc0(size);
     (*obj)->type = qobject_type(qobj);
-    if (promote_int && (*obj)->type == QTYPE_QINT) {
-        (*obj)->type = QTYPE_QFLOAT;
-    }
 }
 
 static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
@@ -387,19 +384,19 @@ static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
 {
     QObjectInputVisitor *qiv = to_qiv(v);
     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
-    QInt *qint;
+    QNum *qnum;
 
     if (!qobj) {
         return;
     }
-    qint = qobject_to_qint(qobj);
-    if (!qint) {
+    qnum = qobject_to_qnum(qobj);
+    if (!qnum) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                    full_name(qiv, name), "integer");
         return;
     }
 
-    *obj = qint_get_int(qint);
+    *obj = qnum_get_int(qnum, errp);
 }
 
 
@@ -423,22 +420,22 @@ static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
 static void qobject_input_type_uint64(Visitor *v, const char *name,
                                       uint64_t *obj, Error **errp)
 {
-    /* FIXME: qobject_to_qint mishandles values over INT64_MAX */
+    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
     QObjectInputVisitor *qiv = to_qiv(v);
     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
-    QInt *qint;
+    QNum *qnum;
 
     if (!qobj) {
         return;
     }
-    qint = qobject_to_qint(qobj);
-    if (!qint) {
+    qnum = qobject_to_qnum(qobj);
+    if (!qnum) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                    full_name(qiv, name), "integer");
         return;
     }
 
-    *obj = qint_get_int(qint);
+    *obj = qnum_get_int(qnum, errp);
 }
 
 static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
@@ -533,21 +530,14 @@ static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
 {
     QObjectInputVisitor *qiv = to_qiv(v);
     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
-    QInt *qint;
-    QFloat *qfloat;
+    QNum *qnum;
 
     if (!qobj) {
         return;
     }
-    qint = qobject_to_qint(qobj);
-    if (qint) {
-        *obj = qint_get_int(qobject_to_qint(qobj));
-        return;
-    }
-
-    qfloat = qobject_to_qfloat(qobj);
-    if (qfloat) {
-        *obj = qfloat_get_double(qobject_to_qfloat(qobj));
+    qnum = qobject_to_qnum(qobj);
+    if (qnum) {
+        *obj = qnum_get_double(qnum);
         return;
     }
 
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
index 871127079d..2ca5093b22 100644
--- a/qapi/qobject-output-visitor.c
+++ b/qapi/qobject-output-visitor.c
@@ -144,7 +144,7 @@ static void qobject_output_type_int64(Visitor *v, const char *name,
                                       int64_t *obj, Error **errp)
 {
     QObjectOutputVisitor *qov = to_qov(v);
-    qobject_output_add(qov, name, qint_from_int(*obj));
+    qobject_output_add(qov, name, qnum_from_int(*obj));
 }
 
 static void qobject_output_type_uint64(Visitor *v, const char *name,
@@ -152,7 +152,7 @@ static void qobject_output_type_uint64(Visitor *v, const char *name,
 {
     /* FIXME values larger than INT64_MAX become negative */
     QObjectOutputVisitor *qov = to_qov(v);
-    qobject_output_add(qov, name, qint_from_int(*obj));
+    qobject_output_add(qov, name, qnum_from_int(*obj));
 }
 
 static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
@@ -177,7 +177,7 @@ static void qobject_output_type_number(Visitor *v, const char *name,
                                        double *obj, Error **errp)
 {
     QObjectOutputVisitor *qov = to_qov(v);
-    qobject_output_add(qov, name, qfloat_from_double(*obj));
+    qobject_output_add(qov, name, qnum_from_double(*obj));
 }
 
 static void qobject_output_type_any(Visitor *v, const char *name,
diff --git a/qga/commands.c b/qga/commands.c
index 3333ed50b2..ff89e805cf 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -485,7 +485,7 @@ int ga_parse_whence(GuestFileWhence *whence, Error **errp)
 {
     /* Exploit the fact that we picked values to match QGA_SEEK_*. */
     if (whence->type == QTYPE_QSTRING) {
-        whence->type = QTYPE_QINT;
+        whence->type = QTYPE_QNUM;
         whence->u.value = whence->u.name;
     }
     switch (whence->u.value) {
diff --git a/qga/main.c b/qga/main.c
index cc58d2b53d..405c1290f8 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -19,7 +19,6 @@
 #endif
 #include "qapi/qmp/json-streamer.h"
 #include "qapi/qmp/json-parser.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qjson.h"
 #include "qga/guest-agent-core.h"
 #include "qemu/module.h"
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index c18e48ab94..f431854ba1 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -466,16 +466,16 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
     } else if (!strcmp(token->str, "%i")) {
         return QOBJECT(qbool_from_bool(va_arg(*ap, int)));
     } else if (!strcmp(token->str, "%d")) {
-        return QOBJECT(qint_from_int(va_arg(*ap, int)));
+        return QOBJECT(qnum_from_int(va_arg(*ap, int)));
     } else if (!strcmp(token->str, "%ld")) {
-        return QOBJECT(qint_from_int(va_arg(*ap, long)));
+        return QOBJECT(qnum_from_int(va_arg(*ap, long)));
     } else if (!strcmp(token->str, "%lld") ||
                !strcmp(token->str, "%I64d")) {
-        return QOBJECT(qint_from_int(va_arg(*ap, long long)));
+        return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
     } else if (!strcmp(token->str, "%s")) {
         return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
     } else if (!strcmp(token->str, "%f")) {
-        return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
+        return QOBJECT(qnum_from_double(va_arg(*ap, double)));
     }
     return NULL;
 }
@@ -494,12 +494,12 @@ static QObject *parse_literal(JSONParserContext *ctxt)
         /* A possibility exists that this is a whole-valued float where the
          * fractional part was left out due to being 0 (.0). It's not a big
          * deal to treat these as ints in the parser, so long as users of the
-         * resulting QObject know to expect a QInt in place of a QFloat in
+         * resulting QObject know to expect a QNum in place of a QNum in
          * cases like these.
          *
          * However, in some cases these values will overflow/underflow a
-         * QInt/int64 container, thus we should assume these are to be handled
-         * as QFloats/doubles rather than silently changing their values.
+         * QNum/int64 container, thus we should assume these are to be handled
+         * as QNums/doubles rather than silently changing their values.
          *
          * strtoll() indicates these instances by setting errno to ERANGE
          */
@@ -508,7 +508,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
         errno = 0; /* strtoll doesn't set errno on success */
         value = strtoll(token->str, NULL, 10);
         if (errno != ERANGE) {
-            return QOBJECT(qint_from_int(value));
+            return QOBJECT(qnum_from_int(value));
         }
         /* fall through to JSON_FLOAT */
     }
@@ -516,7 +516,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
         /* FIXME dependent on locale; a pervasive issue in QEMU */
         /* FIXME our lexer matches RFC 7159 in forbidding Inf or NaN,
          * but those might be useful extensions beyond JSON */
-        return QOBJECT(qfloat_from_double(strtod(token->str, NULL)));
+        return QOBJECT(qnum_from_double(strtod(token->str, NULL)));
     default:
         abort();
     }
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 88e2ecd658..ad5bab9572 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -11,8 +11,7 @@
  */
 
 #include "qemu/osdep.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qfloat.h"
+#include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qstring.h"
@@ -180,37 +179,26 @@ size_t qdict_size(const QDict *qdict)
 /**
  * qdict_get_double(): Get an number mapped by 'key'
  *
- * This function assumes that 'key' exists and it stores a
- * QFloat or QInt object.
+ * This function assumes that 'key' exists and it stores a QNum.
  *
  * Return number mapped by 'key'.
  */
 double qdict_get_double(const QDict *qdict, const char *key)
 {
-    QObject *obj = qdict_get(qdict, key);
-
-    assert(obj);
-    switch (qobject_type(obj)) {
-    case QTYPE_QFLOAT:
-        return qfloat_get_double(qobject_to_qfloat(obj));
-    case QTYPE_QINT:
-        return qint_get_int(qobject_to_qint(obj));
-    default:
-        abort();
-    }
+    return qnum_get_double(qobject_to_qnum(qdict_get(qdict, key)));
 }
 
 /**
  * qdict_get_int(): Get an integer mapped by 'key'
  *
  * This function assumes that 'key' exists and it stores a
- * QInt object.
+ * QNum representable as int.
  *
  * Return integer mapped by 'key'.
  */
 int64_t qdict_get_int(const QDict *qdict, const char *key)
 {
-    return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
+    return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)), &error_abort);
 }
 
 /**
@@ -260,15 +248,25 @@ const char *qdict_get_str(const QDict *qdict, const char *key)
  * qdict_get_try_int(): Try to get integer mapped by 'key'
  *
  * Return integer mapped by 'key', if it is not present in
- * the dictionary or if the stored object is not of QInt type
+ * the dictionary or if the stored object is not of QNum type
  * 'def_value' will be returned.
  */
 int64_t qdict_get_try_int(const QDict *qdict, const char *key,
                           int64_t def_value)
 {
-    QInt *qint = qobject_to_qint(qdict_get(qdict, key));
+    Error *err = NULL;
+    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
+    int64_t val = def_value;
+
+    if (qnum) {
+        val = qnum_get_int(qnum, &err);
+    }
+    if (err) {
+        error_free(err);
+        val = def_value;
+    }
 
-    return qint ? qint_get_int(qint) : def_value;
+    return val;
 }
 
 /**
diff --git a/qobject/qfloat.c b/qobject/qfloat.c
deleted file mode 100644
index d5da847701..0000000000
--- a/qobject/qfloat.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * QFloat Module
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/qmp/qfloat.h"
-#include "qapi/qmp/qobject.h"
-#include "qemu-common.h"
-
-/**
- * qfloat_from_int(): Create a new QFloat from a float
- *
- * Return strong reference.
- */
-QFloat *qfloat_from_double(double value)
-{
-    QFloat *qf;
-
-    qf = g_malloc(sizeof(*qf));
-    qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
-    qf->value = value;
-
-    return qf;
-}
-
-/**
- * qfloat_get_double(): Get the stored float
- */
-double qfloat_get_double(const QFloat *qf)
-{
-    return qf->value;
-}
-
-/**
- * qobject_to_qfloat(): Convert a QObject into a QFloat
- */
-QFloat *qobject_to_qfloat(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
-        return NULL;
-    }
-    return container_of(obj, QFloat, base);
-}
-
-/**
- * qfloat_destroy_obj(): Free all memory allocated by a
- * QFloat object
- */
-void qfloat_destroy_obj(QObject *obj)
-{
-    assert(obj != NULL);
-    g_free(qobject_to_qfloat(obj));
-}
diff --git a/qobject/qint.c b/qobject/qint.c
deleted file mode 100644
index d7d1b3021f..0000000000
--- a/qobject/qint.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * QInt Module
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qobject.h"
-#include "qemu-common.h"
-
-/**
- * qint_from_int(): Create a new QInt from an int64_t
- *
- * Return strong reference.
- */
-QInt *qint_from_int(int64_t value)
-{
-    QInt *qi;
-
-    qi = g_malloc(sizeof(*qi));
-    qobject_init(QOBJECT(qi), QTYPE_QINT);
-    qi->value = value;
-
-    return qi;
-}
-
-/**
- * qint_get_int(): Get the stored integer
- */
-int64_t qint_get_int(const QInt *qi)
-{
-    return qi->value;
-}
-
-/**
- * qobject_to_qint(): Convert a QObject into a QInt
- */
-QInt *qobject_to_qint(const QObject *obj)
-{
-    if (!obj || qobject_type(obj) != QTYPE_QINT) {
-        return NULL;
-    }
-    return container_of(obj, QInt, base);
-}
-
-/**
- * qint_destroy_obj(): Free all memory allocated by a
- * QInt object
- */
-void qint_destroy_obj(QObject *obj)
-{
-    assert(obj != NULL);
-    g_free(qobject_to_qint(obj));
-}
diff --git a/qobject/qjson.c b/qobject/qjson.c
index b2f3bfec53..2e0930884e 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -132,12 +132,11 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
     case QTYPE_QNULL:
         qstring_append(str, "null");
         break;
-    case QTYPE_QINT: {
-        QInt *val = qobject_to_qint(obj);
-        char buffer[1024];
-
-        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
+    case QTYPE_QNUM: {
+        QNum *val = qobject_to_qnum(obj);
+        char *buffer = qnum_to_string(val);
         qstring_append(str, buffer);
+        g_free(buffer);
         break;
     }
     case QTYPE_QSTRING: {
@@ -234,34 +233,6 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
         qstring_append(str, "]");
         break;
     }
-    case QTYPE_QFLOAT: {
-        QFloat *val = qobject_to_qfloat(obj);
-        char buffer[1024];
-        int len;
-
-        /* FIXME: snprintf() is locale dependent; but JSON requires
-         * numbers to be formatted as if in the C locale. Dependence
-         * on C locale is a pervasive issue in QEMU. */
-        /* FIXME: This risks printing Inf or NaN, which are not valid
-         * JSON values. */
-        /* FIXME: the default precision of 6 for %f often causes
-         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
-         * and only rounding to a shorter number if the result would
-         * still produce the same floating point value.  */
-        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
-        while (len > 0 && buffer[len - 1] == '0') {
-            len--;
-        }
-
-        if (len && buffer[len - 1] == '.') {
-            buffer[len - 1] = 0;
-        } else {
-            buffer[len] = 0;
-        }
-
-        qstring_append(str, buffer);
-        break;
-    }
     case QTYPE_QBOOL: {
         QBool *val = qobject_to_qbool(obj);
 
diff --git a/qobject/qnum.c b/qobject/qnum.c
new file mode 100644
index 0000000000..8e9dd38350
--- /dev/null
+++ b/qobject/qnum.c
@@ -0,0 +1,138 @@
+/*
+ * QNum Module
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *  Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qobject.h"
+#include "qemu-common.h"
+
+/**
+ * qnum_from_int(): Create a new QNum from an int64_t
+ *
+ * Return strong reference.
+ */
+QNum *qnum_from_int(int64_t value)
+{
+    QNum *qn = g_new(QNum, 1);
+
+    qobject_init(QOBJECT(qn), QTYPE_QNUM);
+    qn->type = QNUM_I64;
+    qn->u.i64 = value;
+
+    return qn;
+}
+
+/**
+ * qnum_from_double(): Create a new QNum from a double
+ *
+ * Return strong reference.
+ */
+QNum *qnum_from_double(double value)
+{
+    QNum *qn = g_new(QNum, 1);
+
+    qobject_init(QOBJECT(qn), QTYPE_QNUM);
+    qn->type = QNUM_DOUBLE;
+    qn->u.dbl = value;
+
+    return qn;
+}
+
+/**
+ * qnum_get_int(): Get an integer representation of the number
+ */
+int64_t qnum_get_int(const QNum *qn, Error **errp)
+{
+    switch (qn->type) {
+    case QNUM_I64:
+        return qn->u.i64;
+    case QNUM_DOUBLE:
+        error_setg(errp, "The number is a float");
+        return 0;
+    }
+
+    g_assert_not_reached();
+}
+
+/**
+ * qnum_get_double(): Get a float representation of the number
+ */
+double qnum_get_double(QNum *qn)
+{
+    switch (qn->type) {
+    case QNUM_I64:
+        return qn->u.i64;
+    case QNUM_DOUBLE:
+        return qn->u.dbl;
+    }
+
+    g_assert_not_reached();
+}
+
+char *qnum_to_string(QNum *qn)
+{
+    char *buffer;
+    int len;
+
+    switch (qn->type) {
+    case QNUM_I64:
+        return g_strdup_printf("%" PRId64, qn->u.i64);
+    case QNUM_DOUBLE:
+        /* FIXME: snprintf() is locale dependent; but JSON requires
+         * numbers to be formatted as if in the C locale. Dependence
+         * on C locale is a pervasive issue in QEMU. */
+        /* FIXME: This risks printing Inf or NaN, which are not valid
+         * JSON values. */
+        /* FIXME: the default precision of 6 for %f often causes
+         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
+         * and only rounding to a shorter number if the result would
+         * still produce the same floating point value.  */
+        buffer = g_strdup_printf("%f" , qn->u.dbl);
+        len = strlen(buffer);
+        while (len > 0 && buffer[len - 1] == '0') {
+            len--;
+        }
+
+        if (len && buffer[len - 1] == '.') {
+            buffer[len - 1] = 0;
+        } else {
+            buffer[len] = 0;
+        }
+
+        return buffer;
+    }
+
+    g_assert_not_reached();
+}
+
+/**
+ * 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_destroy_obj(): Free all memory allocated by a
+ * QNum object
+ */
+void qnum_destroy_obj(QObject *obj)
+{
+    assert(obj != NULL);
+    g_free(qobject_to_qnum(obj));
+}
diff --git a/qobject/qobject.c b/qobject/qobject.c
index fe4fa10989..b0cafb66f1 100644
--- a/qobject/qobject.c
+++ b/qobject/qobject.c
@@ -14,11 +14,10 @@
 static void (*qdestroy[QTYPE__MAX])(QObject *) = {
     [QTYPE_NONE] = NULL,               /* No such object exists */
     [QTYPE_QNULL] = NULL,              /* qnull_ is indestructible */
-    [QTYPE_QINT] = qint_destroy_obj,
+    [QTYPE_QNUM] = qnum_destroy_obj,
     [QTYPE_QSTRING] = qstring_destroy_obj,
     [QTYPE_QDICT] = qdict_destroy_obj,
     [QTYPE_QLIST] = qlist_destroy_obj,
-    [QTYPE_QFLOAT] = qfloat_destroy_obj,
     [QTYPE_QBOOL] = qbool_destroy_obj,
 };
 
diff --git a/qom/object.c b/qom/object.c
index c7b8079df6..c1644dbcb7 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -27,7 +27,6 @@
 #include "qom/qom-qobject.h"
 #include "qapi/qmp/qobject.h"
 #include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qstring.h"
 
 #define MAX_INTERFACES 32
@@ -1190,28 +1189,32 @@ bool object_property_get_bool(Object *obj, const char *name,
 void object_property_set_int(Object *obj, int64_t value,
                              const char *name, Error **errp)
 {
-    QInt *qint = qint_from_int(value);
-    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
+    QNum *qnum = qnum_from_int(value);
+    object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
 
-    QDECREF(qint);
+    QDECREF(qnum);
 }
 
 int64_t object_property_get_int(Object *obj, const char *name,
                                 Error **errp)
 {
     QObject *ret = object_property_get_qobject(obj, name, errp);
-    QInt *qint;
+    Error *err = NULL;
+    QNum *qnum;
     int64_t retval;
 
     if (!ret) {
         return -1;
     }
-    qint = qobject_to_qint(ret);
-    if (!qint) {
+    qnum = qobject_to_qnum(ret);
+    if (qnum) {
+        retval = qnum_get_int(qnum, &err);
+    }
+
+    if (!qnum || err) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
+        error_free(err);
         retval = -1;
-    } else {
-        retval = qint_get_int(qint);
     }
 
     qobject_decref(ret);
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 13c0985f11..1e8a5b55c0 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -29,11 +29,7 @@
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qapi/qmp/qerror.h"
-#include "qapi/qmp/qstring.h"
-#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qfloat.h"
+#include "qapi/qmp/types.h"
 
 #include "qapi-types.h"
 #include "qapi-visit.h"
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index be8d81f07b..bcd06a7d6b 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -11,7 +11,6 @@
  */
 #include "qemu/osdep.h"
 
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/error.h"
@@ -39,7 +38,7 @@ static void qdict_new_test(void)
 
 static void qdict_put_obj_test(void)
 {
-    QInt *qi;
+    QNum *qi;
     QDict *qdict;
     QDictEntry *ent;
     const int num = 42;
@@ -51,8 +50,8 @@ static void qdict_put_obj_test(void)
 
     g_assert(qdict_size(qdict) == 1);
     ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
-    qi = qobject_to_qint(ent->value);
-    g_assert(qint_get_int(qi) == num);
+    qi = qobject_to_qnum(ent->value);
+    g_assert(qnum_get_int(qi, &error_abort) == num);
 
     // destroy doesn't exit yet
     QDECREF(qi);
@@ -74,7 +73,7 @@ static void qdict_destroy_simple_test(void)
 
 static void qdict_get_test(void)
 {
-    QInt *qi;
+    QNum *qi;
     QObject *obj;
     const int value = -42;
     const char *key = "test";
@@ -85,8 +84,8 @@ static void qdict_get_test(void)
     obj = qdict_get(tests_dict, key);
     g_assert(obj != NULL);
 
-    qi = qobject_to_qint(obj);
-    g_assert(qint_get_int(qi) == value);
+    qi = qobject_to_qnum(obj);
+    g_assert(qnum_get_int(qi, &error_abort) == value);
 
     QDECREF(tests_dict);
 }
@@ -329,7 +328,7 @@ static void qdict_array_split_test(void)
 {
     QDict *test_dict = qdict_new();
     QDict *dict1, *dict2;
-    QInt *int1;
+    QNum *int1;
     QList *test_list;
 
     /*
@@ -380,7 +379,7 @@ static void qdict_array_split_test(void)
 
     dict1 = qobject_to_qdict(qlist_pop(test_list));
     dict2 = qobject_to_qdict(qlist_pop(test_list));
-    int1 = qobject_to_qint(qlist_pop(test_list));
+    int1 = qobject_to_qnum(qlist_pop(test_list));
 
     g_assert(dict1);
     g_assert(dict2);
@@ -402,7 +401,7 @@ static void qdict_array_split_test(void)
 
     QDECREF(dict2);
 
-    g_assert(qint_get_int(int1) == 66);
+    g_assert(qnum_get_int(int1, &error_abort) == 66);
 
     QDECREF(int1);
 
@@ -447,14 +446,14 @@ static void qdict_array_split_test(void)
 
     qdict_array_split(test_dict, &test_list);
 
-    int1 = qobject_to_qint(qlist_pop(test_list));
+    int1 = qobject_to_qnum(qlist_pop(test_list));
 
     g_assert(int1);
     g_assert(qlist_empty(test_list));
 
     QDECREF(test_list);
 
-    g_assert(qint_get_int(int1) == 42);
+    g_assert(qnum_get_int(int1, &error_abort) == 42);
 
     QDECREF(int1);
 
diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c
deleted file mode 100644
index 1da2cdae08..0000000000
--- a/tests/check-qfloat.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * QFloat unit-tests.
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#include "qemu/osdep.h"
-
-#include "qapi/qmp/qfloat.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qfloat_from_double_test(void)
-{
-    QFloat *qf;
-    const double value = -42.23423;
-
-    qf = qfloat_from_double(value);
-    g_assert(qf != NULL);
-    g_assert(qf->value == value);
-    g_assert(qf->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
-
-    // destroy doesn't exit yet
-    g_free(qf);
-}
-
-static void qfloat_destroy_test(void)
-{
-    QFloat *qf = qfloat_from_double(0.0);
-    QDECREF(qf);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_double", qfloat_from_double_test);
-    g_test_add_func("/public/destroy", qfloat_destroy_test);
-
-    return g_test_run();
-}
diff --git a/tests/check-qint.c b/tests/check-qint.c
deleted file mode 100644
index b6e4555115..0000000000
--- a/tests/check-qint.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * QInt unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include "qemu/osdep.h"
-
-#include "qapi/qmp/qint.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qint_from_int_test(void)
-{
-    QInt *qi;
-    const int value = -42;
-
-    qi = qint_from_int(value);
-    g_assert(qi != NULL);
-    g_assert(qi->value == value);
-    g_assert(qi->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
-
-    // destroy doesn't exit yet
-    g_free(qi);
-}
-
-static void qint_destroy_test(void)
-{
-    QInt *qi = qint_from_int(0);
-    QDECREF(qi);
-}
-
-static void qint_from_int64_test(void)
-{
-    QInt *qi;
-    const int64_t value = 0x1234567890abcdefLL;
-
-    qi = qint_from_int(value);
-    g_assert((int64_t) qi->value == value);
-
-    QDECREF(qi);
-}
-
-static void qint_get_int_test(void)
-{
-    QInt *qi;
-    const int value = 123456;
-
-    qi = qint_from_int(value);
-    g_assert(qint_get_int(qi) == value);
-
-    QDECREF(qi);
-}
-
-static void qobject_to_qint_test(void)
-{
-    QInt *qi;
-
-    qi = qint_from_int(0);
-    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
-
-    QDECREF(qi);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_int", qint_from_int_test);
-    g_test_add_func("/public/destroy", qint_destroy_test);
-    g_test_add_func("/public/from_int64", qint_from_int64_test);
-    g_test_add_func("/public/get_int", qint_get_int_test);
-    g_test_add_func("/public/to_qint", qobject_to_qint_test);
-
-    return g_test_run();
-}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 963dd46f07..c432aebf13 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -886,21 +886,21 @@ static void simple_number(void)
     };
 
     for (i = 0; test_cases[i].encoded; i++) {
-        QInt *qint;
+        QNum *qnum;
 
-        qint = qobject_to_qint(qobject_from_json(test_cases[i].encoded,
+        qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
                                                  &error_abort));
-        g_assert(qint);
-        g_assert(qint_get_int(qint) == test_cases[i].decoded);
+        g_assert(qnum);
+        g_assert(qnum_get_int(qnum, &error_abort) == test_cases[i].decoded);
         if (test_cases[i].skip == 0) {
             QString *str;
 
-            str = qobject_to_json(QOBJECT(qint));
+            str = qobject_to_json(QOBJECT(qnum));
             g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
             QDECREF(str);
         }
 
-        QDECREF(qint);
+        QDECREF(qnum);
     }
 }
 
@@ -921,12 +921,12 @@ static void float_number(void)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
-        QFloat *qfloat;
+        QNum *qnum;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        qfloat = qobject_to_qfloat(obj);
-        g_assert(qfloat);
-        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
+        qnum = qobject_to_qnum(obj);
+        g_assert(qnum);
+        g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
 
         if (test_cases[i].skip == 0) {
             QString *str;
@@ -936,29 +936,28 @@ static void float_number(void)
             QDECREF(str);
         }
 
-        QDECREF(qfloat);
+        QDECREF(qnum);
     }
 }
 
 static void vararg_number(void)
 {
-    QInt *qint;
-    QFloat *qfloat;
+    QNum *qnum;
     int value = 0x2342;
     long long value_ll = 0x2342342343LL;
     double valuef = 2.323423423;
 
-    qint = qobject_to_qint(qobject_from_jsonf("%d", value));
-    g_assert(qint_get_int(qint) == value);
-    QDECREF(qint);
+    qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
+    g_assert(qnum_get_int(qnum, &error_abort) == value);
+    QDECREF(qnum);
 
-    qint = qobject_to_qint(qobject_from_jsonf("%lld", value_ll));
-    g_assert(qint_get_int(qint) == value_ll);
-    QDECREF(qint);
+    qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
+    g_assert(qnum_get_int(qnum, &error_abort) == value_ll);
+    QDECREF(qnum);
 
-    qfloat = qobject_to_qfloat(qobject_from_jsonf("%f", valuef));
-    g_assert(qfloat_get_double(qfloat) == valuef);
-    QDECREF(qfloat);
+    qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
+    g_assert(qnum_get_double(qnum) == valuef);
+    QDECREF(qnum);
 }
 
 static void keyword_literal(void)
@@ -1019,7 +1018,7 @@ struct LiteralQObject
 {
     int type;
     union {
-        int64_t qint;
+        int64_t qnum;
         const char *qstr;
         LiteralQDictEntry *qdict;
         LiteralQObject *qlist;
@@ -1032,7 +1031,7 @@ struct LiteralQDictEntry
     LiteralQObject value;
 };
 
-#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
+#define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
@@ -1069,8 +1068,9 @@ static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
     }
 
     switch (lhs->type) {
-    case QTYPE_QINT:
-        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
+    case QTYPE_QNUM:
+        return lhs->value.qnum == qnum_get_int(qobject_to_qnum(rhs),
+                                               &error_abort);
     case QTYPE_QSTRING:
         return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
     case QTYPE_QDICT: {
@@ -1114,7 +1114,7 @@ static void simple_dict(void)
         {
             .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { "foo", QLIT_QINT(42) },
+                        { "foo", QLIT_QNUM(42) },
                         { "bar", QLIT_QSTR("hello world") },
                         { }
                     })),
@@ -1126,7 +1126,7 @@ static void simple_dict(void)
         }, {
             .encoded = "{\"foo\": 43}",
             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { "foo", QLIT_QINT(43) },
+                        { "foo", QLIT_QNUM(43) },
                         { }
                     })),
         },
@@ -1212,15 +1212,15 @@ static void simple_list(void)
         {
             .encoded = "[43,42]",
             .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QINT(42),
+                        QLIT_QNUM(43),
+                        QLIT_QNUM(42),
                         { }
                     })),
         },
         {
             .encoded = "[43]",
             .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
+                        QLIT_QNUM(43),
                         { }
                     })),
         },
@@ -1269,35 +1269,35 @@ static void simple_whitespace(void)
         {
             .encoded = " [ 43 , 42 ]",
             .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QINT(42),
+                        QLIT_QNUM(43),
+                        QLIT_QNUM(42),
                         { }
                     })),
         },
         {
             .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
             .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
+                        QLIT_QNUM(43),
                         QLIT_QDICT(((LiteralQDictEntry[]){
                                     { "h", QLIT_QSTR("b") },
                                     { }})),
                         QLIT_QLIST(((LiteralQObject[]){
                                     { }})),
-                        QLIT_QINT(42),
+                        QLIT_QNUM(42),
                         { }
                     })),
         },
         {
             .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
             .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
+                        QLIT_QNUM(43),
                         QLIT_QDICT(((LiteralQDictEntry[]){
                                     { "h", QLIT_QSTR("b") },
-                                    { "a", QLIT_QINT(32) },
+                                    { "a", QLIT_QNUM(32) },
                                     { }})),
                         QLIT_QLIST(((LiteralQObject[]){
                                     { }})),
-                        QLIT_QINT(42),
+                        QLIT_QNUM(42),
                         { }
                     })),
         },
@@ -1327,11 +1327,11 @@ static void simple_varargs(void)
     QObject *embedded_obj;
     QObject *obj;
     LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
-            QLIT_QINT(1),
-            QLIT_QINT(2),
+            QLIT_QNUM(1),
+            QLIT_QNUM(2),
             QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(32),
-                        QLIT_QINT(42),
+                        QLIT_QNUM(32),
+                        QLIT_QNUM(42),
                         {}})),
             {}}));
 
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
index 4983867c27..a2d1701003 100644
--- a/tests/check-qlist.c
+++ b/tests/check-qlist.c
@@ -11,8 +11,8 @@
  */
 #include "qemu/osdep.h"
 
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qlist.h"
+#include "qapi/error.h"
+#include "qapi/qmp/types.h"
 
 /*
  * Public Interface test-cases
@@ -35,11 +35,11 @@ static void qlist_new_test(void)
 
 static void qlist_append_test(void)
 {
-    QInt *qi;
+    QNum *qi;
     QList *qlist;
     QListEntry *entry;
 
-    qi = qint_from_int(42);
+    qi = qnum_from_int(42);
 
     qlist = qlist_new();
     qlist_append(qlist, qi);
@@ -84,13 +84,14 @@ static const int iter_max = 42;
 
 static void iter_func(QObject *obj, void *opaque)
 {
-    QInt *qi;
+    QNum *qi;
 
     g_assert(opaque == NULL);
 
-    qi = qobject_to_qint(obj);
+    qi = qobject_to_qnum(obj);
     g_assert(qi != NULL);
-    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
+    g_assert((qnum_get_int(qi, &error_abort) >= 0) &&
+             (qnum_get_int(qi, &error_abort) <= iter_max));
 
     iter_called++;
 }
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
new file mode 100644
index 0000000000..d08d35e85a
--- /dev/null
+++ b/tests/check-qnum.c
@@ -0,0 +1,131 @@
+/*
+ * QNum unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+
+#include "qapi/qmp/qnum.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qnum_from_int_test(void)
+{
+    QNum *qi;
+    const int value = -42;
+
+    qi = qnum_from_int(value);
+    g_assert(qi != NULL);
+    g_assert_cmpint(qi->u.i64, ==, value);
+    g_assert_cmpint(qi->base.refcnt, ==, 1);
+    g_assert_cmpint(qobject_type(QOBJECT(qi)), ==, QTYPE_QNUM);
+
+    // destroy doesn't exit yet
+    g_free(qi);
+}
+
+static void qnum_from_double_test(void)
+{
+    QNum *qf;
+    const double value = -42.23423;
+
+    qf = qnum_from_double(value);
+    g_assert(qf != NULL);
+    g_assert_cmpfloat(qf->u.dbl, ==, value);
+    g_assert_cmpint(qf->base.refcnt, ==, 1);
+    g_assert_cmpint(qobject_type(QOBJECT(qf)), ==, QTYPE_QNUM);
+
+    // destroy doesn't exit yet
+    g_free(qf);
+}
+
+static void qnum_from_int64_test(void)
+{
+    QNum *qi;
+    const int64_t value = 0x1234567890abcdefLL;
+
+    qi = qnum_from_int(value);
+    g_assert_cmpint((int64_t) qi->u.i64, ==, value);
+
+    QDECREF(qi);
+}
+
+static void qnum_get_int_test(void)
+{
+    QNum *qi;
+    const int value = 123456;
+
+    qi = qnum_from_int(value);
+    g_assert_cmpint(qnum_get_int(qi, &error_abort), ==, value);
+
+    QDECREF(qi);
+}
+
+static void qobject_to_qnum_test(void)
+{
+    QNum *qn;
+
+    qn = qnum_from_int(0);
+    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
+    QDECREF(qn);
+
+    qn = qnum_from_double(0);
+    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
+    QDECREF(qn);
+}
+
+static void qnum_to_string_test(void)
+{
+    QNum *qn;
+    char *tmp;
+
+    qn = qnum_from_int(123456);
+    tmp = qnum_to_string(qn);
+    g_assert_cmpstr(tmp, ==, "123456");
+    g_free(tmp);
+    QDECREF(qn);
+
+    qn = qnum_from_double(0.42);
+    tmp = qnum_to_string(qn);
+    g_assert_cmpstr(tmp, ==, "0.42");
+    g_free(tmp);
+    QDECREF(qn);
+}
+
+static void qnum_destroy_test(void)
+{
+    QNum *qn;
+
+    qn = qnum_from_int(0);
+    QDECREF(qn);
+
+    qn = qnum_from_double(0.42);
+    QDECREF(qn);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/qnum/from_int", qnum_from_int_test);
+    g_test_add_func("/qnum/from_double", qnum_from_double_test);
+    g_test_add_func("/qnum/destroy", qnum_destroy_test);
+    g_test_add_func("/qnum/from_int64", qnum_from_int64_test);
+    g_test_add_func("/qnum/get_int", qnum_get_int_test);
+    g_test_add_func("/qnum/to_qnum", qobject_to_qnum_test);
+    g_test_add_func("/qnum/to_string", qnum_to_string_test);
+
+    return g_test_run();
+}
diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index df0ff831b5..bec574257e 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -611,7 +611,6 @@ static void test_keyval_visit_optional(void)
 
 static void test_keyval_visit_alternate(void)
 {
-    Error *err = NULL;
     Visitor *v;
     QDict *qdict;
     AltNumStr *ans;
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index acdded4d67..96a52dbca8 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -162,7 +162,7 @@ static void test_dispatch_cmd_io(void)
     QDict *ud1b = qdict_new();
     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
-    QInt *ret3;
+    QNum *ret3;
 
     qdict_put_int(ud1a, "integer", 42);
     qdict_put_str(ud1a, "string", "hello");
@@ -194,8 +194,8 @@ static void test_dispatch_cmd_io(void)
     qdict_put(req, "arguments", args3);
     qdict_put_str(req, "execute", "guest-get-time");
 
-    ret3 = qobject_to_qint(test_qmp_dispatch(req));
-    assert(qint_get_int(ret3) == 66);
+    ret3 = qobject_to_qnum(test_qmp_dispatch(req));
+    assert(qnum_get_int(ret3, &error_abort) == 66);
     QDECREF(ret3);
 
     QDECREF(req);
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 4c0f09601d..e996bebc6e 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -18,7 +18,6 @@
 #include "test-qapi-visit.h"
 #include "test-qapi-event.h"
 #include "qapi/qmp/types.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qobject.h"
 #include "qapi/qmp-event.h"
 
@@ -62,9 +61,9 @@ void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
         d->result = (qbool_get_bool(qobject_to_qbool(obj1)) ==
                      qbool_get_bool(qobject_to_qbool(obj2)));
         return;
-    case QTYPE_QINT:
-        d->result = (qint_get_int(qobject_to_qint(obj1)) ==
-                     qint_get_int(qobject_to_qint(obj2)));
+    case QTYPE_QNUM:
+        d->result = (qnum_get_int(qobject_to_qnum(obj1), &error_abort) ==
+                     qnum_get_int(qobject_to_qnum(obj2), &error_abort));
         return;
     case QTYPE_QSTRING:
         d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index a30e2d5e95..4484980969 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -152,7 +152,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
     Visitor *v;
 
     /* this will overflow a Qint/int64, so should be deserialized into
-     * a QFloat/double field instead, leading to an error if we pass it
+     * a QNum/double field instead, leading to an error if we pass it
      * to visit_type_int. confirm this.
      */
     v = visitor_input_test_init(data, "%f", DBL_MAX);
@@ -428,7 +428,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
 {
     QObject *res = NULL;
     Visitor *v;
-    QInt *qint;
+    QNum *qnum;
     QBool *qbool;
     QString *qstring;
     QDict *qdict;
@@ -436,9 +436,9 @@ static void test_visitor_in_any(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "-42");
     visit_type_any(v, NULL, &res, &error_abort);
-    qint = qobject_to_qint(res);
-    g_assert(qint);
-    g_assert_cmpint(qint_get_int(qint), ==, -42);
+    qnum = qobject_to_qnum(res);
+    g_assert(qnum);
+    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
     qobject_decref(res);
 
     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
@@ -447,9 +447,9 @@ static void test_visitor_in_any(TestInputVisitorData *data,
     g_assert(qdict && qdict_size(qdict) == 3);
     qobj = qdict_get(qdict, "integer");
     g_assert(qobj);
-    qint = qobject_to_qint(qobj);
-    g_assert(qint);
-    g_assert_cmpint(qint_get_int(qint), ==, -42);
+    qnum = qobject_to_qnum(qobj);
+    g_assert(qnum);
+    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
     qobj = qdict_get(qdict, "boolean");
     g_assert(qobj);
     qbool = qobject_to_qbool(qobj);
@@ -527,7 +527,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "42");
     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
-    g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
+    g_assert_cmpint(tmp->type, ==, QTYPE_QNUM);
     g_assert_cmpint(tmp->u.i, ==, 42);
     qapi_free_UserDefAlternate(tmp);
 
@@ -555,7 +555,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "{ 'alt': 42 }");
     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
-    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
+    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QNUM);
     g_assert_cmpint(wrap->alt->u.i, ==, 42);
     qapi_free_WrapAlternate(wrap);
 
@@ -596,19 +596,19 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "42");
     visit_type_AltStrNum(v, NULL, &asn, &error_abort);
-    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
+    g_assert_cmpint(asn->type, ==, QTYPE_QNUM);
     g_assert_cmpfloat(asn->u.n, ==, 42);
     qapi_free_AltStrNum(asn);
 
     v = visitor_input_test_init(data, "42");
     visit_type_AltNumStr(v, NULL, &ans, &error_abort);
-    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
+    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
     g_assert_cmpfloat(ans->u.n, ==, 42);
     qapi_free_AltNumStr(ans);
 
     v = visitor_input_test_init(data, "42");
     visit_type_AltStrInt(v, NULL, &asi, &error_abort);
-    g_assert_cmpint(asi->type, ==, QTYPE_QINT);
+    g_assert_cmpint(asi->type, ==, QTYPE_QNUM);
     g_assert_cmpint(asi->u.i, ==, 42);
     qapi_free_AltStrInt(asi);
 
@@ -621,13 +621,13 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
 
     v = visitor_input_test_init(data, "42.5");
     visit_type_AltStrNum(v, NULL, &asn, &error_abort);
-    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
+    g_assert_cmpint(asn->type, ==, QTYPE_QNUM);
     g_assert_cmpfloat(asn->u.n, ==, 42.5);
     qapi_free_AltStrNum(asn);
 
     v = visitor_input_test_init(data, "42.5");
     visit_type_AltNumStr(v, NULL, &ans, &error_abort);
-    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
+    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
     g_assert_cmpfloat(ans->u.n, ==, 42.5);
     qapi_free_AltNumStr(ans);
 
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 94b9518e40..66a682d5a8 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -58,13 +58,13 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
                                  const void *unused)
 {
     int64_t value = -42;
-    QInt *qint;
+    QNum *qnum;
 
     visit_type_int(data->ov, NULL, &value, &error_abort);
 
-    qint = qobject_to_qint(visitor_get(data));
-    g_assert(qint);
-    g_assert_cmpint(qint_get_int(qint), ==, value);
+    qnum = qobject_to_qnum(visitor_get(data));
+    g_assert(qnum);
+    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, value);
 }
 
 static void test_visitor_out_bool(TestOutputVisitorData *data,
@@ -84,13 +84,13 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
                                     const void *unused)
 {
     double value = 3.14;
-    QFloat *qfloat;
+    QNum *qnum;
 
     visit_type_number(data->ov, NULL, &value, &error_abort);
 
-    qfloat = qobject_to_qfloat(visitor_get(data));
-    g_assert(qfloat);
-    g_assert(qfloat_get_double(qfloat) == value);
+    qnum = qobject_to_qnum(visitor_get(data));
+    g_assert(qnum);
+    g_assert(qnum_get_double(qnum) == value);
 }
 
 static void test_visitor_out_string(TestOutputVisitorData *data,
@@ -329,16 +329,16 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
                                  const void *unused)
 {
     QObject *qobj;
-    QInt *qint;
+    QNum *qnum;
     QBool *qbool;
     QString *qstring;
     QDict *qdict;
 
-    qobj = QOBJECT(qint_from_int(-42));
+    qobj = QOBJECT(qnum_from_int(-42));
     visit_type_any(data->ov, NULL, &qobj, &error_abort);
-    qint = qobject_to_qint(visitor_get(data));
-    g_assert(qint);
-    g_assert_cmpint(qint_get_int(qint), ==, -42);
+    qnum = qobject_to_qnum(visitor_get(data));
+    g_assert(qnum);
+    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
     qobject_decref(qobj);
 
     visitor_reset(data);
@@ -351,9 +351,9 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
     qobject_decref(qobj);
     qdict = qobject_to_qdict(visitor_get(data));
     g_assert(qdict);
-    qint = qobject_to_qint(qdict_get(qdict, "integer"));
-    g_assert(qint);
-    g_assert_cmpint(qint_get_int(qint), ==, -42);
+    qnum = qobject_to_qnum(qdict_get(qdict, "integer"));
+    g_assert(qnum);
+    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
     qbool = qobject_to_qbool(qdict_get(qdict, "boolean"));
     g_assert(qbool);
     g_assert(qbool_get_bool(qbool) == true);
@@ -388,18 +388,18 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
                                        const void *unused)
 {
     UserDefAlternate *tmp;
-    QInt *qint;
+    QNum *qnum;
     QString *qstr;
     QDict *qdict;
 
     tmp = g_new0(UserDefAlternate, 1);
-    tmp->type = QTYPE_QINT;
+    tmp->type = QTYPE_QNUM;
     tmp->u.i = 42;
 
     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
-    qint = qobject_to_qint(visitor_get(data));
-    g_assert(qint);
-    g_assert_cmpint(qint_get_int(qint), ==, 42);
+    qnum = qobject_to_qnum(visitor_get(data));
+    g_assert(qnum);
+    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, 42);
 
     qapi_free_UserDefAlternate(tmp);
 
@@ -603,18 +603,18 @@ static void check_native_list(QObject *qobj,
     case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
     case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
     case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
-        /* all integer elements in JSON arrays get stored into QInts when
+        /* all integer elements in JSON arrays get stored into QNums when
          * we convert to QObjects, so we can check them all in the same
          * fashion, so simply fall through here
          */
     case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
         for (i = 0; i < 32; i++) {
             QObject *tmp;
-            QInt *qvalue;
+            QNum *qvalue;
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qint(tmp);
-            g_assert_cmpint(qint_get_int(qvalue), ==, i);
+            qvalue = qobject_to_qnum(tmp);
+            g_assert_cmpint(qnum_get_int(qvalue, &error_abort), ==, i);
             qobject_decref(qlist_pop(qlist));
         }
         break;
@@ -645,15 +645,15 @@ static void check_native_list(QObject *qobj,
     case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
         for (i = 0; i < 32; i++) {
             QObject *tmp;
-            QFloat *qvalue;
+            QNum *qvalue;
             GString *double_expected = g_string_new("");
             GString *double_actual = g_string_new("");
 
             tmp = qlist_peek(qlist);
             g_assert(tmp);
-            qvalue = qobject_to_qfloat(tmp);
+            qvalue = qobject_to_qnum(tmp);
             g_string_printf(double_expected, "%.6f", (double)i / 3);
-            g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue));
+            g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue));
             g_assert_cmpstr(double_actual->str, ==, double_expected->str);
 
             qobject_decref(qlist_pop(qlist));
diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
index 79a2e69a28..60d168fda8 100644
--- a/tests/test-x86-cpuid-compat.c
+++ b/tests/test-x86-cpuid-compat.c
@@ -1,9 +1,7 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
-#include "qapi/qmp/qlist.h"
-#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qbool.h"
+#include "qapi/error.h"
+#include "qapi/qmp/types.h"
 #include "libqtest.h"
 
 static char *get_cpu0_qom_path(void)
@@ -56,12 +54,13 @@ static void test_cpuid_prop(const void *data)
 {
     const CpuidTestArgs *args = data;
     char *path;
-    QInt *value;
+    QNum *value;
 
     qtest_start(args->cmdline);
     path = get_cpu0_qom_path();
-    value = qobject_to_qint(qom_get(path, args->property));
-    g_assert_cmpint(qint_get_int(value), ==, args->expected_value);
+    value = qobject_to_qnum(qom_get(path, args->property));
+    g_assert_cmpint(qnum_get_int(value, &error_abort), ==,
+                    args->expected_value);
     qtest_end();
 
     QDECREF(value);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 804abc5c0f..561d0649cf 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -30,7 +30,6 @@
 #include "qemu-x509.h"
 #include "qemu/sockets.h"
 #include "qmp-commands.h"
-#include "qapi/qmp/qint.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qmp/qjson.h"
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 1e53b1cf84..89ab12c0d8 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -44,7 +44,6 @@
 #endif
 
 #include "qemu/bswap.h"
-#include "qapi/qmp/qint.h"
 #include "vnc.h"
 #include "vnc-enc-tight.h"
 #include "vnc-palette.h"
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 5977bfc3e9..39b1e06225 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -941,9 +941,8 @@ typedef struct OptsFromQDictState {
 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 {
     OptsFromQDictState *state = opaque;
-    char buf[32];
+    char buf[32], *tmp = NULL;
     const char *value;
-    int n;
 
     if (!strcmp(key, "id") || *state->errp) {
         return;
@@ -953,17 +952,9 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
     case QTYPE_QSTRING:
         value = qstring_get_str(qobject_to_qstring(obj));
         break;
-    case QTYPE_QINT:
-        n = snprintf(buf, sizeof(buf), "%" PRId64,
-                     qint_get_int(qobject_to_qint(obj)));
-        assert(n < sizeof(buf));
-        value = buf;
-        break;
-    case QTYPE_QFLOAT:
-        n = snprintf(buf, sizeof(buf), "%.17g",
-                     qfloat_get_double(qobject_to_qfloat(obj)));
-        assert(n < sizeof(buf));
-        value = buf;
+    case QTYPE_QNUM:
+        tmp = qnum_to_string(qobject_to_qnum(obj));
+        value = tmp;
         break;
     case QTYPE_QBOOL:
         pstrcpy(buf, sizeof(buf),
@@ -975,12 +966,13 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
     }
 
     qemu_opt_set(state->opts, key, value, state->errp);
+    g_free(tmp);
 }
 
 /*
  * Create QemuOpts from a QDict.
  * Use value of key "id" as ID if it exists and is a QString.
- * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
+ * Only QStrings, QNums and QBools are copied.  Entries with
  * other types are silently ignored.
  */
 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
diff --git a/MAINTAINERS b/MAINTAINERS
index 66c9734311..421fb585ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1395,8 +1395,7 @@ F: include/qapi/qmp/
 X: include/qapi/qmp/dispatch.h
 F: scripts/coccinelle/qobject.cocci
 F: tests/check-qdict.c
-F: tests/check-qfloat.c
-F: tests/check-qint.c
+F: tests/check-qnum.c
 F: tests/check-qjson.c
 F: tests/check-qlist.c
 F: tests/check-qstring.c
diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs
index bed55084bb..fc8885c9a4 100644
--- a/qobject/Makefile.objs
+++ b/qobject/Makefile.objs
@@ -1,2 +1,2 @@
-util-obj-y = qnull.o qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
+util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o
 util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.cocci
index 97703a438b..c3253deb1b 100644
--- a/scripts/coccinelle/qobject.cocci
+++ b/scripts/coccinelle/qobject.cocci
@@ -6,7 +6,7 @@ expression Obj, Key, E;
 - qdict_put_obj(Obj, Key, QOBJECT(E));
 + qdict_put(Obj, Key, E);
 |
-- qdict_put(Obj, Key, qint_from_int(E));
+- qdict_put(Obj, Key, qnum_from_int(E));
 + qdict_put_int(Obj, Key, E);
 |
 - qdict_put(Obj, Key, qbool_from_bool(E));
@@ -24,7 +24,7 @@ expression Obj, E;
 - qlist_append_obj(Obj, QOBJECT(E));
 + qlist_append(Obj, E);
 |
-- qlist_append(Obj, qint_from_int(E));
+- qlist_append(Obj, qnum_from_int(E));
 + qlist_append_int(Obj, E);
 |
 - qlist_append(Obj, qbool_from_bool(E));
diff --git a/tests/.gitignore b/tests/.gitignore
index a966740c2c..847f4f1474 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,7 +1,6 @@
 atomic_add-bench
 check-qdict
-check-qfloat
-check-qint
+check-qnum
 check-qjson
 check-qlist
 check-qnull
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 31931c0d77..ac0387d88a 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -10,10 +10,8 @@ check-unit-y = tests/check-qdict$(EXESUF)
 gcov-files-check-qdict-y = qobject/qdict.c
 check-unit-y += tests/test-char$(EXESUF)
 gcov-files-check-qdict-y = chardev/char.c
-check-unit-y += tests/check-qfloat$(EXESUF)
-gcov-files-check-qfloat-y = qobject/qfloat.c
-check-unit-y += tests/check-qint$(EXESUF)
-gcov-files-check-qint-y = qobject/qint.c
+check-unit-y += tests/check-qnum$(EXESUF)
+gcov-files-check-qnum-y = qobject/qnum.c
 check-unit-y += tests/check-qstring$(EXESUF)
 gcov-files-check-qstring-y = qobject/qstring.c
 check-unit-y += tests/check-qlist$(EXESUF)
@@ -500,8 +498,8 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
 	tests/test-qmp-commands.h tests/test-qapi-event.h \
 	tests/test-qmp-introspect.h
 
-test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
-	tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
+test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
+	tests/check-qlist.o tests/check-qnull.o \
 	tests/check-qjson.o \
 	tests/test-coroutine.o tests/test-string-output-visitor.o \
 	tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
@@ -529,11 +527,10 @@ test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
 test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
 test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
 
-tests/check-qint$(EXESUF): tests/check-qint.o $(test-util-obj-y)
+tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y)
 tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y)
 tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
 tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
-tests/check-qfloat$(EXESUF): tests/check-qfloat.o $(test-util-obj-y)
 tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
 tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
index 5d7c13cad1..17e652535c 100644
--- a/tests/qapi-schema/comments.out
+++ b/tests/qapi-schema/comments.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
 object q_empty
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 70c1252408..63ca25a8b9 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -6,7 +6,7 @@ object Object
     tag base1
     case one: Variant1
     case two: Variant2
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 object SugaredUnion
     member type: SugaredUnionKind optional=False
diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
index 8a5b034424..40b886ddae 100644
--- a/tests/qapi-schema/empty.out
+++ b/tests/qapi-schema/empty.out
@@ -1,3 +1,3 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 object q_empty
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index 5a0f2bf805..313c0fe7be 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 event oops None
    boxed=False
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index 1d2722c02e..b5637cb2e0 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 command fooA q_obj_fooA-arg -> None
    gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
index 5d7c13cad1..17e652535c 100644
--- a/tests/qapi-schema/include-relpath.out
+++ b/tests/qapi-schema/include-relpath.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
 object q_empty
diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
index 5d7c13cad1..17e652535c 100644
--- a/tests/qapi-schema/include-repetition.out
+++ b/tests/qapi-schema/include-repetition.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
 object q_empty
diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
index 5d7c13cad1..17e652535c 100644
--- a/tests/qapi-schema/include-simple.out
+++ b/tests/qapi-schema/include-simple.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
 object q_empty
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index e8171c935f..586795f44d 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,4 +1,4 @@
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 command eins None -> None
    gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 5c6655a5c3..7812a6c69b 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -46,7 +46,7 @@ object NestedEnumsOne
     member enum4: EnumOne optional=True
 enum QEnumTwo ['value1', 'value2']
     prefix QENUM_TWO
-enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 object TestStruct
     member integer: int optional=False
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 05/17] qapi: remove promote_int
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (3 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-11 17:30   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 06/17] qnum: add uint type Marc-André Lureau
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

qnum_to_double() implicity promotes int now.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/visitor.h             |  4 +---
 include/qapi/visitor-impl.h        |  2 +-
 scripts/qapi-visit.py              | 12 +++---------
 qapi/qapi-visit-core.c             |  6 +++---
 qapi/qapi-clone-visitor.c          |  2 +-
 qapi/qapi-dealloc-visitor.c        |  2 +-
 qapi/qobject-input-visitor.c       |  2 +-
 tests/test-qobject-input-visitor.c |  2 +-
 qapi/trace-events                  |  2 +-
 9 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index b0e233df76..0caed24942 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -410,15 +410,13 @@ void visit_end_list(Visitor *v, void **list);
  * the qtype of the next thing to be visited, stored in (*@obj)->type.
  * Other visitors will leave @obj unchanged.
  *
- * If @promote_int, treat integers as QTYPE_FLOAT.
- *
  * If successful, this must be paired with visit_end_alternate() with
  * the same @obj to clean up, even if visiting the contents of the
  * alternate fails.
  */
 void visit_start_alternate(Visitor *v, const char *name,
                            GenericAlternate **obj, size_t size,
-                           bool promote_int, Error **errp);
+                           Error **errp);
 
 /*
  * Finish visiting an alternate type.
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index e87709db5c..dcd656ab76 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -71,7 +71,7 @@ struct Visitor
      * optional for output visitors. */
     void (*start_alternate)(Visitor *v, const char *name,
                             GenericAlternate **obj, size_t size,
-                            bool promote_int, Error **errp);
+                            Error **errp);
 
     /* Optional, needed for dealloc visitor */
     void (*end_alternate)(Visitor *v, void **obj);
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index cc447ecacc..bd0b742236 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -161,20 +161,14 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s *obj, Error
 
 
 def gen_visit_alternate(name, variants):
-    promote_int = 'true'
-    ret = ''
-    for var in variants.variants:
-        if var.type.alternate_qtype() == 'QTYPE_QNUM':
-            promote_int = 'false'
-
-    ret += mcgen('''
+    ret = mcgen('''
 
 void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
 {
     Error *err = NULL;
 
     visit_start_alternate(v, name, (GenericAlternate **)obj, sizeof(**obj),
-                          %(promote_int)s, &err);
+                          &err);
     if (err) {
         goto out;
     }
@@ -183,7 +177,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
     }
     switch ((*obj)->type) {
 ''',
-                 c_name=c_name(name), promote_int=promote_int)
+                 c_name=c_name(name))
 
     for var in variants.variants:
         ret += mcgen('''
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 43a09d147d..935a2c5bc9 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -106,15 +106,15 @@ void visit_end_list(Visitor *v, void **obj)
 
 void visit_start_alternate(Visitor *v, const char *name,
                            GenericAlternate **obj, size_t size,
-                           bool promote_int, Error **errp)
+                           Error **errp)
 {
     Error *err = NULL;
 
     assert(obj && size >= sizeof(GenericAlternate));
     assert(!(v->type & VISITOR_OUTPUT) || *obj);
-    trace_visit_start_alternate(v, name, obj, size, promote_int);
+    trace_visit_start_alternate(v, name, obj, size);
     if (v->start_alternate) {
-        v->start_alternate(v, name, obj, size, promote_int, &err);
+        v->start_alternate(v, name, obj, size, &err);
     }
     if (v->type & VISITOR_INPUT) {
         assert(v->start_alternate && !err != !*obj);
diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c
index de756bfb33..ed16d3a17f 100644
--- a/qapi/qapi-clone-visitor.c
+++ b/qapi/qapi-clone-visitor.c
@@ -70,7 +70,7 @@ static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail,
 
 static void qapi_clone_start_alternate(Visitor *v, const char *name,
                                        GenericAlternate **obj, size_t size,
-                                       bool promote_int, Error **errp)
+                                       Error **errp)
 {
     qapi_clone_start_struct(v, name, (void **)obj, size, errp);
 }
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index e39457bc79..fd6f9fb61c 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -38,7 +38,7 @@ static void qapi_dealloc_end_struct(Visitor *v, void **obj)
 
 static void qapi_dealloc_start_alternate(Visitor *v, const char *name,
                                          GenericAlternate **obj, size_t size,
-                                         bool promote_int, Error **errp)
+                                         Error **errp)
 {
 }
 
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 78425a4369..785949ebab 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -366,7 +366,7 @@ static void qobject_input_end_list(Visitor *v, void **obj)
 
 static void qobject_input_start_alternate(Visitor *v, const char *name,
                                           GenericAlternate **obj, size_t size,
-                                          bool promote_int, Error **errp)
+                                          Error **errp)
 {
     QObjectInputVisitor *qiv = to_qiv(v);
     QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 4484980969..5df62c4f9e 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1060,7 +1060,7 @@ static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
     error_free_or_abort(&err);
     visit_start_list(v, "list", NULL, 0, &err);
     error_free_or_abort(&err);
-    visit_start_alternate(v, "alternate", &alt, sizeof(*alt), false, &err);
+    visit_start_alternate(v, "alternate", &alt, sizeof(*alt), &err);
     error_free_or_abort(&err);
     visit_optional(v, "optional", &present);
     g_assert(!present);
diff --git a/qapi/trace-events b/qapi/trace-events
index 339cacf0ad..3b57abaa37 100644
--- a/qapi/trace-events
+++ b/qapi/trace-events
@@ -11,7 +11,7 @@ visit_next_list(void *v, void *tail, size_t size) "v=%p tail=%p size=%zu"
 visit_check_list(void *v) "v=%p"
 visit_end_list(void *v, void *obj) "v=%p obj=%p"
 
-visit_start_alternate(void *v, const char *name, void *obj, size_t size, bool promote_int) "v=%p name=%s obj=%p size=%zu promote_int=%d"
+visit_start_alternate(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
 visit_end_alternate(void *v, void *obj) "v=%p obj=%p"
 
 visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p"
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 06/17] qnum: add uint type
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (4 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 05/17] qapi: remove promote_int Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-15  7:27   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers Marc-André Lureau
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

In order to store integer values superior to INT64_MAX, add a u64
internal representation.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/qnum.h |  4 ++++
 qobject/qnum.c          | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/check-qnum.c      | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+)

diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h
index 0e51427821..89c14e040f 100644
--- a/include/qapi/qmp/qnum.h
+++ b/include/qapi/qmp/qnum.h
@@ -17,6 +17,7 @@
 
 typedef enum {
     QNUM_I64,
+    QNUM_U64,
     QNUM_DOUBLE
 } QNumType;
 
@@ -25,14 +26,17 @@ typedef struct QNum {
     QNumType type;
     union {
         int64_t i64;
+        uint64_t u64;
         double dbl;
     } u;
 } QNum;
 
 QNum *qnum_from_int(int64_t value);
+QNum *qnum_from_uint(uint64_t value);
 QNum *qnum_from_double(double value);
 
 int64_t qnum_get_int(const QNum *qi, Error **errp);
+uint64_t qnum_get_uint(const QNum *qi, Error **errp);
 double qnum_get_double(QNum *qn);
 
 char *qnum_to_string(QNum *qn);
diff --git a/qobject/qnum.c b/qobject/qnum.c
index 8e9dd38350..be6307accf 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -13,6 +13,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qobject.h"
 #include "qemu-common.h"
@@ -34,6 +35,22 @@ QNum *qnum_from_int(int64_t value)
 }
 
 /**
+ * qnum_from_uint(): Create a new QNum from an uint64_t
+ *
+ * Return strong reference.
+ */
+QNum *qnum_from_uint(uint64_t value)
+{
+    QNum *qn = g_new(QNum, 1);
+
+    qobject_init(QOBJECT(qn), QTYPE_QNUM);
+    qn->type = QNUM_U64;
+    qn->u.u64 = value;
+
+    return qn;
+}
+
+/**
  * qnum_from_double(): Create a new QNum from a double
  *
  * Return strong reference.
@@ -57,6 +74,34 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
     switch (qn->type) {
     case QNUM_I64:
         return qn->u.i64;
+    case QNUM_U64:
+        if (qn->u.u64 > INT64_MAX) {
+            error_setg(errp, "The number is too large, use qnum_get_uint()");
+            return 0;
+        }
+        return qn->u.u64;
+    case QNUM_DOUBLE:
+        error_setg(errp, "The number is a float");
+        return 0;
+    }
+
+    g_assert_not_reached();
+}
+
+/**
+ * qnum_get_uint(): Get an unsigned integer from the number
+ */
+uint64_t qnum_get_uint(const QNum *qn, Error **errp)
+{
+    switch (qn->type) {
+    case QNUM_I64:
+        if (qn->u.i64 < 0) {
+            error_setg(errp, "The number is negative");
+            return 0;
+        }
+        return qn->u.i64;
+    case QNUM_U64:
+        return qn->u.u64;
     case QNUM_DOUBLE:
         error_setg(errp, "The number is a float");
         return 0;
@@ -73,6 +118,8 @@ double qnum_get_double(QNum *qn)
     switch (qn->type) {
     case QNUM_I64:
         return qn->u.i64;
+    case QNUM_U64:
+        return qn->u.u64;
     case QNUM_DOUBLE:
         return qn->u.dbl;
     }
@@ -88,6 +135,8 @@ char *qnum_to_string(QNum *qn)
     switch (qn->type) {
     case QNUM_I64:
         return g_strdup_printf("%" PRId64, qn->u.i64);
+    case QNUM_U64:
+        return g_strdup_printf("%" PRIu64, qn->u.u64);
     case QNUM_DOUBLE:
         /* FIXME: snprintf() is locale dependent; but JSON requires
          * numbers to be formatted as if in the C locale. Dependence
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index d08d35e85a..8199546f99 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -36,6 +36,21 @@ static void qnum_from_int_test(void)
     g_free(qi);
 }
 
+static void qnum_from_uint_test(void)
+{
+    QNum *qu;
+    const int value = UINT_MAX;
+
+    qu = qnum_from_int(value);
+    g_assert(qu != NULL);
+    g_assert(qu->u.u64 == value);
+    g_assert(qu->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qu)) == QTYPE_QNUM);
+
+    // destroy doesn't exit yet
+    g_free(qu);
+}
+
 static void qnum_from_double_test(void)
 {
     QNum *qf;
@@ -73,6 +88,37 @@ static void qnum_get_int_test(void)
     QDECREF(qi);
 }
 
+static void qnum_get_uint_test(void)
+{
+    QNum *qn;
+    const int value = 123456;
+    Error *err = NULL;
+
+    qn = qnum_from_uint(value);
+    g_assert(qnum_get_uint(qn, &error_abort) == value);
+    QDECREF(qn);
+
+    qn = qnum_from_int(value);
+    g_assert(qnum_get_uint(qn, &error_abort) == value);
+    QDECREF(qn);
+
+    qn = qnum_from_int(-1);
+    qnum_get_uint(qn, &err);
+    error_free_or_abort(&err);
+    QDECREF(qn);
+
+    qn = qnum_from_uint(-1ULL);
+    qnum_get_int(qn, &err);
+    error_free_or_abort(&err);
+    QDECREF(qn);
+
+    /* invalid case */
+    qn = qnum_from_double(0.42);
+    qnum_get_uint(qn, &err);
+    error_free_or_abort(&err);
+    QDECREF(qn);
+}
+
 static void qobject_to_qnum_test(void)
 {
     QNum *qn;
@@ -111,6 +157,9 @@ static void qnum_destroy_test(void)
     qn = qnum_from_int(0);
     QDECREF(qn);
 
+    qn = qnum_from_uint(0);
+    QDECREF(qn);
+
     qn = qnum_from_double(0.42);
     QDECREF(qn);
 }
@@ -120,10 +169,12 @@ int main(int argc, char **argv)
     g_test_init(&argc, &argv, NULL);
 
     g_test_add_func("/qnum/from_int", qnum_from_int_test);
+    g_test_add_func("/qnum/from_uint", qnum_from_uint_test);
     g_test_add_func("/qnum/from_double", qnum_from_double_test);
     g_test_add_func("/qnum/destroy", qnum_destroy_test);
     g_test_add_func("/qnum/from_int64", qnum_from_int64_test);
     g_test_add_func("/qnum/get_int", qnum_get_int_test);
+    g_test_add_func("/qnum/get_uint", qnum_get_uint_test);
     g_test_add_func("/qnum/to_qnum", qobject_to_qnum_test);
     g_test_add_func("/qnum/to_string", qnum_to_string_test);
 
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (5 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 06/17] qnum: add uint type Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-15 13:59   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt Marc-André Lureau
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Switch strtoll() usage to qemu_strtoi64() helper while at it.

Replace temporarily the error in qnum_get_int() with values >INT64_MAX
until the visitor is updated.

Add a few tests for large numbers.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qobject/json-lexer.c               |  4 ++++
 qobject/json-parser.c              | 30 ++++++++++++++++++++++--------
 qobject/qnum.c                     |  4 ++--
 tests/check-qjson.c                | 28 ++++++++++++++++++++++++++++
 tests/check-qnum.c                 |  9 +++++----
 tests/test-qobject-input-visitor.c |  7 ++-----
 6 files changed, 63 insertions(+), 19 deletions(-)

diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
index af4a75e05b..a0beb0b106 100644
--- a/qobject/json-lexer.c
+++ b/qobject/json-lexer.c
@@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
     /* escape */
     [IN_ESCAPE_LL] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_L] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_LL,
     },
 
     [IN_ESCAPE_I64] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_I6] = {
@@ -247,6 +250,7 @@ static const uint8_t json_lexer[][256] =  {
     },
 
     [IN_ESCAPE] = {
+        ['u'] = JSON_ESCAPE,
         ['d'] = JSON_ESCAPE,
         ['i'] = JSON_ESCAPE,
         ['p'] = JSON_ESCAPE,
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index f431854ba1..fa15c762d3 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -12,6 +12,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "qapi/qmp/types.h"
@@ -472,6 +473,13 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
     } else if (!strcmp(token->str, "%lld") ||
                !strcmp(token->str, "%I64d")) {
         return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
+    } else if (!strcmp(token->str, "%u")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int)));
+    } else if (!strcmp(token->str, "%lu")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long)));
+    } else if (!strcmp(token->str, "%llu") ||
+               !strcmp(token->str, "%I64u")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long)));
     } else if (!strcmp(token->str, "%s")) {
         return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
     } else if (!strcmp(token->str, "%f")) {
@@ -494,22 +502,28 @@ static QObject *parse_literal(JSONParserContext *ctxt)
         /* A possibility exists that this is a whole-valued float where the
          * fractional part was left out due to being 0 (.0). It's not a big
          * deal to treat these as ints in the parser, so long as users of the
-         * resulting QObject know to expect a QNum in place of a QNum in
-         * cases like these.
+         * resulting QObject know to expect a QNum that will handle
+         * implicit conversions to the expected type.
          *
-         * However, in some cases these values will overflow/underflow a
-         * QNum/int64 container, thus we should assume these are to be handled
-         * as QNums/doubles rather than silently changing their values.
+         * However, in some cases these values will overflow/underflow
+         * a QNum/int64 container, thus we should assume these are to
+         * be handled as QNum/uint64 or QNums/doubles rather than
+         * silently changing their values.
          *
-         * strtoll() indicates these instances by setting errno to ERANGE
+         * qemu_strto*() indicates these instances by setting errno to ERANGE
          */
         int64_t value;
+        uint64_t uvalue;
 
-        errno = 0; /* strtoll doesn't set errno on success */
-        value = strtoll(token->str, NULL, 10);
+        qemu_strtoi64(token->str, NULL, 10, &value);
         if (errno != ERANGE) {
             return QOBJECT(qnum_from_int(value));
         }
+
+        qemu_strtou64(token->str, NULL, 10, &uvalue);
+        if (errno != ERANGE) {
+            return QOBJECT(qnum_from_uint(uvalue));
+        }
         /* fall through to JSON_FLOAT */
     }
     case JSON_FLOAT:
diff --git a/qobject/qnum.c b/qobject/qnum.c
index be6307accf..2f87952db8 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
         return qn->u.i64;
     case QNUM_U64:
         if (qn->u.u64 > INT64_MAX) {
-            error_setg(errp, "The number is too large, use qnum_get_uint()");
-            return 0;
+            /* temporarily accepts to cast to i64 until visitor is switched */
+            error_report("The number is too large, use qnum_get_uint()");
         }
         return qn->u.u64;
     case QNUM_DOUBLE:
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index c432aebf13..57c2366dc3 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -904,6 +904,33 @@ static void simple_number(void)
     }
 }
 
+static void large_number(void)
+{
+    const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
+    const char *gtu64 = "18446744073709551616"; /* 2^64 */
+    QNum *qnum;
+    QString *str;
+
+    qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpuint(qnum_get_uint(qnum, &error_abort),
+                     ==, 18446744073709551615U);
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
+    QDECREF(str);
+    QDECREF(qnum);
+
+    qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709551616.0);
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
+    QDECREF(str);
+    QDECREF(qnum);
+}
+
 static void float_number(void)
 {
     int i;
@@ -1468,6 +1495,7 @@ int main(int argc, char **argv)
     g_test_add_func("/literals/string/vararg", vararg_string);
 
     g_test_add_func("/literals/number/simple", simple_number);
+    g_test_add_func("/literals/number/large", large_number);
     g_test_add_func("/literals/number/float", float_number);
     g_test_add_func("/literals/number/vararg", vararg_number);
 
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index 8199546f99..9a22af3d0e 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -107,10 +107,11 @@ static void qnum_get_uint_test(void)
     error_free_or_abort(&err);
     QDECREF(qn);
 
-    qn = qnum_from_uint(-1ULL);
-    qnum_get_int(qn, &err);
-    error_free_or_abort(&err);
-    QDECREF(qn);
+    /* temporarily disabled until visitor is switched */
+    /* qn = qnum_from_uint(-1ULL); */
+    /* qnum_get_int(qn, &err); */
+    /* error_free_or_abort(&err); */
+    /* QDECREF(qn); */
 
     /* invalid case */
     qn = qnum_from_double(0.42);
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 5df62c4f9e..276a6b4427 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -119,7 +119,6 @@ static void test_visitor_in_int(TestInputVisitorData *data,
 static void test_visitor_in_uint(TestInputVisitorData *data,
                                 const void *unused)
 {
-    Error *err = NULL;
     uint64_t res = 0;
     int value = 42;
     Visitor *v;
@@ -136,12 +135,10 @@ static void test_visitor_in_uint(TestInputVisitorData *data,
     visit_type_uint64(v, NULL, &res, &error_abort);
     g_assert_cmpuint(res, ==, (uint64_t)-value);
 
-    /* BUG: value between INT64_MAX+1 and UINT64_MAX rejected */
-
     v = visitor_input_test_init(data, "18446744073709551574");
 
-    visit_type_uint64(v, NULL, &res, &err);
-    error_free_or_abort(&err);
+    visit_type_uint64(v, NULL, &res, &error_abort);
+    g_assert_cmpuint(res, ==, 18446744073709551574U);
 }
 
 static void test_visitor_in_int_overflow(TestInputVisitorData *data,
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (6 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-16 17:31   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX Marc-André Lureau
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Switch to use QNum/uint where appropriate to remove i64 limitation.

The input visitor will cast i64 input to u64 for compatibility
reasons (existing json QMP client already use negative i64 for large
u64, and expect an implicit cast in qemu).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi/qobject-input-visitor.c        | 13 +++++++++++--
 qapi/qobject-output-visitor.c       |  3 +--
 tests/test-qobject-output-visitor.c | 21 ++++++++++++++++-----
 3 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 785949ebab..72cefcf677 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -420,9 +420,9 @@ static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
 static void qobject_input_type_uint64(Visitor *v, const char *name,
                                       uint64_t *obj, Error **errp)
 {
-    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
     QObjectInputVisitor *qiv = to_qiv(v);
     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+    Error *err = NULL;
     QNum *qnum;
 
     if (!qobj) {
@@ -435,7 +435,16 @@ static void qobject_input_type_uint64(Visitor *v, const char *name,
         return;
     }
 
-    *obj = qnum_get_int(qnum, errp);
+    /* XXX: compatibility case, accept negative values as u64 */
+    *obj = qnum_get_int(qnum, &err);
+
+    if (err) {
+        error_free(err);
+        err = NULL;
+        *obj = qnum_get_uint(qnum, &err);
+    }
+
+    error_propagate(errp, err);
 }
 
 static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
index 2ca5093b22..70be84ccb5 100644
--- a/qapi/qobject-output-visitor.c
+++ b/qapi/qobject-output-visitor.c
@@ -150,9 +150,8 @@ static void qobject_output_type_int64(Visitor *v, const char *name,
 static void qobject_output_type_uint64(Visitor *v, const char *name,
                                        uint64_t *obj, Error **errp)
 {
-    /* FIXME values larger than INT64_MAX become negative */
     QObjectOutputVisitor *qov = to_qov(v);
-    qobject_output_add(qov, name, qnum_from_int(*obj));
+    qobject_output_add(qov, name, qnum_from_uint(*obj));
 }
 
 static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 66a682d5a8..767818e393 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -595,15 +595,26 @@ static void check_native_list(QObject *qobj,
     qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
 
     switch (kind) {
-    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
-    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
-    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
-    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
     case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
     case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
     case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
     case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
-        /* all integer elements in JSON arrays get stored into QNums when
+        for (i = 0; i < 32; i++) {
+            QObject *tmp;
+            QNum *qvalue;
+            tmp = qlist_peek(qlist);
+            g_assert(tmp);
+            qvalue = qobject_to_qnum(tmp);
+            g_assert_cmpuint(qnum_get_uint(qvalue, &error_abort), ==, i);
+            qobject_decref(qlist_pop(qlist));
+        }
+        break;
+
+    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
+    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
+    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
+    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
+        /* all integer elements in JSON arrays get stored into QInts when
          * we convert to QObjects, so we can check them all in the same
          * fashion, so simply fall through here
          */
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (7 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-16 17:35   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter Marc-André Lureau
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Now that the visitor has been switch to use qnum_uint, fix the bad
get_int() to use get_uint() instead. Remove compatibility code.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/i386/acpi-build.c | 2 +-
 qobject/qnum.c       | 4 ++--
 tests/check-qnum.c   | 9 ++++-----
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ec3ae7fa85..767da5d78e 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2585,7 +2585,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
     if (!o) {
         return false;
     }
-    mcfg->mcfg_base = qnum_get_int(qobject_to_qnum(o), &error_abort);
+    mcfg->mcfg_base = qnum_get_uint(qobject_to_qnum(o), &error_abort);
     qobject_decref(o);
 
     o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
diff --git a/qobject/qnum.c b/qobject/qnum.c
index 2f87952db8..be6307accf 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
         return qn->u.i64;
     case QNUM_U64:
         if (qn->u.u64 > INT64_MAX) {
-            /* temporarily accepts to cast to i64 until visitor is switched */
-            error_report("The number is too large, use qnum_get_uint()");
+            error_setg(errp, "The number is too large, use qnum_get_uint()");
+            return 0;
         }
         return qn->u.u64;
     case QNUM_DOUBLE:
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index 9a22af3d0e..8199546f99 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -107,11 +107,10 @@ static void qnum_get_uint_test(void)
     error_free_or_abort(&err);
     QDECREF(qn);
 
-    /* temporarily disabled until visitor is switched */
-    /* qn = qnum_from_uint(-1ULL); */
-    /* qnum_get_int(qn, &err); */
-    /* error_free_or_abort(&err); */
-    /* QDECREF(qn); */
+    qn = qnum_from_uint(-1ULL);
+    qnum_get_int(qn, &err);
+    error_free_or_abort(&err);
+    QDECREF(qn);
 
     /* invalid case */
     qn = qnum_from_double(0.42);
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (8 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-16 17:41   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 11/17] object: use more specific property type names Marc-André Lureau
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qom/object.h | 23 +++++++++++++++++++++++
 qom/object.c         | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/qom/object.h b/include/qom/object.h
index cd0f412ce9..abaeb8cf4e 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1094,6 +1094,29 @@ int64_t object_property_get_int(Object *obj, const char *name,
                                 Error **errp);
 
 /**
+ * object_property_set_uint:
+ * @value: the value to be written to the property
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Writes an unsigned integer value to a property.
+ */
+void object_property_set_uint(Object *obj, uint64_t value,
+                              const char *name, Error **errp);
+
+/**
+ * object_property_get_uint:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: the value of the property, converted to an unsigned integer, or 0
+ * an error occurs (including when the property value is not an integer).
+ */
+uint64_t object_property_get_uint(Object *obj, const char *name,
+                                  Error **errp);
+
+/**
  * object_property_get_enum:
  * @obj: the object
  * @name: the name of the property
diff --git a/qom/object.c b/qom/object.c
index c1644dbcb7..a9259e330d 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1221,6 +1221,39 @@ int64_t object_property_get_int(Object *obj, const char *name,
     return retval;
 }
 
+void object_property_set_uint(Object *obj, uint64_t value,
+                             const char *name, Error **errp)
+{
+    QNum *qn = qnum_from_uint(value);
+    object_property_set_qobject(obj, QOBJECT(qn), name, errp);
+    QDECREF(qn);
+}
+
+uint64_t object_property_get_uint(Object *obj, const char *name,
+                                  Error **errp)
+{
+    QObject *ret = object_property_get_qobject(obj, name, errp);
+    Error *err = NULL;
+    QNum *qnum;
+    uint64_t retval;
+
+    if (!ret) {
+        return 0;
+    }
+    qnum = qobject_to_qnum(ret);
+    if (qnum) {
+        retval = qnum_get_uint(qnum, &err);
+    }
+
+    if (!qnum || err) {
+        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
+        retval = 0;
+    }
+
+    qobject_decref(ret);
+    return retval;
+}
+
 typedef struct EnumProperty {
     const char * const *strings;
     int (*get)(Object *, Error **);
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 11/17] object: use more specific property type names
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (9 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-17  8:49   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate Marc-André Lureau
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Use the actual unsigned integer type name (this should't break since
property type aren't directly accessed from outside it seems).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 backends/cryptodev.c |  2 +-
 hw/pci-host/piix.c   |  8 ++++----
 hw/pci-host/q35.c    | 10 +++++-----
 hw/ppc/pnv.c         |  2 +-
 net/dump.c           |  2 +-
 net/filter-buffer.c  |  2 +-
 6 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/backends/cryptodev.c b/backends/cryptodev.c
index 832f056266..1764c179fe 100644
--- a/backends/cryptodev.c
+++ b/backends/cryptodev.c
@@ -222,7 +222,7 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc, Error **errp)
 
 static void cryptodev_backend_instance_init(Object *obj)
 {
-    object_property_add(obj, "queues", "int",
+    object_property_add(obj, "queues", "uint32",
                           cryptodev_backend_get_queues,
                           cryptodev_backend_set_queues,
                           NULL, NULL, NULL);
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f9218aa952..9aed6225bf 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -279,19 +279,19 @@ static void i440fx_pcihost_initfn(Object *obj)
     memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
                           "pci-conf-data", 4);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
                         i440fx_pcihost_get_pci_hole_start,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
                         i440fx_pcihost_get_pci_hole_end,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
                         i440fx_pcihost_get_pci_hole64_start,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
                         i440fx_pcihost_get_pci_hole64_end,
                         NULL, NULL, NULL, NULL);
 }
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 344f77b10c..5438be8253 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -176,23 +176,23 @@ static void q35_host_initfn(Object *obj)
     qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
     qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
                         q35_host_get_pci_hole_start,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
                         q35_host_get_pci_hole_end,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
                         q35_host_get_pci_hole64_start,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
+    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
                         q35_host_get_pci_hole64_end,
                         NULL, NULL, NULL, NULL);
 
-    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
+    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint32",
                         q35_host_get_mmcfg_size,
                         NULL, NULL, NULL, NULL);
 
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d4bcdb027f..a964354081 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1110,7 +1110,7 @@ static void powernv_machine_initfn(Object *obj)
 
 static void powernv_machine_class_props_init(ObjectClass *oc)
 {
-    object_class_property_add(oc, "num-chips", "uint32_t",
+    object_class_property_add(oc, "num-chips", "uint32",
                               pnv_get_num_chips, pnv_set_num_chips,
                               NULL, NULL, NULL);
     object_class_property_set_description(oc, "num-chips",
diff --git a/net/dump.c b/net/dump.c
index 89a149b5dd..7f4d3fda52 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -325,7 +325,7 @@ static void filter_dump_instance_init(Object *obj)
 
     nfds->maxlen = 65536;
 
-    object_property_add(obj, "maxlen", "int", filter_dump_get_maxlen,
+    object_property_add(obj, "maxlen", "uint32", filter_dump_get_maxlen,
                         filter_dump_set_maxlen, NULL, NULL, NULL);
     object_property_add_str(obj, "file", file_dump_get_filename,
                             file_dump_set_filename, NULL);
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index cc6bd94445..9ce96aaa35 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -191,7 +191,7 @@ out:
 
 static void filter_buffer_init(Object *obj)
 {
-    object_property_add(obj, "interval", "int",
+    object_property_add(obj, "interval", "uint32",
                         filter_buffer_get_interval,
                         filter_buffer_set_interval, NULL, NULL, NULL);
 }
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (10 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 11/17] object: use more specific property type names Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-17 11:09   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type Marc-André Lureau
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Use unsigned type for various properties.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/hw/qdev-core.h       |  5 +++-
 include/hw/qdev-properties.h | 67 ++++++++++++++++++++++++++------------------
 hw/block/fdc.c               | 54 +++++++++++++++++------------------
 hw/core/qdev-properties.c    |  8 +++---
 hw/core/qdev.c               | 24 ++++++++++------
 hw/net/e1000e.c              | 14 ++++-----
 6 files changed, 96 insertions(+), 76 deletions(-)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 0f21a500cd..ac10458650 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -225,7 +225,10 @@ struct Property {
     PropertyInfo *info;
     ptrdiff_t    offset;
     uint8_t      bitnr;
-    int64_t      defval;
+    union {
+        int64_t i;
+        uint64_t u;
+    } defval;
     int          arrayoffset;
     PropertyInfo *arrayinfo;
     int          arrayfieldsize;
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 16d5d0629b..ca9c550fa3 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -37,36 +37,47 @@ extern PropertyInfo qdev_prop_arraylen;
         .offset    = offsetof(_state, _field)                    \
             + type_check(_type, typeof_field(_state, _field)),   \
         }
-#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
+
+#define DEFINE_PROP_INT(_name, _state, _field, _defval, _prop, _type) { \
         .name      = (_name),                                           \
         .info      = &(_prop),                                          \
         .offset    = offsetof(_state, _field)                           \
             + type_check(_type,typeof_field(_state, _field)),           \
-        .defval    = (_type)_defval,                                    \
+        .defval.i  = (_type)_defval,                                    \
         }
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
-        .name      = (_name),                                    \
-        .info      = &(qdev_prop_bit),                           \
-        .bitnr    = (_bit),                                      \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(uint32_t,typeof_field(_state, _field)), \
-        .defval    = (bool)_defval,                              \
+
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {         \
+        .name      = (_name),                                           \
+        .info      = &(qdev_prop_bit),                                  \
+        .bitnr    = (_bit),                                             \
+        .offset    = offsetof(_state, _field)                           \
+            + type_check(uint32_t, typeof_field(_state, _field)),        \
+        .defval.u   = (bool)_defval,                                    \
         }
+
+#define DEFINE_PROP_UINT(_name, _state, _field, _defval, _prop, _type) { \
+        .name      = (_name),                                           \
+        .info      = &(_prop),                                          \
+        .offset    = offsetof(_state, _field)                           \
+            + type_check(_type, typeof_field(_state, _field)),          \
+        .defval.u  = (_type)_defval,                                    \
+        }
+
 #define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) {       \
         .name      = (_name),                                           \
         .info      = &(qdev_prop_bit64),                                \
         .bitnr    = (_bit),                                             \
         .offset    = offsetof(_state, _field)                           \
             + type_check(uint64_t, typeof_field(_state, _field)),       \
-        .defval    = (bool)_defval,                                     \
+        .defval.u  = (bool)_defval,                                     \
         }
 
-#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) {       \
-        .name      = (_name),                                    \
-        .info      = &(qdev_prop_bool),                          \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(bool, typeof_field(_state, _field)),    \
-        .defval    = (bool)_defval,                              \
+#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) {      \
+        .name      = (_name),                                   \
+        .info      = &(qdev_prop_bool),                         \
+        .offset    = offsetof(_state, _field)                   \
+            + type_check(bool, typeof_field(_state, _field)),   \
+        .defval.u    = (bool)_defval,                           \
         }
 
 #define PROP_ARRAY_LEN_PREFIX "len-"
@@ -107,19 +118,19 @@ extern PropertyInfo qdev_prop_arraylen;
         }
 
 #define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
+    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
 #define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
+    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
 #define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
 #define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
+    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
 #define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
 #define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_size, uint64_t)
+    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_size, uint64_t)
 #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
+    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
 
 /*
  * Please avoid pointer properties.  If you must use them, you must
@@ -153,17 +164,17 @@ extern PropertyInfo qdev_prop_arraylen;
 #define DEFINE_PROP_MACADDR(_n, _s, _f)         \
     DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
 #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
+    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
 #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
+    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
                         LostTickPolicy)
 #define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
+    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
                         BlockdevOnError)
 #define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
+    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
 #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \
-    DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
+    DEFINE_PROP_UINT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
 #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
     DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
 
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 2e629b398b..07ce4a0d20 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -511,9 +511,9 @@ typedef struct FloppyDrive {
 static Property floppy_drive_properties[] = {
     DEFINE_PROP_UINT32("unit", FloppyDrive, unit, -1),
     DEFINE_BLOCK_PROPERTIES(FloppyDrive, conf),
-    DEFINE_PROP_DEFAULT("drive-type", FloppyDrive, type,
-                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
+    DEFINE_PROP_INT("drive-type", FloppyDrive, type,
+                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -2805,15 +2805,15 @@ static Property isa_fdc_properties[] = {
     DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.qdev_for_drives[1].blk),
     DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
                     0, true),
-    DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
-                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
-    DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
-                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
-    DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
-                        FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
+    DEFINE_PROP_INT("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
+                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
+    DEFINE_PROP_INT("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
+                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
+    DEFINE_PROP_INT("fallback", FDCtrlISABus, state.fallback,
+                    FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -2862,15 +2862,15 @@ static const VMStateDescription vmstate_sysbus_fdc ={
 static Property sysbus_fdc_properties[] = {
     DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.qdev_for_drives[0].blk),
     DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.qdev_for_drives[1].blk),
-    DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
-                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
-    DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
-                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
-    DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
-                        FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
+    DEFINE_PROP_INT("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
+                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
+    DEFINE_PROP_INT("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
+                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
+    DEFINE_PROP_INT("fallback", FDCtrlISABus, state.fallback,
+                    FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -2891,12 +2891,12 @@ static const TypeInfo sysbus_fdc_info = {
 
 static Property sun4m_fdc_properties[] = {
     DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.qdev_for_drives[0].blk),
-    DEFINE_PROP_DEFAULT("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
-                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
-    DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
-                        FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
-                        FloppyDriveType),
+    DEFINE_PROP_INT("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
+                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
+    DEFINE_PROP_INT("fallback", FDCtrlISABus, state.fallback,
+                    FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
+                    FloppyDriveType),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index fa3617db2d..f87327b132 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -982,17 +982,17 @@ void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
 
 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
 {
-    object_property_set_int(OBJECT(dev), value, name, &error_abort);
+    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
 }
 
 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
 {
-    object_property_set_int(OBJECT(dev), value, name, &error_abort);
+    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
 }
 
 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
 {
-    object_property_set_int(OBJECT(dev), value, name, &error_abort);
+    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
 }
 
 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
@@ -1002,7 +1002,7 @@ void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
 
 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
 {
-    object_property_set_int(OBJECT(dev), value, name, &error_abort);
+    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
 }
 
 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 83b0297755..b9313546f7 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -764,17 +764,21 @@ static bool prop_info_is_bool(const PropertyInfo *info)
 
 static bool prop_info_is_int(const PropertyInfo *info)
 {
+    return info == &qdev_prop_int32
+        || info == &qdev_prop_pci_devfn
+        || info == &qdev_prop_on_off_auto
+        || info == &qdev_prop_losttickpolicy
+        || info == &qdev_prop_blockdev_on_error
+        || info == &qdev_prop_bios_chs_trans;
+}
+
+static bool prop_info_is_uint(const PropertyInfo *info)
+{
     return info == &qdev_prop_uint8
         || info == &qdev_prop_uint16
         || info == &qdev_prop_uint32
-        || info == &qdev_prop_int32
         || info == &qdev_prop_uint64
         || info == &qdev_prop_size
-        || info == &qdev_prop_pci_devfn
-        || info == &qdev_prop_on_off_auto
-        || info == &qdev_prop_losttickpolicy
-        || info == &qdev_prop_blockdev_on_error
-        || info == &qdev_prop_bios_chs_trans
         || info == &qdev_prop_blocksize
         || info == &qdev_prop_arraylen;
 }
@@ -819,12 +823,14 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
                                     &error_abort);
 
     if (prop_info_is_bool(prop->info)) {
-        object_property_set_bool(obj, prop->defval, prop->name, &error_abort);
+        object_property_set_bool(obj, prop->defval.u, prop->name, &error_abort);
     } else if (prop->info->enum_table) {
-        object_property_set_str(obj, prop->info->enum_table[prop->defval],
+        object_property_set_str(obj, prop->info->enum_table[prop->defval.i],
                                 prop->name, &error_abort);
     } else if (prop_info_is_int(prop->info)) {
-        object_property_set_int(obj, prop->defval, prop->name, &error_abort);
+        object_property_set_int(obj, prop->defval.i, prop->name, &error_abort);
+    } else if (prop_info_is_uint(prop->info)) {
+        object_property_set_uint(obj, prop->defval.u, prop->name, &error_abort);
     }
 }
 
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 6e234938db..4e4cc9b52f 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -645,13 +645,13 @@ static PropertyInfo e1000e_prop_disable_vnet,
 
 static Property e1000e_properties[] = {
     DEFINE_NIC_PROPERTIES(E1000EState, conf),
-    DEFINE_PROP_DEFAULT("disable_vnet_hdr", E1000EState, disable_vnet, false,
-                        e1000e_prop_disable_vnet, bool),
-    DEFINE_PROP_DEFAULT("subsys_ven", E1000EState, subsys_ven,
-                        PCI_VENDOR_ID_INTEL,
-                        e1000e_prop_subsys_ven, uint16_t),
-    DEFINE_PROP_DEFAULT("subsys", E1000EState, subsys, 0,
-                        e1000e_prop_subsys, uint16_t),
+    DEFINE_PROP_INT("disable_vnet_hdr", E1000EState, disable_vnet, false,
+                    e1000e_prop_disable_vnet, bool),
+    DEFINE_PROP_INT("subsys_ven", E1000EState, subsys_ven,
+                    PCI_VENDOR_ID_INTEL,
+                    e1000e_prop_subsys_ven, uint16_t),
+    DEFINE_PROP_INT("subsys", E1000EState, subsys, 0,
+                    e1000e_prop_subsys, uint16_t),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (11 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-17 17:42   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type Marc-André Lureau
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Based on underlying property type, use the appropriate getters/setters.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/i386/acpi-build.c      | 12 ++++++------
 hw/pci-host/gpex.c        |  2 +-
 hw/pci-host/q35.c         |  2 +-
 hw/pci-host/xilinx-pcie.c |  2 +-
 target/i386/cpu.c         |  2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 767da5d78e..1707fae9bf 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -149,21 +149,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_int(qobject_to_qnum(o), &error_abort);
+        pm->s3_disabled = qnum_get_uint(qobject_to_qnum(o), &error_abort);
     } 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_int(qobject_to_qnum(o), &error_abort);
+        pm->s4_disabled = qnum_get_uint(qobject_to_qnum(o), &error_abort);
     } 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_int(qobject_to_qnum(o), &error_abort);
+        pm->s4_val = qnum_get_uint(qobject_to_qnum(o), &error_abort);
     } else {
         pm->s4_val = false;
     }
@@ -499,7 +499,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) {
-        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
+        uint64_t bsel_val = qnum_get_uint(qobject_to_qnum(bsel), &error_abort);
 
         aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
         notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
@@ -609,7 +609,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) {
-        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
+        uint64_t bsel_val = qnum_get_uint(qobject_to_qnum(bsel), &error_abort);
         aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
         aml_append(method,
             aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
@@ -2590,7 +2590,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 
     o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
     assert(o);
-    mcfg->mcfg_size = qnum_get_int(qobject_to_qnum(o), &error_abort);
+    mcfg->mcfg_size = qnum_get_uint(qobject_to_qnum(o), &error_abort);
     qobject_decref(o);
     return true;
 }
diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
index 66055ee5cc..8d3a64008c 100644
--- a/hw/pci-host/gpex.c
+++ b/hw/pci-host/gpex.c
@@ -94,7 +94,7 @@ static void gpex_host_initfn(Object *obj)
 
     object_initialize(root, sizeof(*root), TYPE_GPEX_ROOT_DEVICE);
     object_property_add_child(obj, "gpex_root", OBJECT(root), NULL);
-    qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
+    qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
     qdev_prop_set_bit(DEVICE(root), "multifunction", false);
 }
 
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 5438be8253..3cbe8cfcea 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -173,7 +173,7 @@ static void q35_host_initfn(Object *obj)
 
     object_initialize(&s->mch, sizeof(s->mch), TYPE_MCH_PCI_DEVICE);
     object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
-    qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
+    qdev_prop_set_int32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
     qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
 
     object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c
index 8b71e2d950..461ed41151 100644
--- a/hw/pci-host/xilinx-pcie.c
+++ b/hw/pci-host/xilinx-pcie.c
@@ -150,7 +150,7 @@ static void xilinx_pcie_host_init(Object *obj)
 
     object_initialize(root, sizeof(*root), TYPE_XILINX_PCIE_ROOT);
     object_property_add_child(obj, "root", OBJECT(root), NULL);
-    qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
+    qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
     qdev_prop_set_bit(DEVICE(root), "multifunction", false);
 }
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1e8a5b55c0..5bb8131bb8 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -3191,7 +3191,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
                               OBJECT(cpu->apic_state), &error_abort);
     object_unref(OBJECT(cpu->apic_state));
 
-    qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
+    qdev_prop_set_int32(cpu->apic_state, "id", cpu->apic_id);
     /* TODO: convert to link<> */
     apic = APIC_COMMON(cpu->apic_state);
     apic->cpu = cpu;
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (12 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-13 20:49   ` Philippe Mathieu-Daudé
  2017-05-18 12:57   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate Marc-André Lureau
                   ` (4 subsequent siblings)
  18 siblings, 2 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Use a more specific bool type.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/acpi/ich9.c       | 24 ++++++++++++------------
 hw/acpi/piix4.c      |  8 ++++----
 hw/i386/acpi-build.c |  5 +++--
 3 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 5c279bbaca..3bd8c4bcf5 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -359,9 +359,9 @@ static void ich9_pm_get_disable_s3(Object *obj, Visitor *v, const char *name,
                                    void *opaque, Error **errp)
 {
     ICH9LPCPMRegs *pm = opaque;
-    uint8_t value = pm->disable_s3;
+    bool value = pm->disable_s3;
 
-    visit_type_uint8(v, name, &value, errp);
+    visit_type_bool(v, name, &value, errp);
 }
 
 static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, const char *name,
@@ -369,9 +369,9 @@ static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, const char *name,
 {
     ICH9LPCPMRegs *pm = opaque;
     Error *local_err = NULL;
-    uint8_t value;
+    bool value;
 
-    visit_type_uint8(v, name, &value, &local_err);
+    visit_type_bool(v, name, &value, &local_err);
     if (local_err) {
         goto out;
     }
@@ -384,9 +384,9 @@ static void ich9_pm_get_disable_s4(Object *obj, Visitor *v, const char *name,
                                    void *opaque, Error **errp)
 {
     ICH9LPCPMRegs *pm = opaque;
-    uint8_t value = pm->disable_s4;
+    bool value = pm->disable_s4;
 
-    visit_type_uint8(v, name, &value, errp);
+    visit_type_bool(v, name, &value, errp);
 }
 
 static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, const char *name,
@@ -394,9 +394,9 @@ static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, const char *name,
 {
     ICH9LPCPMRegs *pm = opaque;
     Error *local_err = NULL;
-    uint8_t value;
+    bool value;
 
-    visit_type_uint8(v, name, &value, &local_err);
+    visit_type_bool(v, name, &value, &local_err);
     if (local_err) {
         goto out;
     }
@@ -447,8 +447,8 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
     static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
     pm->acpi_memory_hotplug.is_enabled = true;
     pm->cpu_hotplug_legacy = true;
-    pm->disable_s3 = 0;
-    pm->disable_s4 = 0;
+    pm->disable_s3 = false;
+    pm->disable_s4 = false;
     pm->s4_val = 2;
 
     object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
@@ -466,11 +466,11 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
                              ich9_pm_get_cpu_hotplug_legacy,
                              ich9_pm_set_cpu_hotplug_legacy,
                              NULL);
-    object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
+    object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "bool",
                         ich9_pm_get_disable_s3,
                         ich9_pm_set_disable_s3,
                         NULL, pm, NULL);
-    object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8",
+    object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "bool",
                         ich9_pm_get_disable_s4,
                         ich9_pm_set_disable_s4,
                         NULL, pm, NULL);
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index a553a7e110..74692336b5 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -83,8 +83,8 @@ typedef struct PIIX4PMState {
     AcpiPciHpState acpi_pci_hotplug;
     bool use_acpi_pci_hotplug;
 
-    uint8_t disable_s3;
-    uint8_t disable_s4;
+    bool disable_s3;
+    bool disable_s4;
     uint8_t s4_val;
 
     bool cpu_hotplug_legacy;
@@ -670,8 +670,8 @@ static void piix4_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
 
 static Property piix4_pm_properties[] = {
     DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
-    DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
-    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
+    DEFINE_PROP_BOOL(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, false),
+    DEFINE_PROP_BOOL(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, false),
     DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
     DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
                      use_acpi_pci_hotplug, true),
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1707fae9bf..27ad420914 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -22,6 +22,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/qmp/types.h"
 #include "acpi-build.h"
 #include "qemu-common.h"
 #include "qemu/bitmap.h"
@@ -149,14 +150,14 @@ 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), &error_abort);
+        pm->s3_disabled = qbool_get_bool(qobject_to_qbool(o));
     } 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), &error_abort);
+        pm->s4_disabled = qbool_get_bool(qobject_to_qbool(o));
     } else {
         pm->s4_disabled = false;
     }
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (13 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-18 15:20   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint Marc-André Lureau
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

All those property usages are associated with unsigned integers, so use
appropriate getter/setter.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/hw/isa/isa.h         |  2 +-
 hw/acpi/memory_hotplug.c     | 10 ++++----
 hw/acpi/nvdimm.c             | 10 ++++----
 hw/acpi/pcihp.c              |  6 ++---
 hw/arm/aspeed.c              |  4 ++--
 hw/arm/bcm2835_peripherals.c |  9 ++++----
 hw/arm/raspi.c               |  4 ++--
 hw/core/platform-bus.c       |  2 +-
 hw/i386/acpi-build.c         | 55 ++++++++++++++++++++++----------------------
 hw/i386/pc.c                 |  6 ++---
 hw/i386/xen/xen-hvm.c        |  6 ++---
 hw/intc/arm_gicv3_common.c   |  2 +-
 hw/mem/pc-dimm.c             |  5 ++--
 hw/misc/auxbus.c             |  2 +-
 hw/misc/pvpanic.c            |  2 +-
 hw/ppc/pnv_core.c            |  2 +-
 hw/ppc/spapr.c               |  8 ++++---
 numa.c                       |  6 ++---
 target/i386/cpu.c            |  4 ++--
 ui/console.c                 |  4 ++--
 20 files changed, 77 insertions(+), 72 deletions(-)

diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index c2fdd70cdc..95593408ef 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -29,7 +29,7 @@ static inline uint16_t applesmc_port(void)
     Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
 
     if (obj) {
-        return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL);
+        return object_property_get_uint(obj, APPLESMC_PROP_IO_BASE, NULL);
     }
     return 0;
 }
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 210073d283..db3c89ceab 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -83,11 +83,12 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
     o = OBJECT(mdev->dimm);
     switch (addr) {
     case 0x0: /* Lo part of phys address where DIMM is mapped */
-        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) : 0;
+        val = o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) : 0;
         trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
         break;
     case 0x4: /* Hi part of phys address where DIMM is mapped */
-        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
+        val =
+            o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
         trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
         break;
     case 0x8: /* Lo part of DIMM size */
@@ -95,11 +96,12 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
         trace_mhp_acpi_read_size_lo(mem_st->selector, val);
         break;
     case 0xc: /* Hi part of DIMM size */
-        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
+        val =
+            o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
         trace_mhp_acpi_read_size_hi(mem_st->selector, val);
         break;
     case 0x10: /* node proximity for _PXM method */
-        val = o ? object_property_get_int(o, PC_DIMM_NODE_PROP, NULL) : 0;
+        val = o ? object_property_get_uint(o, PC_DIMM_NODE_PROP, NULL) : 0;
         trace_mhp_acpi_read_pxm(mem_st->selector, val);
         break;
     case 0x14: /* pack and return is_* fields */
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 8e7d6ec034..e57027149d 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -236,14 +236,14 @@ static void
 nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
 {
     NvdimmNfitSpa *nfit_spa;
-    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
-                                            NULL);
+    uint64_t addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP,
+                                             NULL);
     uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
                                             NULL);
-    uint32_t node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
-                                            NULL);
+    uint32_t node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
+                                             NULL);
     int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
-                                            NULL);
+                                       NULL);
 
     nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
 
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 3a531a4416..c420a388ea 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -62,10 +62,10 @@ typedef struct AcpiPciHpFind {
 static int acpi_pcihp_get_bsel(PCIBus *bus)
 {
     Error *local_err = NULL;
-    int64_t bsel = object_property_get_int(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
-                                           &local_err);
+    uint64_t bsel = object_property_get_uint(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
+                                             &local_err);
 
-    if (local_err || bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
+    if (local_err || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
         if (local_err) {
             error_free(local_err);
         }
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 283c038814..4af422909f 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -187,8 +187,8 @@ static void aspeed_board_init(MachineState *machine,
      * Allocate RAM after the memory controller has checked the size
      * was valid. If not, a default value is used.
      */
-    ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
-                                       &error_abort);
+    ram_size = object_property_get_uint(OBJECT(&bmc->soc), "ram-size",
+                                        &error_abort);
 
     memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
     memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 369ef1e3bd..b168c6f83e 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -126,7 +126,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
     Object *obj;
     MemoryRegion *ram;
     Error *err = NULL;
-    uint32_t ram_size, vcram_size;
+    uint64_t ram_size, vcram_size;
     int n;
 
     obj = object_property_get_link(OBJECT(dev), "ram", &err);
@@ -208,15 +208,14 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
                                INTERRUPT_ARM_MAILBOX));
 
     /* Framebuffer */
-    vcram_size = (uint32_t)object_property_get_int(OBJECT(s), "vcram-size",
-                                                   &err);
+    vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err);
     if (err) {
         error_propagate(errp, err);
         return;
     }
 
-    object_property_set_int(OBJECT(&s->fb), ram_size - vcram_size,
-                            "vcram-base", &err);
+    object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size,
+                             "vcram-base", &err);
     if (err) {
         error_propagate(errp, err);
         return;
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 2b295f14c4..32cdc98c6d 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -153,8 +153,8 @@ static void raspi2_init(MachineState *machine)
     qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
     object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
 
-    vcram_size = object_property_get_int(OBJECT(&s->soc), "vcram-size",
-                                         &error_abort);
+    vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
+                                          &error_abort);
     setup_boot(machine, 2, machine->ram_size - vcram_size);
 }
 
diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
index 329ac670c0..33d32fbf22 100644
--- a/hw/core/platform-bus.c
+++ b/hw/core/platform-bus.c
@@ -71,7 +71,7 @@ hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev,
         return -1;
     }
 
-    return object_property_get_int(OBJECT(sbdev_mr), "addr", NULL);
+    return object_property_get_uint(OBJECT(sbdev_mr), "addr", NULL);
 }
 
 static void platform_bus_count_irqs(SysBusDevice *sbdev, void *opaque)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 27ad420914..76d27ff024 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -137,9 +137,9 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
         obj = piix;
         pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
         pm->pcihp_io_base =
-            object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
+            object_property_get_uint(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
         pm->pcihp_io_len =
-            object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
+            object_property_get_uint(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
     }
     if (lpc) {
         obj = lpc;
@@ -171,20 +171,21 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
     qobject_decref(o);
 
     /* Fill in mandatory properties */
-    pm->sci_int = object_property_get_int(obj, ACPI_PM_PROP_SCI_INT, NULL);
-
-    pm->acpi_enable_cmd = object_property_get_int(obj,
-                                                  ACPI_PM_PROP_ACPI_ENABLE_CMD,
-                                                  NULL);
-    pm->acpi_disable_cmd = object_property_get_int(obj,
-                                                  ACPI_PM_PROP_ACPI_DISABLE_CMD,
-                                                  NULL);
-    pm->io_base = object_property_get_int(obj, ACPI_PM_PROP_PM_IO_BASE,
-                                          NULL);
-    pm->gpe0_blk = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK,
+    pm->sci_int = object_property_get_uint(obj, ACPI_PM_PROP_SCI_INT, NULL);
+
+    pm->acpi_enable_cmd = object_property_get_uint(obj,
+                                                   ACPI_PM_PROP_ACPI_ENABLE_CMD,
+                                                   NULL);
+    pm->acpi_disable_cmd =
+        object_property_get_uint(obj,
+                                 ACPI_PM_PROP_ACPI_DISABLE_CMD,
+                                 NULL);
+    pm->io_base = object_property_get_uint(obj, ACPI_PM_PROP_PM_IO_BASE,
                                            NULL);
-    pm->gpe0_blk_len = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
-                                               NULL);
+    pm->gpe0_blk = object_property_get_uint(obj, ACPI_PM_PROP_GPE0_BLK,
+                                            NULL);
+    pm->gpe0_blk_len = object_property_get_uint(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
+                                                NULL);
     pm->pcihp_bridge_en =
         object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support",
                                  NULL);
@@ -237,19 +238,19 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64)
     g_assert(pci_host);
 
     range_set_bounds1(hole,
-                      object_property_get_int(pci_host,
-                                              PCI_HOST_PROP_PCI_HOLE_START,
-                                              NULL),
-                      object_property_get_int(pci_host,
-                                              PCI_HOST_PROP_PCI_HOLE_END,
-                                              NULL));
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE_START,
+                                               NULL),
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE_END,
+                                               NULL));
     range_set_bounds1(hole64,
-                      object_property_get_int(pci_host,
-                                              PCI_HOST_PROP_PCI_HOLE64_START,
-                                              NULL),
-                      object_property_get_int(pci_host,
-                                              PCI_HOST_PROP_PCI_HOLE64_END,
-                                              NULL));
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE64_START,
+                                               NULL),
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE64_END,
+                                               NULL));
 }
 
 #define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f3b372a18f..8dc4507aa5 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -347,7 +347,7 @@ static int check_fdc(Object *obj, void *opaque)
         return 0;
     }
 
-    iobase = object_property_get_int(obj, "iobase", &local_err);
+    iobase = object_property_get_uint(obj, "iobase", &local_err);
     if (local_err || iobase != 0x3f0) {
         error_free(local_err);
         return 0;
@@ -1100,7 +1100,7 @@ static void pc_new_cpu(const char *typename, int64_t apic_id, Error **errp)
 
     cpu = object_new(typename);
 
-    object_property_set_int(cpu, apic_id, "apic-id", &local_err);
+    object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
     object_property_set_bool(cpu, true, "realized", &local_err);
 
     object_unref(cpu);
@@ -1560,7 +1560,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
              * and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23,
              * IRQ8 and IRQ2.
              */
-            uint8_t compat = object_property_get_int(OBJECT(hpet),
+            uint8_t compat = object_property_get_uint(OBJECT(hpet),
                     HPET_INTCAP, NULL);
             if (!compat) {
                 qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs);
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index b1c05ffb86..cec259f82d 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -183,9 +183,9 @@ static void xen_ram_init(PCMachineState *pcms,
 {
     MemoryRegion *sysmem = get_system_memory();
     ram_addr_t block_len;
-    uint64_t user_lowmem = object_property_get_int(qdev_get_machine(),
-                                                   PC_MACHINE_MAX_RAM_BELOW_4G,
-                                                   &error_abort);
+    uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
+                                                    PC_MACHINE_MAX_RAM_BELOW_4G,
+                                                    &error_abort);
 
     /* Handle the machine opt max-ram-below-4g.  It is basically doing
      * min(xen limit, user limit).
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index c6493d6c07..e2064cd8c5 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -267,7 +267,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
          *  VLPIS == 0 (virtual LPIs not supported)
          *  PLPIS == 0 (physical LPIs not supported)
          */
-        cpu_affid = object_property_get_int(OBJECT(cpu), "mp-affinity", NULL);
+        cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
         last = (i == s->num_cpu - 1);
 
         /* The CPU mp-affinity property is in MPIDR register format; squash
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 9e8dab0e89..f6def8c239 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -46,7 +46,8 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
     uint64_t existing_dimms_capacity = 0;
     uint64_t addr;
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_uint(OBJECT(dimm),
+                                    PC_DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
@@ -73,7 +74,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
         goto out;
     }
 
-    object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
+    object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
index e4a7ba41de..8a90ddda84 100644
--- a/hw/misc/auxbus.c
+++ b/hw/misc/auxbus.c
@@ -244,7 +244,7 @@ static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent)
 
     monitor_printf(mon, "%*smemory " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
                    indent, "",
-                   object_property_get_int(OBJECT(s->mmio), "addr", NULL),
+                   object_property_get_uint(OBJECT(s->mmio), "addr", NULL),
                    memory_region_size(s->mmio));
 }
 
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index 57da7f2199..2b1e9a6450 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -111,7 +111,7 @@ uint16_t pvpanic_port(void)
     if (!o) {
         return 0;
     }
-    return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
+    return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL);
 }
 
 static Property pvpanic_isa_properties[] = {
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 1b7ec70f03..142bad1e57 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -51,7 +51,7 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
     int thread_index = 0; /* TODO: TCG supports only one thread */
     ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
 
-    core_pir = object_property_get_int(OBJECT(cpu), "core-pir", &error_abort);
+    core_pir = object_property_get_uint(OBJECT(cpu), "core-pir", &error_abort);
 
     /*
      * The PIR of a thread is the core PIR + the thread index. We will
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 80d12d005c..9b9a4e8817 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2582,7 +2582,8 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
         goto out;
     }
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_uint(OBJECT(dimm),
+                                    PC_DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
         goto out;
@@ -2670,7 +2671,8 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
     uint64_t size = memory_region_size(mr);
     uint64_t addr;
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_uint(OBJECT(dimm),
+                                    PC_DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
@@ -2878,7 +2880,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
             error_setg(errp, "Memory hotplug not supported for this machine");
             return;
         }
-        node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
+        node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
         if (*errp) {
             return;
         }
diff --git a/numa.c b/numa.c
index 6fc2393ddd..e32259fedb 100644
--- a/numa.c
+++ b/numa.c
@@ -205,7 +205,7 @@ static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp)
         }
 
         object_ref(o);
-        numa_info[nodenr].node_mem = object_property_get_int(o, "size", NULL);
+        numa_info[nodenr].node_mem = object_property_get_uint(o, "size", NULL);
         numa_info[nodenr].node_memdev = MEMORY_BACKEND(o);
     }
     numa_info[nodenr].present = true;
@@ -527,8 +527,8 @@ static int query_memdev(Object *obj, void *opaque)
         m->value->id = object_property_get_str(obj, "id", NULL);
         m->value->has_id = !!m->value->id;
 
-        m->value->size = object_property_get_int(obj, "size",
-                                                 &error_abort);
+        m->value->size = object_property_get_uint(obj, "size",
+                                                  &error_abort);
         m->value->merge = object_property_get_bool(obj, "merge",
                                                    &error_abort);
         m->value->dump = object_property_get_bool(obj, "dump",
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5bb8131bb8..eb200ef58b 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2324,8 +2324,8 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
      */
 
     /* CPU models only set _minimum_ values for level/xlevel: */
-    object_property_set_int(OBJECT(cpu), def->level, "min-level", errp);
-    object_property_set_int(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
+    object_property_set_uint(OBJECT(cpu), def->level, "min-level", errp);
+    object_property_set_uint(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
 
     object_property_set_int(OBJECT(cpu), def->family, "family", errp);
     object_property_set_int(OBJECT(cpu), def->model, "model", errp);
diff --git a/ui/console.c b/ui/console.c
index ac66b3c910..ad3f7c6a2c 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1872,8 +1872,8 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
         if (DEVICE(obj) != dev) {
             continue;
         }
-        h = object_property_get_int(OBJECT(consoles[i]),
-                                    "head", &error_abort);
+        h = object_property_get_uint(OBJECT(consoles[i]),
+                                     "head", &error_abort);
         if (h != head) {
             continue;
         }
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (14 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-18 15:27   ` Markus Armbruster
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 17/17] qobject: move dump_qobject() from block/ to qobject/ Marc-André Lureau
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Similar to int support, add uint support.

Note this is RFC because this is currently unused in qemu, I haven't
found a good user for it yet (kaslr qemu-ga code did use it though).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/qdict.h |  5 +++++
 qobject/qdict.c          | 38 ++++++++++++++++++++++++++++++++++++++
 tests/check-qdict.c      | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 363e431106..8c7c2b762b 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -56,6 +56,8 @@ void qdict_destroy_obj(QObject *obj);
 /* Helpers for int, bool, and string */
 #define qdict_put_int(qdict, key, value) \
         qdict_put(qdict, key, qnum_from_int(value))
+#define qdict_put_uint(qdict, key, value)        \
+        qdict_put(qdict, key, qnum_from_uint(value))
 #define qdict_put_bool(qdict, key, value) \
         qdict_put(qdict, key, qbool_from_bool(value))
 #define qdict_put_str(qdict, key, value) \
@@ -64,12 +66,15 @@ void qdict_destroy_obj(QObject *obj);
 /* High level helpers */
 double qdict_get_double(const QDict *qdict, const char *key);
 int64_t qdict_get_int(const QDict *qdict, const char *key);
+uint64_t qdict_get_uint(const QDict *qdict, const char *key);
 bool qdict_get_bool(const QDict *qdict, const char *key);
 QList *qdict_get_qlist(const QDict *qdict, const char *key);
 QDict *qdict_get_qdict(const QDict *qdict, const char *key);
 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);
+uint64_t qdict_get_try_uint(const QDict *qdict, const char *key,
+                            uint64_t def_value);
 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);
 
diff --git a/qobject/qdict.c b/qobject/qdict.c
index ad5bab9572..34478fbdd4 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -202,6 +202,19 @@ int64_t qdict_get_int(const QDict *qdict, const char *key)
 }
 
 /**
+ * qdict_get_uint(): Get an unsigned integer mapped by 'key'
+ *
+ * This function assumes that 'key' exists and it stores a
+ * QNum int object.
+ *
+ * Return unsigned integer mapped by 'key'.
+ */
+uint64_t qdict_get_uint(const QDict *qdict, const char *key)
+{
+    return qnum_get_uint(qobject_to_qnum(qdict_get(qdict, key)), &error_abort);
+}
+
+/**
  * qdict_get_bool(): Get a bool mapped by 'key'
  *
  * This function assumes that 'key' exists and it stores a
@@ -270,6 +283,31 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key,
 }
 
 /**
+ * qdict_get_try_uint(): Try to get usigned integer mapped by 'key'
+ *
+ * Return unsigned integer mapped by 'key', if it is not present in
+ * the dictionary or if the stored object is not of QNum type
+ * 'def_value' will be returned.
+ */
+uint64_t qdict_get_try_uint(const QDict *qdict, const char *key,
+                            uint64_t def_value)
+{
+    Error *err = NULL;
+    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
+    uint64_t val = def_value;
+
+    if (qnum) {
+        val = qnum_get_uint(qnum, &err);
+    }
+    if (err) {
+        error_free(err);
+        val = def_value;
+    }
+
+    return val;
+}
+
+/**
  * qdict_get_try_bool(): Try to get a bool mapped by 'key'
  *
  * Return bool mapped by 'key', if it is not present in the
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index bcd06a7d6b..7f9ea67862 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -105,6 +105,21 @@ static void qdict_get_int_test(void)
     QDECREF(tests_dict);
 }
 
+static void qdict_get_uint_test(void)
+{
+    uint64_t ret;
+    const uint64_t value = UINT64_MAX;
+    const char *key = "uint";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put_uint(tests_dict, key, value);
+
+    ret = qdict_get_uint(tests_dict, key);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
+}
+
 static void qdict_get_try_int_test(void)
 {
     int ret;
@@ -120,6 +135,21 @@ static void qdict_get_try_int_test(void)
     QDECREF(tests_dict);
 }
 
+static void qdict_get_try_uint_test(void)
+{
+    uint64_t ret;
+    const uint64_t value = UINT64_MAX;
+    const char *key = "uint";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put_uint(tests_dict, key, value);
+
+    ret = qdict_get_try_uint(tests_dict, key, 0);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
+}
+
 static void qdict_get_str_test(void)
 {
     const char *p;
@@ -852,7 +882,9 @@ int main(int argc, char **argv)
     /* Continue, but now with fixtures */
     g_test_add_func("/public/get", qdict_get_test);
     g_test_add_func("/public/get_int", qdict_get_int_test);
+    g_test_add_func("/public/get_uint", qdict_get_uint_test);
     g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
+    g_test_add_func("/public/get_try_uint", qdict_get_try_uint_test);
     g_test_add_func("/public/get_str", qdict_get_str_test);
     g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
     g_test_add_func("/public/defaults", qdict_defaults_test);
-- 
2.13.0.rc1.16.gd80b50c3f

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

* [Qemu-devel] [PATCH 17/17] qobject: move dump_qobject() from block/ to qobject/
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (15 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint Marc-André Lureau
@ 2017-05-09 17:35 ` Marc-André Lureau
  2017-05-13 21:41 ` [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type no-reply
  2017-05-18 15:39 ` Markus Armbruster
  18 siblings, 0 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-09 17:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The dump functions could be generally useful for any qobject user or for
debugging etc.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qapi/qmp/qdict.h   |  2 ++
 include/qapi/qmp/qlist.h   |  2 ++
 include/qapi/qmp/qobject.h |  7 ++++
 block/qapi.c               | 90 +++-------------------------------------------
 qobject/qdict.c            | 30 ++++++++++++++++
 qobject/qlist.c            | 23 ++++++++++++
 qobject/qobject.c          | 19 ++++++++++
 tests/check-qjson.c        | 19 ++++++++++
 8 files changed, 106 insertions(+), 86 deletions(-)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 8c7c2b762b..1ef3bc8cda 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -91,4 +91,6 @@ QObject *qdict_crumple(const QDict *src, Error **errp);
 
 void qdict_join(QDict *dest, QDict *src, bool overwrite);
 
+char *qdict_to_string(QDict *dict, int indent);
+
 #endif /* QDICT_H */
diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
index 2f2c199632..105b16f074 100644
--- a/include/qapi/qmp/qlist.h
+++ b/include/qapi/qmp/qlist.h
@@ -59,6 +59,8 @@ size_t qlist_size(const QList *qlist);
 QList *qobject_to_qlist(const QObject *obj);
 void qlist_destroy_obj(QObject *obj);
 
+char *qlist_to_string(QList *list, int indent);
+
 static inline const QListEntry *qlist_first(const QList *qlist)
 {
     return QTAILQ_FIRST(&qlist->head);
diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index b8ddbca405..0d6ae5048a 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -101,4 +101,11 @@ static inline QObject *qnull(void)
     return &qnull_;
 }
 
+char *qobject_to_string_indent(QObject *obj, int indent);
+
+static inline char *qobject_to_string(QObject *obj)
+{
+    return qobject_to_string_indent(obj, 0);
+}
+
 #endif /* QOBJECT_H */
diff --git a/block/qapi.c b/block/qapi.c
index 2050df29e4..9b7d42e50a 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -586,101 +586,19 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
     }
 }
 
-static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
-                       QDict *dict);
-static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
-                       QList *list);
-
-static void dump_qobject(fprintf_function func_fprintf, void *f,
-                         int comp_indent, QObject *obj)
-{
-    switch (qobject_type(obj)) {
-        case QTYPE_QNUM: {
-            QNum *value = qobject_to_qnum(obj);
-            char *tmp = qnum_to_string(value);
-            func_fprintf(f, "%s", tmp);
-            g_free(tmp);
-            break;
-        }
-        case QTYPE_QSTRING: {
-            QString *value = qobject_to_qstring(obj);
-            func_fprintf(f, "%s", qstring_get_str(value));
-            break;
-        }
-        case QTYPE_QDICT: {
-            QDict *value = qobject_to_qdict(obj);
-            dump_qdict(func_fprintf, f, comp_indent, value);
-            break;
-        }
-        case QTYPE_QLIST: {
-            QList *value = qobject_to_qlist(obj);
-            dump_qlist(func_fprintf, f, comp_indent, value);
-            break;
-        }
-        case QTYPE_QBOOL: {
-            QBool *value = qobject_to_qbool(obj);
-            func_fprintf(f, "%s", qbool_get_bool(value) ? "true" : "false");
-            break;
-        }
-        default:
-            abort();
-    }
-}
-
-static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
-                       QList *list)
-{
-    const QListEntry *entry;
-    int i = 0;
-
-    for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
-        QType type = qobject_type(entry->value);
-        bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
-        func_fprintf(f, "%*s[%i]:%c", indentation * 4, "", i,
-                     composite ? '\n' : ' ');
-        dump_qobject(func_fprintf, f, indentation + 1, entry->value);
-        if (!composite) {
-            func_fprintf(f, "\n");
-        }
-    }
-}
-
-static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
-                       QDict *dict)
-{
-    const QDictEntry *entry;
-
-    for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
-        QType type = qobject_type(entry->value);
-        bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
-        char *key = g_malloc(strlen(entry->key) + 1);
-        int i;
-
-        /* replace dashes with spaces in key (variable) names */
-        for (i = 0; entry->key[i]; i++) {
-            key[i] = entry->key[i] == '-' ? ' ' : entry->key[i];
-        }
-        key[i] = 0;
-        func_fprintf(f, "%*s%s:%c", indentation * 4, "", key,
-                     composite ? '\n' : ' ');
-        dump_qobject(func_fprintf, f, indentation + 1, entry->value);
-        if (!composite) {
-            func_fprintf(f, "\n");
-        }
-        g_free(key);
-    }
-}
-
 void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
                                    ImageInfoSpecific *info_spec)
 {
     QObject *obj, *data;
     Visitor *v = qobject_output_visitor_new(&obj);
+    char *tmp;
 
     visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
     visit_complete(v, &obj);
     data = qdict_get(qobject_to_qdict(obj), "data");
-    dump_qobject(func_fprintf, f, 1, data);
+    tmp = qobject_to_string_indent(data, 1);
+    func_fprintf(f, "%s", tmp);
+    g_free(tmp);
     qobject_decref(obj);
     visit_free(v);
 }
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 34478fbdd4..b325852351 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -1065,3 +1065,33 @@ void qdict_join(QDict *dest, QDict *src, bool overwrite)
         entry = next;
     }
 }
+
+char *qdict_to_string(QDict *dict, int indent)
+{
+    const QDictEntry *entry;
+    GString *str = g_string_new(NULL);
+
+    for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
+        QType type = qobject_type(entry->value);
+        bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+        char *key = g_malloc(strlen(entry->key) + 1);
+        char *val = qobject_to_string_indent(entry->value, indent + 1);
+        int i;
+
+        /* replace dashes with spaces in key (variable) names */
+        for (i = 0; entry->key[i]; i++) {
+            key[i] = entry->key[i] == '-' ? ' ' : entry->key[i];
+        }
+        key[i] = 0;
+        g_string_append_printf(str, "%*s%s:", indent * 4, "", key);
+        g_string_append_c(str, composite ? '\n' : ' ');
+        g_string_append(str, val);
+        if (!composite) {
+            g_string_append_c(str, '\n');
+        }
+        g_free(val);
+        g_free(key);
+    }
+
+    return g_string_free(str, false);
+}
diff --git a/qobject/qlist.c b/qobject/qlist.c
index 86b60cb88c..b769248290 100644
--- a/qobject/qlist.c
+++ b/qobject/qlist.c
@@ -158,3 +158,26 @@ void qlist_destroy_obj(QObject *obj)
 
     g_free(qlist);
 }
+
+char *qlist_to_string(QList *list, int indent)
+{
+    GString *str = g_string_new(NULL);
+    const QListEntry *entry;
+    int i = 0;
+
+    for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
+        QType type = qobject_type(entry->value);
+        bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+        char *val = qobject_to_string_indent(entry->value, indent + 1);
+
+        g_string_append_printf(str, "%*s[%i]:", indent * 4, "", i);
+        g_string_append_c(str, composite ? '\n' : ' ');
+        g_string_append(str, val);
+        if (!composite) {
+            g_string_append_c(str, '\n');
+        }
+        g_free(val);
+    }
+
+    return g_string_free(str, false);
+}
diff --git a/qobject/qobject.c b/qobject/qobject.c
index b0cafb66f1..64e959c54f 100644
--- a/qobject/qobject.c
+++ b/qobject/qobject.c
@@ -27,3 +27,22 @@ void qobject_destroy(QObject *obj)
     assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX);
     qdestroy[obj->type](obj);
 }
+
+char *qobject_to_string_indent(QObject *obj, int indent)
+{
+    switch (qobject_type(obj)) {
+    case QTYPE_QNUM:
+        return qnum_to_string(qobject_to_qnum(obj));
+    case QTYPE_QSTRING:
+        return g_strdup(qstring_get_str(qobject_to_qstring(obj)));
+    case QTYPE_QDICT:
+        return qdict_to_string(qobject_to_qdict(obj), indent);
+    case QTYPE_QLIST:
+        return qlist_to_string(qobject_to_qlist(obj), indent);
+    case QTYPE_QBOOL:
+        return g_strdup(qbool_get_bool(qobject_to_qbool(obj)) ?
+                        "true" : "false");
+    default:
+        abort();
+    }
+}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 57c2366dc3..f97b177eb9 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -1349,6 +1349,23 @@ static void simple_whitespace(void)
     }
 }
 
+static void qobject_to_string_test(void)
+{
+    QObject *obj;
+    char *tmp;
+
+    obj = qobject_from_json("[ 43, { 'c': { 'd' : 12 } }, [ 1, 2 ], 42 ]",
+                            &error_abort);
+    tmp = qobject_to_string(obj);
+    g_assert_cmpstr(tmp, ==,
+                    "[0]: 43\n"
+                    "[1]:\n    c:\n        d: 12\n"
+                    "[2]:\n    [0]: 1\n    [1]: 2\n"
+                    "[3]: 42\n");
+    g_free(tmp);
+    qobject_decref(obj);
+}
+
 static void simple_varargs(void)
 {
     QObject *embedded_obj;
@@ -1522,5 +1539,7 @@ int main(int argc, char **argv)
     g_test_add_func("/errors/unterminated/literal", unterminated_literal);
     g_test_add_func("/errors/limits/nesting", limits_nesting);
 
+    g_test_add_func("/qobject/to_string", qobject_to_string_test);
+
     return g_test_run();
 }
-- 
2.13.0.rc1.16.gd80b50c3f

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

* Re: [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field Marc-André Lureau
@ 2017-05-09 18:40   ` Eric Blake
  2017-05-11 11:59     ` Markus Armbruster
  0 siblings, 1 reply; 70+ messages in thread
From: Eric Blake @ 2017-05-09 18:40 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: armbru

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

On 05/09/2017 12:35 PM, Marc-André Lureau wrote:
> Remove dependency on qapi qtype, replace a field by a few helper
> functions to determine the default value type (introduced in commit
> 4f2d3d7).
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/hw/qdev-core.h       |  1 -
>  include/hw/qdev-properties.h |  5 -----
>  hw/core/qdev.c               | 32 ++++++++++++++++++++++++++------
>  3 files changed, 26 insertions(+), 12 deletions(-)
> 

> +++ b/hw/core/qdev.c
> @@ -755,6 +755,30 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
>      g_free(name);
>  }
>  
> +static bool prop_info_is_bool(const PropertyInfo *info)
> +{
> +    return info == &qdev_prop_bit
> +        || info == &qdev_prop_bit64
> +        || info == &qdev_prop_bool;
> +}

I guess we can expand these helpers if we add more property types later.

> +
> +static bool prop_info_is_int(const PropertyInfo *info)
> +{
> +    return info == &qdev_prop_uint8
> +        || info == &qdev_prop_uint16
> +        || info == &qdev_prop_uint32
> +        || info == &qdev_prop_int32
> +        || info == &qdev_prop_uint64

Interesting dissimilarity between existing types, but not the fault of
your patch.

> +        || info == &qdev_prop_size
> +        || info == &qdev_prop_pci_devfn

Okay so far.

> +        || info == &qdev_prop_on_off_auto
> +        || info == &qdev_prop_losttickpolicy
> +        || info == &qdev_prop_blockdev_on_error
> +        || info == &qdev_prop_bios_chs_trans

Aren't these four enums rather than ints?

> +        || info == &qdev_prop_blocksize
> +        || info == &qdev_prop_arraylen;
> +}
> +

> @@ -794,16 +818,12 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
>                                      prop->info->description,
>                                      &error_abort);
>  
> -    if (prop->qtype == QTYPE_NONE) {
> -        return;
> -    }
> -
> -    if (prop->qtype == QTYPE_QBOOL) {
> +    if (prop_info_is_bool(prop->info)) {
>          object_property_set_bool(obj, prop->defval, prop->name, &error_abort);
>      } else if (prop->info->enum_table) {
>          object_property_set_str(obj, prop->info->enum_table[prop->defval],
>                                  prop->name, &error_abort);
> -    } else if (prop->qtype == QTYPE_QINT) {
> +    } else if (prop_info_is_int(prop->info)) {
>          object_property_set_int(obj, prop->defval, prop->name, &error_abort);

So enum_table has priority over prop_info_is_int(), in which case, the
four types I pointed out as being enums will still use set_str() rather
than set_int().

I'm not necessarily sold on this patch - previously, the type was local
to the declaration of the struct (you could tell by reading
qdev_prop_bit that it was a boolean type); now the type is remote (you
have to hunt elsewhere to see how the property is categorized).  I'm not
rejecting it (I see how getting rid of a dependency on QType makes it
easier for the rest of the series to change QType underpinnings), but
wonder if that is a strong enough justification.

But if we DO keep it, you'll want a v2 that cleans up the
prop_info_is_int() impedance mismatch.

-- 
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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters Marc-André Lureau
@ 2017-05-09 18:44   ` Eric Blake
  0 siblings, 0 replies; 70+ messages in thread
From: Eric Blake @ 2017-05-09 18:44 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: armbru

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

On 05/09/2017 12:35 PM, Marc-André Lureau wrote:
> If the property is not of the requested type, the getters will leak a
> QObject.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qom/object.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases Marc-André Lureau
@ 2017-05-09 18:51   ` Eric Blake
  2017-05-11 12:34     ` Markus Armbruster
  2017-05-22 17:03   ` Markus Armbruster
  1 sibling, 1 reply; 70+ messages in thread
From: Eric Blake @ 2017-05-09 18:51 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: armbru

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

On 05/09/2017 12:35 PM, Marc-André Lureau wrote:
> There are no real users of this case, and it's going to be invalid after
> merging of QFloat and QInt use the same QNum type in the following patch.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  tests/test-keyval.c                     |  3 ---
>  tests/test-qobject-input-visitor.c      | 26 --------------------------
>  tests/qapi-schema/qapi-schema-test.json |  2 --
>  tests/qapi-schema/qapi-schema-test.out  |  8 --------
>  4 files changed, 39 deletions(-)

Is it worth adding tests/qapi-schema/alternate-num-int.json that
attempts to create an alternate on 'int' and 'number' to (eventually)
show that we give a decent error message at QAPI generation time that
such a type is invalid?  Such a test would (eventually be) a negative
replacement test for the (currently positive) test that you are deleting
here, and make it easier to see the point in the series where we flip
the concept from supported to rejected.

That said, it doesn't have to necessarily be done at this point in the
series (since I haven't even yet seen how QNum will look), so it doesn't
hold up review of this particular patch.

Also, this may interact with Eduardo's current attempt (or at least
start of an attempt) to tighten the QAPI parser to reject alternates
that would otherwise be ambiguous when passed through the string input
visitor (for example, forbidding the combination of an enum starting
with a digit in an alternate that also accepts integers).  So be aware
that we may have some integration things to think about down the road.

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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field
  2017-05-09 18:40   ` Eric Blake
@ 2017-05-11 11:59     ` Markus Armbruster
  2017-05-11 12:07       ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-11 11:59 UTC (permalink / raw)
  To: Eric Blake; +Cc: Marc-André Lureau, qemu-devel, Paolo Bonzini

Cc Paolo, because I have a question for him at the end.

Eric Blake <eblake@redhat.com> writes:

> On 05/09/2017 12:35 PM, Marc-André Lureau wrote:
>> Remove dependency on qapi qtype, replace a field by a few helper
>> functions to determine the default value type (introduced in commit
>> 4f2d3d7).
>> 
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  include/hw/qdev-core.h       |  1 -
>>  include/hw/qdev-properties.h |  5 -----
>>  hw/core/qdev.c               | 32 ++++++++++++++++++++++++++------
>>  3 files changed, 26 insertions(+), 12 deletions(-)
>> 
>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
>> index 4bf86b0ad8..0f21a500cd 100644
>> --- a/include/hw/qdev-core.h
>> +++ b/include/hw/qdev-core.h
>> @@ -225,7 +225,6 @@ struct Property {
>>      PropertyInfo *info;
>>      ptrdiff_t    offset;
>>      uint8_t      bitnr;
>> -    QType        qtype;
>>      int64_t      defval;
>>      int          arrayoffset;
>>      PropertyInfo *arrayinfo;

As we'll see in the rest of the patch, member qtype is only used by
qdev_property_add_static().  It has nothing to do with QObject there, it
merely helps sorting properties into buckets "uninteresting", "boolean",
"enumeration", "integer".

>> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
>> index 1d69fa7a8f..16d5d0629b 100644
>> --- a/include/hw/qdev-properties.h
>> +++ b/include/hw/qdev-properties.h
>> @@ -42,7 +42,6 @@ extern PropertyInfo qdev_prop_arraylen;
    #define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
            .name      = (_name),                                           \
>>          .info      = &(_prop),                                          \
>>          .offset    = offsetof(_state, _field)                           \
>>              + type_check(_type,typeof_field(_state, _field)),           \
>> -        .qtype     = QTYPE_QINT,                                        \
>>          .defval    = (_type)_defval,                                    \
>>          }
>>  #define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
>> @@ -51,7 +50,6 @@ extern PropertyInfo qdev_prop_arraylen;
    #define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
            .name      = (_name),                                    \
            .info      = &(qdev_prop_bit),                           \
>>          .bitnr    = (_bit),                                      \
>>          .offset    = offsetof(_state, _field)                    \
>>              + type_check(uint32_t,typeof_field(_state, _field)), \
>> -        .qtype     = QTYPE_QBOOL,                                \
>>          .defval    = (bool)_defval,                              \
>>          }
>>  #define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) {       \
>> @@ -60,7 +58,6 @@ extern PropertyInfo qdev_prop_arraylen;
    #define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) {       \
            .name      = (_name),                                           \
            .info      = &(qdev_prop_bit64),                                \
>>          .bitnr    = (_bit),                                             \
>>          .offset    = offsetof(_state, _field)                           \
>>              + type_check(uint64_t, typeof_field(_state, _field)),       \
>> -        .qtype     = QTYPE_QBOOL,                                       \
>>          .defval    = (bool)_defval,                                     \
>>          }
>>  
>> @@ -69,7 +66,6 @@ extern PropertyInfo qdev_prop_arraylen;
    #define DEFINE_PROP_BOOL(_name, _state, _field, _defval) {       \
            .name      = (_name),                                    \
>>          .info      = &(qdev_prop_bool),                          \
>>          .offset    = offsetof(_state, _field)                    \
>>              + type_check(bool, typeof_field(_state, _field)),    \
>> -        .qtype     = QTYPE_QBOOL,                                \
>>          .defval    = (bool)_defval,                              \
>>          }
>>  
>> @@ -105,7 +101,6 @@ extern PropertyInfo qdev_prop_arraylen;>
    #define DEFINE_PROP_ARRAY(_name, _state, _field,                        \
                              _arrayfield, _arrayprop, _arraytype) {        \
            .name = (PROP_ARRAY_LEN_PREFIX _name),                          \
            .info = &(qdev_prop_arraylen),                                  \
>>          .offset = offsetof(_state, _field)                              \
>>              + type_check(uint32_t, typeof_field(_state, _field)),       \
>> -        .qtype = QTYPE_QINT,                                            \
>>          .arrayinfo = &(_arrayprop),                                     \
>>          .arrayfieldsize = sizeof(_arraytype),                           \
>>          .arrayoffset = offsetof(_state, _arrayfield),                   \

Note for later:

* Member qtype can be QTYPE_QINT, QTYPE_QBOOL or zero (no initializer),
  i.e. QTYPE_NONE.

* Properties defined with DEFINE_PROP_BIT(), DEFINE_PROP_BIT64() and
  DEFINE_PROP_BOOL() are QTYPE_QBOOL.  These are all boolean properties.
  I didn't check whether the converse is also true, i.e. all boolean
  properties are defined that way.

* Properties defined with DEFINE_PROP_DEFAULT() and DEFINE_PROP_ARRAY()
  are QTYPE_QINT.  On closer examination, the former are all integer and
  enumeration properties, and the latter are all arrays of integer.  I
  didn't check whether the converse is also true.

>> +++ b/hw/core/qdev.c
>> @@ -755,6 +755,30 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
>>      g_free(name);
>>  }
>>  
>> +static bool prop_info_is_bool(const PropertyInfo *info)
>> +{
>> +    return info == &qdev_prop_bit
>> +        || info == &qdev_prop_bit64
>> +        || info == &qdev_prop_bool;
>> +}
>
> I guess we can expand these helpers if we add more property types later.
>
>> +
>> +static bool prop_info_is_int(const PropertyInfo *info)
>> +{
>> +    return info == &qdev_prop_uint8
>> +        || info == &qdev_prop_uint16
>> +        || info == &qdev_prop_uint32
>> +        || info == &qdev_prop_int32
>> +        || info == &qdev_prop_uint64
>
> Interesting dissimilarity between existing types, but not the fault of
> your patch.
>
>> +        || info == &qdev_prop_size
>> +        || info == &qdev_prop_pci_devfn
>
> Okay so far.
>
>> +        || info == &qdev_prop_on_off_auto
>> +        || info == &qdev_prop_losttickpolicy
>> +        || info == &qdev_prop_blockdev_on_error
>> +        || info == &qdev_prop_bios_chs_trans
>
> Aren't these four enums rather than ints?
>
>> +        || info == &qdev_prop_blocksize
>> +        || info == &qdev_prop_arraylen;
>> +}
>> +
>
>> @@ -794,16 +818,12 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
>>                                      prop->info->description,
>>                                      &error_abort);
>>  
>> -    if (prop->qtype == QTYPE_NONE) {
>> -        return;
>> -    }
>> -
>> -    if (prop->qtype == QTYPE_QBOOL) {
>> +    if (prop_info_is_bool(prop->info)) {
>>          object_property_set_bool(obj, prop->defval, prop->name, &error_abort);
>>      } else if (prop->info->enum_table) {
>>          object_property_set_str(obj, prop->info->enum_table[prop->defval],
>>                                  prop->name, &error_abort);
>> -    } else if (prop->qtype == QTYPE_QINT) {
>> +    } else if (prop_info_is_int(prop->info)) {
>>          object_property_set_int(obj, prop->defval, prop->name, &error_abort);

Old code:

* Property is either uninteresting (QTYPE_NONE), boolean (QTYPE_QBOOL),
  integer, enumeration or array of integer (QTYPE_QINT)

* If uninteresting (QTYPE_NONE), do nothing.

* If boolean (QTYPE_QBOOL), object_property_set_bool()

* If enumeration (QTYPE_QINT and info->enum_table),
  object_property_set_str()

* If integer or array of integer (QTYPE_QINT and not info->enum_table),
  object_property_set_int()

The patch drops the check of QTYPE_NONE.  No change as long as
info->enum_table implies QTYPE_QINT.  Plausible, but we need to
double-check.

> So enum_table has priority over prop_info_is_int(), in which case, the
> four types I pointed out as being enums will still use set_str() rather
> than set_int().

Yes.

I'm not sure I fully understand this code's logic.  It's from Paolo's
commit 4f2d3d7, moved here in commit fdae245.

> I'm not necessarily sold on this patch - previously, the type was local
> to the declaration of the struct (you could tell by reading
> qdev_prop_bit that it was a boolean type); now the type is remote (you
> have to hunt elsewhere to see how the property is categorized).  I'm not
> rejecting it (I see how getting rid of a dependency on QType makes it
> easier for the rest of the series to change QType underpinnings), but
> wonder if that is a strong enough justification.
>
> But if we DO keep it, you'll want a v2 that cleans up the
> prop_info_is_int() impedance mismatch.

The patch cleans up a mild abuse of QType for another purpose.  I like
that.

What I don't like is enumerating PropertyInfo in helpers.  A relatively
straightforward way to avoid this would be moving the part of
qdev_property_add_static() that varies between properties into a new
PropertyInfo method.  Assumes that *all* instances of the same
PropertyInfo should behave the same.  Paolo, is that the case?

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

* Re: [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field
  2017-05-11 11:59     ` Markus Armbruster
@ 2017-05-11 12:07       ` Paolo Bonzini
  0 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2017-05-11 12:07 UTC (permalink / raw)
  To: Markus Armbruster, Eric Blake; +Cc: Marc-André Lureau, qemu-devel



On 11/05/2017 13:59, Markus Armbruster wrote:
> 
> What I don't like is enumerating PropertyInfo in helpers.  A relatively
> straightforward way to avoid this would be moving the part of
> qdev_property_add_static() that varies between properties into a new
> PropertyInfo method.  Assumes that *all* instances of the same
> PropertyInfo should behave the same.  Paolo, is that the case?

Yes, it is the case, and yes, a virtual method such as
void (*init_default_value)(DeviceState *dev, Property *prop)
would be much better.

Thanks,

Paolo

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

* Re: [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases
  2017-05-09 18:51   ` Eric Blake
@ 2017-05-11 12:34     ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-11 12:34 UTC (permalink / raw)
  To: Eric Blake; +Cc: Marc-André Lureau, qemu-devel

Eric Blake <eblake@redhat.com> writes:

> On 05/09/2017 12:35 PM, Marc-André Lureau wrote:
>> There are no real users of this case, and it's going to be invalid after
>> merging of QFloat and QInt use the same QNum type in the following patch.
>> 
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  tests/test-keyval.c                     |  3 ---
>>  tests/test-qobject-input-visitor.c      | 26 --------------------------
>>  tests/qapi-schema/qapi-schema-test.json |  2 --
>>  tests/qapi-schema/qapi-schema-test.out  |  8 --------
>>  4 files changed, 39 deletions(-)
>
> Is it worth adding tests/qapi-schema/alternate-num-int.json that
> attempts to create an alternate on 'int' and 'number' to (eventually)
> show that we give a decent error message at QAPI generation time that
> such a type is invalid?  Such a test would (eventually be) a negative
> replacement test for the (currently positive) test that you are deleting
> here, and make it easier to see the point in the series where we flip
> the concept from supported to rejected.
>
> That said, it doesn't have to necessarily be done at this point in the
> series (since I haven't even yet seen how QNum will look), so it doesn't
> hold up review of this particular patch.
>
> Also, this may interact with Eduardo's current attempt (or at least
> start of an attempt) to tighten the QAPI parser to reject alternates
> that would otherwise be ambiguous when passed through the string input
> visitor (for example, forbidding the combination of an enum starting
> with a digit in an alternate that also accepts integers).  So be aware
> that we may have some integration things to think about down the road.
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Eduardo's work made me think about alternates, and I've come to the
conclusion that restricting alternates now would be prudent.  I'll work
on a patch.  It'll probably replace this one.

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
@ 2017-05-11 14:29   ` Markus Armbruster
  2017-05-11 15:09     ` Eric Blake
  2017-05-30  7:32     ` Marc-André Lureau
  2017-05-12  6:30   ` Markus Armbruster
  2017-05-12  7:37   ` Markus Armbruster
  2 siblings, 2 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-11 14:29 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> We would like to use a same QObject type to represent numbers, whether
> they are int, uint, or floats. getters will allow some compatibility

Please start your sentence with a capital letter ...

> between the various types if the number fits other representations

... and end them with a period.

>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py                          |  30 +++----
>  scripts/qapi-visit.py                    |   2 +-
>  include/qapi/qmp/qdict.h                 |   3 +-
>  include/qapi/qmp/qfloat.h                |  29 -------
>  include/qapi/qmp/qint.h                  |  28 -------
>  include/qapi/qmp/qlist.h                 |   2 +-
>  include/qapi/qmp/qnum.h                  |  43 ++++++++++
>  include/qapi/qmp/types.h                 |   3 +-
>  include/qapi/qobject-input-visitor.h     |   2 +-
>  include/qapi/qobject-output-visitor.h    |   8 +-
>  block/blkdebug.c                         |   1 -
>  block/nbd.c                              |   1 -
>  block/nfs.c                              |   1 -
>  block/qapi.c                             |  13 ++-
>  block/quorum.c                           |   1 -
>  block/sheepdog.c                         |   1 -
>  block/ssh.c                              |   1 -
>  block/vvfat.c                            |   1 -
>  blockdev.c                               |   5 +-
>  hw/acpi/pcihp.c                          |   1 -
>  hw/i386/acpi-build.c                     |  15 ++--
>  hw/usb/xen-usb.c                         |   1 -
>  monitor.c                                |   2 +-
>  qapi/qobject-input-visitor.c             |  36 +++-----
>  qapi/qobject-output-visitor.c            |   6 +-
>  qga/commands.c                           |   2 +-
>  qga/main.c                               |   1 -
>  qobject/json-parser.c                    |  18 ++--
>  qobject/qdict.c                          |  38 ++++-----
>  qobject/qfloat.c                         |  62 --------------
>  qobject/qint.c                           |  61 --------------
>  qobject/qjson.c                          |  37 +--------
>  qobject/qnum.c                           | 138 +++++++++++++++++++++++++++++++
>  qobject/qobject.c                        |   3 +-
>  qom/object.c                             |  21 +++--
>  target/i386/cpu.c                        |   6 +-
>  tests/check-qdict.c                      |  23 +++---
>  tests/check-qfloat.c                     |  53 ------------
>  tests/check-qint.c                       |  87 -------------------
>  tests/check-qjson.c                      |  84 +++++++++----------
>  tests/check-qlist.c                      |  15 ++--
>  tests/check-qnum.c                       | 131 +++++++++++++++++++++++++++++
>  tests/test-keyval.c                      |   1 -
>  tests/test-qmp-commands.c                |   6 +-
>  tests/test-qmp-event.c                   |   7 +-
>  tests/test-qobject-input-visitor.c       |  30 +++----
>  tests/test-qobject-output-visitor.c      |  56 ++++++-------
>  tests/test-x86-cpuid-compat.c            |  13 ++-
>  ui/spice-core.c                          |   1 -
>  ui/vnc-enc-tight.c                       |   1 -
>  util/qemu-option.c                       |  20 ++---
>  MAINTAINERS                              |   3 +-
>  qobject/Makefile.objs                    |   2 +-
>  scripts/coccinelle/qobject.cocci         |   4 +-
>  tests/.gitignore                         |   3 +-
>  tests/Makefile.include                   |  13 ++-
>  tests/qapi-schema/comments.out           |   2 +-
>  tests/qapi-schema/doc-good.out           |   2 +-
>  tests/qapi-schema/empty.out              |   2 +-
>  tests/qapi-schema/event-case.out         |   2 +-
>  tests/qapi-schema/ident-with-escape.out  |   2 +-
>  tests/qapi-schema/include-relpath.out    |   2 +-
>  tests/qapi-schema/include-repetition.out |   2 +-
>  tests/qapi-schema/include-simple.out     |   2 +-
>  tests/qapi-schema/indented-expr.out      |   2 +-
>  tests/qapi-schema/qapi-schema-test.out   |   2 +-
>  66 files changed, 557 insertions(+), 639 deletions(-)

Nice diffstat :)

>  delete mode 100644 include/qapi/qmp/qfloat.h
>  delete mode 100644 include/qapi/qmp/qint.h
>  create mode 100644 include/qapi/qmp/qnum.h
>  delete mode 100644 qobject/qfloat.c
>  delete mode 100644 qobject/qint.c
>  create mode 100644 qobject/qnum.c
>  delete mode 100644 tests/check-qfloat.c
>  delete mode 100644 tests/check-qint.c
>  create mode 100644 tests/check-qnum.c
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 6c4d554165..01fd0027a5 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -21,18 +21,18 @@ from ordereddict import OrderedDict
>  
>  builtin_types = {
>      'str':      'QTYPE_QSTRING',
> -    'int':      'QTYPE_QINT',
> -    'number':   'QTYPE_QFLOAT',
> +    'int':      'QTYPE_QNUM',
> +    'number':   'QTYPE_QNUM',
>      'bool':     'QTYPE_QBOOL',
> -    'int8':     'QTYPE_QINT',
> -    'int16':    'QTYPE_QINT',
> -    'int32':    'QTYPE_QINT',
> -    'int64':    'QTYPE_QINT',
> -    'uint8':    'QTYPE_QINT',
> -    'uint16':   'QTYPE_QINT',
> -    'uint32':   'QTYPE_QINT',
> -    'uint64':   'QTYPE_QINT',
> -    'size':     'QTYPE_QINT',
> +    'int8':     'QTYPE_QNUM',
> +    'int16':    'QTYPE_QNUM',
> +    'int32':    'QTYPE_QNUM',
> +    'int64':    'QTYPE_QNUM',
> +    'uint8':    'QTYPE_QNUM',
> +    'uint16':   'QTYPE_QNUM',
> +    'uint32':   'QTYPE_QNUM',
> +    'uint64':   'QTYPE_QNUM',
> +    'size':     'QTYPE_QNUM',
>      'any':      None,           # any QType possible, actually
>      'QType':    'QTYPE_QSTRING',
>  }
> @@ -1044,8 +1044,8 @@ class QAPISchemaType(QAPISchemaEntity):
>      def alternate_qtype(self):
>          json2qtype = {
>              'string':  'QTYPE_QSTRING',
> -            'number':  'QTYPE_QFLOAT',
> -            'int':     'QTYPE_QINT',
> +            'number':  'QTYPE_QNUM',
> +            'int':     'QTYPE_QNUM',
>              'boolean': 'QTYPE_QBOOL',
>              'object':  'QTYPE_QDICT'
>          }
> @@ -1507,9 +1507,9 @@ class QAPISchema(object):
>          self.the_empty_object_type = QAPISchemaObjectType(
>              'q_empty', None, None, None, [], None)
>          self._def_entity(self.the_empty_object_type)
> -        qtype_values = self._make_enum_members(['none', 'qnull', 'qint',
> +        qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
>                                                  'qstring', 'qdict', 'qlist',
> -                                                'qfloat', 'qbool'])
> +                                                'qbool'])
>          self._def_entity(QAPISchemaEnumType('QType', None, None,
>                                              qtype_values, 'QTYPE'))
>  
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 5737aefa05..cc447ecacc 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -164,7 +164,7 @@ def gen_visit_alternate(name, variants):
>      promote_int = 'true'
>      ret = ''
>      for var in variants.variants:
> -        if var.type.alternate_qtype() == 'QTYPE_QINT':
> +        if var.type.alternate_qtype() == 'QTYPE_QNUM':
>              promote_int = 'false'
>  
>      ret += mcgen('''

This conflicts with Eduardo's patch.  The current plan is to take yours
first.

> diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
> index 188440a6a8..363e431106 100644
> --- a/include/qapi/qmp/qdict.h
> +++ b/include/qapi/qmp/qdict.h
> @@ -15,6 +15,7 @@
>  
>  #include "qapi/qmp/qobject.h"
>  #include "qapi/qmp/qlist.h"
> +#include "qapi/qmp/qnum.h"
>  #include "qemu/queue.h"

We neglected to include qint.h even though we use qint_from_int() in a
macro.  Including its replacement qnum.h is a bit cleaner.  Good.

Aside: queue.h could be dropped, as qlist.h already includes it.

>  
>  #define QDICT_BUCKET_MAX 512
> @@ -54,7 +55,7 @@ void qdict_destroy_obj(QObject *obj);
>  
>  /* Helpers for int, bool, and string */
>  #define qdict_put_int(qdict, key, value) \
> -        qdict_put(qdict, key, qint_from_int(value))
> +        qdict_put(qdict, key, qnum_from_int(value))
>  #define qdict_put_bool(qdict, key, value) \
>          qdict_put(qdict, key, qbool_from_bool(value))
>  #define qdict_put_str(qdict, key, value) \
> diff --git a/include/qapi/qmp/qfloat.h b/include/qapi/qmp/qfloat.h
> deleted file mode 100644
> index b5d15836b5..0000000000
> --- a/include/qapi/qmp/qfloat.h
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -/*
> - * QFloat Module
> - *
> - * Copyright IBM, Corp. 2009
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
> - *
> - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> - * See the COPYING.LIB file in the top-level directory.
> - *
> - */
> -
> -#ifndef QFLOAT_H
> -#define QFLOAT_H
> -
> -#include "qapi/qmp/qobject.h"
> -
> -typedef struct QFloat {
> -    QObject base;
> -    double value;
> -} QFloat;
> -
> -QFloat *qfloat_from_double(double value);
> -double qfloat_get_double(const QFloat *qi);
> -QFloat *qobject_to_qfloat(const QObject *obj);
> -void qfloat_destroy_obj(QObject *obj);
> -
> -#endif /* QFLOAT_H */
> diff --git a/include/qapi/qmp/qint.h b/include/qapi/qmp/qint.h
> deleted file mode 100644
> index 3aaff768dd..0000000000
> --- a/include/qapi/qmp/qint.h
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -/*
> - * QInt Module
> - *
> - * Copyright (C) 2009 Red Hat Inc.
> - *
> - * Authors:
> - *  Luiz Capitulino <lcapitulino@redhat.com>
> - *
> - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> - * See the COPYING.LIB file in the top-level directory.
> - */
> -
> -#ifndef QINT_H
> -#define QINT_H
> -
> -#include "qapi/qmp/qobject.h"
> -
> -typedef struct QInt {
> -    QObject base;
> -    int64_t value;
> -} QInt;
> -
> -QInt *qint_from_int(int64_t value);
> -int64_t qint_get_int(const QInt *qi);
> -QInt *qobject_to_qint(const QObject *obj);
> -void qint_destroy_obj(QObject *obj);
> -
> -#endif /* QINT_H */
> diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
> index 5dc4ed9616..2f2c199632 100644
> --- a/include/qapi/qmp/qlist.h
> +++ b/include/qapi/qmp/qlist.h

You may want to include qnum.h here for the same reason you do in
qdict.h.

> @@ -31,7 +31,7 @@ typedef struct QList {
>  
>  /* Helpers for int, bool, and string */
>  #define qlist_append_int(qlist, value) \
> -        qlist_append(qlist, qint_from_int(value))
> +        qlist_append(qlist, qnum_from_int(value))
>  #define qlist_append_bool(qlist, value) \
>          qlist_append(qlist, qbool_from_bool(value))
>  #define qlist_append_str(qlist, value) \
> diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h
> new file mode 100644
> index 0000000000..0e51427821
> --- /dev/null
> +++ b/include/qapi/qmp/qnum.h
> @@ -0,0 +1,43 @@
> +/*
> + * QNum Module
> + *
> + * Copyright (C) 2009 Red Hat Inc.
> + *
> + * Authors:
> + *  Luiz Capitulino <lcapitulino@redhat.com>

Your chance to add yourself here :)

> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + */
> +
> +#ifndef QNUM_H
> +#define QNUM_H
> +
> +#include "qapi/qmp/qobject.h"
> +
> +typedef enum {
> +    QNUM_I64,
> +    QNUM_DOUBLE
> +} QNumType;

Not bool because you're going to add to it.  Good.

Suggest to call it QNumKind because we already have QType base.type.

> +
> +typedef struct QNum {
> +    QObject base;
> +    QNumType type;
> +    union {
> +        int64_t i64;
> +        double dbl;
> +    } u;
> +} QNum;
> +
> +QNum *qnum_from_int(int64_t value);
> +QNum *qnum_from_double(double value);
> +
> +int64_t qnum_get_int(const QNum *qi, Error **errp);

Let's call the paramter @qn like we do elsewhere.

> +double qnum_get_double(QNum *qn);
> +
> +char *qnum_to_string(QNum *qn);
> +
> +QNum *qobject_to_qnum(const QObject *obj);
> +void qnum_destroy_obj(QObject *obj);
> +
> +#endif /* QNUM_H */
> diff --git a/include/qapi/qmp/types.h b/include/qapi/qmp/types.h
> index 27cfbd84e5..a4bc662bfb 100644
> --- a/include/qapi/qmp/types.h
> +++ b/include/qapi/qmp/types.h
> @@ -14,8 +14,7 @@
>  #define QAPI_QMP_TYPES_H
>  
>  #include "qapi/qmp/qobject.h"
> -#include "qapi/qmp/qint.h"
> -#include "qapi/qmp/qfloat.h"
> +#include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qmp/qdict.h"
> diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-input-visitor.h
> index b399285c43..5a6fe83f8f 100644
> --- a/include/qapi/qobject-input-visitor.h
> +++ b/include/qapi/qobject-input-visitor.h
> @@ -30,7 +30,7 @@ typedef struct QObjectInputVisitor QObjectInputVisitor;
>   * visit_type_FOO() creates an instance of QAPI type FOO.  The visited
>   * QObject must match FOO.  QDict matches struct/union types, QList
>   * matches list types, QString matches type 'str' and enumeration
> - * types, QInt matches integer types, QFloat matches type 'number',
> + * types, QNum matches integer and float types,
>   * QBool matches type 'bool'.  Type 'any' is matched by QObject.  A
>   * QAPI alternate type is matched when one of its member types is.
>   *

Refill the paragraph, please.  Yes, it makes the diff slightly harder to
read (one time pain), and messes a bit with git-blame (occasional pain),
but I'll gladly trade that for slightly more readable comments (avoid
recurring pain).

> diff --git a/include/qapi/qobject-output-visitor.h b/include/qapi/qobject-output-visitor.h
> index 9b990c318e..e5a3490812 100644
> --- a/include/qapi/qobject-output-visitor.h
> +++ b/include/qapi/qobject-output-visitor.h
> @@ -28,10 +28,10 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor;
>   *
>   * visit_type_FOO() creates a QObject for QAPI type FOO.  It creates a
>   * QDict for struct/union types, a QList for list types, QString for
> - * type 'str' and enumeration types, QInt for integer types, QFloat
> - * for type 'number', QBool for type 'bool'.  For type 'any', it
> - * increments the QObject's reference count.  For QAPI alternate
> - * types, it creates the QObject for the member that is in use.
> + * type 'str' and enumeration types, QNum for integer and float
> + * types, QBool for type 'bool'.  For type 'any', it increments the
> + * QObject's reference count.  For QAPI alternate types, it creates
> + * the QObject for the member that is in use.
>   *
>   * visit_start_struct() ... visit_end_struct() visits a QAPI
>   * struct/union and creates a QDict.  Visits in between visit the
> diff --git a/block/blkdebug.c b/block/blkdebug.c
> index 3c088934db..b3032c3ad7 100644
> --- a/block/blkdebug.c
> +++ b/block/blkdebug.c
> @@ -30,7 +30,6 @@
>  #include "qemu/module.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qdict.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qstring.h"
>  #include "sysemu/qtest.h"
>  
> diff --git a/block/nbd.c b/block/nbd.c
> index 975faab2c5..e946ea944d 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -37,7 +37,6 @@
>  #include "qapi/qobject-output-visitor.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qjson.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qemu/cutils.h"
>  
> diff --git a/block/nfs.c b/block/nfs.c
> index 848b2c0bb0..decefd15f1 100644
> --- a/block/nfs.c
> +++ b/block/nfs.c
> @@ -36,7 +36,6 @@
>  #include "qemu/cutils.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/qmp/qdict.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi-visit.h"
>  #include "qapi/qobject-input-visitor.h"
> diff --git a/block/qapi.c b/block/qapi.c
> index a40922ea26..2050df29e4 100644
> --- a/block/qapi.c
> +++ b/block/qapi.c
> @@ -595,9 +595,11 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
>                           int comp_indent, QObject *obj)
>  {
>      switch (qobject_type(obj)) {
> -        case QTYPE_QINT: {
> -            QInt *value = qobject_to_qint(obj);
> -            func_fprintf(f, "%" PRId64, qint_get_int(value));
> +        case QTYPE_QNUM: {
> +            QNum *value = qobject_to_qnum(obj);
> +            char *tmp = qnum_to_string(value);
> +            func_fprintf(f, "%s", tmp);
> +            g_free(tmp);
>              break;
>          }
>          case QTYPE_QSTRING: {

Becomes a bit awkward due to the dynamically allocated buffer.  Let's
ignore that for now.

Aside: I don't like that the block layer has its own dump_qobject().

> @@ -615,11 +617,6 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
>              dump_qlist(func_fprintf, f, comp_indent, value);
>              break;
>          }
> -        case QTYPE_QFLOAT: {
> -            QFloat *value = qobject_to_qfloat(obj);
> -            func_fprintf(f, "%g", qfloat_get_double(value));
> -            break;
> -        }
>          case QTYPE_QBOOL: {
>              QBool *value = qobject_to_qbool(obj);
>              func_fprintf(f, "%s", qbool_get_bool(value) ? "true" : "false");
> diff --git a/block/quorum.c b/block/quorum.c
> index 1b2a8c3937..55ba916655 100644
> --- a/block/quorum.c
> +++ b/block/quorum.c
> @@ -19,7 +19,6 @@
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qerror.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qjson.h"
>  #include "qapi/qmp/qlist.h"
>  #include "qapi/qmp/qstring.h"
> diff --git a/block/sheepdog.c b/block/sheepdog.c
> index a18315a1ca..dea9000bdd 100644
> --- a/block/sheepdog.c
> +++ b/block/sheepdog.c
> @@ -16,7 +16,6 @@
>  #include "qapi-visit.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "qemu/uri.h"
>  #include "qemu/error-report.h"
> diff --git a/block/ssh.c b/block/ssh.c
> index 11203fc5a2..bac3453c3e 100644
> --- a/block/ssh.c
> +++ b/block/ssh.c
> @@ -34,7 +34,6 @@
>  #include "qemu/sockets.h"
>  #include "qemu/uri.h"
>  #include "qapi-visit.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "qapi/qobject-output-visitor.h"
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 9c82371360..6089bba774 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -29,7 +29,6 @@
>  #include "qemu/module.h"
>  #include "qemu/bswap.h"
>  #include "migration/migration.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qemu/cutils.h"

We got lots of stale #include directives...

> diff --git a/blockdev.c b/blockdev.c
> index 0b38c3df71..ed9b839dd2 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -334,8 +334,9 @@ static bool parse_stats_intervals(BlockAcctStats *stats, QList *intervals,
>              break;
>          }
>  
> -        case QTYPE_QINT: {
> -            int64_t length = qint_get_int(qobject_to_qint(entry->value));
> +        case QTYPE_QNUM: {
> +            int64_t length = qnum_get_int(qobject_to_qnum(entry->value),
> +                                          &error_abort);

Before: if entry->value isn't QInt, qint_get_int() dereferences null.

After: if entr->value isn't QNum with QNUM_I64, qnum_get_int() aborts on
setting an error.

Good.

Same argument for similar changes below.

>              if (length > 0 && length <= UINT_MAX) {
>                  block_acct_add_interval(stats, (unsigned) length);
>              } else {
> diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
> index 2b0f3e1bfb..3a531a4416 100644
> --- a/hw/acpi/pcihp.c
> +++ b/hw/acpi/pcihp.c
> @@ -37,7 +37,6 @@
>  #include "hw/pci/pci_bus.h"
>  #include "qapi/error.h"
>  #include "qom/qom-qobject.h"
> -#include "qapi/qmp/qint.h"
>  
>  //#define DEBUG
>  
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 2073108577..ec3ae7fa85 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -57,7 +57,6 @@
>  
>  #include "hw/acpi/aml-build.h"
>  
> -#include "qapi/qmp/qint.h"
>  #include "qom/qom-qobject.h"
>  #include "hw/i386/amd_iommu.h"
>  #include "hw/i386/intel_iommu.h"
> @@ -150,21 +149,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 = qint_get_int(qobject_to_qint(o));
> +        pm->s3_disabled = qnum_get_int(qobject_to_qnum(o), &error_abort);

Aside: there should be a less heavyweight way to read an uint8_t
property than going through a QObject created with a QObject output
visitor.  Not your problem.

>      } 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 = qint_get_int(qobject_to_qint(o));
> +        pm->s4_disabled = qnum_get_int(qobject_to_qnum(o), &error_abort);
>      } 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 = qint_get_int(qobject_to_qint(o));
> +        pm->s4_val = qnum_get_int(qobject_to_qnum(o), &error_abort);
>      } else {
>          pm->s4_val = false;
>      }
> @@ -500,7 +499,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) {
> -        int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
> +        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
>  
>          aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
>          notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
> @@ -610,7 +609,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) {
> -        int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
> +        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
>          aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
>          aml_append(method,
>              aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
> @@ -2586,12 +2585,12 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>      if (!o) {
>          return false;
>      }
> -    mcfg->mcfg_base = qint_get_int(qobject_to_qint(o));
> +    mcfg->mcfg_base = qnum_get_int(qobject_to_qnum(o), &error_abort);
>      qobject_decref(o);
>  
>      o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
>      assert(o);
> -    mcfg->mcfg_size = qint_get_int(qobject_to_qint(o));
> +    mcfg->mcfg_size = qnum_get_int(qobject_to_qnum(o), &error_abort);
>      qobject_decref(o);
>      return true;
>  }
> diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
> index fe62183fe3..584a6f2442 100644
> --- a/hw/usb/xen-usb.c
> +++ b/hw/usb/xen-usb.c
> @@ -30,7 +30,6 @@
>  #include "hw/xen/xen_backend.h"
>  #include "monitor/qdev.h"
>  #include "qapi/qmp/qbool.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qstring.h"
>  
>  #include "hw/xen/io/ring.h"
> diff --git a/monitor.c b/monitor.c
> index 078cba5c86..7a640f0f65 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2972,7 +2972,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
>                      monitor_printf(mon, "Unknown unit suffix\n");
>                      goto fail;
>                  }
> -                qdict_put(qdict, key, qfloat_from_double(val));
> +                qdict_put(qdict, key, qnum_from_double(val));
>              }
>              break;
>          case 'b':
> diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
> index d0f0002317..78425a4369 100644
> --- a/qapi/qobject-input-visitor.c
> +++ b/qapi/qobject-input-visitor.c
> @@ -377,9 +377,6 @@ static void qobject_input_start_alternate(Visitor *v, const char *name,
>      }
>      *obj = g_malloc0(size);
>      (*obj)->type = qobject_type(qobj);
> -    if (promote_int && (*obj)->type == QTYPE_QINT) {
> -        (*obj)->type = QTYPE_QFLOAT;
> -    }
>  }
>  

Never liked this one, glad to see it go.

>  static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
> @@ -387,19 +384,19 @@ static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
>  {
>      QObjectInputVisitor *qiv = to_qiv(v);
>      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> -    QInt *qint;
> +    QNum *qnum;
>  
>      if (!qobj) {
>          return;
>      }
> -    qint = qobject_to_qint(qobj);
> -    if (!qint) {
> +    qnum = qobject_to_qnum(qobj);
> +    if (!qnum) {
>          error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
>                     full_name(qiv, name), "integer");
>          return;
>      }
>  
> -    *obj = qint_get_int(qint);
> +    *obj = qnum_get_int(qnum, errp);

Compare the error message a few lines up

    Invalid parameter type for 'NAME', expected: integer

to the one we get here:

    The number is a float

Which number?  There can be quite a few in a QMP command.  We need to
pass @name to qnum_get_int() for a decent error message, like

    Parameter 'NAME' is not a 64 bit integer

>  }
>  
>  
> @@ -423,22 +420,22 @@ static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
>  static void qobject_input_type_uint64(Visitor *v, const char *name,
>                                        uint64_t *obj, Error **errp)
>  {
> -    /* FIXME: qobject_to_qint mishandles values over INT64_MAX */
> +    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
>      QObjectInputVisitor *qiv = to_qiv(v);
>      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> -    QInt *qint;
> +    QNum *qnum;
>  
>      if (!qobj) {
>          return;
>      }
> -    qint = qobject_to_qint(qobj);
> -    if (!qint) {
> +    qnum = qobject_to_qnum(qobj);
> +    if (!qnum) {
>          error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
>                     full_name(qiv, name), "integer");
>          return;
>      }
>  
> -    *obj = qint_get_int(qint);
> +    *obj = qnum_get_int(qnum, errp);

Likewise.

>  }
>  
>  static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
> @@ -533,21 +530,14 @@ static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
>  {
>      QObjectInputVisitor *qiv = to_qiv(v);
>      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> -    QInt *qint;
> -    QFloat *qfloat;
> +    QNum *qnum;
>  
>      if (!qobj) {
>          return;
>      }
> -    qint = qobject_to_qint(qobj);
> -    if (qint) {
> -        *obj = qint_get_int(qobject_to_qint(qobj));
> -        return;
> -    }
> -
> -    qfloat = qobject_to_qfloat(qobj);
> -    if (qfloat) {
> -        *obj = qfloat_get_double(qobject_to_qfloat(qobj));
> +    qnum = qobject_to_qnum(qobj);
> +    if (qnum) {
> +        *obj = qnum_get_double(qnum);
>          return;
>      }
>  
       error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                  full_name(qiv, name), "number");
   }

Let's clean this up to the more common

       if (!qnum) {
          error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                     full_name(qiv, name), "number");
          return;
       }

       *obj = qnum_get_double(qnum);

Preferrably in another patch, though.

> diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
> index 871127079d..2ca5093b22 100644
> --- a/qapi/qobject-output-visitor.c
> +++ b/qapi/qobject-output-visitor.c
> @@ -144,7 +144,7 @@ static void qobject_output_type_int64(Visitor *v, const char *name,
>                                        int64_t *obj, Error **errp)
>  {
>      QObjectOutputVisitor *qov = to_qov(v);
> -    qobject_output_add(qov, name, qint_from_int(*obj));
> +    qobject_output_add(qov, name, qnum_from_int(*obj));
>  }
>  
>  static void qobject_output_type_uint64(Visitor *v, const char *name,
> @@ -152,7 +152,7 @@ static void qobject_output_type_uint64(Visitor *v, const char *name,
>  {
>      /* FIXME values larger than INT64_MAX become negative */
>      QObjectOutputVisitor *qov = to_qov(v);
> -    qobject_output_add(qov, name, qint_from_int(*obj));
> +    qobject_output_add(qov, name, qnum_from_int(*obj));
>  }
>  
>  static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
> @@ -177,7 +177,7 @@ static void qobject_output_type_number(Visitor *v, const char *name,
>                                         double *obj, Error **errp)
>  {
>      QObjectOutputVisitor *qov = to_qov(v);
> -    qobject_output_add(qov, name, qfloat_from_double(*obj));
> +    qobject_output_add(qov, name, qnum_from_double(*obj));
>  }
>  
>  static void qobject_output_type_any(Visitor *v, const char *name,
> diff --git a/qga/commands.c b/qga/commands.c
> index 3333ed50b2..ff89e805cf 100644
> --- a/qga/commands.c
> +++ b/qga/commands.c
> @@ -485,7 +485,7 @@ int ga_parse_whence(GuestFileWhence *whence, Error **errp)
>  {
>      /* Exploit the fact that we picked values to match QGA_SEEK_*. */
>      if (whence->type == QTYPE_QSTRING) {
> -        whence->type = QTYPE_QINT;
> +        whence->type = QTYPE_QNUM;
>          whence->u.value = whence->u.name;
>      }
>      switch (whence->u.value) {

Aside: modifying *whence is unnecessarily dirty.

> diff --git a/qga/main.c b/qga/main.c
> index cc58d2b53d..405c1290f8 100644
> --- a/qga/main.c
> +++ b/qga/main.c
> @@ -19,7 +19,6 @@
>  #endif
>  #include "qapi/qmp/json-streamer.h"
>  #include "qapi/qmp/json-parser.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qjson.h"
>  #include "qga/guest-agent-core.h"
>  #include "qemu/module.h"
> diff --git a/qobject/json-parser.c b/qobject/json-parser.c
> index c18e48ab94..f431854ba1 100644
> --- a/qobject/json-parser.c
> +++ b/qobject/json-parser.c
> @@ -466,16 +466,16 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
>      } else if (!strcmp(token->str, "%i")) {
>          return QOBJECT(qbool_from_bool(va_arg(*ap, int)));
>      } else if (!strcmp(token->str, "%d")) {
> -        return QOBJECT(qint_from_int(va_arg(*ap, int)));
> +        return QOBJECT(qnum_from_int(va_arg(*ap, int)));
>      } else if (!strcmp(token->str, "%ld")) {
> -        return QOBJECT(qint_from_int(va_arg(*ap, long)));
> +        return QOBJECT(qnum_from_int(va_arg(*ap, long)));
>      } else if (!strcmp(token->str, "%lld") ||
>                 !strcmp(token->str, "%I64d")) {
> -        return QOBJECT(qint_from_int(va_arg(*ap, long long)));
> +        return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
>      } else if (!strcmp(token->str, "%s")) {
>          return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
>      } else if (!strcmp(token->str, "%f")) {
> -        return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
> +        return QOBJECT(qnum_from_double(va_arg(*ap, double)));
>      }
>      return NULL;
>  }
> @@ -494,12 +494,12 @@ static QObject *parse_literal(JSONParserContext *ctxt)
>          /* A possibility exists that this is a whole-valued float where the
>           * fractional part was left out due to being 0 (.0). It's not a big
>           * deal to treat these as ints in the parser, so long as users of the
> -         * resulting QObject know to expect a QInt in place of a QFloat in
> +         * resulting QObject know to expect a QNum in place of a QNum in
>           * cases like these.

Oopsie :)

>           *
>           * However, in some cases these values will overflow/underflow a
> -         * QInt/int64 container, thus we should assume these are to be handled
> -         * as QFloats/doubles rather than silently changing their values.
> +         * QNum/int64 container, thus we should assume these are to be handled
> +         * as QNums/doubles rather than silently changing their values.
>           *
>           * strtoll() indicates these instances by setting errno to ERANGE
>           */

The whole comment needs to be rephrased.

The comment is about two things.  One, explain why code expecting QFloat
must be prepared to accept and convert QInt.  No longer applies.  Two,
explain that we store apparent integers as floating-point numbers when
they don't fit into int64_t.  This is still relevant.

What about:

           /*
            * When a JSON_INTEGER can't be represented as QNUM_I64, use
            * QNUM_DOUBLE instead.  stroll() fails with ERANGE then.
            *
            * Code expecting QNUM_I64 must reject QNUM_DOUBLE as out of
            * range.  qnum_get_int() does, so simply call that.
            *
            * Code expecting QNUM_DOUBLE must also accept QNUM_I64.
            * qnum_get_double() does, so simply call that.
            */

> @@ -508,7 +508,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
>          errno = 0; /* strtoll doesn't set errno on success */
>          value = strtoll(token->str, NULL, 10);
>          if (errno != ERANGE) {
> -            return QOBJECT(qint_from_int(value));
> +            return QOBJECT(qnum_from_int(value));
>          }
>          /* fall through to JSON_FLOAT */
>      }
> @@ -516,7 +516,7 @@ static QObject *parse_literal(JSONParserContext *ctxt)
>          /* FIXME dependent on locale; a pervasive issue in QEMU */
>          /* FIXME our lexer matches RFC 7159 in forbidding Inf or NaN,
>           * but those might be useful extensions beyond JSON */
> -        return QOBJECT(qfloat_from_double(strtod(token->str, NULL)));
> +        return QOBJECT(qnum_from_double(strtod(token->str, NULL)));
>      default:
>          abort();
>      }
> diff --git a/qobject/qdict.c b/qobject/qdict.c
> index 88e2ecd658..ad5bab9572 100644
> --- a/qobject/qdict.c
> +++ b/qobject/qdict.c
> @@ -11,8 +11,7 @@
>   */
>  
>  #include "qemu/osdep.h"
> -#include "qapi/qmp/qint.h"
> -#include "qapi/qmp/qfloat.h"
> +#include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qstring.h"
> @@ -180,37 +179,26 @@ size_t qdict_size(const QDict *qdict)
>  /**
>   * qdict_get_double(): Get an number mapped by 'key'
>   *
> - * This function assumes that 'key' exists and it stores a
> - * QFloat or QInt object.
> + * This function assumes that 'key' exists and it stores a QNum.
>   *
>   * Return number mapped by 'key'.
>   */
>  double qdict_get_double(const QDict *qdict, const char *key)
>  {
> -    QObject *obj = qdict_get(qdict, key);
> -
> -    assert(obj);
> -    switch (qobject_type(obj)) {
> -    case QTYPE_QFLOAT:
> -        return qfloat_get_double(qobject_to_qfloat(obj));
> -    case QTYPE_QINT:
> -        return qint_get_int(qobject_to_qint(obj));
> -    default:
> -        abort();
> -    }
> +    return qnum_get_double(qobject_to_qnum(qdict_get(qdict, key)));
>  }
>  
>  /**
>   * qdict_get_int(): Get an integer mapped by 'key'
>   *
>   * This function assumes that 'key' exists and it stores a
> - * QInt object.
> + * QNum representable as int.
>   *
>   * Return integer mapped by 'key'.
>   */
>  int64_t qdict_get_int(const QDict *qdict, const char *key)
>  {
> -    return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
> +    return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)), &error_abort);

Line is a bit long for my taste.

>  }
>  
>  /**
> @@ -260,15 +248,25 @@ const char *qdict_get_str(const QDict *qdict, const char *key)
>   * qdict_get_try_int(): Try to get integer mapped by 'key'
>   *
>   * Return integer mapped by 'key', if it is not present in
> - * the dictionary or if the stored object is not of QInt type
> + * the dictionary or if the stored object is not of QNum type

Actually "is not a QNum representing an integer".

>   * 'def_value' will be returned.
>   */
>  int64_t qdict_get_try_int(const QDict *qdict, const char *key,
>                            int64_t def_value)
>  {
> -    QInt *qint = qobject_to_qint(qdict_get(qdict, key));
> +    Error *err = NULL;
> +    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
> +    int64_t val = def_value;
> +
> +    if (qnum) {
> +        val = qnum_get_int(qnum, &err);
> +    }
> +    if (err) {
> +        error_free(err);
> +        val = def_value;
> +    }

This is a bit inefficient: it creates and destroys an Error object.
Easily avoided with a predicate qnum_is_int().

>  
> -    return qint ? qint_get_int(qint) : def_value;
> +    return val;
>  }
>  
>  /**
> diff --git a/qobject/qfloat.c b/qobject/qfloat.c
> deleted file mode 100644
> index d5da847701..0000000000
> --- a/qobject/qfloat.c
> +++ /dev/null
> @@ -1,62 +0,0 @@
> -/*
> - * QFloat Module
> - *
> - * Copyright IBM, Corp. 2009
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
> - *
> - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> - * See the COPYING.LIB file in the top-level directory.
> - *
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qapi/qmp/qfloat.h"
> -#include "qapi/qmp/qobject.h"
> -#include "qemu-common.h"
> -
> -/**
> - * qfloat_from_int(): Create a new QFloat from a float
> - *
> - * Return strong reference.
> - */
> -QFloat *qfloat_from_double(double value)
> -{
> -    QFloat *qf;
> -
> -    qf = g_malloc(sizeof(*qf));
> -    qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
> -    qf->value = value;
> -
> -    return qf;
> -}
> -
> -/**
> - * qfloat_get_double(): Get the stored float
> - */
> -double qfloat_get_double(const QFloat *qf)
> -{
> -    return qf->value;
> -}
> -
> -/**
> - * qobject_to_qfloat(): Convert a QObject into a QFloat
> - */
> -QFloat *qobject_to_qfloat(const QObject *obj)
> -{
> -    if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
> -        return NULL;
> -    }
> -    return container_of(obj, QFloat, base);
> -}
> -
> -/**
> - * qfloat_destroy_obj(): Free all memory allocated by a
> - * QFloat object
> - */
> -void qfloat_destroy_obj(QObject *obj)
> -{
> -    assert(obj != NULL);
> -    g_free(qobject_to_qfloat(obj));
> -}
> diff --git a/qobject/qint.c b/qobject/qint.c
> deleted file mode 100644
> index d7d1b3021f..0000000000
> --- a/qobject/qint.c
> +++ /dev/null
> @@ -1,61 +0,0 @@
> -/*
> - * QInt Module
> - *
> - * Copyright (C) 2009 Red Hat Inc.
> - *
> - * Authors:
> - *  Luiz Capitulino <lcapitulino@redhat.com>
> - *
> - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> - * See the COPYING.LIB file in the top-level directory.
> - */
> -
> -#include "qemu/osdep.h"
> -#include "qapi/qmp/qint.h"
> -#include "qapi/qmp/qobject.h"
> -#include "qemu-common.h"
> -
> -/**
> - * qint_from_int(): Create a new QInt from an int64_t
> - *
> - * Return strong reference.
> - */
> -QInt *qint_from_int(int64_t value)
> -{
> -    QInt *qi;
> -
> -    qi = g_malloc(sizeof(*qi));
> -    qobject_init(QOBJECT(qi), QTYPE_QINT);
> -    qi->value = value;
> -
> -    return qi;
> -}
> -
> -/**
> - * qint_get_int(): Get the stored integer
> - */
> -int64_t qint_get_int(const QInt *qi)
> -{
> -    return qi->value;
> -}
> -
> -/**
> - * qobject_to_qint(): Convert a QObject into a QInt
> - */
> -QInt *qobject_to_qint(const QObject *obj)
> -{
> -    if (!obj || qobject_type(obj) != QTYPE_QINT) {
> -        return NULL;
> -    }
> -    return container_of(obj, QInt, base);
> -}
> -
> -/**
> - * qint_destroy_obj(): Free all memory allocated by a
> - * QInt object
> - */
> -void qint_destroy_obj(QObject *obj)
> -{
> -    assert(obj != NULL);
> -    g_free(qobject_to_qint(obj));
> -}
> diff --git a/qobject/qjson.c b/qobject/qjson.c
> index b2f3bfec53..2e0930884e 100644
> --- a/qobject/qjson.c
> +++ b/qobject/qjson.c
> @@ -132,12 +132,11 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
>      case QTYPE_QNULL:
>          qstring_append(str, "null");
>          break;
> -    case QTYPE_QINT: {
> -        QInt *val = qobject_to_qint(obj);
> -        char buffer[1024];
> -
> -        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
> +    case QTYPE_QNUM: {
> +        QNum *val = qobject_to_qnum(obj);
> +        char *buffer = qnum_to_string(val);
>          qstring_append(str, buffer);
> +        g_free(buffer);
>          break;
>      }
>      case QTYPE_QSTRING: {
> @@ -234,34 +233,6 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
>          qstring_append(str, "]");
>          break;
>      }
> -    case QTYPE_QFLOAT: {
> -        QFloat *val = qobject_to_qfloat(obj);
> -        char buffer[1024];
> -        int len;
> -
> -        /* FIXME: snprintf() is locale dependent; but JSON requires
> -         * numbers to be formatted as if in the C locale. Dependence
> -         * on C locale is a pervasive issue in QEMU. */
> -        /* FIXME: This risks printing Inf or NaN, which are not valid
> -         * JSON values. */
> -        /* FIXME: the default precision of 6 for %f often causes
> -         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
> -         * and only rounding to a shorter number if the result would
> -         * still produce the same floating point value.  */
> -        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
> -        while (len > 0 && buffer[len - 1] == '0') {
> -            len--;
> -        }
> -
> -        if (len && buffer[len - 1] == '.') {
> -            buffer[len - 1] = 0;
> -        } else {
> -            buffer[len] = 0;
> -        }
> -
> -        qstring_append(str, buffer);
> -        break;
> -    }
>      case QTYPE_QBOOL: {
>          QBool *val = qobject_to_qbool(obj);
>  
> diff --git a/qobject/qnum.c b/qobject/qnum.c
> new file mode 100644
> index 0000000000..8e9dd38350
> --- /dev/null
> +++ b/qobject/qnum.c
> @@ -0,0 +1,138 @@
> +/*
> + * QNum Module
> + *
> + * Copyright (C) 2009 Red Hat Inc.
> + *
> + * Authors:
> + *  Luiz Capitulino <lcapitulino@redhat.com>
> + *  Marc-André Lureau <marcandre.lureau@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qapi/qmp/qnum.h"
> +#include "qapi/qmp/qobject.h"
> +#include "qemu-common.h"
> +
> +/**
> + * qnum_from_int(): Create a new QNum from an int64_t
> + *
> + * Return strong reference.
> + */
> +QNum *qnum_from_int(int64_t value)
> +{
> +    QNum *qn = g_new(QNum, 1);
> +
> +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> +    qn->type = QNUM_I64;
> +    qn->u.i64 = value;
> +
> +    return qn;
> +}
> +
> +/**
> + * qnum_from_double(): Create a new QNum from a double
> + *
> + * Return strong reference.
> + */
> +QNum *qnum_from_double(double value)
> +{
> +    QNum *qn = g_new(QNum, 1);
> +
> +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> +    qn->type = QNUM_DOUBLE;
> +    qn->u.dbl = value;
> +
> +    return qn;
> +}
> +
> +/**
> + * qnum_get_int(): Get an integer representation of the number
> + */
> +int64_t qnum_get_int(const QNum *qn, Error **errp)
> +{
> +    switch (qn->type) {
> +    case QNUM_I64:
> +        return qn->u.i64;
> +    case QNUM_DOUBLE:
> +        error_setg(errp, "The number is a float");
> +        return 0;
> +    }
> +
> +    g_assert_not_reached();

g_assert_not_reached() is problematic, see "[PATCH] checkpatch: Disallow
glib asserts in main code".

Message-Id: <20170427165526.19836-1-dgilbert@redhat.com>
https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg05499.html

More of the same below.

The function does the right thing for QNums created by the JSON parser,
which picks the QNumType carefully, in parse_literal():

* if the JSON number has neither a fractional nor an exponent part, and

  - fits into int64_t, use qnum_from_int()
  - fits into uint64_t, use qnum_from_uint()

  (if it fits both, qnum_from_int(), but that should not matter)

* else, use qnum_from_double().

For such a QNum, rejecting QNUM_DOUBLE here is correct, because the
value either had a fractional part, an exponent part, or didn't fit
int64_t.

Other code using qnum_from_int() and qnum_from_double() needs to be
similarly careful.

As discussed above, the function needs a @name parameter so it can
create better error message.

Could also try leave the Error business entirely to the caller, and only
return success / failure here.  Pick what you like better.

> +}
> +
> +/**
> + * qnum_get_double(): Get a float representation of the number
> + */
> +double qnum_get_double(QNum *qn)
> +{
> +    switch (qn->type) {
> +    case QNUM_I64:
> +        return qn->u.i64;
> +    case QNUM_DOUBLE:
> +        return qn->u.dbl;
> +    }
> +
> +    g_assert_not_reached();
> +}
> +
> +char *qnum_to_string(QNum *qn)
> +{
> +    char *buffer;
> +    int len;
> +
> +    switch (qn->type) {
> +    case QNUM_I64:
> +        return g_strdup_printf("%" PRId64, qn->u.i64);
> +    case QNUM_DOUBLE:
> +        /* FIXME: snprintf() is locale dependent; but JSON requires
> +         * numbers to be formatted as if in the C locale. Dependence
> +         * on C locale is a pervasive issue in QEMU. */
> +        /* FIXME: This risks printing Inf or NaN, which are not valid
> +         * JSON values. */
> +        /* FIXME: the default precision of 6 for %f often causes
> +         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
> +         * and only rounding to a shorter number if the result would
> +         * still produce the same floating point value.  */
> +        buffer = g_strdup_printf("%f" , qn->u.dbl);
> +        len = strlen(buffer);
> +        while (len > 0 && buffer[len - 1] == '0') {
> +            len--;
> +        }
> +
> +        if (len && buffer[len - 1] == '.') {
> +            buffer[len - 1] = 0;
> +        } else {
> +            buffer[len] = 0;
> +        }
> +
> +        return buffer;
> +    }
> +
> +    g_assert_not_reached();
> +}
> +
> +/**
> + * 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_destroy_obj(): Free all memory allocated by a
> + * QNum object
> + */
> +void qnum_destroy_obj(QObject *obj)
> +{
> +    assert(obj != NULL);
> +    g_free(qobject_to_qnum(obj));
> +}
> diff --git a/qobject/qobject.c b/qobject/qobject.c
> index fe4fa10989..b0cafb66f1 100644
> --- a/qobject/qobject.c
> +++ b/qobject/qobject.c
> @@ -14,11 +14,10 @@
>  static void (*qdestroy[QTYPE__MAX])(QObject *) = {
>      [QTYPE_NONE] = NULL,               /* No such object exists */
>      [QTYPE_QNULL] = NULL,              /* qnull_ is indestructible */
> -    [QTYPE_QINT] = qint_destroy_obj,
> +    [QTYPE_QNUM] = qnum_destroy_obj,
>      [QTYPE_QSTRING] = qstring_destroy_obj,
>      [QTYPE_QDICT] = qdict_destroy_obj,
>      [QTYPE_QLIST] = qlist_destroy_obj,
> -    [QTYPE_QFLOAT] = qfloat_destroy_obj,
>      [QTYPE_QBOOL] = qbool_destroy_obj,
>  };
>  
> diff --git a/qom/object.c b/qom/object.c
> index c7b8079df6..c1644dbcb7 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -27,7 +27,6 @@
>  #include "qom/qom-qobject.h"
>  #include "qapi/qmp/qobject.h"
>  #include "qapi/qmp/qbool.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qstring.h"
>  
>  #define MAX_INTERFACES 32
> @@ -1190,28 +1189,32 @@ bool object_property_get_bool(Object *obj, const char *name,
>  void object_property_set_int(Object *obj, int64_t value,
>                               const char *name, Error **errp)
>  {
> -    QInt *qint = qint_from_int(value);
> -    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
> +    QNum *qnum = qnum_from_int(value);
> +    object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
>  
> -    QDECREF(qint);
> +    QDECREF(qnum);
>  }
>  
>  int64_t object_property_get_int(Object *obj, const char *name,
>                                  Error **errp)
>  {
>      QObject *ret = object_property_get_qobject(obj, name, errp);
> -    QInt *qint;
> +    Error *err = NULL;
> +    QNum *qnum;
>      int64_t retval;
>  
>      if (!ret) {
>          return -1;
>      }
> -    qint = qobject_to_qint(ret);
> -    if (!qint) {
> +    qnum = qobject_to_qnum(ret);
> +    if (qnum) {
> +        retval = qnum_get_int(qnum, &err);
> +    }
> +
> +    if (!qnum || err) {
>          error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
> +        error_free(err);
>          retval = -1;
> -    } else {
> -        retval = qint_get_int(qint);
>      }
>  

The error message could be improved, but that's outside your patch's
scope.

>      qobject_decref(ret);
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 13c0985f11..1e8a5b55c0 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -29,11 +29,7 @@
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
>  #include "qapi/qmp/qerror.h"
> -#include "qapi/qmp/qstring.h"
> -#include "qapi/qmp/qdict.h"
> -#include "qapi/qmp/qbool.h"
> -#include "qapi/qmp/qint.h"
> -#include "qapi/qmp/qfloat.h"
> +#include "qapi/qmp/types.h"
>  
>  #include "qapi-types.h"
>  #include "qapi-visit.h"
[Skipping tests in this first pass...]

I rather like the patch so far :)

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-11 14:29   ` Markus Armbruster
@ 2017-05-11 15:09     ` Eric Blake
  2017-05-30  7:32     ` Marc-André Lureau
  1 sibling, 0 replies; 70+ messages in thread
From: Eric Blake @ 2017-05-11 15:09 UTC (permalink / raw)
  To: Markus Armbruster, Marc-André Lureau; +Cc: qemu-devel

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

On 05/11/2017 09:29 AM, Markus Armbruster wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
>> We would like to use a same QObject type to represent numbers, whether
>> they are int, uint, or floats. getters will allow some compatibility
> 
> Please start your sentence with a capital letter ...
> 
>> between the various types if the number fits other representations
> 
> ... and end them with a period.
> 

>> +++ b/block/qapi.c
>> @@ -595,9 +595,11 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
>>                           int comp_indent, QObject *obj)
>>  {
>>      switch (qobject_type(obj)) {
>> -        case QTYPE_QINT: {
>> -            QInt *value = qobject_to_qint(obj);
>> -            func_fprintf(f, "%" PRId64, qint_get_int(value));
>> +        case QTYPE_QNUM: {
>> +            QNum *value = qobject_to_qnum(obj);
>> +            char *tmp = qnum_to_string(value);
>> +            func_fprintf(f, "%s", tmp);
>> +            g_free(tmp);
>>              break;
>>          }
>>          case QTYPE_QSTRING: {
> 
> Becomes a bit awkward due to the dynamically allocated buffer.  Let's
> ignore that for now.
> 
> Aside: I don't like that the block layer has its own dump_qobject().

I should really revive my patches for a QAPI JSON output visitor.

-- 
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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 05/17] qapi: remove promote_int
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 05/17] qapi: remove promote_int Marc-André Lureau
@ 2017-05-11 17:30   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-11 17:30 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> qnum_to_double() implicity promotes int now.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

qnum_to_double() works for both for integers and doubles.  That's not
really new; it's what we've always done when we need a double, see
qobject_input_type_number() before your patch.

promote_int is about visit_start_alternate().  It's called before the
switch over the alternate object's member type (of type QType).

Input visitors allocate the alternate object, and set member type to a
value determined by the input.  promote_int = true asks the input
visitor to set type to QTYPE_QFLOAT when the input would otherwise call
for QTYPE_QINT.

Non-input visitors leave member type alone.

The generated visitors pass promote_int = true exactly when QTYPE_QINT
isn't a valid type.  Without that, we'd have to monkey-patch QTYPE_QINT
to QTYPE_QFLOAT in every generated visitor, just in case it's used with
an input visitor.  Not exactly elegant, but it works.

The only input visitor that implements alternates right now is the
QObject input visitor.

The previous patch fused QTYPE_QINT and QTYPE_QFLOAT, rendering
promote_int useless and unused.

Here's my attempt at a commit message:

    qapi: Remove visit_start_alternate() parameter promote_int

    Before the previous commit, parameter promote_int = true made
    visit_start_alternate() with an input visitor avoid QTYPE_QINT
    variants and create QTYPE_QFLOAT variants instead.  This was used
    where QTYPE_QINT variants were invalid.

    The previous commit fused QTYPE_QINT with QTYPE_QFLOAT, rendering
    rendering promote_int useless and unused.

Patch looks good to me.

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
  2017-05-11 14:29   ` Markus Armbruster
@ 2017-05-12  6:30   ` Markus Armbruster
  2017-05-12 13:00     ` Luiz Capitulino
  2017-05-12  7:37   ` Markus Armbruster
  2 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-12  6:30 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Luiz Capitulino

Question for Luiz...

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

[...]
> diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> new file mode 100644
> index 0000000000..d08d35e85a
> --- /dev/null
> +++ b/tests/check-qnum.c
> @@ -0,0 +1,131 @@
> +/*
> + * QNum unit-tests.
> + *
> + * Copyright (C) 2009 Red Hat Inc.
> + *
> + * Authors:
> + *  Luiz Capitulino <lcapitulino@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + */
> +#include "qemu/osdep.h"
> +
> +#include "qapi/qmp/qnum.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +
> +/*
> + * Public Interface test-cases
> + *
> + * (with some violations to access 'private' data)
> + */
> +
> +static void qnum_from_int_test(void)
> +{
> +    QNum *qi;
> +    const int value = -42;
> +
> +    qi = qnum_from_int(value);
> +    g_assert(qi != NULL);
> +    g_assert_cmpint(qi->u.i64, ==, value);
> +    g_assert_cmpint(qi->base.refcnt, ==, 1);
> +    g_assert_cmpint(qobject_type(QOBJECT(qi)), ==, QTYPE_QNUM);
> +
> +    // destroy doesn't exit yet
> +    g_free(qi);
> +}

The comment is enigmatic.  It was first written in commit 33837ba
"Introduce QInt unit-tests", and got copied around since.  In
check-qlist.c, it's spelled "exist yet".

What is "destroy", why doesn't it exit / exist now, but will exit /
exist later?  It can't be qnum_destroy_obj(), because that certainly
exists already, exits already in the sense of returning, and shouldn't
ever exit in the sense of terminating the program.

The comment applies to a g_free().  Why do we free directly instead
decrementing the reference count?  Perhaps the comment tries to explain
that (if it does, it fails).

Luiz, any idea?

[...]

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
  2017-05-11 14:29   ` Markus Armbruster
  2017-05-12  6:30   ` Markus Armbruster
@ 2017-05-12  7:37   ` Markus Armbruster
  2017-05-12 13:03     ` Luiz Capitulino
  2 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-12  7:37 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Luiz Capitulino

Luiz, there's a lone question for you further down.  Search for your
name.

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> We would like to use a same QObject type to represent numbers, whether
> they are int, uint, or floats. getters will allow some compatibility
> between the various types if the number fits other representations
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[Snip part I already reviewed...]
> diff --git a/tests/check-qdict.c b/tests/check-qdict.c
> index be8d81f07b..bcd06a7d6b 100644
> --- a/tests/check-qdict.c
> +++ b/tests/check-qdict.c
> @@ -11,7 +11,6 @@
>   */
>  #include "qemu/osdep.h"
>  
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/error.h"
> @@ -39,7 +38,7 @@ static void qdict_new_test(void)
>  
>  static void qdict_put_obj_test(void)
>  {
> -    QInt *qi;
> +    QNum *qi;
>      QDict *qdict;
>      QDictEntry *ent;
>      const int num = 42;
> @@ -51,8 +50,8 @@ static void qdict_put_obj_test(void)
>  
>      g_assert(qdict_size(qdict) == 1);
>      ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
> -    qi = qobject_to_qint(ent->value);
> -    g_assert(qint_get_int(qi) == num);
> +    qi = qobject_to_qnum(ent->value);
> +    g_assert(qnum_get_int(qi, &error_abort) == num);
>  
>      // destroy doesn't exit yet
>      QDECREF(qi);

Since you're touching three out of four lines containing @qi anyway:
rename it to @qn?  You rename like that in some places, but not all.

> @@ -74,7 +73,7 @@ static void qdict_destroy_simple_test(void)
>  
>  static void qdict_get_test(void)
>  {
> -    QInt *qi;
> +    QNum *qi;
>      QObject *obj;
>      const int value = -42;
>      const char *key = "test";
> @@ -85,8 +84,8 @@ static void qdict_get_test(void)
>      obj = qdict_get(tests_dict, key);
>      g_assert(obj != NULL);
>  
> -    qi = qobject_to_qint(obj);
> -    g_assert(qint_get_int(qi) == value);
> +    qi = qobject_to_qnum(obj);
> +    g_assert(qnum_get_int(qi, &error_abort) == value);
>  
>      QDECREF(tests_dict);
>  }
> @@ -329,7 +328,7 @@ static void qdict_array_split_test(void)
>  {
>      QDict *test_dict = qdict_new();
>      QDict *dict1, *dict2;
> -    QInt *int1;
> +    QNum *int1;
>      QList *test_list;
>  
>      /*
> @@ -380,7 +379,7 @@ static void qdict_array_split_test(void)
>  
>      dict1 = qobject_to_qdict(qlist_pop(test_list));
>      dict2 = qobject_to_qdict(qlist_pop(test_list));
> -    int1 = qobject_to_qint(qlist_pop(test_list));
> +    int1 = qobject_to_qnum(qlist_pop(test_list));
>  
>      g_assert(dict1);
>      g_assert(dict2);
> @@ -402,7 +401,7 @@ static void qdict_array_split_test(void)
>  
>      QDECREF(dict2);
>  
> -    g_assert(qint_get_int(int1) == 66);
> +    g_assert(qnum_get_int(int1, &error_abort) == 66);
>  
>      QDECREF(int1);
>  
> @@ -447,14 +446,14 @@ static void qdict_array_split_test(void)
>  
>      qdict_array_split(test_dict, &test_list);
>  
> -    int1 = qobject_to_qint(qlist_pop(test_list));
> +    int1 = qobject_to_qnum(qlist_pop(test_list));
>  
>      g_assert(int1);
>      g_assert(qlist_empty(test_list));
>  
>      QDECREF(test_list);
>  
> -    g_assert(qint_get_int(int1) == 42);
> +    g_assert(qnum_get_int(int1, &error_abort) == 42);
>  
>      QDECREF(int1);
>  
> diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c
> deleted file mode 100644
> index 1da2cdae08..0000000000
> --- a/tests/check-qfloat.c
> +++ /dev/null
> @@ -1,53 +0,0 @@
> -/*
> - * QFloat unit-tests.
> - *
> - * Copyright IBM, Corp. 2009
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
> - *
> - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> - * See the COPYING.LIB file in the top-level directory.
> - *
> - */
> -#include "qemu/osdep.h"
> -
> -#include "qapi/qmp/qfloat.h"
> -#include "qemu-common.h"
> -
> -/*
> - * Public Interface test-cases
> - *
> - * (with some violations to access 'private' data)
> - */
> -
> -static void qfloat_from_double_test(void)
> -{
> -    QFloat *qf;
> -    const double value = -42.23423;
> -
> -    qf = qfloat_from_double(value);
> -    g_assert(qf != NULL);
> -    g_assert(qf->value == value);
> -    g_assert(qf->base.refcnt == 1);
> -    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
> -
> -    // destroy doesn't exit yet
> -    g_free(qf);
> -}
> -
> -static void qfloat_destroy_test(void)
> -{
> -    QFloat *qf = qfloat_from_double(0.0);
> -    QDECREF(qf);
> -}
> -
> -int main(int argc, char **argv)
> -{
> -    g_test_init(&argc, &argv, NULL);
> -
> -    g_test_add_func("/public/from_double", qfloat_from_double_test);
> -    g_test_add_func("/public/destroy", qfloat_destroy_test);
> -
> -    return g_test_run();
> -}
> diff --git a/tests/check-qint.c b/tests/check-qint.c
> deleted file mode 100644
> index b6e4555115..0000000000
> --- a/tests/check-qint.c
> +++ /dev/null
> @@ -1,87 +0,0 @@
> -/*
> - * QInt unit-tests.
> - *
> - * Copyright (C) 2009 Red Hat Inc.
> - *
> - * Authors:
> - *  Luiz Capitulino <lcapitulino@redhat.com>
> - *
> - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> - * See the COPYING.LIB file in the top-level directory.
> - */
> -#include "qemu/osdep.h"
> -
> -#include "qapi/qmp/qint.h"
> -#include "qemu-common.h"
> -
> -/*
> - * Public Interface test-cases
> - *
> - * (with some violations to access 'private' data)
> - */
> -
> -static void qint_from_int_test(void)
> -{
> -    QInt *qi;
> -    const int value = -42;
> -
> -    qi = qint_from_int(value);
> -    g_assert(qi != NULL);
> -    g_assert(qi->value == value);
> -    g_assert(qi->base.refcnt == 1);
> -    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
> -
> -    // destroy doesn't exit yet
> -    g_free(qi);
> -}
> -
> -static void qint_destroy_test(void)
> -{
> -    QInt *qi = qint_from_int(0);
> -    QDECREF(qi);
> -}
> -
> -static void qint_from_int64_test(void)
> -{
> -    QInt *qi;
> -    const int64_t value = 0x1234567890abcdefLL;
> -
> -    qi = qint_from_int(value);
> -    g_assert((int64_t) qi->value == value);
> -
> -    QDECREF(qi);
> -}
> -
> -static void qint_get_int_test(void)
> -{
> -    QInt *qi;
> -    const int value = 123456;
> -
> -    qi = qint_from_int(value);
> -    g_assert(qint_get_int(qi) == value);
> -
> -    QDECREF(qi);
> -}
> -
> -static void qobject_to_qint_test(void)
> -{
> -    QInt *qi;
> -
> -    qi = qint_from_int(0);
> -    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
> -
> -    QDECREF(qi);
> -}
> -
> -int main(int argc, char **argv)
> -{
> -    g_test_init(&argc, &argv, NULL);
> -
> -    g_test_add_func("/public/from_int", qint_from_int_test);
> -    g_test_add_func("/public/destroy", qint_destroy_test);
> -    g_test_add_func("/public/from_int64", qint_from_int64_test);
> -    g_test_add_func("/public/get_int", qint_get_int_test);
> -    g_test_add_func("/public/to_qint", qobject_to_qint_test);
> -
> -    return g_test_run();
> -}
> diff --git a/tests/check-qjson.c b/tests/check-qjson.c
> index 963dd46f07..c432aebf13 100644
> --- a/tests/check-qjson.c
> +++ b/tests/check-qjson.c
> @@ -886,21 +886,21 @@ static void simple_number(void)
>      };
>  
>      for (i = 0; test_cases[i].encoded; i++) {
> -        QInt *qint;
> +        QNum *qnum;
>  
> -        qint = qobject_to_qint(qobject_from_json(test_cases[i].encoded,
> +        qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
>                                                   &error_abort));
> -        g_assert(qint);
> -        g_assert(qint_get_int(qint) == test_cases[i].decoded);
> +        g_assert(qnum);
> +        g_assert(qnum_get_int(qnum, &error_abort) == test_cases[i].decoded);
>          if (test_cases[i].skip == 0) {
>              QString *str;
>  
> -            str = qobject_to_json(QOBJECT(qint));
> +            str = qobject_to_json(QOBJECT(qnum));
>              g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
>              QDECREF(str);
>          }
>  
> -        QDECREF(qint);
> +        QDECREF(qnum);
>      }
>  }
>  
> @@ -921,12 +921,12 @@ static void float_number(void)
>  
>      for (i = 0; test_cases[i].encoded; i++) {
>          QObject *obj;
> -        QFloat *qfloat;
> +        QNum *qnum;
>  
>          obj = qobject_from_json(test_cases[i].encoded, &error_abort);
> -        qfloat = qobject_to_qfloat(obj);
> -        g_assert(qfloat);
> -        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
> +        qnum = qobject_to_qnum(obj);
> +        g_assert(qnum);
> +        g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
>  
>          if (test_cases[i].skip == 0) {
>              QString *str;
> @@ -936,29 +936,28 @@ static void float_number(void)
>              QDECREF(str);
>          }
>  
> -        QDECREF(qfloat);
> +        QDECREF(qnum);
>      }
>  }
>  
>  static void vararg_number(void)
>  {
> -    QInt *qint;
> -    QFloat *qfloat;
> +    QNum *qnum;
>      int value = 0x2342;
>      long long value_ll = 0x2342342343LL;
>      double valuef = 2.323423423;
>  
> -    qint = qobject_to_qint(qobject_from_jsonf("%d", value));
> -    g_assert(qint_get_int(qint) == value);
> -    QDECREF(qint);
> +    qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
> +    g_assert(qnum_get_int(qnum, &error_abort) == value);
> +    QDECREF(qnum);
>  
> -    qint = qobject_to_qint(qobject_from_jsonf("%lld", value_ll));
> -    g_assert(qint_get_int(qint) == value_ll);
> -    QDECREF(qint);
> +    qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
> +    g_assert(qnum_get_int(qnum, &error_abort) == value_ll);
> +    QDECREF(qnum);
>  
> -    qfloat = qobject_to_qfloat(qobject_from_jsonf("%f", valuef));
> -    g_assert(qfloat_get_double(qfloat) == valuef);
> -    QDECREF(qfloat);
> +    qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
> +    g_assert(qnum_get_double(qnum) == valuef);
> +    QDECREF(qnum);
>  }
>  
>  static void keyword_literal(void)

By now we see the pattern.  It's a mechanical transformation

    - qobject_to_qint(E)
    + qobject_to_qnum(E)

    - qint_get_int(E)
    + qnum_get_int(E, &error_abort)

    - qobject_to_qfloat(E)
    + qobject_to_qnum(E)

    - qfloat_get_double(E)
    + qnum_get_double(E)

plus replacement / merge of QInt / QFloat variables.  Did you do it
entirely by hand or with help from Coccinelle?

A helper function qnum_get_int_nofail(E) would result in slightly more
compact source code (object code probably, too), but I'm not sure it's
worth it.

Other patterns that might justify helpers:

    qnum_get_double(qobject_to_qnum(OBJ))
    qnum_get_int(qobject_to_qnum(OBJ), ERR)
    qnum_get_int(qobject_to_qnum(OBJ), &error_abort)

These are ideas, not demands.

> @@ -1019,7 +1018,7 @@ struct LiteralQObject
>  {
>      int type;
>      union {
> -        int64_t qint;
> +        int64_t qnum;
>          const char *qstr;
>          LiteralQDictEntry *qdict;
>          LiteralQObject *qlist;
> @@ -1032,7 +1031,7 @@ struct LiteralQDictEntry
>      LiteralQObject value;
>  };
>  
> -#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
> +#define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
>  #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
>  #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
>  #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}

Aside: yet another private way to compare actual QObjects to expected
ones.  We should pick *one* way to compare, and stick to it.

> @@ -1069,8 +1068,9 @@ static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
>      }
>  
>      switch (lhs->type) {
> -    case QTYPE_QINT:
> -        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
> +    case QTYPE_QNUM:
> +        return lhs->value.qnum == qnum_get_int(qobject_to_qnum(rhs),
> +                                               &error_abort);
>      case QTYPE_QSTRING:
>          return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
>      case QTYPE_QDICT: {
> @@ -1114,7 +1114,7 @@ static void simple_dict(void)
>          {
>              .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
>              .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
> -                        { "foo", QLIT_QINT(42) },
> +                        { "foo", QLIT_QNUM(42) },
>                          { "bar", QLIT_QSTR("hello world") },
>                          { }
>                      })),
> @@ -1126,7 +1126,7 @@ static void simple_dict(void)
>          }, {
>              .encoded = "{\"foo\": 43}",
>              .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
> -                        { "foo", QLIT_QINT(43) },
> +                        { "foo", QLIT_QNUM(43) },
>                          { }
>                      })),
>          },
> @@ -1212,15 +1212,15 @@ static void simple_list(void)
>          {
>              .encoded = "[43,42]",
>              .decoded = QLIT_QLIST(((LiteralQObject[]){
> -                        QLIT_QINT(43),
> -                        QLIT_QINT(42),
> +                        QLIT_QNUM(43),
> +                        QLIT_QNUM(42),
>                          { }
>                      })),
>          },
>          {
>              .encoded = "[43]",
>              .decoded = QLIT_QLIST(((LiteralQObject[]){
> -                        QLIT_QINT(43),
> +                        QLIT_QNUM(43),
>                          { }
>                      })),
>          },
> @@ -1269,35 +1269,35 @@ static void simple_whitespace(void)
>          {
>              .encoded = " [ 43 , 42 ]",
>              .decoded = QLIT_QLIST(((LiteralQObject[]){
> -                        QLIT_QINT(43),
> -                        QLIT_QINT(42),
> +                        QLIT_QNUM(43),
> +                        QLIT_QNUM(42),
>                          { }
>                      })),
>          },
>          {
>              .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
>              .decoded = QLIT_QLIST(((LiteralQObject[]){
> -                        QLIT_QINT(43),
> +                        QLIT_QNUM(43),
>                          QLIT_QDICT(((LiteralQDictEntry[]){
>                                      { "h", QLIT_QSTR("b") },
>                                      { }})),
>                          QLIT_QLIST(((LiteralQObject[]){
>                                      { }})),
> -                        QLIT_QINT(42),
> +                        QLIT_QNUM(42),
>                          { }
>                      })),
>          },
>          {
>              .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
>              .decoded = QLIT_QLIST(((LiteralQObject[]){
> -                        QLIT_QINT(43),
> +                        QLIT_QNUM(43),
>                          QLIT_QDICT(((LiteralQDictEntry[]){
>                                      { "h", QLIT_QSTR("b") },
> -                                    { "a", QLIT_QINT(32) },
> +                                    { "a", QLIT_QNUM(32) },
>                                      { }})),
>                          QLIT_QLIST(((LiteralQObject[]){
>                                      { }})),
> -                        QLIT_QINT(42),
> +                        QLIT_QNUM(42),
>                          { }
>                      })),
>          },
> @@ -1327,11 +1327,11 @@ static void simple_varargs(void)
>      QObject *embedded_obj;
>      QObject *obj;
>      LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
> -            QLIT_QINT(1),
> -            QLIT_QINT(2),
> +            QLIT_QNUM(1),
> +            QLIT_QNUM(2),
>              QLIT_QLIST(((LiteralQObject[]){
> -                        QLIT_QINT(32),
> -                        QLIT_QINT(42),
> +                        QLIT_QNUM(32),
> +                        QLIT_QNUM(42),
>                          {}})),
>              {}}));
>  
> diff --git a/tests/check-qlist.c b/tests/check-qlist.c
> index 4983867c27..a2d1701003 100644
> --- a/tests/check-qlist.c
> +++ b/tests/check-qlist.c
> @@ -11,8 +11,8 @@
>   */
>  #include "qemu/osdep.h"
>  
> -#include "qapi/qmp/qint.h"
> -#include "qapi/qmp/qlist.h"
> +#include "qapi/error.h"
> +#include "qapi/qmp/types.h"

qapi/qmp/types.h is a lazy way to increase compile times by including
more than you need.  One day I'll kill it.  Until then, I tolerate it in
.c, but not in .h.  But I'd stick to just qlist.h and qnum.h here.

>  
>  /*
>   * Public Interface test-cases
> @@ -35,11 +35,11 @@ static void qlist_new_test(void)
>  
>  static void qlist_append_test(void)
>  {
> -    QInt *qi;
> +    QNum *qi;
>      QList *qlist;
>      QListEntry *entry;
>  
> -    qi = qint_from_int(42);
> +    qi = qnum_from_int(42);
>  
>      qlist = qlist_new();
>      qlist_append(qlist, qi);
> @@ -84,13 +84,14 @@ static const int iter_max = 42;
>  
>  static void iter_func(QObject *obj, void *opaque)
>  {
> -    QInt *qi;
> +    QNum *qi;
>  
>      g_assert(opaque == NULL);
>  
> -    qi = qobject_to_qint(obj);
> +    qi = qobject_to_qnum(obj);
>      g_assert(qi != NULL);
> -    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
> +    g_assert((qnum_get_int(qi, &error_abort) >= 0) &&
> +             (qnum_get_int(qi, &error_abort) <= iter_max));
>  
>      iter_called++;
>  }
> diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> new file mode 100644
> index 0000000000..d08d35e85a
> --- /dev/null
> +++ b/tests/check-qnum.c

Let's compare to the old check-qint.c and check-qfloat.c.

> @@ -0,0 +1,131 @@
> +/*
> + * QNum unit-tests.
> + *
> + * Copyright (C) 2009 Red Hat Inc.

Also merge check-qfloat.c's

    * Copyright IBM, Corp. 2009

here, and

> + *
> + * Authors:
> + *  Luiz Capitulino <lcapitulino@redhat.com>

    *  Anthony Liguori   <aliguori@us.ibm.com>

here.

> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + */

Blank line here, please.

> +#include "qemu/osdep.h"
> +
> +#include "qapi/qmp/qnum.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +
> +/*
> + * Public Interface test-cases
> + *
> + * (with some violations to access 'private' data)
> + */

I consider this comment close to useless.

> +
> +static void qnum_from_int_test(void)
> +{
> +    QNum *qi;
> +    const int value = -42;
> +
> +    qi = qnum_from_int(value);
> +    g_assert(qi != NULL);

       g_assert_cmpint(qi->type, ==, QNUM_I64);

> +    g_assert_cmpint(qi->u.i64, ==, value);
> +    g_assert_cmpint(qi->base.refcnt, ==, 1);
> +    g_assert_cmpint(qobject_type(QOBJECT(qi)), ==, QTYPE_QNUM);
> +
> +    // destroy doesn't exit yet
> +    g_free(qi);
> +}
> +
> +static void qnum_from_double_test(void)
> +{
> +    QNum *qf;
> +    const double value = -42.23423;
> +
> +    qf = qnum_from_double(value);
> +    g_assert(qf != NULL);

       g_assert_cmpint(qf->type, ==, QNUM_DOUBLE);

> +    g_assert_cmpfloat(qf->u.dbl, ==, value);
> +    g_assert_cmpint(qf->base.refcnt, ==, 1);
> +    g_assert_cmpint(qobject_type(QOBJECT(qf)), ==, QTYPE_QNUM);
> +
> +    // destroy doesn't exit yet
> +    g_free(qf);
> +}

Let's rename @qi and @qf to @qn.

> +
> +static void qnum_from_int64_test(void)
> +{
> +    QNum *qi;
> +    const int64_t value = 0x1234567890abcdefLL;
> +
> +    qi = qnum_from_int(value);
> +    g_assert_cmpint((int64_t) qi->u.i64, ==, value);
> +
> +    QDECREF(qi);
> +}
> +
> +static void qnum_get_int_test(void)
> +{
> +    QNum *qi;
> +    const int value = 123456;
> +
> +    qi = qnum_from_int(value);
> +    g_assert_cmpint(qnum_get_int(qi, &error_abort), ==, value);
> +
> +    QDECREF(qi);
> +}
> +
> +static void qobject_to_qnum_test(void)
> +{
> +    QNum *qn;
> +
> +    qn = qnum_from_int(0);
> +    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
> +    QDECREF(qn);
> +
> +    qn = qnum_from_double(0);
> +    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
> +    QDECREF(qn);

You added this one.  Makes sense, but announcing in the commit message
that you're also adding test cases wouldn't hurt.

> +}
> +
> +static void qnum_to_string_test(void)
> +{
> +    QNum *qn;
> +    char *tmp;
> +
> +    qn = qnum_from_int(123456);
> +    tmp = qnum_to_string(qn);
> +    g_assert_cmpstr(tmp, ==, "123456");
> +    g_free(tmp);
> +    QDECREF(qn);
> +
> +    qn = qnum_from_double(0.42);
> +    tmp = qnum_to_string(qn);
> +    g_assert_cmpstr(tmp, ==, "0.42");
> +    g_free(tmp);
> +    QDECREF(qn);

Also new.  Good.

Test coverage could use further improvement, but this will do for now.

> +}
> +
> +static void qnum_destroy_test(void)
> +{
> +    QNum *qn;
> +
> +    qn = qnum_from_int(0);
> +    QDECREF(qn);
> +
> +    qn = qnum_from_double(0.42);
> +    QDECREF(qn);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    g_test_init(&argc, &argv, NULL);
> +
> +    g_test_add_func("/qnum/from_int", qnum_from_int_test);
> +    g_test_add_func("/qnum/from_double", qnum_from_double_test);
> +    g_test_add_func("/qnum/destroy", qnum_destroy_test);
> +    g_test_add_func("/qnum/from_int64", qnum_from_int64_test);
> +    g_test_add_func("/qnum/get_int", qnum_get_int_test);
> +    g_test_add_func("/qnum/to_qnum", qobject_to_qnum_test);
> +    g_test_add_func("/qnum/to_string", qnum_to_string_test);
> +
> +    return g_test_run();
> +}
> diff --git a/tests/test-keyval.c b/tests/test-keyval.c
> index df0ff831b5..bec574257e 100644
> --- a/tests/test-keyval.c
> +++ b/tests/test-keyval.c
> @@ -611,7 +611,6 @@ static void test_keyval_visit_optional(void)
>  
>  static void test_keyval_visit_alternate(void)
>  {
> -    Error *err = NULL;
>      Visitor *v;
>      QDict *qdict;
>      AltNumStr *ans;

This belongs to PATCH 03.

> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> index acdded4d67..96a52dbca8 100644
> --- a/tests/test-qmp-commands.c
> +++ b/tests/test-qmp-commands.c
> @@ -162,7 +162,7 @@ static void test_dispatch_cmd_io(void)
>      QDict *ud1b = qdict_new();
>      QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
>      QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
> -    QInt *ret3;
> +    QNum *ret3;
>  
>      qdict_put_int(ud1a, "integer", 42);
>      qdict_put_str(ud1a, "string", "hello");
> @@ -194,8 +194,8 @@ static void test_dispatch_cmd_io(void)
>      qdict_put(req, "arguments", args3);
>      qdict_put_str(req, "execute", "guest-get-time");
>  
> -    ret3 = qobject_to_qint(test_qmp_dispatch(req));
> -    assert(qint_get_int(ret3) == 66);
> +    ret3 = qobject_to_qnum(test_qmp_dispatch(req));
> +    assert(qnum_get_int(ret3, &error_abort) == 66);
>      QDECREF(ret3);
>  
>      QDECREF(req);
> diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
> index 4c0f09601d..e996bebc6e 100644
> --- a/tests/test-qmp-event.c
> +++ b/tests/test-qmp-event.c
> @@ -18,7 +18,6 @@
>  #include "test-qapi-visit.h"
>  #include "test-qapi-event.h"
>  #include "qapi/qmp/types.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qobject.h"
>  #include "qapi/qmp-event.h"
>  
> @@ -62,9 +61,9 @@ void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
>          d->result = (qbool_get_bool(qobject_to_qbool(obj1)) ==
>                       qbool_get_bool(qobject_to_qbool(obj2)));
>          return;
> -    case QTYPE_QINT:
> -        d->result = (qint_get_int(qobject_to_qint(obj1)) ==
> -                     qint_get_int(qobject_to_qint(obj2)));
> +    case QTYPE_QNUM:
> +        d->result = (qnum_get_int(qobject_to_qnum(obj1), &error_abort) ==
> +                     qnum_get_int(qobject_to_qnum(obj2), &error_abort));
>          return;
>      case QTYPE_QSTRING:
>          d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
> diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
> index a30e2d5e95..4484980969 100644
> --- a/tests/test-qobject-input-visitor.c
> +++ b/tests/test-qobject-input-visitor.c
> @@ -152,7 +152,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
>      Visitor *v;
>  
>      /* this will overflow a Qint/int64, so should be deserialized into
> -     * a QFloat/double field instead, leading to an error if we pass it
> +     * a QNum/double field instead, leading to an error if we pass it

s#a Qint/int64#an int64_t#
s#a QNum/double field#a double#

Or perhaps explain using QNUM_I64 and QNUM_DOUBLE.  Your choice.

>       * to visit_type_int. confirm this.
>       */
>      v = visitor_input_test_init(data, "%f", DBL_MAX);
> @@ -428,7 +428,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
>  {
>      QObject *res = NULL;
>      Visitor *v;
> -    QInt *qint;
> +    QNum *qnum;
>      QBool *qbool;
>      QString *qstring;
>      QDict *qdict;
> @@ -436,9 +436,9 @@ static void test_visitor_in_any(TestInputVisitorData *data,
>  
>      v = visitor_input_test_init(data, "-42");
>      visit_type_any(v, NULL, &res, &error_abort);
> -    qint = qobject_to_qint(res);
> -    g_assert(qint);
> -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> +    qnum = qobject_to_qnum(res);
> +    g_assert(qnum);
> +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
>      qobject_decref(res);
>  
>      v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
> @@ -447,9 +447,9 @@ static void test_visitor_in_any(TestInputVisitorData *data,
>      g_assert(qdict && qdict_size(qdict) == 3);
>      qobj = qdict_get(qdict, "integer");
>      g_assert(qobj);
> -    qint = qobject_to_qint(qobj);
> -    g_assert(qint);
> -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> +    qnum = qobject_to_qnum(qobj);
> +    g_assert(qnum);
> +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
>      qobj = qdict_get(qdict, "boolean");
>      g_assert(qobj);
>      qbool = qobject_to_qbool(qobj);
> @@ -527,7 +527,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
>  
>      v = visitor_input_test_init(data, "42");
>      visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
> -    g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
> +    g_assert_cmpint(tmp->type, ==, QTYPE_QNUM);
>      g_assert_cmpint(tmp->u.i, ==, 42);
>      qapi_free_UserDefAlternate(tmp);
>  
> @@ -555,7 +555,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
>  
>      v = visitor_input_test_init(data, "{ 'alt': 42 }");
>      visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
> -    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
> +    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QNUM);
>      g_assert_cmpint(wrap->alt->u.i, ==, 42);
>      qapi_free_WrapAlternate(wrap);
>  
> @@ -596,19 +596,19 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
>  
>      v = visitor_input_test_init(data, "42");
>      visit_type_AltStrNum(v, NULL, &asn, &error_abort);
> -    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
> +    g_assert_cmpint(asn->type, ==, QTYPE_QNUM);
>      g_assert_cmpfloat(asn->u.n, ==, 42);
>      qapi_free_AltStrNum(asn);
>  
>      v = visitor_input_test_init(data, "42");
>      visit_type_AltNumStr(v, NULL, &ans, &error_abort);
> -    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
> +    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
>      g_assert_cmpfloat(ans->u.n, ==, 42);
>      qapi_free_AltNumStr(ans);
>  
>      v = visitor_input_test_init(data, "42");
>      visit_type_AltStrInt(v, NULL, &asi, &error_abort);
> -    g_assert_cmpint(asi->type, ==, QTYPE_QINT);
> +    g_assert_cmpint(asi->type, ==, QTYPE_QNUM);
>      g_assert_cmpint(asi->u.i, ==, 42);
>      qapi_free_AltStrInt(asi);
>  
> @@ -621,13 +621,13 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
>  
>      v = visitor_input_test_init(data, "42.5");
>      visit_type_AltStrNum(v, NULL, &asn, &error_abort);
> -    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
> +    g_assert_cmpint(asn->type, ==, QTYPE_QNUM);
>      g_assert_cmpfloat(asn->u.n, ==, 42.5);
>      qapi_free_AltStrNum(asn);
>  
>      v = visitor_input_test_init(data, "42.5");
>      visit_type_AltNumStr(v, NULL, &ans, &error_abort);
> -    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
> +    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
>      g_assert_cmpfloat(ans->u.n, ==, 42.5);
>      qapi_free_AltNumStr(ans);
>  
> diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
> index 94b9518e40..66a682d5a8 100644
> --- a/tests/test-qobject-output-visitor.c
> +++ b/tests/test-qobject-output-visitor.c
> @@ -58,13 +58,13 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
>                                   const void *unused)
>  {
>      int64_t value = -42;
> -    QInt *qint;
> +    QNum *qnum;
>  
>      visit_type_int(data->ov, NULL, &value, &error_abort);
>  
> -    qint = qobject_to_qint(visitor_get(data));
> -    g_assert(qint);
> -    g_assert_cmpint(qint_get_int(qint), ==, value);
> +    qnum = qobject_to_qnum(visitor_get(data));
> +    g_assert(qnum);
> +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, value);
>  }
>  
>  static void test_visitor_out_bool(TestOutputVisitorData *data,
> @@ -84,13 +84,13 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
>                                      const void *unused)
>  {
>      double value = 3.14;
> -    QFloat *qfloat;
> +    QNum *qnum;
>  
>      visit_type_number(data->ov, NULL, &value, &error_abort);
>  
> -    qfloat = qobject_to_qfloat(visitor_get(data));
> -    g_assert(qfloat);
> -    g_assert(qfloat_get_double(qfloat) == value);
> +    qnum = qobject_to_qnum(visitor_get(data));
> +    g_assert(qnum);
> +    g_assert(qnum_get_double(qnum) == value);
>  }
>  
>  static void test_visitor_out_string(TestOutputVisitorData *data,
> @@ -329,16 +329,16 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
>                                   const void *unused)
>  {
>      QObject *qobj;
> -    QInt *qint;
> +    QNum *qnum;
>      QBool *qbool;
>      QString *qstring;
>      QDict *qdict;
>  
> -    qobj = QOBJECT(qint_from_int(-42));
> +    qobj = QOBJECT(qnum_from_int(-42));
>      visit_type_any(data->ov, NULL, &qobj, &error_abort);
> -    qint = qobject_to_qint(visitor_get(data));
> -    g_assert(qint);
> -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> +    qnum = qobject_to_qnum(visitor_get(data));
> +    g_assert(qnum);
> +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
>      qobject_decref(qobj);
>  
>      visitor_reset(data);
> @@ -351,9 +351,9 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
>      qobject_decref(qobj);
>      qdict = qobject_to_qdict(visitor_get(data));
>      g_assert(qdict);
> -    qint = qobject_to_qint(qdict_get(qdict, "integer"));
> -    g_assert(qint);
> -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> +    qnum = qobject_to_qnum(qdict_get(qdict, "integer"));
> +    g_assert(qnum);
> +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
>      qbool = qobject_to_qbool(qdict_get(qdict, "boolean"));
>      g_assert(qbool);
>      g_assert(qbool_get_bool(qbool) == true);
> @@ -388,18 +388,18 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
>                                         const void *unused)
>  {
>      UserDefAlternate *tmp;
> -    QInt *qint;
> +    QNum *qnum;
>      QString *qstr;
>      QDict *qdict;
>  
>      tmp = g_new0(UserDefAlternate, 1);
> -    tmp->type = QTYPE_QINT;
> +    tmp->type = QTYPE_QNUM;
>      tmp->u.i = 42;
>  
>      visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
> -    qint = qobject_to_qint(visitor_get(data));
> -    g_assert(qint);
> -    g_assert_cmpint(qint_get_int(qint), ==, 42);
> +    qnum = qobject_to_qnum(visitor_get(data));
> +    g_assert(qnum);
> +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, 42);
>  
>      qapi_free_UserDefAlternate(tmp);
>  
> @@ -603,18 +603,18 @@ static void check_native_list(QObject *qobj,
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
> -        /* all integer elements in JSON arrays get stored into QInts when
> +        /* all integer elements in JSON arrays get stored into QNums when

Please use the opportunity to wing the comment at both ends and start
with a capital letter:

           /*
            * All integer ...

>           * we convert to QObjects, so we can check them all in the same
>           * fashion, so simply fall through here
>           */
>      case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
>          for (i = 0; i < 32; i++) {
>              QObject *tmp;
> -            QInt *qvalue;
> +            QNum *qvalue;
>              tmp = qlist_peek(qlist);
>              g_assert(tmp);
> -            qvalue = qobject_to_qint(tmp);
> -            g_assert_cmpint(qint_get_int(qvalue), ==, i);
> +            qvalue = qobject_to_qnum(tmp);
> +            g_assert_cmpint(qnum_get_int(qvalue, &error_abort), ==, i);
>              qobject_decref(qlist_pop(qlist));
>          }
>          break;
> @@ -645,15 +645,15 @@ static void check_native_list(QObject *qobj,
>      case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
>          for (i = 0; i < 32; i++) {
>              QObject *tmp;
> -            QFloat *qvalue;
> +            QNum *qvalue;
>              GString *double_expected = g_string_new("");
>              GString *double_actual = g_string_new("");
>  
>              tmp = qlist_peek(qlist);
>              g_assert(tmp);
> -            qvalue = qobject_to_qfloat(tmp);
> +            qvalue = qobject_to_qnum(tmp);
>              g_string_printf(double_expected, "%.6f", (double)i / 3);
> -            g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue));
> +            g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue));
>              g_assert_cmpstr(double_actual->str, ==, double_expected->str);
>  
>              qobject_decref(qlist_pop(qlist));
> diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
> index 79a2e69a28..60d168fda8 100644
> --- a/tests/test-x86-cpuid-compat.c
> +++ b/tests/test-x86-cpuid-compat.c
> @@ -1,9 +1,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> -#include "qapi/qmp/qlist.h"
> -#include "qapi/qmp/qdict.h"
> -#include "qapi/qmp/qint.h"
> -#include "qapi/qmp/qbool.h"
> +#include "qapi/error.h"
> +#include "qapi/qmp/types.h"

Previous note on qapi/qmp/types.h applies.

>  #include "libqtest.h"
>  
>  static char *get_cpu0_qom_path(void)
> @@ -56,12 +54,13 @@ static void test_cpuid_prop(const void *data)
>  {
>      const CpuidTestArgs *args = data;
>      char *path;
> -    QInt *value;
> +    QNum *value;
>  
>      qtest_start(args->cmdline);
>      path = get_cpu0_qom_path();
> -    value = qobject_to_qint(qom_get(path, args->property));
> -    g_assert_cmpint(qint_get_int(value), ==, args->expected_value);
> +    value = qobject_to_qnum(qom_get(path, args->property));
> +    g_assert_cmpint(qnum_get_int(value, &error_abort), ==,
> +                    args->expected_value);
>      qtest_end();
>  
>      QDECREF(value);
> diff --git a/ui/spice-core.c b/ui/spice-core.c
> index 804abc5c0f..561d0649cf 100644
> --- a/ui/spice-core.c
> +++ b/ui/spice-core.c
> @@ -30,7 +30,6 @@
>  #include "qemu-x509.h"
>  #include "qemu/sockets.h"
>  #include "qmp-commands.h"
> -#include "qapi/qmp/qint.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qmp/qjson.h"
> diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
> index 1e53b1cf84..89ab12c0d8 100644
> --- a/ui/vnc-enc-tight.c
> +++ b/ui/vnc-enc-tight.c
> @@ -44,7 +44,6 @@
>  #endif
>  
>  #include "qemu/bswap.h"
> -#include "qapi/qmp/qint.h"
>  #include "vnc.h"
>  #include "vnc-enc-tight.h"
>  #include "vnc-palette.h"
> diff --git a/util/qemu-option.c b/util/qemu-option.c
> index 5977bfc3e9..39b1e06225 100644
> --- a/util/qemu-option.c
> +++ b/util/qemu-option.c
> @@ -941,9 +941,8 @@ typedef struct OptsFromQDictState {
>  static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
>  {
>      OptsFromQDictState *state = opaque;
> -    char buf[32];
> +    char buf[32], *tmp = NULL;
>      const char *value;
> -    int n;
>  
>      if (!strcmp(key, "id") || *state->errp) {
>          return;
> @@ -953,17 +952,9 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
>      case QTYPE_QSTRING:
>          value = qstring_get_str(qobject_to_qstring(obj));
>          break;
> -    case QTYPE_QINT:
> -        n = snprintf(buf, sizeof(buf), "%" PRId64,
> -                     qint_get_int(qobject_to_qint(obj)));
> -        assert(n < sizeof(buf));
> -        value = buf;
> -        break;
> -    case QTYPE_QFLOAT:
> -        n = snprintf(buf, sizeof(buf), "%.17g",
> -                     qfloat_get_double(qobject_to_qfloat(obj)));
> -        assert(n < sizeof(buf));
> -        value = buf;
> +    case QTYPE_QNUM:
> +        tmp = qnum_to_string(qobject_to_qnum(obj));
> +        value = tmp;
>          break;
>      case QTYPE_QBOOL:
>          pstrcpy(buf, sizeof(buf),
> @@ -975,12 +966,13 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
>      }
>  
>      qemu_opt_set(state->opts, key, value, state->errp);
> +    g_free(tmp);
>  }
>  
>  /*
>   * Create QemuOpts from a QDict.
>   * Use value of key "id" as ID if it exists and is a QString.
> - * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
> + * Only QStrings, QNums and QBools are copied.  Entries with
>   * other types are silently ignored.
>   */

Refill the sentence, please.

>  QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 66c9734311..421fb585ae 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1395,8 +1395,7 @@ F: include/qapi/qmp/
>  X: include/qapi/qmp/dispatch.h
>  F: scripts/coccinelle/qobject.cocci
>  F: tests/check-qdict.c
> -F: tests/check-qfloat.c
> -F: tests/check-qint.c
> +F: tests/check-qnum.c
>  F: tests/check-qjson.c
>  F: tests/check-qlist.c
>  F: tests/check-qstring.c
> diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs
> index bed55084bb..fc8885c9a4 100644
> --- a/qobject/Makefile.objs
> +++ b/qobject/Makefile.objs
> @@ -1,2 +1,2 @@
> -util-obj-y = qnull.o qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
> +util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o
>  util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
> diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.cocci
> index 97703a438b..c3253deb1b 100644
> --- a/scripts/coccinelle/qobject.cocci
> +++ b/scripts/coccinelle/qobject.cocci
> @@ -6,7 +6,7 @@ expression Obj, Key, E;
>  - qdict_put_obj(Obj, Key, QOBJECT(E));
>  + qdict_put(Obj, Key, E);
>  |
> -- qdict_put(Obj, Key, qint_from_int(E));
> +- qdict_put(Obj, Key, qnum_from_int(E));
>  + qdict_put_int(Obj, Key, E);
>  |
>  - qdict_put(Obj, Key, qbool_from_bool(E));
> @@ -24,7 +24,7 @@ expression Obj, E;
>  - qlist_append_obj(Obj, QOBJECT(E));
>  + qlist_append(Obj, E);
>  |
> -- qlist_append(Obj, qint_from_int(E));
> +- qlist_append(Obj, qnum_from_int(E));
>  + qlist_append_int(Obj, E);
>  |
>  - qlist_append(Obj, qbool_from_bool(E));
> diff --git a/tests/.gitignore b/tests/.gitignore
> index a966740c2c..847f4f1474 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -1,7 +1,6 @@
>  atomic_add-bench
>  check-qdict
> -check-qfloat
> -check-qint
> +check-qnum
>  check-qjson
>  check-qlist
>  check-qnull
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 31931c0d77..ac0387d88a 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -10,10 +10,8 @@ check-unit-y = tests/check-qdict$(EXESUF)
>  gcov-files-check-qdict-y = qobject/qdict.c
>  check-unit-y += tests/test-char$(EXESUF)
>  gcov-files-check-qdict-y = chardev/char.c
> -check-unit-y += tests/check-qfloat$(EXESUF)
> -gcov-files-check-qfloat-y = qobject/qfloat.c
> -check-unit-y += tests/check-qint$(EXESUF)
> -gcov-files-check-qint-y = qobject/qint.c
> +check-unit-y += tests/check-qnum$(EXESUF)
> +gcov-files-check-qnum-y = qobject/qnum.c
>  check-unit-y += tests/check-qstring$(EXESUF)
>  gcov-files-check-qstring-y = qobject/qstring.c
>  check-unit-y += tests/check-qlist$(EXESUF)
> @@ -500,8 +498,8 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
>  	tests/test-qmp-commands.h tests/test-qapi-event.h \
>  	tests/test-qmp-introspect.h
>  
> -test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
> -	tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
> +test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
> +	tests/check-qlist.o tests/check-qnull.o \
>  	tests/check-qjson.o \
>  	tests/test-coroutine.o tests/test-string-output-visitor.o \
>  	tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
> @@ -529,11 +527,10 @@ test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
>  test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
>  test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
>  
> -tests/check-qint$(EXESUF): tests/check-qint.o $(test-util-obj-y)
> +tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y)
>  tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y)
>  tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
>  tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
> -tests/check-qfloat$(EXESUF): tests/check-qfloat.o $(test-util-obj-y)
>  tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
>  tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
>  tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
> diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
> index 5d7c13cad1..17e652535c 100644
> --- a/tests/qapi-schema/comments.out
> +++ b/tests/qapi-schema/comments.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
>  object q_empty
> diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> index 70c1252408..63ca25a8b9 100644
> --- a/tests/qapi-schema/doc-good.out
> +++ b/tests/qapi-schema/doc-good.out
> @@ -6,7 +6,7 @@ object Object
>      tag base1
>      case one: Variant1
>      case two: Variant2
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  object SugaredUnion
>      member type: SugaredUnionKind optional=False
> diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
> index 8a5b034424..40b886ddae 100644
> --- a/tests/qapi-schema/empty.out
> +++ b/tests/qapi-schema/empty.out
> @@ -1,3 +1,3 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  object q_empty
> diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
> index 5a0f2bf805..313c0fe7be 100644
> --- a/tests/qapi-schema/event-case.out
> +++ b/tests/qapi-schema/event-case.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  event oops None
>     boxed=False
> diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
> index 1d2722c02e..b5637cb2e0 100644
> --- a/tests/qapi-schema/ident-with-escape.out
> +++ b/tests/qapi-schema/ident-with-escape.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  command fooA q_obj_fooA-arg -> None
>     gen=True success_response=True boxed=False
> diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
> index 5d7c13cad1..17e652535c 100644
> --- a/tests/qapi-schema/include-relpath.out
> +++ b/tests/qapi-schema/include-relpath.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
>  object q_empty
> diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
> index 5d7c13cad1..17e652535c 100644
> --- a/tests/qapi-schema/include-repetition.out
> +++ b/tests/qapi-schema/include-repetition.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
>  object q_empty
> diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
> index 5d7c13cad1..17e652535c 100644
> --- a/tests/qapi-schema/include-simple.out
> +++ b/tests/qapi-schema/include-simple.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
>  object q_empty
> diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
> index e8171c935f..586795f44d 100644
> --- a/tests/qapi-schema/indented-expr.out
> +++ b/tests/qapi-schema/indented-expr.out
> @@ -1,4 +1,4 @@
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  command eins None -> None
>     gen=True success_response=True boxed=False
> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
> index 5c6655a5c3..7812a6c69b 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -46,7 +46,7 @@ object NestedEnumsOne
>      member enum4: EnumOne optional=True
>  enum QEnumTwo ['value1', 'value2']
>      prefix QENUM_TWO
> -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  object TestStruct
>      member integer: int optional=False

I still like it :)

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-12  6:30   ` Markus Armbruster
@ 2017-05-12 13:00     ` Luiz Capitulino
  2017-05-15  7:00       ` Markus Armbruster
  0 siblings, 1 reply; 70+ messages in thread
From: Luiz Capitulino @ 2017-05-12 13:00 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Marc-André Lureau, qemu-devel

On Fri, 12 May 2017 08:30:36 +0200
Markus Armbruster <armbru@redhat.com> wrote:

> Question for Luiz...
> 
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> [...]
> > diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> > new file mode 100644
> > index 0000000000..d08d35e85a
> > --- /dev/null
> > +++ b/tests/check-qnum.c
> > @@ -0,0 +1,131 @@
> > +/*
> > + * QNum unit-tests.
> > + *
> > + * Copyright (C) 2009 Red Hat Inc.
> > + *
> > + * Authors:
> > + *  Luiz Capitulino <lcapitulino@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + */
> > +#include "qemu/osdep.h"
> > +
> > +#include "qapi/qmp/qnum.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +
> > +/*
> > + * Public Interface test-cases
> > + *
> > + * (with some violations to access 'private' data)
> > + */
> > +
> > +static void qnum_from_int_test(void)
> > +{
> > +    QNum *qi;
> > +    const int value = -42;
> > +
> > +    qi = qnum_from_int(value);
> > +    g_assert(qi != NULL);
> > +    g_assert_cmpint(qi->u.i64, ==, value);
> > +    g_assert_cmpint(qi->base.refcnt, ==, 1);
> > +    g_assert_cmpint(qobject_type(QOBJECT(qi)), ==, QTYPE_QNUM);
> > +
> > +    // destroy doesn't exit yet
> > +    g_free(qi);
> > +}  
> 
> The comment is enigmatic. 

It was meant for future generations to figure it out :)

> It was first written in commit 33837ba
> "Introduce QInt unit-tests", and got copied around since.  In
> check-qlist.c, it's spelled "exist yet".

Yes, "exit" is a typo it should be "exist".

> What is "destroy", why doesn't it exit / exist now, but will exit /
> exist later?  It can't be qnum_destroy_obj(), because that certainly
> exists already, exits already in the sense of returning, and shouldn't
> ever exit in the sense of terminating the program.
> 
> The comment applies to a g_free().  Why do we free directly instead
> decrementing the reference count?  Perhaps the comment tries to explain
> that (if it does, it fails).

In my personal style of writing unit-tests, I never use a method
in a test before testing it. So, as QDECREF() wasn't tested yet,
I wasn't allowed to use it.

While I keep this principle when writing unit-tests today, this
particular case is very extreme and not useful at all. Today I'd just
go ahead and use QDECREF(). The qint_destroy_test() in the original
commit is also very bogus, it's not really doing an useful test.

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-12  7:37   ` Markus Armbruster
@ 2017-05-12 13:03     ` Luiz Capitulino
  2017-05-15  6:35       ` Markus Armbruster
  0 siblings, 1 reply; 70+ messages in thread
From: Luiz Capitulino @ 2017-05-12 13:03 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Marc-André Lureau, qemu-devel

On Fri, 12 May 2017 09:37:50 +0200
Markus Armbruster <armbru@redhat.com> wrote:

> Luiz, there's a lone question for you further down.  Search for your
> name.

I could not a question, can you paste it here?

> 
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > We would like to use a same QObject type to represent numbers, whether
> > they are int, uint, or floats. getters will allow some compatibility
> > between the various types if the number fits other representations
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>  
> [Snip part I already reviewed...]
> > diff --git a/tests/check-qdict.c b/tests/check-qdict.c
> > index be8d81f07b..bcd06a7d6b 100644
> > --- a/tests/check-qdict.c
> > +++ b/tests/check-qdict.c
> > @@ -11,7 +11,6 @@
> >   */
> >  #include "qemu/osdep.h"
> >  
> > -#include "qapi/qmp/qint.h"
> >  #include "qapi/qmp/qdict.h"
> >  #include "qapi/qmp/qstring.h"
> >  #include "qapi/error.h"
> > @@ -39,7 +38,7 @@ static void qdict_new_test(void)
> >  
> >  static void qdict_put_obj_test(void)
> >  {
> > -    QInt *qi;
> > +    QNum *qi;
> >      QDict *qdict;
> >      QDictEntry *ent;
> >      const int num = 42;
> > @@ -51,8 +50,8 @@ static void qdict_put_obj_test(void)
> >  
> >      g_assert(qdict_size(qdict) == 1);
> >      ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
> > -    qi = qobject_to_qint(ent->value);
> > -    g_assert(qint_get_int(qi) == num);
> > +    qi = qobject_to_qnum(ent->value);
> > +    g_assert(qnum_get_int(qi, &error_abort) == num);
> >  
> >      // destroy doesn't exit yet
> >      QDECREF(qi);  
> 
> Since you're touching three out of four lines containing @qi anyway:
> rename it to @qn?  You rename like that in some places, but not all.
> 
> > @@ -74,7 +73,7 @@ static void qdict_destroy_simple_test(void)
> >  
> >  static void qdict_get_test(void)
> >  {
> > -    QInt *qi;
> > +    QNum *qi;
> >      QObject *obj;
> >      const int value = -42;
> >      const char *key = "test";
> > @@ -85,8 +84,8 @@ static void qdict_get_test(void)
> >      obj = qdict_get(tests_dict, key);
> >      g_assert(obj != NULL);
> >  
> > -    qi = qobject_to_qint(obj);
> > -    g_assert(qint_get_int(qi) == value);
> > +    qi = qobject_to_qnum(obj);
> > +    g_assert(qnum_get_int(qi, &error_abort) == value);
> >  
> >      QDECREF(tests_dict);
> >  }
> > @@ -329,7 +328,7 @@ static void qdict_array_split_test(void)
> >  {
> >      QDict *test_dict = qdict_new();
> >      QDict *dict1, *dict2;
> > -    QInt *int1;
> > +    QNum *int1;
> >      QList *test_list;
> >  
> >      /*
> > @@ -380,7 +379,7 @@ static void qdict_array_split_test(void)
> >  
> >      dict1 = qobject_to_qdict(qlist_pop(test_list));
> >      dict2 = qobject_to_qdict(qlist_pop(test_list));
> > -    int1 = qobject_to_qint(qlist_pop(test_list));
> > +    int1 = qobject_to_qnum(qlist_pop(test_list));
> >  
> >      g_assert(dict1);
> >      g_assert(dict2);
> > @@ -402,7 +401,7 @@ static void qdict_array_split_test(void)
> >  
> >      QDECREF(dict2);
> >  
> > -    g_assert(qint_get_int(int1) == 66);
> > +    g_assert(qnum_get_int(int1, &error_abort) == 66);
> >  
> >      QDECREF(int1);
> >  
> > @@ -447,14 +446,14 @@ static void qdict_array_split_test(void)
> >  
> >      qdict_array_split(test_dict, &test_list);
> >  
> > -    int1 = qobject_to_qint(qlist_pop(test_list));
> > +    int1 = qobject_to_qnum(qlist_pop(test_list));
> >  
> >      g_assert(int1);
> >      g_assert(qlist_empty(test_list));
> >  
> >      QDECREF(test_list);
> >  
> > -    g_assert(qint_get_int(int1) == 42);
> > +    g_assert(qnum_get_int(int1, &error_abort) == 42);
> >  
> >      QDECREF(int1);
> >  
> > diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c
> > deleted file mode 100644
> > index 1da2cdae08..0000000000
> > --- a/tests/check-qfloat.c
> > +++ /dev/null
> > @@ -1,53 +0,0 @@
> > -/*
> > - * QFloat unit-tests.
> > - *
> > - * Copyright IBM, Corp. 2009
> > - *
> > - * Authors:
> > - *  Anthony Liguori   <aliguori@us.ibm.com>
> > - *
> > - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> > - * See the COPYING.LIB file in the top-level directory.
> > - *
> > - */
> > -#include "qemu/osdep.h"
> > -
> > -#include "qapi/qmp/qfloat.h"
> > -#include "qemu-common.h"
> > -
> > -/*
> > - * Public Interface test-cases
> > - *
> > - * (with some violations to access 'private' data)
> > - */
> > -
> > -static void qfloat_from_double_test(void)
> > -{
> > -    QFloat *qf;
> > -    const double value = -42.23423;
> > -
> > -    qf = qfloat_from_double(value);
> > -    g_assert(qf != NULL);
> > -    g_assert(qf->value == value);
> > -    g_assert(qf->base.refcnt == 1);
> > -    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
> > -
> > -    // destroy doesn't exit yet
> > -    g_free(qf);
> > -}
> > -
> > -static void qfloat_destroy_test(void)
> > -{
> > -    QFloat *qf = qfloat_from_double(0.0);
> > -    QDECREF(qf);
> > -}
> > -
> > -int main(int argc, char **argv)
> > -{
> > -    g_test_init(&argc, &argv, NULL);
> > -
> > -    g_test_add_func("/public/from_double", qfloat_from_double_test);
> > -    g_test_add_func("/public/destroy", qfloat_destroy_test);
> > -
> > -    return g_test_run();
> > -}
> > diff --git a/tests/check-qint.c b/tests/check-qint.c
> > deleted file mode 100644
> > index b6e4555115..0000000000
> > --- a/tests/check-qint.c
> > +++ /dev/null
> > @@ -1,87 +0,0 @@
> > -/*
> > - * QInt unit-tests.
> > - *
> > - * Copyright (C) 2009 Red Hat Inc.
> > - *
> > - * Authors:
> > - *  Luiz Capitulino <lcapitulino@redhat.com>
> > - *
> > - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> > - * See the COPYING.LIB file in the top-level directory.
> > - */
> > -#include "qemu/osdep.h"
> > -
> > -#include "qapi/qmp/qint.h"
> > -#include "qemu-common.h"
> > -
> > -/*
> > - * Public Interface test-cases
> > - *
> > - * (with some violations to access 'private' data)
> > - */
> > -
> > -static void qint_from_int_test(void)
> > -{
> > -    QInt *qi;
> > -    const int value = -42;
> > -
> > -    qi = qint_from_int(value);
> > -    g_assert(qi != NULL);
> > -    g_assert(qi->value == value);
> > -    g_assert(qi->base.refcnt == 1);
> > -    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
> > -
> > -    // destroy doesn't exit yet
> > -    g_free(qi);
> > -}
> > -
> > -static void qint_destroy_test(void)
> > -{
> > -    QInt *qi = qint_from_int(0);
> > -    QDECREF(qi);
> > -}
> > -
> > -static void qint_from_int64_test(void)
> > -{
> > -    QInt *qi;
> > -    const int64_t value = 0x1234567890abcdefLL;
> > -
> > -    qi = qint_from_int(value);
> > -    g_assert((int64_t) qi->value == value);
> > -
> > -    QDECREF(qi);
> > -}
> > -
> > -static void qint_get_int_test(void)
> > -{
> > -    QInt *qi;
> > -    const int value = 123456;
> > -
> > -    qi = qint_from_int(value);
> > -    g_assert(qint_get_int(qi) == value);
> > -
> > -    QDECREF(qi);
> > -}
> > -
> > -static void qobject_to_qint_test(void)
> > -{
> > -    QInt *qi;
> > -
> > -    qi = qint_from_int(0);
> > -    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
> > -
> > -    QDECREF(qi);
> > -}
> > -
> > -int main(int argc, char **argv)
> > -{
> > -    g_test_init(&argc, &argv, NULL);
> > -
> > -    g_test_add_func("/public/from_int", qint_from_int_test);
> > -    g_test_add_func("/public/destroy", qint_destroy_test);
> > -    g_test_add_func("/public/from_int64", qint_from_int64_test);
> > -    g_test_add_func("/public/get_int", qint_get_int_test);
> > -    g_test_add_func("/public/to_qint", qobject_to_qint_test);
> > -
> > -    return g_test_run();
> > -}
> > diff --git a/tests/check-qjson.c b/tests/check-qjson.c
> > index 963dd46f07..c432aebf13 100644
> > --- a/tests/check-qjson.c
> > +++ b/tests/check-qjson.c
> > @@ -886,21 +886,21 @@ static void simple_number(void)
> >      };
> >  
> >      for (i = 0; test_cases[i].encoded; i++) {
> > -        QInt *qint;
> > +        QNum *qnum;
> >  
> > -        qint = qobject_to_qint(qobject_from_json(test_cases[i].encoded,
> > +        qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
> >                                                   &error_abort));
> > -        g_assert(qint);
> > -        g_assert(qint_get_int(qint) == test_cases[i].decoded);
> > +        g_assert(qnum);
> > +        g_assert(qnum_get_int(qnum, &error_abort) == test_cases[i].decoded);
> >          if (test_cases[i].skip == 0) {
> >              QString *str;
> >  
> > -            str = qobject_to_json(QOBJECT(qint));
> > +            str = qobject_to_json(QOBJECT(qnum));
> >              g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
> >              QDECREF(str);
> >          }
> >  
> > -        QDECREF(qint);
> > +        QDECREF(qnum);
> >      }
> >  }
> >  
> > @@ -921,12 +921,12 @@ static void float_number(void)
> >  
> >      for (i = 0; test_cases[i].encoded; i++) {
> >          QObject *obj;
> > -        QFloat *qfloat;
> > +        QNum *qnum;
> >  
> >          obj = qobject_from_json(test_cases[i].encoded, &error_abort);
> > -        qfloat = qobject_to_qfloat(obj);
> > -        g_assert(qfloat);
> > -        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
> > +        qnum = qobject_to_qnum(obj);
> > +        g_assert(qnum);
> > +        g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
> >  
> >          if (test_cases[i].skip == 0) {
> >              QString *str;
> > @@ -936,29 +936,28 @@ static void float_number(void)
> >              QDECREF(str);
> >          }
> >  
> > -        QDECREF(qfloat);
> > +        QDECREF(qnum);
> >      }
> >  }
> >  
> >  static void vararg_number(void)
> >  {
> > -    QInt *qint;
> > -    QFloat *qfloat;
> > +    QNum *qnum;
> >      int value = 0x2342;
> >      long long value_ll = 0x2342342343LL;
> >      double valuef = 2.323423423;
> >  
> > -    qint = qobject_to_qint(qobject_from_jsonf("%d", value));
> > -    g_assert(qint_get_int(qint) == value);
> > -    QDECREF(qint);
> > +    qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
> > +    g_assert(qnum_get_int(qnum, &error_abort) == value);
> > +    QDECREF(qnum);
> >  
> > -    qint = qobject_to_qint(qobject_from_jsonf("%lld", value_ll));
> > -    g_assert(qint_get_int(qint) == value_ll);
> > -    QDECREF(qint);
> > +    qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
> > +    g_assert(qnum_get_int(qnum, &error_abort) == value_ll);
> > +    QDECREF(qnum);
> >  
> > -    qfloat = qobject_to_qfloat(qobject_from_jsonf("%f", valuef));
> > -    g_assert(qfloat_get_double(qfloat) == valuef);
> > -    QDECREF(qfloat);
> > +    qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
> > +    g_assert(qnum_get_double(qnum) == valuef);
> > +    QDECREF(qnum);
> >  }
> >  
> >  static void keyword_literal(void)  
> 
> By now we see the pattern.  It's a mechanical transformation
> 
>     - qobject_to_qint(E)
>     + qobject_to_qnum(E)
> 
>     - qint_get_int(E)
>     + qnum_get_int(E, &error_abort)
> 
>     - qobject_to_qfloat(E)
>     + qobject_to_qnum(E)
> 
>     - qfloat_get_double(E)
>     + qnum_get_double(E)
> 
> plus replacement / merge of QInt / QFloat variables.  Did you do it
> entirely by hand or with help from Coccinelle?
> 
> A helper function qnum_get_int_nofail(E) would result in slightly more
> compact source code (object code probably, too), but I'm not sure it's
> worth it.
> 
> Other patterns that might justify helpers:
> 
>     qnum_get_double(qobject_to_qnum(OBJ))
>     qnum_get_int(qobject_to_qnum(OBJ), ERR)
>     qnum_get_int(qobject_to_qnum(OBJ), &error_abort)
> 
> These are ideas, not demands.
> 
> > @@ -1019,7 +1018,7 @@ struct LiteralQObject
> >  {
> >      int type;
> >      union {
> > -        int64_t qint;
> > +        int64_t qnum;
> >          const char *qstr;
> >          LiteralQDictEntry *qdict;
> >          LiteralQObject *qlist;
> > @@ -1032,7 +1031,7 @@ struct LiteralQDictEntry
> >      LiteralQObject value;
> >  };
> >  
> > -#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
> > +#define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
> >  #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
> >  #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
> >  #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}  
> 
> Aside: yet another private way to compare actual QObjects to expected
> ones.  We should pick *one* way to compare, and stick to it.
> 
> > @@ -1069,8 +1068,9 @@ static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
> >      }
> >  
> >      switch (lhs->type) {
> > -    case QTYPE_QINT:
> > -        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
> > +    case QTYPE_QNUM:
> > +        return lhs->value.qnum == qnum_get_int(qobject_to_qnum(rhs),
> > +                                               &error_abort);
> >      case QTYPE_QSTRING:
> >          return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
> >      case QTYPE_QDICT: {
> > @@ -1114,7 +1114,7 @@ static void simple_dict(void)
> >          {
> >              .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
> >              .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
> > -                        { "foo", QLIT_QINT(42) },
> > +                        { "foo", QLIT_QNUM(42) },
> >                          { "bar", QLIT_QSTR("hello world") },
> >                          { }
> >                      })),
> > @@ -1126,7 +1126,7 @@ static void simple_dict(void)
> >          }, {
> >              .encoded = "{\"foo\": 43}",
> >              .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
> > -                        { "foo", QLIT_QINT(43) },
> > +                        { "foo", QLIT_QNUM(43) },
> >                          { }
> >                      })),
> >          },
> > @@ -1212,15 +1212,15 @@ static void simple_list(void)
> >          {
> >              .encoded = "[43,42]",
> >              .decoded = QLIT_QLIST(((LiteralQObject[]){
> > -                        QLIT_QINT(43),
> > -                        QLIT_QINT(42),
> > +                        QLIT_QNUM(43),
> > +                        QLIT_QNUM(42),
> >                          { }
> >                      })),
> >          },
> >          {
> >              .encoded = "[43]",
> >              .decoded = QLIT_QLIST(((LiteralQObject[]){
> > -                        QLIT_QINT(43),
> > +                        QLIT_QNUM(43),
> >                          { }
> >                      })),
> >          },
> > @@ -1269,35 +1269,35 @@ static void simple_whitespace(void)
> >          {
> >              .encoded = " [ 43 , 42 ]",
> >              .decoded = QLIT_QLIST(((LiteralQObject[]){
> > -                        QLIT_QINT(43),
> > -                        QLIT_QINT(42),
> > +                        QLIT_QNUM(43),
> > +                        QLIT_QNUM(42),
> >                          { }
> >                      })),
> >          },
> >          {
> >              .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
> >              .decoded = QLIT_QLIST(((LiteralQObject[]){
> > -                        QLIT_QINT(43),
> > +                        QLIT_QNUM(43),
> >                          QLIT_QDICT(((LiteralQDictEntry[]){
> >                                      { "h", QLIT_QSTR("b") },
> >                                      { }})),
> >                          QLIT_QLIST(((LiteralQObject[]){
> >                                      { }})),
> > -                        QLIT_QINT(42),
> > +                        QLIT_QNUM(42),
> >                          { }
> >                      })),
> >          },
> >          {
> >              .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
> >              .decoded = QLIT_QLIST(((LiteralQObject[]){
> > -                        QLIT_QINT(43),
> > +                        QLIT_QNUM(43),
> >                          QLIT_QDICT(((LiteralQDictEntry[]){
> >                                      { "h", QLIT_QSTR("b") },
> > -                                    { "a", QLIT_QINT(32) },
> > +                                    { "a", QLIT_QNUM(32) },
> >                                      { }})),
> >                          QLIT_QLIST(((LiteralQObject[]){
> >                                      { }})),
> > -                        QLIT_QINT(42),
> > +                        QLIT_QNUM(42),
> >                          { }
> >                      })),
> >          },
> > @@ -1327,11 +1327,11 @@ static void simple_varargs(void)
> >      QObject *embedded_obj;
> >      QObject *obj;
> >      LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
> > -            QLIT_QINT(1),
> > -            QLIT_QINT(2),
> > +            QLIT_QNUM(1),
> > +            QLIT_QNUM(2),
> >              QLIT_QLIST(((LiteralQObject[]){
> > -                        QLIT_QINT(32),
> > -                        QLIT_QINT(42),
> > +                        QLIT_QNUM(32),
> > +                        QLIT_QNUM(42),
> >                          {}})),
> >              {}}));
> >  
> > diff --git a/tests/check-qlist.c b/tests/check-qlist.c
> > index 4983867c27..a2d1701003 100644
> > --- a/tests/check-qlist.c
> > +++ b/tests/check-qlist.c
> > @@ -11,8 +11,8 @@
> >   */
> >  #include "qemu/osdep.h"
> >  
> > -#include "qapi/qmp/qint.h"
> > -#include "qapi/qmp/qlist.h"
> > +#include "qapi/error.h"
> > +#include "qapi/qmp/types.h"  
> 
> qapi/qmp/types.h is a lazy way to increase compile times by including
> more than you need.  One day I'll kill it.  Until then, I tolerate it in
> .c, but not in .h.  But I'd stick to just qlist.h and qnum.h here.
> 
> >  
> >  /*
> >   * Public Interface test-cases
> > @@ -35,11 +35,11 @@ static void qlist_new_test(void)
> >  
> >  static void qlist_append_test(void)
> >  {
> > -    QInt *qi;
> > +    QNum *qi;
> >      QList *qlist;
> >      QListEntry *entry;
> >  
> > -    qi = qint_from_int(42);
> > +    qi = qnum_from_int(42);
> >  
> >      qlist = qlist_new();
> >      qlist_append(qlist, qi);
> > @@ -84,13 +84,14 @@ static const int iter_max = 42;
> >  
> >  static void iter_func(QObject *obj, void *opaque)
> >  {
> > -    QInt *qi;
> > +    QNum *qi;
> >  
> >      g_assert(opaque == NULL);
> >  
> > -    qi = qobject_to_qint(obj);
> > +    qi = qobject_to_qnum(obj);
> >      g_assert(qi != NULL);
> > -    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
> > +    g_assert((qnum_get_int(qi, &error_abort) >= 0) &&
> > +             (qnum_get_int(qi, &error_abort) <= iter_max));
> >  
> >      iter_called++;
> >  }
> > diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> > new file mode 100644
> > index 0000000000..d08d35e85a
> > --- /dev/null
> > +++ b/tests/check-qnum.c  
> 
> Let's compare to the old check-qint.c and check-qfloat.c.
> 
> > @@ -0,0 +1,131 @@
> > +/*
> > + * QNum unit-tests.
> > + *
> > + * Copyright (C) 2009 Red Hat Inc.  
> 
> Also merge check-qfloat.c's
> 
>     * Copyright IBM, Corp. 2009
> 
> here, and
> 
> > + *
> > + * Authors:
> > + *  Luiz Capitulino <lcapitulino@redhat.com>  
> 
>     *  Anthony Liguori   <aliguori@us.ibm.com>
> 
> here.
> 
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + */  
> 
> Blank line here, please.
> 
> > +#include "qemu/osdep.h"
> > +
> > +#include "qapi/qmp/qnum.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +
> > +/*
> > + * Public Interface test-cases
> > + *
> > + * (with some violations to access 'private' data)
> > + */  
> 
> I consider this comment close to useless.
> 
> > +
> > +static void qnum_from_int_test(void)
> > +{
> > +    QNum *qi;
> > +    const int value = -42;
> > +
> > +    qi = qnum_from_int(value);
> > +    g_assert(qi != NULL);  
> 
>        g_assert_cmpint(qi->type, ==, QNUM_I64);
> 
> > +    g_assert_cmpint(qi->u.i64, ==, value);
> > +    g_assert_cmpint(qi->base.refcnt, ==, 1);
> > +    g_assert_cmpint(qobject_type(QOBJECT(qi)), ==, QTYPE_QNUM);
> > +
> > +    // destroy doesn't exit yet
> > +    g_free(qi);
> > +}
> > +
> > +static void qnum_from_double_test(void)
> > +{
> > +    QNum *qf;
> > +    const double value = -42.23423;
> > +
> > +    qf = qnum_from_double(value);
> > +    g_assert(qf != NULL);  
> 
>        g_assert_cmpint(qf->type, ==, QNUM_DOUBLE);
> 
> > +    g_assert_cmpfloat(qf->u.dbl, ==, value);
> > +    g_assert_cmpint(qf->base.refcnt, ==, 1);
> > +    g_assert_cmpint(qobject_type(QOBJECT(qf)), ==, QTYPE_QNUM);
> > +
> > +    // destroy doesn't exit yet
> > +    g_free(qf);
> > +}  
> 
> Let's rename @qi and @qf to @qn.
> 
> > +
> > +static void qnum_from_int64_test(void)
> > +{
> > +    QNum *qi;
> > +    const int64_t value = 0x1234567890abcdefLL;
> > +
> > +    qi = qnum_from_int(value);
> > +    g_assert_cmpint((int64_t) qi->u.i64, ==, value);
> > +
> > +    QDECREF(qi);
> > +}
> > +
> > +static void qnum_get_int_test(void)
> > +{
> > +    QNum *qi;
> > +    const int value = 123456;
> > +
> > +    qi = qnum_from_int(value);
> > +    g_assert_cmpint(qnum_get_int(qi, &error_abort), ==, value);
> > +
> > +    QDECREF(qi);
> > +}
> > +
> > +static void qobject_to_qnum_test(void)
> > +{
> > +    QNum *qn;
> > +
> > +    qn = qnum_from_int(0);
> > +    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
> > +    QDECREF(qn);
> > +
> > +    qn = qnum_from_double(0);
> > +    g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
> > +    QDECREF(qn);  
> 
> You added this one.  Makes sense, but announcing in the commit message
> that you're also adding test cases wouldn't hurt.
> 
> > +}
> > +
> > +static void qnum_to_string_test(void)
> > +{
> > +    QNum *qn;
> > +    char *tmp;
> > +
> > +    qn = qnum_from_int(123456);
> > +    tmp = qnum_to_string(qn);
> > +    g_assert_cmpstr(tmp, ==, "123456");
> > +    g_free(tmp);
> > +    QDECREF(qn);
> > +
> > +    qn = qnum_from_double(0.42);
> > +    tmp = qnum_to_string(qn);
> > +    g_assert_cmpstr(tmp, ==, "0.42");
> > +    g_free(tmp);
> > +    QDECREF(qn);  
> 
> Also new.  Good.
> 
> Test coverage could use further improvement, but this will do for now.
> 
> > +}
> > +
> > +static void qnum_destroy_test(void)
> > +{
> > +    QNum *qn;
> > +
> > +    qn = qnum_from_int(0);
> > +    QDECREF(qn);
> > +
> > +    qn = qnum_from_double(0.42);
> > +    QDECREF(qn);
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +    g_test_init(&argc, &argv, NULL);
> > +
> > +    g_test_add_func("/qnum/from_int", qnum_from_int_test);
> > +    g_test_add_func("/qnum/from_double", qnum_from_double_test);
> > +    g_test_add_func("/qnum/destroy", qnum_destroy_test);
> > +    g_test_add_func("/qnum/from_int64", qnum_from_int64_test);
> > +    g_test_add_func("/qnum/get_int", qnum_get_int_test);
> > +    g_test_add_func("/qnum/to_qnum", qobject_to_qnum_test);
> > +    g_test_add_func("/qnum/to_string", qnum_to_string_test);
> > +
> > +    return g_test_run();
> > +}
> > diff --git a/tests/test-keyval.c b/tests/test-keyval.c
> > index df0ff831b5..bec574257e 100644
> > --- a/tests/test-keyval.c
> > +++ b/tests/test-keyval.c
> > @@ -611,7 +611,6 @@ static void test_keyval_visit_optional(void)
> >  
> >  static void test_keyval_visit_alternate(void)
> >  {
> > -    Error *err = NULL;
> >      Visitor *v;
> >      QDict *qdict;
> >      AltNumStr *ans;  
> 
> This belongs to PATCH 03.
> 
> > diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> > index acdded4d67..96a52dbca8 100644
> > --- a/tests/test-qmp-commands.c
> > +++ b/tests/test-qmp-commands.c
> > @@ -162,7 +162,7 @@ static void test_dispatch_cmd_io(void)
> >      QDict *ud1b = qdict_new();
> >      QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
> >      QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
> > -    QInt *ret3;
> > +    QNum *ret3;
> >  
> >      qdict_put_int(ud1a, "integer", 42);
> >      qdict_put_str(ud1a, "string", "hello");
> > @@ -194,8 +194,8 @@ static void test_dispatch_cmd_io(void)
> >      qdict_put(req, "arguments", args3);
> >      qdict_put_str(req, "execute", "guest-get-time");
> >  
> > -    ret3 = qobject_to_qint(test_qmp_dispatch(req));
> > -    assert(qint_get_int(ret3) == 66);
> > +    ret3 = qobject_to_qnum(test_qmp_dispatch(req));
> > +    assert(qnum_get_int(ret3, &error_abort) == 66);
> >      QDECREF(ret3);
> >  
> >      QDECREF(req);
> > diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
> > index 4c0f09601d..e996bebc6e 100644
> > --- a/tests/test-qmp-event.c
> > +++ b/tests/test-qmp-event.c
> > @@ -18,7 +18,6 @@
> >  #include "test-qapi-visit.h"
> >  #include "test-qapi-event.h"
> >  #include "qapi/qmp/types.h"
> > -#include "qapi/qmp/qint.h"
> >  #include "qapi/qmp/qobject.h"
> >  #include "qapi/qmp-event.h"
> >  
> > @@ -62,9 +61,9 @@ void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
> >          d->result = (qbool_get_bool(qobject_to_qbool(obj1)) ==
> >                       qbool_get_bool(qobject_to_qbool(obj2)));
> >          return;
> > -    case QTYPE_QINT:
> > -        d->result = (qint_get_int(qobject_to_qint(obj1)) ==
> > -                     qint_get_int(qobject_to_qint(obj2)));
> > +    case QTYPE_QNUM:
> > +        d->result = (qnum_get_int(qobject_to_qnum(obj1), &error_abort) ==
> > +                     qnum_get_int(qobject_to_qnum(obj2), &error_abort));
> >          return;
> >      case QTYPE_QSTRING:
> >          d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
> > diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
> > index a30e2d5e95..4484980969 100644
> > --- a/tests/test-qobject-input-visitor.c
> > +++ b/tests/test-qobject-input-visitor.c
> > @@ -152,7 +152,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
> >      Visitor *v;
> >  
> >      /* this will overflow a Qint/int64, so should be deserialized into
> > -     * a QFloat/double field instead, leading to an error if we pass it
> > +     * a QNum/double field instead, leading to an error if we pass it  
> 
> s#a Qint/int64#an int64_t#
> s#a QNum/double field#a double#
> 
> Or perhaps explain using QNUM_I64 and QNUM_DOUBLE.  Your choice.
> 
> >       * to visit_type_int. confirm this.
> >       */
> >      v = visitor_input_test_init(data, "%f", DBL_MAX);
> > @@ -428,7 +428,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
> >  {
> >      QObject *res = NULL;
> >      Visitor *v;
> > -    QInt *qint;
> > +    QNum *qnum;
> >      QBool *qbool;
> >      QString *qstring;
> >      QDict *qdict;
> > @@ -436,9 +436,9 @@ static void test_visitor_in_any(TestInputVisitorData *data,
> >  
> >      v = visitor_input_test_init(data, "-42");
> >      visit_type_any(v, NULL, &res, &error_abort);
> > -    qint = qobject_to_qint(res);
> > -    g_assert(qint);
> > -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> > +    qnum = qobject_to_qnum(res);
> > +    g_assert(qnum);
> > +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
> >      qobject_decref(res);
> >  
> >      v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
> > @@ -447,9 +447,9 @@ static void test_visitor_in_any(TestInputVisitorData *data,
> >      g_assert(qdict && qdict_size(qdict) == 3);
> >      qobj = qdict_get(qdict, "integer");
> >      g_assert(qobj);
> > -    qint = qobject_to_qint(qobj);
> > -    g_assert(qint);
> > -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> > +    qnum = qobject_to_qnum(qobj);
> > +    g_assert(qnum);
> > +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
> >      qobj = qdict_get(qdict, "boolean");
> >      g_assert(qobj);
> >      qbool = qobject_to_qbool(qobj);
> > @@ -527,7 +527,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
> >  
> >      v = visitor_input_test_init(data, "42");
> >      visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
> > -    g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
> > +    g_assert_cmpint(tmp->type, ==, QTYPE_QNUM);
> >      g_assert_cmpint(tmp->u.i, ==, 42);
> >      qapi_free_UserDefAlternate(tmp);
> >  
> > @@ -555,7 +555,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
> >  
> >      v = visitor_input_test_init(data, "{ 'alt': 42 }");
> >      visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
> > -    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
> > +    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QNUM);
> >      g_assert_cmpint(wrap->alt->u.i, ==, 42);
> >      qapi_free_WrapAlternate(wrap);
> >  
> > @@ -596,19 +596,19 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
> >  
> >      v = visitor_input_test_init(data, "42");
> >      visit_type_AltStrNum(v, NULL, &asn, &error_abort);
> > -    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
> > +    g_assert_cmpint(asn->type, ==, QTYPE_QNUM);
> >      g_assert_cmpfloat(asn->u.n, ==, 42);
> >      qapi_free_AltStrNum(asn);
> >  
> >      v = visitor_input_test_init(data, "42");
> >      visit_type_AltNumStr(v, NULL, &ans, &error_abort);
> > -    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
> > +    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
> >      g_assert_cmpfloat(ans->u.n, ==, 42);
> >      qapi_free_AltNumStr(ans);
> >  
> >      v = visitor_input_test_init(data, "42");
> >      visit_type_AltStrInt(v, NULL, &asi, &error_abort);
> > -    g_assert_cmpint(asi->type, ==, QTYPE_QINT);
> > +    g_assert_cmpint(asi->type, ==, QTYPE_QNUM);
> >      g_assert_cmpint(asi->u.i, ==, 42);
> >      qapi_free_AltStrInt(asi);
> >  
> > @@ -621,13 +621,13 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
> >  
> >      v = visitor_input_test_init(data, "42.5");
> >      visit_type_AltStrNum(v, NULL, &asn, &error_abort);
> > -    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
> > +    g_assert_cmpint(asn->type, ==, QTYPE_QNUM);
> >      g_assert_cmpfloat(asn->u.n, ==, 42.5);
> >      qapi_free_AltStrNum(asn);
> >  
> >      v = visitor_input_test_init(data, "42.5");
> >      visit_type_AltNumStr(v, NULL, &ans, &error_abort);
> > -    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
> > +    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
> >      g_assert_cmpfloat(ans->u.n, ==, 42.5);
> >      qapi_free_AltNumStr(ans);
> >  
> > diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
> > index 94b9518e40..66a682d5a8 100644
> > --- a/tests/test-qobject-output-visitor.c
> > +++ b/tests/test-qobject-output-visitor.c
> > @@ -58,13 +58,13 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
> >                                   const void *unused)
> >  {
> >      int64_t value = -42;
> > -    QInt *qint;
> > +    QNum *qnum;
> >  
> >      visit_type_int(data->ov, NULL, &value, &error_abort);
> >  
> > -    qint = qobject_to_qint(visitor_get(data));
> > -    g_assert(qint);
> > -    g_assert_cmpint(qint_get_int(qint), ==, value);
> > +    qnum = qobject_to_qnum(visitor_get(data));
> > +    g_assert(qnum);
> > +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, value);
> >  }
> >  
> >  static void test_visitor_out_bool(TestOutputVisitorData *data,
> > @@ -84,13 +84,13 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
> >                                      const void *unused)
> >  {
> >      double value = 3.14;
> > -    QFloat *qfloat;
> > +    QNum *qnum;
> >  
> >      visit_type_number(data->ov, NULL, &value, &error_abort);
> >  
> > -    qfloat = qobject_to_qfloat(visitor_get(data));
> > -    g_assert(qfloat);
> > -    g_assert(qfloat_get_double(qfloat) == value);
> > +    qnum = qobject_to_qnum(visitor_get(data));
> > +    g_assert(qnum);
> > +    g_assert(qnum_get_double(qnum) == value);
> >  }
> >  
> >  static void test_visitor_out_string(TestOutputVisitorData *data,
> > @@ -329,16 +329,16 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
> >                                   const void *unused)
> >  {
> >      QObject *qobj;
> > -    QInt *qint;
> > +    QNum *qnum;
> >      QBool *qbool;
> >      QString *qstring;
> >      QDict *qdict;
> >  
> > -    qobj = QOBJECT(qint_from_int(-42));
> > +    qobj = QOBJECT(qnum_from_int(-42));
> >      visit_type_any(data->ov, NULL, &qobj, &error_abort);
> > -    qint = qobject_to_qint(visitor_get(data));
> > -    g_assert(qint);
> > -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> > +    qnum = qobject_to_qnum(visitor_get(data));
> > +    g_assert(qnum);
> > +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
> >      qobject_decref(qobj);
> >  
> >      visitor_reset(data);
> > @@ -351,9 +351,9 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
> >      qobject_decref(qobj);
> >      qdict = qobject_to_qdict(visitor_get(data));
> >      g_assert(qdict);
> > -    qint = qobject_to_qint(qdict_get(qdict, "integer"));
> > -    g_assert(qint);
> > -    g_assert_cmpint(qint_get_int(qint), ==, -42);
> > +    qnum = qobject_to_qnum(qdict_get(qdict, "integer"));
> > +    g_assert(qnum);
> > +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, -42);
> >      qbool = qobject_to_qbool(qdict_get(qdict, "boolean"));
> >      g_assert(qbool);
> >      g_assert(qbool_get_bool(qbool) == true);
> > @@ -388,18 +388,18 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
> >                                         const void *unused)
> >  {
> >      UserDefAlternate *tmp;
> > -    QInt *qint;
> > +    QNum *qnum;
> >      QString *qstr;
> >      QDict *qdict;
> >  
> >      tmp = g_new0(UserDefAlternate, 1);
> > -    tmp->type = QTYPE_QINT;
> > +    tmp->type = QTYPE_QNUM;
> >      tmp->u.i = 42;
> >  
> >      visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
> > -    qint = qobject_to_qint(visitor_get(data));
> > -    g_assert(qint);
> > -    g_assert_cmpint(qint_get_int(qint), ==, 42);
> > +    qnum = qobject_to_qnum(visitor_get(data));
> > +    g_assert(qnum);
> > +    g_assert_cmpint(qnum_get_int(qnum, &error_abort), ==, 42);
> >  
> >      qapi_free_UserDefAlternate(tmp);
> >  
> > @@ -603,18 +603,18 @@ static void check_native_list(QObject *qobj,
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
> > -        /* all integer elements in JSON arrays get stored into QInts when
> > +        /* all integer elements in JSON arrays get stored into QNums when  
> 
> Please use the opportunity to wing the comment at both ends and start
> with a capital letter:
> 
>            /*
>             * All integer ...
> 
> >           * we convert to QObjects, so we can check them all in the same
> >           * fashion, so simply fall through here
> >           */
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
> >          for (i = 0; i < 32; i++) {
> >              QObject *tmp;
> > -            QInt *qvalue;
> > +            QNum *qvalue;
> >              tmp = qlist_peek(qlist);
> >              g_assert(tmp);
> > -            qvalue = qobject_to_qint(tmp);
> > -            g_assert_cmpint(qint_get_int(qvalue), ==, i);
> > +            qvalue = qobject_to_qnum(tmp);
> > +            g_assert_cmpint(qnum_get_int(qvalue, &error_abort), ==, i);
> >              qobject_decref(qlist_pop(qlist));
> >          }
> >          break;
> > @@ -645,15 +645,15 @@ static void check_native_list(QObject *qobj,
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
> >          for (i = 0; i < 32; i++) {
> >              QObject *tmp;
> > -            QFloat *qvalue;
> > +            QNum *qvalue;
> >              GString *double_expected = g_string_new("");
> >              GString *double_actual = g_string_new("");
> >  
> >              tmp = qlist_peek(qlist);
> >              g_assert(tmp);
> > -            qvalue = qobject_to_qfloat(tmp);
> > +            qvalue = qobject_to_qnum(tmp);
> >              g_string_printf(double_expected, "%.6f", (double)i / 3);
> > -            g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue));
> > +            g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue));
> >              g_assert_cmpstr(double_actual->str, ==, double_expected->str);
> >  
> >              qobject_decref(qlist_pop(qlist));
> > diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
> > index 79a2e69a28..60d168fda8 100644
> > --- a/tests/test-x86-cpuid-compat.c
> > +++ b/tests/test-x86-cpuid-compat.c
> > @@ -1,9 +1,7 @@
> >  #include "qemu/osdep.h"
> >  #include "qemu-common.h"
> > -#include "qapi/qmp/qlist.h"
> > -#include "qapi/qmp/qdict.h"
> > -#include "qapi/qmp/qint.h"
> > -#include "qapi/qmp/qbool.h"
> > +#include "qapi/error.h"
> > +#include "qapi/qmp/types.h"  
> 
> Previous note on qapi/qmp/types.h applies.
> 
> >  #include "libqtest.h"
> >  
> >  static char *get_cpu0_qom_path(void)
> > @@ -56,12 +54,13 @@ static void test_cpuid_prop(const void *data)
> >  {
> >      const CpuidTestArgs *args = data;
> >      char *path;
> > -    QInt *value;
> > +    QNum *value;
> >  
> >      qtest_start(args->cmdline);
> >      path = get_cpu0_qom_path();
> > -    value = qobject_to_qint(qom_get(path, args->property));
> > -    g_assert_cmpint(qint_get_int(value), ==, args->expected_value);
> > +    value = qobject_to_qnum(qom_get(path, args->property));
> > +    g_assert_cmpint(qnum_get_int(value, &error_abort), ==,
> > +                    args->expected_value);
> >      qtest_end();
> >  
> >      QDECREF(value);
> > diff --git a/ui/spice-core.c b/ui/spice-core.c
> > index 804abc5c0f..561d0649cf 100644
> > --- a/ui/spice-core.c
> > +++ b/ui/spice-core.c
> > @@ -30,7 +30,6 @@
> >  #include "qemu-x509.h"
> >  #include "qemu/sockets.h"
> >  #include "qmp-commands.h"
> > -#include "qapi/qmp/qint.h"
> >  #include "qapi/qmp/qbool.h"
> >  #include "qapi/qmp/qstring.h"
> >  #include "qapi/qmp/qjson.h"
> > diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
> > index 1e53b1cf84..89ab12c0d8 100644
> > --- a/ui/vnc-enc-tight.c
> > +++ b/ui/vnc-enc-tight.c
> > @@ -44,7 +44,6 @@
> >  #endif
> >  
> >  #include "qemu/bswap.h"
> > -#include "qapi/qmp/qint.h"
> >  #include "vnc.h"
> >  #include "vnc-enc-tight.h"
> >  #include "vnc-palette.h"
> > diff --git a/util/qemu-option.c b/util/qemu-option.c
> > index 5977bfc3e9..39b1e06225 100644
> > --- a/util/qemu-option.c
> > +++ b/util/qemu-option.c
> > @@ -941,9 +941,8 @@ typedef struct OptsFromQDictState {
> >  static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
> >  {
> >      OptsFromQDictState *state = opaque;
> > -    char buf[32];
> > +    char buf[32], *tmp = NULL;
> >      const char *value;
> > -    int n;
> >  
> >      if (!strcmp(key, "id") || *state->errp) {
> >          return;
> > @@ -953,17 +952,9 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
> >      case QTYPE_QSTRING:
> >          value = qstring_get_str(qobject_to_qstring(obj));
> >          break;
> > -    case QTYPE_QINT:
> > -        n = snprintf(buf, sizeof(buf), "%" PRId64,
> > -                     qint_get_int(qobject_to_qint(obj)));
> > -        assert(n < sizeof(buf));
> > -        value = buf;
> > -        break;
> > -    case QTYPE_QFLOAT:
> > -        n = snprintf(buf, sizeof(buf), "%.17g",
> > -                     qfloat_get_double(qobject_to_qfloat(obj)));
> > -        assert(n < sizeof(buf));
> > -        value = buf;
> > +    case QTYPE_QNUM:
> > +        tmp = qnum_to_string(qobject_to_qnum(obj));
> > +        value = tmp;
> >          break;
> >      case QTYPE_QBOOL:
> >          pstrcpy(buf, sizeof(buf),
> > @@ -975,12 +966,13 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
> >      }
> >  
> >      qemu_opt_set(state->opts, key, value, state->errp);
> > +    g_free(tmp);
> >  }
> >  
> >  /*
> >   * Create QemuOpts from a QDict.
> >   * Use value of key "id" as ID if it exists and is a QString.
> > - * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
> > + * Only QStrings, QNums and QBools are copied.  Entries with
> >   * other types are silently ignored.
> >   */  
> 
> Refill the sentence, please.
> 
> >  QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 66c9734311..421fb585ae 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -1395,8 +1395,7 @@ F: include/qapi/qmp/
> >  X: include/qapi/qmp/dispatch.h
> >  F: scripts/coccinelle/qobject.cocci
> >  F: tests/check-qdict.c
> > -F: tests/check-qfloat.c
> > -F: tests/check-qint.c
> > +F: tests/check-qnum.c
> >  F: tests/check-qjson.c
> >  F: tests/check-qlist.c
> >  F: tests/check-qstring.c
> > diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs
> > index bed55084bb..fc8885c9a4 100644
> > --- a/qobject/Makefile.objs
> > +++ b/qobject/Makefile.objs
> > @@ -1,2 +1,2 @@
> > -util-obj-y = qnull.o qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
> > +util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o
> >  util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
> > diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.cocci
> > index 97703a438b..c3253deb1b 100644
> > --- a/scripts/coccinelle/qobject.cocci
> > +++ b/scripts/coccinelle/qobject.cocci
> > @@ -6,7 +6,7 @@ expression Obj, Key, E;
> >  - qdict_put_obj(Obj, Key, QOBJECT(E));
> >  + qdict_put(Obj, Key, E);
> >  |
> > -- qdict_put(Obj, Key, qint_from_int(E));
> > +- qdict_put(Obj, Key, qnum_from_int(E));
> >  + qdict_put_int(Obj, Key, E);
> >  |
> >  - qdict_put(Obj, Key, qbool_from_bool(E));
> > @@ -24,7 +24,7 @@ expression Obj, E;
> >  - qlist_append_obj(Obj, QOBJECT(E));
> >  + qlist_append(Obj, E);
> >  |
> > -- qlist_append(Obj, qint_from_int(E));
> > +- qlist_append(Obj, qnum_from_int(E));
> >  + qlist_append_int(Obj, E);
> >  |
> >  - qlist_append(Obj, qbool_from_bool(E));
> > diff --git a/tests/.gitignore b/tests/.gitignore
> > index a966740c2c..847f4f1474 100644
> > --- a/tests/.gitignore
> > +++ b/tests/.gitignore
> > @@ -1,7 +1,6 @@
> >  atomic_add-bench
> >  check-qdict
> > -check-qfloat
> > -check-qint
> > +check-qnum
> >  check-qjson
> >  check-qlist
> >  check-qnull
> > diff --git a/tests/Makefile.include b/tests/Makefile.include
> > index 31931c0d77..ac0387d88a 100644
> > --- a/tests/Makefile.include
> > +++ b/tests/Makefile.include
> > @@ -10,10 +10,8 @@ check-unit-y = tests/check-qdict$(EXESUF)
> >  gcov-files-check-qdict-y = qobject/qdict.c
> >  check-unit-y += tests/test-char$(EXESUF)
> >  gcov-files-check-qdict-y = chardev/char.c
> > -check-unit-y += tests/check-qfloat$(EXESUF)
> > -gcov-files-check-qfloat-y = qobject/qfloat.c
> > -check-unit-y += tests/check-qint$(EXESUF)
> > -gcov-files-check-qint-y = qobject/qint.c
> > +check-unit-y += tests/check-qnum$(EXESUF)
> > +gcov-files-check-qnum-y = qobject/qnum.c
> >  check-unit-y += tests/check-qstring$(EXESUF)
> >  gcov-files-check-qstring-y = qobject/qstring.c
> >  check-unit-y += tests/check-qlist$(EXESUF)
> > @@ -500,8 +498,8 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
> >  	tests/test-qmp-commands.h tests/test-qapi-event.h \
> >  	tests/test-qmp-introspect.h
> >  
> > -test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
> > -	tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
> > +test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
> > +	tests/check-qlist.o tests/check-qnull.o \
> >  	tests/check-qjson.o \
> >  	tests/test-coroutine.o tests/test-string-output-visitor.o \
> >  	tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
> > @@ -529,11 +527,10 @@ test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
> >  test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
> >  test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
> >  
> > -tests/check-qint$(EXESUF): tests/check-qint.o $(test-util-obj-y)
> > +tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y)
> >  tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y)
> >  tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
> >  tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
> > -tests/check-qfloat$(EXESUF): tests/check-qfloat.o $(test-util-obj-y)
> >  tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
> >  tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
> >  tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
> > diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
> > index 5d7c13cad1..17e652535c 100644
> > --- a/tests/qapi-schema/comments.out
> > +++ b/tests/qapi-schema/comments.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  enum Status ['good', 'bad', 'ugly']
> >  object q_empty
> > diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> > index 70c1252408..63ca25a8b9 100644
> > --- a/tests/qapi-schema/doc-good.out
> > +++ b/tests/qapi-schema/doc-good.out
> > @@ -6,7 +6,7 @@ object Object
> >      tag base1
> >      case one: Variant1
> >      case two: Variant2
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  object SugaredUnion
> >      member type: SugaredUnionKind optional=False
> > diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
> > index 8a5b034424..40b886ddae 100644
> > --- a/tests/qapi-schema/empty.out
> > +++ b/tests/qapi-schema/empty.out
> > @@ -1,3 +1,3 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  object q_empty
> > diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
> > index 5a0f2bf805..313c0fe7be 100644
> > --- a/tests/qapi-schema/event-case.out
> > +++ b/tests/qapi-schema/event-case.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  event oops None
> >     boxed=False
> > diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
> > index 1d2722c02e..b5637cb2e0 100644
> > --- a/tests/qapi-schema/ident-with-escape.out
> > +++ b/tests/qapi-schema/ident-with-escape.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  command fooA q_obj_fooA-arg -> None
> >     gen=True success_response=True boxed=False
> > diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
> > index 5d7c13cad1..17e652535c 100644
> > --- a/tests/qapi-schema/include-relpath.out
> > +++ b/tests/qapi-schema/include-relpath.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  enum Status ['good', 'bad', 'ugly']
> >  object q_empty
> > diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
> > index 5d7c13cad1..17e652535c 100644
> > --- a/tests/qapi-schema/include-repetition.out
> > +++ b/tests/qapi-schema/include-repetition.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  enum Status ['good', 'bad', 'ugly']
> >  object q_empty
> > diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
> > index 5d7c13cad1..17e652535c 100644
> > --- a/tests/qapi-schema/include-simple.out
> > +++ b/tests/qapi-schema/include-simple.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  enum Status ['good', 'bad', 'ugly']
> >  object q_empty
> > diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
> > index e8171c935f..586795f44d 100644
> > --- a/tests/qapi-schema/indented-expr.out
> > +++ b/tests/qapi-schema/indented-expr.out
> > @@ -1,4 +1,4 @@
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  command eins None -> None
> >     gen=True success_response=True boxed=False
> > diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
> > index 5c6655a5c3..7812a6c69b 100644
> > --- a/tests/qapi-schema/qapi-schema-test.out
> > +++ b/tests/qapi-schema/qapi-schema-test.out
> > @@ -46,7 +46,7 @@ object NestedEnumsOne
> >      member enum4: EnumOne optional=True
> >  enum QEnumTwo ['value1', 'value2']
> >      prefix QENUM_TWO
> > -enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
> > +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> >      prefix QTYPE
> >  object TestStruct
> >      member integer: int optional=False  
> 
> I still like it :)
> 

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

* Re: [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type Marc-André Lureau
@ 2017-05-13 20:49   ` Philippe Mathieu-Daudé
  2017-05-18 12:57   ` Markus Armbruster
  1 sibling, 0 replies; 70+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-13 20:49 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: armbru

On 05/09/2017 02:35 PM, Marc-André Lureau wrote:
> Use a more specific bool type.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  hw/acpi/ich9.c       | 24 ++++++++++++------------
>  hw/acpi/piix4.c      |  8 ++++----
>  hw/i386/acpi-build.c |  5 +++--
>  3 files changed, 19 insertions(+), 18 deletions(-)
>
> diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
> index 5c279bbaca..3bd8c4bcf5 100644
> --- a/hw/acpi/ich9.c
> +++ b/hw/acpi/ich9.c
> @@ -359,9 +359,9 @@ static void ich9_pm_get_disable_s3(Object *obj, Visitor *v, const char *name,
>                                     void *opaque, Error **errp)
>  {
>      ICH9LPCPMRegs *pm = opaque;
> -    uint8_t value = pm->disable_s3;
> +    bool value = pm->disable_s3;
>
> -    visit_type_uint8(v, name, &value, errp);
> +    visit_type_bool(v, name, &value, errp);
>  }
>
>  static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, const char *name,
> @@ -369,9 +369,9 @@ static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, const char *name,
>  {
>      ICH9LPCPMRegs *pm = opaque;
>      Error *local_err = NULL;
> -    uint8_t value;
> +    bool value;
>
> -    visit_type_uint8(v, name, &value, &local_err);
> +    visit_type_bool(v, name, &value, &local_err);
>      if (local_err) {
>          goto out;
>      }
> @@ -384,9 +384,9 @@ static void ich9_pm_get_disable_s4(Object *obj, Visitor *v, const char *name,
>                                     void *opaque, Error **errp)
>  {
>      ICH9LPCPMRegs *pm = opaque;
> -    uint8_t value = pm->disable_s4;
> +    bool value = pm->disable_s4;
>
> -    visit_type_uint8(v, name, &value, errp);
> +    visit_type_bool(v, name, &value, errp);
>  }
>
>  static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, const char *name,
> @@ -394,9 +394,9 @@ static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, const char *name,
>  {
>      ICH9LPCPMRegs *pm = opaque;
>      Error *local_err = NULL;
> -    uint8_t value;
> +    bool value;
>
> -    visit_type_uint8(v, name, &value, &local_err);
> +    visit_type_bool(v, name, &value, &local_err);
>      if (local_err) {
>          goto out;
>      }
> @@ -447,8 +447,8 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
>      static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
>      pm->acpi_memory_hotplug.is_enabled = true;
>      pm->cpu_hotplug_legacy = true;
> -    pm->disable_s3 = 0;
> -    pm->disable_s4 = 0;
> +    pm->disable_s3 = false;
> +    pm->disable_s4 = false;
>      pm->s4_val = 2;
>
>      object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
> @@ -466,11 +466,11 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
>                               ich9_pm_get_cpu_hotplug_legacy,
>                               ich9_pm_set_cpu_hotplug_legacy,
>                               NULL);
> -    object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
> +    object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "bool",
>                          ich9_pm_get_disable_s3,
>                          ich9_pm_set_disable_s3,
>                          NULL, pm, NULL);
> -    object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8",
> +    object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "bool",
>                          ich9_pm_get_disable_s4,
>                          ich9_pm_set_disable_s4,
>                          NULL, pm, NULL);
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index a553a7e110..74692336b5 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -83,8 +83,8 @@ typedef struct PIIX4PMState {
>      AcpiPciHpState acpi_pci_hotplug;
>      bool use_acpi_pci_hotplug;
>
> -    uint8_t disable_s3;
> -    uint8_t disable_s4;
> +    bool disable_s3;
> +    bool disable_s4;
>      uint8_t s4_val;
>
>      bool cpu_hotplug_legacy;
> @@ -670,8 +670,8 @@ static void piix4_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
>
>  static Property piix4_pm_properties[] = {
>      DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
> -    DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
> -    DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
> +    DEFINE_PROP_BOOL(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, false),
> +    DEFINE_PROP_BOOL(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, false),
>      DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
>      DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
>                       use_acpi_pci_hotplug, true),
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 1707fae9bf..27ad420914 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -22,6 +22,7 @@
>
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
> +#include "qapi/qmp/types.h"
>  #include "acpi-build.h"
>  #include "qemu-common.h"
>  #include "qemu/bitmap.h"
> @@ -149,14 +150,14 @@ 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), &error_abort);
> +        pm->s3_disabled = qbool_get_bool(qobject_to_qbool(o));
>      } 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), &error_abort);
> +        pm->s4_disabled = qbool_get_bool(qobject_to_qbool(o));
>      } else {
>          pm->s4_disabled = false;
>      }
>

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

* Re: [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (16 preceding siblings ...)
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 17/17] qobject: move dump_qobject() from block/ to qobject/ Marc-André Lureau
@ 2017-05-13 21:41 ` no-reply
  2017-05-18 15:39 ` Markus Armbruster
  18 siblings, 0 replies; 70+ messages in thread
From: no-reply @ 2017-05-13 21:41 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel, armbru

Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type
Type: series
Message-id: 20170509173559.31598-1-marcandre.lureau@redhat.com

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/1494553288-30764-1-git-send-email-zhangchen.fnst@cn.fujitsu.com -> patchew/1494553288-30764-1-git-send-email-zhangchen.fnst@cn.fujitsu.com
 - [tag update]      patchew/20170513004616.25749-1-n54@gmx.com -> patchew/20170513004616.25749-1-n54@gmx.com
Switched to a new branch 'test'
b371cbd qobject: move dump_qobject() from block/ to qobject/
bfd6fc7 RFC: qdict: add uint
dcd5370 Use uint property getter/setter where appropriate
143e214 acpi: fix s3/s4 disabled type
d99e973 qdev: use appropriate getter/setters type
db1dfea qdev: use int and uint properties as appropriate
16017fd object: use more specific property type names
741b10f object: add uint property setter/getter
b3804bd qnum: fix get_int() with values > INT64_MAX
2aba7fc qapi: update the qobject visitor to use QUInt
5e637e4 json: learn to parse uint64 numbers
03c3c0a qnum: add uint type
f9011a3 qapi: remove promote_int
755c246 qapi: merge QInt and QFloat in QNum
4d37032 tests: remove alt num-int cases
e9722ac object: fix potential leak in getters
988cb53 qdev: remove PropertyInfo.qtype field

=== OUTPUT BEGIN ===
Checking PATCH 1/17: qdev: remove PropertyInfo.qtype field...
Checking PATCH 2/17: object: fix potential leak in getters...
Checking PATCH 3/17: tests: remove alt num-int cases...
Checking PATCH 4/17: qapi: merge QInt and QFloat in QNum...
ERROR: do not use C99 // comments
#1885: FILE: tests/check-qnum.c:35:
+    // destroy doesn't exit yet

ERROR: do not use C99 // comments
#1900: FILE: tests/check-qnum.c:50:
+    // destroy doesn't exit yet

total: 2 errors, 0 warnings, 1766 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 5/17: qapi: remove promote_int...
Checking PATCH 6/17: qnum: add uint type...
ERROR: do not use C99 // comments
#152: FILE: tests/check-qnum.c:50:
+    // destroy doesn't exit yet

total: 1 errors, 0 warnings, 182 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 7/17: json: learn to parse uint64 numbers...
Checking PATCH 8/17: qapi: update the qobject visitor to use QUInt...
Checking PATCH 9/17: qnum: fix get_int() with values > INT64_MAX...
Checking PATCH 10/17: object: add uint property setter/getter...
Checking PATCH 11/17: object: use more specific property type names...
Checking PATCH 12/17: qdev: use int and uint properties as appropriate...
Checking PATCH 13/17: qdev: use appropriate getter/setters type...
Checking PATCH 14/17: acpi: fix s3/s4 disabled type...
Checking PATCH 15/17: Use uint property getter/setter where appropriate...
Checking PATCH 16/17: RFC: qdict: add uint...
Checking PATCH 17/17: qobject: move dump_qobject() from block/ to qobject/...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-12 13:03     ` Luiz Capitulino
@ 2017-05-15  6:35       ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-15  6:35 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: Marc-André Lureau, qemu-devel

Luiz Capitulino <lcapitulino@redhat.com> writes:

> On Fri, 12 May 2017 09:37:50 +0200
> Markus Armbruster <armbru@redhat.com> wrote:
>
>> Luiz, there's a lone question for you further down.  Search for your
>> name.
>
> I could not a question, can you paste it here?

Uh, I actually spun it out into its own message, so you don't have to
wade through this one, then forgot to update this one.  I award myself
one point out of ten for trying.

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-12 13:00     ` Luiz Capitulino
@ 2017-05-15  7:00       ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-15  7:00 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: Marc-André Lureau, qemu-devel

Luiz Capitulino <lcapitulino@redhat.com> writes:

> On Fri, 12 May 2017 08:30:36 +0200
> Markus Armbruster <armbru@redhat.com> wrote:
>
>> Question for Luiz...
>> 
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> 
>> [...]
>> > diff --git a/tests/check-qnum.c b/tests/check-qnum.c
>> > new file mode 100644
>> > index 0000000000..d08d35e85a
>> > --- /dev/null
>> > +++ b/tests/check-qnum.c
>> > @@ -0,0 +1,131 @@
>> > +/*
>> > + * QNum unit-tests.
>> > + *
>> > + * Copyright (C) 2009 Red Hat Inc.
>> > + *
>> > + * Authors:
>> > + *  Luiz Capitulino <lcapitulino@redhat.com>
>> > + *
>> > + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>> > + * See the COPYING.LIB file in the top-level directory.
>> > + */
>> > +#include "qemu/osdep.h"
>> > +
>> > +#include "qapi/qmp/qnum.h"
>> > +#include "qapi/error.h"
>> > +#include "qemu-common.h"
>> > +
>> > +/*
>> > + * Public Interface test-cases
>> > + *
>> > + * (with some violations to access 'private' data)
>> > + */
>> > +
>> > +static void qnum_from_int_test(void)
>> > +{
>> > +    QNum *qi;
>> > +    const int value = -42;
>> > +
>> > +    qi = qnum_from_int(value);
>> > +    g_assert(qi != NULL);
>> > +    g_assert_cmpint(qi->u.i64, ==, value);
>> > +    g_assert_cmpint(qi->base.refcnt, ==, 1);
>> > +    g_assert_cmpint(qobject_type(QOBJECT(qi)), ==, QTYPE_QNUM);
>> > +
>> > +    // destroy doesn't exit yet
>> > +    g_free(qi);
>> > +}  
>> 
>> The comment is enigmatic. 
>
> It was meant for future generations to figure it out :)

Hah!

>> It was first written in commit 33837ba
>> "Introduce QInt unit-tests", and got copied around since.  In
>> check-qlist.c, it's spelled "exist yet".
>
> Yes, "exit" is a typo it should be "exist".
>
>> What is "destroy", why doesn't it exit / exist now, but will exit /
>> exist later?  It can't be qnum_destroy_obj(), because that certainly
>> exists already, exits already in the sense of returning, and shouldn't
>> ever exit in the sense of terminating the program.
>> 
>> The comment applies to a g_free().  Why do we free directly instead
>> decrementing the reference count?  Perhaps the comment tries to explain
>> that (if it does, it fails).
>
> In my personal style of writing unit-tests, I never use a method
> in a test before testing it. So, as QDECREF() wasn't tested yet,
> I wasn't allowed to use it.

It's a good principle for organizing tests.

> While I keep this principle when writing unit-tests today, this
> particular case is very extreme and not useful at all. Today I'd just
> go ahead and use QDECREF().

Makes sense.

>                             The qint_destroy_test() in the original
> commit is also very bogus, it's not really doing an useful test.

It can demonstrate leaks under valgrind.  But pretty much every other
test can just as well, so...

Marc-André, care to stick a cleanup patch into your series?

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

* Re: [Qemu-devel] [PATCH 06/17] qnum: add uint type
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 06/17] qnum: add uint type Marc-André Lureau
@ 2017-05-15  7:27   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-15  7:27 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> In order to store integer values superior to INT64_MAX, add a u64
> internal representation.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/qapi/qmp/qnum.h |  4 ++++
>  qobject/qnum.c          | 49 +++++++++++++++++++++++++++++++++++++++++++++++
>  tests/check-qnum.c      | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+)
>
> diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h
> index 0e51427821..89c14e040f 100644
> --- a/include/qapi/qmp/qnum.h
> +++ b/include/qapi/qmp/qnum.h
> @@ -17,6 +17,7 @@
>  
>  typedef enum {
>      QNUM_I64,
> +    QNUM_U64,
>      QNUM_DOUBLE
>  } QNumType;
>  
> @@ -25,14 +26,17 @@ typedef struct QNum {
>      QNumType type;
>      union {
>          int64_t i64;
> +        uint64_t u64;
>          double dbl;
>      } u;
>  } QNum;
>  
>  QNum *qnum_from_int(int64_t value);
> +QNum *qnum_from_uint(uint64_t value);
>  QNum *qnum_from_double(double value);
>  
>  int64_t qnum_get_int(const QNum *qi, Error **errp);
> +uint64_t qnum_get_uint(const QNum *qi, Error **errp);
>  double qnum_get_double(QNum *qn);
>  
>  char *qnum_to_string(QNum *qn);
> diff --git a/qobject/qnum.c b/qobject/qnum.c
> index 8e9dd38350..be6307accf 100644
> --- a/qobject/qnum.c
> +++ b/qobject/qnum.c
> @@ -13,6 +13,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
> +#include "qemu/error-report.h"

Superfluous, please drop.

>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qobject.h"
>  #include "qemu-common.h"
> @@ -34,6 +35,22 @@ QNum *qnum_from_int(int64_t value)
>  }
>  
>  /**
> + * qnum_from_uint(): Create a new QNum from an uint64_t
> + *
> + * Return strong reference.
> + */
> +QNum *qnum_from_uint(uint64_t value)
> +{
> +    QNum *qn = g_new(QNum, 1);
> +
> +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> +    qn->type = QNUM_U64;
> +    qn->u.u64 = value;
> +
> +    return qn;
> +}
> +
> +/**
>   * qnum_from_double(): Create a new QNum from a double
>   *
>   * Return strong reference.
> @@ -57,6 +74,34 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
>      switch (qn->type) {
>      case QNUM_I64:
>          return qn->u.i64;
> +    case QNUM_U64:
> +        if (qn->u.u64 > INT64_MAX) {
> +            error_setg(errp, "The number is too large, use qnum_get_uint()");

The user has no way to "use qnum_get_uint()".

> +            return 0;
> +        }
> +        return qn->u.u64;
> +    case QNUM_DOUBLE:
> +        error_setg(errp, "The number is a float");
> +        return 0;
> +    }
> +
> +    g_assert_not_reached();
> +}
> +
> +/**
> + * qnum_get_uint(): Get an unsigned integer from the number
> + */
> +uint64_t qnum_get_uint(const QNum *qn, Error **errp)
> +{
> +    switch (qn->type) {
> +    case QNUM_I64:
> +        if (qn->u.i64 < 0) {
> +            error_setg(errp, "The number is negative");

The new error messages are inadequate in the same way as the existing
one.

> +            return 0;
> +        }
> +        return qn->u.i64;
> +    case QNUM_U64:
> +        return qn->u.u64;
>      case QNUM_DOUBLE:
>          error_setg(errp, "The number is a float");
>          return 0;
> @@ -73,6 +118,8 @@ double qnum_get_double(QNum *qn)
>      switch (qn->type) {
>      case QNUM_I64:
>          return qn->u.i64;
> +    case QNUM_U64:
> +        return qn->u.u64;
>      case QNUM_DOUBLE:
>          return qn->u.dbl;
>      }
> @@ -88,6 +135,8 @@ char *qnum_to_string(QNum *qn)
>      switch (qn->type) {
>      case QNUM_I64:
>          return g_strdup_printf("%" PRId64, qn->u.i64);
> +    case QNUM_U64:
> +        return g_strdup_printf("%" PRIu64, qn->u.u64);
>      case QNUM_DOUBLE:
>          /* FIXME: snprintf() is locale dependent; but JSON requires
>           * numbers to be formatted as if in the C locale. Dependence
> diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> index d08d35e85a..8199546f99 100644
> --- a/tests/check-qnum.c
> +++ b/tests/check-qnum.c
> @@ -36,6 +36,21 @@ static void qnum_from_int_test(void)
>      g_free(qi);
>  }
>  
> +static void qnum_from_uint_test(void)
> +{
> +    QNum *qu;
> +    const int value = UINT_MAX;
> +
> +    qu = qnum_from_int(value);
> +    g_assert(qu != NULL);
> +    g_assert(qu->u.u64 == value);
> +    g_assert(qu->base.refcnt == 1);
> +    g_assert(qobject_type(QOBJECT(qu)) == QTYPE_QNUM);
> +
> +    // destroy doesn't exit yet
> +    g_free(qu);
> +}
> +

Matches the other qnum_from_TYPE_test().  Let's clean them up before
this patch: use QDECREF() instead of g_free(), and drop the comment (see
Luiz's reply to PATCH 04).

>  static void qnum_from_double_test(void)
>  {
>      QNum *qf;
> @@ -73,6 +88,37 @@ static void qnum_get_int_test(void)
>      QDECREF(qi);
>  }
>  
> +static void qnum_get_uint_test(void)
> +{
> +    QNum *qn;
> +    const int value = 123456;
> +    Error *err = NULL;
> +
> +    qn = qnum_from_uint(value);
> +    g_assert(qnum_get_uint(qn, &error_abort) == value);
> +    QDECREF(qn);
> +
> +    qn = qnum_from_int(value);
> +    g_assert(qnum_get_uint(qn, &error_abort) == value);
> +    QDECREF(qn);
> +
> +    qn = qnum_from_int(-1);
> +    qnum_get_uint(qn, &err);
> +    error_free_or_abort(&err);
> +    QDECREF(qn);
> +
> +    qn = qnum_from_uint(-1ULL);
> +    qnum_get_int(qn, &err);
> +    error_free_or_abort(&err);
> +    QDECREF(qn);
> +
> +    /* invalid case */

No more invalid than the previous two, isn't it?

> +    qn = qnum_from_double(0.42);
> +    qnum_get_uint(qn, &err);
> +    error_free_or_abort(&err);
> +    QDECREF(qn);
> +}
> +
>  static void qobject_to_qnum_test(void)
>  {
>      QNum *qn;
> @@ -111,6 +157,9 @@ static void qnum_destroy_test(void)
>      qn = qnum_from_int(0);
>      QDECREF(qn);
>  
> +    qn = qnum_from_uint(0);
> +    QDECREF(qn);
> +
>      qn = qnum_from_double(0.42);
>      QDECREF(qn);
>  }

Let's drop this test before this patch.

> @@ -120,10 +169,12 @@ int main(int argc, char **argv)
>      g_test_init(&argc, &argv, NULL);
>  
>      g_test_add_func("/qnum/from_int", qnum_from_int_test);
> +    g_test_add_func("/qnum/from_uint", qnum_from_uint_test);
>      g_test_add_func("/qnum/from_double", qnum_from_double_test);
>      g_test_add_func("/qnum/destroy", qnum_destroy_test);
>      g_test_add_func("/qnum/from_int64", qnum_from_int64_test);
>      g_test_add_func("/qnum/get_int", qnum_get_int_test);
> +    g_test_add_func("/qnum/get_uint", qnum_get_uint_test);
>      g_test_add_func("/qnum/to_qnum", qobject_to_qnum_test);
>      g_test_add_func("/qnum/to_string", qnum_to_string_test);

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

* Re: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers Marc-André Lureau
@ 2017-05-15 13:59   ` Markus Armbruster
  2017-05-30 11:35     ` Marc-André Lureau
  0 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-15 13:59 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Switch strtoll() usage to qemu_strtoi64() helper while at it.
>
> Replace temporarily the error in qnum_get_int() with values >INT64_MAX
> until the visitor is updated.
>
> Add a few tests for large numbers.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qobject/json-lexer.c               |  4 ++++
>  qobject/json-parser.c              | 30 ++++++++++++++++++++++--------
>  qobject/qnum.c                     |  4 ++--
>  tests/check-qjson.c                | 28 ++++++++++++++++++++++++++++
>  tests/check-qnum.c                 |  9 +++++----
>  tests/test-qobject-input-visitor.c |  7 ++-----
>  6 files changed, 63 insertions(+), 19 deletions(-)
>
> diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
> index af4a75e05b..a0beb0b106 100644
> --- a/qobject/json-lexer.c
> +++ b/qobject/json-lexer.c
> @@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
>      /* escape */
>      [IN_ESCAPE_LL] = {
>          ['d'] = JSON_ESCAPE,
> +        ['u'] = JSON_ESCAPE,
>      },
>  
>      [IN_ESCAPE_L] = {
>          ['d'] = JSON_ESCAPE,
> +        ['u'] = JSON_ESCAPE,
>          ['l'] = IN_ESCAPE_LL,
>      },
>  
>      [IN_ESCAPE_I64] = {
>          ['d'] = JSON_ESCAPE,
> +        ['u'] = JSON_ESCAPE,
>      },
>  
>      [IN_ESCAPE_I6] = {
> @@ -247,6 +250,7 @@ static const uint8_t json_lexer[][256] =  {
>      },
>  
>      [IN_ESCAPE] = {
> +        ['u'] = JSON_ESCAPE,
>          ['d'] = JSON_ESCAPE,
>          ['i'] = JSON_ESCAPE,
>          ['p'] = JSON_ESCAPE,

Please keep the JSON_ESCAPE lines sorted.

> diff --git a/qobject/json-parser.c b/qobject/json-parser.c
> index f431854ba1..fa15c762d3 100644
> --- a/qobject/json-parser.c
> +++ b/qobject/json-parser.c
> @@ -12,6 +12,7 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qemu/cutils.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
>  #include "qapi/qmp/types.h"
> @@ -472,6 +473,13 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
>      } else if (!strcmp(token->str, "%lld") ||
>                 !strcmp(token->str, "%I64d")) {
>          return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
> +    } else if (!strcmp(token->str, "%u")) {
> +        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int)));
> +    } else if (!strcmp(token->str, "%lu")) {
> +        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long)));
> +    } else if (!strcmp(token->str, "%llu") ||
> +               !strcmp(token->str, "%I64u")) {
> +        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long)));
>      } else if (!strcmp(token->str, "%s")) {
>          return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
>      } else if (!strcmp(token->str, "%f")) {
> @@ -494,22 +502,28 @@ static QObject *parse_literal(JSONParserContext *ctxt)
>          /* A possibility exists that this is a whole-valued float where the
>           * fractional part was left out due to being 0 (.0). It's not a big
>           * deal to treat these as ints in the parser, so long as users of the
> -         * resulting QObject know to expect a QNum in place of a QNum in
> -         * cases like these.
> +         * resulting QObject know to expect a QNum that will handle
> +         * implicit conversions to the expected type.
>           *
> -         * However, in some cases these values will overflow/underflow a
> -         * QNum/int64 container, thus we should assume these are to be handled
> -         * as QNums/doubles rather than silently changing their values.
> +         * However, in some cases these values will overflow/underflow
> +         * a QNum/int64 container, thus we should assume these are to
> +         * be handled as QNum/uint64 or QNums/doubles rather than
> +         * silently changing their values.
>           *
> -         * strtoll() indicates these instances by setting errno to ERANGE
> +         * qemu_strto*() indicates these instances by setting errno to ERANGE
>           */

I asked for this comment to be rephrased in PATCH 04.  Turns out my
proposal there there isn't so easy to extend for unsigned, so let me try
again from scratch:

           /*
            * Represent JSON_INTEGER as QNUM_I64 if possible, else as
            * QNUM_U64, else as QNUM_DOUBLE.  Note that qemu_strtoi64()
            * and qemu_strtou64 fail with ERANGE when it's not possible.
            *
            * qnum_get_int() will then work for any signed 64-bit
            * JSON_INTEGER, qnum_get_uint() for any unsigned 64-bit
            * integer, and qnum_get_double both for any JSON_INTEGER and
            * any JSON_FLOAT.
            */

Remove the unsigned part for PATCH 04.

>          int64_t value;
> +        uint64_t uvalue;
>  
> -        errno = 0; /* strtoll doesn't set errno on success */
> -        value = strtoll(token->str, NULL, 10);
> +        qemu_strtoi64(token->str, NULL, 10, &value);
>          if (errno != ERANGE) {
>              return QOBJECT(qnum_from_int(value));
>          }

qemu_strtoi64() returns an error code.  Checking errno is wrong.
Better:

           ret = qemu_strtoi64(token->str, NULL, 10, &value);
           if (!ret) {
               return QOBJECT(qnum_from_int(value));
           }
           assert(ret == -ERANGE);

> +
> +        qemu_strtou64(token->str, NULL, 10, &uvalue);
> +        if (errno != ERANGE) {
> +            return QOBJECT(qnum_from_uint(uvalue));
> +        }

Likewise.

Moreover, values between -2^64 and 0 exclusive are accepted modulo 2^64.
Example: -9223372036854775809 is accepted as a funny way to say
9223372036854775807.  Bad.  This is a well-known strtoul() wart
qemu_strtou64() reproduces faithfully.  We need to avoid trying
qemu_strtou64() when token->str[0] == '-'.  Exploits that the lexer
strips off leading whitespace, but I think that's quite tolerable.

>          /* fall through to JSON_FLOAT */
>      }
>      case JSON_FLOAT:
> diff --git a/qobject/qnum.c b/qobject/qnum.c
> index be6307accf..2f87952db8 100644
> --- a/qobject/qnum.c
> +++ b/qobject/qnum.c
> @@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
>          return qn->u.i64;
>      case QNUM_U64:
>          if (qn->u.u64 > INT64_MAX) {
> -            error_setg(errp, "The number is too large, use qnum_get_uint()");
> -            return 0;
> +            /* temporarily accepts to cast to i64 until visitor is switched */
> +            error_report("The number is too large, use qnum_get_uint()");

Awkward.  Can we avoid this somehow?

>          }
>          return qn->u.u64;
>      case QNUM_DOUBLE:
> diff --git a/tests/check-qjson.c b/tests/check-qjson.c
> index c432aebf13..57c2366dc3 100644
> --- a/tests/check-qjson.c
> +++ b/tests/check-qjson.c
> @@ -904,6 +904,33 @@ static void simple_number(void)
>      }
>  }
>  
> +static void large_number(void)
> +{
> +    const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
> +    const char *gtu64 = "18446744073709551616"; /* 2^64 */
> +    QNum *qnum;
> +    QString *str;
> +
> +    qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
> +    g_assert(qnum);
> +    g_assert_cmpuint(qnum_get_uint(qnum, &error_abort),
> +                     ==, 18446744073709551615U);
> +
> +    str = qobject_to_json(QOBJECT(qnum));
> +    g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
> +    QDECREF(str);
> +    QDECREF(qnum);
> +
> +    qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
> +    g_assert(qnum);
> +    g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709551616.0);

       qnum_get_uint(qnum, &err);
       error_free_or_abort(err);

> +
> +    str = qobject_to_json(QOBJECT(qnum));
> +    g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
> +    QDECREF(str);
> +    QDECREF(qnum);
> +}
> +
>  static void float_number(void)
>  {
>      int i;
> @@ -1468,6 +1495,7 @@ int main(int argc, char **argv)
>      g_test_add_func("/literals/string/vararg", vararg_string);
>  
>      g_test_add_func("/literals/number/simple", simple_number);
> +    g_test_add_func("/literals/number/large", large_number);
>      g_test_add_func("/literals/number/float", float_number);
>      g_test_add_func("/literals/number/vararg", vararg_number);
>  
> diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> index 8199546f99..9a22af3d0e 100644
> --- a/tests/check-qnum.c
> +++ b/tests/check-qnum.c
> @@ -107,10 +107,11 @@ static void qnum_get_uint_test(void)
>      error_free_or_abort(&err);
>      QDECREF(qn);
>  
> -    qn = qnum_from_uint(-1ULL);
> -    qnum_get_int(qn, &err);
> -    error_free_or_abort(&err);
> -    QDECREF(qn);
> +    /* temporarily disabled until visitor is switched */
> +    /* qn = qnum_from_uint(-1ULL); */
> +    /* qnum_get_int(qn, &err); */
> +    /* error_free_or_abort(&err); */
> +    /* QDECREF(qn); */

Please use #if 0 to disable code.

>  
>      /* invalid case */
>      qn = qnum_from_double(0.42);
> diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
> index 5df62c4f9e..276a6b4427 100644
> --- a/tests/test-qobject-input-visitor.c
> +++ b/tests/test-qobject-input-visitor.c
> @@ -119,7 +119,6 @@ static void test_visitor_in_int(TestInputVisitorData *data,
>  static void test_visitor_in_uint(TestInputVisitorData *data,
>                                  const void *unused)
>  {
> -    Error *err = NULL;
>      uint64_t res = 0;
>      int value = 42;
>      Visitor *v;
> @@ -136,12 +135,10 @@ static void test_visitor_in_uint(TestInputVisitorData *data,
>      visit_type_uint64(v, NULL, &res, &error_abort);
>      g_assert_cmpuint(res, ==, (uint64_t)-value);
>  
> -    /* BUG: value between INT64_MAX+1 and UINT64_MAX rejected */
> -
>      v = visitor_input_test_init(data, "18446744073709551574");
>  
> -    visit_type_uint64(v, NULL, &res, &err);
> -    error_free_or_abort(&err);
> +    visit_type_uint64(v, NULL, &res, &error_abort);
> +    g_assert_cmpuint(res, ==, 18446744073709551574U);
>  }
>  
>  static void test_visitor_in_int_overflow(TestInputVisitorData *data,

We should systematically cover the integers, in particular the
boundaries (because that's where bugs like to hide):

* Integers in [-2^63,0) can be visited with visit_type_int() and
  visit_type_number().

* Integers in [0,2^63) can be visited with visit_type_int(),
  visit_type_uint64() and visit_type_number().

* Integers in [2^63,2^64) can be visited with visit_type_uint64() and
  visit_type_number().

* Integers outside [-2^63,2^53) can be visited with visit_type_number().

In any case, visit_type_number() loses precision beyond 53 bits.

I'd do this as a separate patch before PATCH 04, so we can see how the
patches affect the test results.

Doing the same for check-qnum.c wouldn't hurt.  Not sure it's worth the
trouble, though.

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

* Re: [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt Marc-André Lureau
@ 2017-05-16 17:31   ` Markus Armbruster
  2017-05-17 16:26     ` Markus Armbruster
  2017-05-30 12:28     ` Marc-André Lureau
  0 siblings, 2 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-16 17:31 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Eric Blake

On the subject: there is no such thing as "QUInt".  I guess you mean
"uint type" (like in PATCH 06's subject).  Could also say "QNUM_U64".

Apropos subject: humor me, and start your subjects with a capital
letter, like this:

    qapi: Update the qobject visitor ...

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Switch to use QNum/uint where appropriate to remove i64 limitation.
>
> The input visitor will cast i64 input to u64 for compatibility
> reasons (existing json QMP client already use negative i64 for large
> u64, and expect an implicit cast in qemu).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qapi/qobject-input-visitor.c        | 13 +++++++++++--
>  qapi/qobject-output-visitor.c       |  3 +--
>  tests/test-qobject-output-visitor.c | 21 ++++++++++++++++-----
>  3 files changed, 28 insertions(+), 9 deletions(-)
>
> diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
> index 785949ebab..72cefcf677 100644
> --- a/qapi/qobject-input-visitor.c
> +++ b/qapi/qobject-input-visitor.c
> @@ -420,9 +420,9 @@ static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
>  static void qobject_input_type_uint64(Visitor *v, const char *name,
>                                        uint64_t *obj, Error **errp)
>  {
> -    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
>      QObjectInputVisitor *qiv = to_qiv(v);
>      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> +    Error *err = NULL;
>      QNum *qnum;
>  
>      if (!qobj) {
> @@ -435,7 +435,16 @@ static void qobject_input_type_uint64(Visitor *v, const char *name,
>          return;
>      }
>  
> -    *obj = qnum_get_int(qnum, errp);
> +    /* XXX: compatibility case, accept negative values as u64 */

What does "XXX" signify?

> +    *obj = qnum_get_int(qnum, &err);
> +

Shouldn't the comment go right here?

> +    if (err) {
> +        error_free(err);
> +        err = NULL;
> +        *obj = qnum_get_uint(qnum, &err);
> +    }
> +
> +    error_propagate(errp, err);
>  }
>  
>  static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
> diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
> index 2ca5093b22..70be84ccb5 100644
> --- a/qapi/qobject-output-visitor.c
> +++ b/qapi/qobject-output-visitor.c
> @@ -150,9 +150,8 @@ static void qobject_output_type_int64(Visitor *v, const char *name,
>  static void qobject_output_type_uint64(Visitor *v, const char *name,
>                                         uint64_t *obj, Error **errp)
>  {
> -    /* FIXME values larger than INT64_MAX become negative */
>      QObjectOutputVisitor *qov = to_qov(v);
> -    qobject_output_add(qov, name, qnum_from_int(*obj));
> +    qobject_output_add(qov, name, qnum_from_uint(*obj));

Before the patch, uint64_t values above INT64_MAX are sent as negative
values, e.g. UINT64_MAX is sent as -1.

After the patch, they are sent unmodified.  Clearly a bug fix, but we
have to consider compatibility issues anyway.  Does libvirt expect large
integers to be sent as negative integers?  Does it cope with this fix
gracefully?  Eric, any idea?

>  }
>  
>  static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
> diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
> index 66a682d5a8..767818e393 100644
> --- a/tests/test-qobject-output-visitor.c
> +++ b/tests/test-qobject-output-visitor.c
> @@ -595,15 +595,26 @@ static void check_native_list(QObject *qobj,
>      qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
>  
>      switch (kind) {
> -    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
> -    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
> -    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
> -    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
>      case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
> -        /* all integer elements in JSON arrays get stored into QNums when
> +        for (i = 0; i < 32; i++) {
> +            QObject *tmp;
> +            QNum *qvalue;
> +            tmp = qlist_peek(qlist);
> +            g_assert(tmp);
> +            qvalue = qobject_to_qnum(tmp);
> +            g_assert_cmpuint(qnum_get_uint(qvalue, &error_abort), ==, i);
> +            qobject_decref(qlist_pop(qlist));
> +        }
> +        break;
> +
> +    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
> +    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
> +    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
> +    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
> +        /* all integer elements in JSON arrays get stored into QInts when
>           * we convert to QObjects, so we can check them all in the same
>           * fashion, so simply fall through here
>           */

Make that "All signed integer ...", and wing both ends of the comment.
Or simply drop the comment.

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

* Re: [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX Marc-André Lureau
@ 2017-05-16 17:35   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-16 17:35 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Now that the visitor has been switch to use qnum_uint, fix the bad
> get_int() to use get_uint() instead. Remove compatibility code.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/i386/acpi-build.c | 2 +-
>  qobject/qnum.c       | 4 ++--
>  tests/check-qnum.c   | 9 ++++-----
>  3 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index ec3ae7fa85..767da5d78e 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -2585,7 +2585,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>      if (!o) {
>          return false;
>      }
> -    mcfg->mcfg_base = qnum_get_int(qobject_to_qnum(o), &error_abort);
> +    mcfg->mcfg_base = qnum_get_uint(qobject_to_qnum(o), &error_abort);
>      qobject_decref(o);
>  
>      o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);

The change makes sense becaise mcfg_base is uint64_t.  But why does it
belong to this patch?

> diff --git a/qobject/qnum.c b/qobject/qnum.c
> index 2f87952db8..be6307accf 100644
> --- a/qobject/qnum.c
> +++ b/qobject/qnum.c
> @@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
>          return qn->u.i64;
>      case QNUM_U64:
>          if (qn->u.u64 > INT64_MAX) {
> -            /* temporarily accepts to cast to i64 until visitor is switched */
> -            error_report("The number is too large, use qnum_get_uint()");
> +            error_setg(errp, "The number is too large, use qnum_get_uint()");
> +            return 0;
>          }
>          return qn->u.u64;
>      case QNUM_DOUBLE:
> diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> index 9a22af3d0e..8199546f99 100644
> --- a/tests/check-qnum.c
> +++ b/tests/check-qnum.c
> @@ -107,11 +107,10 @@ static void qnum_get_uint_test(void)
>      error_free_or_abort(&err);
>      QDECREF(qn);
>  
> -    /* temporarily disabled until visitor is switched */
> -    /* qn = qnum_from_uint(-1ULL); */
> -    /* qnum_get_int(qn, &err); */
> -    /* error_free_or_abort(&err); */
> -    /* QDECREF(qn); */
> +    qn = qnum_from_uint(-1ULL);
> +    qnum_get_int(qn, &err);
> +    error_free_or_abort(&err);
> +    QDECREF(qn);
>  
>      /* invalid case */
>      qn = qnum_from_double(0.42);

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

* Re: [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter Marc-André Lureau
@ 2017-05-16 17:41   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-16 17:41 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/qom/object.h | 23 +++++++++++++++++++++++
>  qom/object.c         | 33 +++++++++++++++++++++++++++++++++
>  2 files changed, 56 insertions(+)
>
> diff --git a/include/qom/object.h b/include/qom/object.h
> index cd0f412ce9..abaeb8cf4e 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -1094,6 +1094,29 @@ int64_t object_property_get_int(Object *obj, const char *name,
>                                  Error **errp);
>  
>  /**
> + * object_property_set_uint:
> + * @value: the value to be written to the property
> + * @name: the name of the property
> + * @errp: returns an error if this function fails
> + *
> + * Writes an unsigned integer value to a property.
> + */
> +void object_property_set_uint(Object *obj, uint64_t value,
> +                              const char *name, Error **errp);
> +
> +/**
> + * object_property_get_uint:
> + * @obj: the object
> + * @name: the name of the property
> + * @errp: returns an error if this function fails
> + *
> + * Returns: the value of the property, converted to an unsigned integer, or 0
> + * an error occurs (including when the property value is not an integer).
> + */
> +uint64_t object_property_get_uint(Object *obj, const char *name,
> +                                  Error **errp);
> +
> +/**
>   * object_property_get_enum:
>   * @obj: the object
>   * @name: the name of the property
> diff --git a/qom/object.c b/qom/object.c
> index c1644dbcb7..a9259e330d 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -1221,6 +1221,39 @@ int64_t object_property_get_int(Object *obj, const char *name,
>      return retval;
>  }
>  
> +void object_property_set_uint(Object *obj, uint64_t value,
> +                             const char *name, Error **errp)
> +{
> +    QNum *qn = qnum_from_uint(value);

Please call the variable @qnum, to match object_property_set_int() and
object_property_get_uint().

Blank line here.

> +    object_property_set_qobject(obj, QOBJECT(qn), name, errp);
> +    QDECREF(qn);
> +}
> +
> +uint64_t object_property_get_uint(Object *obj, const char *name,
> +                                  Error **errp)
> +{
> +    QObject *ret = object_property_get_qobject(obj, name, errp);
> +    Error *err = NULL;
> +    QNum *qnum;
> +    uint64_t retval;
> +
> +    if (!ret) {
> +        return 0;
> +    }
> +    qnum = qobject_to_qnum(ret);
> +    if (qnum) {
> +        retval = qnum_get_uint(qnum, &err);
> +    }
> +
> +    if (!qnum || err) {
> +        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
> +        retval = 0;
> +    }
> +
> +    qobject_decref(ret);
> +    return retval;
> +}
> +
>  typedef struct EnumProperty {
>      const char * const *strings;
>      int (*get)(Object *, Error **);

With the nits touched up:
Reviewed-by: Markus Armbruster <armbru@redhat.com>

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

* Re: [Qemu-devel] [PATCH 11/17] object: use more specific property type names
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 11/17] object: use more specific property type names Marc-André Lureau
@ 2017-05-17  8:49   ` Markus Armbruster
  2017-05-30 13:58     ` Marc-André Lureau
  0 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-17  8:49 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Use the actual unsigned integer type name (this should't break since
> property type aren't directly accessed from outside it seems).

I'm not sure I understand the parenthesis.  Do you mean changing the
type names is safe because they're used only in a certain way?  Which
way?

How did you find the names that need fixing?

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  backends/cryptodev.c |  2 +-
>  hw/pci-host/piix.c   |  8 ++++----
>  hw/pci-host/q35.c    | 10 +++++-----
>  hw/ppc/pnv.c         |  2 +-
>  net/dump.c           |  2 +-
>  net/filter-buffer.c  |  2 +-
>  6 files changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/backends/cryptodev.c b/backends/cryptodev.c
> index 832f056266..1764c179fe 100644
> --- a/backends/cryptodev.c
> +++ b/backends/cryptodev.c
> @@ -222,7 +222,7 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc, Error **errp)
>  
>  static void cryptodev_backend_instance_init(Object *obj)
>  {
> -    object_property_add(obj, "queues", "int",
> +    object_property_add(obj, "queues", "uint32",
>                            cryptodev_backend_get_queues,
>                            cryptodev_backend_set_queues,
>                            NULL, NULL, NULL);

Correct, because the callbacks access struct CryptoDevBackendPeers
member queues, which is uint32_t.

The callbacks pass a local variable instead of the struct member to the
visitor.  Problematic, because it weakens the type checking we get from
the compiler.  Let's tighten it up:

   static void
   cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
                                void *opaque, Error **errp)
   {
       CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
  -    uint32_t value = backend->conf.peers.queues;

  -    visit_type_uint32(v, name, &value, errp);
  +    visit_type_uint32(v, name, &backend->conf.peers.queues, errp);
   }

   static void
   cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
                                void *opaque, Error **errp)
   {
       CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
       Error *local_err = NULL;
  -    uint32_t value;

  -    visit_type_uint32(v, name, &value, &local_err);
  +    visit_type_uint32(v, name, &backend->conf.peers.queues, &local_err);
       if (local_err) {
           goto out;
       }
  -    if (!value) {
  +    if (!backend->conf.peers.queues) {
           error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
  -                   PRIu32 "'", object_get_typename(obj), name, value);
  +                   PRIu32 "'", object_get_typename(obj), name,
  +                   backend->conf.peers.queues);
  -        goto out;
       }
  -    backend->conf.peers.queues = value;
  -out:
       error_propagate(errp, local_err);
   }

If we need to preserve backend->conf.peers.queue on an attempt to set it
to zero, things get a bit more complicated.  But having the compiler
enforce the visitor matches the member type exactly is worth it, in my
opinion.

Separate patch, not necessarily in this series.

> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index f9218aa952..9aed6225bf 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -279,19 +279,19 @@ static void i440fx_pcihost_initfn(Object *obj)
>      memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
>                            "pci-conf-data", 4);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
>                          i440fx_pcihost_get_pci_hole_start,
>                          NULL, NULL, NULL, NULL);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
>                          i440fx_pcihost_get_pci_hole_end,
>                          NULL, NULL, NULL, NULL);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
>                          i440fx_pcihost_get_pci_hole64_start,
>                          NULL, NULL, NULL, NULL);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
>                          i440fx_pcihost_get_pci_hole64_end,
>                          NULL, NULL, NULL, NULL);
>  }

These look good.  The underlying values are 64 bits, but the 32 bit
callbacks assert they fit into 32.

> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
> index 344f77b10c..5438be8253 100644
> --- a/hw/pci-host/q35.c
> +++ b/hw/pci-host/q35.c
> @@ -176,23 +176,23 @@ static void q35_host_initfn(Object *obj)
>      qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
>      qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
>                          q35_host_get_pci_hole_start,
>                          NULL, NULL, NULL, NULL);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
>                          q35_host_get_pci_hole_end,
>                          NULL, NULL, NULL, NULL);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
>                          q35_host_get_pci_hole64_start,
>                          NULL, NULL, NULL, NULL);
>  
> -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
> +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
>                          q35_host_get_pci_hole64_end,
>                          NULL, NULL, NULL, NULL);

Likewise.

>  
> -    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
> +    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint32",
>                          q35_host_get_mmcfg_size,
>                          NULL, NULL, NULL, NULL);

This one leads to a bug, I think:

   static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
                                       void *opaque, Error **errp)
   {
       PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
       uint32_t value = e->size;

       visit_type_uint32(v, name, &value, errp);
   }

e->size is hwaddr, i.e. uint64_t.  We silently truncate.

Demonstrates that the detour through a separate variable breeds bugs and
should be avoided.

Suggested fix:

   static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
                                       void *opaque, Error **errp)
   {
       PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
  -    uint32_t value = e->size;

  -    visit_type_uint64(v, name, &value, errp);
  +    visit_type_uint64(v, name, &e->size, errp);
   }

You then have to change the type name to "uint64" instead of "uint32",
of course.

>  
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index d4bcdb027f..a964354081 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -1110,7 +1110,7 @@ static void powernv_machine_initfn(Object *obj)
>  
>  static void powernv_machine_class_props_init(ObjectClass *oc)
>  {
> -    object_class_property_add(oc, "num-chips", "uint32_t",
> +    object_class_property_add(oc, "num-chips", "uint32",
>                                pnv_get_num_chips, pnv_set_num_chips,
>                                NULL, NULL, NULL);
>      object_class_property_set_description(oc, "num-chips",

Looks good.

> diff --git a/net/dump.c b/net/dump.c
> index 89a149b5dd..7f4d3fda52 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -325,7 +325,7 @@ static void filter_dump_instance_init(Object *obj)
>  
>      nfds->maxlen = 65536;
>  
> -    object_property_add(obj, "maxlen", "int", filter_dump_get_maxlen,
> +    object_property_add(obj, "maxlen", "uint32", filter_dump_get_maxlen,
>                          filter_dump_set_maxlen, NULL, NULL, NULL);
>      object_property_add_str(obj, "file", file_dump_get_filename,
>                              file_dump_set_filename, NULL);

Same type checking weakness as in cryptodev.c.

> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> index cc6bd94445..9ce96aaa35 100644
> --- a/net/filter-buffer.c
> +++ b/net/filter-buffer.c
> @@ -191,7 +191,7 @@ out:
>  
>  static void filter_buffer_init(Object *obj)
>  {
> -    object_property_add(obj, "interval", "int",
> +    object_property_add(obj, "interval", "uint32",
>                          filter_buffer_get_interval,
>                          filter_buffer_set_interval, NULL, NULL, NULL);
>  }

Likeise.

Aside: I dislike having to define setters and getters for everything in
QOM.  It's flexible, but verbose and error-prone when the flexibility
isn't actually needed.

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

* Re: [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate Marc-André Lureau
@ 2017-05-17 11:09   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-17 11:09 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Use unsigned type for various properties.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/hw/qdev-core.h       |  5 +++-
>  include/hw/qdev-properties.h | 67 ++++++++++++++++++++++++++------------------
>  hw/block/fdc.c               | 54 +++++++++++++++++------------------
>  hw/core/qdev-properties.c    |  8 +++---
>  hw/core/qdev.c               | 24 ++++++++++------
>  hw/net/e1000e.c              | 14 ++++-----
>  6 files changed, 96 insertions(+), 76 deletions(-)
>
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 0f21a500cd..ac10458650 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -225,7 +225,10 @@ struct Property {
>      PropertyInfo *info;
>      ptrdiff_t    offset;
>      uint8_t      bitnr;
> -    int64_t      defval;
> +    union {
> +        int64_t i;
> +        uint64_t u;
> +    } defval;

Could also simply make it uint64_t.  Converting a negative integer to
uint64_t adds 2^64 (See ISO/IEC 9899:1999 §6.3.1.3).  Converting back is
implementation-defined (ibid.), but in practice it yields the same
signed integer (loads of code relies on that).  Matter of taste.

>      int          arrayoffset;
>      PropertyInfo *arrayinfo;
>      int          arrayfieldsize;
> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
> index 16d5d0629b..ca9c550fa3 100644
> --- a/include/hw/qdev-properties.h
> +++ b/include/hw/qdev-properties.h
> @@ -37,36 +37,47 @@ extern PropertyInfo qdev_prop_arraylen;
>          .offset    = offsetof(_state, _field)                    \
>              + type_check(_type, typeof_field(_state, _field)),   \
>          }
> -#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
> +
> +#define DEFINE_PROP_INT(_name, _state, _field, _defval, _prop, _type) { \
>          .name      = (_name),                                           \
>          .info      = &(_prop),                                          \
>          .offset    = offsetof(_state, _field)                           \
>              + type_check(_type,typeof_field(_state, _field)),           \
> -        .defval    = (_type)_defval,                                    \
> +        .defval.i  = (_type)_defval,                                    \
>          }

Doing the rename in a separate patch would make review a bit easier.
Not worth splitting now, but consider it next time.

> -#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
> -        .name      = (_name),                                    \
> -        .info      = &(qdev_prop_bit),                           \
> -        .bitnr    = (_bit),                                      \
> -        .offset    = offsetof(_state, _field)                    \
> -            + type_check(uint32_t,typeof_field(_state, _field)), \
> -        .defval    = (bool)_defval,                              \
> +
> +#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {         \
> +        .name      = (_name),                                           \
> +        .info      = &(qdev_prop_bit),                                  \
> +        .bitnr    = (_bit),                                             \
> +        .offset    = offsetof(_state, _field)                           \
> +            + type_check(uint32_t, typeof_field(_state, _field)),        \
> +        .defval.u   = (bool)_defval,                                    \
>          }
> +
> +#define DEFINE_PROP_UINT(_name, _state, _field, _defval, _prop, _type) { \
> +        .name      = (_name),                                           \
> +        .info      = &(_prop),                                          \
> +        .offset    = offsetof(_state, _field)                           \
> +            + type_check(_type, typeof_field(_state, _field)),          \
> +        .defval.u  = (_type)_defval,                                    \
> +        }
> +
>  #define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) {       \
>          .name      = (_name),                                           \
>          .info      = &(qdev_prop_bit64),                                \
>          .bitnr    = (_bit),                                             \
>          .offset    = offsetof(_state, _field)                           \
>              + type_check(uint64_t, typeof_field(_state, _field)),       \
> -        .defval    = (bool)_defval,                                     \
> +        .defval.u  = (bool)_defval,                                     \
>          }
>  
> -#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) {       \
> -        .name      = (_name),                                    \
> -        .info      = &(qdev_prop_bool),                          \
> -        .offset    = offsetof(_state, _field)                    \
> -            + type_check(bool, typeof_field(_state, _field)),    \
> -        .defval    = (bool)_defval,                              \
> +#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) {      \
> +        .name      = (_name),                                   \
> +        .info      = &(qdev_prop_bool),                         \
> +        .offset    = offsetof(_state, _field)                   \
> +            + type_check(bool, typeof_field(_state, _field)),   \
> +        .defval.u    = (bool)_defval,                           \
>          }
>  
>  #define PROP_ARRAY_LEN_PREFIX "len-"
> @@ -107,19 +118,19 @@ extern PropertyInfo qdev_prop_arraylen;
>          }
>  
>  #define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
> +    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
>  #define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
> +    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
>  #define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
> +    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
>  #define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
> +    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
>  #define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
> +    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
>  #define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_size, uint64_t)
> +    DEFINE_PROP_UINT(_n, _s, _f, _d, qdev_prop_size, uint64_t)
>  #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d)                   \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
> +    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
>  
>  /*
>   * Please avoid pointer properties.  If you must use them, you must
> @@ -153,17 +164,17 @@ extern PropertyInfo qdev_prop_arraylen;
>  #define DEFINE_PROP_MACADDR(_n, _s, _f)         \
>      DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
>  #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
> +    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
>  #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
> +    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
>                          LostTickPolicy)
>  #define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
> +    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
>                          BlockdevOnError)
>  #define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
> +    DEFINE_PROP_INT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
>  #define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \
> -    DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
> +    DEFINE_PROP_UINT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
>  #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
>      DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
>  
> diff --git a/hw/block/fdc.c b/hw/block/fdc.c
> index 2e629b398b..07ce4a0d20 100644
> --- a/hw/block/fdc.c
> +++ b/hw/block/fdc.c
> @@ -511,9 +511,9 @@ typedef struct FloppyDrive {
>  static Property floppy_drive_properties[] = {
>      DEFINE_PROP_UINT32("unit", FloppyDrive, unit, -1),
>      DEFINE_BLOCK_PROPERTIES(FloppyDrive, conf),
> -    DEFINE_PROP_DEFAULT("drive-type", FloppyDrive, type,
> -                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> +    DEFINE_PROP_INT("drive-type", FloppyDrive, type,
> +                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -2805,15 +2805,15 @@ static Property isa_fdc_properties[] = {
>      DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.qdev_for_drives[1].blk),
>      DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
>                      0, true),
> -    DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
> -                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> -    DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
> -                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> -    DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
> -                        FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> +    DEFINE_PROP_INT("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
> +                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
> +    DEFINE_PROP_INT("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
> +                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
> +    DEFINE_PROP_INT("fallback", FDCtrlISABus, state.fallback,
> +                    FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -2862,15 +2862,15 @@ static const VMStateDescription vmstate_sysbus_fdc ={
>  static Property sysbus_fdc_properties[] = {
>      DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.qdev_for_drives[0].blk),
>      DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.qdev_for_drives[1].blk),
> -    DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
> -                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> -    DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
> -                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> -    DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
> -                        FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> +    DEFINE_PROP_INT("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
> +                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
> +    DEFINE_PROP_INT("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
> +                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
> +    DEFINE_PROP_INT("fallback", FDCtrlISABus, state.fallback,
> +                    FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -2891,12 +2891,12 @@ static const TypeInfo sysbus_fdc_info = {
>  
>  static Property sun4m_fdc_properties[] = {
>      DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.qdev_for_drives[0].blk),
> -    DEFINE_PROP_DEFAULT("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
> -                        FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> -    DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
> -                        FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
> -                        FloppyDriveType),
> +    DEFINE_PROP_INT("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
> +                    FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
> +    DEFINE_PROP_INT("fallback", FDCtrlISABus, state.fallback,
> +                    FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
> +                    FloppyDriveType),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
> index fa3617db2d..f87327b132 100644
> --- a/hw/core/qdev-properties.c
> +++ b/hw/core/qdev-properties.c
> @@ -982,17 +982,17 @@ void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
>  
>  void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
>  {
> -    object_property_set_int(OBJECT(dev), value, name, &error_abort);
> +    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
>  }
>  
>  void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
>  {
> -    object_property_set_int(OBJECT(dev), value, name, &error_abort);
> +    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
>  }
>  
>  void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
>  {
> -    object_property_set_int(OBJECT(dev), value, name, &error_abort);
> +    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
>  }
>  
>  void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
> @@ -1002,7 +1002,7 @@ void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
>  
>  void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
>  {
> -    object_property_set_int(OBJECT(dev), value, name, &error_abort);
> +    object_property_set_uint(OBJECT(dev), value, name, &error_abort);
>  }
>  
>  void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 83b0297755..b9313546f7 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -764,17 +764,21 @@ static bool prop_info_is_bool(const PropertyInfo *info)
>  
>  static bool prop_info_is_int(const PropertyInfo *info)
>  {
> +    return info == &qdev_prop_int32
> +        || info == &qdev_prop_pci_devfn
> +        || info == &qdev_prop_on_off_auto
> +        || info == &qdev_prop_losttickpolicy
> +        || info == &qdev_prop_blockdev_on_error
> +        || info == &qdev_prop_bios_chs_trans;
> +}
> +
> +static bool prop_info_is_uint(const PropertyInfo *info)
> +{
>      return info == &qdev_prop_uint8
>          || info == &qdev_prop_uint16
>          || info == &qdev_prop_uint32
> -        || info == &qdev_prop_int32
>          || info == &qdev_prop_uint64
>          || info == &qdev_prop_size
> -        || info == &qdev_prop_pci_devfn
> -        || info == &qdev_prop_on_off_auto
> -        || info == &qdev_prop_losttickpolicy
> -        || info == &qdev_prop_blockdev_on_error
> -        || info == &qdev_prop_bios_chs_trans
>          || info == &qdev_prop_blocksize
>          || info == &qdev_prop_arraylen;
>  }
> @@ -819,12 +823,14 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
>                                      &error_abort);
>  
>      if (prop_info_is_bool(prop->info)) {
> -        object_property_set_bool(obj, prop->defval, prop->name, &error_abort);
> +        object_property_set_bool(obj, prop->defval.u, prop->name, &error_abort);
>      } else if (prop->info->enum_table) {
> -        object_property_set_str(obj, prop->info->enum_table[prop->defval],
> +        object_property_set_str(obj, prop->info->enum_table[prop->defval.i],
>                                  prop->name, &error_abort);
>      } else if (prop_info_is_int(prop->info)) {
> -        object_property_set_int(obj, prop->defval, prop->name, &error_abort);
> +        object_property_set_int(obj, prop->defval.i, prop->name, &error_abort);
> +    } else if (prop_info_is_uint(prop->info)) {
> +        object_property_set_uint(obj, prop->defval.u, prop->name, &error_abort);
>      }
>  }
>  
> diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
> index 6e234938db..4e4cc9b52f 100644
> --- a/hw/net/e1000e.c
> +++ b/hw/net/e1000e.c
> @@ -645,13 +645,13 @@ static PropertyInfo e1000e_prop_disable_vnet,
>  
>  static Property e1000e_properties[] = {
>      DEFINE_NIC_PROPERTIES(E1000EState, conf),
> -    DEFINE_PROP_DEFAULT("disable_vnet_hdr", E1000EState, disable_vnet, false,
> -                        e1000e_prop_disable_vnet, bool),
> -    DEFINE_PROP_DEFAULT("subsys_ven", E1000EState, subsys_ven,
> -                        PCI_VENDOR_ID_INTEL,
> -                        e1000e_prop_subsys_ven, uint16_t),
> -    DEFINE_PROP_DEFAULT("subsys", E1000EState, subsys, 0,
> -                        e1000e_prop_subsys, uint16_t),
> +    DEFINE_PROP_INT("disable_vnet_hdr", E1000EState, disable_vnet, false,
> +                    e1000e_prop_disable_vnet, bool),
> +    DEFINE_PROP_INT("subsys_ven", E1000EState, subsys_ven,
> +                    PCI_VENDOR_ID_INTEL,
> +                    e1000e_prop_subsys_ven, uint16_t),
> +    DEFINE_PROP_INT("subsys", E1000EState, subsys, 0,
> +                    e1000e_prop_subsys, uint16_t),
>      DEFINE_PROP_END_OF_LIST(),
>  };

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

* Re: [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt
  2017-05-16 17:31   ` Markus Armbruster
@ 2017-05-17 16:26     ` Markus Armbruster
  2017-05-30 12:28     ` Marc-André Lureau
  1 sibling, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-17 16:26 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Eric Blake

Markus Armbruster <armbru@redhat.com> writes:

> On the subject: there is no such thing as "QUInt".  I guess you mean
> "uint type" (like in PATCH 06's subject).  Could also say "QNUM_U64".
>
> Apropos subject: humor me, and start your subjects with a capital
> letter, like this:
>
>     qapi: Update the qobject visitor ...
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Switch to use QNum/uint where appropriate to remove i64 limitation.
>>
>> The input visitor will cast i64 input to u64 for compatibility
>> reasons (existing json QMP client already use negative i64 for large
>> u64, and expect an implicit cast in qemu).
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  qapi/qobject-input-visitor.c        | 13 +++++++++++--
>>  qapi/qobject-output-visitor.c       |  3 +--
>>  tests/test-qobject-output-visitor.c | 21 ++++++++++++++++-----
>>  3 files changed, 28 insertions(+), 9 deletions(-)
>>
>> diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
>> index 785949ebab..72cefcf677 100644
>> --- a/qapi/qobject-input-visitor.c
>> +++ b/qapi/qobject-input-visitor.c
>> @@ -420,9 +420,9 @@ static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
>>  static void qobject_input_type_uint64(Visitor *v, const char *name,
>>                                        uint64_t *obj, Error **errp)
>>  {
>> -    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
>>      QObjectInputVisitor *qiv = to_qiv(v);
>>      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
>> +    Error *err = NULL;
>>      QNum *qnum;
>>  
>>      if (!qobj) {
>> @@ -435,7 +435,16 @@ static void qobject_input_type_uint64(Visitor *v, const char *name,
>>          return;
>>      }
>>  
>> -    *obj = qnum_get_int(qnum, errp);
>> +    /* XXX: compatibility case, accept negative values as u64 */
>
> What does "XXX" signify?
>
>> +    *obj = qnum_get_int(qnum, &err);
>> +
>
> Shouldn't the comment go right here?

Nope, I misread the code.

We first try qnum_get_int().  Works for integers between -2^63 and
2^63-1.  The assignment to *obj adds 2^64 to negative ones.

When it doesn't work, we try qnum_get_uint().  Works for integers
between 0 and 2^64-1, but only integers between 2^63 and 2^64-1 can
occur.

>> +    if (err) {
>> +        error_free(err);
>> +        err = NULL;
>> +        *obj = qnum_get_uint(qnum, &err);
>> +    }
>> +
>> +    error_propagate(errp, err);
>>  }

Let's do this the other way round:

    *obj = qnum_get_uint(qnum, &err);
    if (err) {
        /* Need to accept negative values for backward compatibility */
        error_free(err);
        err = NULL;
        *obj = qnum_get_int(qnum, &err);
    }

    error_propagate(errp, err);

This way, the backward compatibility code is entirely contained in the
conditional.

It's also how I misread the code :)

[...]

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

* Re: [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type Marc-André Lureau
@ 2017-05-17 17:42   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-17 17:42 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Based on underlying property type, use the appropriate getters/setters.

How did you find the ones that need changing?

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/i386/acpi-build.c      | 12 ++++++------
>  hw/pci-host/gpex.c        |  2 +-
>  hw/pci-host/q35.c         |  2 +-
>  hw/pci-host/xilinx-pcie.c |  2 +-
>  target/i386/cpu.c         |  2 +-
>  5 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 767da5d78e..1707fae9bf 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -149,21 +149,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_int(qobject_to_qnum(o), &error_abort);
> +        pm->s3_disabled = qnum_get_uint(qobject_to_qnum(o), &error_abort);
>      } 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_int(qobject_to_qnum(o), &error_abort);
> +        pm->s4_disabled = qnum_get_uint(qobject_to_qnum(o), &error_abort);
>      } 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_int(qobject_to_qnum(o), &error_abort);
> +        pm->s4_val = qnum_get_uint(qobject_to_qnum(o), &error_abort);
>      } else {
>          pm->s4_val = false;
>      }

The getter and setter of properties ACPI_PM_PROP_S3_DISABLED,
ACPI_PM_PROP_S4_DISABLED and ACPI_PM_PROP_S4_VAL use visit_type_uint8().

object_property_get_qobject() uses this getter below the hood with a
QObject output visitor, to get the value into a QObject.  Since the
getter uses visit_type_uint8(), the QObject is a QNum with QNUM_U64.

The appropriate way to extract the QNum's value is qnum_get_uint().

Okay.

> @@ -499,7 +499,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) {
> -        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
> +        uint64_t bsel_val = qnum_get_uint(qobject_to_qnum(bsel), &error_abort);
>  
>          aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
>          notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);

Similar argument, only slightly more tricky, as the getter dereferences
a pointer.

> @@ -609,7 +609,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) {
> -        int64_t bsel_val = qnum_get_int(qobject_to_qnum(bsel), &error_abort);
> +        uint64_t bsel_val = qnum_get_uint(qobject_to_qnum(bsel), &error_abort);
>          aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
>          aml_append(method,
>              aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)

Likewise (@bsel is the same as above).

> @@ -2590,7 +2590,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>  
>      o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
>      assert(o);
> -    mcfg->mcfg_size = qnum_get_int(qobject_to_qnum(o), &error_abort);
> +    mcfg->mcfg_size = qnum_get_uint(qobject_to_qnum(o), &error_abort);
>      qobject_decref(o);
>      return true;
>  }

Similar argument.

I suspect the hunk I challenged in PATCH 09 actually belongs here.

> diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
> index 66055ee5cc..8d3a64008c 100644
> --- a/hw/pci-host/gpex.c
> +++ b/hw/pci-host/gpex.c
> @@ -94,7 +94,7 @@ static void gpex_host_initfn(Object *obj)
>  
>      object_initialize(root, sizeof(*root), TYPE_GPEX_ROOT_DEVICE);
>      object_property_add_child(obj, "gpex_root", OBJECT(root), NULL);
> -    qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
> +    qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
>      qdev_prop_set_bit(DEVICE(root), "multifunction", false);
>  }
>  

"addr" is a property of TYPE_PCI_DEVICE, defined with
DEFINE_PROP_PCI_DEVFN().  It's int32_t, even though only 8 bits are
used.  Okay.

> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
> index 5438be8253..3cbe8cfcea 100644
> --- a/hw/pci-host/q35.c
> +++ b/hw/pci-host/q35.c
> @@ -173,7 +173,7 @@ static void q35_host_initfn(Object *obj)
>  
>      object_initialize(&s->mch, sizeof(s->mch), TYPE_MCH_PCI_DEVICE);
>      object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
> -    qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
> +    qdev_prop_set_int32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
>      qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
>  
>      object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",

Likewise.

> diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c
> index 8b71e2d950..461ed41151 100644
> --- a/hw/pci-host/xilinx-pcie.c
> +++ b/hw/pci-host/xilinx-pcie.c
> @@ -150,7 +150,7 @@ static void xilinx_pcie_host_init(Object *obj)
>  
>      object_initialize(root, sizeof(*root), TYPE_XILINX_PCIE_ROOT);
>      object_property_add_child(obj, "root", OBJECT(root), NULL);
> -    qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
> +    qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
>      qdev_prop_set_bit(DEVICE(root), "multifunction", false);
>  }
>  

Likewise.

> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 1e8a5b55c0..5bb8131bb8 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -3191,7 +3191,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
>                                OBJECT(cpu->apic_state), &error_abort);
>      object_unref(OBJECT(cpu->apic_state));
>  
> -    qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
> +    qdev_prop_set_int32(cpu->apic_state, "id", cpu->apic_id);
>      /* TODO: convert to link<> */
>      apic = APIC_COMMON(cpu->apic_state);
>      apic->cpu = cpu;

This one's a bit of a mess.

The getter and setter of TYPE_APIC_COMMON property "id" are
apic_common_get_id() and apic_common_set_id().

apic_common_get_id() reads either APICCommonState member uint32_t
initial_apic_id or uint8_t id into an int64_t local variable.  It then
passes this variable to visit_type_int().

apic_common_set_id() uses visit_type_int() to read the value into a
local variable, which it then assigns both to initial_apic_id and id.

While the state backing the property is two unsigned members, 8 and 32
bits wide, the actual visitor is 64 bits signed.

cpu->apic_id is uint32_t.

qdev_prop_set_uint32() isn't really wrong, because any uint32_t value is
also a valid int64_t value.

qdev_prop_set_int32() is implicitly converts cpu->apic_id from uint32_t
to int32_t.  Perhaps that's even okay, but I don't care, I want this
mess cleaned up :)

Two possible ways to clean up:

1. Use qdev_prop_set_int().  Then the members get converted to
int64_t and back.  Looks safe to me.

2. Change getter and setter to use visit_type_uint32().  Then
everything's uint32_t, except for @id.

I prefer 2.

This getter and setter business drives me nuts.  Them mixing up
signedness and width doesn't help.

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

* Re: [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type Marc-André Lureau
  2017-05-13 20:49   ` Philippe Mathieu-Daudé
@ 2017-05-18 12:57   ` Markus Armbruster
  2017-05-31 11:10     ` Marc-André Lureau
  1 sibling, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-18 12:57 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Use a more specific bool type.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Why doesn't this run afoul backward compatibility?  To answer the
question, we need to enumerate affected external interfaces.

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

* Re: [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate Marc-André Lureau
@ 2017-05-18 15:20   ` Markus Armbruster
  2017-05-31 12:22     ` Marc-André Lureau
  0 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-18 15:20 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> All those property usages are associated with unsigned integers, so use
> appropriate getter/setter.

"Usages"?  I think this is a question of whether the property value is
signed or unsigned.  I guess "those properties are" would work.

How did you find the ones that need changing?

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/hw/isa/isa.h         |  2 +-
>  hw/acpi/memory_hotplug.c     | 10 ++++----
>  hw/acpi/nvdimm.c             | 10 ++++----
>  hw/acpi/pcihp.c              |  6 ++---
>  hw/arm/aspeed.c              |  4 ++--
>  hw/arm/bcm2835_peripherals.c |  9 ++++----
>  hw/arm/raspi.c               |  4 ++--
>  hw/core/platform-bus.c       |  2 +-
>  hw/i386/acpi-build.c         | 55 ++++++++++++++++++++++----------------------
>  hw/i386/pc.c                 |  6 ++---
>  hw/i386/xen/xen-hvm.c        |  6 ++---
>  hw/intc/arm_gicv3_common.c   |  2 +-
>  hw/mem/pc-dimm.c             |  5 ++--
>  hw/misc/auxbus.c             |  2 +-
>  hw/misc/pvpanic.c            |  2 +-
>  hw/ppc/pnv_core.c            |  2 +-
>  hw/ppc/spapr.c               |  8 ++++---
>  numa.c                       |  6 ++---
>  target/i386/cpu.c            |  4 ++--
>  ui/console.c                 |  4 ++--
>  20 files changed, 77 insertions(+), 72 deletions(-)
>
> diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
> index c2fdd70cdc..95593408ef 100644
> --- a/include/hw/isa/isa.h
> +++ b/include/hw/isa/isa.h
> @@ -29,7 +29,7 @@ static inline uint16_t applesmc_port(void)
>      Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
>  
>      if (obj) {
> -        return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL);
> +        return object_property_get_uint(obj, APPLESMC_PROP_IO_BASE, NULL);
>      }
>      return 0;
>  }

The property is defined with DEFINE_PROP_UINT32().  Okay.

> diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
> index 210073d283..db3c89ceab 100644
> --- a/hw/acpi/memory_hotplug.c
> +++ b/hw/acpi/memory_hotplug.c
> @@ -83,11 +83,12 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
>      o = OBJECT(mdev->dimm);
>      switch (addr) {
>      case 0x0: /* Lo part of phys address where DIMM is mapped */
> -        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) : 0;
> +        val = o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) : 0;
>          trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
>          break;
>      case 0x4: /* Hi part of phys address where DIMM is mapped */
> -        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
> +        val =
> +            o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
>          trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
>          break;
>      case 0x8: /* Lo part of DIMM size */

TYPE_PC_DIMM's property PC_DIMM_ADDR_PROP is defined with
DEFINE_PROP_UINT64().  Okay.

> @@ -95,11 +96,12 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
>          trace_mhp_acpi_read_size_lo(mem_st->selector, val);
>          break;
>      case 0xc: /* Hi part of DIMM size */
> -        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
> +        val =
> +            o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;

pc_dimm_get_size() uses visit_type_int().  Does that need a matching
update?

>          trace_mhp_acpi_read_size_hi(mem_st->selector, val);
>          break;
>      case 0x10: /* node proximity for _PXM method */
> -        val = o ? object_property_get_int(o, PC_DIMM_NODE_PROP, NULL) : 0;
> +        val = o ? object_property_get_uint(o, PC_DIMM_NODE_PROP, NULL) : 0;
>          trace_mhp_acpi_read_pxm(mem_st->selector, val);
>          break;
>      case 0x14: /* pack and return is_* fields */

TYPE_PC_DIMM's property PC_DIMM_NODE_PROP is defined with
DEFINE_PROP_UINT32().  Okay.

> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 8e7d6ec034..e57027149d 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -236,14 +236,14 @@ static void
>  nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
>  {
>      NvdimmNfitSpa *nfit_spa;
> -    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
> -                                            NULL);
> +    uint64_t addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP,
> +                                             NULL);
>      uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
>                                              NULL);

Here, you leave PC_DIMM_SIZE_PROP alone.  The code gets it signed and
assigns it to unsigned.  Needs cleanup.

> -    uint32_t node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
> -                                            NULL);
> +    uint32_t node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
> +                                             NULL);
>      int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> -                                            NULL);
> +                                       NULL);
>  
>      nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
>  

More of the same.

> diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
> index 3a531a4416..c420a388ea 100644
> --- a/hw/acpi/pcihp.c
> +++ b/hw/acpi/pcihp.c
> @@ -62,10 +62,10 @@ typedef struct AcpiPciHpFind {
>  static int acpi_pcihp_get_bsel(PCIBus *bus)
>  {
>      Error *local_err = NULL;
> -    int64_t bsel = object_property_get_int(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
> -                                           &local_err);
> +    uint64_t bsel = object_property_get_uint(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
> +                                             &local_err);
>  
> -    if (local_err || bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
> +    if (local_err || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
>          if (local_err) {
>              error_free(local_err);
>          }

Haven't I seen ACPI_PCIHP_PROP_BSEL before?  Yes, in PATCH 13.  I think
splitting along subsystems rather than functions changed would be easier
to review, because the what the reviewer needs to understand is not so
much the functions but the underlying properties.

> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 283c038814..4af422909f 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -187,8 +187,8 @@ static void aspeed_board_init(MachineState *machine,
>       * Allocate RAM after the memory controller has checked the size
>       * was valid. If not, a default value is used.
>       */
> -    ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
> -                                       &error_abort);
> +    ram_size = object_property_get_uint(OBJECT(&bmc->soc), "ram-size",
> +                                        &error_abort);

The assignment to global ram_size looks nasty, but that particular
nastiness is outside this patch's scope.

If I understand the aspeed code correctly, then this property is an
alias for device TYPE_ASPEED_SDMC's property "ram-size", which is
defined with DEFINE_PROP_UINT64().  Okay.

However, a few lines further up, we have:

       object_property_set_int(OBJECT(&bmc->soc), ram_size, "ram-size",
                              &error_abort);

The two should be kept consistent.

Adds urgency to my question how you found the ones that need changing.

>  
>      memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
>      memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
> diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
> index 369ef1e3bd..b168c6f83e 100644
> --- a/hw/arm/bcm2835_peripherals.c
> +++ b/hw/arm/bcm2835_peripherals.c
> @@ -126,7 +126,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
>      Object *obj;
>      MemoryRegion *ram;
>      Error *err = NULL;
> -    uint32_t ram_size, vcram_size;
> +    uint64_t ram_size, vcram_size;
>      int n;
>  
>      obj = object_property_get_link(OBJECT(dev), "ram", &err);
> @@ -208,15 +208,14 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
>                                 INTERRUPT_ARM_MAILBOX));
>  
>      /* Framebuffer */
> -    vcram_size = (uint32_t)object_property_get_int(OBJECT(s), "vcram-size",
> -                                                   &err);
> +    vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err);

This one appears to be an alias of TYPE_BCM2835_FB's property
"vcram-size", which is defined with DEFINE_PROP_UINT32().  Okay.

>      if (err) {
>          error_propagate(errp, err);
>          return;
>      }
>  
> -    object_property_set_int(OBJECT(&s->fb), ram_size - vcram_size,
> -                            "vcram-base", &err);
> +    object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size,
> +                             "vcram-base", &err);
>      if (err) {
>          error_propagate(errp, err);
>          return;

Defined with DEFINE_PROP_UINT32().  Okay.

> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> index 2b295f14c4..32cdc98c6d 100644
> --- a/hw/arm/raspi.c
> +++ b/hw/arm/raspi.c
> @@ -153,8 +153,8 @@ static void raspi2_init(MachineState *machine)
>      qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
>      object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
>  
> -    vcram_size = object_property_get_int(OBJECT(&s->soc), "vcram-size",
> -                                         &error_abort);
> +    vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
> +                                          &error_abort);
>      setup_boot(machine, 2, machine->ram_size - vcram_size);
>  }

Same property as above.  Okay.

>  
> diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
> index 329ac670c0..33d32fbf22 100644
> --- a/hw/core/platform-bus.c
> +++ b/hw/core/platform-bus.c
> @@ -71,7 +71,7 @@ hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev,
>          return -1;
>      }
>  
> -    return object_property_get_int(OBJECT(sbdev_mr), "addr", NULL);
> +    return object_property_get_uint(OBJECT(sbdev_mr), "addr", NULL);
>  }

I figure this is TYPE_MEMORY_REGION's property.  Its getter
memory_region_get_addr() uses visit_type_uint64().  Okay.

>  
>  static void platform_bus_count_irqs(SysBusDevice *sbdev, void *opaque)
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 27ad420914..76d27ff024 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -137,9 +137,9 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
>          obj = piix;
>          pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
>          pm->pcihp_io_base =
> -            object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
> +            object_property_get_uint(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
>          pm->pcihp_io_len =
> -            object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
> +            object_property_get_uint(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
>      }
>      if (lpc) {
>          obj = lpc;

These appear to be defined with object_property_add_uint16_ptr().  Okay,
I think.

> @@ -171,20 +171,21 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
>      qobject_decref(o);
>  
>      /* Fill in mandatory properties */
> -    pm->sci_int = object_property_get_int(obj, ACPI_PM_PROP_SCI_INT, NULL);
> -
> -    pm->acpi_enable_cmd = object_property_get_int(obj,
> -                                                  ACPI_PM_PROP_ACPI_ENABLE_CMD,
> -                                                  NULL);
> -    pm->acpi_disable_cmd = object_property_get_int(obj,
> -                                                  ACPI_PM_PROP_ACPI_DISABLE_CMD,
> -                                                  NULL);
> -    pm->io_base = object_property_get_int(obj, ACPI_PM_PROP_PM_IO_BASE,
> -                                          NULL);
> -    pm->gpe0_blk = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK,
> +    pm->sci_int = object_property_get_uint(obj, ACPI_PM_PROP_SCI_INT, NULL);
> +
> +    pm->acpi_enable_cmd = object_property_get_uint(obj,
> +                                                   ACPI_PM_PROP_ACPI_ENABLE_CMD,
> +                                                   NULL);
> +    pm->acpi_disable_cmd =
> +        object_property_get_uint(obj,
> +                                 ACPI_PM_PROP_ACPI_DISABLE_CMD,
> +                                 NULL);
> +    pm->io_base = object_property_get_uint(obj, ACPI_PM_PROP_PM_IO_BASE,
>                                             NULL);
> -    pm->gpe0_blk_len = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
> -                                               NULL);
> +    pm->gpe0_blk = object_property_get_uint(obj, ACPI_PM_PROP_GPE0_BLK,
> +                                            NULL);
> +    pm->gpe0_blk_len = object_property_get_uint(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
> +                                                NULL);
>      pm->pcihp_bridge_en =
>          object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support",
>                                   NULL);

PIIX4: piix4_pm_add_propeties() defines these with
object_property_add_uint*_ptr().

Q35: ich9_lpc_add_properties() and ich9_pm_add_properties() define them
similarly, except for ACPI_PM_PROP_GPE0_BLK().  That one's getter
ich9_pm_get_gpe0_blk() uses visit_type_uint32().

Okay.

> @@ -237,19 +238,19 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64)
>      g_assert(pci_host);
>  
>      range_set_bounds1(hole,
> -                      object_property_get_int(pci_host,
> -                                              PCI_HOST_PROP_PCI_HOLE_START,
> -                                              NULL),
> -                      object_property_get_int(pci_host,
> -                                              PCI_HOST_PROP_PCI_HOLE_END,
> -                                              NULL));
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE_START,
> +                                               NULL),
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE_END,
> +                                               NULL));
>      range_set_bounds1(hole64,
> -                      object_property_get_int(pci_host,
> -                                              PCI_HOST_PROP_PCI_HOLE64_START,
> -                                              NULL),
> -                      object_property_get_int(pci_host,
> -                                              PCI_HOST_PROP_PCI_HOLE64_END,
> -                                              NULL));
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE64_START,
> +                                               NULL),
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE64_END,
> +                                               NULL));
>  }
>  

Deja vu again, this time PATCH 11.  Okay.

>  #define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index f3b372a18f..8dc4507aa5 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -347,7 +347,7 @@ static int check_fdc(Object *obj, void *opaque)
>          return 0;
>      }
>  
> -    iobase = object_property_get_int(obj, "iobase", &local_err);
> +    iobase = object_property_get_uint(obj, "iobase", &local_err);
>      if (local_err || iobase != 0x3f0) {
>          error_free(local_err);
>          return 0;

TYPE_ISA_FDC's property "iobase" is defined with DEFINE_PROP_UINT32().
Okay.

> @@ -1100,7 +1100,7 @@ static void pc_new_cpu(const char *typename, int64_t apic_id, Error **errp)
>  
>      cpu = object_new(typename);
>  
> -    object_property_set_int(cpu, apic_id, "apic-id", &local_err);
> +    object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
>      object_property_set_bool(cpu, true, "realized", &local_err);
>  

TYPE_X86_CPU's property "apic-id" is defined with DEFINE_PROP_UINT32().
Okay.

>      object_unref(cpu);
> @@ -1560,7 +1560,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
>               * and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23,
>               * IRQ8 and IRQ2.
>               */
> -            uint8_t compat = object_property_get_int(OBJECT(hpet),
> +            uint8_t compat = object_property_get_uint(OBJECT(hpet),
>                      HPET_INTCAP, NULL);
>              if (!compat) {
>                  qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs);

TYPE_HPET's property HPET_INTCAP is defined with DEFINE_PROP_UINT32().
Okay.

> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index b1c05ffb86..cec259f82d 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -183,9 +183,9 @@ static void xen_ram_init(PCMachineState *pcms,
>  {
>      MemoryRegion *sysmem = get_system_memory();
>      ram_addr_t block_len;
> -    uint64_t user_lowmem = object_property_get_int(qdev_get_machine(),
> -                                                   PC_MACHINE_MAX_RAM_BELOW_4G,
> -                                                   &error_abort);
> +    uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
> +                                                    PC_MACHINE_MAX_RAM_BELOW_4G,
> +                                                    &error_abort);
>  
>      /* Handle the machine opt max-ram-below-4g.  It is basically doing
>       * min(xen limit, user limit).

TYPE_PC_MACHINE's property PC_MACHINE_MAX_RAM_BELOW_4G's getter and
setter pc_machine_get_max_ram_below_4g() and
pc_machine_set_max_ram_below_4g() use visit_type_size().  Okay.

> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index c6493d6c07..e2064cd8c5 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -267,7 +267,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
>           *  VLPIS == 0 (virtual LPIs not supported)
>           *  PLPIS == 0 (physical LPIs not supported)
>           */
> -        cpu_affid = object_property_get_int(OBJECT(cpu), "mp-affinity", NULL);
> +        cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
>          last = (i == s->num_cpu - 1);
>  
>          /* The CPU mp-affinity property is in MPIDR register format; squash

TYPE_ARM_CPU's property "mp-affinity" is defined with
DEFINE_PROP_UINT64().  Okay.

> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
> index 9e8dab0e89..f6def8c239 100644
> --- a/hw/mem/pc-dimm.c
> +++ b/hw/mem/pc-dimm.c
> @@ -46,7 +46,8 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
>      uint64_t existing_dimms_capacity = 0;
>      uint64_t addr;
>  
> -    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
> +    addr = object_property_get_uint(OBJECT(dimm),
> +                                    PC_DIMM_ADDR_PROP, &local_err);
>      if (local_err) {
>          goto out;
>      }

Discussed above.

> @@ -73,7 +74,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
>          goto out;
>      }
>  
> -    object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
> +    object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
>      if (local_err) {
>          goto out;
>      }

Same.

> diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
> index e4a7ba41de..8a90ddda84 100644
> --- a/hw/misc/auxbus.c
> +++ b/hw/misc/auxbus.c
> @@ -244,7 +244,7 @@ static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent)
>  
>      monitor_printf(mon, "%*smemory " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
>                     indent, "",
> -                   object_property_get_int(OBJECT(s->mmio), "addr", NULL),
> +                   object_property_get_uint(OBJECT(s->mmio), "addr", NULL),
>                     memory_region_size(s->mmio));
>  }
>  

I figure this is again TYPE_MEMORY_REGION's property.

> diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
> index 57da7f2199..2b1e9a6450 100644
> --- a/hw/misc/pvpanic.c
> +++ b/hw/misc/pvpanic.c
> @@ -111,7 +111,7 @@ uint16_t pvpanic_port(void)
>      if (!o) {
>          return 0;
>      }
> -    return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
> +    return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL);
>  }
>  

TYPE_ISA_PVPANIC_DEVICE's property PVPANIC_IOPORT_PROP is defined with
DEFINE_PROP_UINT16().  Okay.

>  static Property pvpanic_isa_properties[] = {
> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
> index 1b7ec70f03..142bad1e57 100644
> --- a/hw/ppc/pnv_core.c
> +++ b/hw/ppc/pnv_core.c
> @@ -51,7 +51,7 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
>      int thread_index = 0; /* TODO: TCG supports only one thread */
>      ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
>  
> -    core_pir = object_property_get_int(OBJECT(cpu), "core-pir", &error_abort);
> +    core_pir = object_property_get_uint(OBJECT(cpu), "core-pir", &error_abort);
>  
>      /*
>       * The PIR of a thread is the core PIR + the thread index. We will

This seems to be an alias of TYPE_PNV_CORE's property "pir", which is
defined with DEFINE_PROP_UINT32().  Okay.

> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 80d12d005c..9b9a4e8817 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -2582,7 +2582,8 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
>          goto out;
>      }
>  
> -    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
> +    addr = object_property_get_uint(OBJECT(dimm),
> +                                    PC_DIMM_ADDR_PROP, &local_err);
>      if (local_err) {
>          pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
>          goto out;

Discussed above.

> @@ -2670,7 +2671,8 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
>      uint64_t size = memory_region_size(mr);
>      uint64_t addr;
>  
> -    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
> +    addr = object_property_get_uint(OBJECT(dimm),
> +                                    PC_DIMM_ADDR_PROP, &local_err);
>      if (local_err) {
>          goto out;
>      }

Same.

> @@ -2878,7 +2880,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
>              error_setg(errp, "Memory hotplug not supported for this machine");
>              return;
>          }
> -        node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
> +        node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
>          if (*errp) {
>              return;
>          }

Same.

> diff --git a/numa.c b/numa.c
> index 6fc2393ddd..e32259fedb 100644
> --- a/numa.c
> +++ b/numa.c
> @@ -205,7 +205,7 @@ static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp)
>          }
>  
>          object_ref(o);
> -        numa_info[nodenr].node_mem = object_property_get_int(o, "size", NULL);
> +        numa_info[nodenr].node_mem = object_property_get_uint(o, "size", NULL);
>          numa_info[nodenr].node_memdev = MEMORY_BACKEND(o);
>      }
>      numa_info[nodenr].present = true;
> @@ -527,8 +527,8 @@ static int query_memdev(Object *obj, void *opaque)
>          m->value->id = object_property_get_str(obj, "id", NULL);
>          m->value->has_id = !!m->value->id;
>  
> -        m->value->size = object_property_get_int(obj, "size",
> -                                                 &error_abort);
> +        m->value->size = object_property_get_uint(obj, "size",
> +                                                  &error_abort);
>          m->value->merge = object_property_get_bool(obj, "merge",
>                                                     &error_abort);
>          m->value->dump = object_property_get_bool(obj, "dump",

I figure "size" is a property of TYPE_MEMORY_BACKEND.
host_memory_backend_get_size() and host_memory_backend_set_size() use
visit_type_size().  Okay.

> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 5bb8131bb8..eb200ef58b 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -2324,8 +2324,8 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
>       */
>  
>      /* CPU models only set _minimum_ values for level/xlevel: */
> -    object_property_set_int(OBJECT(cpu), def->level, "min-level", errp);
> -    object_property_set_int(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
> +    object_property_set_uint(OBJECT(cpu), def->level, "min-level", errp);
> +    object_property_set_uint(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
>  
>      object_property_set_int(OBJECT(cpu), def->family, "family", errp);
>      object_property_set_int(OBJECT(cpu), def->model, "model", errp);

I figure these are properties of TYPE_X86_CPU, defined with
DEFINE_PROP_UINT32().  Okay.

> diff --git a/ui/console.c b/ui/console.c
> index ac66b3c910..ad3f7c6a2c 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -1872,8 +1872,8 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
>          if (DEVICE(obj) != dev) {
>              continue;
>          }
> -        h = object_property_get_int(OBJECT(consoles[i]),
> -                                    "head", &error_abort);
> +        h = object_property_get_uint(OBJECT(consoles[i]),
> +                                     "head", &error_abort);
>          if (h != head) {
>              continue;
>          }

TYPE_QEMU_CONSOLE property "head" is defined with
object_property_add_uint*_ptr().  Okay.


Not your patch's fault, but I need to vent: to read a QOM property, we
call a suitable object_property_get_FOO(), which uses the property's
getter with a new QObject output visitor to get the property value as a
QObject, converts the QObject to the C type for FOO, frees the QObject,
and returns the converted value.

The getter knows the property's C type.

The code reading the property has to know the appropriate FOO for this C
type.

The conversion from QObject to C type does a bit of dynamic type
checking, so the code reading the property screws up too badly, we get
at least a run time failure.  There is no protection against messing up
signedness or width, and of course we mess up in places.

Writing is just as convoluted, opaque and error-prone.

This looks like a severe case of OOPitis to me.  There must be a better
way!  The signedness issues you correct should have been flagged by the
compiler or at least by Coverity.  Our OOPitis muddies the waters
sufficiently to defeat both.

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

* Re: [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint Marc-André Lureau
@ 2017-05-18 15:27   ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-18 15:27 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Similar to int support, add uint support.
>
> Note this is RFC because this is currently unused in qemu, I haven't
> found a good user for it yet (kaslr qemu-ga code did use it though).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Do we think future use is reasonably likely?  If yes, let's stop
worrying and take the patch.

> ---
>  include/qapi/qmp/qdict.h |  5 +++++
>  qobject/qdict.c          | 38 ++++++++++++++++++++++++++++++++++++++
>  tests/check-qdict.c      | 32 ++++++++++++++++++++++++++++++++
>  3 files changed, 75 insertions(+)
>
> diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
> index 363e431106..8c7c2b762b 100644
> --- a/include/qapi/qmp/qdict.h
> +++ b/include/qapi/qmp/qdict.h
> @@ -56,6 +56,8 @@ void qdict_destroy_obj(QObject *obj);
>  /* Helpers for int, bool, and string */
>  #define qdict_put_int(qdict, key, value) \
>          qdict_put(qdict, key, qnum_from_int(value))
> +#define qdict_put_uint(qdict, key, value)        \
> +        qdict_put(qdict, key, qnum_from_uint(value))
>  #define qdict_put_bool(qdict, key, value) \
>          qdict_put(qdict, key, qbool_from_bool(value))
>  #define qdict_put_str(qdict, key, value) \
> @@ -64,12 +66,15 @@ void qdict_destroy_obj(QObject *obj);
>  /* High level helpers */
>  double qdict_get_double(const QDict *qdict, const char *key);
>  int64_t qdict_get_int(const QDict *qdict, const char *key);
> +uint64_t qdict_get_uint(const QDict *qdict, const char *key);
>  bool qdict_get_bool(const QDict *qdict, const char *key);
>  QList *qdict_get_qlist(const QDict *qdict, const char *key);
>  QDict *qdict_get_qdict(const QDict *qdict, const char *key);
>  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);
> +uint64_t qdict_get_try_uint(const QDict *qdict, const char *key,
> +                            uint64_t def_value);
>  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);
>  
> diff --git a/qobject/qdict.c b/qobject/qdict.c
> index ad5bab9572..34478fbdd4 100644
> --- a/qobject/qdict.c
> +++ b/qobject/qdict.c
> @@ -202,6 +202,19 @@ int64_t qdict_get_int(const QDict *qdict, const char *key)
>  }
>  
>  /**
> + * qdict_get_uint(): Get an unsigned integer mapped by 'key'
> + *
> + * This function assumes that 'key' exists and it stores a
> + * QNum int object.
> + *
> + * Return unsigned integer mapped by 'key'.
> + */
> +uint64_t qdict_get_uint(const QDict *qdict, const char *key)
> +{
> +    return qnum_get_uint(qobject_to_qnum(qdict_get(qdict, key)), &error_abort);
> +}
> +
> +/**
>   * qdict_get_bool(): Get a bool mapped by 'key'
>   *
>   * This function assumes that 'key' exists and it stores a
> @@ -270,6 +283,31 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key,
>  }
>  
>  /**
> + * qdict_get_try_uint(): Try to get usigned integer mapped by 'key'
> + *
> + * Return unsigned integer mapped by 'key', if it is not present in
> + * the dictionary or if the stored object is not of QNum type
> + * 'def_value' will be returned.
> + */
> +uint64_t qdict_get_try_uint(const QDict *qdict, const char *key,
> +                            uint64_t def_value)
> +{
> +    Error *err = NULL;
> +    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
> +    uint64_t val = def_value;
> +
> +    if (qnum) {
> +        val = qnum_get_uint(qnum, &err);
> +    }
> +    if (err) {
> +        error_free(err);
> +        val = def_value;
> +    }
> +
> +    return val;
> +}
> +
> +/**
>   * qdict_get_try_bool(): Try to get a bool mapped by 'key'
>   *
>   * Return bool mapped by 'key', if it is not present in the
> diff --git a/tests/check-qdict.c b/tests/check-qdict.c
> index bcd06a7d6b..7f9ea67862 100644
> --- a/tests/check-qdict.c
> +++ b/tests/check-qdict.c
> @@ -105,6 +105,21 @@ static void qdict_get_int_test(void)
>      QDECREF(tests_dict);
>  }
>  
> +static void qdict_get_uint_test(void)
> +{
> +    uint64_t ret;
> +    const uint64_t value = UINT64_MAX;
> +    const char *key = "uint";
> +    QDict *tests_dict = qdict_new();
> +
> +    qdict_put_uint(tests_dict, key, value);
> +
> +    ret = qdict_get_uint(tests_dict, key);
> +    g_assert(ret == value);
> +
> +    QDECREF(tests_dict);
> +}
> +
>  static void qdict_get_try_int_test(void)
>  {
>      int ret;
> @@ -120,6 +135,21 @@ static void qdict_get_try_int_test(void)
>      QDECREF(tests_dict);
>  }
>  
> +static void qdict_get_try_uint_test(void)
> +{
> +    uint64_t ret;
> +    const uint64_t value = UINT64_MAX;
> +    const char *key = "uint";
> +    QDict *tests_dict = qdict_new();
> +
> +    qdict_put_uint(tests_dict, key, value);
> +
> +    ret = qdict_get_try_uint(tests_dict, key, 0);
> +    g_assert(ret == value);
> +
> +    QDECREF(tests_dict);
> +}
> +

Just as spotty as its signed buddy.  Both should at least also test
cases "key is not in dict" and "key maps to a value that isn't QNum".

>  static void qdict_get_str_test(void)
>  {
>      const char *p;
> @@ -852,7 +882,9 @@ int main(int argc, char **argv)
>      /* Continue, but now with fixtures */
>      g_test_add_func("/public/get", qdict_get_test);
>      g_test_add_func("/public/get_int", qdict_get_int_test);
> +    g_test_add_func("/public/get_uint", qdict_get_uint_test);
>      g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
> +    g_test_add_func("/public/get_try_uint", qdict_get_try_uint_test);
>      g_test_add_func("/public/get_str", qdict_get_str_test);
>      g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
>      g_test_add_func("/public/defaults", qdict_defaults_test);

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

* Re: [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type
  2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
                   ` (17 preceding siblings ...)
  2017-05-13 21:41 ` [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type no-reply
@ 2017-05-18 15:39 ` Markus Armbruster
  18 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-18 15:39 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Hi,
>
> In previously sent series "[PATCH 00/21] WIP: dump: add kaslr support
> (for after 2.9)", I proposed changes to accept uint64 values from
> json, by adding a QUint type. During review, it was suggested to
> introduce a QNum type to hold various number representations.
>
> This series introduces the QNum type, adds uint representation to it,
> and make uint64 values over json possible (while keeping json negative
> int for values >INT64_MAX to unsigned cast compatibility). It also
> improves some int vs uint usage for object properties and other
> QObject related clean-ups.
>
> The series is on top of http://repo.or.cz/qemu/armbru.git qapi-next

The series needs a bit of work here and there, but I think you're on the
right path.  Thanks for tackling this!

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

* Re: [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases
  2017-05-09 17:35 ` [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases Marc-André Lureau
  2017-05-09 18:51   ` Eric Blake
@ 2017-05-22 17:03   ` Markus Armbruster
  2017-05-30  3:40     ` Fam Zheng
  1 sibling, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-22 17:03 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> There are no real users of this case, and it's going to be invalid after
> merging of QFloat and QInt use the same QNum type in the following patch.

Invalid because our alternate code is insufficiently sophisticated.  In
other words fixable.  See "[PATCH 4/4] qapi: Reject alternates that
can't work with keyval_parse()" I just posted.

My patch's commit message describes two related issues, one fixable and
one unfixable.  The fixable one already exists, but only in QGA.  I
intend to fix it, but it's not a priority.

Fixing the issue you describe seems even less important.  I considered
outlawing it in my series (patch appended for your reading pleasure),
but decided to leave it to yours.  I don't expect you to replace your
patch.  Perhaps my patch helps you with rebasing yours should that
become necessary.


diff --git a/scripts/qapi.py b/scripts/qapi.py
index b7a25e4..06e583d 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -826,6 +826,10 @@ def check_alternate(expr, info):
                 conflicting.add('QTYPE_QINT')
                 conflicting.add('QTYPE_QFLOAT')
                 conflicting.add('QTYPE_QBOOL')
+        elif qtype == 'QTYPE_QINT':
+            conflicting.add('QTYPE_QFLOAT')
+        elif qtype == 'QTYPE_QFLOAT':
+            conflicting.add('QTYPE_QINT')
         if conflicting & set(types_seen):
             raise QAPISemError(info, "Alternate '%s' member '%s' can't "
                                "be distinguished from member '%s'"
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 17649c6..91ffb26 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -103,8 +103,6 @@
 { 'alternate': 'AltEnumNum', 'data': { 'e': 'EnumOne', 'n': 'number' } }
 { 'alternate': 'AltNumEnum', 'data': { 'n': 'number', 'e': 'EnumOne' } }
 { 'alternate': 'AltEnumInt', 'data': { 'e': 'EnumOne', 'i': 'int' } }
-{ 'alternate': 'AltIntNum', 'data': { 'i': 'int', 'n': 'number' } }
-{ 'alternate': 'AltNumInt', 'data': { 'n': 'number', 'i': 'int' } }
 
 # for testing use of 'str' within alternates
 { 'alternate': 'AltStrObj', 'data': { 's': 'str', 'o': 'TestStruct' } }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 9f68610..e727a5a 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -10,18 +10,10 @@ alternate AltEnumNum
     tag type
     case e: EnumOne
     case n: number
-alternate AltIntNum
-    tag type
-    case i: int
-    case n: number
 alternate AltNumEnum
     tag type
     case n: number
     case e: EnumOne
-alternate AltNumInt
-    tag type
-    case n: number
-    case i: int
 alternate AltStrObj
     tag type
     case s: str
diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index c3be005..baf7e33 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -615,7 +615,7 @@ static void test_keyval_visit_alternate(void)
     Visitor *v;
     QDict *qdict;
     AltStrObj *aso;
-    AltNumInt *ani;
+    AltNumEnum *ane;
     AltEnumBool *aeb;
 
     /*
@@ -631,7 +631,7 @@ static void test_keyval_visit_alternate(void)
     g_assert_cmpint(aso->type, ==, QTYPE_QSTRING);
     g_assert_cmpstr(aso->u.s, ==, "1");
     qapi_free_AltStrObj(aso);
-    visit_type_AltNumInt(v, "b", &ani, &err);
+    visit_type_AltNumEnum(v, "b", &ane, &err);
     error_free_or_abort(&err);
     visit_type_AltEnumBool(v, "c", &aeb, &err);
     error_free_or_abort(&err);
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 6b997a1..83d663d 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -592,8 +592,6 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
     AltEnumNum *aen;
     AltNumEnum *ans;
     AltEnumInt *asi;
-    AltIntNum *ain;
-    AltNumInt *ani;
 
     /* Parsing an int */
 
@@ -620,18 +618,6 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
     g_assert_cmpint(asi->u.i, ==, 42);
     qapi_free_AltEnumInt(asi);
 
-    v = visitor_input_test_init(data, "42");
-    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
-    g_assert_cmpint(ain->type, ==, QTYPE_QINT);
-    g_assert_cmpint(ain->u.i, ==, 42);
-    qapi_free_AltIntNum(ain);
-
-    v = visitor_input_test_init(data, "42");
-    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
-    g_assert_cmpint(ani->type, ==, QTYPE_QINT);
-    g_assert_cmpint(ani->u.i, ==, 42);
-    qapi_free_AltNumInt(ani);
-
     /* Parsing a double */
 
     v = visitor_input_test_init(data, "42.5");
@@ -655,18 +641,6 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
     visit_type_AltEnumInt(v, NULL, &asi, &err);
     error_free_or_abort(&err);
     qapi_free_AltEnumInt(asi);
-
-    v = visitor_input_test_init(data, "42.5");
-    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
-    g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
-    g_assert_cmpfloat(ain->u.n, ==, 42.5);
-    qapi_free_AltIntNum(ain);
-
-    v = visitor_input_test_init(data, "42.5");
-    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
-    g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
-    g_assert_cmpfloat(ani->u.n, ==, 42.5);
-    qapi_free_AltNumInt(ani);
 }
 
 static void test_native_list_integer_helper(TestInputVisitorData *data,

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

* Re: [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases
  2017-05-22 17:03   ` Markus Armbruster
@ 2017-05-30  3:40     ` Fam Zheng
  2017-05-30 14:17       ` Eric Blake
  0 siblings, 1 reply; 70+ messages in thread
From: Fam Zheng @ 2017-05-30  3:40 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Marc-André Lureau, qemu-devel

I noticed you were wondering what happend to this message in the patchew thread:

http://patchew.org/QEMU/20170509173559.31598-1-marcandre.lureau@redhat.com/

Markus, apparently this is because of the unusual "In-Reply-To" header of your
message, which confuses patchew:

In-Reply-To: <20170509173559.31598-4-marcandre.lureau@redhat.com>
	(=?utf-8?Q?=22Marc-Andr=C3=A9?=
	Lureau"'s message of "Tue, 9 May 2017 20:35:45 +0300")

Is this an extension of your email client, or a standard?

In https://tools.ietf.org/html/rfc2822#section-3.6.4:
>    The "References:" and "In-Reply-To:" field each contain one or more
>    unique message identifiers, optionally separated by CFWS.
> 
>    The message identifier (msg-id) is similar in syntax to an angle-addr
>    construct without the internal CFWS.
> 
> message-id      =       "Message-ID:" msg-id CRLF
> 
> in-reply-to     =       "In-Reply-To:" 1*msg-id CRLF
> 
> references      =       "References:" 1*msg-id CRLF

I can imagine if consider CFWS, patchew should probably just work (I can fix
that), but it's still good to understand this.

Fam

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-11 14:29   ` Markus Armbruster
  2017-05-11 15:09     ` Eric Blake
@ 2017-05-30  7:32     ` Marc-André Lureau
  2017-05-30 14:19       ` Eric Blake
  2017-05-30 14:23       ` Markus Armbruster
  1 sibling, 2 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-30  7:32 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Thu, May 11, 2017 at 6:30 PM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.1
> or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + */
> > +
> > +#ifndef QNUM_H
> > +#define QNUM_H
> > +
> > +#include "qapi/qmp/qobject.h"
> > +
> > +typedef enum {
> > +    QNUM_I64,
> > +    QNUM_DOUBLE
> > +} QNumType;
>
> Not bool because you're going to add to it.  Good.
>
>
Hmm? There is no plan to add bool there so far, I am not sure that makes
sense.


>  static void qobject_input_type_int64(Visitor *v, const char *name,
> int64_t *obj,
> > @@ -387,19 +384,19 @@ static void qobject_input_type_int64(Visitor *v,
> const char *name, int64_t *obj,
> >  {
> >      QObjectInputVisitor *qiv = to_qiv(v);
> >      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> > -    QInt *qint;
> > +    QNum *qnum;
> >
> >      if (!qobj) {
> >          return;
> >      }
> > -    qint = qobject_to_qint(qobj);
> > -    if (!qint) {
> > +    qnum = qobject_to_qnum(qobj);
> > +    if (!qnum) {
> >          error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
> >                     full_name(qiv, name), "integer");
> >          return;
> >      }
> >
> > -    *obj = qint_get_int(qint);
> > +    *obj = qnum_get_int(qnum, errp);
>
> Compare the error message a few lines up
>
>     Invalid parameter type for 'NAME', expected: integer
>
> to the one we get here:
>
>     The number is a float
>
> Which number?  There can be quite a few in a QMP command.  We need to
> pass @name to qnum_get_int() for a decent error message, like
>
>     Parameter 'NAME' is not a 64 bit integer
>
>
I suggest we do it the same way as qom/object.c, handle the error and
prepend/modify it. Passing @name feels awkward, since qtypes don't have to
have names.


> >  int64_t qdict_get_int(const QDict *qdict, const char *key)
> >  {
> > -    return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
> > +    return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)),
> &error_abort);
>
> Line is a bit long for my taste.
>
> >  }
> >
> >  /**
> > @@ -260,15 +248,25 @@ const char *qdict_get_str(const QDict *qdict,
> const char *key)
> >   * qdict_get_try_int(): Try to get integer mapped by 'key'
> >   *
> >   * Return integer mapped by 'key', if it is not present in
> > - * the dictionary or if the stored object is not of QInt type
> > + * the dictionary or if the stored object is not of QNum type
>
> Actually "is not a QNum representing an integer".
>
> >   * 'def_value' will be returned.
> >   */
> >  int64_t qdict_get_try_int(const QDict *qdict, const char *key,
> >                            int64_t def_value)
> >  {
> > -    QInt *qint = qobject_to_qint(qdict_get(qdict, key));
> > +    Error *err = NULL;
> > +    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
> > +    int64_t val = def_value;
> > +
> > +    if (qnum) {
> > +        val = qnum_get_int(qnum, &err);
> > +    }
> > +    if (err) {
> > +        error_free(err);
> > +        val = def_value;
> > +    }
>
> This is a bit inefficient: it creates and destroys an Error object.
> Easily avoided with a predicate qnum_is_int().
>

True, but a predicate would have to deal with the same implicit conversion
as qnum_get_int(). Not sure it's worth the duplication.


>
> >
> > -    return qint ? qint_get_int(qint) : def_value;
> > +    return val;
> >  }
> >
> >  /**
> > diff --git a/qobject/qfloat.c b/qobject/qfloat.c
> > deleted file mode 100644
> > index d5da847701..0000000000
> > --- a/qobject/qfloat.c
> > +++ /dev/null
> > @@ -1,62 +0,0 @@
> > -/*
> > - * QFloat Module
> > - *
> > - * Copyright IBM, Corp. 2009
> > - *
> > - * Authors:
> > - *  Anthony Liguori   <aliguori@us.ibm.com>
> > - *
> > - * This work is licensed under the terms of the GNU LGPL, version 2.1
> or later.
> > - * See the COPYING.LIB file in the top-level directory.
> > - *
> > - */
> > -
> > -#include "qemu/osdep.h"
> > -#include "qapi/qmp/qfloat.h"
> > -#include "qapi/qmp/qobject.h"
> > -#include "qemu-common.h"
> > -
> > -/**
> > - * qfloat_from_int(): Create a new QFloat from a float
> > - *
> > - * Return strong reference.
> > - */
> > -QFloat *qfloat_from_double(double value)
> > -{
> > -    QFloat *qf;
> > -
> > -    qf = g_malloc(sizeof(*qf));
> > -    qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
> > -    qf->value = value;
> > -
> > -    return qf;
> > -}
> > -
> > -/**
> > - * qfloat_get_double(): Get the stored float
> > - */
> > -double qfloat_get_double(const QFloat *qf)
> > -{
> > -    return qf->value;
> > -}
> > -
> > -/**
> > - * qobject_to_qfloat(): Convert a QObject into a QFloat
> > - */
> > -QFloat *qobject_to_qfloat(const QObject *obj)
> > -{
> > -    if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
> > -        return NULL;
> > -    }
> > -    return container_of(obj, QFloat, base);
> > -}
> > -
> > -/**
> > - * qfloat_destroy_obj(): Free all memory allocated by a
> > - * QFloat object
> > - */
> > -void qfloat_destroy_obj(QObject *obj)
> > -{
> > -    assert(obj != NULL);
> > -    g_free(qobject_to_qfloat(obj));
> > -}
> > diff --git a/qobject/qint.c b/qobject/qint.c
> > deleted file mode 100644
> > index d7d1b3021f..0000000000
> > --- a/qobject/qint.c
> > +++ /dev/null
> > @@ -1,61 +0,0 @@
> > -/*
> > - * QInt Module
> > - *
> > - * Copyright (C) 2009 Red Hat Inc.
> > - *
> > - * Authors:
> > - *  Luiz Capitulino <lcapitulino@redhat.com>
> > - *
> > - * This work is licensed under the terms of the GNU LGPL, version 2.1
> or later.
> > - * See the COPYING.LIB file in the top-level directory.
> > - */
> > -
> > -#include "qemu/osdep.h"
> > -#include "qapi/qmp/qint.h"
> > -#include "qapi/qmp/qobject.h"
> > -#include "qemu-common.h"
> > -
> > -/**
> > - * qint_from_int(): Create a new QInt from an int64_t
> > - *
> > - * Return strong reference.
> > - */
> > -QInt *qint_from_int(int64_t value)
> > -{
> > -    QInt *qi;
> > -
> > -    qi = g_malloc(sizeof(*qi));
> > -    qobject_init(QOBJECT(qi), QTYPE_QINT);
> > -    qi->value = value;
> > -
> > -    return qi;
> > -}
> > -
> > -/**
> > - * qint_get_int(): Get the stored integer
> > - */
> > -int64_t qint_get_int(const QInt *qi)
> > -{
> > -    return qi->value;
> > -}
> > -
> > -/**
> > - * qobject_to_qint(): Convert a QObject into a QInt
> > - */
> > -QInt *qobject_to_qint(const QObject *obj)
> > -{
> > -    if (!obj || qobject_type(obj) != QTYPE_QINT) {
> > -        return NULL;
> > -    }
> > -    return container_of(obj, QInt, base);
> > -}
> > -
> > -/**
> > - * qint_destroy_obj(): Free all memory allocated by a
> > - * QInt object
> > - */
> > -void qint_destroy_obj(QObject *obj)
> > -{
> > -    assert(obj != NULL);
> > -    g_free(qobject_to_qint(obj));
> > -}
> > diff --git a/qobject/qjson.c b/qobject/qjson.c
> > index b2f3bfec53..2e0930884e 100644
> > --- a/qobject/qjson.c
> > +++ b/qobject/qjson.c
> > @@ -132,12 +132,11 @@ static void to_json(const QObject *obj, QString
> *str, int pretty, int indent)
> >      case QTYPE_QNULL:
> >          qstring_append(str, "null");
> >          break;
> > -    case QTYPE_QINT: {
> > -        QInt *val = qobject_to_qint(obj);
> > -        char buffer[1024];
> > -
> > -        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
> > +    case QTYPE_QNUM: {
> > +        QNum *val = qobject_to_qnum(obj);
> > +        char *buffer = qnum_to_string(val);
> >          qstring_append(str, buffer);
> > +        g_free(buffer);
> >          break;
> >      }
> >      case QTYPE_QSTRING: {
> > @@ -234,34 +233,6 @@ static void to_json(const QObject *obj, QString
> *str, int pretty, int indent)
> >          qstring_append(str, "]");
> >          break;
> >      }
> > -    case QTYPE_QFLOAT: {
> > -        QFloat *val = qobject_to_qfloat(obj);
> > -        char buffer[1024];
> > -        int len;
> > -
> > -        /* FIXME: snprintf() is locale dependent; but JSON requires
> > -         * numbers to be formatted as if in the C locale. Dependence
> > -         * on C locale is a pervasive issue in QEMU. */
> > -        /* FIXME: This risks printing Inf or NaN, which are not valid
> > -         * JSON values. */
> > -        /* FIXME: the default precision of 6 for %f often causes
> > -         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
> > -         * and only rounding to a shorter number if the result would
> > -         * still produce the same floating point value.  */
> > -        len = snprintf(buffer, sizeof(buffer), "%f",
> qfloat_get_double(val));
> > -        while (len > 0 && buffer[len - 1] == '0') {
> > -            len--;
> > -        }
> > -
> > -        if (len && buffer[len - 1] == '.') {
> > -            buffer[len - 1] = 0;
> > -        } else {
> > -            buffer[len] = 0;
> > -        }
> > -
> > -        qstring_append(str, buffer);
> > -        break;
> > -    }
> >      case QTYPE_QBOOL: {
> >          QBool *val = qobject_to_qbool(obj);
> >
> > diff --git a/qobject/qnum.c b/qobject/qnum.c
> > new file mode 100644
> > index 0000000000..8e9dd38350
> > --- /dev/null
> > +++ b/qobject/qnum.c
> > @@ -0,0 +1,138 @@
> > +/*
> > + * QNum Module
> > + *
> > + * Copyright (C) 2009 Red Hat Inc.
> > + *
> > + * Authors:
> > + *  Luiz Capitulino <lcapitulino@redhat.com>
> > + *  Marc-André Lureau <marcandre.lureau@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.1
> or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qapi/qmp/qnum.h"
> > +#include "qapi/qmp/qobject.h"
> > +#include "qemu-common.h"
> > +
> > +/**
> > + * qnum_from_int(): Create a new QNum from an int64_t
> > + *
> > + * Return strong reference.
> > + */
> > +QNum *qnum_from_int(int64_t value)
> > +{
> > +    QNum *qn = g_new(QNum, 1);
> > +
> > +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> > +    qn->type = QNUM_I64;
> > +    qn->u.i64 = value;
> > +
> > +    return qn;
> > +}
> > +
> > +/**
> > + * qnum_from_double(): Create a new QNum from a double
> > + *
> > + * Return strong reference.
> > + */
> > +QNum *qnum_from_double(double value)
> > +{
> > +    QNum *qn = g_new(QNum, 1);
> > +
> > +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> > +    qn->type = QNUM_DOUBLE;
> > +    qn->u.dbl = value;
> > +
> > +    return qn;
> > +}
> > +
> > +/**
> > + * qnum_get_int(): Get an integer representation of the number
> > + */
> > +int64_t qnum_get_int(const QNum *qn, Error **errp)
> > +{
> > +    switch (qn->type) {
> > +    case QNUM_I64:
> > +        return qn->u.i64;
> > +    case QNUM_DOUBLE:
> > +        error_setg(errp, "The number is a float");
> > +        return 0;
> > +    }
> > +
> > +    g_assert_not_reached();
>
> g_assert_not_reached() is problematic, see "[PATCH] checkpatch: Disallow
> glib asserts in main code".
>
> Message-Id: <20170427165526.19836-1-dgilbert@redhat.com>
> https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg05499.html
>
>
Actually g_assert() and g_assert_not_reached() are accepted.
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-15 13:59   ` Markus Armbruster
@ 2017-05-30 11:35     ` Marc-André Lureau
  2017-05-30 14:22       ` Eric Blake
  2017-05-31 10:08       ` Markus Armbruster
  0 siblings, 2 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-30 11:35 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Mon, May 15, 2017 at 6:00 PM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Switch strtoll() usage to qemu_strtoi64() helper while at it.
> >
> > Replace temporarily the error in qnum_get_int() with values >INT64_MAX
> > until the visitor is updated.
> >
> > Add a few tests for large numbers.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  qobject/json-lexer.c               |  4 ++++
> >  qobject/json-parser.c              | 30 ++++++++++++++++++++++--------
> >  qobject/qnum.c                     |  4 ++--
> >  tests/check-qjson.c                | 28 ++++++++++++++++++++++++++++
> >  tests/check-qnum.c                 |  9 +++++----
> >  tests/test-qobject-input-visitor.c |  7 ++-----
> >  6 files changed, 63 insertions(+), 19 deletions(-)
> >
> > diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
> > index af4a75e05b..a0beb0b106 100644
> > --- a/qobject/json-lexer.c
> > +++ b/qobject/json-lexer.c
> > @@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
> >      /* escape */
> >      [IN_ESCAPE_LL] = {
> >          ['d'] = JSON_ESCAPE,
> > +        ['u'] = JSON_ESCAPE,
> >      },
> >
> >      [IN_ESCAPE_L] = {
> >          ['d'] = JSON_ESCAPE,
> > +        ['u'] = JSON_ESCAPE,
> >          ['l'] = IN_ESCAPE_LL,
> >      },
> >
> >      [IN_ESCAPE_I64] = {
> >          ['d'] = JSON_ESCAPE,
> > +        ['u'] = JSON_ESCAPE,
> >      },
> >
> >      [IN_ESCAPE_I6] = {
> > @@ -247,6 +250,7 @@ static const uint8_t json_lexer[][256] =  {
> >      },
> >
> >      [IN_ESCAPE] = {
> > +        ['u'] = JSON_ESCAPE,
> >          ['d'] = JSON_ESCAPE,
> >          ['i'] = JSON_ESCAPE,
> >          ['p'] = JSON_ESCAPE,
>
> Please keep the JSON_ESCAPE lines sorted.
>

they are not all sorted, but ok


>
> > diff --git a/qobject/json-parser.c b/qobject/json-parser.c
> > index f431854ba1..fa15c762d3 100644
> > --- a/qobject/json-parser.c
> > +++ b/qobject/json-parser.c
> > @@ -12,6 +12,7 @@
> >   */
> >
> >  #include "qemu/osdep.h"
> > +#include "qemu/cutils.h"
> >  #include "qapi/error.h"
> >  #include "qemu-common.h"
> >  #include "qapi/qmp/types.h"
> > @@ -472,6 +473,13 @@ static QObject *parse_escape(JSONParserContext
> *ctxt, va_list *ap)
> >      } else if (!strcmp(token->str, "%lld") ||
> >                 !strcmp(token->str, "%I64d")) {
> >          return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
> > +    } else if (!strcmp(token->str, "%u")) {
> > +        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int)));
> > +    } else if (!strcmp(token->str, "%lu")) {
> > +        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long)));
> > +    } else if (!strcmp(token->str, "%llu") ||
> > +               !strcmp(token->str, "%I64u")) {
> > +        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long)));
> >      } else if (!strcmp(token->str, "%s")) {
> >          return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
> >      } else if (!strcmp(token->str, "%f")) {
> > @@ -494,22 +502,28 @@ static QObject *parse_literal(JSONParserContext
> *ctxt)
> >          /* A possibility exists that this is a whole-valued float where
> the
> >           * fractional part was left out due to being 0 (.0). It's not a
> big
> >           * deal to treat these as ints in the parser, so long as users
> of the
> > -         * resulting QObject know to expect a QNum in place of a QNum in
> > -         * cases like these.
> > +         * resulting QObject know to expect a QNum that will handle
> > +         * implicit conversions to the expected type.
> >           *
> > -         * However, in some cases these values will overflow/underflow a
> > -         * QNum/int64 container, thus we should assume these are to be
> handled
> > -         * as QNums/doubles rather than silently changing their values.
> > +         * However, in some cases these values will overflow/underflow
> > +         * a QNum/int64 container, thus we should assume these are to
> > +         * be handled as QNum/uint64 or QNums/doubles rather than
> > +         * silently changing their values.
> >           *
> > -         * strtoll() indicates these instances by setting errno to
> ERANGE
> > +         * qemu_strto*() indicates these instances by setting errno to
> ERANGE
> >           */
>
> I asked for this comment to be rephrased in PATCH 04.  Turns out my
> proposal there there isn't so easy to extend for unsigned, so let me try
> again from scratch:
>
>            /*
>             * Represent JSON_INTEGER as QNUM_I64 if possible, else as
>             * QNUM_U64, else as QNUM_DOUBLE.  Note that qemu_strtoi64()
>             * and qemu_strtou64 fail with ERANGE when it's not possible.
>             *
>             * qnum_get_int() will then work for any signed 64-bit
>             * JSON_INTEGER, qnum_get_uint() for any unsigned 64-bit
>             * integer, and qnum_get_double both for any JSON_INTEGER and
>             * any JSON_FLOAT.
>             */
>
> Remove the unsigned part for PATCH 04.
>

ok


>
> >          int64_t value;
> > +        uint64_t uvalue;
> >
> > -        errno = 0; /* strtoll doesn't set errno on success */
> > -        value = strtoll(token->str, NULL, 10);
> > +        qemu_strtoi64(token->str, NULL, 10, &value);
> >          if (errno != ERANGE) {
> >              return QOBJECT(qnum_from_int(value));
> >          }
>
> qemu_strtoi64() returns an error code.  Checking errno is wrong.
> Better:
>
>            ret = qemu_strtoi64(token->str, NULL, 10, &value);
>            if (!ret) {
>                return QOBJECT(qnum_from_int(value));
>            }
>            assert(ret == -ERANGE);
>

ok


>
> > +
> > +        qemu_strtou64(token->str, NULL, 10, &uvalue);
> > +        if (errno != ERANGE) {
> > +            return QOBJECT(qnum_from_uint(uvalue));
> > +        }
>
> Likewise.
>
> Moreover, values between -2^64 and 0 exclusive are accepted modulo 2^64.
> Example: -9223372036854775809 is accepted as a funny way to say
> 9223372036854775807.  Bad.  This is a well-known strtoul() wart
> qemu_strtou64() reproduces faithfully.  We need to avoid trying
> qemu_strtou64() when token->str[0] == '-'.  Exploits that the lexer
> strips off leading whitespace, but I think that's quite tolerable.
>

 ok


> >          /* fall through to JSON_FLOAT */
> >      }
> >      case JSON_FLOAT:
> > diff --git a/qobject/qnum.c b/qobject/qnum.c
> > index be6307accf..2f87952db8 100644
> > --- a/qobject/qnum.c
> > +++ b/qobject/qnum.c
> > @@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
> >          return qn->u.i64;
> >      case QNUM_U64:
> >          if (qn->u.u64 > INT64_MAX) {
> > -            error_setg(errp, "The number is too large, use
> qnum_get_uint()");
> > -            return 0;
> > +            /* temporarily accepts to cast to i64 until visitor is
> switched */
> > +            error_report("The number is too large, use
> qnum_get_uint()");
>
> Awkward.  Can we avoid this somehow?
>
>
by merging the next two patches? I think it's easier to understand why and
how I came up with the following fix.


> >          }
> >          return qn->u.u64;
> >      case QNUM_DOUBLE:
> > diff --git a/tests/check-qjson.c b/tests/check-qjson.c
> > index c432aebf13..57c2366dc3 100644
> > --- a/tests/check-qjson.c
> > +++ b/tests/check-qjson.c
> > @@ -904,6 +904,33 @@ static void simple_number(void)
> >      }
> >  }
> >
> > +static void large_number(void)
> > +{
> > +    const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
> > +    const char *gtu64 = "18446744073709551616"; /* 2^64 */
> > +    QNum *qnum;
> > +    QString *str;
> > +
> > +    qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
> > +    g_assert(qnum);
> > +    g_assert_cmpuint(qnum_get_uint(qnum, &error_abort),
> > +                     ==, 18446744073709551615U);
> > +
> > +    str = qobject_to_json(QOBJECT(qnum));
> > +    g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
> > +    QDECREF(str);
> > +    QDECREF(qnum);
> > +
> > +    qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
> > +    g_assert(qnum);
> > +    g_assert_cmpfloat(qnum_get_double(qnum), ==,
> 18446744073709551616.0);
>
>        qnum_get_uint(qnum, &err);
>        error_free_or_abort(err);
>
>
ok


> > +
> > +    str = qobject_to_json(QOBJECT(qnum));
> > +    g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
> > +    QDECREF(str);
> > +    QDECREF(qnum);
> > +}
> > +
> >  static void float_number(void)
> >  {
> >      int i;
> > @@ -1468,6 +1495,7 @@ int main(int argc, char **argv)
> >      g_test_add_func("/literals/string/vararg", vararg_string);
> >
> >      g_test_add_func("/literals/number/simple", simple_number);
> > +    g_test_add_func("/literals/number/large", large_number);
> >      g_test_add_func("/literals/number/float", float_number);
> >      g_test_add_func("/literals/number/vararg", vararg_number);
> >
> > diff --git a/tests/check-qnum.c b/tests/check-qnum.c
> > index 8199546f99..9a22af3d0e 100644
> > --- a/tests/check-qnum.c
> > +++ b/tests/check-qnum.c
> > @@ -107,10 +107,11 @@ static void qnum_get_uint_test(void)
> >      error_free_or_abort(&err);
> >      QDECREF(qn);
> >
> > -    qn = qnum_from_uint(-1ULL);
> > -    qnum_get_int(qn, &err);
> > -    error_free_or_abort(&err);
> > -    QDECREF(qn);
> > +    /* temporarily disabled until visitor is switched */
> > +    /* qn = qnum_from_uint(-1ULL); */
> > +    /* qnum_get_int(qn, &err); */
> > +    /* error_free_or_abort(&err); */
> > +    /* QDECREF(qn); */
>
> Please use #if 0 to disable code.
>
>
ok


> >
> >      /* invalid case */
> >      qn = qnum_from_double(0.42);
> > diff --git a/tests/test-qobject-input-visitor.c
> b/tests/test-qobject-input-visitor.c
> > index 5df62c4f9e..276a6b4427 100644
> > --- a/tests/test-qobject-input-visitor.c
> > +++ b/tests/test-qobject-input-visitor.c
> > @@ -119,7 +119,6 @@ static void test_visitor_in_int(TestInputVisitorData
> *data,
> >  static void test_visitor_in_uint(TestInputVisitorData *data,
> >                                  const void *unused)
> >  {
> > -    Error *err = NULL;
> >      uint64_t res = 0;
> >      int value = 42;
> >      Visitor *v;
> > @@ -136,12 +135,10 @@ static void
> test_visitor_in_uint(TestInputVisitorData *data,
> >      visit_type_uint64(v, NULL, &res, &error_abort);
> >      g_assert_cmpuint(res, ==, (uint64_t)-value);
> >
> > -    /* BUG: value between INT64_MAX+1 and UINT64_MAX rejected */
> > -
> >      v = visitor_input_test_init(data, "18446744073709551574");
> >
> > -    visit_type_uint64(v, NULL, &res, &err);
> > -    error_free_or_abort(&err);
> > +    visit_type_uint64(v, NULL, &res, &error_abort);
> > +    g_assert_cmpuint(res, ==, 18446744073709551574U);
> >  }
> >
> >  static void test_visitor_in_int_overflow(TestInputVisitorData *data,
>
> We should systematically cover the integers, in particular the
> boundaries (because that's where bugs like to hide):
>
> * Integers in [-2^63,0) can be visited with visit_type_int() and
>   visit_type_number().
>

added to  test_visitor_in_int()

>
> * Integers in [0,2^63) can be visited with visit_type_int(),
>   visit_type_uint64() and visit_type_number().
>

added to test_visitor_in_uint()


>
> * Integers in [2^63,2^64) can be visited with visit_type_uint64() and
>   visit_type_number().
>
>
added to test_visitor_in_uint()


> * Integers outside [-2^63,2^53) can be visited with visit_type_number().
>
>
added a test_visitor_in_large_number()

In any case, visit_type_number() loses precision beyond 53 bits.
>
> I'd do this as a separate patch before PATCH 04, so we can see how the
> patches affect the test results.
>
> Doing the same for check-qnum.c wouldn't hurt.  Not sure it's worth the
> trouble, though.
>
>
I'll skip it since it should be covered by visitor test hopefully

thanks
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt
  2017-05-16 17:31   ` Markus Armbruster
  2017-05-17 16:26     ` Markus Armbruster
@ 2017-05-30 12:28     ` Marc-André Lureau
  2017-05-31 13:10       ` Markus Armbruster
  1 sibling, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-30 12:28 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Tue, May 16, 2017 at 9:33 PM Markus Armbruster <armbru@redhat.com> wrote:

> On the subject: there is no such thing as "QUInt".  I guess you mean
> "uint type" (like in PATCH 06's subject).  Could also say "QNUM_U64".
>
> Apropos subject: humor me, and start your subjects with a capital
> letter, like this:
>
>     qapi: Update the qobject visitor ...
>
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Switch to use QNum/uint where appropriate to remove i64 limitation.
> >
> > The input visitor will cast i64 input to u64 for compatibility
> > reasons (existing json QMP client already use negative i64 for large
> > u64, and expect an implicit cast in qemu).
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  qapi/qobject-input-visitor.c        | 13 +++++++++++--
> >  qapi/qobject-output-visitor.c       |  3 +--
> >  tests/test-qobject-output-visitor.c | 21 ++++++++++++++++-----
> >  3 files changed, 28 insertions(+), 9 deletions(-)
> >
> > diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
> > index 785949ebab..72cefcf677 100644
> > --- a/qapi/qobject-input-visitor.c
> > +++ b/qapi/qobject-input-visitor.c
> > @@ -420,9 +420,9 @@ static void qobject_input_type_int64_keyval(Visitor
> *v, const char *name,
> >  static void qobject_input_type_uint64(Visitor *v, const char *name,
> >                                        uint64_t *obj, Error **errp)
> >  {
> > -    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
> >      QObjectInputVisitor *qiv = to_qiv(v);
> >      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> > +    Error *err = NULL;
> >      QNum *qnum;
> >
> >      if (!qobj) {
> > @@ -435,7 +435,16 @@ static void qobject_input_type_uint64(Visitor *v,
> const char *name,
> >          return;
> >      }
> >
> > -    *obj = qnum_get_int(qnum, errp);
> > +    /* XXX: compatibility case, accept negative values as u64 */
>
> What does "XXX" signify?
>

It's a fairly common marker for something similar to FIXME (there are
hundreds of them in qemu source tree).

I'd like to leave a fixme that means that there should be a visitor
flag/capability to fix this compatibility behaviour. (this could be exposed
as a qmp capability)

>
> > +    *obj = qnum_get_int(qnum, &err);
> > +
>
> Shouldn't the comment go right here?
>
>
Above qnum_get_int() is the right place imho.



> > +    if (err) {
> > +        error_free(err);
> > +        err = NULL;
> > +        *obj = qnum_get_uint(qnum, &err);
> > +    }
> > +
> > +    error_propagate(errp, err);
> >  }
> >
> >  static void qobject_input_type_uint64_keyval(Visitor *v, const char
> *name,
> > diff --git a/qapi/qobject-output-visitor.c
> b/qapi/qobject-output-visitor.c
> > index 2ca5093b22..70be84ccb5 100644
> > --- a/qapi/qobject-output-visitor.c
> > +++ b/qapi/qobject-output-visitor.c
> > @@ -150,9 +150,8 @@ static void qobject_output_type_int64(Visitor *v,
> const char *name,
> >  static void qobject_output_type_uint64(Visitor *v, const char *name,
> >                                         uint64_t *obj, Error **errp)
> >  {
> > -    /* FIXME values larger than INT64_MAX become negative */
> >      QObjectOutputVisitor *qov = to_qov(v);
> > -    qobject_output_add(qov, name, qnum_from_int(*obj));
> > +    qobject_output_add(qov, name, qnum_from_uint(*obj));
>
> Before the patch, uint64_t values above INT64_MAX are sent as negative
> values, e.g. UINT64_MAX is sent as -1.
>
> After the patch, they are sent unmodified.  Clearly a bug fix, but we
> have to consider compatibility issues anyway.  Does libvirt expect large
> integers to be sent as negative integers?  Does it cope with this fix
> gracefully?  Eric, any idea?
>

The libvirt json parser seems to rely on virStrToLong_ui(), which is a
wrapper around strtoul(), so it accepts negative values with -2^63..-1.
Changing it to return values larger than INT64_MAX should be ok.


>
> >  }
> >
> >  static void qobject_output_type_bool(Visitor *v, const char *name, bool
> *obj,
> > diff --git a/tests/test-qobject-output-visitor.c
> b/tests/test-qobject-output-visitor.c
> > index 66a682d5a8..767818e393 100644
> > --- a/tests/test-qobject-output-visitor.c
> > +++ b/tests/test-qobject-output-visitor.c
> > @@ -595,15 +595,26 @@ static void check_native_list(QObject *qobj,
> >      qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
> >
> >      switch (kind) {
> > -    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
> > -    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
> > -    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
> > -    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
> >      case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
> > -        /* all integer elements in JSON arrays get stored into QNums
> when
> > +        for (i = 0; i < 32; i++) {
> > +            QObject *tmp;
> > +            QNum *qvalue;
> > +            tmp = qlist_peek(qlist);
> > +            g_assert(tmp);
> > +            qvalue = qobject_to_qnum(tmp);
> > +            g_assert_cmpuint(qnum_get_uint(qvalue, &error_abort), ==,
> i);
> > +            qobject_decref(qlist_pop(qlist));
> > +        }
> > +        break;
> > +
> > +    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
> > +    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
> > +    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
> > +    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
> > +        /* all integer elements in JSON arrays get stored into QInts
> when
> >           * we convert to QObjects, so we can check them all in the same
> >           * fashion, so simply fall through here
> >           */
>
> Make that "All signed integer ...", and wing both ends of the comment.
>

ok


> Or simply drop the comment.

-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 11/17] object: use more specific property type names
  2017-05-17  8:49   ` Markus Armbruster
@ 2017-05-30 13:58     ` Marc-André Lureau
  2017-05-31 13:18       ` Markus Armbruster
  0 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-30 13:58 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Wed, May 17, 2017 at 12:50 PM Markus Armbruster <armbru@redhat.com>
wrote:

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Use the actual unsigned integer type name (this should't break since
> > property type aren't directly accessed from outside it seems).
>
> I'm not sure I understand the parenthesis.  Do you mean changing the
> type names is safe because they're used only in a certain way?  Which
> way?
>

It looks like prop->type is only used internally by qom/object.c and not
exposed to QMP or other internal APIs, it would be nice if someone more
familiar with it could confirm.


> How did you find the names that need fixing?
>

Mostly by grepping and reviewing the code, I don't have a better approach..


>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  backends/cryptodev.c |  2 +-
> >  hw/pci-host/piix.c   |  8 ++++----
> >  hw/pci-host/q35.c    | 10 +++++-----
> >  hw/ppc/pnv.c         |  2 +-
> >  net/dump.c           |  2 +-
> >  net/filter-buffer.c  |  2 +-
> >  6 files changed, 13 insertions(+), 13 deletions(-)
> >
> > diff --git a/backends/cryptodev.c b/backends/cryptodev.c
> > index 832f056266..1764c179fe 100644
> > --- a/backends/cryptodev.c
> > +++ b/backends/cryptodev.c
> > @@ -222,7 +222,7 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc,
> Error **errp)
> >
> >  static void cryptodev_backend_instance_init(Object *obj)
> >  {
> > -    object_property_add(obj, "queues", "int",
> > +    object_property_add(obj, "queues", "uint32",
> >                            cryptodev_backend_get_queues,
> >                            cryptodev_backend_set_queues,
> >                            NULL, NULL, NULL);
>
> Correct, because the callbacks access struct CryptoDevBackendPeers
> member queues, which is uint32_t.
>
> The callbacks pass a local variable instead of the struct member to the
> visitor.  Problematic, because it weakens the type checking we get from
> the compiler.  Let's tighten it up:
>
>    static void
>    cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
>                                 void *opaque, Error **errp)
>    {
>        CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
>   -    uint32_t value = backend->conf.peers.queues;
>
>   -    visit_type_uint32(v, name, &value, errp);
>   +    visit_type_uint32(v, name, &backend->conf.peers.queues, errp);
>    }
>
>    static void
>    cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
>                                 void *opaque, Error **errp)
>    {
>        CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
>        Error *local_err = NULL;
>   -    uint32_t value;
>
>   -    visit_type_uint32(v, name, &value, &local_err);
>   +    visit_type_uint32(v, name, &backend->conf.peers.queues, &local_err);
>        if (local_err) {
>            goto out;
>        }
>   -    if (!value) {
>   +    if (!backend->conf.peers.queues) {
>            error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
>   -                   PRIu32 "'", object_get_typename(obj), name, value);
>   +                   PRIu32 "'", object_get_typename(obj), name,
>   +                   backend->conf.peers.queues);
>   -        goto out;
>        }
>   -    backend->conf.peers.queues = value;
>   -out:
>        error_propagate(errp, local_err);
>    }
>
> If we need to preserve backend->conf.peers.queue on an attempt to set it
> to zero, things get a bit more complicated.  But having the compiler
> enforce the visitor matches the member type exactly is worth it, in my
> opinion.
>
> Separate patch, not necessarily in this series.
>
> > diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> > index f9218aa952..9aed6225bf 100644
> > --- a/hw/pci-host/piix.c
> > +++ b/hw/pci-host/piix.c
> > @@ -279,19 +279,19 @@ static void i440fx_pcihost_initfn(Object *obj)
> >      memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
> >                            "pci-conf-data", 4);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
> >                          i440fx_pcihost_get_pci_hole_start,
> >                          NULL, NULL, NULL, NULL);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
> >                          i440fx_pcihost_get_pci_hole_end,
> >                          NULL, NULL, NULL, NULL);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
> >                          i440fx_pcihost_get_pci_hole64_start,
> >                          NULL, NULL, NULL, NULL);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
> >                          i440fx_pcihost_get_pci_hole64_end,
> >                          NULL, NULL, NULL, NULL);
> >  }
>
> These look good.  The underlying values are 64 bits, but the 32 bit
> callbacks assert they fit into 32.
>
> > diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
> > index 344f77b10c..5438be8253 100644
> > --- a/hw/pci-host/q35.c
> > +++ b/hw/pci-host/q35.c
> > @@ -176,23 +176,23 @@ static void q35_host_initfn(Object *obj)
> >      qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
> >      qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
> >                          q35_host_get_pci_hole_start,
> >                          NULL, NULL, NULL, NULL);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
> >                          q35_host_get_pci_hole_end,
> >                          NULL, NULL, NULL, NULL);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
> >                          q35_host_get_pci_hole64_start,
> >                          NULL, NULL, NULL, NULL);
> >
> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
> >                          q35_host_get_pci_hole64_end,
> >                          NULL, NULL, NULL, NULL);
>
> Likewise.
>
> >
> > -    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
> > +    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint32",
> >                          q35_host_get_mmcfg_size,
> >                          NULL, NULL, NULL, NULL);
>
> This one leads to a bug, I think:
>
>    static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char
> *name,
>                                        void *opaque, Error **errp)
>    {
>        PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
>        uint32_t value = e->size;
>
>        visit_type_uint32(v, name, &value, errp);
>    }
>
> e->size is hwaddr, i.e. uint64_t.  We silently truncate.
>
> Demonstrates that the detour through a separate variable breeds bugs and
> should be avoided.
>
> Suggested fix:
>
>    static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char
> *name,
>                                        void *opaque, Error **errp)
>    {
>        PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
>   -    uint32_t value = e->size;
>
>   -    visit_type_uint64(v, name, &value, errp);
>   +    visit_type_uint64(v, name, &e->size, errp);
>    }
>
> You then have to change the type name to "uint64" instead of "uint32",
> of course.
>

Ok, although this bug exist before the type name change, right? I'll make
it a seperate patch

>
> >
> > diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> > index d4bcdb027f..a964354081 100644
> > --- a/hw/ppc/pnv.c
> > +++ b/hw/ppc/pnv.c
> > @@ -1110,7 +1110,7 @@ static void powernv_machine_initfn(Object *obj)
> >
> >  static void powernv_machine_class_props_init(ObjectClass *oc)
> >  {
> > -    object_class_property_add(oc, "num-chips", "uint32_t",
> > +    object_class_property_add(oc, "num-chips", "uint32",
> >                                pnv_get_num_chips, pnv_set_num_chips,
> >                                NULL, NULL, NULL);
> >      object_class_property_set_description(oc, "num-chips",
>
> Looks good.
>
> > diff --git a/net/dump.c b/net/dump.c
> > index 89a149b5dd..7f4d3fda52 100644
> > --- a/net/dump.c
> > +++ b/net/dump.c
> > @@ -325,7 +325,7 @@ static void filter_dump_instance_init(Object *obj)
> >
> >      nfds->maxlen = 65536;
> >
> > -    object_property_add(obj, "maxlen", "int", filter_dump_get_maxlen,
> > +    object_property_add(obj, "maxlen", "uint32", filter_dump_get_maxlen,
> >                          filter_dump_set_maxlen, NULL, NULL, NULL);
> >      object_property_add_str(obj, "file", file_dump_get_filename,
> >                              file_dump_set_filename, NULL);
>
> Same type checking weakness as in cryptodev.c.
>
> > diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> > index cc6bd94445..9ce96aaa35 100644
> > --- a/net/filter-buffer.c
> > +++ b/net/filter-buffer.c
> > @@ -191,7 +191,7 @@ out:
> >
> >  static void filter_buffer_init(Object *obj)
> >  {
> > -    object_property_add(obj, "interval", "int",
> > +    object_property_add(obj, "interval", "uint32",
> >                          filter_buffer_get_interval,
> >                          filter_buffer_set_interval, NULL, NULL, NULL);
> >  }
>
> Likeise.
>
> Aside: I dislike having to define setters and getters for everything in
> QOM.  It's flexible, but verbose and error-prone when the flexibility
> isn't actually needed.
>
> --
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases
  2017-05-30  3:40     ` Fam Zheng
@ 2017-05-30 14:17       ` Eric Blake
  0 siblings, 0 replies; 70+ messages in thread
From: Eric Blake @ 2017-05-30 14:17 UTC (permalink / raw)
  To: Fam Zheng, Markus Armbruster; +Cc: Marc-André Lureau, qemu-devel

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

On 05/29/2017 10:40 PM, Fam Zheng wrote:

> In-Reply-To: <20170509173559.31598-4-marcandre.lureau@redhat.com>
> 	(=?utf-8?Q?=22Marc-Andr=C3=A9?=
> 	Lureau"'s message of "Tue, 9 May 2017 20:35:45 +0300")
> 

>> in-reply-to     =       "In-Reply-To:" 1*msg-id CRLF
>>

msg-id          =       [CFWS] "<" id-left "@" id-right ">" [CFWS]

then looking at 3.2.3 on folding white space and comments:

CFWS            =       *([FWS] comment) (([FWS] comment) / FWS)

comment         =       "(" *([FWS] ccontent) [FWS] ")"

> I can imagine if consider CFWS, patchew should probably just work (I can fix
> that), but it's still good to understand this.

So yes, I think the comment is valid per the grammar, and patchew should
be taught to recognize it.

-- 
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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-30  7:32     ` Marc-André Lureau
@ 2017-05-30 14:19       ` Eric Blake
  2017-05-30 14:23       ` Markus Armbruster
  1 sibling, 0 replies; 70+ messages in thread
From: Eric Blake @ 2017-05-30 14:19 UTC (permalink / raw)
  To: Marc-André Lureau, Markus Armbruster; +Cc: qemu-devel

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

On 05/30/2017 02:32 AM, Marc-André Lureau wrote:
> Hi
> 
> On Thu, May 11, 2017 at 6:30 PM Markus Armbruster <armbru@redhat.com> wrote:
> 
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>
>>> + *
>>> + * This work is licensed under the terms of the GNU LGPL, version 2.1
>> or later.
>>> + * See the COPYING.LIB file in the top-level directory.
>>> + */
>>> +
>>> +#ifndef QNUM_H
>>> +#define QNUM_H
>>> +
>>> +#include "qapi/qmp/qobject.h"
>>> +
>>> +typedef enum {
>>> +    QNUM_I64,
>>> +    QNUM_DOUBLE
>>> +} QNumType;
>>
>> Not bool because you're going to add to it.  Good.
>>
>>
> Hmm? There is no plan to add bool there so far, I am not sure that makes
> sense.

I think the intent was more along these lines:

"Using a two-element enum instead of a bool because a later patch will
add to the enum" (with the implication that an enum is better for
representing tri-state than a pair of bools).

At any rate, the only change I'd make is to add the trailing comma to
QNUM_DOUBLE (C99 permits trailing commas, and consistently using them
makes for less churn down the road when extending an enum).

-- 
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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-30 11:35     ` Marc-André Lureau
@ 2017-05-30 14:22       ` Eric Blake
  2017-05-31  7:38         ` Marc-André Lureau
  2017-05-31 10:08       ` Markus Armbruster
  1 sibling, 1 reply; 70+ messages in thread
From: Eric Blake @ 2017-05-30 14:22 UTC (permalink / raw)
  To: Marc-André Lureau, Markus Armbruster; +Cc: qemu-devel

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

On 05/30/2017 06:35 AM, Marc-André Lureau wrote:
> Hi
> 
> On Mon, May 15, 2017 at 6:00 PM Markus Armbruster <armbru@redhat.com> wrote:
> 
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> Switch strtoll() usage to qemu_strtoi64() helper while at it.
>>>
>>> Replace temporarily the error in qnum_get_int() with values >INT64_MAX
>>> until the visitor is updated.
>>>
>>> Add a few tests for large numbers.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---
>>>  qobject/json-lexer.c               |  4 ++++
>>>  qobject/json-parser.c              | 30 ++++++++++++++++++++++--------
>>>  qobject/qnum.c                     |  4 ++--
>>>  tests/check-qjson.c                | 28 ++++++++++++++++++++++++++++
>>>  tests/check-qnum.c                 |  9 +++++----
>>>  tests/test-qobject-input-visitor.c |  7 ++-----
>>>  6 files changed, 63 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
>>> index af4a75e05b..a0beb0b106 100644
>>> --- a/qobject/json-lexer.c
>>> +++ b/qobject/json-lexer.c
>>> @@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
>>>      /* escape */
>>>      [IN_ESCAPE_LL] = {
>>>          ['d'] = JSON_ESCAPE,
>>> +        ['u'] = JSON_ESCAPE,

Do we really want to add MORE escape sequences to our pseudo-JSON escape
parser? I had a series a while back that was able to completely kill the
pseudo-JSON escapes, in favor of teaching the testsuite how to directly
handle %s (which is really the most useful of the escapes - we really
aren't using many others).

If there's interest in removing the JSON parser escape sequences, I can
revive my series.

-- 
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: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-30  7:32     ` Marc-André Lureau
  2017-05-30 14:19       ` Eric Blake
@ 2017-05-30 14:23       ` Markus Armbruster
  2017-05-30 15:36         ` Marc-André Lureau
  1 sibling, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-30 14:23 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Thu, May 11, 2017 at 6:30 PM Markus Armbruster <armbru@redhat.com> wrote:
>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>
>> > + *
>> > + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>> > + * See the COPYING.LIB file in the top-level directory.
>> > + */
>> > +
>> > +#ifndef QNUM_H
>> > +#define QNUM_H
>> > +
>> > +#include "qapi/qmp/qobject.h"
>> > +
>> > +typedef enum {
>> > +    QNUM_I64,
>> > +    QNUM_DOUBLE
>> > +} QNumType;
>>
>> Not bool because you're going to add to it.  Good.
>>
>>
> Hmm? There is no plan to add bool there so far, I am not sure that makes
> sense.

Misunderstanding.  I meant to say something like "defining an
enumeration with two values is usually silly, but you're going to add to
this one, so it's okay".

>> >  static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
>> > @@ -387,19 +384,19 @@ static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
>> >  {
>> >      QObjectInputVisitor *qiv = to_qiv(v);
>> >      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
>> > -    QInt *qint;
>> > +    QNum *qnum;
>> >
>> >      if (!qobj) {
>> >          return;
>> >      }
>> > -    qint = qobject_to_qint(qobj);
>> > -    if (!qint) {
>> > +    qnum = qobject_to_qnum(qobj);
>> > +    if (!qnum) {
>> >          error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
>> >                     full_name(qiv, name), "integer");
>> >          return;
>> >      }
>> >
>> > -    *obj = qint_get_int(qint);
>> > +    *obj = qnum_get_int(qnum, errp);
>>
>> Compare the error message a few lines up
>>
>>     Invalid parameter type for 'NAME', expected: integer
>>
>> to the one we get here:
>>
>>     The number is a float
>>
>> Which number?  There can be quite a few in a QMP command.  We need to
>> pass @name to qnum_get_int() for a decent error message, like
>>
>>     Parameter 'NAME' is not a 64 bit integer
>>
>>
> I suggest we do it the same way as qom/object.c, handle the error and
> prepend/modify it. Passing @name feels awkward, since qtypes don't have to
> have names.

I'm afraid prepending leads to inferior error messages.  What exactly do
you propose to prepend?

Can you point to a call of qnum_get_int() where the appropriate name
isn't readily available?

If callers of qnum_get_int() have to mess with the error message to get
a decent one, chances are qnum_get_int() should leave creating the Error
object to its callers by returning just an error code.  If many callers
need the same messages, they can share a wrapper.

>> >  int64_t qdict_get_int(const QDict *qdict, const char *key)
>> >  {
>> > -    return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
>> > +    return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)), &error_abort);
>>
>> Line is a bit long for my taste.
>>
>> >  }
>> >
>> >  /**
>> > @@ -260,15 +248,25 @@ const char *qdict_get_str(const QDict *qdict, const char *key)
>> >   * qdict_get_try_int(): Try to get integer mapped by 'key'
>> >   *
>> >   * Return integer mapped by 'key', if it is not present in
>> > - * the dictionary or if the stored object is not of QInt type
>> > + * the dictionary or if the stored object is not of QNum type
>>
>> Actually "is not a QNum representing an integer".
>>
>> >   * 'def_value' will be returned.
>> >   */
>> >  int64_t qdict_get_try_int(const QDict *qdict, const char *key,
>> >                            int64_t def_value)
>> >  {
>> > -    QInt *qint = qobject_to_qint(qdict_get(qdict, key));
>> > +    Error *err = NULL;
>> > +    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
>> > +    int64_t val = def_value;
>> > +
>> > +    if (qnum) {
>> > +        val = qnum_get_int(qnum, &err);
>> > +    }
>> > +    if (err) {
>> > +        error_free(err);
>> > +        val = def_value;
>> > +    }
>>
>> This is a bit inefficient: it creates and destroys an Error object.
>> Easily avoided with a predicate qnum_is_int().
>
> True, but a predicate would have to deal with the same implicit conversion
> as qnum_get_int(). Not sure it's worth the duplication.

I dislike duplicating the (small) switch less than the clumsy signalling
of failure by giving the caller an Error object to free.  Matter of
taste.  However, it adds to my uneasy feeling about the qnum_get_int()
interface.

Further up, we discussed qnum_get_int() leaving error messages to
callers by returning just an error code.  Would also eliminate the
clumsiness here.  Hmm.

>> >
>> > -    return qint ? qint_get_int(qint) : def_value;
>> > +    return val;
>> >  }
>> >
>> >  /**
>> > diff --git a/qobject/qfloat.c b/qobject/qfloat.c
>> > deleted file mode 100644
>> > index d5da847701..0000000000
>> > --- a/qobject/qfloat.c
>> > +++ /dev/null
>> > @@ -1,62 +0,0 @@
>> > -/*
>> > - * QFloat Module
>> > - *
>> > - * Copyright IBM, Corp. 2009
>> > - *
>> > - * Authors:
>> > - *  Anthony Liguori   <aliguori@us.ibm.com>
>> > - *
>> > - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>> > - * See the COPYING.LIB file in the top-level directory.
>> > - *
>> > - */
>> > -
>> > -#include "qemu/osdep.h"
>> > -#include "qapi/qmp/qfloat.h"
>> > -#include "qapi/qmp/qobject.h"
>> > -#include "qemu-common.h"
>> > -
>> > -/**
>> > - * qfloat_from_int(): Create a new QFloat from a float
>> > - *
>> > - * Return strong reference.
>> > - */
>> > -QFloat *qfloat_from_double(double value)
>> > -{
>> > -    QFloat *qf;
>> > -
>> > -    qf = g_malloc(sizeof(*qf));
>> > -    qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
>> > -    qf->value = value;
>> > -
>> > -    return qf;
>> > -}
>> > -
>> > -/**
>> > - * qfloat_get_double(): Get the stored float
>> > - */
>> > -double qfloat_get_double(const QFloat *qf)
>> > -{
>> > -    return qf->value;
>> > -}
>> > -
>> > -/**
>> > - * qobject_to_qfloat(): Convert a QObject into a QFloat
>> > - */
>> > -QFloat *qobject_to_qfloat(const QObject *obj)
>> > -{
>> > -    if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
>> > -        return NULL;
>> > -    }
>> > -    return container_of(obj, QFloat, base);
>> > -}
>> > -
>> > -/**
>> > - * qfloat_destroy_obj(): Free all memory allocated by a
>> > - * QFloat object
>> > - */
>> > -void qfloat_destroy_obj(QObject *obj)
>> > -{
>> > -    assert(obj != NULL);
>> > -    g_free(qobject_to_qfloat(obj));
>> > -}
>> > diff --git a/qobject/qint.c b/qobject/qint.c
>> > deleted file mode 100644
>> > index d7d1b3021f..0000000000
>> > --- a/qobject/qint.c
>> > +++ /dev/null
>> > @@ -1,61 +0,0 @@
>> > -/*
>> > - * QInt Module
>> > - *
>> > - * Copyright (C) 2009 Red Hat Inc.
>> > - *
>> > - * Authors:
>> > - *  Luiz Capitulino <lcapitulino@redhat.com>
>> > - *
>> > - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>> > - * See the COPYING.LIB file in the top-level directory.
>> > - */
>> > -
>> > -#include "qemu/osdep.h"
>> > -#include "qapi/qmp/qint.h"
>> > -#include "qapi/qmp/qobject.h"
>> > -#include "qemu-common.h"
>> > -
>> > -/**
>> > - * qint_from_int(): Create a new QInt from an int64_t
>> > - *
>> > - * Return strong reference.
>> > - */
>> > -QInt *qint_from_int(int64_t value)
>> > -{
>> > -    QInt *qi;
>> > -
>> > -    qi = g_malloc(sizeof(*qi));
>> > -    qobject_init(QOBJECT(qi), QTYPE_QINT);
>> > -    qi->value = value;
>> > -
>> > -    return qi;
>> > -}
>> > -
>> > -/**
>> > - * qint_get_int(): Get the stored integer
>> > - */
>> > -int64_t qint_get_int(const QInt *qi)
>> > -{
>> > -    return qi->value;
>> > -}
>> > -
>> > -/**
>> > - * qobject_to_qint(): Convert a QObject into a QInt
>> > - */
>> > -QInt *qobject_to_qint(const QObject *obj)
>> > -{
>> > -    if (!obj || qobject_type(obj) != QTYPE_QINT) {
>> > -        return NULL;
>> > -    }
>> > -    return container_of(obj, QInt, base);
>> > -}
>> > -
>> > -/**
>> > - * qint_destroy_obj(): Free all memory allocated by a
>> > - * QInt object
>> > - */
>> > -void qint_destroy_obj(QObject *obj)
>> > -{
>> > -    assert(obj != NULL);
>> > -    g_free(qobject_to_qint(obj));
>> > -}
>> > diff --git a/qobject/qjson.c b/qobject/qjson.c
>> > index b2f3bfec53..2e0930884e 100644
>> > --- a/qobject/qjson.c
>> > +++ b/qobject/qjson.c
>> > @@ -132,12 +132,11 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
>> >      case QTYPE_QNULL:
>> >          qstring_append(str, "null");
>> >          break;
>> > -    case QTYPE_QINT: {
>> > -        QInt *val = qobject_to_qint(obj);
>> > -        char buffer[1024];
>> > -
>> > -        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
>> > +    case QTYPE_QNUM: {
>> > +        QNum *val = qobject_to_qnum(obj);
>> > +        char *buffer = qnum_to_string(val);
>> >          qstring_append(str, buffer);
>> > +        g_free(buffer);
>> >          break;
>> >      }
>> >      case QTYPE_QSTRING: {
>> > @@ -234,34 +233,6 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
>> >          qstring_append(str, "]");
>> >          break;
>> >      }
>> > -    case QTYPE_QFLOAT: {
>> > -        QFloat *val = qobject_to_qfloat(obj);
>> > -        char buffer[1024];
>> > -        int len;
>> > -
>> > -        /* FIXME: snprintf() is locale dependent; but JSON requires
>> > -         * numbers to be formatted as if in the C locale. Dependence
>> > -         * on C locale is a pervasive issue in QEMU. */
>> > -        /* FIXME: This risks printing Inf or NaN, which are not valid
>> > -         * JSON values. */
>> > -        /* FIXME: the default precision of 6 for %f often causes
>> > -         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
>> > -         * and only rounding to a shorter number if the result would
>> > -         * still produce the same floating point value.  */
>> > -        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
>> > -        while (len > 0 && buffer[len - 1] == '0') {
>> > -            len--;
>> > -        }
>> > -
>> > -        if (len && buffer[len - 1] == '.') {
>> > -            buffer[len - 1] = 0;
>> > -        } else {
>> > -            buffer[len] = 0;
>> > -        }
>> > -
>> > -        qstring_append(str, buffer);
>> > -        break;
>> > -    }
>> >      case QTYPE_QBOOL: {
>> >          QBool *val = qobject_to_qbool(obj);
>> >
>> > diff --git a/qobject/qnum.c b/qobject/qnum.c
>> > new file mode 100644
>> > index 0000000000..8e9dd38350
>> > --- /dev/null
>> > +++ b/qobject/qnum.c
>> > @@ -0,0 +1,138 @@
>> > +/*
>> > + * QNum Module
>> > + *
>> > + * Copyright (C) 2009 Red Hat Inc.
>> > + *
>> > + * Authors:
>> > + *  Luiz Capitulino <lcapitulino@redhat.com>
>> > + *  Marc-André Lureau <marcandre.lureau@redhat.com>
>> > + *
>> > + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>> > + * See the COPYING.LIB file in the top-level directory.
>> > + */
>> > +
>> > +#include "qemu/osdep.h"
>> > +#include "qapi/error.h"
>> > +#include "qapi/qmp/qnum.h"
>> > +#include "qapi/qmp/qobject.h"
>> > +#include "qemu-common.h"
>> > +
>> > +/**
>> > + * qnum_from_int(): Create a new QNum from an int64_t
>> > + *
>> > + * Return strong reference.
>> > + */
>> > +QNum *qnum_from_int(int64_t value)
>> > +{
>> > +    QNum *qn = g_new(QNum, 1);
>> > +
>> > +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
>> > +    qn->type = QNUM_I64;
>> > +    qn->u.i64 = value;
>> > +
>> > +    return qn;
>> > +}
>> > +
>> > +/**
>> > + * qnum_from_double(): Create a new QNum from a double
>> > + *
>> > + * Return strong reference.
>> > + */
>> > +QNum *qnum_from_double(double value)
>> > +{
>> > +    QNum *qn = g_new(QNum, 1);
>> > +
>> > +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
>> > +    qn->type = QNUM_DOUBLE;
>> > +    qn->u.dbl = value;
>> > +
>> > +    return qn;
>> > +}
>> > +
>> > +/**
>> > + * qnum_get_int(): Get an integer representation of the number
>> > + */
>> > +int64_t qnum_get_int(const QNum *qn, Error **errp)
>> > +{
>> > +    switch (qn->type) {
>> > +    case QNUM_I64:
>> > +        return qn->u.i64;
>> > +    case QNUM_DOUBLE:
>> > +        error_setg(errp, "The number is a float");
>> > +        return 0;
>> > +    }
>> > +
>> > +    g_assert_not_reached();
>>
>> g_assert_not_reached() is problematic, see "[PATCH] checkpatch: Disallow
>> glib asserts in main code".
>>
>> Message-Id: <20170427165526.19836-1-dgilbert@redhat.com>
>> https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg05499.html
>>
>>
> Actually g_assert() and g_assert_not_reached() are accepted.

What exactly does g_assert() buy us over plain assert(), and
g_assert_not_reached() over assert(0)?

qapi/ overwhelmingly uses assert().

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-30 14:23       ` Markus Armbruster
@ 2017-05-30 15:36         ` Marc-André Lureau
  2017-06-02  6:30           ` Markus Armbruster
  0 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-30 15:36 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Tue, May 30, 2017 at 6:23 PM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>
> > Hi
> >
> > On Thu, May 11, 2017 at 6:30 PM Markus Armbruster <armbru@redhat.com>
> wrote:
> >
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >>
> >> > + *
> >> > + * This work is licensed under the terms of the GNU LGPL, version
> 2.1 or later.
> >> > + * See the COPYING.LIB file in the top-level directory.
> >> > + */
> >> > +
> >> > +#ifndef QNUM_H
> >> > +#define QNUM_H
> >> > +
> >> > +#include "qapi/qmp/qobject.h"
> >> > +
> >> > +typedef enum {
> >> > +    QNUM_I64,
> >> > +    QNUM_DOUBLE
> >> > +} QNumType;
> >>
> >> Not bool because you're going to add to it.  Good.
> >>
> >>
> > Hmm? There is no plan to add bool there so far, I am not sure that makes
> > sense.
>
> Misunderstanding.  I meant to say something like "defining an
> enumeration with two values is usually silly, but you're going to add to
> this one, so it's okay".
>
>
ok


> >> >  static void qobject_input_type_int64(Visitor *v, const char *name,
> int64_t *obj,
> >> > @@ -387,19 +384,19 @@ static void qobject_input_type_int64(Visitor
> *v, const char *name, int64_t *obj,
> >> >  {
> >> >      QObjectInputVisitor *qiv = to_qiv(v);
> >> >      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
> >> > -    QInt *qint;
> >> > +    QNum *qnum;
> >> >
> >> >      if (!qobj) {
> >> >          return;
> >> >      }
> >> > -    qint = qobject_to_qint(qobj);
> >> > -    if (!qint) {
> >> > +    qnum = qobject_to_qnum(qobj);
> >> > +    if (!qnum) {
> >> >          error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
> >> >                     full_name(qiv, name), "integer");
> >> >          return;
> >> >      }
> >> >
> >> > -    *obj = qint_get_int(qint);
> >> > +    *obj = qnum_get_int(qnum, errp);
> >>
> >> Compare the error message a few lines up
> >>
> >>     Invalid parameter type for 'NAME', expected: integer
> >>
> >> to the one we get here:
> >>
> >>     The number is a float
> >>
> >> Which number?  There can be quite a few in a QMP command.  We need to
> >> pass @name to qnum_get_int() for a decent error message, like
> >>
> >>     Parameter 'NAME' is not a 64 bit integer
> >>
> >>
> > I suggest we do it the same way as qom/object.c, handle the error and
> > prepend/modify it. Passing @name feels awkward, since qtypes don't have
> to
> > have names.
>
> I'm afraid prepending leads to inferior error messages.  What exactly do
> you propose to prepend?
>

The property @name


> Can you point to a call of qnum_get_int() where the appropriate name
> isn't readily available?
>
>
I haven't looked closely, but I suppose it's mostly in tests/


> If callers of qnum_get_int() have to mess with the error message to get
> a decent one, chances are qnum_get_int() should leave creating the Error
> object to its callers by returning just an error code.  If many callers
> need the same messages, they can share a wrapper.
>

qnum_get_(u)int() has various error messages, they are not that useful
though. I'll try to remove Error usage.


> >> >  int64_t qdict_get_int(const QDict *qdict, const char *key)
> >> >  {
> >> > -    return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
> >> > +    return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key)),
> &error_abort);
> >>
> >> Line is a bit long for my taste.
> >>
> >> >  }
> >> >
> >> >  /**
> >> > @@ -260,15 +248,25 @@ const char *qdict_get_str(const QDict *qdict,
> const char *key)
> >> >   * qdict_get_try_int(): Try to get integer mapped by 'key'
> >> >   *
> >> >   * Return integer mapped by 'key', if it is not present in
> >> > - * the dictionary or if the stored object is not of QInt type
> >> > + * the dictionary or if the stored object is not of QNum type
> >>
> >> Actually "is not a QNum representing an integer".
> >>
> >> >   * 'def_value' will be returned.
> >> >   */
> >> >  int64_t qdict_get_try_int(const QDict *qdict, const char *key,
> >> >                            int64_t def_value)
> >> >  {
> >> > -    QInt *qint = qobject_to_qint(qdict_get(qdict, key));
> >> > +    Error *err = NULL;
> >> > +    QNum *qnum = qobject_to_qnum(qdict_get(qdict, key));
> >> > +    int64_t val = def_value;
> >> > +
> >> > +    if (qnum) {
> >> > +        val = qnum_get_int(qnum, &err);
> >> > +    }
> >> > +    if (err) {
> >> > +        error_free(err);
> >> > +        val = def_value;
> >> > +    }
> >>
> >> This is a bit inefficient: it creates and destroys an Error object.
> >> Easily avoided with a predicate qnum_is_int().
> >
> > True, but a predicate would have to deal with the same implicit
> conversion
> > as qnum_get_int(). Not sure it's worth the duplication.
>
> I dislike duplicating the (small) switch less than the clumsy signalling
> of failure by giving the caller an Error object to free.  Matter of
> taste.  However, it adds to my uneasy feeling about the qnum_get_int()
> interface.
>
> Further up, we discussed qnum_get_int() leaving error messages to
> callers by returning just an error code.  Would also eliminate the
> clumsiness here.  Hmm.
>
>
yep


> >> >
> >> > -    return qint ? qint_get_int(qint) : def_value;
> >> > +    return val;
> >> >  }
> >> >
> >> >  /**
> >> > diff --git a/qobject/qfloat.c b/qobject/qfloat.c
> >> > deleted file mode 100644
> >> > index d5da847701..0000000000
> >> > --- a/qobject/qfloat.c
> >> > +++ /dev/null
> >> > @@ -1,62 +0,0 @@
> >> > -/*
> >> > - * QFloat Module
> >> > - *
> >> > - * Copyright IBM, Corp. 2009
> >> > - *
> >> > - * Authors:
> >> > - *  Anthony Liguori   <aliguori@us.ibm.com>
> >> > - *
> >> > - * This work is licensed under the terms of the GNU LGPL, version
> 2.1 or later.
> >> > - * See the COPYING.LIB file in the top-level directory.
> >> > - *
> >> > - */
> >> > -
> >> > -#include "qemu/osdep.h"
> >> > -#include "qapi/qmp/qfloat.h"
> >> > -#include "qapi/qmp/qobject.h"
> >> > -#include "qemu-common.h"
> >> > -
> >> > -/**
> >> > - * qfloat_from_int(): Create a new QFloat from a float
> >> > - *
> >> > - * Return strong reference.
> >> > - */
> >> > -QFloat *qfloat_from_double(double value)
> >> > -{
> >> > -    QFloat *qf;
> >> > -
> >> > -    qf = g_malloc(sizeof(*qf));
> >> > -    qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
> >> > -    qf->value = value;
> >> > -
> >> > -    return qf;
> >> > -}
> >> > -
> >> > -/**
> >> > - * qfloat_get_double(): Get the stored float
> >> > - */
> >> > -double qfloat_get_double(const QFloat *qf)
> >> > -{
> >> > -    return qf->value;
> >> > -}
> >> > -
> >> > -/**
> >> > - * qobject_to_qfloat(): Convert a QObject into a QFloat
> >> > - */
> >> > -QFloat *qobject_to_qfloat(const QObject *obj)
> >> > -{
> >> > -    if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
> >> > -        return NULL;
> >> > -    }
> >> > -    return container_of(obj, QFloat, base);
> >> > -}
> >> > -
> >> > -/**
> >> > - * qfloat_destroy_obj(): Free all memory allocated by a
> >> > - * QFloat object
> >> > - */
> >> > -void qfloat_destroy_obj(QObject *obj)
> >> > -{
> >> > -    assert(obj != NULL);
> >> > -    g_free(qobject_to_qfloat(obj));
> >> > -}
> >> > diff --git a/qobject/qint.c b/qobject/qint.c
> >> > deleted file mode 100644
> >> > index d7d1b3021f..0000000000
> >> > --- a/qobject/qint.c
> >> > +++ /dev/null
> >> > @@ -1,61 +0,0 @@
> >> > -/*
> >> > - * QInt Module
> >> > - *
> >> > - * Copyright (C) 2009 Red Hat Inc.
> >> > - *
> >> > - * Authors:
> >> > - *  Luiz Capitulino <lcapitulino@redhat.com>
> >> > - *
> >> > - * This work is licensed under the terms of the GNU LGPL, version
> 2.1 or later.
> >> > - * See the COPYING.LIB file in the top-level directory.
> >> > - */
> >> > -
> >> > -#include "qemu/osdep.h"
> >> > -#include "qapi/qmp/qint.h"
> >> > -#include "qapi/qmp/qobject.h"
> >> > -#include "qemu-common.h"
> >> > -
> >> > -/**
> >> > - * qint_from_int(): Create a new QInt from an int64_t
> >> > - *
> >> > - * Return strong reference.
> >> > - */
> >> > -QInt *qint_from_int(int64_t value)
> >> > -{
> >> > -    QInt *qi;
> >> > -
> >> > -    qi = g_malloc(sizeof(*qi));
> >> > -    qobject_init(QOBJECT(qi), QTYPE_QINT);
> >> > -    qi->value = value;
> >> > -
> >> > -    return qi;
> >> > -}
> >> > -
> >> > -/**
> >> > - * qint_get_int(): Get the stored integer
> >> > - */
> >> > -int64_t qint_get_int(const QInt *qi)
> >> > -{
> >> > -    return qi->value;
> >> > -}
> >> > -
> >> > -/**
> >> > - * qobject_to_qint(): Convert a QObject into a QInt
> >> > - */
> >> > -QInt *qobject_to_qint(const QObject *obj)
> >> > -{
> >> > -    if (!obj || qobject_type(obj) != QTYPE_QINT) {
> >> > -        return NULL;
> >> > -    }
> >> > -    return container_of(obj, QInt, base);
> >> > -}
> >> > -
> >> > -/**
> >> > - * qint_destroy_obj(): Free all memory allocated by a
> >> > - * QInt object
> >> > - */
> >> > -void qint_destroy_obj(QObject *obj)
> >> > -{
> >> > -    assert(obj != NULL);
> >> > -    g_free(qobject_to_qint(obj));
> >> > -}
> >> > diff --git a/qobject/qjson.c b/qobject/qjson.c
> >> > index b2f3bfec53..2e0930884e 100644
> >> > --- a/qobject/qjson.c
> >> > +++ b/qobject/qjson.c
> >> > @@ -132,12 +132,11 @@ static void to_json(const QObject *obj, QString
> *str, int pretty, int indent)
> >> >      case QTYPE_QNULL:
> >> >          qstring_append(str, "null");
> >> >          break;
> >> > -    case QTYPE_QINT: {
> >> > -        QInt *val = qobject_to_qint(obj);
> >> > -        char buffer[1024];
> >> > -
> >> > -        snprintf(buffer, sizeof(buffer), "%" PRId64,
> qint_get_int(val));
> >> > +    case QTYPE_QNUM: {
> >> > +        QNum *val = qobject_to_qnum(obj);
> >> > +        char *buffer = qnum_to_string(val);
> >> >          qstring_append(str, buffer);
> >> > +        g_free(buffer);
> >> >          break;
> >> >      }
> >> >      case QTYPE_QSTRING: {
> >> > @@ -234,34 +233,6 @@ static void to_json(const QObject *obj, QString
> *str, int pretty, int indent)
> >> >          qstring_append(str, "]");
> >> >          break;
> >> >      }
> >> > -    case QTYPE_QFLOAT: {
> >> > -        QFloat *val = qobject_to_qfloat(obj);
> >> > -        char buffer[1024];
> >> > -        int len;
> >> > -
> >> > -        /* FIXME: snprintf() is locale dependent; but JSON requires
> >> > -         * numbers to be formatted as if in the C locale. Dependence
> >> > -         * on C locale is a pervasive issue in QEMU. */
> >> > -        /* FIXME: This risks printing Inf or NaN, which are not valid
> >> > -         * JSON values. */
> >> > -        /* FIXME: the default precision of 6 for %f often causes
> >> > -         * rounding errors; we should be using DBL_DECIMAL_DIG (17),
> >> > -         * and only rounding to a shorter number if the result would
> >> > -         * still produce the same floating point value.  */
> >> > -        len = snprintf(buffer, sizeof(buffer), "%f",
> qfloat_get_double(val));
> >> > -        while (len > 0 && buffer[len - 1] == '0') {
> >> > -            len--;
> >> > -        }
> >> > -
> >> > -        if (len && buffer[len - 1] == '.') {
> >> > -            buffer[len - 1] = 0;
> >> > -        } else {
> >> > -            buffer[len] = 0;
> >> > -        }
> >> > -
> >> > -        qstring_append(str, buffer);
> >> > -        break;
> >> > -    }
> >> >      case QTYPE_QBOOL: {
> >> >          QBool *val = qobject_to_qbool(obj);
> >> >
> >> > diff --git a/qobject/qnum.c b/qobject/qnum.c
> >> > new file mode 100644
> >> > index 0000000000..8e9dd38350
> >> > --- /dev/null
> >> > +++ b/qobject/qnum.c
> >> > @@ -0,0 +1,138 @@
> >> > +/*
> >> > + * QNum Module
> >> > + *
> >> > + * Copyright (C) 2009 Red Hat Inc.
> >> > + *
> >> > + * Authors:
> >> > + *  Luiz Capitulino <lcapitulino@redhat.com>
> >> > + *  Marc-André Lureau <marcandre.lureau@redhat.com>
> >> > + *
> >> > + * This work is licensed under the terms of the GNU LGPL, version
> 2.1 or later.
> >> > + * See the COPYING.LIB file in the top-level directory.
> >> > + */
> >> > +
> >> > +#include "qemu/osdep.h"
> >> > +#include "qapi/error.h"
> >> > +#include "qapi/qmp/qnum.h"
> >> > +#include "qapi/qmp/qobject.h"
> >> > +#include "qemu-common.h"
> >> > +
> >> > +/**
> >> > + * qnum_from_int(): Create a new QNum from an int64_t
> >> > + *
> >> > + * Return strong reference.
> >> > + */
> >> > +QNum *qnum_from_int(int64_t value)
> >> > +{
> >> > +    QNum *qn = g_new(QNum, 1);
> >> > +
> >> > +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> >> > +    qn->type = QNUM_I64;
> >> > +    qn->u.i64 = value;
> >> > +
> >> > +    return qn;
> >> > +}
> >> > +
> >> > +/**
> >> > + * qnum_from_double(): Create a new QNum from a double
> >> > + *
> >> > + * Return strong reference.
> >> > + */
> >> > +QNum *qnum_from_double(double value)
> >> > +{
> >> > +    QNum *qn = g_new(QNum, 1);
> >> > +
> >> > +    qobject_init(QOBJECT(qn), QTYPE_QNUM);
> >> > +    qn->type = QNUM_DOUBLE;
> >> > +    qn->u.dbl = value;
> >> > +
> >> > +    return qn;
> >> > +}
> >> > +
> >> > +/**
> >> > + * qnum_get_int(): Get an integer representation of the number
> >> > + */
> >> > +int64_t qnum_get_int(const QNum *qn, Error **errp)
> >> > +{
> >> > +    switch (qn->type) {
> >> > +    case QNUM_I64:
> >> > +        return qn->u.i64;
> >> > +    case QNUM_DOUBLE:
> >> > +        error_setg(errp, "The number is a float");
> >> > +        return 0;
> >> > +    }
> >> > +
> >> > +    g_assert_not_reached();
> >>
> >> g_assert_not_reached() is problematic, see "[PATCH] checkpatch: Disallow
> >> glib asserts in main code".
> >>
> >> Message-Id: <20170427165526.19836-1-dgilbert@redhat.com>
> >> https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg05499.html
> >>
> >>
> > Actually g_assert() and g_assert_not_reached() are accepted.
>
> What exactly does g_assert() buy us over plain assert(), and
> g_assert_not_reached() over assert(0)?
>

g_assert() brings a bit more context, afaik, can be trapped for error
testing, and error reporting can be handled by an handler. Not that useful
to qemu, but could be for the graphical UI though.

g_assert_not_reached() is quite more readable than assert(0)


>
> qapi/ overwhelmingly uses assert().
>

ok, it's already a mix of assert & g_assert in qemu though
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-30 14:22       ` Eric Blake
@ 2017-05-31  7:38         ` Marc-André Lureau
  0 siblings, 0 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-31  7:38 UTC (permalink / raw)
  To: Eric Blake, Markus Armbruster; +Cc: qemu-devel

Hi

On Tue, May 30, 2017 at 6:22 PM Eric Blake <eblake@redhat.com> wrote:

> On 05/30/2017 06:35 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Mon, May 15, 2017 at 6:00 PM Markus Armbruster <armbru@redhat.com>
> wrote:
> >
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >>> Switch strtoll() usage to qemu_strtoi64() helper while at it.
> >>>
> >>> Replace temporarily the error in qnum_get_int() with values >INT64_MAX
> >>> until the visitor is updated.
> >>>
> >>> Add a few tests for large numbers.
> >>>
> >>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >>> ---
> >>>  qobject/json-lexer.c               |  4 ++++
> >>>  qobject/json-parser.c              | 30 ++++++++++++++++++++++--------
> >>>  qobject/qnum.c                     |  4 ++--
> >>>  tests/check-qjson.c                | 28 ++++++++++++++++++++++++++++
> >>>  tests/check-qnum.c                 |  9 +++++----
> >>>  tests/test-qobject-input-visitor.c |  7 ++-----
> >>>  6 files changed, 63 insertions(+), 19 deletions(-)
> >>>
> >>> diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
> >>> index af4a75e05b..a0beb0b106 100644
> >>> --- a/qobject/json-lexer.c
> >>> +++ b/qobject/json-lexer.c
> >>> @@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
> >>>      /* escape */
> >>>      [IN_ESCAPE_LL] = {
> >>>          ['d'] = JSON_ESCAPE,
> >>> +        ['u'] = JSON_ESCAPE,
>
> Do we really want to add MORE escape sequences to our pseudo-JSON escape
> parser? I had a series a while back that was able to completely kill the
> pseudo-JSON escapes, in favor of teaching the testsuite how to directly
> handle %s (which is really the most useful of the escapes - we really
> aren't using many others).
>
> If there's interest in removing the JSON parser escape sequences, I can
> revive my series.
>

I don't have a full picture of what we use it for, but if you can simplify
it, I am all for it.

In the meantime, I'll keep my change for testing and consistency. If your
patch goes first, I'll adapt it.

-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-30 11:35     ` Marc-André Lureau
  2017-05-30 14:22       ` Eric Blake
@ 2017-05-31 10:08       ` Markus Armbruster
  2017-05-31 10:53         ` Marc-André Lureau
  1 sibling, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-31 10:08 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Mon, May 15, 2017 at 6:00 PM Markus Armbruster <armbru@redhat.com> wrote:
>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Switch strtoll() usage to qemu_strtoi64() helper while at it.
>> >
>> > Replace temporarily the error in qnum_get_int() with values >INT64_MAX
>> > until the visitor is updated.
>> >
>> > Add a few tests for large numbers.
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[...]
>> > diff --git a/qobject/qnum.c b/qobject/qnum.c
>> > index be6307accf..2f87952db8 100644
>> > --- a/qobject/qnum.c
>> > +++ b/qobject/qnum.c
>> > @@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
>> >          return qn->u.i64;
>> >      case QNUM_U64:
>> >          if (qn->u.u64 > INT64_MAX) {
>> > -            error_setg(errp, "The number is too large, use qnum_get_uint()");
>> > -            return 0;
>> > +            /* temporarily accepts to cast to i64 until visitor is switched */
>> > +            error_report("The number is too large, use qnum_get_uint()");
>>
>> Awkward.  Can we avoid this somehow?
>>
>>
> by merging the next two patches? I think it's easier to understand why and
> how I came up with the following fix.

I played with it a bit.  Here's something that appears to do the trick:

PATCH 07: Drop changes to qobject/qnum.c tests/check-qnum.c
          Move change to tests/test-qobject-input-visitor.c to PATCH 08
PATCH 08: Move PATCH 09's change to hw/i386/acpi-build.c here
PATCH 09: No need to revert the changes dropped in PATCH 07; patch is
          now empty

Less churn, no temporary breakage, same end result.

Pushed as branch hack-qapi-qnum for your convenience:
https://repo.or.cz/qemu/armbru.git/shortlog/refs/heads/hack-qapi-qnum

Original is on branch review-qapi-qnum.

>> >          }
>> >          return qn->u.u64;
>> >      case QNUM_DOUBLE:
[...]

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

* Re: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
  2017-05-31 10:08       ` Markus Armbruster
@ 2017-05-31 10:53         ` Marc-André Lureau
  0 siblings, 0 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-31 10:53 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Wed, May 31, 2017 at 2:08 PM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>
> > Hi
> >
> > On Mon, May 15, 2017 at 6:00 PM Markus Armbruster <armbru@redhat.com>
> wrote:
> >
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >> > Switch strtoll() usage to qemu_strtoi64() helper while at it.
> >> >
> >> > Replace temporarily the error in qnum_get_int() with values >INT64_MAX
> >> > until the visitor is updated.
> >> >
> >> > Add a few tests for large numbers.
> >> >
> >> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> [...]
> >> > diff --git a/qobject/qnum.c b/qobject/qnum.c
> >> > index be6307accf..2f87952db8 100644
> >> > --- a/qobject/qnum.c
> >> > +++ b/qobject/qnum.c
> >> > @@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
> >> >          return qn->u.i64;
> >> >      case QNUM_U64:
> >> >          if (qn->u.u64 > INT64_MAX) {
> >> > -            error_setg(errp, "The number is too large, use
> qnum_get_uint()");
> >> > -            return 0;
> >> > +            /* temporarily accepts to cast to i64 until visitor is
> switched */
> >> > +            error_report("The number is too large, use
> qnum_get_uint()");
> >>
> >> Awkward.  Can we avoid this somehow?
> >>
> >>
> > by merging the next two patches? I think it's easier to understand why
> and
> > how I came up with the following fix.
>
> I played with it a bit.  Here's something that appears to do the trick:
>
> PATCH 07: Drop changes to qobject/qnum.c tests/check-qnum.c
>           Move change to tests/test-qobject-input-visitor.c to PATCH 08
> PATCH 08: Move PATCH 09's change to hw/i386/acpi-build.c here
> PATCH 09: No need to revert the changes dropped in PATCH 07; patch is
>           now empty
>
> Less churn, no temporary breakage, same end result.
>

ok


>
> Pushed as branch hack-qapi-qnum for your convenience:
> https://repo.or.cz/qemu/armbru.git/shortlog/refs/heads/hack-qapi-qnum
>
> Original is on branch review-qapi-qnum.
>
>
thanks that helped

> >> >          }
> >> >          return qn->u.u64;
> >> >      case QNUM_DOUBLE:
> [...]
>
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type
  2017-05-18 12:57   ` Markus Armbruster
@ 2017-05-31 11:10     ` Marc-André Lureau
  2017-05-31 13:23       ` Markus Armbruster
  0 siblings, 1 reply; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-31 11:10 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

On Thu, May 18, 2017 at 4:58 PM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
> > Use a more specific bool type.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Why doesn't this run afoul backward compatibility?  To answer the
> question, we need to enumerate affected external interfaces.
>
>
Right, this will break if we have users such as:

 -global PIIX4_PM.disable_s3=2

With this change, it will now error with:

qemu-system-x86_64: can't apply global PIIX4_PM.disable_s3=2: Invalid
parameter type for 'disable_s3', expected: boolean

Acceptable? otherwise, I drop the patch

thanks
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate
  2017-05-18 15:20   ` Markus Armbruster
@ 2017-05-31 12:22     ` Marc-André Lureau
  0 siblings, 0 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-31 12:22 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

----- Original Message -----
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > All those property usages are associated with unsigned integers, so use
> > appropriate getter/setter.
> 
> "Usages"?  I think this is a question of whether the property value is
> signed or unsigned.  I guess "those properties are" would work.
> 
> How did you find the ones that need changing?

By manual review of our properties. Not sure how we could do differently.

I have splitted the patch with your review comments for the various subsystems.

> 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  include/hw/isa/isa.h         |  2 +-
> >  hw/acpi/memory_hotplug.c     | 10 ++++----
> >  hw/acpi/nvdimm.c             | 10 ++++----
> >  hw/acpi/pcihp.c              |  6 ++---
> >  hw/arm/aspeed.c              |  4 ++--
> >  hw/arm/bcm2835_peripherals.c |  9 ++++----
> >  hw/arm/raspi.c               |  4 ++--
> >  hw/core/platform-bus.c       |  2 +-
> >  hw/i386/acpi-build.c         | 55
> >  ++++++++++++++++++++++----------------------
> >  hw/i386/pc.c                 |  6 ++---
> >  hw/i386/xen/xen-hvm.c        |  6 ++---
> >  hw/intc/arm_gicv3_common.c   |  2 +-
> >  hw/mem/pc-dimm.c             |  5 ++--
> >  hw/misc/auxbus.c             |  2 +-
> >  hw/misc/pvpanic.c            |  2 +-
> >  hw/ppc/pnv_core.c            |  2 +-
> >  hw/ppc/spapr.c               |  8 ++++---
> >  numa.c                       |  6 ++---
> >  target/i386/cpu.c            |  4 ++--
> >  ui/console.c                 |  4 ++--
> >  20 files changed, 77 insertions(+), 72 deletions(-)
> >
> > diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
> > index c2fdd70cdc..95593408ef 100644
> > --- a/include/hw/isa/isa.h
> > +++ b/include/hw/isa/isa.h
> > @@ -29,7 +29,7 @@ static inline uint16_t applesmc_port(void)
> >      Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
> >  
> >      if (obj) {
> > -        return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL);
> > +        return object_property_get_uint(obj, APPLESMC_PROP_IO_BASE, NULL);
> >      }
> >      return 0;
> >  }
> 
> The property is defined with DEFINE_PROP_UINT32().  Okay.
> 
> > diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
> > index 210073d283..db3c89ceab 100644
> > --- a/hw/acpi/memory_hotplug.c
> > +++ b/hw/acpi/memory_hotplug.c
> > @@ -83,11 +83,12 @@ static uint64_t acpi_memory_hotplug_read(void *opaque,
> > hwaddr addr,
> >      o = OBJECT(mdev->dimm);
> >      switch (addr) {
> >      case 0x0: /* Lo part of phys address where DIMM is mapped */
> > -        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) : 0;
> > +        val = o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) :
> > 0;
> >          trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
> >          break;
> >      case 0x4: /* Hi part of phys address where DIMM is mapped */
> > -        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) >>
> > 32 : 0;
> > +        val =
> > +            o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) >> 32
> > : 0;
> >          trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
> >          break;
> >      case 0x8: /* Lo part of DIMM size */
> 
> TYPE_PC_DIMM's property PC_DIMM_ADDR_PROP is defined with
> DEFINE_PROP_UINT64().  Okay.
> 
> > @@ -95,11 +96,12 @@ static uint64_t acpi_memory_hotplug_read(void *opaque,
> > hwaddr addr,
> >          trace_mhp_acpi_read_size_lo(mem_st->selector, val);
> >          break;
> >      case 0xc: /* Hi part of DIMM size */
> > -        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >>
> > 32 : 0;
> > +        val =
> > +            o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32
> > : 0;
> 
> pc_dimm_get_size() uses visit_type_int().  Does that need a matching
> update?
> 
> >          trace_mhp_acpi_read_size_hi(mem_st->selector, val);
> >          break;
> >      case 0x10: /* node proximity for _PXM method */
> > -        val = o ? object_property_get_int(o, PC_DIMM_NODE_PROP, NULL) : 0;
> > +        val = o ? object_property_get_uint(o, PC_DIMM_NODE_PROP, NULL) :
> > 0;
> >          trace_mhp_acpi_read_pxm(mem_st->selector, val);
> >          break;
> >      case 0x14: /* pack and return is_* fields */
> 
> TYPE_PC_DIMM's property PC_DIMM_NODE_PROP is defined with
> DEFINE_PROP_UINT32().  Okay.
> 
> > diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> > index 8e7d6ec034..e57027149d 100644
> > --- a/hw/acpi/nvdimm.c
> > +++ b/hw/acpi/nvdimm.c
> > @@ -236,14 +236,14 @@ static void
> >  nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
> >  {
> >      NvdimmNfitSpa *nfit_spa;
> > -    uint64_t addr = object_property_get_int(OBJECT(dev),
> > PC_DIMM_ADDR_PROP,
> > -                                            NULL);
> > +    uint64_t addr = object_property_get_uint(OBJECT(dev),
> > PC_DIMM_ADDR_PROP,
> > +                                             NULL);
> >      uint64_t size = object_property_get_int(OBJECT(dev),
> >      PC_DIMM_SIZE_PROP,
> >                                              NULL);
> 
> Here, you leave PC_DIMM_SIZE_PROP alone.  The code gets it signed and
> assigns it to unsigned.  Needs cleanup.
> 
> > -    uint32_t node = object_property_get_int(OBJECT(dev),
> > PC_DIMM_NODE_PROP,
> > -                                            NULL);
> > +    uint32_t node = object_property_get_uint(OBJECT(dev),
> > PC_DIMM_NODE_PROP,
> > +                                             NULL);
> >      int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> > -                                            NULL);
> > +                                       NULL);
> >  
> >      nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
> >  
> 
> More of the same.
> 
> > diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
> > index 3a531a4416..c420a388ea 100644
> > --- a/hw/acpi/pcihp.c
> > +++ b/hw/acpi/pcihp.c
> > @@ -62,10 +62,10 @@ typedef struct AcpiPciHpFind {
> >  static int acpi_pcihp_get_bsel(PCIBus *bus)
> >  {
> >      Error *local_err = NULL;
> > -    int64_t bsel = object_property_get_int(OBJECT(bus),
> > ACPI_PCIHP_PROP_BSEL,
> > -                                           &local_err);
> > +    uint64_t bsel = object_property_get_uint(OBJECT(bus),
> > ACPI_PCIHP_PROP_BSEL,
> > +                                             &local_err);
> >  
> > -    if (local_err || bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
> > +    if (local_err || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
> >          if (local_err) {
> >              error_free(local_err);
> >          }
> 
> Haven't I seen ACPI_PCIHP_PROP_BSEL before?  Yes, in PATCH 13.  I think
> splitting along subsystems rather than functions changed would be easier
> to review, because the what the reviewer needs to understand is not so
> much the functions but the underlying properties.
> 
> > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > index 283c038814..4af422909f 100644
> > --- a/hw/arm/aspeed.c
> > +++ b/hw/arm/aspeed.c
> > @@ -187,8 +187,8 @@ static void aspeed_board_init(MachineState *machine,
> >       * Allocate RAM after the memory controller has checked the size
> >       * was valid. If not, a default value is used.
> >       */
> > -    ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
> > -                                       &error_abort);
> > +    ram_size = object_property_get_uint(OBJECT(&bmc->soc), "ram-size",
> > +                                        &error_abort);
> 
> The assignment to global ram_size looks nasty, but that particular
> nastiness is outside this patch's scope.
> 
> If I understand the aspeed code correctly, then this property is an
> alias for device TYPE_ASPEED_SDMC's property "ram-size", which is
> defined with DEFINE_PROP_UINT64().  Okay.
> 
> However, a few lines further up, we have:
> 
>        object_property_set_int(OBJECT(&bmc->soc), ram_size, "ram-size",
>                               &error_abort);
> 
> The two should be kept consistent.
> 
> Adds urgency to my question how you found the ones that need changing.
> 
> >  
> >      memory_region_allocate_system_memory(&bmc->ram, NULL, "ram",
> >      ram_size);
> >      memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
> > diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
> > index 369ef1e3bd..b168c6f83e 100644
> > --- a/hw/arm/bcm2835_peripherals.c
> > +++ b/hw/arm/bcm2835_peripherals.c
> > @@ -126,7 +126,7 @@ static void bcm2835_peripherals_realize(DeviceState
> > *dev, Error **errp)
> >      Object *obj;
> >      MemoryRegion *ram;
> >      Error *err = NULL;
> > -    uint32_t ram_size, vcram_size;
> > +    uint64_t ram_size, vcram_size;
> >      int n;
> >  
> >      obj = object_property_get_link(OBJECT(dev), "ram", &err);
> > @@ -208,15 +208,14 @@ static void bcm2835_peripherals_realize(DeviceState
> > *dev, Error **errp)
> >                                 INTERRUPT_ARM_MAILBOX));
> >  
> >      /* Framebuffer */
> > -    vcram_size = (uint32_t)object_property_get_int(OBJECT(s),
> > "vcram-size",
> > -                                                   &err);
> > +    vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err);
> 
> This one appears to be an alias of TYPE_BCM2835_FB's property
> "vcram-size", which is defined with DEFINE_PROP_UINT32().  Okay.
> 
> >      if (err) {
> >          error_propagate(errp, err);
> >          return;
> >      }
> >  
> > -    object_property_set_int(OBJECT(&s->fb), ram_size - vcram_size,
> > -                            "vcram-base", &err);
> > +    object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size,
> > +                             "vcram-base", &err);
> >      if (err) {
> >          error_propagate(errp, err);
> >          return;
> 
> Defined with DEFINE_PROP_UINT32().  Okay.
> 
> > diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> > index 2b295f14c4..32cdc98c6d 100644
> > --- a/hw/arm/raspi.c
> > +++ b/hw/arm/raspi.c
> > @@ -153,8 +153,8 @@ static void raspi2_init(MachineState *machine)
> >      qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
> >      object_property_set_bool(OBJECT(carddev), true, "realized",
> >      &error_fatal);
> >  
> > -    vcram_size = object_property_get_int(OBJECT(&s->soc), "vcram-size",
> > -                                         &error_abort);
> > +    vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
> > +                                          &error_abort);
> >      setup_boot(machine, 2, machine->ram_size - vcram_size);
> >  }
> 
> Same property as above.  Okay.
> 
> >  
> > diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
> > index 329ac670c0..33d32fbf22 100644
> > --- a/hw/core/platform-bus.c
> > +++ b/hw/core/platform-bus.c
> > @@ -71,7 +71,7 @@ hwaddr platform_bus_get_mmio_addr(PlatformBusDevice
> > *pbus, SysBusDevice *sbdev,
> >          return -1;
> >      }
> >  
> > -    return object_property_get_int(OBJECT(sbdev_mr), "addr", NULL);
> > +    return object_property_get_uint(OBJECT(sbdev_mr), "addr", NULL);
> >  }
> 
> I figure this is TYPE_MEMORY_REGION's property.  Its getter
> memory_region_get_addr() uses visit_type_uint64().  Okay.
> 
> >  
> >  static void platform_bus_count_irqs(SysBusDevice *sbdev, void *opaque)
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 27ad420914..76d27ff024 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -137,9 +137,9 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
> >          obj = piix;
> >          pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
> >          pm->pcihp_io_base =
> > -            object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
> > +            object_property_get_uint(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
> >          pm->pcihp_io_len =
> > -            object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
> > +            object_property_get_uint(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
> >      }
> >      if (lpc) {
> >          obj = lpc;
> 
> These appear to be defined with object_property_add_uint16_ptr().  Okay,
> I think.
> 
> > @@ -171,20 +171,21 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
> >      qobject_decref(o);
> >  
> >      /* Fill in mandatory properties */
> > -    pm->sci_int = object_property_get_int(obj, ACPI_PM_PROP_SCI_INT,
> > NULL);
> > -
> > -    pm->acpi_enable_cmd = object_property_get_int(obj,
> > -
> > ACPI_PM_PROP_ACPI_ENABLE_CMD,
> > -                                                  NULL);
> > -    pm->acpi_disable_cmd = object_property_get_int(obj,
> > -
> > ACPI_PM_PROP_ACPI_DISABLE_CMD,
> > -                                                  NULL);
> > -    pm->io_base = object_property_get_int(obj, ACPI_PM_PROP_PM_IO_BASE,
> > -                                          NULL);
> > -    pm->gpe0_blk = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK,
> > +    pm->sci_int = object_property_get_uint(obj, ACPI_PM_PROP_SCI_INT,
> > NULL);
> > +
> > +    pm->acpi_enable_cmd = object_property_get_uint(obj,
> > +
> > ACPI_PM_PROP_ACPI_ENABLE_CMD,
> > +                                                   NULL);
> > +    pm->acpi_disable_cmd =
> > +        object_property_get_uint(obj,
> > +                                 ACPI_PM_PROP_ACPI_DISABLE_CMD,
> > +                                 NULL);
> > +    pm->io_base = object_property_get_uint(obj, ACPI_PM_PROP_PM_IO_BASE,
> >                                             NULL);
> > -    pm->gpe0_blk_len = object_property_get_int(obj,
> > ACPI_PM_PROP_GPE0_BLK_LEN,
> > -                                               NULL);
> > +    pm->gpe0_blk = object_property_get_uint(obj, ACPI_PM_PROP_GPE0_BLK,
> > +                                            NULL);
> > +    pm->gpe0_blk_len = object_property_get_uint(obj,
> > ACPI_PM_PROP_GPE0_BLK_LEN,
> > +                                                NULL);
> >      pm->pcihp_bridge_en =
> >          object_property_get_bool(obj,
> >          "acpi-pci-hotplug-with-bridge-support",
> >                                   NULL);
> 
> PIIX4: piix4_pm_add_propeties() defines these with
> object_property_add_uint*_ptr().
> 
> Q35: ich9_lpc_add_properties() and ich9_pm_add_properties() define them
> similarly, except for ACPI_PM_PROP_GPE0_BLK().  That one's getter
> ich9_pm_get_gpe0_blk() uses visit_type_uint32().
> 
> Okay.
> 
> > @@ -237,19 +238,19 @@ static void acpi_get_pci_holes(Range *hole, Range
> > *hole64)
> >      g_assert(pci_host);
> >  
> >      range_set_bounds1(hole,
> > -                      object_property_get_int(pci_host,
> > -
> > PCI_HOST_PROP_PCI_HOLE_START,
> > -                                              NULL),
> > -                      object_property_get_int(pci_host,
> > -                                              PCI_HOST_PROP_PCI_HOLE_END,
> > -                                              NULL));
> > +                      object_property_get_uint(pci_host,
> > +
> > PCI_HOST_PROP_PCI_HOLE_START,
> > +                                               NULL),
> > +                      object_property_get_uint(pci_host,
> > +                                               PCI_HOST_PROP_PCI_HOLE_END,
> > +                                               NULL));
> >      range_set_bounds1(hole64,
> > -                      object_property_get_int(pci_host,
> > -
> > PCI_HOST_PROP_PCI_HOLE64_START,
> > -                                              NULL),
> > -                      object_property_get_int(pci_host,
> > -
> > PCI_HOST_PROP_PCI_HOLE64_END,
> > -                                              NULL));
> > +                      object_property_get_uint(pci_host,
> > +
> > PCI_HOST_PROP_PCI_HOLE64_START,
> > +                                               NULL),
> > +                      object_property_get_uint(pci_host,
> > +
> > PCI_HOST_PROP_PCI_HOLE64_END,
> > +                                               NULL));
> >  }
> >  
> 
> Deja vu again, this time PATCH 11.  Okay.
> 
> >  #define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT
> >  */
> > diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> > index f3b372a18f..8dc4507aa5 100644
> > --- a/hw/i386/pc.c
> > +++ b/hw/i386/pc.c
> > @@ -347,7 +347,7 @@ static int check_fdc(Object *obj, void *opaque)
> >          return 0;
> >      }
> >  
> > -    iobase = object_property_get_int(obj, "iobase", &local_err);
> > +    iobase = object_property_get_uint(obj, "iobase", &local_err);
> >      if (local_err || iobase != 0x3f0) {
> >          error_free(local_err);
> >          return 0;
> 
> TYPE_ISA_FDC's property "iobase" is defined with DEFINE_PROP_UINT32().
> Okay.
> 
> > @@ -1100,7 +1100,7 @@ static void pc_new_cpu(const char *typename, int64_t
> > apic_id, Error **errp)
> >  
> >      cpu = object_new(typename);
> >  
> > -    object_property_set_int(cpu, apic_id, "apic-id", &local_err);
> > +    object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
> >      object_property_set_bool(cpu, true, "realized", &local_err);
> >  
> 
> TYPE_X86_CPU's property "apic-id" is defined with DEFINE_PROP_UINT32().
> Okay.
> 
> >      object_unref(cpu);
> > @@ -1560,7 +1560,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq
> > *gsi,
> >               * and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23,
> >               * IRQ8 and IRQ2.
> >               */
> > -            uint8_t compat = object_property_get_int(OBJECT(hpet),
> > +            uint8_t compat = object_property_get_uint(OBJECT(hpet),
> >                      HPET_INTCAP, NULL);
> >              if (!compat) {
> >                  qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs);
> 
> TYPE_HPET's property HPET_INTCAP is defined with DEFINE_PROP_UINT32().
> Okay.
> 
> > diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> > index b1c05ffb86..cec259f82d 100644
> > --- a/hw/i386/xen/xen-hvm.c
> > +++ b/hw/i386/xen/xen-hvm.c
> > @@ -183,9 +183,9 @@ static void xen_ram_init(PCMachineState *pcms,
> >  {
> >      MemoryRegion *sysmem = get_system_memory();
> >      ram_addr_t block_len;
> > -    uint64_t user_lowmem = object_property_get_int(qdev_get_machine(),
> > -
> > PC_MACHINE_MAX_RAM_BELOW_4G,
> > -                                                   &error_abort);
> > +    uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
> > +
> > PC_MACHINE_MAX_RAM_BELOW_4G,
> > +                                                    &error_abort);
> >  
> >      /* Handle the machine opt max-ram-below-4g.  It is basically doing
> >       * min(xen limit, user limit).
> 
> TYPE_PC_MACHINE's property PC_MACHINE_MAX_RAM_BELOW_4G's getter and
> setter pc_machine_get_max_ram_below_4g() and
> pc_machine_set_max_ram_below_4g() use visit_type_size().  Okay.
> 
> > diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> > index c6493d6c07..e2064cd8c5 100644
> > --- a/hw/intc/arm_gicv3_common.c
> > +++ b/hw/intc/arm_gicv3_common.c
> > @@ -267,7 +267,7 @@ static void arm_gicv3_common_realize(DeviceState *dev,
> > Error **errp)
> >           *  VLPIS == 0 (virtual LPIs not supported)
> >           *  PLPIS == 0 (physical LPIs not supported)
> >           */
> > -        cpu_affid = object_property_get_int(OBJECT(cpu), "mp-affinity",
> > NULL);
> > +        cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity",
> > NULL);
> >          last = (i == s->num_cpu - 1);
> >  
> >          /* The CPU mp-affinity property is in MPIDR register format;
> >          squash
> 
> TYPE_ARM_CPU's property "mp-affinity" is defined with
> DEFINE_PROP_UINT64().  Okay.
> 
> > diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
> > index 9e8dab0e89..f6def8c239 100644
> > --- a/hw/mem/pc-dimm.c
> > +++ b/hw/mem/pc-dimm.c
> > @@ -46,7 +46,8 @@ void pc_dimm_memory_plug(DeviceState *dev,
> > MemoryHotplugState *hpms,
> >      uint64_t existing_dimms_capacity = 0;
> >      uint64_t addr;
> >  
> > -    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP,
> > &local_err);
> > +    addr = object_property_get_uint(OBJECT(dimm),
> > +                                    PC_DIMM_ADDR_PROP, &local_err);
> >      if (local_err) {
> >          goto out;
> >      }
> 
> Discussed above.
> 
> > @@ -73,7 +74,7 @@ void pc_dimm_memory_plug(DeviceState *dev,
> > MemoryHotplugState *hpms,
> >          goto out;
> >      }
> >  
> > -    object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP,
> > &local_err);
> > +    object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP,
> > &local_err);
> >      if (local_err) {
> >          goto out;
> >      }
> 
> Same.
> 
> > diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
> > index e4a7ba41de..8a90ddda84 100644
> > --- a/hw/misc/auxbus.c
> > +++ b/hw/misc/auxbus.c
> > @@ -244,7 +244,7 @@ static void aux_slave_dev_print(Monitor *mon,
> > DeviceState *dev, int indent)
> >  
> >      monitor_printf(mon, "%*smemory " TARGET_FMT_plx "/" TARGET_FMT_plx
> >      "\n",
> >                     indent, "",
> > -                   object_property_get_int(OBJECT(s->mmio), "addr", NULL),
> > +                   object_property_get_uint(OBJECT(s->mmio), "addr",
> > NULL),
> >                     memory_region_size(s->mmio));
> >  }
> >  
> 
> I figure this is again TYPE_MEMORY_REGION's property.
> 
> > diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
> > index 57da7f2199..2b1e9a6450 100644
> > --- a/hw/misc/pvpanic.c
> > +++ b/hw/misc/pvpanic.c
> > @@ -111,7 +111,7 @@ uint16_t pvpanic_port(void)
> >      if (!o) {
> >          return 0;
> >      }
> > -    return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
> > +    return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL);
> >  }
> >  
> 
> TYPE_ISA_PVPANIC_DEVICE's property PVPANIC_IOPORT_PROP is defined with
> DEFINE_PROP_UINT16().  Okay.
> 
> >  static Property pvpanic_isa_properties[] = {
> > diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
> > index 1b7ec70f03..142bad1e57 100644
> > --- a/hw/ppc/pnv_core.c
> > +++ b/hw/ppc/pnv_core.c
> > @@ -51,7 +51,7 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error
> > **errp)
> >      int thread_index = 0; /* TODO: TCG supports only one thread */
> >      ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
> >  
> > -    core_pir = object_property_get_int(OBJECT(cpu), "core-pir",
> > &error_abort);
> > +    core_pir = object_property_get_uint(OBJECT(cpu), "core-pir",
> > &error_abort);
> >  
> >      /*
> >       * The PIR of a thread is the core PIR + the thread index. We will
> 
> This seems to be an alias of TYPE_PNV_CORE's property "pir", which is
> defined with DEFINE_PROP_UINT32().  Okay.
> 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 80d12d005c..9b9a4e8817 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -2582,7 +2582,8 @@ static void spapr_memory_plug(HotplugHandler
> > *hotplug_dev, DeviceState *dev,
> >          goto out;
> >      }
> >  
> > -    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP,
> > &local_err);
> > +    addr = object_property_get_uint(OBJECT(dimm),
> > +                                    PC_DIMM_ADDR_PROP, &local_err);
> >      if (local_err) {
> >          pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
> >          goto out;
> 
> Discussed above.
> 
> > @@ -2670,7 +2671,8 @@ static void
> > spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
> >      uint64_t size = memory_region_size(mr);
> >      uint64_t addr;
> >  
> > -    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP,
> > &local_err);
> > +    addr = object_property_get_uint(OBJECT(dimm),
> > +                                    PC_DIMM_ADDR_PROP, &local_err);
> >      if (local_err) {
> >          goto out;
> >      }
> 
> Same.
> 
> > @@ -2878,7 +2880,7 @@ static void spapr_machine_device_plug(HotplugHandler
> > *hotplug_dev,
> >              error_setg(errp, "Memory hotplug not supported for this
> >              machine");
> >              return;
> >          }
> > -        node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
> > errp);
> > +        node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
> > errp);
> >          if (*errp) {
> >              return;
> >          }
> 
> Same.
> 
> > diff --git a/numa.c b/numa.c
> > index 6fc2393ddd..e32259fedb 100644
> > --- a/numa.c
> > +++ b/numa.c
> > @@ -205,7 +205,7 @@ static void numa_node_parse(NumaNodeOptions *node,
> > QemuOpts *opts, Error **errp)
> >          }
> >  
> >          object_ref(o);
> > -        numa_info[nodenr].node_mem = object_property_get_int(o, "size",
> > NULL);
> > +        numa_info[nodenr].node_mem = object_property_get_uint(o, "size",
> > NULL);
> >          numa_info[nodenr].node_memdev = MEMORY_BACKEND(o);
> >      }
> >      numa_info[nodenr].present = true;
> > @@ -527,8 +527,8 @@ static int query_memdev(Object *obj, void *opaque)
> >          m->value->id = object_property_get_str(obj, "id", NULL);
> >          m->value->has_id = !!m->value->id;
> >  
> > -        m->value->size = object_property_get_int(obj, "size",
> > -                                                 &error_abort);
> > +        m->value->size = object_property_get_uint(obj, "size",
> > +                                                  &error_abort);
> >          m->value->merge = object_property_get_bool(obj, "merge",
> >                                                     &error_abort);
> >          m->value->dump = object_property_get_bool(obj, "dump",
> 
> I figure "size" is a property of TYPE_MEMORY_BACKEND.
> host_memory_backend_get_size() and host_memory_backend_set_size() use
> visit_type_size().  Okay.
> 
> > diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> > index 5bb8131bb8..eb200ef58b 100644
> > --- a/target/i386/cpu.c
> > +++ b/target/i386/cpu.c
> > @@ -2324,8 +2324,8 @@ static void x86_cpu_load_def(X86CPU *cpu,
> > X86CPUDefinition *def, Error **errp)
> >       */
> >  
> >      /* CPU models only set _minimum_ values for level/xlevel: */
> > -    object_property_set_int(OBJECT(cpu), def->level, "min-level", errp);
> > -    object_property_set_int(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
> > +    object_property_set_uint(OBJECT(cpu), def->level, "min-level", errp);
> > +    object_property_set_uint(OBJECT(cpu), def->xlevel, "min-xlevel",
> > errp);
> >  
> >      object_property_set_int(OBJECT(cpu), def->family, "family", errp);
> >      object_property_set_int(OBJECT(cpu), def->model, "model", errp);
> 
> I figure these are properties of TYPE_X86_CPU, defined with
> DEFINE_PROP_UINT32().  Okay.
> 
> > diff --git a/ui/console.c b/ui/console.c
> > index ac66b3c910..ad3f7c6a2c 100644
> > --- a/ui/console.c
> > +++ b/ui/console.c
> > @@ -1872,8 +1872,8 @@ QemuConsole
> > *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
> >          if (DEVICE(obj) != dev) {
> >              continue;
> >          }
> > -        h = object_property_get_int(OBJECT(consoles[i]),
> > -                                    "head", &error_abort);
> > +        h = object_property_get_uint(OBJECT(consoles[i]),
> > +                                     "head", &error_abort);
> >          if (h != head) {
> >              continue;
> >          }
> 
> TYPE_QEMU_CONSOLE property "head" is defined with
> object_property_add_uint*_ptr().  Okay.
> 
> 
> Not your patch's fault, but I need to vent: to read a QOM property, we
> call a suitable object_property_get_FOO(), which uses the property's
> getter with a new QObject output visitor to get the property value as a
> QObject, converts the QObject to the C type for FOO, frees the QObject,
> and returns the converted value.
> 
> The getter knows the property's C type.
> 
> The code reading the property has to know the appropriate FOO for this C
> type.
> 
> The conversion from QObject to C type does a bit of dynamic type
> checking, so the code reading the property screws up too badly, we get
> at least a run time failure.  There is no protection against messing up
> signedness or width, and of course we mess up in places.
> 
> Writing is just as convoluted, opaque and error-prone.
> 
> This looks like a severe case of OOPitis to me.  There must be a better
> way!  The signedness issues you correct should have been flagged by the
> compiler or at least by Coverity.  Our OOPitis muddies the waters
> sufficiently to defeat both.

I agree, I find it convoluted too :)

thanks

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

* Re: [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt
  2017-05-30 12:28     ` Marc-André Lureau
@ 2017-05-31 13:10       ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-31 13:10 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Tue, May 16, 2017 at 9:33 PM Markus Armbruster <armbru@redhat.com> wrote:
>
>> On the subject: there is no such thing as "QUInt".  I guess you mean
>> "uint type" (like in PATCH 06's subject).  Could also say "QNUM_U64".
>>
>> Apropos subject: humor me, and start your subjects with a capital
>> letter, like this:
>>
>>     qapi: Update the qobject visitor ...
>>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Switch to use QNum/uint where appropriate to remove i64 limitation.
>> >
>> > The input visitor will cast i64 input to u64 for compatibility
>> > reasons (existing json QMP client already use negative i64 for large
>> > u64, and expect an implicit cast in qemu).
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> >  qapi/qobject-input-visitor.c        | 13 +++++++++++--
>> >  qapi/qobject-output-visitor.c       |  3 +--
>> >  tests/test-qobject-output-visitor.c | 21 ++++++++++++++++-----
>> >  3 files changed, 28 insertions(+), 9 deletions(-)
>> >
>> > diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
>> > index 785949ebab..72cefcf677 100644
>> > --- a/qapi/qobject-input-visitor.c
>> > +++ b/qapi/qobject-input-visitor.c
>> > @@ -420,9 +420,9 @@ static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
>> >  static void qobject_input_type_uint64(Visitor *v, const char *name,
>> >                                        uint64_t *obj, Error **errp)
>> >  {
>> > -    /* FIXME: qobject_to_qnum mishandles values over INT64_MAX */
>> >      QObjectInputVisitor *qiv = to_qiv(v);
>> >      QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
>> > +    Error *err = NULL;
>> >      QNum *qnum;
>> >
>> >      if (!qobj) {
>> > @@ -435,7 +435,16 @@ static void qobject_input_type_uint64(Visitor *v, const char *name,
>> >          return;
>> >      }
>> >
>> > -    *obj = qnum_get_int(qnum, errp);
>> > +    /* XXX: compatibility case, accept negative values as u64 */
>>
>> What does "XXX" signify?
>>
>
> It's a fairly common marker for something similar to FIXME (there are
> hundreds of them in qemu source tree).
>
> I'd like to leave a fixme that means that there should be a visitor
> flag/capability to fix this compatibility behaviour. (this could be exposed
> as a qmp capability)

What I don't like about XXX: it doesn't say whether it merely marks
something we intend to do or something that's actually broken.  The text
following it should clarify, but let's stick to FIXME for the latter
case, and TODO for the former.

A FIXME comment must explain what's broken.  It may explain how to fix
it.

A TODO comment should explain what we intend to do (d'oh).

Your XXX comment does neither, and that's also why I asked :)

>>
>> > +    *obj = qnum_get_int(qnum, &err);
>> > +
>>
>> Shouldn't the comment go right here?
>>
>>
> Above qnum_get_int() is the right place imho.

I may have a stronger opinion once I see the revised comment text.

>> > +    if (err) {
>> > +        error_free(err);
>> > +        err = NULL;
>> > +        *obj = qnum_get_uint(qnum, &err);
>> > +    }
>> > +
>> > +    error_propagate(errp, err);
>> >  }
>> >
>> >  static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
>> > diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
>> > index 2ca5093b22..70be84ccb5 100644
>> > --- a/qapi/qobject-output-visitor.c
>> > +++ b/qapi/qobject-output-visitor.c
>> > @@ -150,9 +150,8 @@ static void qobject_output_type_int64(Visitor *v, const char *name,
>> >  static void qobject_output_type_uint64(Visitor *v, const char *name,
>> >                                         uint64_t *obj, Error **errp)
>> >  {
>> > -    /* FIXME values larger than INT64_MAX become negative */
>> >      QObjectOutputVisitor *qov = to_qov(v);
>> > -    qobject_output_add(qov, name, qnum_from_int(*obj));
>> > +    qobject_output_add(qov, name, qnum_from_uint(*obj));
>>
>> Before the patch, uint64_t values above INT64_MAX are sent as negative
>> values, e.g. UINT64_MAX is sent as -1.
>>
>> After the patch, they are sent unmodified.  Clearly a bug fix, but we
>> have to consider compatibility issues anyway.  Does libvirt expect large
>> integers to be sent as negative integers?  Does it cope with this fix
>> gracefully?  Eric, any idea?
>>
>
> The libvirt json parser seems to rely on virStrToLong_ui(), which is a
> wrapper around strtoul(), so it accepts negative values with -2^63..-1.
> Changing it to return values larger than INT64_MAX should be ok.

Thanks for checking.

[...]

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

* Re: [Qemu-devel] [PATCH 11/17] object: use more specific property type names
  2017-05-30 13:58     ` Marc-André Lureau
@ 2017-05-31 13:18       ` Markus Armbruster
  0 siblings, 0 replies; 70+ messages in thread
From: Markus Armbruster @ 2017-05-31 13:18 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Wed, May 17, 2017 at 12:50 PM Markus Armbruster <armbru@redhat.com>
> wrote:
>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Use the actual unsigned integer type name (this should't break since
>> > property type aren't directly accessed from outside it seems).
>>
>> I'm not sure I understand the parenthesis.  Do you mean changing the
>> type names is safe because they're used only in a certain way?  Which
>> way?
>>
>
> It looks like prop->type is only used internally by qom/object.c and not
> exposed to QMP or other internal APIs, it would be nice if someone more
> familiar with it could confirm.

I see.  I can have a look once I'm done catching up with your replies.

>> How did you find the names that need fixing?
>
> Mostly by grepping and reviewing the code, I don't have a better approach..

Can't think of a better way offhand.  If something comes to me, I'll let
you know.  Thanks for going the extra mile!

>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> >  backends/cryptodev.c |  2 +-
>> >  hw/pci-host/piix.c   |  8 ++++----
>> >  hw/pci-host/q35.c    | 10 +++++-----
>> >  hw/ppc/pnv.c         |  2 +-
>> >  net/dump.c           |  2 +-
>> >  net/filter-buffer.c  |  2 +-
>> >  6 files changed, 13 insertions(+), 13 deletions(-)
>> >
>> > diff --git a/backends/cryptodev.c b/backends/cryptodev.c
>> > index 832f056266..1764c179fe 100644
>> > --- a/backends/cryptodev.c
>> > +++ b/backends/cryptodev.c
>> > @@ -222,7 +222,7 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc, Error **errp)
>> >
>> >  static void cryptodev_backend_instance_init(Object *obj)
>> >  {
>> > -    object_property_add(obj, "queues", "int",
>> > +    object_property_add(obj, "queues", "uint32",
>> >                            cryptodev_backend_get_queues,
>> >                            cryptodev_backend_set_queues,
>> >                            NULL, NULL, NULL);
>>
>> Correct, because the callbacks access struct CryptoDevBackendPeers
>> member queues, which is uint32_t.
>>
>> The callbacks pass a local variable instead of the struct member to the
>> visitor.  Problematic, because it weakens the type checking we get from
>> the compiler.  Let's tighten it up:
>>
>>    static void
>>    cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
>>                                 void *opaque, Error **errp)
>>    {
>>        CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
>>   -    uint32_t value = backend->conf.peers.queues;
>>
>>   -    visit_type_uint32(v, name, &value, errp);
>>   +    visit_type_uint32(v, name, &backend->conf.peers.queues, errp);
>>    }
>>
>>    static void
>>    cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
>>                                 void *opaque, Error **errp)
>>    {
>>        CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
>>        Error *local_err = NULL;
>>   -    uint32_t value;
>>
>>   -    visit_type_uint32(v, name, &value, &local_err);
>>   +    visit_type_uint32(v, name, &backend->conf.peers.queues, &local_err);
>>        if (local_err) {
>>            goto out;
>>        }
>>   -    if (!value) {
>>   +    if (!backend->conf.peers.queues) {
>>            error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
>>   -                   PRIu32 "'", object_get_typename(obj), name, value);
>>   +                   PRIu32 "'", object_get_typename(obj), name,
>>   +                   backend->conf.peers.queues);
>>   -        goto out;
>>        }
>>   -    backend->conf.peers.queues = value;
>>   -out:
>>        error_propagate(errp, local_err);
>>    }
>>
>> If we need to preserve backend->conf.peers.queue on an attempt to set it
>> to zero, things get a bit more complicated.  But having the compiler
>> enforce the visitor matches the member type exactly is worth it, in my
>> opinion.
>>
>> Separate patch, not necessarily in this series.
>>
>> > diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> > index f9218aa952..9aed6225bf 100644
>> > --- a/hw/pci-host/piix.c
>> > +++ b/hw/pci-host/piix.c
>> > @@ -279,19 +279,19 @@ static void i440fx_pcihost_initfn(Object *obj)
>> >      memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
>> >                            "pci-conf-data", 4);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
>> >                          i440fx_pcihost_get_pci_hole_start,
>> >                          NULL, NULL, NULL, NULL);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
>> >                          i440fx_pcihost_get_pci_hole_end,
>> >                          NULL, NULL, NULL, NULL);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
>> >                          i440fx_pcihost_get_pci_hole64_start,
>> >                          NULL, NULL, NULL, NULL);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
>> >                          i440fx_pcihost_get_pci_hole64_end,
>> >                          NULL, NULL, NULL, NULL);
>> >  }
>>
>> These look good.  The underlying values are 64 bits, but the 32 bit
>> callbacks assert they fit into 32.
>>
>> > diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> > index 344f77b10c..5438be8253 100644
>> > --- a/hw/pci-host/q35.c
>> > +++ b/hw/pci-host/q35.c
>> > @@ -176,23 +176,23 @@ static void q35_host_initfn(Object *obj)
>> >      qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
>> >      qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
>> >                          q35_host_get_pci_hole_start,
>> >                          NULL, NULL, NULL, NULL);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
>> >                          q35_host_get_pci_hole_end,
>> >                          NULL, NULL, NULL, NULL);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
>> >                          q35_host_get_pci_hole64_start,
>> >                          NULL, NULL, NULL, NULL);
>> >
>> > -    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
>> > +    object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
>> >                          q35_host_get_pci_hole64_end,
>> >                          NULL, NULL, NULL, NULL);
>>
>> Likewise.
>>
>> >
>> > -    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
>> > +    object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint32",
>> >                          q35_host_get_mmcfg_size,
>> >                          NULL, NULL, NULL, NULL);
>>
>> This one leads to a bug, I think:
>>
>>    static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char
>> *name,
>>                                        void *opaque, Error **errp)
>>    {
>>        PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
>>        uint32_t value = e->size;
>>
>>        visit_type_uint32(v, name, &value, errp);
>>    }
>>
>> e->size is hwaddr, i.e. uint64_t.  We silently truncate.
>>
>> Demonstrates that the detour through a separate variable breeds bugs and
>> should be avoided.
>>
>> Suggested fix:
>>
>>    static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char
>> *name,
>>                                        void *opaque, Error **errp)
>>    {
>>        PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
>>   -    uint32_t value = e->size;
>>
>>   -    visit_type_uint64(v, name, &value, errp);
>>   +    visit_type_uint64(v, name, &e->size, errp);
>>    }
>>
>> You then have to change the type name to "uint64" instead of "uint32",
>> of course.
>>
>
> Ok, although this bug exist before the type name change, right? I'll make
> it a seperate patch

Yes, please.

[...]

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

* Re: [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type
  2017-05-31 11:10     ` Marc-André Lureau
@ 2017-05-31 13:23       ` Markus Armbruster
  2017-05-31 13:26         ` Marc-André Lureau
  0 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-05-31 13:23 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> On Thu, May 18, 2017 at 4:58 PM Markus Armbruster <armbru@redhat.com> wrote:
>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>> > Use a more specific bool type.
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>
>> Why doesn't this run afoul backward compatibility?  To answer the
>> question, we need to enumerate affected external interfaces.
>>
>>
> Right, this will break if we have users such as:
>
>  -global PIIX4_PM.disable_s3=2
>
> With this change, it will now error with:
>
> qemu-system-x86_64: can't apply global PIIX4_PM.disable_s3=2: Invalid
> parameter type for 'disable_s3', expected: boolean
>
> Acceptable? otherwise, I drop the patch

Quick grep through libvirt... aha, src/qemu_command.c:

    if (def->pm.s3) {
        const char *pm_object = "PIIX4_PM";

        if (qemuDomainIsQ35(def) &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3)) {
            pm_object = "ICH9-LPC";
        } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S3)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           "%s", _("setting ACPI S3 not supported"));
            return -1;
        }

        virCommandAddArg(cmd, "-global");
        virCommandAddArgFormat(cmd, "%s.disable_s3=%d",
                               pm_object, def->pm.s3 == VIR_TRISTATE_BOOL_NO);
    }

We need to keep at least disable_s3=0 and disable_s3=1 working.  Let's
drop the patch from this series.

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

* Re: [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type
  2017-05-31 13:23       ` Markus Armbruster
@ 2017-05-31 13:26         ` Marc-André Lureau
  0 siblings, 0 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-05-31 13:26 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

On Wed, May 31, 2017 at 5:23 PM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>
> > On Thu, May 18, 2017 at 4:58 PM Markus Armbruster <armbru@redhat.com>
> wrote:
> >
> >> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> >>
> >> > Use a more specific bool type.
> >> >
> >> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >>
> >> Why doesn't this run afoul backward compatibility?  To answer the
> >> question, we need to enumerate affected external interfaces.
> >>
> >>
> > Right, this will break if we have users such as:
> >
> >  -global PIIX4_PM.disable_s3=2
> >
> > With this change, it will now error with:
> >
> > qemu-system-x86_64: can't apply global PIIX4_PM.disable_s3=2: Invalid
> > parameter type for 'disable_s3', expected: boolean
> >
> > Acceptable? otherwise, I drop the patch
>
> Quick grep through libvirt... aha, src/qemu_command.c:
>
>     if (def->pm.s3) {
>         const char *pm_object = "PIIX4_PM";
>
>         if (qemuDomainIsQ35(def) &&
>             virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3)) {
>             pm_object = "ICH9-LPC";
>         } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S3)) {
>             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>                            "%s", _("setting ACPI S3 not supported"));
>             return -1;
>         }
>
>         virCommandAddArg(cmd, "-global");
>         virCommandAddArgFormat(cmd, "%s.disable_s3=%d",
>                                pm_object, def->pm.s3 ==
> VIR_TRISTATE_BOOL_NO);
>     }
>
> We need to keep at least disable_s3=0 and disable_s3=1 working.  Let's
> drop the patch from this series.
>

Ah crap, I thought 0 and 1 where acceptable bool values, it's not the case..
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-05-30 15:36         ` Marc-André Lureau
@ 2017-06-02  6:30           ` Markus Armbruster
  2017-06-02 11:18             ` Marc-André Lureau
  0 siblings, 1 reply; 70+ messages in thread
From: Markus Armbruster @ 2017-06-02  6:30 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Tue, May 30, 2017 at 6:23 PM Markus Armbruster <armbru@redhat.com> wrote:
>
>> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>>
>> > Hi
>> >
>> > On Thu, May 11, 2017 at 6:30 PM Markus Armbruster <armbru@redhat.com> wrote:
[...]
>> >> g_assert_not_reached() is problematic, see "[PATCH] checkpatch: Disallow
>> >> glib asserts in main code".
>> >>
>> >> Message-Id: <20170427165526.19836-1-dgilbert@redhat.com>
>> >> https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg05499.html
>> >>
>> >>
>> > Actually g_assert() and g_assert_not_reached() are accepted.
>>
>> What exactly does g_assert() buy us over plain assert(), and
>> g_assert_not_reached() over assert(0)?
>>
>
> g_assert() brings a bit more context, afaik, can be trapped for error
> testing, and error reporting can be handled by an handler. Not that useful
> to qemu, but could be for the graphical UI though.
>
> g_assert_not_reached() is quite more readable than assert(0)

I'm all for making intent explicit, but what else could assert(0)
possibly mean?

>> qapi/ overwhelmingly uses assert().
>>
>
> ok, it's already a mix of assert & g_assert in qemu though

True.

In my opinion, we should use only one outside tests.  g_assert() if it
adds value, else plain assert().  "Outside tests", because g_assert()
might add sufficient value in tests even when it doesn't elsewhere.

Until then, I prefer to use only one *locally*.  In qapi/, that's plain
assert() now.

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

* Re: [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum
  2017-06-02  6:30           ` Markus Armbruster
@ 2017-06-02 11:18             ` Marc-André Lureau
  0 siblings, 0 replies; 70+ messages in thread
From: Marc-André Lureau @ 2017-06-02 11:18 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel

Hi

On Fri, Jun 2, 2017 at 10:30 AM Markus Armbruster <armbru@redhat.com> wrote:

> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
>
> > Hi
> >
> > On Tue, May 30, 2017 at 6:23 PM Markus Armbruster <armbru@redhat.com>
> wrote:
> >
> >> Marc-André Lureau <marcandre.lureau@gmail.com> writes:
> >>
> >> > Hi
> >> >
> >> > On Thu, May 11, 2017 at 6:30 PM Markus Armbruster <armbru@redhat.com>
> wrote:
> [...]
> >> >> g_assert_not_reached() is problematic, see "[PATCH] checkpatch:
> Disallow
> >> >> glib asserts in main code".
> >> >>
> >> >> Message-Id: <20170427165526.19836-1-dgilbert@redhat.com>
> >> >> https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg05499.html
> >> >>
> >> >>
> >> > Actually g_assert() and g_assert_not_reached() are accepted.
> >>
> >> What exactly does g_assert() buy us over plain assert(), and
> >> g_assert_not_reached() over assert(0)?
> >>
> >
> > g_assert() brings a bit more context, afaik, can be trapped for error
> > testing, and error reporting can be handled by an handler. Not that
> useful
> > to qemu, but could be for the graphical UI though.
> >
> > g_assert_not_reached() is quite more readable than assert(0)
>
> I'm all for making intent explicit, but what else could assert(0)
> possibly mean?
>
> >> qapi/ overwhelmingly uses assert().
> >>
> >
> > ok, it's already a mix of assert & g_assert in qemu though
>
> True.
>
> In my opinion, we should use only one outside tests.  g_assert() if it
> adds value, else plain assert().  "Outside tests", because g_assert()
> might add sufficient value in tests even when it doesn't elsewhere.
>
>
g_assert*() is useful in the unit under test, so you can check the assert
behaviour. This could be useful in particular for the assertions under
qapi/ since we have unit tests for those


> Until then, I prefer to use only one *locally*.  In qapi/, that's plain
> assert() now.
>

ok, fair enough
-- 
Marc-André Lureau

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

end of thread, other threads:[~2017-06-02 11:19 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field Marc-André Lureau
2017-05-09 18:40   ` Eric Blake
2017-05-11 11:59     ` Markus Armbruster
2017-05-11 12:07       ` Paolo Bonzini
2017-05-09 17:35 ` [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters Marc-André Lureau
2017-05-09 18:44   ` Eric Blake
2017-05-09 17:35 ` [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases Marc-André Lureau
2017-05-09 18:51   ` Eric Blake
2017-05-11 12:34     ` Markus Armbruster
2017-05-22 17:03   ` Markus Armbruster
2017-05-30  3:40     ` Fam Zheng
2017-05-30 14:17       ` Eric Blake
2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
2017-05-11 14:29   ` Markus Armbruster
2017-05-11 15:09     ` Eric Blake
2017-05-30  7:32     ` Marc-André Lureau
2017-05-30 14:19       ` Eric Blake
2017-05-30 14:23       ` Markus Armbruster
2017-05-30 15:36         ` Marc-André Lureau
2017-06-02  6:30           ` Markus Armbruster
2017-06-02 11:18             ` Marc-André Lureau
2017-05-12  6:30   ` Markus Armbruster
2017-05-12 13:00     ` Luiz Capitulino
2017-05-15  7:00       ` Markus Armbruster
2017-05-12  7:37   ` Markus Armbruster
2017-05-12 13:03     ` Luiz Capitulino
2017-05-15  6:35       ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 05/17] qapi: remove promote_int Marc-André Lureau
2017-05-11 17:30   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 06/17] qnum: add uint type Marc-André Lureau
2017-05-15  7:27   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers Marc-André Lureau
2017-05-15 13:59   ` Markus Armbruster
2017-05-30 11:35     ` Marc-André Lureau
2017-05-30 14:22       ` Eric Blake
2017-05-31  7:38         ` Marc-André Lureau
2017-05-31 10:08       ` Markus Armbruster
2017-05-31 10:53         ` Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt Marc-André Lureau
2017-05-16 17:31   ` Markus Armbruster
2017-05-17 16:26     ` Markus Armbruster
2017-05-30 12:28     ` Marc-André Lureau
2017-05-31 13:10       ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX Marc-André Lureau
2017-05-16 17:35   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter Marc-André Lureau
2017-05-16 17:41   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 11/17] object: use more specific property type names Marc-André Lureau
2017-05-17  8:49   ` Markus Armbruster
2017-05-30 13:58     ` Marc-André Lureau
2017-05-31 13:18       ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate Marc-André Lureau
2017-05-17 11:09   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type Marc-André Lureau
2017-05-17 17:42   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type Marc-André Lureau
2017-05-13 20:49   ` Philippe Mathieu-Daudé
2017-05-18 12:57   ` Markus Armbruster
2017-05-31 11:10     ` Marc-André Lureau
2017-05-31 13:23       ` Markus Armbruster
2017-05-31 13:26         ` Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate Marc-André Lureau
2017-05-18 15:20   ` Markus Armbruster
2017-05-31 12:22     ` Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint Marc-André Lureau
2017-05-18 15:27   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 17/17] qobject: move dump_qobject() from block/ to qobject/ Marc-André Lureau
2017-05-13 21:41 ` [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type no-reply
2017-05-18 15:39 ` Markus Armbruster

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.