From: Kevin Wolf <kwolf@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, hreitz@redhat.com, eblake@redhat.com,
vsementsov@yandex-team.ru, jsnow@redhat.com, idryomov@gmail.com,
pl@kamp.de, sw@weilnetz.de, sstabellini@kernel.org,
anthony.perard@citrix.com, paul@xen.org, pbonzini@redhat.com,
marcandre.lureau@redhat.com, berrange@redhat.com,
thuth@redhat.com, philmd@linaro.org, stefanha@redhat.com,
fam@euphon.net, quintela@redhat.com, peterx@redhat.com,
leobras@redhat.com, kraxel@redhat.com, qemu-block@nongnu.org,
xen-devel@lists.xenproject.org, alex.bennee@linaro.org,
peter.maydell@linaro.org
Subject: Re: [PATCH v2 7/7] qobject atomics osdep: Make a few macros more hygienic
Date: Thu, 21 Sep 2023 10:42:57 +0200 [thread overview]
Message-ID: <ZQwCEW4SBpI9f1Yx@redhat.com> (raw)
In-Reply-To: <20230920183149.1105333-8-armbru@redhat.com>
Am 20.09.2023 um 20:31 hat Markus Armbruster geschrieben:
> Variables declared in macros can shadow other variables. Much of the
> time, this is harmless, e.g.:
>
> #define _FDT(exp) \
> do { \
> int ret = (exp); \
> if (ret < 0) { \
> error_report("error creating device tree: %s: %s", \
> #exp, fdt_strerror(ret)); \
> exit(1); \
> } \
> } while (0)
>
> Harmless shadowing in h_client_architecture_support():
>
> target_ulong ret;
>
> [...]
>
> ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize);
> if (ret == H_SUCCESS) {
> _FDT((fdt_pack(spapr->fdt_blob)));
> [...]
> }
>
> return ret;
>
> However, we can get in trouble when the shadowed variable is used in a
> macro argument:
>
> #define QOBJECT(obj) ({ \
> typeof(obj) o = (obj); \
> o ? container_of(&(o)->base, QObject, base) : NULL; \
> })
>
> QOBJECT(o) expands into
>
> ({
> ---> typeof(o) o = (o);
> o ? container_of(&(o)->base, QObject, base) : NULL;
> })
>
> Unintended variable name capture at --->. We'd be saved by
> -Winit-self. But I could certainly construct more elaborate death
> traps that don't trigger it.
>
> To reduce the risk of trapping ourselves, we use variable names in
> macros that no sane person would use elsewhere. Here's our actual
> definition of QOBJECT():
>
> #define QOBJECT(obj) ({ \
> typeof(obj) _obj = (obj); \
> _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \
> })
>
> Works well enough until we nest macro calls. For instance, with
>
> #define qobject_ref(obj) ({ \
> typeof(obj) _obj = (obj); \
> qobject_ref_impl(QOBJECT(_obj)); \
> _obj; \
> })
>
> the expression qobject_ref(obj) expands into
>
> ({
> typeof(obj) _obj = (obj);
> qobject_ref_impl(
> ({
> ---> typeof(_obj) _obj = (_obj);
> _obj ? container_of(&(_obj)->base, QObject, base) : NULL;
> }));
> _obj;
> })
>
> Unintended variable name capture at --->.
>
> The only reliable way to prevent unintended variable name capture is
> -Wshadow.
>
> One blocker for enabling it is shadowing hiding in function-like
> macros like
>
> qdict_put(dict, "name", qobject_ref(...))
>
> qdict_put() wraps its last argument in QOBJECT(), and the last
> argument here contains another QOBJECT().
>
> Use dark preprocessor sorcery to make the macros that give us this
> problem use different variable names on every call.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
> include/qapi/qmp/qobject.h | 11 +++++++++--
> include/qemu/atomic.h | 17 ++++++++++++-----
> include/qemu/compiler.h | 3 +++
> include/qemu/osdep.h | 31 +++++++++++++++++++++++--------
> 4 files changed, 47 insertions(+), 15 deletions(-)
>
> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
> index 9003b71fd3..d36cc97805 100644
> --- a/include/qapi/qmp/qobject.h
> +++ b/include/qapi/qmp/qobject.h
> @@ -45,10 +45,17 @@ struct QObject {
> struct QObjectBase_ base;
> };
>
> -#define QOBJECT(obj) ({ \
> +/*
> + * Preprocessory sorcery ahead: use a different identifier for the
> + * local variable in each expansion, so we can nest macro calls
> + * without shadowing variables.
> + */
> +#define QOBJECT_INTERNAL(obj, _obj) ({ \
> typeof(obj) _obj = (obj); \
> - _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \
> + _obj \
> + ? container_of(&(_obj)->base, QObject, base) : NULL; \
What happened here? The code in this line (or now two lines) seems to be
unchanged apart from a strange looking newline.
> })
> +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), MAKE_IDENTFIER(_obj))
Kevin
next prev parent reply other threads:[~2023-09-21 8:43 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-20 18:31 [PATCH v2 0/7] Steps towards enabling -Wshadow=local Markus Armbruster
2023-09-20 18:31 ` [PATCH v2 1/7] migration/rdma: Fix save_page method to fail on polling error Markus Armbruster
2023-09-20 18:31 ` [PATCH v2 2/7] migration: Clean up local variable shadowing Markus Armbruster
2023-09-21 6:06 ` Zhijian Li (Fujitsu)
2023-09-20 18:31 ` [PATCH v2 3/7] ui: " Markus Armbruster
2023-09-20 18:31 ` [PATCH v2 4/7] block/dirty-bitmap: " Markus Armbruster
2023-09-21 8:37 ` Kevin Wolf
2023-09-20 18:31 ` [PATCH v2 5/7] block/vdi: " Markus Armbruster
2023-09-21 8:29 ` Kevin Wolf
2023-09-20 18:31 ` [PATCH v2 6/7] block: " Markus Armbruster
2023-09-21 8:33 ` Kevin Wolf
2023-09-20 18:31 ` [PATCH v2 7/7] qobject atomics osdep: Make a few macros more hygienic Markus Armbruster
2023-09-20 20:10 ` Eric Blake
2023-09-21 5:14 ` Markus Armbruster
2023-09-21 8:42 ` Kevin Wolf [this message]
2023-09-21 11:23 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZQwCEW4SBpI9f1Yx@redhat.com \
--to=kwolf@redhat.com \
--cc=alex.bennee@linaro.org \
--cc=anthony.perard@citrix.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=eblake@redhat.com \
--cc=fam@euphon.net \
--cc=hreitz@redhat.com \
--cc=idryomov@gmail.com \
--cc=jsnow@redhat.com \
--cc=kraxel@redhat.com \
--cc=leobras@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=paul@xen.org \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=peterx@redhat.com \
--cc=philmd@linaro.org \
--cc=pl@kamp.de \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
--cc=sstabellini@kernel.org \
--cc=stefanha@redhat.com \
--cc=sw@weilnetz.de \
--cc=thuth@redhat.com \
--cc=vsementsov@yandex-team.ru \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.