qemu/include/qapi
Markus Armbruster bb71846325 qobject atomics osdep: Make a few macros more hygienic
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>
Message-ID: <20230921121312.1301864-8-armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2023-09-29 08:13:57 +02:00
..
qmp qobject atomics osdep: Make a few macros more hygienic 2023-09-29 08:13:57 +02:00
clone-visitor.h qapi: Make visitor functions taking Error ** return bool, not void 2020-07-10 15:18:08 +02:00
compat-policy.h qapi: Factor out compat_policy_input_ok() 2021-10-29 21:27:20 +02:00
dealloc-visitor.h
error.h error: add global &error_warn destination 2023-03-13 15:23:37 +04:00
forward-visitor.h qapi: introduce forwarding visitor 2021-07-23 18:17:17 +02:00
opts-visitor.h Move include qemu/option.h from qemu-common.h to actual users 2018-02-09 13:52:16 +01:00
qmp-event.h qapi: Eliminate indirection through qmp_event_get_func_emit() 2019-01-24 10:01:05 +01:00
qobject-input-visitor.h qapi: Move compat policy from QObject to generic visitor 2021-10-27 17:19:15 +02:00
qobject-output-visitor.h qapi: Move compat policy from QObject to generic visitor 2021-10-27 17:19:15 +02:00
string-input-visitor.h qapi: Rewrite string-input-visitor's integer and list parsing 2018-12-13 19:10:06 +01:00
string-output-visitor.h
type-helpers.h monitor: introduce HumanReadableText and HMP support 2021-11-02 15:55:13 +00:00
util.h qapi: Extend -compat to set policy for unstable interfaces 2021-10-29 21:28:01 +02:00
visitor-impl.h qapi: Generalize struct member policy checking 2021-10-29 18:23:09 +02:00
visitor.h qapi: Generalize struct member policy checking 2021-10-29 18:23:09 +02:00