diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 7cd1313129..74196847fa 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -33,7 +33,7 @@ struct Visitor void (*type_enum)(Visitor *v, int *obj, const char * const strings[], const char *kind, const char *name, Error **errp); /* May be NULL; only needed for input visitors. */ - void (*get_next_type)(Visitor *v, QType *type, + void (*get_next_type)(Visitor *v, QType *type, bool promote_int, const char *name, Error **errp); void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp); diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 6d25ad27a2..1414de1b0d 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -43,8 +43,9 @@ void visit_optional(Visitor *v, bool *present, const char *name, * Determine the qtype of the item @name in the current object visit. * For input visitors, set *@type to the correct qtype of a qapi * alternate type; for other visitors, leave *@type unchanged. + * If @promote_int, treat integers as QTYPE_FLOAT. */ -void visit_get_next_type(Visitor *v, QType *type, +void visit_get_next_type(Visitor *v, QType *type, bool promote_int, const char *name, Error **errp); void visit_type_enum(Visitor *v, int *obj, const char * const strings[], const char *kind, const char *name, Error **errp); diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 850ca034cb..cee76bc649 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -81,11 +81,11 @@ void visit_optional(Visitor *v, bool *present, const char *name, } } -void visit_get_next_type(Visitor *v, QType *type, +void visit_get_next_type(Visitor *v, QType *type, bool promote_int, const char *name, Error **errp) { if (v->get_next_type) { - v->get_next_type(v, type, name, errp); + v->get_next_type(v, type, promote_int, name, errp); } } diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index d398de743d..26b7414178 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -208,7 +208,7 @@ static void qmp_input_end_list(Visitor *v, Error **errp) qmp_input_pop(qiv, errp); } -static void qmp_input_get_next_type(Visitor *v, QType *type, +static void qmp_input_get_next_type(Visitor *v, QType *type, bool promote_int, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); @@ -219,6 +219,9 @@ static void qmp_input_get_next_type(Visitor *v, QType *type, return; } *type = qobject_type(qobj); + if (promote_int && *type == QTYPE_QINT) { + *type = QTYPE_QFLOAT; + } } static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name, diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 4797d6e050..b93690b608 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -184,6 +184,11 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s *obj, const char *name, Error def gen_visit_alternate(name, variants): + promote_int = 'true' + for var in variants.variants: + if var.type.alternate_qtype() == 'QTYPE_QINT': + promote_int = 'false' + ret = mcgen(''' void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp) @@ -194,16 +199,14 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error if (err) { goto out; } - visit_get_next_type(v, &(*obj)->type, name, &err); + visit_get_next_type(v, &(*obj)->type, %(promote_int)s, name, &err); if (err) { goto out_obj; } switch ((*obj)->type) { ''', - c_name=c_name(name)) + c_name=c_name(name), promote_int=promote_int) - # FIXME: When 'number' but not 'int' is present in the alternate, we - # should allow QTYPE_INT to promote to QTYPE_FLOAT. for var in variants.variants: ret += mcgen(''' case %(case)s: diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 43b9e18912..b4a5bee6a5 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -347,20 +347,16 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, error_free_or_abort(&err); qapi_free_AltStrBool(asb); - /* FIXME: integer should parse as number */ v = visitor_input_test_init(data, "42"); - visit_type_AltStrNum(v, &asn, NULL, &err); - /* FIXME g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT); */ - /* FIXME g_assert_cmpfloat(asn->u.n, ==, 42); */ - error_free_or_abort(&err); + visit_type_AltStrNum(v, &asn, NULL, &error_abort); + g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT); + g_assert_cmpfloat(asn->u.n, ==, 42); qapi_free_AltStrNum(asn); - /* FIXME: integer should parse as number */ v = visitor_input_test_init(data, "42"); - visit_type_AltNumStr(v, &ans, NULL, &err); - /* FIXME g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT); */ - /* FIXME g_assert_cmpfloat(ans->u.n, ==, 42); */ - error_free_or_abort(&err); + visit_type_AltNumStr(v, &ans, NULL, &error_abort); + g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT); + g_assert_cmpfloat(ans->u.n, ==, 42); qapi_free_AltNumStr(ans); v = visitor_input_test_init(data, "42");