Change DynamicCastMessage to throw a `std::bad_cast` exception when exceptions

are enabled.
This makes the function a drop-in replacement for `dynamic_cast` when the user
is expecting exceptions to be thrown.

PiperOrigin-RevId: 689419852
pull/18936/head
Protobuf Team Bot 4 months ago committed by Copybara-Service
parent 350e24efa9
commit 33bbbebf20
  1. 3
      src/google/protobuf/BUILD.bazel
  2. 11
      src/google/protobuf/lite_unittest.cc
  3. 5
      src/google/protobuf/message_lite.cc
  4. 7
      src/google/protobuf/message_unittest.inc

@ -1268,6 +1268,7 @@ cc_library(
":protobuf",
"//src/google/protobuf/testing",
"//src/google/protobuf/testing:file",
"@com_google_absl//absl/base:config",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/strings",
@ -1735,6 +1736,7 @@ cc_test(
"//src/google/protobuf/testing",
"//src/google/protobuf/testing:file",
"//src/google/protobuf/util:differencer",
"@com_google_absl//absl/base:config",
"@com_google_absl//absl/hash:hash_testing",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/log:scoped_mock_log",
@ -1766,6 +1768,7 @@ cc_test(
"//src/google/protobuf/testing",
"//src/google/protobuf/testing:file",
"//src/google/protobuf/util:differencer",
"@com_google_absl//absl/base:config",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/log:scoped_mock_log",
"@com_google_absl//absl/strings",

@ -1395,16 +1395,23 @@ TEST(LiteTest, DynamicCastMessage) {
EXPECT_EQ(shared_2, nullptr);
}
#if GTEST_HAS_DEATH_TEST
TEST(LiteTest, DynamicCastMessageInvalidReferenceType) {
CastType1 test_type_1;
const MessageLite& test_type_1_pointer_const_ref = test_type_1;
#if defined(ABSL_HAVE_EXCEPTIONS)
EXPECT_THROW(DynamicCastMessage<CastType2>(test_type_1_pointer_const_ref),
std::bad_cast);
#elif defined(GTEST_HAS_DEATH_TEST)
ASSERT_DEATH(
DynamicCastMessage<CastType2>(test_type_1_pointer_const_ref),
absl::StrCat("Cannot downcast ", test_type_1.GetTypeName(), " to ",
CastType2::default_instance().GetTypeName()));
#else
(void)test_type_1;
(void)test_type_1_pointer_const_ref;
GTEST_SKIP() << "Can't test the failure.";
#endif
}
#endif // GTEST_HAS_DEATH_TEST
TEST(LiteTest, DownCastMessageValidType) {
CastType1 test_type_1;

@ -19,8 +19,10 @@
#include <istream>
#include <ostream>
#include <string>
#include <typeinfo>
#include <utility>
#include "absl/base/config.h"
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/cord.h"
@ -198,6 +200,9 @@ void MessageLite::LogInitializationErrorMessage() const {
namespace internal {
void FailDynamicCast(const MessageLite& from, const MessageLite& to) {
#if defined(ABSL_HAVE_EXCEPTIONS)
throw std::bad_cast();
#endif
const auto to_name = to.GetTypeName();
if (internal::GetClassData(from)->is_dynamic) {
ABSL_LOG(FATAL)

@ -35,6 +35,7 @@
#include <gmock/gmock.h>
#include "google/protobuf/testing/googletest.h"
#include <gtest/gtest.h>
#include "absl/base/config.h"
#include "absl/log/absl_check.h"
#include "absl/log/scoped_mock_log.h"
#include "absl/strings/cord.h"
@ -816,11 +817,17 @@ TEST(MESSAGE_TEST_NAME, DynamicCastMessage) {
TEST(MESSAGE_TEST_NAME, DynamicCastMessageInvalidReferenceType) {
UNITTEST::TestAllTypes test_all_types;
const MessageLite& test_all_types_pointer_const_ref = test_all_types;
#if defined(ABSL_HAVE_EXCEPTIONS)
EXPECT_THROW(DynamicCastMessage<UNITTEST::TestRequired>(
test_all_types_pointer_const_ref),
std::bad_cast);
#else
ASSERT_DEATH(
DynamicCastMessage<UNITTEST::TestRequired>(
test_all_types_pointer_const_ref),
absl::StrCat("Cannot downcast ", test_all_types.GetTypeName(), " to ",
UNITTEST::TestRequired::default_instance().GetTypeName()));
#endif
}
TEST(MESSAGE_TEST_NAME, DownCastMessageValidType) {

Loading…
Cancel
Save