diff --git a/src/google/protobuf/repeated_ptr_field.cc b/src/google/protobuf/repeated_ptr_field.cc index e51c1a111a..36dac0e0f3 100644 --- a/src/google/protobuf/repeated_ptr_field.cc +++ b/src/google/protobuf/repeated_ptr_field.cc @@ -185,6 +185,10 @@ MessageLite* RepeatedPtrFieldBase::AddWeak(const MessageLite* prototype) { return result; } +void InternalOutOfLineDeleteMessageLite(MessageLite* message) { + delete message; +} + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h index 5b5d770c56..98398526c5 100644 --- a/src/google/protobuf/repeated_ptr_field.h +++ b/src/google/protobuf/repeated_ptr_field.h @@ -843,6 +843,8 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { void* tagged_rep_or_elem_; }; +void InternalOutOfLineDeleteMessageLite(MessageLite* message); + template class GenericTypeHandler { public: @@ -860,9 +862,18 @@ class GenericTypeHandler { return New(arena); } static inline void Delete(GenericType* value, Arena* arena) { - if (arena == nullptr) { + if (arena != nullptr) return; +#ifdef __cpp_if_constexpr + if constexpr (std::is_base_of::value) { + // Using virtual destructor to reduce generated code size that would have + // happened otherwise due to inlined `~GenericType`. + InternalOutOfLineDeleteMessageLite(value); + } else { delete value; } +#else + delete value; +#endif } static inline Arena* GetOwningArena(GenericType* value) { return Arena::InternalGetOwningArena(value);