X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fmacro.h;h=179b24c9838971d1609d1ce74d027f497ea55801;hb=7242d7420b04132f93f1426ec713f9b09bdeba54;hp=4198095011c0750437c44041de5cc8d92ac314be;hpb=059d9fbb5a691ced7428cff5ff1da5681cacf6da;p=elogind.git diff --git a/src/shared/macro.h b/src/shared/macro.h index 419809501..179b24c98 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -30,7 +30,6 @@ #define _printf_(a,b) __attribute__ ((format (printf, a, b))) #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) #define _sentinel_ __attribute__ ((sentinel)) -#define _noreturn_ __attribute__((noreturn)) #define _unused_ __attribute__ ((unused)) #define _destructor_ __attribute__ ((destructor)) #define _pure_ __attribute__ ((pure)) @@ -47,6 +46,30 @@ #define _alignas_(x) __attribute__((aligned(__alignof(x)))) #define _cleanup_(x) __attribute__((cleanup(x))) +/* Temporarily disable some warnings */ +#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") + +#define DISABLE_WARNING_FORMAT_NONLITERAL \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") + +#define DISABLE_WARNING_MISSING_PROTOTYPES \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"") + +#define DISABLE_WARNING_NONNULL \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wnonnull\"") + +#define DISABLE_WARNING_SHADOW \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wshadow\"") + +#define REENABLE_WARNING \ + _Pragma("GCC diagnostic pop") + /* automake test harness */ #define EXIT_TEST_SKIP 77 @@ -79,7 +102,20 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) { return ((l + ali - 1) & ~(ali - 1)); } -#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p)) +#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p, ali)) + +/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */ +static inline unsigned long ALIGN_POWER2(unsigned long u) { + /* clz(0) is undefined */ + if (u == 1) + return 1; + + /* left-shift overflow is undefined */ + if (__builtin_clzl(u - 1UL) < 1) + return 0; + + return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL)); +} #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) @@ -97,33 +133,55 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) { }) #undef MAX -#define MAX(a,b) \ - __extension__ ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - _a > _b ? _a : _b; \ +#define MAX(a,b) \ + __extension__ ({ \ + const typeof(a) _a = (a); \ + const typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ }) -#define MAX3(x,y,z) \ - __extension__ ({ \ - typeof(x) _c = MAX(x,y); \ - MAX(_c, z); \ +/* evaluates to (void) if _A or _B are not constant or of different types */ +#define CONST_MAX(_A, _B) \ + __extension__ (__builtin_choose_expr( \ + __builtin_constant_p(_A) && \ + __builtin_constant_p(_B) && \ + __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ + ((_A) > (_B)) ? (_A) : (_B), \ + (void)0)) + +#define MAX3(x,y,z) \ + __extension__ ({ \ + const typeof(x) _c = MAX(x,y); \ + MAX(_c, z); \ }) #undef MIN -#define MIN(a,b) \ - __extension__ ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - _a < _b ? _a : _b; \ +#define MIN(a,b) \ + __extension__ ({ \ + const typeof(a) _a = (a); \ + const typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + +#define MIN3(x,y,z) \ + __extension__ ({ \ + const typeof(x) _c = MIN(x,y); \ + MIN(_c, z); \ + }) + +#define LESS_BY(A,B) \ + __extension__ ({ \ + const typeof(A) _A = (A); \ + const typeof(B) _B = (B); \ + _A > _B ? _A - _B : 0; \ }) #ifndef CLAMP #define CLAMP(x, low, high) \ __extension__ ({ \ - typeof(x) _x = (x); \ - typeof(low) _low = (low); \ - typeof(high) _high = (high); \ + const typeof(x) _x = (x); \ + const typeof(low) _low = (low); \ + const typeof(high) _high = (high); \ ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \ }) #endif @@ -148,15 +206,28 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) { } while (false) #if defined(static_assert) -#define assert_cc(expr) static_assert(expr, #expr) +/* static_assert() is sometimes defined in a way that trips up + * -Wdeclaration-after-statement, hence let's temporarily turn off + * this warning around it. */ +#define assert_cc(expr) \ + DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \ + static_assert(expr, #expr); \ + REENABLE_WARNING #else -#define assert_cc(expr) struct UNIQUE(_assert_struct_) { char x[(expr) ? 0 : -1]; }; +#define assert_cc(expr) \ + DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \ + struct UNIQUE(_assert_struct_) { \ + char x[(expr) ? 0 : -1]; \ + }; \ + REENABLE_WARNING #endif -#define assert_return(expr, r) \ - do { \ - if (_unlikely_(!(expr))) \ - return (r); \ +#define assert_return(expr, r) \ + do { \ + if (_unlikely_(!(expr))) { \ + log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + return (r); \ + } \ } while (false) #define PTR_TO_INT(p) ((int) ((intptr_t) (p))) @@ -179,6 +250,9 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) { #define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p))) #define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u))) +#define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p))) +#define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u))) + #define memzero(x,l) (memset((x), 0, (l))) #define zero(x) (memzero(&(x), sizeof(x))) @@ -285,18 +359,42 @@ do { \ #define SET_FLAG(v, flag, b) \ (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) -#define IN_SET(x, ...) \ +#define IN_SET(x, y, ...) \ ({ \ - const typeof(x) _x = (x); \ + const typeof(y) _y = (y); \ + const typeof(_y) _x = (x); \ unsigned _i; \ bool _found = false; \ - for (_i = 0; _i < sizeof((const typeof(_x)[]) { __VA_ARGS__ })/sizeof(const typeof(_x)); _i++) \ - if (((const typeof(_x)[]) { __VA_ARGS__ })[_i] == _x) { \ + for (_i = 0; _i < 1 + sizeof((const typeof(_x)[]) { __VA_ARGS__ })/sizeof(const typeof(_x)); _i++) \ + if (((const typeof(_x)[]) { _y, __VA_ARGS__ })[_i] == _x) { \ _found = true; \ break; \ } \ _found; \ }) +/* Define C11 thread_local attribute even on older gcc compiler + * version */ +#ifndef thread_local +/* + * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ + * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 + */ +#if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) +#define thread_local _Thread_local +#else +#define thread_local __thread +#endif +#endif + +/* Define C11 noreturn without and even on older gcc + * compiler versions */ +#ifndef noreturn +#if __STDC_VERSION__ >= 201112L +#define noreturn _Noreturn +#else +#define noreturn __attribute__((noreturn)) +#endif +#endif #include "log.h"