]> git.proxmox.com Git - mirror_frr.git/blob - lib/compiler.h
Merge pull request #4468 from donaldsharp/isis_v6_addr_count
[mirror_frr.git] / lib / compiler.h
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 #elif defined(__GNUC__)
37 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
38 # define _RET_NONNULL , returns_nonnull
39 #endif
40 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
41 # define _CONSTRUCTOR(x) constructor(x)
42 # define _DESTRUCTOR(x) destructor(x)
43 # define _ALLOC_SIZE(x) alloc_size(x)
44 #endif
45 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
46 # define _DEPRECATED(x) deprecated(x)
47 #endif
48 #if __GNUC__ >= 7
49 # define _FALLTHROUGH __attribute__((fallthrough));
50 #endif
51 #endif
52
53 #if !defined(__GNUC__)
54 #error module code needs GCC visibility extensions
55 #elif __GNUC__ < 4
56 #error module code needs GCC visibility extensions
57 #else
58 # define DSO_PUBLIC __attribute__ ((visibility ("default")))
59 # define DSO_SELF __attribute__ ((visibility ("protected")))
60 # define DSO_LOCAL __attribute__ ((visibility ("hidden")))
61 #endif
62
63 #ifdef __sun
64 /* Solaris doesn't do constructor priorities due to linker restrictions */
65 #undef _CONSTRUCTOR
66 #undef _DESTRUCTOR
67 #endif
68
69 /* fallback versions */
70 #ifndef _RET_NONNULL
71 # define _RET_NONNULL
72 #endif
73 #ifndef _CONSTRUCTOR
74 # define _CONSTRUCTOR(x) constructor
75 #endif
76 #ifndef _DESTRUCTOR
77 # define _DESTRUCTOR(x) destructor
78 #endif
79 #ifndef _ALLOC_SIZE
80 # define _ALLOC_SIZE(x)
81 #endif
82 #ifndef _FALLTHROUGH
83 #define _FALLTHROUGH
84 #endif
85 #ifndef _DEPRECATED
86 #define _DEPRECATED(x) deprecated
87 #endif
88
89 /* pure = function does not modify memory & return value is the same if
90 * memory hasn't changed (=> allows compiler to optimize)
91 *
92 * Mostly autodetected by the compiler if function body is available (i.e.
93 * static inline functions in headers). Since that implies it should only be
94 * used in headers for non-inline functions, the "extern" is included here.
95 */
96 #define ext_pure extern __attribute__((pure))
97
98 /* for helper functions defined inside macros */
99 #define macro_inline static inline __attribute__((unused))
100 #define macro_pure static inline __attribute__((unused, pure))
101
102 /*
103 * for warnings on macros, put in the macro content like this:
104 * #define MACRO BLA CPP_WARN("MACRO has been deprecated")
105 */
106 #define CPP_STR(X) #X
107
108 #if defined(__ICC)
109 #define CPP_NOTICE(text) _Pragma(CPP_STR(message __FILE__ ": " text))
110 #define CPP_WARN(text) CPP_NOTICE(text)
111
112 #elif (defined(__GNUC__) \
113 && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
114 || (defined(__clang__) \
115 && (__clang_major__ >= 4 \
116 || (__clang_major__ == 3 && __clang_minor__ >= 5)))
117 #define CPP_WARN(text) _Pragma(CPP_STR(GCC warning text))
118 #define CPP_NOTICE(text) _Pragma(CPP_STR(message text))
119
120 #else
121 #define CPP_WARN(text)
122 #define CPP_NOTICE(text)
123 #endif
124
125 /* MAX / MIN are not commonly defined, but useful */
126 /* note: glibc sys/param.h has #define MIN(a,b) (((a)<(b))?(a):(b)) */
127 #ifdef MAX
128 #undef MAX
129 #endif
130 #define MAX(a, b) \
131 ({ \
132 typeof(a) _max_a = (a); \
133 typeof(b) _max_b = (b); \
134 _max_a > _max_b ? _max_a : _max_b; \
135 })
136 #ifdef MIN
137 #undef MIN
138 #endif
139 #define MIN(a, b) \
140 ({ \
141 typeof(a) _min_a = (a); \
142 typeof(b) _min_b = (b); \
143 _min_a < _min_b ? _min_a : _min_b; \
144 })
145
146 #ifndef offsetof
147 #ifdef __compiler_offsetof
148 #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER)
149 #else
150 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
151 #endif
152 #endif
153
154 /* this variant of container_of() retains 'const' on pointers without needing
155 * to be told to do so. The following will all work without warning:
156 *
157 * struct member *p;
158 * const struct member *cp;
159 *
160 * const struct cont *x = container_of(cp, struct cont, member);
161 * const struct cont *x = container_of(cp, const struct cont, member);
162 * const struct cont *x = container_of(p, struct cont, member);
163 * const struct cont *x = container_of(p, const struct cont, member);
164 * struct cont *x = container_of(p, struct cont, member);
165 *
166 * but the following will generate warnings about stripping const:
167 *
168 * struct cont *x = container_of(cp, struct cont, member);
169 * struct cont *x = container_of(cp, const struct cont, member);
170 * struct cont *x = container_of(p, const struct cont, member);
171 */
172 #ifdef container_of
173 #undef container_of
174 #endif
175 #define container_of(ptr, type, member) \
176 (__builtin_choose_expr( \
177 __builtin_types_compatible_p(typeof(&((type *)0)->member), \
178 typeof(ptr)) \
179 || __builtin_types_compatible_p(void *, typeof(ptr)), \
180 ({ \
181 typeof(((type *)0)->member) *__mptr = (void *)(ptr); \
182 (type *)((char *)__mptr - offsetof(type, member)); \
183 }), \
184 ({ \
185 typeof(((const type *)0)->member) *__mptr = (ptr); \
186 (const type *)((const char *)__mptr - \
187 offsetof(type, member)); \
188 }) \
189 ))
190
191 #define container_of_null(ptr, type, member) \
192 ({ \
193 typeof(ptr) _tmp = (ptr); \
194 _tmp ? container_of(_tmp, type, member) : NULL; \
195 })
196
197 #define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
198
199 #ifdef __cplusplus
200 }
201 #endif
202
203 #endif /* _FRR_COMPILER_H */