diff options
-rw-r--r-- | git-compat-util.h | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/git-compat-util.h b/git-compat-util.h index 400e921086..7fad5aad9f 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -3,6 +3,23 @@ #define _FILE_OFFSET_BITS 64 + +/* Derived from Linux "Features Test Macro" header + * Convenience macros to test the versions of gcc (or + * a compatible compiler). + * Use them like this: + * #if GIT_GNUC_PREREQ (2,8) + * ... code requiring gcc 2.8 or later ... + * #endif +*/ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define GIT_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else + #define GIT_GNUC_PREREQ(maj, min) 0 +#endif + + #ifndef FLEX_ARRAY /* * See if our compiler is known to support flexible array members. @@ -25,7 +42,42 @@ #endif #endif -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +/* + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#if defined(__GNUC__) && (__GNUC__ >= 3) +# if GIT_GNUC_PREREQ(3, 1) + /* &arr[0] degrades to a pointer: a different type from an array */ +# define BARF_UNLESS_AN_ARRAY(arr) \ + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(__typeof__(arr), \ + __typeof__(&(arr)[0]))) +# else +# define BARF_UNLESS_AN_ARRAY(arr) 0 +# endif +#endif +/* + * ARRAY_SIZE - get the number of elements in a visible array + * <at> x: the array whose size you want. + * + * This does not work on pointers, or arrays declared as [], or + * function parameters. With correct compiler support, such usage + * will cause a build error (see the build_assert_or_zero macro). + */ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]) + BARF_UNLESS_AN_ARRAY(x)) + #define bitsizeof(x) (CHAR_BIT * sizeof(x)) #define maximum_signed_value_of_type(a) \ |