]> git.ozlabs.org Git - ccan/blobdiff - ccan/compiler/compiler.h
ccan/compiler: add cpu_supports() macro.
[ccan] / ccan / compiler / compiler.h
index 49088ac799e6f0ba9772afde55d8a9fdd421f71d..1bbb3b8b61c6cb4a0fd44ab39e5bf7505eaa91bd 100644 (file)
+/* 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_ATTRIBUTE - a function is unlikely to be called.
+ * 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_ATTRIBUTE moan(const char *reason)
+ * static void COLD moan(const char *reason)
  * {
  *     fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
  * }
  */
-#define COLD_ATTRIBUTE __attribute__((cold))
+#define COLD __attribute__((__cold__))
 #else
-#define COLD_ATTRIBUTE
+#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_ATTRIBUTE - a function takes printf-style arguments
+ * 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_ATTRIBUTE(2,3) my_printf(const char *prefix,
- *                                     const char *fmt, ...);
+ * void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...);
  */
-#define PRINTF_ATTRIBUTE(nfmt, narg) \
+#define PRINTF_FMT(nfmt, narg) \
        __attribute__((format(__printf__, nfmt, narg)))
 #else
-#define PRINTF_ATTRIBUTE(nfmt, narg)
+#define PRINTF_FMT(nfmt, narg)
+#endif
 #endif
 
+#ifndef CONST_FUNCTION
 #if HAVE_ATTRIBUTE_CONST
 /**
- * IDEMPOTENT_ATTRIBUTE - a function's return depends only on its argument
+ * 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 IDEMPOTENT_ATTRIBUTE __attribute__((const))
+#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 IDEMPOTENT_ATTRIBUTE
+#define PURE_FUNCTION
+#endif
+#endif
 #endif
 
 #if HAVE_ATTRIBUTE_UNUSED
+#ifndef UNNEEDED
 /**
- * UNNEEDED_ATTRIBUTE - a parameter/variable/function may not be needed
+ * UNNEEDED - a variable/function may not be needed
  *
- * This suppresses warnings about unused variables or parameters, but tells
+ * 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_ATTRIBUTE int counter;
+ * static UNNEEDED int counter;
  *
  * // With some preprocessor options, this is unnecessary.
- * static UNNEEDED_ATTRIBUTE void add_to_counter(int add)
+ * static UNNEEDED void add_to_counter(int add)
  * {
  *     counter += add;
  * }
  */
-#define UNNEEDED_ATTRIBUTE __attribute__((unused))
+#define UNNEEDED __attribute__((__unused__))
+#endif
 
+#ifndef NEEDED
 #if HAVE_ATTRIBUTE_USED
 /**
- * NEEDED_ATTRIBUTE - a parameter/variable/function is needed
+ * NEEDED - a variable/function is needed
  *
- * This suppresses warnings about unused variables or parameters, but tells
+ * 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 UNNEEDED_ATTRIBUTE int counter;
- *     static UNNEEDED_ATTRIBUTE void dump_counter(void)
+ *     static NEEDED int counter;
+ *     static NEEDED void dump_counter(void)
  *     {
  *             printf("Counter is %i\n", counter);
  *     }
  */
-#define NEEDED_ATTRIBUTE __attribute__((used))
+#define NEEDED __attribute__((__used__))
 #else
 /* Before used, unused functions and vars were always emitted. */
-#define NEEDED_ATTRIBUTE __attribute__((unused))
+#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
-#define UNNEEDED_ATTRIBUTE
-#define NEEDED_ATTRIBUTE
+#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?
  *     const char *greek_name(enum greek greek);
  *
  *     // Inline version.
- *     static inline char *_greek_name(enum greek greek)
+ *     static inline const char *_greek_name(enum greek greek)
  *     {
  *             switch (greek) {
  *             case ALPHA: return "alpha";
 /* 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.
  *     return realloc(buf, (*size) *= 2);
  * }
  */
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#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_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 */