diff --git a/src/google/protobuf/compiler/cpp/extension.cc b/src/google/protobuf/compiler/cpp/extension.cc index 924ef4e5cb..a13aae2d4f 100644 --- a/src/google/protobuf/compiler/cpp/extension.cc +++ b/src/google/protobuf/compiler/cpp/extension.cc @@ -165,10 +165,9 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* p) { if (IsLazilyInitializedFile(descriptor_->file()->name())) { p->Emit(R"cc( PROTOBUF_CONSTINIT$ dllexport_decl$ - PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::$proto_ns$::internal:: - ExtensionIdentifier< - $extendee$, ::$proto_ns$::internal::$type_traits$, - $field_type$, $packed$> + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: + ExtensionIdentifier<$extendee$, ::_pbi::$type_traits$, + $field_type$, $packed$> $scoped_name$($constant_name$); )cc"); return; @@ -183,23 +182,37 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* p) { ShouldVerify(descriptor_->containing_type(), options_, scc_analyzer_); - if (should_verify) { + if (!should_verify) { p->Emit(R"cc( - $dllexport_decl $PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 :: - $proto_ns$::internal::ExtensionIdentifier< - $extendee$, ::$proto_ns$::internal::$type_traits$, - $field_type$, $packed$> - $scoped_name$($constant_name$, $default_str$, - &$message_type$::InternalVerify); - )cc"); - } else { - p->Emit(R"cc( - $dllexport_decl $PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 :: - $proto_ns$::internal::ExtensionIdentifier< - $extendee$, ::$proto_ns$::internal::$type_traits$, - $field_type$, $packed$> + $dllexport_decl $PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: + ExtensionIdentifier<$extendee$, ::_pbi::$type_traits$, + $field_type$, $packed$> $scoped_name$($constant_name$, $default_str$); )cc"); + return; + } + + const auto& options = descriptor_->options(); + if (options.has_lazy()) { + p->Emit( + {{"is_lazy", options.lazy() ? "kLazy" : "kEager"}}, + R"cc( + $dllexport_decl $PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: + ExtensionIdentifier<$extendee$, ::_pbi::$type_traits$, + $field_type$, $packed$> + $scoped_name$($constant_name$, $default_str$, + &$message_type$::InternalVerify, + ::_pbi::LazyAnnotation::$is_lazy$); + )cc"); + } else { + p->Emit( + R"cc( + $dllexport_decl $PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: + ExtensionIdentifier<$extendee$, ::_pbi::$type_traits$, + $field_type$, $packed$> + $scoped_name$($constant_name$, $default_str$, + &$message_type$::InternalVerify); + )cc"); } }}, }, diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index c90164e5f0..1b02dbef59 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -375,10 +375,9 @@ void JavaFeatures::InternalSwap(JavaFeatures* PROTOBUF_RESTRICT other) { &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_once, file_level_metadata_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto[0]); } -PROTOC_EXPORT PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 :: - google::protobuf::internal::ExtensionIdentifier< - ::google::protobuf::FeatureSet, ::google::protobuf::internal::MessageTypeTraits< ::pb::JavaFeatures >, - 11, false> +PROTOC_EXPORT PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: + ExtensionIdentifier<::google::protobuf::FeatureSet, ::_pbi::MessageTypeTraits< ::pb::JavaFeatures >, + 11, false> java(kJavaFieldNumber, ::pb::JavaFeatures::default_instance()); // @@protoc_insertion_point(namespace_scope) } // namespace pb diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index 6e5538d889..55c1864695 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -299,10 +299,9 @@ void CppFeatures::InternalSwap(CppFeatures* PROTOBUF_RESTRICT other) { file_level_metadata_google_2fprotobuf_2fcpp_5ffeatures_2eproto[0]); } PROTOBUF_CONSTINIT PROTOBUF_EXPORT - PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::google::protobuf::internal:: - ExtensionIdentifier< - ::google::protobuf::FeatureSet, ::google::protobuf::internal::MessageTypeTraits< ::pb::CppFeatures >, - 11, false> + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: + ExtensionIdentifier<::google::protobuf::FeatureSet, ::_pbi::MessageTypeTraits< ::pb::CppFeatures >, + 11, false> cpp(kCppFieldNumber); // @@protoc_insertion_point(namespace_scope) } // namespace pb diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 538178fc4a..32528d4cb2 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -148,11 +148,12 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* extendee, int number, FieldType type, bool is_repeated, bool is_packed, const MessageLite* prototype, - LazyEagerVerifyFnType verify_func) { + LazyEagerVerifyFnType verify_func, + LazyAnnotation is_lazy) { ABSL_CHECK(type == WireFormatLite::TYPE_MESSAGE || type == WireFormatLite::TYPE_GROUP); ExtensionInfo info(extendee, number, type, is_repeated, is_packed, - verify_func); + verify_func, is_lazy); info.message_info = {prototype}; Register(info); } diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index f9fb2bd94f..74a316eee3 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -32,6 +32,7 @@ #include "google/protobuf/internal_visibility.h" #include "google/protobuf/port.h" #include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/parse_context.h" #include "google/protobuf/repeated_field.h" #include "google/protobuf/repeated_ptr_field.h" @@ -90,6 +91,12 @@ typedef bool EnumValidityFunc(int number); // extensions that are not compiled in. typedef bool EnumValidityFuncWithArg(const void* arg, int number); +enum class LazyAnnotation : int8_t { + kUndefined = 0, + kLazy = 1, + kEager = 2, +}; + // Information about a registered extension. struct ExtensionInfo { constexpr ExtensionInfo() : enum_validity_check() {} @@ -103,12 +110,14 @@ struct ExtensionInfo { enum_validity_check() {} constexpr ExtensionInfo(const MessageLite* extendee, int param_number, FieldType type_param, bool isrepeated, bool ispacked, - LazyEagerVerifyFnType verify_func) + LazyEagerVerifyFnType verify_func, + LazyAnnotation islazy = LazyAnnotation::kUndefined) : message(extendee), number(param_number), type(type_param), is_repeated(isrepeated), is_packed(ispacked), + is_lazy(islazy), enum_validity_check(), lazy_eager_verify_func(verify_func) {} @@ -118,6 +127,7 @@ struct ExtensionInfo { FieldType type = 0; bool is_repeated = false; bool is_packed = false; + LazyAnnotation is_lazy = LazyAnnotation::kUndefined; struct EnumValidityCheck { EnumValidityFuncWithArg* func; @@ -144,6 +154,7 @@ struct ExtensionInfo { LazyEagerVerifyFnType lazy_eager_verify_func = nullptr; }; + // An ExtensionFinder is an object which looks up extension definitions. It // must implement this method: // @@ -209,7 +220,8 @@ class PROTOBUF_EXPORT ExtensionSet { FieldType type, bool is_repeated, bool is_packed, const MessageLite* prototype, - LazyEagerVerifyFnType verify_func); + LazyEagerVerifyFnType verify_func, + LazyAnnotation is_lazy); // ================================================================= @@ -1405,17 +1417,17 @@ class MessageTypeTraits { // Some messages won't (can't) be verified; e.g. lite. template static void Register(int number, FieldType type, bool is_packed) { - ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), - number, type, false, is_packed, - &Type::default_instance(), nullptr); + ExtensionSet::RegisterMessageExtension( + &ExtendeeT::default_instance(), number, type, false, is_packed, + &Type::default_instance(), nullptr, LazyAnnotation::kUndefined); } template static void Register(int number, FieldType type, bool is_packed, - LazyEagerVerifyFnType fn) { - ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), - number, type, false, is_packed, - &Type::default_instance(), fn); + LazyEagerVerifyFnType fn, LazyAnnotation is_lazy) { + ExtensionSet::RegisterMessageExtension( + &ExtendeeT::default_instance(), number, type, false, is_packed, + &Type::default_instance(), fn, is_lazy); } }; @@ -1481,17 +1493,17 @@ class RepeatedMessageTypeTraits { // Some messages won't (can't) be verified; e.g. lite. template static void Register(int number, FieldType type, bool is_packed) { - ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), - number, type, true, is_packed, - &Type::default_instance(), nullptr); + ExtensionSet::RegisterMessageExtension( + &ExtendeeT::default_instance(), number, type, true, is_packed, + &Type::default_instance(), nullptr, LazyAnnotation::kUndefined); } template static void Register(int number, FieldType type, bool is_packed, - LazyEagerVerifyFnType fn) { - ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), - number, type, true, is_packed, - &Type::default_instance(), fn); + LazyEagerVerifyFnType fn, LazyAnnotation is_lazy) { + ExtensionSet::RegisterMessageExtension( + &ExtendeeT::default_instance(), number, type, true, is_packed, + &Type::default_instance(), fn, is_lazy); } }; @@ -1533,9 +1545,10 @@ class ExtensionIdentifier { Register(number); } ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value, - LazyEagerVerifyFnType verify_func) + LazyEagerVerifyFnType verify_func, + LazyAnnotation is_lazy = LazyAnnotation::kUndefined) : number_(number), default_value_(default_value) { - Register(number, verify_func); + Register(number, verify_func, is_lazy); } inline int number() const { return number_; } typename TypeTraits::ConstType default_value() const { @@ -1546,9 +1559,10 @@ class ExtensionIdentifier { TypeTraits::template Register(number, field_type, is_packed); } - static void Register(int number, LazyEagerVerifyFnType verify_func) { + static void Register(int number, LazyEagerVerifyFnType verify_func, + LazyAnnotation is_lazy) { TypeTraits::template Register(number, field_type, is_packed, - verify_func); + verify_func, is_lazy); } typename TypeTraits::ConstType const& default_value_ref() const { @@ -1586,7 +1600,7 @@ class ExtensionIdentifier, 11, absl::call_once(once_, [&] { default_value_ = &default_instance; MessageTypeTraits::template Register( - number_, 11, false, verify_func); + number_, 11, false, verify_func, LazyAnnotation::kUndefined); }); } diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 20530c14dc..79d7977ab0 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -271,6 +271,11 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { ABSL_CHECK(output->message_info.prototype != nullptr) << "Extension factory's GetPrototype() returned nullptr; extension: " << extension->full_name(); + + if (extension->options().has_lazy()) { + output->is_lazy = extension->options().lazy() ? LazyAnnotation::kLazy + : LazyAnnotation::kEager; + } } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { output->enum_validity_check.func = ValidateEnumUsingDescriptor; output->enum_validity_check.arg = extension->enum_type(); diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index c65ebd96d1..df926e7a20 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -11,6 +11,8 @@ #include "google/protobuf/extension_set.h" +#include + #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/testing/googletest.h" #include @@ -27,6 +29,7 @@ #include "google/protobuf/test_util2.h" #include "google/protobuf/text_format.h" #include "google/protobuf/unittest.pb.h" +#include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_mset.pb.h" #include "google/protobuf/wire_format.h" #include "google/protobuf/wire_format_lite.h" @@ -37,6 +40,8 @@ namespace google { namespace protobuf { + + namespace internal { namespace {