1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef FWK_ATTRIBUTES_H
9 #define FWK_ATTRIBUTES_H
10 
11 #include <fwk_macros.h>
12 
13 /*!
14  * \addtogroup GroupLibFramework Framework
15  * \{
16  */
17 
18 /*!
19  * \defgroup GroupAttributes Attributes
20  *
21  * \brief Compiler-independent attribute macros.
22  *
23  * \details This component exposes a number of compiler-specific macros in a
24  *      way that they can be used without causing compilation issues on
25  *      compilers that do not support them.
26  *
27  * @warning Where an attribute does not modify the behaviour of a well-formed
28  *      program, it may expand to nothing if the compiler in use does not
29  *      support it. However, attributes for which a lack of support may
30  *      fundamentally alter the program will not be defined on any compiler that
31  *      does not support it.
32  *
33  * \{
34  */
35 
36 /*!
37  * \def FWK_HAS_BUILTIN
38  *
39  * \brief Check whether the compiler supports a given builtin.
40  *
41  * \param[in] BUILTIN Builtin name.
42  *
43  * \returns A value usable in the expression of a preprocessor `if` or `elif`
44  *      statement.
45  */
46 
47 #ifdef __has_builtin
48 #    define FWK_HAS_BUILTIN(BUILTIN) __has_builtin(BUILTIN)
49 #else
50 #    define FWK_HAS_BUILTIN(BUILTIN) 0
51 #endif
52 
53 /*!
54  * \def FWK_HAS_GNU_ATTRIBUTE
55  *
56  * \brief Check whether the compiler supports a given GNU attribute.
57  *
58  * \param[in] ATTRIBUTE Attribute name.
59  *
60  * \returns A value usable in the expression of a preprocessor `if` or `elif`
61  *      statement.
62  */
63 
64 #ifdef __has_attribute
65 #    define FWK_HAS_GNU_ATTRIBUTE(ATTRIBUTE) __has_attribute(ATTRIBUTE)
66 #else
67 #    define FWK_HAS_GNU_ATTRIBUTE(ATTRIBUTE) 0
68 #endif
69 
70 /*!
71  * \def FWK_HAS_MS_ATTRIBUTE
72  *
73  * \brief Check whether the compiler supports a given Microsoft attribute.
74  *
75  * \param[in] ATTRIBUTE Attribute name.
76  *
77  * \returns A value usable in the expression of a preprocessor `if` or `elif`
78  *      statement.
79  */
80 
81 #if defined(__has_declspec_attribute) && !defined(__clang__)
82 #    define FWK_HAS_MS_ATTRIBUTE(ATTRIBUTE) __has_declspec_attribute(ATTRIBUTE)
83 #else
84 #    define FWK_HAS_MS_ATTRIBUTE(ATTRIBUTE) 0
85 #endif
86 
87 /*!
88  * \def FWK_ALLOC
89  *
90  * \brief "Allocator" attribute.
91  *
92  * \details Hints that the pointer returned by this function does not alias any
93  *      other pointer, nor do any pointers to valid objects exist within the
94  *      storage addressed by the pointer.
95  *
96  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
97  * \see https://docs.microsoft.com/en-us/cpp/cpp/allocator?view=vs-2019
98  */
99 
100 #if FWK_HAS_GNU_ATTRIBUTE(__malloc__)
101 #    define FWK_ALLOC_1 __attribute__((__malloc__))
102 #else
103 #    define FWK_ALLOC_1
104 #endif
105 
106 #if FWK_HAS_MS_ATTRIBUTE(allocator)
107 #    define FWK_ALLOC_2 __declspec(allocator)
108 #else
109 #    define FWK_ALLOC_2
110 #endif
111 
112 #if FWK_HAS_MS_ATTRIBUTE(restrict)
113 #    define FWK_ALLOC_3 __declspec(restrict)
114 #else
115 #    define FWK_ALLOC_3
116 #endif
117 
118 #define FWK_ALLOC FWK_ALLOC_1 FWK_ALLOC_2 FWK_ALLOC_3
119 
120 /*!
121  * \def FWK_ALLOC_SIZE1
122  *
123  * \brief "Sizing allocator" attribute.
124  *
125  * \details Hints that the pointer returned by this function has a size given
126  *      by a parameter.
127  *
128  * \param[in] SIZE_POS Position of the size parameter, 1-indexed.
129  *
130  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
131  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-alloc_005fsize-variable-attribute
132  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-alloc_005fsize-type-attribute
133  */
134 
135 /*!
136  * \def FWK_ALLOC_SIZE2
137  *
138  * \brief "Sizing allocator" attribute.
139  *
140  * \details Hints that the pointer returned by this function has a size given
141  *      by the product of a size and a count parameter.
142  *
143  * \param[in] SIZE_POS Position of the size parameter, 1-indexed.
144  * \param[in] COUNT_POS Position of the count parameter, 1-indexed.
145  *
146  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
147  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-alloc_005fsize-variable-attribute
148  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-alloc_005fsize-type-attribute
149  */
150 
151 #if FWK_HAS_GNU_ATTRIBUTE(__alloc_size__)
152 #    define FWK_ALLOC_SIZE1(SIZE_POS) __attribute__((__alloc_size__(SIZE_POS)))
153 #    define FWK_ALLOC_SIZE2(SIZE_POS, COUNT_POS) \
154         __attribute__((__alloc_size__(SIZE_POS, COUNT_POS)))
155 #else
156 #    define FWK_ALLOC_SIZE1(SIZE_POS)
157 #    define FWK_ALLOC_SIZE2(SIZE_POS, COUNT_POS)
158 #endif
159 
160 /*!
161  * \def FWK_ALLOC_ALIGN
162  *
163  * \brief "Aligning allocator" attribute.
164  *
165  * \details Hints that the pointer returned by this function has an alignment
166  *      given by a parameter.
167  *
168  * \param[in] ALIGN_POS Position of the alignment parameter, 1-indexed.
169  *
170  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005falign-function-attribute
171  */
172 
173 #if FWK_HAS_GNU_ATTRIBUTE(__alloc_align__)
174 #    define FWK_ALLOC_ALIGN(ALIGN_POS) \
175         __attribute__((__alloc_align__(ALIGN_POS)))
176 #else
177 #    define FWK_ALLOC_ALIGN(ALIGN_POS)
178 #endif
179 
180 /*!
181  * \def FWK_WEAK
182  *
183  * \brief "Weak" attribute.
184  *
185  * \details Applies weak linkage to the item.
186  *
187  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute
188  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-weak-variable-attribute
189  */
190 
191 #if FWK_HAS_GNU_ATTRIBUTE(__weak__)
192 #    define FWK_WEAK __attribute__((__weak__))
193 #endif
194 
195 /*!
196  * \def FWK_PRINTF
197  *
198  * \brief "`printf`-like" attribute.
199  *
200  * \details Hints that the function takes a string literal with the same
201  *      semantics as the `printf` format string.
202  *
203  * \param[in] STR_POS Position of the format string parameter, 1-indexed.
204  * \param[in] VA_POS Position of the argument list, 1-indexed.
205  *
206  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-Wformat-3
207  */
208 
209 #if FWK_HAS_GNU_ATTRIBUTE(__format__)
210 #    define FWK_PRINTF(STR_POS, VA_POS) \
211         __attribute__((__format__(printf, STR_POS, VA_POS)))
212 #else
213 #    define FWK_PRINTF(STR_POS, VA_POS)
214 #endif
215 
216 /*!
217  * \def FWK_CONSTRUCTOR
218  *
219  * \brief "Constructor" attribute.
220  *
221  * \details Adds the function to the list of functions to be executed before
222  *      `main`.
223  *
224  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-constructor-function-attribute
225  */
226 
227 #if FWK_HAS_GNU_ATTRIBUTE(__constructor__)
228 #    define FWK_CONSTRUCTOR __attribute__((__constructor__))
229 #endif
230 
231 /*!
232  * \def FWK_PACKED
233  *
234  * \brief "Packed" attribute.
235  *
236  * \details Packs the item that this attribute is attached to.
237  *
238  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-aligned-type-attribute
239  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
240  */
241 
242 #if FWK_HAS_GNU_ATTRIBUTE(__packed__)
243 #    define FWK_PACKED __attribute__((__packed__))
244 #endif
245 
246 /*!
247  * \def FWK_SECTION
248  *
249  * \brief "Linker section" attribute.
250  *
251  * \details Places the item that this attribute is attached to into a particular
252  *      linker section.
253  *
254  * \param[in] SECTION String literal representing the name of the section.
255  *
256  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute
257  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
258  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
259  */
260 
261 #if FWK_HAS_GNU_ATTRIBUTE(__section__)
262 #    define FWK_SECTION(SECTION) __attribute__((__section__(SECTION)))
263 #endif
264 
265 /*!
266  * \def FWK_DEPRECATED
267  *
268  * \brief "Deprecated" attribute.
269  *
270  * \details Marks the item that this attribute is attached to as deprecated.
271  *
272  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute
273  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-deprecated-variable-attribute
274  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-deprecated-type-attribute
275  * \see https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html#index-deprecated-enumerator-attribute
276  */
277 
278 #if FWK_HAS_GNU_ATTRIBUTE(__deprecated__)
279 #    define FWK_DEPRECATED __attribute__((__deprecated__))
280 #else
281 #    define FWK_DEPRECATED
282 #endif
283 
284 /*!
285  * \def FWK_NOINLINE
286  *
287  * \brief "Do not inline" attribute.
288  *
289  * \details Hints to the compiler that the function should not be inlined.
290  *
291  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
292  */
293 
294 #if FWK_HAS_GNU_ATTRIBUTE(__noinline__)
295 #    define FWK_NOINLINE __attribute__((__noinline__))
296 #else
297 #    define FWK_NOINLINE
298 #endif
299 
300 /*!
301  * \def FWK_WARN_UNUSED
302  *
303  * \brief "Warn on unused result" attribute.
304  *
305  * \details Hints that it is a possible error to ignore the result of a
306  *      function.
307  *
308  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-warn_005funused_005fresult-function-attribute
309  */
310 
311 #if FWK_HAS_GNU_ATTRIBUTE(__warn_unused_result__)
312 #    define FWK_WARN_UNUSED __attribute__((__warn_unused_result__))
313 #else
314 #    define FWK_WARN_UNUSED
315 #endif
316 
317 /*!
318  * \def FWK_LEAF
319  *
320  * \brief "Leaf" attribute.
321  *
322  * \details Specifies that the function will return to the current compilation
323  *      unit only by returning or by throwing an exception.
324  *
325  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-leaf-function-attribute
326  */
327 
328 #if FWK_HAS_GNU_ATTRIBUTE(__leaf__)
329 #    define FWK_LEAF __attribute__((__leaf__))
330 #else
331 #    define FWK_LEAF
332 #endif
333 
334 /*!
335  * \def FWK_NOTHROW
336  *
337  * \brief "Doesn't throw" attribute.
338  *
339  * \details Specifies that the function will not throw an exception, either
340  *      directly or indirectly.
341  *
342  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nothrow-function-attribute
343  */
344 
345 #if FWK_HAS_GNU_ATTRIBUTE(__nothrow__)
346 #    define FWK_NOTHROW __attribute__((__nothrow__))
347 #else
348 #    define FWK_NOTHROW
349 #endif
350 
351 /*!
352  * \def FWK_CONST
353  *
354  * \brief "Strictly pure" attribute.
355  *
356  * \details Hints that the function will consistently return the same result for
357  *      the same input and will not make any changes to the observable state
358  *      of the program.
359  *
360  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
361  */
362 
363 #if FWK_HAS_GNU_ATTRIBUTE(__const__)
364 #    define FWK_CONST __attribute__((__const__))
365 #else
366 #    define FWK_CONST
367 #endif
368 
369 /*!
370  * \def FWK_PURE
371  *
372  * \brief "Pure" attribute.
373  *
374  * \details Hints that the function will consistently return the same result for
375  *      the same input and will not make any changes to the observable state
376  *      of the program, but may read non-volatile objects not given as an input
377  *      to the function
378  *
379  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
380  */
381 
382 #if FWK_HAS_GNU_ATTRIBUTE(__pure__)
383 #    define FWK_PURE __attribute__((__pure__))
384 #else
385 #    define FWK_PURE
386 #endif
387 
388 /*!
389  * \def FWK_READ_ONLY1
390  *
391  * \brief "Read only" attribute.
392  *
393  * \details Hints that the function takes a reference to an object which is read
394  *      from but not written to, and that the object must therefore be
395  *      initialized.
396  *
397  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
398  *
399  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
400  */
401 
402 /*!
403  * \def FWK_READ_ONLY2
404  *
405  * \brief "Read only" attribute.
406  *
407  * \details Hints that the function takes a reference to an object with a given
408  *      size which is read from but not written to, and that the object must
409  *      therefore be initialized.
410  *
411  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
412  * \param[in] SIZE_POS Position of the size parameter, 1-indexed.
413  *
414  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
415  */
416 
417 #if FWK_HAS_GNU_ATTRIBUTE(__access__)
418 #    define FWK_READ_ONLY1(REF_POS) \
419         __attribute__((__access__(read_only, REF_POS)))
420 #    define FWK_READ_ONLY2(REF_POS, SIZE_POS) \
421         __attribute__((__access__(read_only, REF_POS, SIZE_POS)))
422 #else
423 #    define FWK_READ_ONLY1(REF_POS)
424 #    define FWK_READ_ONLY2(REF_POS, SIZE_POS)
425 #endif
426 
427 /*!
428  * \def FWK_WRITE_ONLY1
429  *
430  * \brief "Write only" attribute.
431  *
432  * \details Hints that the function takes a reference to an object which is
433  *      written to but not read from, and that the object is therefore permitted
434  *      to be uninitialized.
435  *
436  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
437  *
438  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
439  */
440 
441 /*!
442  * \def FWK_WRITE_ONLY2
443  *
444  * \brief "Write only" attribute.
445  *
446  * \details Hints that the function takes a reference to an object with a given
447  *      size which is written to but not read from, and that the object is
448  *      therefore permitted to be uninitialized.
449  *
450  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
451  * \param[in] SIZE_POS Position of the size parameter, 1-indexed.
452  *
453  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
454  */
455 
456 #if FWK_HAS_GNU_ATTRIBUTE(__access__)
457 #    define FWK_WRITE_ONLY1(REF_POS) \
458         __attribute__((__access__(write_only, REF_POS)))
459 #    define FWK_WRITE_ONLY2(REF_POS, SIZE_POS) \
460         __attribute__((__access__(write_only, REF_POS, SIZE_POS)))
461 #else
462 #    define FWK_WRITE_ONLY1(REF_POS)
463 #    define FWK_WRITE_ONLY2(REF_POS, SIZE_POS)
464 #endif
465 
466 /*!
467  * \def FWK_READ_WRITE1
468  *
469  * \brief "Read/write" attribute.
470  *
471  * \details Hints that the function takes a reference to an object which is
472  *      both read from and written to, and that the object must therefore be
473  *      initialized.
474  *
475  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
476  *
477  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
478  */
479 
480 /*!
481  * \def FWK_READ_WRITE2
482  *
483  * \brief "Read/write" attribute.
484  *
485  * \details Hints that the function takes a reference to an object with a given
486  *      size which is both read from and written to, and that the object must
487  *      therefore be initialized.
488  *
489  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
490  * \param[in] SIZE_POS Position of the size parameter, 1-indexed.
491  *
492  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
493  */
494 
495 #if FWK_HAS_GNU_ATTRIBUTE(__access__)
496 #    define FWK_READ_WRITE1(REF_POS) \
497         __attribute__((__access__(read_write, REF_POS)))
498 #    define FWK_READ_WRITE2(REF_POS, SIZE_POS) \
499         __attribute__((__access__(read_write, REF_POS, SIZE_POS)))
500 #else
501 #    define FWK_READ_WRITE1(REF_POS)
502 #    define FWK_READ_WRITE2(REF_POS, SIZE_POS)
503 #endif
504 
505 /*!
506  * \def FWK_UNTOUCHED
507  *
508  * \brief "Untouched" attribute.
509  *
510  * \details Hints that the function takes a reference to an object which is
511  *      neither read from nor written to, but for which the reference itself is
512  *      used.
513  *
514  * \param[in] REF_POS Position of the reference parameter, 1-indexed.
515  *
516  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
517  */
518 
519 #if FWK_HAS_GNU_ATTRIBUTE(__access__) && __GNUC__ >= 11
520 #    define FWK_UNTOUCHED(REF_POS) __attribute__((__access__(none, REF_POS)))
521 #else
522 #    define FWK_UNTOUCHED(REF_POS)
523 #endif
524 
525 /*!
526  * \def FWK_NONNULL
527  *
528  * \brief "Non-null" attribute.
529  *
530  * \details Hints that the the function takes a pointer that should not be null.
531  *
532  * \param[in] PTR_POS Position of the pointer parameter, 1-indexed.
533  *
534  * \see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute
535  */
536 
537 #if FWK_HAS_GNU_ATTRIBUTE(__nonnull__)
538 #    define FWK_NONNULL(PTR_POS) __attribute__((__nonnull__(PTR_POS)))
539 #else
540 #    define FWK_NONNULL(PTR_POS)
541 #endif
542 
543 /*!
544  * \def FWK_FALLTHROUGH
545  *
546  * \brief "Fallthrough" attribute.
547  *
548  * \details Hints that a fallthrough in a switch statement is intended.
549  *
550  * \see https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-fallthrough-statement-attribute
551  */
552 
553 #if FWK_HAS_GNU_ATTRIBUTE(__fallthrough__)
554 #    define FWK_FALLTHROUGH __attribute__((__fallthrough__))
555 #else
556 #    define FWK_FALLTHROUGH
557 #endif
558 
559 /*!
560  * \}
561  */
562 
563 /*!
564  * \}
565  */
566 
567 #endif /* FWK_ATTRIBUTES_H */
568