| 131 #endif |
131 #endif |
| 132 |
132 |
| 133 /** |
133 /** |
| 134 * Inform the compiler that falling through a switch case is intentional. |
134 * Inform the compiler that falling through a switch case is intentional. |
| 135 */ |
135 */ |
| 136 #define cx_attr_fallthrough __attribute__((__fallthrough__)) |
136 #define CX_FALLTHROUGH __attribute__((__fallthrough__)) |
| 137 |
137 |
| 138 /** |
138 /** |
| 139 * All pointer arguments must be non-NULL. |
139 * All pointer arguments must be non-NULL. |
| 140 */ |
140 */ |
| 141 #define cx_attr_nonnull __attribute__((__nonnull__)) |
141 #define CX_NONNULL __attribute__((__nonnull__)) |
| 142 |
142 |
| 143 /** |
143 /** |
| 144 * The specified pointer arguments must be non-NULL. |
144 * The specified pointer arguments must be non-NULL. |
| 145 */ |
145 */ |
| 146 #define cx_attr_nonnull_arg(...) __attribute__((__nonnull__(__VA_ARGS__))) |
146 #define CX_NONNULL_ARG(...) __attribute__((__nonnull__(__VA_ARGS__))) |
| 147 |
147 |
| 148 /** |
148 /** |
| 149 * The returned value is guaranteed to be non-NULL. |
149 * The returned value is guaranteed to be non-NULL. |
| 150 */ |
150 */ |
| 151 #define cx_attr_returns_nonnull __attribute__((__returns_nonnull__)) |
151 #define CX_RETURNS_NONNULL __attribute__((__returns_nonnull__)) |
| 152 |
152 |
| 153 /** |
153 /** |
| 154 * The attributed function always returns freshly allocated memory. |
154 * The attributed function always returns freshly allocated memory. |
| 155 */ |
155 */ |
| 156 #define cx_attr_malloc __attribute__((__malloc__)) |
156 #define CX_MALLOC __attribute__((__malloc__)) |
| 157 |
157 |
| 158 #if !defined(__clang__) && __GNUC__ >= 11 |
158 #if !defined(__clang__) && __GNUC__ >= 11 |
| 159 /** |
159 /** |
| 160 * The pointer returned by the attributed function is supposed to be freed |
160 * The pointer returned by the attributed function is supposed to be freed |
| 161 * by @p freefunc. |
161 * by @p freefunc. |
| 162 * |
162 * |
| 163 * @param freefunc the function that shall be used to free the memory |
163 * @param freefunc the function that shall be used to free the memory |
| 164 * @param freefunc_arg the index of the pointer argument in @p freefunc |
164 * @param freefunc_arg the index of the pointer argument in @p freefunc |
| 165 */ |
165 */ |
| 166 #define cx_attr_dealloc(freefunc, freefunc_arg) \ |
166 #define CX_DEALLOC(freefunc, freefunc_arg) \ |
| 167 __attribute__((__malloc__(freefunc, freefunc_arg))) |
167 __attribute__((__malloc__(freefunc, freefunc_arg))) |
| 168 #else |
168 #else |
| 169 /** |
169 /** |
| 170 * Not supported in clang. |
170 * Not supported in clang. |
| 171 */ |
171 */ |
| 172 #define cx_attr_dealloc(...) |
172 #define CX_DEALLOC(...) |
| 173 #endif // __clang__ |
173 #endif // __clang__ |
| 174 |
174 |
| 175 /** |
175 /** |
| 176 * Shortcut to specify #cxFree() as deallocator. |
176 * Shortcut to specify #cxFree() as deallocator. |
| 177 */ |
177 */ |
| 178 #define cx_attr_dealloc_ucx cx_attr_dealloc(cxFree, 2) |
178 #define CX_DEALLOC_UCX CX_DEALLOC(cxFree, 2) |
| 179 |
179 |
| 180 /** |
180 /** |
| 181 * Specifies the parameters from which the allocation size is calculated. |
181 * Specifies the parameters from which the allocation size is calculated. |
| 182 */ |
182 */ |
| 183 #define cx_attr_allocsize(...) __attribute__((__alloc_size__(__VA_ARGS__))) |
183 #define CX_ALLOCSIZE(...) __attribute__((__alloc_size__(__VA_ARGS__))) |
| 184 |
184 |
| 185 |
185 |
| 186 #ifdef __clang__ |
186 #ifdef __clang__ |
| 187 /** |
187 /** |
| 188 * No support for @c null_terminated_string_arg in clang or GCC below 14. |
188 * No support for @c null_terminated_string_arg in clang or GCC below 14. |
| 189 */ |
189 */ |
| 190 #define cx_attr_cstr_arg(idx) |
190 #define CX_CSTR_ARG(idx) |
| 191 /** |
191 /** |
| 192 * No support for the access attribute in clang. |
192 * No support for the access attribute in clang. |
| 193 */ |
193 */ |
| 194 #define cx_attr_access(mode, ...) |
194 #define CX_ACCESS(mode, ...) |
| 195 #else |
195 #else |
| 196 #if __GNUC__ < 10 |
196 #if __GNUC__ < 10 |
| 197 /** |
197 /** |
| 198 * No support for access attribute in GCC < 10. |
198 * No support for access attribute in GCC < 10. |
| 199 */ |
199 */ |
| 200 #define cx_attr_access(mode, ...) |
200 #define CX_ACCESS(mode, ...) |
| 201 #else |
201 #else |
| 202 /** |
202 /** |
| 203 * Helper macro to define access macros. |
203 * Helper macro to define access macros. |
| 204 */ |
204 */ |
| 205 #define cx_attr_access(mode, ...) __attribute__((__access__(mode, __VA_ARGS__))) |
205 #define CX_ACCESS(mode, ...) __attribute__((__access__(mode, __VA_ARGS__))) |
| 206 #endif // __GNUC__ < 10 |
206 #endif // __GNUC__ < 10 |
| 207 #if __GNUC__ < 14 |
207 #if __GNUC__ < 14 |
| 208 /** |
208 /** |
| 209 * No support for @c null_terminated_string_arg in clang or GCC below 14. |
209 * No support for @c null_terminated_string_arg in clang or GCC below 14. |
| 210 */ |
210 */ |
| 211 #define cx_attr_cstr_arg(idx) |
211 #define CX_CSTR_ARG(idx) |
| 212 #else |
212 #else |
| 213 /** |
213 /** |
| 214 * The specified argument is expected to be a zero-terminated string. |
214 * The specified argument is expected to be a zero-terminated string. |
| 215 * |
215 * |
| 216 * @param idx the index of the argument |
216 * @param idx the index of the argument |
| 217 */ |
217 */ |
| 218 #define cx_attr_cstr_arg(idx) \ |
218 #define CX_CSTR_ARG(idx) \ |
| 219 __attribute__((__null_terminated_string_arg__(idx))) |
219 __attribute__((__null_terminated_string_arg__(idx))) |
| 220 #endif // __GNUC__ < 14 |
220 #endif // __GNUC__ < 14 |
| 221 #endif // __clang__ |
221 #endif // __clang__ |
| 222 |
222 |
| 223 |
223 |
| 225 * Specifies that the function will only read through the given pointer. |
225 * Specifies that the function will only read through the given pointer. |
| 226 * |
226 * |
| 227 * Takes one or two arguments: the index of the pointer and (optionally) the |
227 * Takes one or two arguments: the index of the pointer and (optionally) the |
| 228 * index of another argument specifying the maximum number of accessed bytes. |
228 * index of another argument specifying the maximum number of accessed bytes. |
| 229 */ |
229 */ |
| 230 #define cx_attr_access_r(...) cx_attr_access(__read_only__, __VA_ARGS__) |
230 #define CX_ACCESS_R(...) CX_ACCESS(__read_only__, __VA_ARGS__) |
| 231 |
231 |
| 232 /** |
232 /** |
| 233 * Specifies that the function will read and write through the given pointer. |
233 * Specifies that the function will read and write through the given pointer. |
| 234 * |
234 * |
| 235 * Takes one or two arguments: the index of the pointer and (optionally) the |
235 * Takes one or two arguments: the index of the pointer and (optionally) the |
| 236 * index of another argument specifying the maximum number of accessed bytes. |
236 * index of another argument specifying the maximum number of accessed bytes. |
| 237 */ |
237 */ |
| 238 #define cx_attr_access_rw(...) cx_attr_access(__read_write__, __VA_ARGS__) |
238 #define CX_ACCESS_RW(...) CX_ACCESS(__read_write__, __VA_ARGS__) |
| 239 |
239 |
| 240 /** |
240 /** |
| 241 * Specifies that the function will only write through the given pointer. |
241 * Specifies that the function will only write through the given pointer. |
| 242 * |
242 * |
| 243 * Takes one or two arguments: the index of the pointer and (optionally) the |
243 * Takes one or two arguments: the index of the pointer and (optionally) the |
| 244 * index of another argument specifying the maximum number of accessed bytes. |
244 * index of another argument specifying the maximum number of accessed bytes. |
| 245 */ |
245 */ |
| 246 #define cx_attr_access_w(...) cx_attr_access(__write_only__, __VA_ARGS__) |
246 #define CX_ACCESS_W(...) CX_ACCESS(__write_only__, __VA_ARGS__) |
| 247 |
247 |
| 248 /** |
248 /** |
| 249 * Do not warn about unused variable. |
249 * Do not warn about unused variable. |
| 250 */ |
250 */ |
| 251 #define cx_attr_unused __attribute__((__unused__)) |
251 #define CX_UNUSED __attribute__((__unused__)) |
| 252 |
252 |
| 253 /** |
253 /** |
| 254 * Warn about discarded return value. |
254 * Warn about discarded return value. |
| 255 */ |
255 */ |
| 256 #define cx_attr_nodiscard __attribute__((__warn_unused_result__)) |
256 #define CX_NODISCARD __attribute__((__warn_unused_result__)) |
| 257 |
257 |
| 258 |
258 |
| 259 // --------------------------------------------------------------------------- |
259 // --------------------------------------------------------------------------- |
| 260 // Support for thread_local |
260 // Support for thread_local |
| 261 // --------------------------------------------------------------------------- |
261 // --------------------------------------------------------------------------- |