diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index d770517633..44f33f3584 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -239,6 +239,7 @@ cc_test( deps = [ ":port_def", ":varint_shuffle", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/log:absl_check", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", @@ -439,6 +440,7 @@ cc_library( "//src/google/protobuf/stubs:lite", "//third_party/utf8_range:utf8_validity", "@com_google_absl//absl/base", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/hash", diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h index 51e63e30e2..6d7bd4b713 100644 --- a/src/google/protobuf/port.h +++ b/src/google/protobuf/port.h @@ -22,6 +22,7 @@ #include +#include "absl/base/config.h" #include "absl/meta/type_traits.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" @@ -201,6 +202,18 @@ inline constexpr bool DebugHardenStringValues() { #endif } +#if ABSL_HAVE_BUILTIN(__builtin_FILE) && ABSL_HAVE_BUILTIN(__builtin_LINE) +[[noreturn]] inline void Unreachable(const char* file = __builtin_FILE(), + int line = __builtin_LINE()) { +#else +[[noreturn]] inline void Unreachable(const char* file = "", int line = 0) { +#endif +#if defined(NDEBUG) && ABSL_HAVE_BUILTIN(__builtin_unreachable) + __builtin_unreachable(); +#endif + protobuf_assumption_failed("Unreachable", file, line); +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index d1bf975a16..42ffca6fd6 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -1030,8 +1030,9 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), namespace google { namespace protobuf { namespace internal { -PROTOBUF_EXPORT void protobuf_assumption_failed(const char *pred, - const char *file, int line); +[[noreturn]] PROTOBUF_EXPORT void protobuf_assumption_failed(const char *pred, + const char *file, + int line); } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/port_test.cc b/src/google/protobuf/port_test.cc index d1174c3a1b..5fbd55b67e 100644 --- a/src/google/protobuf/port_test.cc +++ b/src/google/protobuf/port_test.cc @@ -5,10 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd // +#include "google/protobuf/port.h" + #include #include #include +#include "absl/base/config.h" // Must be included last #include "google/protobuf/port_def.inc" @@ -28,6 +31,16 @@ TEST(PortTest, ProtobufAssume) { #endif } +TEST(PortTest, UnreachableTrapsOnDebugMode) { +#ifdef GTEST_HAS_DEATH_TEST + EXPECT_DEBUG_DEATH(Unreachable(), "Assumption failed: 'Unreachable'"); +#if ABSL_HAVE_BUILTIN(__builtin_FILE) + EXPECT_DEBUG_DEATH(Unreachable(), + "port_test\\.cc:.*Assumption failed: 'Unreachable'"); +#endif +#endif +} + } // namespace internal } // namespace protobuf } // namespace google