damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

compiler.h (8242B)


      1 /* CC0 (Public domain) - see LICENSE file for details */
      2 #ifndef CCAN_COMPILER_H
      3 #define CCAN_COMPILER_H
      4 #include "config.h"
      5 
      6 #ifndef COLD
      7 #if HAVE_ATTRIBUTE_COLD
      8 /**
      9  * COLD - a function is unlikely to be called.
     10  *
     11  * Used to mark an unlikely code path and optimize appropriately.
     12  * It is usually used on logging or error routines.
     13  *
     14  * Example:
     15  * static void COLD moan(const char *reason)
     16  * {
     17  *    fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
     18  * }
     19  */
     20 #define COLD __attribute__((__cold__))
     21 #else
     22 #define COLD
     23 #endif
     24 #endif
     25 
     26 #ifndef NORETURN
     27 #if HAVE_ATTRIBUTE_NORETURN
     28 /**
     29  * NORETURN - a function does not return
     30  *
     31  * Used to mark a function which exits; useful for suppressing warnings.
     32  *
     33  * Example:
     34  * static void NORETURN fail(const char *reason)
     35  * {
     36  *    fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
     37  *    exit(1);
     38  * }
     39  */
     40 #define NORETURN __attribute__((__noreturn__))
     41 #else
     42 #define NORETURN
     43 #endif
     44 #endif
     45 
     46 #ifndef PRINTF_FMT
     47 #if HAVE_ATTRIBUTE_PRINTF
     48 /**
     49  * PRINTF_FMT - a function takes printf-style arguments
     50  * @nfmt: the 1-based number of the function's format argument.
     51  * @narg: the 1-based number of the function's first variable argument.
     52  *
     53  * This allows the compiler to check your parameters as it does for printf().
     54  *
     55  * Example:
     56  * void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...);
     57  */
     58 #define PRINTF_FMT(nfmt, narg) \
     59     __attribute__((format(__printf__, nfmt, narg)))
     60 #else
     61 #define PRINTF_FMT(nfmt, narg)
     62 #endif
     63 #endif
     64 
     65 #ifndef CONST_FUNCTION
     66 #if HAVE_ATTRIBUTE_CONST
     67 /**
     68  * CONST_FUNCTION - a function's return depends only on its argument
     69  *
     70  * This allows the compiler to assume that the function will return the exact
     71  * same value for the exact same arguments.  This implies that the function
     72  * must not use global variables, or dereference pointer arguments.
     73  */
     74 #define CONST_FUNCTION __attribute__((__const__))
     75 #else
     76 #define CONST_FUNCTION
     77 #endif
     78 
     79 #ifndef PURE_FUNCTION
     80 #if HAVE_ATTRIBUTE_PURE
     81 /**
     82  * PURE_FUNCTION - a function is pure
     83  *
     84  * A pure function is one that has no side effects other than it's return value
     85  * and uses no inputs other than it's arguments and global variables.
     86  */
     87 #define PURE_FUNCTION __attribute__((__pure__))
     88 #else
     89 #define PURE_FUNCTION
     90 #endif
     91 #endif
     92 #endif
     93 
     94 #if HAVE_ATTRIBUTE_UNUSED
     95 #ifndef UNNEEDED
     96 /**
     97  * UNNEEDED - a variable/function may not be needed
     98  *
     99  * This suppresses warnings about unused variables or functions, but tells
    100  * the compiler that if it is unused it need not emit it into the source code.
    101  *
    102  * Example:
    103  * // With some preprocessor options, this is unnecessary.
    104  * static UNNEEDED int counter;
    105  *
    106  * // With some preprocessor options, this is unnecessary.
    107  * static UNNEEDED void add_to_counter(int add)
    108  * {
    109  *    counter += add;
    110  * }
    111  */
    112 #define UNNEEDED __attribute__((__unused__))
    113 #endif
    114 
    115 #ifndef NEEDED
    116 #if HAVE_ATTRIBUTE_USED
    117 /**
    118  * NEEDED - a variable/function is needed
    119  *
    120  * This suppresses warnings about unused variables or functions, but tells
    121  * the compiler that it must exist even if it (seems) unused.
    122  *
    123  * Example:
    124  *    // Even if this is unused, these are vital for debugging.
    125  *    static NEEDED int counter;
    126  *    static NEEDED void dump_counter(void)
    127  *    {
    128  *        printf("Counter is %i\n", counter);
    129  *    }
    130  */
    131 #define NEEDED __attribute__((__used__))
    132 #else
    133 /* Before used, unused functions and vars were always emitted. */
    134 #define NEEDED __attribute__((__unused__))
    135 #endif
    136 #endif
    137 
    138 #ifndef UNUSED
    139 /**
    140  * UNUSED - a parameter is unused
    141  *
    142  * Some compilers (eg. gcc with -W or -Wunused) warn about unused
    143  * function parameters.  This suppresses such warnings and indicates
    144  * to the reader that it's deliberate.
    145  *
    146  * Example:
    147  *    // This is used as a callback, so needs to have this prototype.
    148  *    static int some_callback(void *unused UNUSED)
    149  *    {
    150  *        return 0;
    151  *    }
    152  */
    153 #define UNUSED __attribute__((__unused__))
    154 #endif
    155 #else
    156 #ifndef UNNEEDED
    157 #define UNNEEDED
    158 #endif
    159 #ifndef NEEDED
    160 #define NEEDED
    161 #endif
    162 #ifndef UNUSED
    163 #define UNUSED
    164 #endif
    165 #endif
    166 
    167 #ifndef IS_COMPILE_CONSTANT
    168 #if HAVE_BUILTIN_CONSTANT_P
    169 /**
    170  * IS_COMPILE_CONSTANT - does the compiler know the value of this expression?
    171  * @expr: the expression to evaluate
    172  *
    173  * When an expression manipulation is complicated, it is usually better to
    174  * implement it in a function.  However, if the expression being manipulated is
    175  * known at compile time, it is better to have the compiler see the entire
    176  * expression so it can simply substitute the result.
    177  *
    178  * This can be done using the IS_COMPILE_CONSTANT() macro.
    179  *
    180  * Example:
    181  *    enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON };
    182  *
    183  *    // Out-of-line version.
    184  *    const char *greek_name(enum greek greek);
    185  *
    186  *    // Inline version.
    187  *    static inline const char *_greek_name(enum greek greek)
    188  *    {
    189  *        switch (greek) {
    190  *        case ALPHA: return "alpha";
    191  *        case BETA: return "beta";
    192  *        case GAMMA: return "gamma";
    193  *        case DELTA: return "delta";
    194  *        case EPSILON: return "epsilon";
    195  *        default: return "**INVALID**";
    196  *        }
    197  *    }
    198  *
    199  *    // Use inline if compiler knows answer.  Otherwise call function
    200  *    // to avoid copies of the same code everywhere.
    201  *    #define greek_name(g)                        \
    202  *         (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g))
    203  */
    204 #define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr)
    205 #else
    206 /* If we don't know, assume it's not. */
    207 #define IS_COMPILE_CONSTANT(expr) 0
    208 #endif
    209 #endif
    210 
    211 #ifndef WARN_UNUSED_RESULT
    212 #if HAVE_WARN_UNUSED_RESULT
    213 /**
    214  * WARN_UNUSED_RESULT - warn if a function return value is unused.
    215  *
    216  * Used to mark a function where it is extremely unlikely that the caller
    217  * can ignore the result, eg realloc().
    218  *
    219  * Example:
    220  * // buf param may be freed by this; need return value!
    221  * static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size)
    222  * {
    223  *    return realloc(buf, (*size) *= 2);
    224  * }
    225  */
    226 #define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
    227 #else
    228 #define WARN_UNUSED_RESULT
    229 #endif
    230 #endif
    231 
    232 
    233 #if HAVE_ATTRIBUTE_DEPRECATED
    234 /**
    235  * WARN_DEPRECATED - warn that a function/type/variable is deprecated when used.
    236  *
    237  * Used to mark a function, type or variable should not be used.
    238  *
    239  * Example:
    240  * WARN_DEPRECATED char *oldfunc(char *buf);
    241  */
    242 #define WARN_DEPRECATED __attribute__((__deprecated__))
    243 #else
    244 #define WARN_DEPRECATED
    245 #endif
    246 
    247 
    248 #if HAVE_ATTRIBUTE_NONNULL
    249 /**
    250  * NO_NULL_ARGS - specify that no arguments to this function can be NULL.
    251  *
    252  * The compiler will warn if any pointer args are NULL.
    253  *
    254  * Example:
    255  * NO_NULL_ARGS char *my_copy(char *buf);
    256  */
    257 #define NO_NULL_ARGS __attribute__((__nonnull__))
    258 
    259 /**
    260  * NON_NULL_ARGS - specify that some arguments to this function can't be NULL.
    261  * @...: 1-based argument numbers for which args can't be NULL.
    262  *
    263  * The compiler will warn if any of the specified pointer args are NULL.
    264  *
    265  * Example:
    266  * char *my_copy2(char *buf, char *maybenull) NON_NULL_ARGS(1);
    267  */
    268 #define NON_NULL_ARGS(...) __attribute__((__nonnull__(__VA_ARGS__)))
    269 #else
    270 #define NO_NULL_ARGS
    271 #define NON_NULL_ARGS(...)
    272 #endif
    273 
    274 #if HAVE_ATTRIBUTE_RETURNS_NONNULL
    275 /**
    276  * RETURNS_NONNULL - specify that this function cannot return NULL.
    277  *
    278  * Mainly an optimization opportunity, but can also suppress warnings.
    279  *
    280  * Example:
    281  * RETURNS_NONNULL char *my_copy(char *buf);
    282  */
    283 #define RETURNS_NONNULL __attribute__((__returns_nonnull__))
    284 #else
    285 #define RETURNS_NONNULL
    286 #endif
    287 
    288 #if HAVE_ATTRIBUTE_SENTINEL
    289 /**
    290  * LAST_ARG_NULL - specify the last argument of a variadic function must be NULL.
    291  *
    292  * The compiler will warn if the last argument isn't NULL.
    293  *
    294  * Example:
    295  * char *join_string(char *buf, ...) LAST_ARG_NULL;
    296  */
    297 #define LAST_ARG_NULL __attribute__((__sentinel__))
    298 #else
    299 #define LAST_ARG_NULL
    300 #endif
    301 
    302 #if HAVE_BUILTIN_CPU_SUPPORTS
    303 /**
    304  * cpu_supports - test if current CPU supports the named feature.
    305  *
    306  * This takes a literal string, and currently only works on glibc platforms.
    307  *
    308  * Example:
    309  * if (cpu_supports("mmx"))
    310  *    printf("MMX support engaged!\n");
    311  */
    312 #define cpu_supports(x) __builtin_cpu_supports(x)
    313 #else
    314 #define cpu_supports(x) 0
    315 #endif /* HAVE_BUILTIN_CPU_SUPPORTS */
    316 
    317 #endif /* CCAN_COMPILER_H */