pattributes.h (2400B)
1 2 /* 3 * C23 introduces an attribute syntax `[[<attribute>]]`. Prior to that 4 * other non-standard syntaxes such as `__attribute__((<attribute>))` 5 * and `__declspec(<attribute>)` have been supported by some compiler 6 * versions. 7 * 8 * See also: 9 * https://en.cppreference.com/w/c/language/attributes 10 * 11 * There is no portable way to use C23 attributes in older C standards 12 * so in order to use these portably, some macro name needs to be 13 * defined for each attribute that either maps to the older supported 14 * syntax, or ignores the attribute as appropriate. 15 * 16 * The Linux kernel defines certain attributes as macros, such as 17 * `fallthrough`. When adding attributes it seems reasonable to follow 18 * the Linux conventions in lack of any official standard. However, it 19 * is not the intention that this file should mirror the Linux 20 * attributes 1 to 1. 21 * 22 * See also: 23 * https://github.com/torvalds/linux/blob/master/include/linux/compiler_attributes.h 24 * 25 * There is a risk that exposed attribute names may lead to name 26 * conflicts. A conflicting name can be undefined and if necessary used 27 * using `pattribute(<attribute>)`. All attributes can be hidden by 28 * defining `PORTABLE_EXPOSE_ATTRIBUTES=0` in which case 29 * `pattribute(<attribute>)` can still be used and then if a specific 30 * attribute name still needs to be exposed, it can be defined manually 31 * like `#define fallthrough pattribute(fallthrough)`. 32 */ 33 34 35 #ifndef PATTRIBUTES_H 36 #define PATTRIBUTES_H 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 #ifndef PORTABLE_EXPOSE_ATTRIBUTES 43 #define PORTABLE_EXPOSE_ATTRIBUTES 0 44 #endif 45 46 #ifdef __has_c_attribute 47 # define PORTABLE_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) 48 #else 49 # define PORTABLE_HAS_C_ATTRIBUTE(x) 0 50 #endif 51 52 #ifdef __has_attribute 53 # define PORTABLE_HAS_ATTRIBUTE(x) __has_attribute(x) 54 #else 55 # define PORTABLE_HAS_ATTRIBUTE(x) 0 56 #endif 57 58 59 /* https://en.cppreference.com/w/c/language/attributes/fallthrough */ 60 #if PORTABLE_HAS_C_ATTRIBUTE(__fallthrough__) 61 # define pattribute_fallthrough [[__fallthrough__]] 62 #elif PORTABLE_HAS_ATTRIBUTE(__fallthrough__) 63 # define pattribute_fallthrough __attribute__((__fallthrough__)) 64 #else 65 # define pattribute_fallthrough ((void)0) 66 #endif 67 68 69 #define pattribute(x) pattribute_##x 70 71 #if PORTABLE_EXPOSE_ATTRIBUTES 72 73 #ifndef fallthrough 74 # define fallthrough pattribute(fallthrough) 75 #endif 76 77 #endif 78 79 80 #ifdef __cplusplus 81 } 82 #endif 83 84 #endif /* PATTRIBUTES_H */