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