tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

compat_compiler.h (8807B)


      1 /* Copyright (c) 2003-2004, Roger Dingledine
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 /**
      7 * \file compat_compiler.h
      8 * \brief Utility macros to handle different features and behavior in different
      9 *    compilers.
     10 **/
     11 
     12 #ifndef TOR_COMPAT_COMPILER_H
     13 #define TOR_COMPAT_COMPILER_H
     14 
     15 #include "orconfig.h"
     16 #include <inttypes.h>
     17 
     18 #if defined(__MINGW32__) || defined(__MINGW64__)
     19 #define MINGW_ANY
     20 #endif
     21 
     22 #ifdef MINGW_ANY
     23 /* We need this for __MINGW_PRINTF_FORMAT, alas. */
     24 #include <stdio.h>
     25 #endif
     26 
     27 #if defined(__has_feature)
     28 #  if __has_feature(address_sanitizer)
     29 /* Some of the fancy glibc strcmp() macros include references to memory that
     30 * clang rejects because it is off the end of a less-than-3. Clang hates this,
     31 * even though those references never actually happen. */
     32 #    undef strcmp
     33 #endif /* __has_feature(address_sanitizer) */
     34 #endif /* defined(__has_feature) */
     35 
     36 #ifndef NULL_REP_IS_ZERO_BYTES
     37 #error "Your platform does not represent NULL as zero. We can't cope."
     38 #endif
     39 
     40 #ifndef DOUBLE_0_REP_IS_ZERO_BYTES
     41 #error "Your platform does not represent 0.0 as zeros. We can't cope."
     42 #endif
     43 
     44 #if 'a'!=97 || 'z'!=122 || 'A'!=65 || ' '!=32
     45 #error "It seems that you encode characters in something other than ASCII."
     46 #endif
     47 
     48 /* Use the right magic attribute on mingw, which might be printf, gnu_printf,
     49 * or ms_printf, depending on how we're set up to build.
     50 */
     51 #ifdef __MINGW_PRINTF_FORMAT
     52 #define PRINTF_FORMAT_ATTR __MINGW_PRINTF_FORMAT
     53 #else
     54 #define PRINTF_FORMAT_ATTR printf
     55 #endif
     56 #ifdef __MINGW_SCANF_FORMAT
     57 #define SCANF_FORMAT_ATTR __MINGW_SCANF_FORMAT
     58 #else
     59 #define SCANF_FORMAT_ATTR scanf
     60 #endif
     61 
     62 /* GCC can check printf and scanf types on arbitrary functions. */
     63 #ifdef __GNUC__
     64 #define CHECK_PRINTF(formatIdx, firstArg) \
     65   __attribute__ ((format(PRINTF_FORMAT_ATTR, formatIdx, firstArg)))
     66 #else
     67 #define CHECK_PRINTF(formatIdx, firstArg)
     68 #endif /* defined(__GNUC__) */
     69 #ifdef __GNUC__
     70 #define CHECK_SCANF(formatIdx, firstArg) \
     71   __attribute__ ((format(SCANF_FORMAT_ATTR, formatIdx, firstArg)))
     72 #else
     73 #define CHECK_SCANF(formatIdx, firstArg)
     74 #endif /* defined(__GNUC__) */
     75 
     76 #if defined(HAVE_ATTR_FALLTHROUGH)
     77 #define FALLTHROUGH __attribute__((fallthrough))
     78 #else
     79 #define FALLTHROUGH
     80 #endif
     81 
     82 #if defined(HAVE_ATTR_NONSTRING)
     83 #define NONSTRING __attribute__((nonstring))
     84 #else
     85 #define NONSTRING
     86 #endif
     87 
     88 /* What GCC do we have? */
     89 #ifdef __GNUC__
     90 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
     91 #else
     92 #define GCC_VERSION 0
     93 #endif
     94 
     95 /* Temporarily enable and disable warnings. */
     96 #ifdef __GNUC__
     97 /* Support for macro-generated pragmas (c99) */
     98 #  define PRAGMA_(x) _Pragma (#x)
     99 #  ifdef __clang__
    100 #    define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(clang diagnostic x)
    101 #  else
    102 #    define PRAGMA_DIAGNOSTIC_(x) PRAGMA_(GCC diagnostic x)
    103 #  endif
    104 #  if defined(__clang__) || GCC_VERSION >= 406
    105 /* we have push/pop support */
    106 #    define DISABLE_GCC_WARNING(warningopt) \
    107          PRAGMA_DIAGNOSTIC_(push) \
    108          PRAGMA_DIAGNOSTIC_(ignored warningopt)
    109 #    define ENABLE_GCC_WARNING(warningopt) \
    110          PRAGMA_DIAGNOSTIC_(pop)
    111 #else /* !(defined(__clang__) || GCC_VERSION >= 406) */
    112 /* older version of gcc: no push/pop support. */
    113 #    define DISABLE_GCC_WARNING(warningopt) \
    114         PRAGMA_DIAGNOSTIC_(ignored warningopt)
    115 #    define ENABLE_GCC_WARNING(warningopt) \
    116         PRAGMA_DIAGNOSTIC_(warning warningopt)
    117 #endif /* defined(__clang__) || GCC_VERSION >= 406 */
    118 #else /* !defined(__GNUC__) */
    119 /* not gcc at all */
    120 # define DISABLE_GCC_WARNING(warning)
    121 # define ENABLE_GCC_WARNING(warning)
    122 #endif /* defined(__GNUC__) */
    123 
    124 /* inline is __inline on windows. */
    125 #ifdef _WIN32
    126 #define inline __inline
    127 #endif
    128 
    129 /* Try to get a reasonable __func__ substitute in place. */
    130 #if defined(_MSC_VER)
    131 
    132 #define __func__ __FUNCTION__
    133 
    134 #else
    135 /* For platforms where autoconf works, make sure __func__ is defined
    136 * sanely. */
    137 #ifndef HAVE_MACRO__func__
    138 #ifdef HAVE_MACRO__FUNCTION__
    139 #define __func__ __FUNCTION__
    140 #elif HAVE_MACRO__FUNC__
    141 #define __func__ __FUNC__
    142 #else
    143 #define __func__ "???"
    144 #endif /* defined(HAVE_MACRO__FUNCTION__) || ... */
    145 #endif /* !defined(HAVE_MACRO__func__) */
    146 #endif /* defined(_MSC_VER) */
    147 
    148 #ifdef ENUM_VALS_ARE_SIGNED
    149 #define ENUM_BF(t) unsigned
    150 #else
    151 /** Wrapper for having a bitfield of an enumerated type. Where possible, we
    152 * just use the enumerated type (so the compiler can help us and notice
    153 * problems), but if enumerated types are unsigned, we must use unsigned,
    154 * so that the loss of precision doesn't make large values negative. */
    155 #define ENUM_BF(t) t
    156 #endif /* defined(ENUM_VALS_ARE_SIGNED) */
    157 
    158 /* GCC has several useful attributes. */
    159 #if defined(__GNUC__) && __GNUC__ >= 3
    160 #define ATTR_NORETURN __attribute__((noreturn))
    161 #define ATTR_CONST __attribute__((const))
    162 #define ATTR_MALLOC __attribute__((malloc))
    163 #define ATTR_NORETURN __attribute__((noreturn))
    164 #define ATTR_WUR __attribute__((warn_unused_result))
    165 #define ATTR_UNUSED __attribute__ ((unused))
    166 
    167 /** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
    168 * of <b>exp</b> will probably be true.
    169 *
    170 * In other words, "if (PREDICT_LIKELY(foo))" is the same as "if (foo)",
    171 * except that it tells the compiler that the branch will be taken most of the
    172 * time.  This can generate slightly better code with some CPUs.
    173 */
    174 #define PREDICT_LIKELY(exp) __builtin_expect(!!(exp), 1)
    175 /** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
    176 * of <b>exp</b> will probably be false.
    177 *
    178 * In other words, "if (PREDICT_UNLIKELY(foo))" is the same as "if (foo)",
    179 * except that it tells the compiler that the branch will usually not be
    180 * taken.  This can generate slightly better code with some CPUs.
    181 */
    182 #define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0)
    183 #else /* !(defined(__GNUC__) && __GNUC__ >= 3) */
    184 #define ATTR_NORETURN
    185 #define ATTR_CONST
    186 #define ATTR_MALLOC
    187 #define ATTR_NORETURN
    188 #define ATTR_UNUSED
    189 #define ATTR_WUR
    190 #define PREDICT_LIKELY(exp) (exp)
    191 #define PREDICT_UNLIKELY(exp) (exp)
    192 #endif /* defined(__GNUC__) && __GNUC__ >= 3 */
    193 
    194 /** Expands to a syntactically valid empty statement.  */
    195 #define STMT_NIL (void)0
    196 
    197 /** Expands to a syntactically valid empty statement, explicitly (void)ing its
    198 * argument. */
    199 #define STMT_VOID(a) while (0) { (void)(a); }
    200 
    201 #ifdef __GNUC__
    202 /** STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that
    203 * the macro can be used as if it were a single C statement. */
    204 #define STMT_BEGIN (void) ({
    205 #define STMT_END })
    206 #elif defined(sun) || defined(__sun__)
    207 #define STMT_BEGIN if (1) {
    208 #define STMT_END } else STMT_NIL
    209 #else
    210 #define STMT_BEGIN do {
    211 #define STMT_END } while (0)
    212 #endif /* defined(__GNUC__) || ... */
    213 
    214 /* Some tools (like coccinelle) don't like to see operators as macro
    215 * arguments. */
    216 #define OP_LT <
    217 #define OP_GT >
    218 #define OP_GE >=
    219 #define OP_LE <=
    220 #define OP_EQ ==
    221 #define OP_NE !=
    222 
    223 /** Macro: yield a pointer to the field at position <b>off</b> within the
    224 * structure <b>st</b>.  Example:
    225 * <pre>
    226 *   struct a_t { int foo; int bar; } x;
    227 *   ptrdiff_t bar_offset = offsetof(struct a_t, bar);
    228 *   int *bar_p = STRUCT_VAR_P(&x, bar_offset);
    229 *   *bar_p = 3;
    230 * </pre>
    231 */
    232 #define STRUCT_VAR_P(st, off) ((void*) ( ((char*)(st)) + (off) ) )
    233 
    234 /** Macro: yield a pointer to an enclosing structure given a pointer to
    235 * a substructure at offset <b>off</b>. Example:
    236 * <pre>
    237 *   struct base_t { ... };
    238 *   struct subtype_t { int x; struct base_t b; } x;
    239 *   struct base_t *bp = &x.base;
    240 *   struct *sp = SUBTYPE_P(bp, struct subtype_t, b);
    241 * </pre>
    242 */
    243 #define SUBTYPE_P(p, subtype, basemember) \
    244  ((void*) ( ((char*)(p)) - offsetof(subtype, basemember) ))
    245 
    246 /** Macro: Yields the number of elements in array x. */
    247 #define ARRAY_LENGTH(x) ((sizeof(x)) / sizeof(x[0]))
    248 
    249 /**
    250 * "Eat" a semicolon that somebody puts at the end of a top-level macro.
    251 *
    252 * Frequently, we want to declare a macro that people will use at file scope,
    253 * and we want to allow people to put a semicolon after the macro.
    254 *
    255 * This declaration of a struct can be repeated any number of times, and takes
    256 * a trailing semicolon afterwards.
    257 **/
    258 #define EAT_SEMICOLON                                   \
    259  struct dummy_semicolon_eater__
    260 
    261 /**
    262 * Tell our static analysis tool to believe that (clang's scan-build or
    263 * coverity scan) that an expression might be true.  We use this to suppress
    264 * dead-code warnings.
    265 **/
    266 #if defined(__COVERITY__) || defined(__clang_analyzer__)
    267 /* By calling getenv, we force the analyzer not to conclude that 'expr' is
    268 * false. */
    269 #define POSSIBLE(expr) ((expr) || getenv("STATIC_ANALYZER_DEADCODE_DUMMY_"))
    270 #else
    271 #define POSSIBLE(expr) (expr)
    272 #endif /* defined(__COVERITY__) || defined(__clang_analyzer__) */
    273 
    274 #endif /* !defined(TOR_COMPAT_COMPILER_H) */