]> git.proxmox.com Git - mirror_frr.git/blame - lib/compiler.h
lib: add some macro helpers
[mirror_frr.git] / lib / compiler.h
CommitLineData
de1a880c
DL
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
5e244469
RW
20#ifdef __cplusplus
21extern "C" {
22#endif
23
de1a880c
DL
24/* function attributes, use like
25 * void prototype(void) __attribute__((_CONSTRUCTOR(100)));
26 */
27#if defined(__clang__)
996c9314 28#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
de1a880c 29# define _RET_NONNULL , returns_nonnull
996c9314 30#endif
bd27ea43
DL
31#if __has_attribute(fallthrough)
32# define _FALLTHROUGH __attribute__((fallthrough));
33#endif
de1a880c 34# define _CONSTRUCTOR(x) constructor(x)
bcea0c0f 35# define _DEPRECATED(x) deprecated(x)
111a04f7
DL
36# if __has_builtin(assume)
37# define assume(x) __builtin_assume(x)
38# endif
de1a880c 39#elif defined(__GNUC__)
996c9314 40#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
de1a880c 41# define _RET_NONNULL , returns_nonnull
996c9314
LB
42#endif
43#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
de1a880c
DL
44# define _CONSTRUCTOR(x) constructor(x)
45# define _DESTRUCTOR(x) destructor(x)
46# define _ALLOC_SIZE(x) alloc_size(x)
996c9314 47#endif
bcea0c0f
DL
48#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
49# define _DEPRECATED(x) deprecated(x)
111a04f7
DL
50# define assume(x) do { if (!(x)) __builtin_unreachable(); } while (0)
51#endif
52#if __GNUC__ < 5
53# define __has_attribute(x) 0
bcea0c0f 54#endif
bd27ea43
DL
55#if __GNUC__ >= 7
56# define _FALLTHROUGH __attribute__((fallthrough));
57#endif
de1a880c
DL
58#endif
59
111a04f7
DL
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
8be3678a
DL
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
de1a880c
DL
82#ifdef __sun
83/* Solaris doesn't do constructor priorities due to linker restrictions */
996c9314
LB
84#undef _CONSTRUCTOR
85#undef _DESTRUCTOR
de1a880c
DL
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
bd27ea43
DL
101#ifndef _FALLTHROUGH
102#define _FALLTHROUGH
103#endif
bcea0c0f
DL
104#ifndef _DEPRECATED
105#define _DEPRECATED(x) deprecated
106#endif
111a04f7
DL
107#ifndef assume
108#define assume(x)
109#endif
de1a880c 110
3b18b6c0
DL
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
0d019561
DL
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
48373d46
DL
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
de1a880c
DL
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)
ec40eaf9 187#define CPP_NOTICE(text)
de1a880c
DL
188#endif
189
0d019561
DL
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
1315d74d
DL
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
0d019561
DL
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
a7f20d43
DL
226#ifdef container_of
227#undef container_of
228#endif
229
230#if !(defined(__cplusplus) || defined(test__cplusplus))
0d019561
DL
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 */
0d019561
DL
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 ))
a7f20d43
DL
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
0d019561
DL
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
afb35622
DL
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__((printfrr(a, b)))
309
310#else /* !_FRR_ATTRIBUTE_PRINTFRR */
311#define PRINTFRR(a, b) __attribute__((format(printf, a, b)))
312
313/* these should be typedefs, but might also be #define */
314#ifdef uint64_t
315#undef uint64_t
316#endif
317#ifdef int64_t
318#undef int64_t
319#endif
320
321/* can't overwrite the typedef, but we can replace int64_t with _int64_t */
322typedef unsigned long long _uint64_t;
323#define uint64_t _uint64_t
324typedef signed long long _int64_t;
325#define int64_t _int64_t
326
327/* if this breaks, 128-bit machines may have entered reality (or <long long>
328 * is something weird)
329 */
330#if __STDC_VERSION__ >= 201112L
331_Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8,
332 "nobody expects the spanish intquisition");
333#endif
334
335/* since we redefined int64_t, we also need to redefine PRI*64 */
336#undef PRIu64
337#undef PRId64
338#undef PRIx64
339#define PRIu64 "llu"
340#define PRId64 "lld"
341#define PRIx64 "llx"
342#endif /* !_FRR_ATTRIBUTE_PRINTFRR */
343
5e244469
RW
344#ifdef __cplusplus
345}
346#endif
347
de1a880c 348#endif /* _FRR_COMPILER_H */