@@ -124,6 +124,16 @@ constexpr bool FieldHasArenaOffset() {
124124return !std::is_same_v<T, ArenaRepT>;
125125}
126126
127+ // TODO - Some types have a deprecated arena-enabled constructor,
128+ // as we plan to remove it in favor of using arena offsets, but for now Arena
129+ // needs to call it. While the arena constructor exists, we will call the
130+ // `InternalVisibility` override to silence the warning.
131+ template <typename T>
132+ constexpr bool HasDeprecatedArenaConstructor () {
133+ return std::is_base_of_v<internal::RepeatedPtrFieldBase, T> &&
134+ !std::is_same_v<T, internal::RepeatedPtrFieldBase>;
135+ }
136+
127137template <typename T>
128138void arena_delete_object (void * PROTOBUF_NONNULL object) {
129139delete reinterpret_cast <T*>(object);
@@ -478,16 +488,12 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8)
478488static T* PROTOBUF_NONNULLConstructOnArena (void * PROTOBUF_NONNULL ptr,
479489 Arena& arena, Args&&... args) {
480490// TODO - ClangTidy gives warnings for calling the deprecated
481- // `RepeatedPtrField(Arena*)` constructor here, but this is the correct
482- // way to call it as it will allow us to silently switch to a different
483- // constructor once arena pointers are removed from RepeatedPtrFields.
484- // While this constructor exists, we will call the `InternalVisibility`
485- // override to silence the warning.
486- //
487- // Note: RepeatedPtrFieldBase is sometimes constructed internally, and it
488- // doesn't have `InternalVisibility` constructors.
489- if constexpr (std::is_base_of_v<internal::RepeatedPtrFieldBase, T> &&
490- !std::is_same_v<T, internal::RepeatedPtrFieldBase>) {
491+ // constructors here, which leads to log spam. It is correct to invoke
492+ // these constructors through the Arena class as it will allow us to
493+ // silently switch to a different constructor once arena pointers are
494+ // removed. While these constructors exists, we will call the
495+ // `InternalVisibility` overrides to silence the warning.
496+ if constexpr (internal::HasDeprecatedArenaConstructor<T>()) {
491497return new (ptr)T (internal::InternalVisibility (), &arena,
492498static_cast <Args&&>(args)...);
493499 }else {
@@ -510,7 +516,8 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8)
510516// Fields which use arena offsets don't have constructors that take an
511517// arena pointer. Since the arena is nullptr, it is safe to default
512518// construct the object.
513- if constexpr (internal::FieldHasArenaOffset<T>()) {
519+ if constexpr (internal::FieldHasArenaOffset<T>() ||
520+ internal::HasDeprecatedArenaConstructor<T>()) {
514521return new T ();
515522 }else {
516523return new T (nullptr );
@@ -590,7 +597,8 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8)
590597static_assert (is_arena_constructable<T>::value,
591598" Can only construct types that are ArenaConstructable" );
592599if (ABSL_PREDICT_FALSE (arena ==nullptr )) {
593- if constexpr (internal::FieldHasArenaOffset<T>()) {
600+ if constexpr (internal::FieldHasArenaOffset<T>() ||
601+ internal::HasDeprecatedArenaConstructor<T>()) {
594602return new T (static_cast <Args&&>(args)...);
595603 }else {
596604return new T (nullptr ,static_cast <Args&&>(args)...);
@@ -744,7 +752,12 @@ Arena::DefaultConstruct(Arena* PROTOBUF_NULLABLE arena) {
744752static_assert (is_destructor_skippable<T>::value," " );
745753void * mem = arena !=nullptr ? arena->AllocateAligned (sizeof (T))
746754 : ::operator new (sizeof (T));
747- return new (mem)T (arena);
755+
756+ if constexpr (internal::HasDeprecatedArenaConstructor<T>()) {
757+ return new (mem)T (internal::InternalVisibility (), arena);
758+ }else {
759+ return new (mem)T (arena);
760+ }
748761}
749762
750763template <typename T>