summaryrefslogtreecommitdiff
path: root/scripts/qapi.py
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2015-10-26 16:34:44 -0600
committerMarkus Armbruster <armbru@redhat.com>2015-11-02 08:30:26 +0100
commit9fb081e0b98409556d023c7193eeb68947cd1211 (patch)
treec19eeaa3eed47ee66a97a4c14a421c61e2055ff6 /scripts/qapi.py
parent255960dd374d4497d6ea537305f1b0d8a3433789 (diff)
downloadqemu-9fb081e0b98409556d023c7193eeb68947cd1211.tar.gz
qemu-9fb081e0b98409556d023c7193eeb68947cd1211.tar.bz2
qemu-9fb081e0b98409556d023c7193eeb68947cd1211.zip
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 <eblake@redhat.com> 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 <armbru@redhat.com>
Diffstat (limited to 'scripts/qapi.py')
-rw-r--r--scripts/qapi.py8
1 files changed, 7 insertions, 1 deletions
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,