|
181 | 181 | #define ABSL_PREDICT_TRUE(x) (x) |
182 | 182 | #endif |
183 | 183 |
|
| 184 | +// `ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL()` aborts the program in the fastest |
| 185 | +// possible way, with no attempt at logging. One use is to implement hardening |
| 186 | +// aborts with ABSL_OPTION_HARDENED. Since this is an internal symbol, it |
| 187 | +// should not be used directly outside of Abseil. |
| 188 | +#if ABSL_HAVE_BUILTIN(__builtin_trap) || \ |
| 189 | + (defined(__GNUC__) && !defined(__clang__)) |
| 190 | +#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() __builtin_trap() |
| 191 | +#else |
| 192 | +#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() abort() |
| 193 | +#endif |
| 194 | + |
| 195 | +// `ABSL_INTERNAL_UNREACHABLE_IMPL()` is the platform specific directive to |
| 196 | +// indicate that a statement is unreachable, and to allow the compiler to |
| 197 | +// optimize accordingly. Clients should use `ABSL_UNREACHABLE()`, which is |
| 198 | +// defined below. |
| 199 | +#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L |
| 200 | +#define ABSL_INTERNAL_UNREACHABLE_IMPL() std::unreachable() |
| 201 | +#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) |
| 202 | +#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_unreachable() |
| 203 | +#elif ABSL_HAVE_BUILTIN(__builtin_assume) |
| 204 | +#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_assume(false) |
| 205 | +#elif defined(_MSC_VER) |
| 206 | +#define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false) |
| 207 | +#else |
| 208 | +#define ABSL_INTERNAL_UNREACHABLE_IMPL() |
| 209 | +#endif |
| 210 | + |
| 211 | +// `ABSL_UNREACHABLE()` is an unreachable statement. A program which reaches |
| 212 | +// one has undefined behavior, and the compiler may optimize accordingly. |
| 213 | +#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) |
| 214 | +// Abort in hardened mode to avoid dangerous undefined behavior. |
| 215 | +#define ABSL_UNREACHABLE() \ |
| 216 | + do { \ |
| 217 | + ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \ |
| 218 | + ABSL_INTERNAL_UNREACHABLE_IMPL(); \ |
| 219 | + } while (false) |
| 220 | +#else |
| 221 | +// The assert only fires in debug mode to aid in debugging. |
| 222 | +// When NDEBUG is defined, reaching ABSL_UNREACHABLE() is undefined behavior. |
| 223 | +#define ABSL_UNREACHABLE() \ |
| 224 | + do { \ |
| 225 | + assert(false && "ABSL_UNREACHABLE reached"); \ |
| 226 | + ABSL_INTERNAL_UNREACHABLE_IMPL(); \ |
| 227 | + } while (false) |
| 228 | +#endif |
| 229 | + |
184 | 230 | // ABSL_ASSUME(cond) |
185 | 231 | // |
186 | 232 | // Informs the compiler that a condition is always true and that it can assume |
|
209 | 255 | #define ABSL_ASSUME(cond) assert(cond) |
210 | 256 | #elif ABSL_HAVE_BUILTIN(__builtin_assume) |
211 | 257 | #define ABSL_ASSUME(cond) __builtin_assume(cond) |
| 258 | +#elif defined(_MSC_VER) |
| 259 | +#define ABSL_ASSUME(cond) __assume(cond) |
| 260 | +#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L |
| 261 | +#define ABSL_ASSUME(cond) \ |
| 262 | + do { \ |
| 263 | + if (!(cond)) std::unreachable(); \ |
| 264 | + } while (false) |
212 | 265 | #elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) |
213 | 266 | #define ABSL_ASSUME(cond) \ |
214 | 267 | do { \ |
215 | 268 | if (!(cond)) __builtin_unreachable(); \ |
216 | | - } while (0) |
217 | | -#elif defined(_MSC_VER) |
218 | | -#define ABSL_ASSUME(cond) __assume(cond) |
| 269 | + } while (false) |
219 | 270 | #else |
220 | 271 | #define ABSL_ASSUME(cond) \ |
221 | 272 | do { \ |
222 | 273 | static_cast<void>(false && (cond)); \ |
223 | | - } while (0) |
| 274 | + } while (false) |
224 | 275 | #endif |
225 | 276 |
|
226 | 277 | // ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) |
|
0 commit comments