mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
assert: add STATIC_ASSERT macro
Can be quite handy, attempt to provide fallbacks for compilers that don't support _Static_assert (which is technically a C11 feature). Suppress warnings as best we can (Clang and GCC warn that we're using a C11 feature while in C99 mode). Needs to be tested for MSVC still.
This commit is contained in:
parent
25f3cedfe6
commit
095b4479c0
78
src/nvim/assert.h
Normal file
78
src/nvim/assert.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef NVIM_ASSERT_H
|
||||
#define NVIM_ASSERT_H
|
||||
|
||||
// support static asserts (aka compile-time asserts)
|
||||
|
||||
// some compilers don't properly support short-circuiting apparently, giving
|
||||
// ugly syntax errors when using things like defined(__clang__) &&
|
||||
// defined(__has_feature) && __has_feature(...). Therefore we define Clang's
|
||||
// __has_feature and __has_extension macro's before referring to them.
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_extension
|
||||
#define __has_extension __has_feature
|
||||
#endif
|
||||
|
||||
/// STATIC_ASSERT(condition, message) - assert at compile time if !cond
|
||||
///
|
||||
/// example:
|
||||
/// STATIC_ASSERT(sizeof(void *) == 8, "need 64-bits mode");
|
||||
|
||||
// define STATIC_ASSERT as C11's _Static_assert whenever either C11 mode is
|
||||
// detected or the compiler is known to support it. Note that Clang in C99
|
||||
// mode defines __has_feature(c_static_assert) as false and
|
||||
// __has_extension(c_static_assert) as true. Meaning it does support it, but
|
||||
// warns. A similar thing goes for gcc, which warns when it's not compiling
|
||||
// as C11 but does support _Static_assert since 4.6. Since we prefer the
|
||||
// clearer messages we get from _Static_assert, we suppress the warnings
|
||||
// temporarily.
|
||||
|
||||
// the easiest case, when the mode is C11 (generic compiler) or Clang
|
||||
// advertises explicit support for c_static_assert, meaning it won't warn.
|
||||
#if __STDC_VERSION__ >= 201112L || __has_feature(c_static_assert)
|
||||
#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
|
||||
// if we're dealing with gcc >= 4.6 in C99 mode, we can still use
|
||||
// _Static_assert but we need to suppress warnings, this is pretty ugly.
|
||||
#elif (!defined(__clang__) && !defined(__INTEL_COMPILER)) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
#define STATIC_ASSERT(cond, msg) \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-pedantic\"") \
|
||||
_Static_assert(cond, msg); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
|
||||
// the same goes for clang in C99 mode, but we suppress a different warning
|
||||
#elif defined(__clang__) && __has_extension(c_static_assert)
|
||||
#define STATIC_ASSERT(cond, msg) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wc11-extensions\"") \
|
||||
_Static_assert(cond, msg); \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
|
||||
// TODO(aktau): verify that this works, don't have MSVC on hand.
|
||||
#elif _MSC_VER >= 1600
|
||||
#define STATIC_ASSERT(cond, msg) static_assert(cond, msg)
|
||||
|
||||
// fallback for compilers that don't support _Static_assert or static_assert
|
||||
// not as pretty but gets the job done. Credit goes to Pádraig Brady and
|
||||
// contributors.
|
||||
#else
|
||||
#define ASSERT_CONCAT_(a, b) a##b
|
||||
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
|
||||
// These can't be used after statements in c89.
|
||||
#ifdef __COUNTER__
|
||||
#define STATIC_ASSERT(e,m) \
|
||||
{ enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }; }
|
||||
#else
|
||||
// This can't be used twice on the same line so ensure if using in headers
|
||||
// that the headers are not included twice (by wrapping in #ifndef...#endif)
|
||||
// Note it doesn't cause an issue when used on same line of separate modules
|
||||
// compiled with gcc -combine -fwhole-program.
|
||||
#define STATIC_ASSERT(e,m) \
|
||||
{ enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // NVIM_ASSERT_H
|
Loading…
Reference in New Issue
Block a user