diff --git a/include/qapi/util.h b/include/qapi/util.h index d7bfb30e25..257c600f99 100644 --- a/include/qapi/util.h +++ b/include/qapi/util.h @@ -11,9 +11,13 @@ #ifndef QAPI_UTIL_H #define QAPI_UTIL_H +/* QEnumLookup flags */ +#define QAPI_ENUM_DEPRECATED 1 + typedef struct QEnumLookup { const char *const *array; - int size; + const unsigned char *const flags; + const int size; } QEnumLookup; const char *qapi_enum_lookup(const QEnumLookup *lookup, int val); diff --git a/qapi/compat.json b/qapi/compat.json index 1d2b76f00c..74a8493d3d 100644 --- a/qapi/compat.json +++ b/qapi/compat.json @@ -42,7 +42,8 @@ # with feature 'deprecated'. We may want to extend it to cover # semantic aspects, CLI, and experimental features. # -# Limitation: not implemented for deprecated enumeration values. +# Limitation: deprecated-output policy @hide is not implemented for +# enumeration values. They behave the same as with policy @accept. # # @deprecated-input: how to handle deprecated input (default 'accept') # @deprecated-output: how to handle deprecated output (default 'accept') diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 93fb154ef3..617ef3fa46 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -393,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj, const QEnumLookup *lookup, Error **errp) { int64_t value; - char *enum_str; + g_autofree char *enum_str = NULL; if (!visit_type_str(v, name, &enum_str, errp)) { return false; @@ -403,11 +403,23 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj, if (value < 0) { error_setg(errp, "Parameter '%s' does not accept value '%s'", name ? name : "null", enum_str); - g_free(enum_str); return false; } - g_free(enum_str); + if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) { + switch (v->compat_policy.deprecated_input) { + case COMPAT_POLICY_INPUT_ACCEPT: + break; + case COMPAT_POLICY_INPUT_REJECT: + error_setg(errp, "Deprecated value '%s' disabled by policy", + enum_str); + return false; + case COMPAT_POLICY_INPUT_CRASH: + default: + abort(); + } + } + *obj = value; return true; } diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py index 831294fe42..ab2441adc9 100644 --- a/scripts/qapi/types.py +++ b/scripts/qapi/types.py @@ -38,6 +38,8 @@ objects_seen = set() def gen_enum_lookup(name: str, members: List[QAPISchemaEnumMember], prefix: Optional[str] = None) -> str: + max_index = c_enum_const(name, '_MAX', prefix) + flags = '' ret = mcgen(''' const QEnumLookup %(c_name)s_lookup = { @@ -52,13 +54,26 @@ const QEnumLookup %(c_name)s_lookup = { ''', index=index, name=memb.name) ret += memb.ifcond.gen_endif() + if 'deprecated' in (f.name for f in memb.features): + flags += mcgen(''' + [%(index)s] = QAPI_ENUM_DEPRECATED, +''', + index=index) + + if flags: + ret += mcgen(''' + }, + .flags = (const unsigned char[%(max_index)s]) { +''', + max_index=max_index) + ret += flags ret += mcgen(''' }, .size = %(max_index)s }; ''', - max_index=c_enum_const(name, '_MAX', prefix)) + max_index=max_index) return ret