diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc index 71943600a5..105f5f6022 100644 --- a/src/google/protobuf/compiler/cpp/helpers.cc +++ b/src/google/protobuf/compiler/cpp/helpers.cc @@ -1169,6 +1169,17 @@ bool HasMapFields(const FileDescriptor* file) { return false; } +bool HasV2Table(const Descriptor* descriptor) { + return false; +} + +bool HasV2Table(const FileDescriptor* file) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasV2Table(file->message_type(i))) return true; + } + return false; +} + static bool HasEnumDefinitions(const Descriptor* message_type) { if (message_type->enum_type_count() > 0) return true; for (int i = 0; i < message_type->nested_type_count(); ++i) { diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h index a8e0417fa4..4e67019f33 100644 --- a/src/google/protobuf/compiler/cpp/helpers.h +++ b/src/google/protobuf/compiler/cpp/helpers.h @@ -467,6 +467,12 @@ bool HasMapFields(const FileDescriptor* file); // Does this file have any enum type definitions? bool HasEnumDefinitions(const FileDescriptor* file); +// Returns true if a message in the file can have v2 table. +bool HasV2Table(const FileDescriptor* file); + +// Returns true if a message (descriptor) can have v2 table. +bool HasV2Table(const Descriptor* descriptor); + // Does this file have generated parsing, serialization, and other // standard methods for which reflection-based fallback implementations exist? inline bool HasGeneratedMethods(const FileDescriptor* file, diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 0b79ce336b..ebd48ea2d9 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -1366,7 +1366,9 @@ void MessageGenerator::GenerateMapEntryClassDefinition(io::Printer* p) { }}, {"decl_annotate", [&] { GenerateAnnotationDecl(p); }}, {"parse_decls", - [&] { parse_function_generator_->GenerateDataDecls(p); }}}, + [&] { + parse_function_generator_->GenerateDataDecls(p); + }}}, R"cc( class $classname$ final : public ::$proto_ns$::internal::MapEntry< @@ -2026,7 +2028,10 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { )cc"); } }}, - {"decl_data", [&] { parse_function_generator_->GenerateDataDecls(p); }}, + {"decl_data", + [&] { + parse_function_generator_->GenerateDataDecls(p); + }}, {"post_loop_handler", [&] { if (!NeedsPostLoopHandler(descriptor_, options_)) return; @@ -4040,6 +4045,9 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { {"is_initialized", is_initialized}, {"pin_weak_descriptor", pin_weak_descriptor}, {"custom_vtable_methods", custom_vtable_methods}, + {"v2_msg_table", + [&] { + }}, {"tracker_on_get_metadata", [&] { if (HasTracker(descriptor_, options_)) { @@ -4071,6 +4079,7 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { #endif // PROTOBUF_CUSTOM_VTABLE PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), false, + $v2_msg_table$, }, &$classname$::kDescriptorMethods, &$desc_table$, @@ -4090,6 +4099,9 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { {"on_demand_register_arena_dtor", on_demand_register_arena_dtor}, {"is_initialized", is_initialized}, {"custom_vtable_methods", custom_vtable_methods}, + {"v2_msg_table", + [&] { + }}, }, R"cc( PROTOBUF_CONSTINIT @@ -4109,6 +4121,7 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { #endif // PROTOBUF_CUSTOM_VTABLE PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), true, + $v2_msg_table$, }, "$full_name$", }; diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index dc0137e064..c02f7b6735 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -68,6 +68,13 @@ class ZeroCopyInputStream; class ZeroCopyOutputStream; } // namespace io + +namespace compiler { +namespace cpp { +class MessageTableTester; +} // namespace cpp +} // namespace compiler + namespace internal { class MessageCreator { @@ -712,15 +719,15 @@ class PROTOBUF_EXPORT MessageLite { // In normal mode we have the small constructor to avoid the cost in // codegen. #if !defined(PROTOBUF_CUSTOM_VTABLE) - constexpr ClassData(const MessageLite* prototype, - const internal::TcParseTableBase* tc_table, - void (*on_demand_register_arena_dtor)(MessageLite&, - Arena&), - bool (*is_initialized)(const MessageLite&), - void (*merge_to_from)(MessageLite& to, - const MessageLite& from_msg), - internal::MessageCreator message_creator, - uint32_t cached_size_offset, bool is_lite) + constexpr ClassData( + const MessageLite* prototype, + const internal::TcParseTableBase* tc_table, + void (*on_demand_register_arena_dtor)(MessageLite&, Arena&), + bool (*is_initialized)(const MessageLite&), + void (*merge_to_from)(MessageLite& to, const MessageLite& from_msg), + internal::MessageCreator message_creator, uint32_t cached_size_offset, + bool is_lite + ) : prototype(prototype), tc_table(tc_table), on_demand_register_arena_dtor(on_demand_register_arena_dtor), @@ -728,7 +735,9 @@ class PROTOBUF_EXPORT MessageLite { merge_to_from(merge_to_from), message_creator(message_creator), cached_size_offset(cached_size_offset), - is_lite(is_lite) {} + is_lite(is_lite) + { + } #endif // !PROTOBUF_CUSTOM_VTABLE // But we always provide the full constructor even in normal mode to make @@ -745,7 +754,8 @@ class PROTOBUF_EXPORT MessageLite { size_t (*byte_size_long)(const MessageLite&), uint8_t* (*serialize)(const MessageLite& msg, uint8_t* ptr, io::EpsCopyOutputStream* stream), - uint32_t cached_size_offset, bool is_lite) + uint32_t cached_size_offset, bool is_lite + ) : prototype(prototype), tc_table(tc_table), on_demand_register_arena_dtor(on_demand_register_arena_dtor), @@ -759,7 +769,8 @@ class PROTOBUF_EXPORT MessageLite { serialize(serialize), #endif // PROTOBUF_CUSTOM_VTABLE cached_size_offset(cached_size_offset), - is_lite(is_lite) { + is_lite(is_lite) + { } const ClassDataFull& full() const { @@ -930,6 +941,7 @@ class PROTOBUF_EXPORT MessageLite { friend class Message; friend class Reflection; friend class TypeId; + friend class compiler::cpp::MessageTableTester; friend class internal::DescriptorPoolExtensionFinder; friend class internal::ExtensionSet; friend class internal::LazyField; @@ -957,6 +969,13 @@ class PROTOBUF_EXPORT MessageLite { // `operator delete` void DeleteInstance(); + // For tests that need to inspect private _oneof_case_. It is the callers + // responsibility to ensure T has the right member. + template + static uint32_t GetOneofCaseOffsetForTesting() { + return offsetof(T, _impl_._oneof_case_); + } + template static constexpr auto GetStrongPointerForTypeImpl(int) { return ptr;