mirror of https://github.com/lukechilds/damus.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
8.0 KiB
317 lines
8.0 KiB
/* CC0 (Public domain) - see LICENSE file for details */
|
|
#ifndef CCAN_COMPILER_H
|
|
#define CCAN_COMPILER_H
|
|
#include "config.h"
|
|
|
|
#ifndef COLD
|
|
#if HAVE_ATTRIBUTE_COLD
|
|
/**
|
|
* COLD - a function is unlikely to be called.
|
|
*
|
|
* Used to mark an unlikely code path and optimize appropriately.
|
|
* It is usually used on logging or error routines.
|
|
*
|
|
* Example:
|
|
* static void COLD moan(const char *reason)
|
|
* {
|
|
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
|
|
* }
|
|
*/
|
|
#define COLD __attribute__((__cold__))
|
|
#else
|
|
#define COLD
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef NORETURN
|
|
#if HAVE_ATTRIBUTE_NORETURN
|
|
/**
|
|
* NORETURN - a function does not return
|
|
*
|
|
* Used to mark a function which exits; useful for suppressing warnings.
|
|
*
|
|
* Example:
|
|
* static void NORETURN fail(const char *reason)
|
|
* {
|
|
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
|
|
* exit(1);
|
|
* }
|
|
*/
|
|
#define NORETURN __attribute__((__noreturn__))
|
|
#else
|
|
#define NORETURN
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef PRINTF_FMT
|
|
#if HAVE_ATTRIBUTE_PRINTF
|
|
/**
|
|
* PRINTF_FMT - a function takes printf-style arguments
|
|
* @nfmt: the 1-based number of the function's format argument.
|
|
* @narg: the 1-based number of the function's first variable argument.
|
|
*
|
|
* This allows the compiler to check your parameters as it does for printf().
|
|
*
|
|
* Example:
|
|
* void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...);
|
|
*/
|
|
#define PRINTF_FMT(nfmt, narg) \
|
|
__attribute__((format(__printf__, nfmt, narg)))
|
|
#else
|
|
#define PRINTF_FMT(nfmt, narg)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef CONST_FUNCTION
|
|
#if HAVE_ATTRIBUTE_CONST
|
|
/**
|
|
* CONST_FUNCTION - a function's return depends only on its argument
|
|
*
|
|
* This allows the compiler to assume that the function will return the exact
|
|
* same value for the exact same arguments. This implies that the function
|
|
* must not use global variables, or dereference pointer arguments.
|
|
*/
|
|
#define CONST_FUNCTION __attribute__((__const__))
|
|
#else
|
|
#define CONST_FUNCTION
|
|
#endif
|
|
|
|
#ifndef PURE_FUNCTION
|
|
#if HAVE_ATTRIBUTE_PURE
|
|
/**
|
|
* PURE_FUNCTION - a function is pure
|
|
*
|
|
* A pure function is one that has no side effects other than it's return value
|
|
* and uses no inputs other than it's arguments and global variables.
|
|
*/
|
|
#define PURE_FUNCTION __attribute__((__pure__))
|
|
#else
|
|
#define PURE_FUNCTION
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#if HAVE_ATTRIBUTE_UNUSED
|
|
#ifndef UNNEEDED
|
|
/**
|
|
* UNNEEDED - a variable/function may not be needed
|
|
*
|
|
* This suppresses warnings about unused variables or functions, but tells
|
|
* the compiler that if it is unused it need not emit it into the source code.
|
|
*
|
|
* Example:
|
|
* // With some preprocessor options, this is unnecessary.
|
|
* static UNNEEDED int counter;
|
|
*
|
|
* // With some preprocessor options, this is unnecessary.
|
|
* static UNNEEDED void add_to_counter(int add)
|
|
* {
|
|
* counter += add;
|
|
* }
|
|
*/
|
|
#define UNNEEDED __attribute__((__unused__))
|
|
#endif
|
|
|
|
#ifndef NEEDED
|
|
#if HAVE_ATTRIBUTE_USED
|
|
/**
|
|
* NEEDED - a variable/function is needed
|
|
*
|
|
* This suppresses warnings about unused variables or functions, but tells
|
|
* the compiler that it must exist even if it (seems) unused.
|
|
*
|
|
* Example:
|
|
* // Even if this is unused, these are vital for debugging.
|
|
* static NEEDED int counter;
|
|
* static NEEDED void dump_counter(void)
|
|
* {
|
|
* printf("Counter is %i\n", counter);
|
|
* }
|
|
*/
|
|
#define NEEDED __attribute__((__used__))
|
|
#else
|
|
/* Before used, unused functions and vars were always emitted. */
|
|
#define NEEDED __attribute__((__unused__))
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef UNUSED
|
|
/**
|
|
* UNUSED - a parameter is unused
|
|
*
|
|
* Some compilers (eg. gcc with -W or -Wunused) warn about unused
|
|
* function parameters. This suppresses such warnings and indicates
|
|
* to the reader that it's deliberate.
|
|
*
|
|
* Example:
|
|
* // This is used as a callback, so needs to have this prototype.
|
|
* static int some_callback(void *unused UNUSED)
|
|
* {
|
|
* return 0;
|
|
* }
|
|
*/
|
|
#define UNUSED __attribute__((__unused__))
|
|
#endif
|
|
#else
|
|
#ifndef UNNEEDED
|
|
#define UNNEEDED
|
|
#endif
|
|
#ifndef NEEDED
|
|
#define NEEDED
|
|
#endif
|
|
#ifndef UNUSED
|
|
#define UNUSED
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef IS_COMPILE_CONSTANT
|
|
#if HAVE_BUILTIN_CONSTANT_P
|
|
/**
|
|
* IS_COMPILE_CONSTANT - does the compiler know the value of this expression?
|
|
* @expr: the expression to evaluate
|
|
*
|
|
* When an expression manipulation is complicated, it is usually better to
|
|
* implement it in a function. However, if the expression being manipulated is
|
|
* known at compile time, it is better to have the compiler see the entire
|
|
* expression so it can simply substitute the result.
|
|
*
|
|
* This can be done using the IS_COMPILE_CONSTANT() macro.
|
|
*
|
|
* Example:
|
|
* enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON };
|
|
*
|
|
* // Out-of-line version.
|
|
* const char *greek_name(enum greek greek);
|
|
*
|
|
* // Inline version.
|
|
* static inline const char *_greek_name(enum greek greek)
|
|
* {
|
|
* switch (greek) {
|
|
* case ALPHA: return "alpha";
|
|
* case BETA: return "beta";
|
|
* case GAMMA: return "gamma";
|
|
* case DELTA: return "delta";
|
|
* case EPSILON: return "epsilon";
|
|
* default: return "**INVALID**";
|
|
* }
|
|
* }
|
|
*
|
|
* // Use inline if compiler knows answer. Otherwise call function
|
|
* // to avoid copies of the same code everywhere.
|
|
* #define greek_name(g) \
|
|
* (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g))
|
|
*/
|
|
#define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr)
|
|
#else
|
|
/* If we don't know, assume it's not. */
|
|
#define IS_COMPILE_CONSTANT(expr) 0
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef WARN_UNUSED_RESULT
|
|
#if HAVE_WARN_UNUSED_RESULT
|
|
/**
|
|
* WARN_UNUSED_RESULT - warn if a function return value is unused.
|
|
*
|
|
* Used to mark a function where it is extremely unlikely that the caller
|
|
* can ignore the result, eg realloc().
|
|
*
|
|
* Example:
|
|
* // buf param may be freed by this; need return value!
|
|
* static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size)
|
|
* {
|
|
* return realloc(buf, (*size) *= 2);
|
|
* }
|
|
*/
|
|
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
|
|
#else
|
|
#define WARN_UNUSED_RESULT
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if HAVE_ATTRIBUTE_DEPRECATED
|
|
/**
|
|
* WARN_DEPRECATED - warn that a function/type/variable is deprecated when used.
|
|
*
|
|
* Used to mark a function, type or variable should not be used.
|
|
*
|
|
* Example:
|
|
* WARN_DEPRECATED char *oldfunc(char *buf);
|
|
*/
|
|
#define WARN_DEPRECATED __attribute__((__deprecated__))
|
|
#else
|
|
#define WARN_DEPRECATED
|
|
#endif
|
|
|
|
|
|
#if HAVE_ATTRIBUTE_NONNULL
|
|
/**
|
|
* NO_NULL_ARGS - specify that no arguments to this function can be NULL.
|
|
*
|
|
* The compiler will warn if any pointer args are NULL.
|
|
*
|
|
* Example:
|
|
* NO_NULL_ARGS char *my_copy(char *buf);
|
|
*/
|
|
#define NO_NULL_ARGS __attribute__((__nonnull__))
|
|
|
|
/**
|
|
* NON_NULL_ARGS - specify that some arguments to this function can't be NULL.
|
|
* @...: 1-based argument numbers for which args can't be NULL.
|
|
*
|
|
* The compiler will warn if any of the specified pointer args are NULL.
|
|
*
|
|
* Example:
|
|
* char *my_copy2(char *buf, char *maybenull) NON_NULL_ARGS(1);
|
|
*/
|
|
#define NON_NULL_ARGS(...) __attribute__((__nonnull__(__VA_ARGS__)))
|
|
#else
|
|
#define NO_NULL_ARGS
|
|
#define NON_NULL_ARGS(...)
|
|
#endif
|
|
|
|
#if HAVE_ATTRIBUTE_RETURNS_NONNULL
|
|
/**
|
|
* RETURNS_NONNULL - specify that this function cannot return NULL.
|
|
*
|
|
* Mainly an optimization opportunity, but can also suppress warnings.
|
|
*
|
|
* Example:
|
|
* RETURNS_NONNULL char *my_copy(char *buf);
|
|
*/
|
|
#define RETURNS_NONNULL __attribute__((__returns_nonnull__))
|
|
#else
|
|
#define RETURNS_NONNULL
|
|
#endif
|
|
|
|
#if HAVE_ATTRIBUTE_SENTINEL
|
|
/**
|
|
* LAST_ARG_NULL - specify the last argument of a variadic function must be NULL.
|
|
*
|
|
* The compiler will warn if the last argument isn't NULL.
|
|
*
|
|
* Example:
|
|
* char *join_string(char *buf, ...) LAST_ARG_NULL;
|
|
*/
|
|
#define LAST_ARG_NULL __attribute__((__sentinel__))
|
|
#else
|
|
#define LAST_ARG_NULL
|
|
#endif
|
|
|
|
#if HAVE_BUILTIN_CPU_SUPPORTS
|
|
/**
|
|
* cpu_supports - test if current CPU supports the named feature.
|
|
*
|
|
* This takes a literal string, and currently only works on glibc platforms.
|
|
*
|
|
* Example:
|
|
* if (cpu_supports("mmx"))
|
|
* printf("MMX support engaged!\n");
|
|
*/
|
|
#define cpu_supports(x) __builtin_cpu_supports(x)
|
|
#else
|
|
#define cpu_supports(x) 0
|
|
#endif /* HAVE_BUILTIN_CPU_SUPPORTS */
|
|
|
|
#endif /* CCAN_COMPILER_H */
|
|
|