diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index e9e0ae2e37..a519ee924b 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -3744,11 +3744,14 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* p) { if (!HasDescriptorMethods(descriptor_->file(), options_)) { // Generate CheckTypeAndMergeFrom(). - format( - "void $classname$::CheckTypeAndMergeFrom(\n" - " const ::$proto_ns$::MessageLite& from) {\n" - " MergeFrom(::$proto_ns$::DownCastToGenerated<$classname$>(from));\n" - "}\n"); + // We pass `*this` instead of `default_instance()` to allow for ICF. + p->Emit(R"cc( + void $classname$::CheckTypeAndMergeFrom( + const ::$proto_ns$::MessageLite& from) { + $pbi$::AssertDownCast(from, *this); + MergeFrom(static_cast(from)); + } + )cc"); } } diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 990b92292e..4c3b7ea7d5 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -863,6 +863,11 @@ T* OnShutdownDelete(T* p) { return p; } +inline void AssertDownCast(const MessageLite& from, const MessageLite& to) { + ABSL_DCHECK(internal::TypeId::Get(from) == internal::TypeId::Get(to)) + << "Cannot downcast " << from.GetTypeName() << " to " << to.GetTypeName(); +} + } // namespace internal std::string ShortFormat(const MessageLite& message_lite);