ABSL_ASSUME: Use a ternary operator instead of do-while in the
implementations that use a branch marked unreachable so that it is
usable in more contexts.

The unimplemented case now uses the same definition as ABSL_ASSERT
when NDEBUG is defined.

Fixes https://github.com/abseil/abseil-cpp/issues/1814

PiperOrigin-RevId: 720236336
Change-Id: I4f4f6e8a384dd11a07626b085a001fc2f5b7db21
diff --git a/absl/base/optimization.h b/absl/base/optimization.h
index 3aa66e1..429ea9c 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<void>(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 897234f..b47b11a 100644
--- a/absl/base/optimization_test.cc
+++ b/absl/base/optimization_test.cc
@@ -126,4 +126,16 @@
   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