Skip to content

Commit 6a87605

Browse files
derekmaurocopybara-github
authored andcommitted
Adds ABSL_UNREACHABLE(), a public symbol to replace ABSL_INTERNAL_UNREACHABLE
ABSL_UNREACHABLE() is an unreachable statement. A program which reaches one has undefined behavior, and the compiler may optimize accordingly. The behavior is changed to abort the program in !NDEBUG or ABSL_OPTION_HARDENED modes. PiperOrigin-RevId: 496917150 Change-Id: If036b2d9567933fa266fbcd33f3f98c682ad7f41
1 parent 8caa47c commit 6a87605

File tree

2 files changed

+61
-24
lines changed

2 files changed

+61
-24
lines changed

absl/base/macros.h

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,11 @@ ABSL_NAMESPACE_END
103103
// aborts the program in release mode (when NDEBUG is defined). The
104104
// implementation should abort the program as quickly as possible and ideally it
105105
// should not be possible to ignore the abort request.
106-
#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \
107-
ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \
108-
(defined(__GNUC__) && !defined(__clang__))
109-
#define ABSL_INTERNAL_HARDENING_ABORT() \
110-
do { \
111-
__builtin_trap(); \
112-
__builtin_unreachable(); \
106+
#define ABSL_INTERNAL_HARDENING_ABORT() \
107+
do { \
108+
ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
109+
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
113110
} while (false)
114-
#else
115-
#define ABSL_INTERNAL_HARDENING_ABORT() abort()
116-
#endif
117111

118112
// ABSL_HARDENING_ASSERT()
119113
//
@@ -144,15 +138,7 @@ ABSL_NAMESPACE_END
144138
#define ABSL_INTERNAL_RETHROW do {} while (false)
145139
#endif // ABSL_HAVE_EXCEPTIONS
146140

147-
// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
148-
// reaches one has undefined behavior, and the compiler may optimize
149-
// accordingly.
150-
#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
151-
#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
152-
#elif defined(_MSC_VER)
153-
#define ABSL_INTERNAL_UNREACHABLE __assume(0)
154-
#else
155-
#define ABSL_INTERNAL_UNREACHABLE
156-
#endif
141+
// TODO(b/261916195): Replace ABSL_INTERNAL_UNREACHABLE with ABSL_UNREACHABLE().
142+
#define ABSL_INTERNAL_UNREACHABLE ABSL_UNREACHABLE()
157143

158144
#endif // ABSL_BASE_MACROS_H_

absl/base/optimization.h

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,52 @@
181181
#define ABSL_PREDICT_TRUE(x) (x)
182182
#endif
183183

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+
184230
// ABSL_ASSUME(cond)
185231
//
186232
// Informs the compiler that a condition is always true and that it can assume
@@ -209,18 +255,23 @@
209255
#define ABSL_ASSUME(cond) assert(cond)
210256
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
211257
#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)
212265
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
213266
#define ABSL_ASSUME(cond) \
214267
do { \
215268
if (!(cond)) __builtin_unreachable(); \
216-
} while (0)
217-
#elif defined(_MSC_VER)
218-
#define ABSL_ASSUME(cond) __assume(cond)
269+
} while (false)
219270
#else
220271
#define ABSL_ASSUME(cond) \
221272
do { \
222273
static_cast<void>(false && (cond)); \
223-
} while (0)
274+
} while (false)
224275
#endif
225276

226277
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)

0 commit comments

Comments
 (0)