From 9ac2545d66e630cce6a718a7c6f374fbecb00e96 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 1 Nov 2016 19:36:15 +0100 Subject: Add support for static assertions (on compilers that support them) This introduces the macro `STATIC_ASSERT(ex, msg)`, that works like its C11 counterpart `_Static_assert(ex, msg)`, on compilers that support it. Support is provided, depending on the compiler: - When in C11 mode, use the native `_Static_assert` - If the compiler advertises having the `c_static_assert` feature, use `_Static_assert` (according to the clang documentation). - If the compiler is GCC >= 4.7 (tested to be compatible), use `_Static_assert` (nonstandard extension, C11 feature available in C99). - If the compiler is MSVC (all the currently supported versions have been tested to be compatible), then use `static_assert` (nonstandard extension, C++ feature) - Otherwise, define it as a no-op macro. Signed-off-by: Haru --- src/common/cbasetypes.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index 8c3b5ad04..2c36c23bc 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -109,6 +109,14 @@ # define __attribute__(x) #endif +/// Feature/extension checking macros +#ifndef __has_extension /* Available in clang and gcc >= 3 */ +#define __has_extension(x) 0 +#endif +#ifndef __has_feature /* Available in clang and gcc >= 5 */ +#define __has_feature(x) __has_extension(x) +#endif + ////////////////////////////////////////////////////////////////////////// // portable printf/scanf format macros and integer definitions // NOTE: Visual C++ uses and provided in /3rdparty @@ -441,4 +449,23 @@ typedef char bool; /** Support macros for marking structs as unavailable */ #define UNAVAILABLE_STRUCT int8 HERC__unavailable_struct +/** Static assertion (only on compilers that support it) */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +// C11 version +#define STATIC_ASSERT(ex, msg) _Static_assert(ex, msg) +#elif __has_feature(c_static_assert) +// Clang support (as per http://clang.llvm.org/docs/LanguageExtensions.html) +#define STATIC_ASSERT(ex, msg) _Static_assert(ex, msg) +#elif defined(__GNUC__) && GCC_VERSION >= 40700 +// GCC >= 4.7 is known to support it +#define STATIC_ASSERT(ex, msg) _Static_assert(ex, msg) +#elif defined(_MSC_VER) +// MSVC doesn't support it, but it accepts the C++ style version +#define STATIC_ASSERT(ex, msg) static_assert(ex, msg) +#else +// Otherise just ignore it until it's supported +#define STATIC_ASSERT(ex, msg) +#endif + + #endif /* COMMON_CBASETYPES_H */ -- cgit v1.2.3-70-g09d2