1 /* 2 * Copyright (c) 2015-2017 David Lamparter, for NetDEF, Inc. 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #ifndef _FRR_COMPILER_H 18 #define _FRR_COMPILER_H 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /* function attributes, use like 25 * void prototype(void) __attribute__((_CONSTRUCTOR(100))); 26 */ 27 #if defined(__clang__) 28 #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) 29 # define _RET_NONNULL , returns_nonnull 30 #endif 31 #if __has_attribute(fallthrough) 32 # define _FALLTHROUGH __attribute__((fallthrough)); 33 #endif 34 # define _CONSTRUCTOR(x) constructor(x) 35 # define _DEPRECATED(x) deprecated(x) 36 # if __has_builtin(assume) 37 # define assume(x) __builtin_assume(x) 38 # endif 39 #elif defined(__GNUC__) 40 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) 41 # define _RET_NONNULL , returns_nonnull 42 #endif 43 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) 44 # define _CONSTRUCTOR(x) constructor(x) 45 # define _DESTRUCTOR(x) destructor(x) 46 # define _ALLOC_SIZE(x) alloc_size(x) 47 #endif 48 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 49 # define _DEPRECATED(x) deprecated(x) 50 # define assume(x) do { if (!(x)) __builtin_unreachable(); } while (0) 51 #endif 52 #if __GNUC__ < 5 53 # define __has_attribute(x) 0 54 #endif 55 #if __GNUC__ >= 7 56 # define _FALLTHROUGH __attribute__((fallthrough)); 57 #endif 58 #endif 59 60 #if __has_attribute(hot) 61 # define _OPTIMIZE_HOT __attribute__((hot)) 62 #else 63 # define _OPTIMIZE_HOT 64 #endif 65 #if __has_attribute(optimize) 66 # define _OPTIMIZE_O3 __attribute__((optimize("3"))) 67 #else 68 # define _OPTIMIZE_O3 69 #endif 70 #define OPTIMIZE _OPTIMIZE_O3 _OPTIMIZE_HOT 71 72 #if !defined(__GNUC__) 73 #error module code needs GCC visibility extensions 74 #elif __GNUC__ < 4 75 #error module code needs GCC visibility extensions 76 #else 77 # define DSO_PUBLIC __attribute__ ((visibility ("default"))) 78 # define DSO_SELF __attribute__ ((visibility ("protected"))) 79 # define DSO_LOCAL __attribute__ ((visibility ("hidden"))) 80 #endif 81 82 #ifdef __sun 83 /* Solaris doesn't do constructor priorities due to linker restrictions */ 84 #undef _CONSTRUCTOR 85 #undef _DESTRUCTOR 86 #endif 87 88 /* fallback versions */ 89 #ifndef _RET_NONNULL 90 # define _RET_NONNULL 91 #endif 92 #ifndef _CONSTRUCTOR 93 # define _CONSTRUCTOR(x) constructor 94 #endif 95 #ifndef _DESTRUCTOR 96 # define _DESTRUCTOR(x) destructor 97 #endif 98 #ifndef _ALLOC_SIZE 99 # define _ALLOC_SIZE(x) 100 #endif 101 #ifndef _FALLTHROUGH 102 #define _FALLTHROUGH 103 #endif 104 #ifndef _DEPRECATED 105 #define _DEPRECATED(x) deprecated 106 #endif 107 #ifndef assume 108 #define assume(x) 109 #endif 110 111 /* pure = function does not modify memory & return value is the same if 112 * memory hasn't changed (=> allows compiler to optimize) 113 * 114 * Mostly autodetected by the compiler if function body is available (i.e. 115 * static inline functions in headers). Since that implies it should only be 116 * used in headers for non-inline functions, the "extern" is included here. 117 */ 118 #define ext_pure extern __attribute__((pure)) 119 120 /* for helper functions defined inside macros */ 121 #define macro_inline static inline __attribute__((unused)) 122 #define macro_pure static inline __attribute__((unused, pure)) 123 124 125 /* variadic macros, use like: 126 * #define V_0() ... 127 * #define V_1(x) ... 128 * #define V(...) MACRO_VARIANT(V, ##__VA_ARGS__)(__VA_ARGS__) 129 */ 130 #define _MACRO_VARIANT(A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10, N, ...) N 131 132 #define _CONCAT2(a, b) a ## b 133 #define _CONCAT(a, b) _CONCAT2(a,b) 134 135 #define MACRO_VARIANT(NAME, ...) \ 136 _CONCAT(NAME, _MACRO_VARIANT(0, ##__VA_ARGS__, \ 137 _10, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)) 138 139 #define NAMECTR(name) _CONCAT(name, __COUNTER__) 140 141 /* per-arg repeat macros, use like: 142 * #define PERARG(n) ...n... 143 * #define FOO(...) MACRO_REPEAT(PERARG, ##__VA_ARGS__) 144 */ 145 146 #define _MACRO_REPEAT_0(NAME) 147 #define _MACRO_REPEAT_1(NAME, A1) \ 148 NAME(A1) 149 #define _MACRO_REPEAT_2(NAME, A1, A2) \ 150 NAME(A1) NAME(A2) 151 #define _MACRO_REPEAT_3(NAME, A1, A2, A3) \ 152 NAME(A1) NAME(A2) NAME(A3) 153 #define _MACRO_REPEAT_4(NAME, A1, A2, A3, A4) \ 154 NAME(A1) NAME(A2) NAME(A3) NAME(A4) 155 #define _MACRO_REPEAT_5(NAME, A1, A2, A3, A4, A5) \ 156 NAME(A1) NAME(A2) NAME(A3) NAME(A4) NAME(A5) 157 #define _MACRO_REPEAT_6(NAME, A1, A2, A3, A4, A5, A6) \ 158 NAME(A1) NAME(A2) NAME(A3) NAME(A4) NAME(A5) NAME(A6) 159 #define _MACRO_REPEAT_7(NAME, A1, A2, A3, A4, A5, A6, A7) \ 160 NAME(A1) NAME(A2) NAME(A3) NAME(A4) NAME(A5) NAME(A6) NAME(A7) 161 #define _MACRO_REPEAT_8(NAME, A1, A2, A3, A4, A5, A6, A7, A8) \ 162 NAME(A1) NAME(A2) NAME(A3) NAME(A4) NAME(A5) NAME(A6) NAME(A7) NAME(A8) 163 164 #define MACRO_REPEAT(NAME, ...) \ 165 MACRO_VARIANT(_MACRO_REPEAT, ##__VA_ARGS__)(NAME, ##__VA_ARGS__) 166 167 /* 168 * for warnings on macros, put in the macro content like this: 169 * #define MACRO BLA CPP_WARN("MACRO has been deprecated") 170 */ 171 #define CPP_STR(X) #X 172 173 #if defined(__ICC) 174 #define CPP_NOTICE(text) _Pragma(CPP_STR(message __FILE__ ": " text)) 175 #define CPP_WARN(text) CPP_NOTICE(text) 176 177 #elif (defined(__GNUC__) \ 178 && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ 179 || (defined(__clang__) \ 180 && (__clang_major__ >= 4 \ 181 || (__clang_major__ == 3 && __clang_minor__ >= 5))) 182 #define CPP_WARN(text) _Pragma(CPP_STR(GCC warning text)) 183 #define CPP_NOTICE(text) _Pragma(CPP_STR(message text)) 184 185 #else 186 #define CPP_WARN(text) 187 #define CPP_NOTICE(text) 188 #endif 189 190 /* MAX / MIN are not commonly defined, but useful */ 191 /* note: glibc sys/param.h has #define MIN(a,b) (((a)<(b))?(a):(b)) */ 192 #ifdef MAX 193 #undef MAX 194 #endif 195 #define MAX(a, b) \ 196 ({ \ 197 typeof(a) _max_a = (a); \ 198 typeof(b) _max_b = (b); \ 199 _max_a > _max_b ? _max_a : _max_b; \ 200 }) 201 #ifdef MIN 202 #undef MIN 203 #endif 204 #define MIN(a, b) \ 205 ({ \ 206 typeof(a) _min_a = (a); \ 207 typeof(b) _min_b = (b); \ 208 _min_a < _min_b ? _min_a : _min_b; \ 209 }) 210 211 #define numcmp(a, b) \ 212 ({ \ 213 typeof(a) _cmp_a = (a); \ 214 typeof(b) _cmp_b = (b); \ 215 (_cmp_a < _cmp_b) ? -1 : ((_cmp_a > _cmp_b) ? 1 : 0); \ 216 }) 217 218 #ifndef offsetof 219 #ifdef __compiler_offsetof 220 #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER) 221 #else 222 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 223 #endif 224 #endif 225 226 #ifdef container_of 227 #undef container_of 228 #endif 229 230 #if !(defined(__cplusplus) || defined(test__cplusplus)) 231 /* this variant of container_of() retains 'const' on pointers without needing 232 * to be told to do so. The following will all work without warning: 233 * 234 * struct member *p; 235 * const struct member *cp; 236 * 237 * const struct cont *x = container_of(cp, struct cont, member); 238 * const struct cont *x = container_of(cp, const struct cont, member); 239 * const struct cont *x = container_of(p, struct cont, member); 240 * const struct cont *x = container_of(p, const struct cont, member); 241 * struct cont *x = container_of(p, struct cont, member); 242 * 243 * but the following will generate warnings about stripping const: 244 * 245 * struct cont *x = container_of(cp, struct cont, member); 246 * struct cont *x = container_of(cp, const struct cont, member); 247 * struct cont *x = container_of(p, const struct cont, member); 248 */ 249 #define container_of(ptr, type, member) \ 250 (__builtin_choose_expr( \ 251 __builtin_types_compatible_p(typeof(&((type *)0)->member), \ 252 typeof(ptr)) \ 253 || __builtin_types_compatible_p(void *, typeof(ptr)), \ 254 ({ \ 255 typeof(((type *)0)->member) *__mptr = (void *)(ptr); \ 256 (type *)((char *)__mptr - offsetof(type, member)); \ 257 }), \ 258 ({ \ 259 typeof(((const type *)0)->member) *__mptr = (ptr); \ 260 (const type *)((const char *)__mptr - \ 261 offsetof(type, member)); \ 262 }) \ 263 )) 264 #else 265 /* current C++ compilers don't have the builtins used above; so this version 266 * of the macro doesn't do the const check. */ 267 #define container_of(ptr, type, member) \ 268 ({ \ 269 const typeof(((type *)0)->member) *__mptr = (ptr); \ 270 (type *)((char *)__mptr - offsetof(type, member)); \ 271 }) 272 #endif 273 274 #define container_of_null(ptr, type, member) \ 275 ({ \ 276 typeof(ptr) _tmp = (ptr); \ 277 _tmp ? container_of(_tmp, type, member) : NULL; \ 278 }) 279 280 #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) 281 282 /* sigh. this is so ugly, it overflows and wraps to being nice again. 283 * 284 * printfrr() supports "%Ld" for <int64_t>, whatever that is typedef'd to. 285 * However, gcc & clang think that "%Ld" is <long long>, which doesn't quite 286 * match up since int64_t is <long> on a lot of 64-bit systems. 287 * 288 * If we have _FRR_ATTRIBUTE_PRINTFRR, we loaded a compiler plugin that 289 * replaces the whole format checking bits with a custom version that 290 * understands "%Ld" (along with "%pI4" and co.), so we don't need to do 291 * anything. 292 * 293 * If we don't have that attribute... we still want -Wformat to work. So, 294 * this is the "f*ck it" approach and we just redefine int64_t to always be 295 * <long long>. This should work until such a time that <long long> is 296 * something else (e.g. 128-bit integer)... let's just guard against that 297 * with the _Static_assert below and work with the world we have right now, 298 * where <long long> is always 64-bit. 299 */ 300 301 /* these need to be included before any of the following, so we can 302 * "overwrite" things. 303 */ 304 #include <stdint.h> 305 #include <inttypes.h> 306 307 #ifdef _FRR_ATTRIBUTE_PRINTFRR 308 #define PRINTFRR(a, b) __attribute__((frr_format("frr_printf", a, b))) 309 310 #undef PRIu64 311 #undef PRId64 312 #undef PRIx64 313 #define PRIu64 "Lu" 314 #define PRId64 "Ld" 315 #define PRIx64 "Lx" 316 317 #else /* !_FRR_ATTRIBUTE_PRINTFRR */ 318 #define PRINTFRR(a, b) __attribute__((format(printf, a, b))) 319 320 /* these should be typedefs, but might also be #define */ 321 #ifdef uint64_t 322 #undef uint64_t 323 #endif 324 #ifdef int64_t 325 #undef int64_t 326 #endif 327 328 /* can't overwrite the typedef, but we can replace int64_t with _int64_t */ 329 typedef unsigned long long _uint64_t; 330 #define uint64_t _uint64_t 331 typedef signed long long _int64_t; 332 #define int64_t _int64_t 333 334 /* if this breaks, 128-bit machines may have entered reality (or <long long> 335 * is something weird) 336 */ 337 #if __STDC_VERSION__ >= 201112L 338 _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8, 339 "nobody expects the spanish intquisition"); 340 #endif 341 342 /* since we redefined int64_t, we also need to redefine PRI*64 */ 343 #undef PRIu64 344 #undef PRId64 345 #undef PRIx64 346 #define PRIu64 "llu" 347 #define PRId64 "lld" 348 #define PRIx64 "llx" 349 #endif /* !_FRR_ATTRIBUTE_PRINTFRR */ 350 351 #ifdef __cplusplus 352 } 353 #endif 354 355 #endif /* _FRR_COMPILER_H */ 356