diff --git a/absl/base/optimization.h b/absl/base/optimization.h index 3aa66e1c7db..429ea9ce79d 100644 --- a/absl/base/optimization.h +++ b/absl/base/optimization.h @@ -25,6 +25,8 @@ // new code that requires C compatibility or assume C compatibility will remain // indefinitely. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_BASE_OPTIMIZATION_H_ #define ABSL_BASE_OPTIMIZATION_H_ @@ -271,20 +273,14 @@ #elif defined(_MSC_VER) #define ABSL_ASSUME(cond) __assume(cond) #elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L -#define ABSL_ASSUME(cond) \ - do { \ - if (!(cond)) std::unreachable(); \ - } while (false) +#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable()) #elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) -#define ABSL_ASSUME(cond) \ - do { \ - if (!(cond)) __builtin_unreachable(); \ - } while (false) +#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable()) +#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case. +#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())()) #else -#define ABSL_ASSUME(cond) \ - do { \ - static_cast(false && (cond)); \ - } while (false) +#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void()) #endif // ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) diff --git a/absl/base/optimization_test.cc b/absl/base/optimization_test.cc index 897234f3d49..b47b11a1ad3 100644 --- a/absl/base/optimization_test.cc +++ b/absl/base/optimization_test.cc @@ -126,4 +126,16 @@ TEST(PredictTest, ExplicitBoolConversion) { if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE(); } +// This verifies that ABSL_ASSUME compiles in a variety of contexts. +// It does not test optimization. +TEST(AbslAssume, Compiles) { + int x = 0; + ABSL_ASSUME(x >= 0); + EXPECT_EQ(x, 0); + + // https://github.com/abseil/abseil-cpp/issues/1814 + ABSL_ASSUME(x >= 0), (x >= 0) ? ++x : --x; + EXPECT_EQ(x, 1); +} + } // namespace