From 8712fa5333ad348da20034b717dd814219d1ec11 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 26 Oct 2015 16:34:41 -0600 Subject: qapi: More idiomatic string operations Rather than slicing the end of a string, we can use python's endswith(). And rather than creating a set of characters, we can search for a character within a string. Signed-off-by: Eric Blake Message-Id: <1445898903-12082-3-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster --- scripts/qapi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index 9d53255320..3af4c2c737 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -172,7 +172,7 @@ class QAPISchemaParser(object): if self.tok == '#': self.cursor = self.src.find('\n', self.cursor) - elif self.tok in ['{', '}', ':', ',', '[', ']']: + elif self.tok in "{}:,[]": return elif self.tok == "'": string = '' @@ -390,7 +390,7 @@ def add_name(name, info, meta, implicit=False): raise QAPIExprError(info, "%s '%s' is already defined" % (all_names[name], name)) - if not implicit and name[-4:] == 'Kind': + if not implicit and name.endswith('Kind'): raise QAPIExprError(info, "%s '%s' should not end in 'Kind'" % (meta, name)) @@ -910,7 +910,7 @@ class QAPISchemaEnumType(QAPISchemaType): def is_implicit(self): # See QAPISchema._make_implicit_enum_type() - return self.name[-4:] == 'Kind' + return self.name.endswith('Kind') def c_type(self, is_param=False): return c_name(self.name) -- cgit v1.2.3-55-g7522 From 255960dd374d4497d6ea537305f1b0d8a3433789 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 26 Oct 2015 16:34:43 -0600 Subject: qapi: Reserve '*List' type names for list types Type names ending in 'List' can clash with qapi list types in generated C. We don't currently use such names. It is easier to outlaw them now than to worry about how to resolve such a clash in the future. For precedence, see commit 4dc2e69, which did the same for names ending in 'Kind' versus implicit enum types for qapi unions. Update the testsuite to match. Signed-off-by: Eric Blake Message-Id: <1445898903-12082-5-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster --- docs/qapi-code-gen.txt | 3 ++- scripts/qapi.py | 10 ++++------ tests/qapi-schema/reserved-type-list.err | 1 + tests/qapi-schema/reserved-type-list.exit | 2 +- tests/qapi-schema/reserved-type-list.json | 6 +++--- tests/qapi-schema/reserved-type-list.out | 3 --- 6 files changed, 11 insertions(+), 14 deletions(-) (limited to 'scripts/qapi.py') diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 2afab20f55..c4264a819b 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -106,7 +106,8 @@ Types, commands, and events share a common namespace. Therefore, generally speaking, type definitions should always use CamelCase for user-defined type names, while built-in types are lowercase. Type definitions should not end in 'Kind', as this namespace is used for -creating implicit C enums for visiting union types. Command names, +creating implicit C enums for visiting union types, or in 'List', as +this namespace is used for creating array types. Command names, and field names within a type, should be all lower case with words separated by a hyphen. However, some existing older commands and complex types use underscore; when extending such expressions, diff --git a/scripts/qapi.py b/scripts/qapi.py index 3af4c2c737..d53b5c4b45 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -390,10 +390,10 @@ def add_name(name, info, meta, implicit=False): raise QAPIExprError(info, "%s '%s' is already defined" % (all_names[name], name)) - if not implicit and name.endswith('Kind'): + if not implicit and (name.endswith('Kind') or name.endswith('List')): raise QAPIExprError(info, - "%s '%s' should not end in 'Kind'" - % (meta, name)) + "%s '%s' should not end in '%s'" + % (meta, name, name[-4:])) all_names[name] = meta @@ -1196,9 +1196,7 @@ class QAPISchema(object): return name def _make_array_type(self, element_type, info): - # TODO fooList namespace is not reserved; user can create collisions, - # or abuse our type system with ['fooList'] for 2D array - name = element_type + 'List' + name = element_type + 'List' # Use namespace reserved by add_name() if not self.lookup_type(name): self._def_entity(QAPISchemaArrayType(name, info, element_type)) return name diff --git a/tests/qapi-schema/reserved-type-list.err b/tests/qapi-schema/reserved-type-list.err index e69de29bb2..4510fa6d90 100644 --- a/tests/qapi-schema/reserved-type-list.err +++ b/tests/qapi-schema/reserved-type-list.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-type-list.json:5: struct 'FooList' should not end in 'List' diff --git a/tests/qapi-schema/reserved-type-list.exit b/tests/qapi-schema/reserved-type-list.exit index 573541ac97..d00491fd7e 100644 --- a/tests/qapi-schema/reserved-type-list.exit +++ b/tests/qapi-schema/reserved-type-list.exit @@ -1 +1 @@ -0 +1 diff --git a/tests/qapi-schema/reserved-type-list.json b/tests/qapi-schema/reserved-type-list.json index 5b7d0f995f..98d53bf808 100644 --- a/tests/qapi-schema/reserved-type-list.json +++ b/tests/qapi-schema/reserved-type-list.json @@ -1,5 +1,5 @@ # Potential C name collision -# FIXME - This parses and compiles on its own, but prevents the user from -# creating a type named 'Foo' and using ['Foo'] for an array. We should -# reject the use of any type names ending in 'List'. +# We reserve names ending in 'List' for use by array types. +# TODO - we could choose array names to avoid collision with user types, +# in order to let this compile { 'struct': 'FooList', 'data': { 's': 'str' } } diff --git a/tests/qapi-schema/reserved-type-list.out b/tests/qapi-schema/reserved-type-list.out index 0406bfe319..e69de29bb2 100644 --- a/tests/qapi-schema/reserved-type-list.out +++ b/tests/qapi-schema/reserved-type-list.out @@ -1,3 +0,0 @@ -object :empty -object FooList - member s: str optional=False -- cgit v1.2.3-55-g7522 From 9fb081e0b98409556d023c7193eeb68947cd1211 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 26 Oct 2015 16:34:44 -0600 Subject: qapi: Reserve 'q_*' and 'has_*' member names c_name() produces names starting with 'q_' when protecting a dictionary member name that would fail to directly compile, but in doing so can cause clashes with any member name already beginning with 'q-' or 'q_'. Likewise, we create a C name 'has_' for any optional member that can clash with any member name beginning with 'has-' or 'has_'. Technically, rather than blindly reserving the namespace, we could try to complain about user names only when an actual collision occurs, or even teach c_name() how to munge names to avoid collisions. But it is not trivial, especially when collisions can occur across multiple types (such as via inheritance or flat unions). Besides, no existing .json files are trying to use these names. So it's easier to just outright forbid the potential for collision. We can always relax things in the future if a real need arises for QMP to express member names that have been forbidden here. 'has_' only has to be reserved for struct/union member names, while 'q_' is reserved everywhere (matching the fact that only members can be optional, while we use c_name() for munging both members and entities). Note that we could relax 'q_' restrictions on entities independently from member names; for example, c_name('qmp_' + 'unix') would result in a different function name than our current 'qmp_' + c_name('unix'). Update and add tests to cover the new error messages. Signed-off-by: Eric Blake Message-Id: <1445898903-12082-6-git-send-email-eblake@redhat.com> [Consistently pass protect=False to c_name(); commit message tweaked slightly] Signed-off-by: Markus Armbruster --- docs/qapi-code-gen.txt | 11 +++++++---- scripts/qapi.py | 8 +++++++- tests/qapi-schema/reserved-command-q.err | 1 + tests/qapi-schema/reserved-command-q.exit | 2 +- tests/qapi-schema/reserved-command-q.json | 6 ++---- tests/qapi-schema/reserved-command-q.out | 5 ----- tests/qapi-schema/reserved-member-has.err | 1 + tests/qapi-schema/reserved-member-has.exit | 2 +- tests/qapi-schema/reserved-member-has.json | 7 +++---- tests/qapi-schema/reserved-member-has.out | 6 ------ tests/qapi-schema/reserved-member-q.err | 1 + tests/qapi-schema/reserved-member-q.exit | 2 +- tests/qapi-schema/reserved-member-q.json | 6 ++---- tests/qapi-schema/reserved-member-q.out | 4 ---- 14 files changed, 27 insertions(+), 35 deletions(-) (limited to 'scripts/qapi.py') diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index c4264a819b..4d8c2fcf02 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -112,7 +112,9 @@ and field names within a type, should be all lower case with words separated by a hyphen. However, some existing older commands and complex types use underscore; when extending such expressions, consistency is preferred over blindly avoiding underscore. Event -names should be ALL_CAPS with words separated by underscore. +names should be ALL_CAPS with words separated by underscore. Field +names cannot start with 'has-' or 'has_', as this is reserved for +tracking optional fields. Any name (command, event, type, field, or enum value) beginning with "x-" is marked experimental, and may be withdrawn or changed @@ -123,9 +125,10 @@ vendor), even if the rest of the name uses dash (example: __com.redhat_drive-mirror). Other than downstream extensions (with leading underscore and the use of dots), all names should begin with a letter, and contain only ASCII letters, digits, dash, and underscore. -It is okay to reuse names that match C keywords; the generator will -rename a field named "default" in the QAPI to "q_default" in the -generated C code. +Names beginning with 'q_' are reserved for the generator: QMP names +that resemble C keywords or other problematic strings will be munged +in C to use this prefix. For example, a field named "default" in +qapi becomes "q_default" in the generated C code. In the rest of this document, usage lines are given for each expression type, with literal strings written in lower case and diff --git a/scripts/qapi.py b/scripts/qapi.py index d53b5c4b45..3ff7b11e61 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -376,7 +376,9 @@ def check_name(expr_info, source, name, allow_optional=False, # code always prefixes it with the enum name if enum_member: membername = '_' + membername - if not valid_name.match(membername): + # Reserve the entire 'q_' namespace for c_name() + if not valid_name.match(membername) or \ + c_name(membername, False).startswith('q_'): raise QAPIExprError(expr_info, "%s uses invalid name '%s'" % (source, name)) @@ -488,6 +490,10 @@ def check_type(expr_info, source, value, allow_array=False, for (key, arg) in value.items(): check_name(expr_info, "Member of %s" % source, key, allow_optional=allow_optional) + if c_name(key, False).startswith('has_'): + raise QAPIExprError(expr_info, + "Member of %s uses reserved name '%s'" + % (source, key)) # Todo: allow dictionaries to represent default values of # an optional argument. check_type(expr_info, "Member '%s' of %s" % (key, source), arg, diff --git a/tests/qapi-schema/reserved-command-q.err b/tests/qapi-schema/reserved-command-q.err index e69de29bb2..f939e044eb 100644 --- a/tests/qapi-schema/reserved-command-q.err +++ b/tests/qapi-schema/reserved-command-q.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-command-q.json:5: 'command' uses invalid name 'q-unix' diff --git a/tests/qapi-schema/reserved-command-q.exit b/tests/qapi-schema/reserved-command-q.exit index 573541ac97..d00491fd7e 100644 --- a/tests/qapi-schema/reserved-command-q.exit +++ b/tests/qapi-schema/reserved-command-q.exit @@ -1 +1 @@ -0 +1 diff --git a/tests/qapi-schema/reserved-command-q.json b/tests/qapi-schema/reserved-command-q.json index be9944c68a..99f8aae314 100644 --- a/tests/qapi-schema/reserved-command-q.json +++ b/tests/qapi-schema/reserved-command-q.json @@ -1,7 +1,5 @@ # C entity name collision -# FIXME - This parses, but fails to compile, because it attempts to declare -# two 'qmp_q_unix' functions (one for 'q-unix', the other because c_name() -# munges 'unix' to 'q_unix' to avoid reserved word collisions). We should -# reject attempts to explicitly use 'q_' names, to reserve it for qapi. +# We reject names like 'q-unix', because they can collide with the mangled +# name for 'unix' in generated C. { 'command': 'unix' } { 'command': 'q-unix' } diff --git a/tests/qapi-schema/reserved-command-q.out b/tests/qapi-schema/reserved-command-q.out index b31b38ff0d..e69de29bb2 100644 --- a/tests/qapi-schema/reserved-command-q.out +++ b/tests/qapi-schema/reserved-command-q.out @@ -1,5 +0,0 @@ -object :empty -command q-unix None -> None - gen=True success_response=True -command unix None -> None - gen=True success_response=True diff --git a/tests/qapi-schema/reserved-member-has.err b/tests/qapi-schema/reserved-member-has.err index e69de29bb2..e755771446 100644 --- a/tests/qapi-schema/reserved-member-has.err +++ b/tests/qapi-schema/reserved-member-has.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-member-has.json:5: Member of 'data' for command 'oops' uses reserved name 'has-a' diff --git a/tests/qapi-schema/reserved-member-has.exit b/tests/qapi-schema/reserved-member-has.exit index 573541ac97..d00491fd7e 100644 --- a/tests/qapi-schema/reserved-member-has.exit +++ b/tests/qapi-schema/reserved-member-has.exit @@ -1 +1 @@ -0 +1 diff --git a/tests/qapi-schema/reserved-member-has.json b/tests/qapi-schema/reserved-member-has.json index a2197de6b5..45b9109bdc 100644 --- a/tests/qapi-schema/reserved-member-has.json +++ b/tests/qapi-schema/reserved-member-has.json @@ -1,6 +1,5 @@ # C member name collision -# FIXME - This parses, but fails to compile, because the C struct is given -# two 'has_a' members, one from the flag for optional 'a', and the other -# from member 'has-a'. Either reject this at parse time, or munge the C -# names to avoid the collision. +# We reject names like 'has-a', because they can collide with the flag +# for an optional 'a' in generated C. +# TODO we could munge the optional flag name to avoid the collision. { 'command': 'oops', 'data': { '*a': 'str', 'has-a': 'str' } } diff --git a/tests/qapi-schema/reserved-member-has.out b/tests/qapi-schema/reserved-member-has.out index 5a18b6be8c..e69de29bb2 100644 --- a/tests/qapi-schema/reserved-member-has.out +++ b/tests/qapi-schema/reserved-member-has.out @@ -1,6 +0,0 @@ -object :empty -object :obj-oops-arg - member a: str optional=True - member has-a: str optional=False -command oops :obj-oops-arg -> None - gen=True success_response=True diff --git a/tests/qapi-schema/reserved-member-q.err b/tests/qapi-schema/reserved-member-q.err index e69de29bb2..f3d5dd7818 100644 --- a/tests/qapi-schema/reserved-member-q.err +++ b/tests/qapi-schema/reserved-member-q.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-member-q.json:4: Member of 'data' for struct 'Foo' uses invalid name 'q-unix' diff --git a/tests/qapi-schema/reserved-member-q.exit b/tests/qapi-schema/reserved-member-q.exit index 573541ac97..d00491fd7e 100644 --- a/tests/qapi-schema/reserved-member-q.exit +++ b/tests/qapi-schema/reserved-member-q.exit @@ -1 +1 @@ -0 +1 diff --git a/tests/qapi-schema/reserved-member-q.json b/tests/qapi-schema/reserved-member-q.json index 1602ed3281..62fed8fddf 100644 --- a/tests/qapi-schema/reserved-member-q.json +++ b/tests/qapi-schema/reserved-member-q.json @@ -1,6 +1,4 @@ # C member name collision -# FIXME - This parses, but fails to compile, because it attempts to declare -# two 'q_unix' members (one for 'q-unix', the other because c_name() -# munges 'unix' to 'q_unix' to avoid reserved word collisions). We should -# reject attempts to explicitly use 'q_' names, to reserve it for qapi. +# We reject names like 'q-unix', because they can collide with the mangled +# name for 'unix' in generated C. { 'struct': 'Foo', 'data': { 'unix':'int', 'q-unix':'bool' } } diff --git a/tests/qapi-schema/reserved-member-q.out b/tests/qapi-schema/reserved-member-q.out index 0d8685aeb0..e69de29bb2 100644 --- a/tests/qapi-schema/reserved-member-q.out +++ b/tests/qapi-schema/reserved-member-q.out @@ -1,4 +0,0 @@ -object :empty -object Foo - member unix: int optional=False - member q-unix: bool optional=False -- cgit v1.2.3-55-g7522 From f51d8fab44b231aa299d8de24cfdf9ba41ef4a21 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 26 Oct 2015 16:34:51 -0600 Subject: qapi: Start converting to new qapi union layout We have two issues with our qapi union layout: 1) Even though the QMP wire format spells the tag 'type', the C code spells it 'kind', requiring some hacks in the generator. 2) The C struct uses an anonymous union, which places all tag values in the same namespace as all non-variant members. This leads to spurious collisions if a tag value matches a non-variant member's name. This patch is the front end for a series that converts to a saner qapi union layout. By the end of the series, we will no longer have the type/kind mismatch, and all tag values will be under a named union, which requires clients to access 'obj->u.value' instead of 'obj->value'. But since the conversion touches a number of files, it is easiest if we temporarily support BOTH layouts simultaneously. Given a simple union qapi type: { 'union':'Foo', 'data': { 'a':'int', 'b':'bool' } } make the following changes in generated qapi-types.h: | struct Foo { |- FooKind kind; |- union { /* union tag is @kind */ |+ union { |+ FooKind kind; |+ FooKind type; |+ }; |+ union { /* union tag is @type */ | void *data; | int64_t a; | bool b; |+ union { /* union tag is @type */ |+ void *data; |+ int64_t a; |+ bool b; |+ } u; | }; | }; Flat unions do not need the anonymous union for the tag member, as we already fixed that to use the member name instead of 'kind' back in commit 0f61af3e. One additional change is needed in qapi.py: check_union() now needs to check for collisions with 'type' in addition to those with 'kind'. Later, when the conversions are complete, we will remove the duplication hacks, and also drop the check_union() restrictions. Note, however, that we do not rename the generated enum, which is still 'FooKind'. A further patch could generate implicit enums as 'FooType', but while the generator already reserved the '*Kind' namespace (commit 4dc2e69), there are already QMP constructs with '*Type' naming, which means changing our reservation namespace would have lots of churn to C code to deal with a forced name change. Signed-off-by: Eric Blake Message-Id: <1445898903-12082-13-git-send-email-eblake@redhat.com> [Commit message tweaked slightly] Signed-off-by: Markus Armbruster --- scripts/qapi-types.py | 26 +++++++++++++++++++------- scripts/qapi.py | 3 ++- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'scripts/qapi.py') diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index faf7022e2c..1420e00ffb 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -149,11 +149,23 @@ struct %(c_name)s { if base: ret += gen_struct_fields([], base) else: + # TODO As a hack, we emit both 'kind' and 'type'. Ultimately, we + # want to use only 'type', but the conversion is large enough to + # require staging over several commits. ret += mcgen(''' - %(c_type)s kind; + union { + %(c_type)s kind; + %(c_type)s type; + }; ''', c_type=c_name(variants.tag_member.type.name)) + # TODO As a hack, we emit the union twice, once as an anonymous union + # and once as a named union. Ultimately, we want to use only the + # named union version (as it avoids conflicts between tag values as + # branch names competing with non-variant QMP names), but the conversion + # is large enough to require staging over several commits. + tmp = '' # FIXME: What purpose does data serve, besides preventing a union that # has a branch named 'data'? We use it in qapi-visit.py to decide # whether to bypass the switch statement if visiting the discriminator @@ -162,25 +174,25 @@ struct %(c_name)s { # should not be any data leaks even without a data pointer. Or, if # 'data' is merely added to guarantee we don't have an empty union, # shouldn't we enforce that at .json parse time? - ret += mcgen(''' + tmp += mcgen(''' union { /* union tag is @%(c_name)s */ void *data; ''', - # TODO ugly special case for simple union - # Use same tag name in C as on the wire to get rid of - # it, then: c_name=c_name(variants.tag_member.name) - c_name=c_name(variants.tag_name or 'kind')) + c_name=c_name(variants.tag_member.name)) for var in variants.variants: # Ugly special case for simple union TODO get rid of it typ = var.simple_union_type() or var.type - ret += mcgen(''' + tmp += mcgen(''' %(c_type)s %(c_name)s; ''', c_type=typ.c_type(), c_name=c_name(var.name)) + ret += tmp + ret += ' ' + '\n '.join(tmp.split('\n')) ret += mcgen(''' + } u; }; }; ''') diff --git a/scripts/qapi.py b/scripts/qapi.py index 3ff7b11e61..00a16203df 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -548,7 +548,8 @@ def check_union(expr, expr_info): base = expr.get('base') discriminator = expr.get('discriminator') members = expr['data'] - values = {'MAX': '(automatic)', 'KIND': '(automatic)'} + values = {'MAX': '(automatic)', 'KIND': '(automatic)', + 'TYPE': '(automatic)'} # Two types of unions, determined by discriminator. -- cgit v1.2.3-55-g7522 From 5e59baf90a72cd25d38a3134edc029f4f022da74 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 26 Oct 2015 16:35:02 -0600 Subject: qapi: Reserve 'u' member name Now that we have separated union tag values from colliding with non-variant C names, by naming the union 'u', we should reserve this name for our use. Note that we want to forbid 'u' even in a struct with no variants, because it is possible for a future qemu release to extend QMP in a backwards-compatible manner while converting from a struct to a flat union. Fortunately, no existing clients were using this member name. If we ever find the need for QMP to have a member 'u', we could at that time relax things, perhaps by having c_name() munge the QMP member to 'q_u'. Note that we cannot forbid 'u' everywhere (by adding the rejection code to check_name()), because the existing QKeyCode enum already uses it; therefore we only reserve it as a struct type member name. Signed-off-by: Eric Blake Message-Id: <1445898903-12082-24-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster --- scripts/qapi.py | 2 +- tests/Makefile | 1 + tests/qapi-schema/reserved-member-u.err | 1 + tests/qapi-schema/reserved-member-u.exit | 1 + tests/qapi-schema/reserved-member-u.json | 7 +++++++ tests/qapi-schema/reserved-member-u.out | 0 6 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/qapi-schema/reserved-member-u.err create mode 100644 tests/qapi-schema/reserved-member-u.exit create mode 100644 tests/qapi-schema/reserved-member-u.json create mode 100644 tests/qapi-schema/reserved-member-u.out (limited to 'scripts/qapi.py') diff --git a/scripts/qapi.py b/scripts/qapi.py index 00a16203df..7c50cc4c87 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -490,7 +490,7 @@ def check_type(expr_info, source, value, allow_array=False, for (key, arg) in value.items(): check_name(expr_info, "Member of %s" % source, key, allow_optional=allow_optional) - if c_name(key, False).startswith('has_'): + if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'): raise QAPIExprError(expr_info, "Member of %s uses reserved name '%s'" % (source, key)) diff --git a/tests/Makefile b/tests/Makefile index fd4ec03e09..92969e8288 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -318,6 +318,7 @@ qapi-schema += redefined-type.json qapi-schema += reserved-command-q.json qapi-schema += reserved-member-has.json qapi-schema += reserved-member-q.json +qapi-schema += reserved-member-u.json qapi-schema += reserved-type-kind.json qapi-schema += reserved-type-list.json qapi-schema += returns-alternate.json diff --git a/tests/qapi-schema/reserved-member-u.err b/tests/qapi-schema/reserved-member-u.err new file mode 100644 index 0000000000..87d42296cc --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-member-u.json:7: Member of 'data' for struct 'Oops' uses reserved name 'u' diff --git a/tests/qapi-schema/reserved-member-u.exit b/tests/qapi-schema/reserved-member-u.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/reserved-member-u.json b/tests/qapi-schema/reserved-member-u.json new file mode 100644 index 0000000000..1eaf0f301c --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.json @@ -0,0 +1,7 @@ +# Potential C member name collision +# We reject use of 'u' as a member name, to allow it for internal use in +# putting union branch members in a separate namespace from QMP members. +# This is true even for non-unions, because it is possible to convert a +# struct to flat union while remaining backwards compatible in QMP. +# TODO - we could munge the member name to 'q_u' to avoid the collision +{ 'struct': 'Oops', 'data': { 'u': 'str' } } diff --git a/tests/qapi-schema/reserved-member-u.out b/tests/qapi-schema/reserved-member-u.out new file mode 100644 index 0000000000..e69de29bb2 -- cgit v1.2.3-55-g7522