diff --git a/git-compat-util.h b/git-compat-util.h index 685a0a4063edd2a6700533df7faa2a910df60bb3..b7a97fbe8300532505b9d63dace2a3f76d8e04e2 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 + * 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) \