use _Static_assert in QEMU_BUILD_BUG_ON

QEMU_BUILD_BUG_ON should use C11's _Static_assert, if the compiler supports it,
to provide more readable messages on failure.

We check for _Static_assert in configure, and set CONFIG_STATIC_ASSERT
accordingly. QEMU_BUILD_BUG_ON invokes _Static_assert if CONFIG_STATIC_ASSERT
is defined, and reverts to the old way otherwise.

That way, systems without C11 conforming compiler will still have the old
messages, as verified by intentionally breaking the configure check.

the following example output was generated by inverting the condition in
QEMU_BUILD_BUG_ON:

without _Static_assert:

> In file included from /qemu/include/qemu/osdep.h:36:0,
>                  from /qemu/qga/commands.c:13:
> /qemu/qga/commands.c: In function ‘qmp_guest_exec_status’:
> /qemu/include/qemu/compiler.h:89:12: error: negative width in bit-field ‘<anonymous>’
>      struct { \
>             ^
> /qemu/include/qemu/compiler.h:96:38: note: in expansion of macro  QEMU_BUILD_BUG_ON_STRUCT’
>  #define QEMU_BUILD_BUG_ON(x) typedef QEMU_BUILD_BUG_ON_STRUCT(x) \
>                                       ^~~~~~~~~~~~~~~~~~~~~~~~
> /qemu/include/qemu/atomic.h:146:5: note: in expansion of macro ‘QEMU_BUILD_BUG_ON’
>      QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
>      ^~~~~~~~~~~~~~~~~
> /qemu/include/qemu/atomic.h:417:5: note: in expansion of macro ‘atomic_load_acquire’
>      atomic_load_acquire(ptr)
>      ^~~~~~~~~~~~~~~~~~~
> /qemu/qga/commands.c:160:21: note: in expansion of macro ‘atomic_mb_read’
>      bool finished = atomic_mb_read(&gei->finished);
>                      ^~~~~~~~~~~~~~

with _Static_assert:

> In file included from /qemu/include/qemu/osdep.h:36:0,
>                  from /qemu/qga/commands.c:13:
> /qemu/qga/commands.c: In function ‘qmp_guest_exec_status’:
> /qemu/include/qemu/compiler.h:94:30: error: static assertion failed: "not expecting: sizeof(*&gei->finished) > sizeof(void *)"
>  #define QEMU_BUILD_BUG_ON(x) _Static_assert((x), #x)
>                               ^
> /qemu/include/qemu/atomic.h:146:5: note: in expansion of macro ‘QEMU_BUILD_BUG_ON’
>      QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
>      ^~~~~~~~~~~~~~~~~
> /qemu/include/qemu/atomic.h:417:5: note: in expansion of macro ‘atomic_load_acquire’
>      atomic_load_acquire(ptr)
>      ^~~~~~~~~~~~~~~~~~~
> /qemu/qga/commands.c:160:21: note: in expansion of macro ‘atomic_mb_read’
>      bool finished = atomic_mb_read(&gei->finished);
>                      ^~~~~~~~~~~~~~

Signed-off-by: Andreas Grapentin <andreas@grapentin.org>
Message-Id: <20170314165953.18506-1-andreas@grapentin.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Andreas Grapentin 2017-03-14 17:59:53 +01:00 committed by Paolo Bonzini
parent 00fcd100c3
commit 49e00a1870
2 changed files with 21 additions and 1 deletions

18
configure vendored
View File

@ -4852,6 +4852,20 @@ EOF
fi fi
fi fi
##########################################
# check for _Static_assert()
have_static_assert=no
cat > $TMPC << EOF
_Static_assert(1, "success");
int main(void) {
return 0;
}
EOF
if compile_prog "" "" ; then
have_static_assert=yes
fi
########################################## ##########################################
# End of CC checks # End of CC checks
# After here, no more $cc or $ld runs # After here, no more $cc or $ld runs
@ -5848,6 +5862,10 @@ if test "$have_sysmacros" = "yes" ; then
echo "CONFIG_SYSMACROS=y" >> $config_host_mak echo "CONFIG_SYSMACROS=y" >> $config_host_mak
fi fi
if test "$have_static_assert" = "yes" ; then
echo "CONFIG_STATIC_ASSERT=y" >> $config_host_mak
fi
# Hold two types of flag: # Hold two types of flag:
# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on # CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on
# a thread we have a handle to # a thread we have a handle to

View File

@ -82,7 +82,9 @@
int:(x) ? -1 : 1; \ int:(x) ? -1 : 1; \
} }
#ifdef __COUNTER__ #if defined(CONFIG_STATIC_ASSERT)
#define QEMU_BUILD_BUG_ON(x) _Static_assert(!(x), "not expecting: " #x)
#elif defined(__COUNTER__)
#define QEMU_BUILD_BUG_ON(x) typedef QEMU_BUILD_BUG_ON_STRUCT(x) \ #define QEMU_BUILD_BUG_ON(x) typedef QEMU_BUILD_BUG_ON_STRUCT(x) \
glue(qemu_build_bug_on__, __COUNTER__) __attribute__((unused)) glue(qemu_build_bug_on__, __COUNTER__) __attribute__((unused))
#else #else