diff options
author | nechda <[email protected]> | 2024-08-29 23:50:27 +0300 |
---|---|---|
committer | nechda <[email protected]> | 2024-08-30 00:05:25 +0300 |
commit | e10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch) | |
tree | 571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc | |
parent | e79b38f2bbbf78d295d1901d2a79f898022d5224 (diff) |
Update cpp-protobuf to 22.5
Привет!\
Этот PR переключат cpp & python библиотеки protobuf на версию 22.5
Если у вас возникли проблемы после влития этого PR:
1. Если начали падать канон тесты, то проведите их переканонизацию
2. Прочитайте <https://wiki.yandex-team.ru/users/nechda/obnovlenie-cpp-protobuf-22.5/> страничку с основными изменениями
3. Если страничка в вики не помогла, то пишите в [DEVTOOLSSUPPORT](https://st.yandex-team.ru/DEVTOOLSSUPPORT)
7fecade616c20a841b9e9af7b7998bdfc8d2807d
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc')
-rw-r--r-- | contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc | 850 |
1 files changed, 473 insertions, 377 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc index 48879f29d57..977aa87d85e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc @@ -32,35 +32,45 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/helpers.h> +#include "google/protobuf/compiler/cpp/helpers.h" +#include <algorithm> #include <cstdint> #include <functional> #include <limits> -#include <map> #include <memory> #include <queue> -#include <unordered_set> +#include <string> +#include <utility> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/names.h> -#include <google/protobuf/compiler/cpp/options.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/compiler/scc.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/dynamic_message.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/wire_format_lite.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/stubs/hash.h> +#include "google/protobuf/stubs/common.h" +#include "google/protobuf/compiler/scc.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/dynamic_message.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "y_absl/strings/substitute.h" +#include "y_absl/synchronization/mutex.h" +#include "google/protobuf/compiler/cpp/names.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/wire_format_lite.h" + // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -72,11 +82,12 @@ namespace { static const char kAnyMessageName[] = "Any"; static const char kAnyProtoFile[] = "google/protobuf/any.proto"; -TProtoStringType DotsToColons(const TProtoStringType& name) { - return StringReplace(name, ".", "::", true); +TProtoStringType DotsToColons(y_absl::string_view name) { + return y_absl::StrReplaceAll(name, {{".", "::"}}); } -static const char* const kKeywordList[] = { // +static const char* const kKeywordList[] = { + // "NULL", "alignas", "alignof", @@ -163,48 +174,36 @@ static const char* const kKeywordList[] = { // "wchar_t", "while", "xor", - "xor_eq"}; - -static std::unordered_set<TProtoStringType>* MakeKeywordsMap() { - auto* result = new std::unordered_set<TProtoStringType>(); - for (const auto keyword : kKeywordList) { - result->emplace(keyword); - } - return result; -} - -static std::unordered_set<TProtoStringType>& kKeywords = *MakeKeywordsMap(); + "xor_eq", + "char8_t", + "char16_t", + "char32_t", + "concept", + "consteval", + "constinit", + "co_await", + "co_return", + "co_yield", + "requires", +}; -TProtoStringType IntTypeName(const Options& options, const TProtoStringType& type) { - return "::NProtoBuf::" + type; -} +const y_absl::flat_hash_set<y_absl::string_view>& Keywords() { + static const auto* keywords = [] { + auto* keywords = new y_absl::flat_hash_set<y_absl::string_view>(); -void SetIntVar(const Options& options, const TProtoStringType& type, - std::map<TProtoStringType, TProtoStringType>* variables) { - (*variables)[type] = IntTypeName(options, type); + for (const auto keyword : kKeywordList) { + keywords->emplace(keyword); + } + return keywords; + }(); + return *keywords; } -// Returns true if the message can potentially allocate memory for its field. -// This is used to determine if message-owned arena will be useful. -bool AllocExpected(const Descriptor* descriptor) { - return false; +TProtoStringType IntTypeName(const Options& options, y_absl::string_view type) { + return y_absl::StrCat("::NProtoBuf::", type); } -// Describes different approaches to detect non-canonical int32 encoding. Only -// kNever or kAlways is eligible for *simple* verification methods. -enum class VerifyInt32Type { - kCustom, // Only check if field number matches. - kNever, // Do not check. - kAlways, // Always check. -}; -inline VerifySimpleType VerifyInt32TypeToVerifyCustom(VerifyInt32Type t) { - static VerifySimpleType kCustomTypes[] = { - VerifySimpleType::kCustom, VerifySimpleType::kCustomInt32Never, - VerifySimpleType::kCustomInt32Always}; - return kCustomTypes[static_cast<arc_i32>(t) - - static_cast<arc_i32>(VerifyInt32Type::kCustom)]; -} } // namespace @@ -232,86 +231,69 @@ bool IsLazilyVerifiedLazy(const FieldDescriptor* field, return false; } -void SetCommonVars(const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables) { - (*variables)["proto_ns"] = ProtobufNamespace(options); - - // Warning: there is some clever naming/splitting here to avoid extract script - // rewrites. The names of these variables must not be things that the extract - // script will rewrite. That's why we use "CHK" (for example) instead of - // "GOOGLE_CHECK". - if (options.opensource_runtime) { - (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE_PROTOBUF"; - (*variables)["CHK"] = "GOOGLE_CHECK"; - (*variables)["DCHK"] = "GOOGLE_DCHECK"; - } else { - // These values are things the extract script would rewrite if we did not - // split them. It might not strictly matter since we don't generate google3 - // code in open-source. But it's good to prevent surprising things from - // happening. - (*variables)["GOOGLE_PROTOBUF"] = - "GOOGLE3" - "_PROTOBUF"; - (*variables)["CHK"] = - "CH" - "ECK"; - (*variables)["DCHK"] = - "DCH" - "ECK"; - } - - SetIntVar(options, "int8", variables); - SetIntVar(options, "uint8", variables); - SetIntVar(options, "uint32", variables); - SetIntVar(options, "uint64", variables); - SetIntVar(options, "int32", variables); - SetIntVar(options, "int64", variables); - (*variables)["string"] = "TProtoStringType"; +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> MessageVars( + const Descriptor* desc) { + y_absl::string_view prefix = IsMapEntryMessage(desc) ? "" : "_impl_."; + return { + {"any_metadata", y_absl::StrCat(prefix, "_any_metadata_")}, + {"cached_size", y_absl::StrCat(prefix, "_cached_size_")}, + {"extensions", y_absl::StrCat(prefix, "_extensions_")}, + {"has_bits", y_absl::StrCat(prefix, "_has_bits_")}, + {"inlined_string_donated_array", + y_absl::StrCat(prefix, "_inlined_string_donated_")}, + {"oneof_case", y_absl::StrCat(prefix, "_oneof_case_")}, + {"tracker", "Impl_::_tracker_"}, + {"weak_field_map", y_absl::StrCat(prefix, "_weak_field_map_")}, + {"split", y_absl::StrCat(prefix, "_split_")}, + {"cached_split_ptr", "cached_split_ptr"}, + }; } void SetCommonMessageDataVariables( const Descriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { - TProtoStringType prefix = IsMapEntryMessage(descriptor) ? "" : "_impl_."; - (*variables)["any_metadata"] = prefix + "_any_metadata_"; - (*variables)["cached_size"] = prefix + "_cached_size_"; - (*variables)["extensions"] = prefix + "_extensions_"; - (*variables)["has_bits"] = prefix + "_has_bits_"; - (*variables)["inlined_string_donated_array"] = - prefix + "_inlined_string_donated_"; - (*variables)["oneof_case"] = prefix + "_oneof_case_"; - (*variables)["tracker"] = "Impl_::_tracker_"; - (*variables)["weak_field_map"] = prefix + "_weak_field_map_"; - (*variables)["split"] = prefix + "_split_"; - (*variables)["cached_split_ptr"] = "cached_split_ptr"; -} - -void SetUnknownFieldsVariable(const Descriptor* descriptor, - const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables) { - TProtoStringType proto_ns = ProtobufNamespace(options); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + for (auto& pair : MessageVars(descriptor)) { + variables->emplace(pair); + } +} + +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> UnknownFieldsVars( + const Descriptor* desc, const Options& opts) { + TProtoStringType proto_ns = ProtobufNamespace(opts); + TProtoStringType unknown_fields_type; - if (UseUnknownFieldSet(descriptor->file(), options)) { - unknown_fields_type = "::" + proto_ns + "::UnknownFieldSet"; - (*variables)["unknown_fields"] = - "_internal_metadata_.unknown_fields<" + unknown_fields_type + ">(" + - unknown_fields_type + "::default_instance)"; + TProtoStringType default_instance; + if (UseUnknownFieldSet(desc->file(), opts)) { + unknown_fields_type = y_absl::StrCat("::", proto_ns, "::UnknownFieldSet"); + default_instance = y_absl::StrCat(unknown_fields_type, "::default_instance"); } else { unknown_fields_type = - PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING); - (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields<" + - unknown_fields_type + ">(::" + proto_ns + - "::internal::GetEmptyString)"; + PrimitiveTypeName(opts, FieldDescriptor::CPPTYPE_STRING); + default_instance = + y_absl::StrCat("::", proto_ns, "::internal::GetEmptyString"); + } + + return { + {"unknown_fields", + y_absl::Substitute("_internal_metadata_.unknown_fields<$0>($1)", + unknown_fields_type, default_instance)}, + {"unknown_fields_type", unknown_fields_type}, + {"have_unknown_fields", "_internal_metadata_.have_unknown_fields()"}, + {"mutable_unknown_fields", + y_absl::Substitute("_internal_metadata_.mutable_unknown_fields<$0>()", + unknown_fields_type)}, + }; +} + +void SetUnknownFieldsVariable( + const Descriptor* descriptor, const Options& options, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + for (auto& pair : UnknownFieldsVars(descriptor, options)) { + variables->emplace(pair); } - (*variables)["unknown_fields_type"] = unknown_fields_type; - (*variables)["have_unknown_fields"] = - "_internal_metadata_.have_unknown_fields()"; - (*variables)["mutable_unknown_fields"] = - "_internal_metadata_.mutable_unknown_fields<" + unknown_fields_type + - ">()"; } -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, bool cap_next_letter) { TProtoStringType result; // Note: I distrust ctype.h due to locales. @@ -342,7 +324,9 @@ const char kThickSeparator[] = const char kThinSeparator[] = "// -------------------------------------------------------------------\n"; -bool CanInitializeByZeroing(const FieldDescriptor* field) { +bool CanInitializeByZeroing(const FieldDescriptor* field, + const Options& options, + MessageSCCAnalyzer* scc_analyzer) { if (field->is_repeated() || field->is_extension()) return false; switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_ENUM: @@ -361,6 +345,57 @@ bool CanInitializeByZeroing(const FieldDescriptor* field) { return field->default_value_double() == 0; case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool() == false; + case FieldDescriptor::CPPTYPE_MESSAGE: + // Non-repeated, non-lazy message fields are raw pointers initialized to + // null. + return !IsLazy(field, options, scc_analyzer); + default: + return false; + } +} + +bool CanClearByZeroing(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + return field->default_value_enum()->number() == 0; + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() == 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() == 0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() == 0; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() == 0; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() == false; + default: + return false; + } +} + +// Determines if swap can be implemented via memcpy. +bool HasTrivialSwap(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_BOOL: + return true; + case FieldDescriptor::CPPTYPE_MESSAGE: + // Non-repeated, non-lazy message fields are simply raw pointers, so we + // can swap them with memcpy. + return !IsLazy(field, options, scc_analyzer); default: return false; } @@ -369,9 +404,9 @@ bool CanInitializeByZeroing(const FieldDescriptor* field) { TProtoStringType ClassName(const Descriptor* descriptor) { const Descriptor* parent = descriptor->containing_type(); TProtoStringType res; - if (parent) res += ClassName(parent) + "_"; - res += descriptor->name(); - if (IsMapEntryMessage(descriptor)) res += "_DoNotUse"; + if (parent) y_absl::StrAppend(&res, ClassName(parent), "_"); + y_absl::StrAppend(&res, descriptor->name()); + if (IsMapEntryMessage(descriptor)) y_absl::StrAppend(&res, "_DoNotUse"); return ResolveKeyword(res); } @@ -379,8 +414,8 @@ TProtoStringType ClassName(const EnumDescriptor* enum_descriptor) { if (enum_descriptor->containing_type() == nullptr) { return ResolveKeyword(enum_descriptor->name()); } else { - return ClassName(enum_descriptor->containing_type()) + "_" + - enum_descriptor->name(); + return y_absl::StrCat(ClassName(enum_descriptor->containing_type()), "_", + enum_descriptor->name()); } } @@ -403,13 +438,13 @@ TProtoStringType QualifiedClassName(const EnumDescriptor* d) { TProtoStringType ExtensionName(const FieldDescriptor* d) { if (const Descriptor* scope = d->extension_scope()) - return StrCat(ClassName(scope), "::", ResolveKeyword(d->name())); + return y_absl::StrCat(ClassName(scope), "::", ResolveKeyword(d->name())); return ResolveKeyword(d->name()); } TProtoStringType QualifiedExtensionName(const FieldDescriptor* d, const Options& options) { - GOOGLE_DCHECK(d->is_extension()); + Y_ABSL_DCHECK(d->is_extension()); return QualifiedFileLevelSymbol(d->file(), ExtensionName(d), options); } @@ -417,32 +452,38 @@ TProtoStringType QualifiedExtensionName(const FieldDescriptor* d) { return QualifiedExtensionName(d, Options()); } -TProtoStringType Namespace(const TProtoStringType& package) { +TProtoStringType Namespace(y_absl::string_view package) { if (package.empty()) return ""; - return "::" + DotsToColons(package); + return y_absl::StrCat("::", DotsToColons(package)); } +TProtoStringType Namespace(const FileDescriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const FileDescriptor* d, const Options& options) { - TProtoStringType ret = Namespace(d->package()); + TProtoStringType ns = Namespace(d->package()); if (IsWellKnownMessage(d) && options.opensource_runtime) { // Written with string concatenation to prevent rewriting of // ::google::protobuf. - ret = StringReplace(ret, - "::google::" - "protobuf", - "::PROTOBUF_NAMESPACE_ID", false); + constexpr y_absl::string_view prefix = + "::google::" // prevent clang-format reflowing + "protobuf"; + y_absl::string_view new_ns(ns); + y_absl::ConsumePrefix(&new_ns, prefix); + return y_absl::StrCat("::PROTOBUF_NAMESPACE_ID", new_ns); } - return ret; + return ns; } +TProtoStringType Namespace(const Descriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const Descriptor* d, const Options& options) { return Namespace(d->file(), options); } +TProtoStringType Namespace(const FieldDescriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const FieldDescriptor* d, const Options& options) { return Namespace(d->file(), options); } +TProtoStringType Namespace(const EnumDescriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const EnumDescriptor* d, const Options& options) { return Namespace(d->file(), options); } @@ -455,13 +496,13 @@ TProtoStringType DefaultInstanceType(const Descriptor* descriptor, TProtoStringType DefaultInstanceName(const Descriptor* descriptor, const Options& /*options*/, bool split) { - return "_" + ClassName(descriptor, false) + (split ? "__Impl_Split" : "") + - "_default_instance_"; + return y_absl::StrCat("_", ClassName(descriptor, false), + (split ? "__Impl_Split" : ""), "_default_instance_"); } TProtoStringType DefaultInstancePtr(const Descriptor* descriptor, const Options& options, bool split) { - return DefaultInstanceName(descriptor, options, split) + "ptr_"; + return y_absl::StrCat(DefaultInstanceName(descriptor, options, split), "ptr_"); } TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor, @@ -473,7 +514,8 @@ TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor, TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor, const Options& options, bool split) { - return QualifiedDefaultInstanceName(descriptor, options, split) + "ptr_"; + return y_absl::StrCat(QualifiedDefaultInstanceName(descriptor, options, split), + "ptr_"); } TProtoStringType DescriptorTableName(const FileDescriptor* file, @@ -488,60 +530,61 @@ TProtoStringType FileDllExport(const FileDescriptor* file, const Options& option TProtoStringType SuperClassName(const Descriptor* descriptor, const Options& options) { if (!HasDescriptorMethods(descriptor->file(), options)) { - return "::" + ProtobufNamespace(options) + "::MessageLite"; + return y_absl::StrCat("::", ProtobufNamespace(options), "::MessageLite"); } auto simple_base = SimpleBaseClass(descriptor, options); if (simple_base.empty()) { - return "::" + ProtobufNamespace(options) + "::Message"; + return y_absl::StrCat("::", ProtobufNamespace(options), "::Message"); } - return "::" + ProtobufNamespace(options) + "::internal::" + simple_base; + return y_absl::StrCat("::", ProtobufNamespace(options), + "::internal::", simple_base); } -TProtoStringType ResolveKeyword(const TProtoStringType& name) { - if (kKeywords.count(name) > 0) { - return name + "_"; +TProtoStringType ResolveKeyword(y_absl::string_view name) { + if (Keywords().count(name) > 0) { + return y_absl::StrCat(name, "_"); } - return name; + return TProtoStringType(name); } TProtoStringType FieldName(const FieldDescriptor* field) { TProtoStringType result = field->name(); - LowerString(&result); - if (kKeywords.count(result) > 0) { + y_absl::AsciiStrToLower(&result); + if (Keywords().count(result) > 0) { result.append("_"); } return result; } TProtoStringType FieldMemberName(const FieldDescriptor* field, bool split) { - StringPiece prefix = + y_absl::string_view prefix = IsMapEntryMessage(field->containing_type()) ? "" : "_impl_."; - StringPiece split_prefix = split ? "_split_->" : ""; + y_absl::string_view split_prefix = split ? "_split_->" : ""; if (field->real_containing_oneof() == nullptr) { - return StrCat(prefix, split_prefix, FieldName(field), "_"); + return y_absl::StrCat(prefix, split_prefix, FieldName(field), "_"); } // Oneof fields are never split. - GOOGLE_CHECK(!split); - return StrCat(prefix, field->containing_oneof()->name(), "_.", + Y_ABSL_CHECK(!split); + return y_absl::StrCat(prefix, field->containing_oneof()->name(), "_.", FieldName(field), "_"); } TProtoStringType OneofCaseConstantName(const FieldDescriptor* field) { - GOOGLE_DCHECK(field->containing_oneof()); + Y_ABSL_DCHECK(field->containing_oneof()); TProtoStringType field_name = UnderscoresToCamelCase(field->name(), true); - return "k" + field_name; + return y_absl::StrCat("k", field_name); } TProtoStringType QualifiedOneofCaseConstantName(const FieldDescriptor* field) { - GOOGLE_DCHECK(field->containing_oneof()); + Y_ABSL_DCHECK(field->containing_oneof()); const TProtoStringType qualification = QualifiedClassName(field->containing_type()); - return StrCat(qualification, "::", OneofCaseConstantName(field)); + return y_absl::StrCat(qualification, "::", OneofCaseConstantName(field)); } TProtoStringType EnumValueName(const EnumValueDescriptor* enum_value) { TProtoStringType result = enum_value->name(); - if (kKeywords.count(result) > 0) { + if (Keywords().count(result) > 0) { result.append("_"); } return result; @@ -567,13 +610,13 @@ int EstimateAlignmentSize(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_MESSAGE: return 8; } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return -1; // Make compiler happy. } TProtoStringType FieldConstantName(const FieldDescriptor* field) { TProtoStringType field_name = UnderscoresToCamelCase(field->name(), true); - TProtoStringType result = "k" + field_name + "FieldNumber"; + TProtoStringType result = y_absl::StrCat("k", field_name, "FieldNumber"); if (!field->is_extension() && field->containing_type()->FindFieldByCamelcaseName( @@ -581,7 +624,7 @@ TProtoStringType FieldConstantName(const FieldDescriptor* field) { // This field's camelcase name is not unique. As a hack, add the field // number to the constant name. This makes the constant rather useless, // but what can we do? - result += "_" + StrCat(field->number()); + y_absl::StrAppend(&result, "_", field->number()); } return result; @@ -594,7 +637,7 @@ TProtoStringType FieldMessageTypeName(const FieldDescriptor* field, return QualifiedClassName(field->message_type(), options); } -TProtoStringType StripProto(const TProtoStringType& filename) { +TProtoStringType StripProto(y_absl::string_view filename) { /* * TODO(github/georgthegreat) remove this proxy method * once Google's internal codebase will become ready @@ -605,13 +648,13 @@ TProtoStringType StripProto(const TProtoStringType& filename) { const char* PrimitiveTypeName(FieldDescriptor::CppType type) { switch (type) { case FieldDescriptor::CPPTYPE_INT32: - return "arc_i32"; + return "::arc_i32"; case FieldDescriptor::CPPTYPE_INT64: - return "arc_i64"; + return "::arc_i64"; case FieldDescriptor::CPPTYPE_UINT32: - return "arc_ui32"; + return "::arc_ui32"; case FieldDescriptor::CPPTYPE_UINT64: - return "arc_ui64"; + return "::arc_ui64"; case FieldDescriptor::CPPTYPE_DOUBLE: return "double"; case FieldDescriptor::CPPTYPE_FLOAT: @@ -629,7 +672,7 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type) { // CppTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return nullptr; } @@ -661,7 +704,7 @@ TProtoStringType PrimitiveTypeName(const Options& options, // CppTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } @@ -709,7 +752,7 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { // No default because we want the compiler to complain if any new // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } @@ -717,9 +760,9 @@ TProtoStringType Int32ToString(int number) { if (number == std::numeric_limits<arc_i32>::min()) { // This needs to be special-cased, see explanation here: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 - return StrCat(number + 1, " - 1"); + return y_absl::StrCat(number + 1, " - 1"); } else { - return StrCat(number); + return y_absl::StrCat(number); } } @@ -727,13 +770,13 @@ static TProtoStringType Int64ToString(arc_i64 number) { if (number == std::numeric_limits<arc_i64>::min()) { // This needs to be special-cased, see explanation here: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 - return StrCat("arc_i64{", number + 1, "} - 1"); + return y_absl::StrCat("::arc_i64{", number + 1, "} - 1"); } - return StrCat("arc_i64{", number, "}"); + return y_absl::StrCat("::arc_i64{", number, "}"); } static TProtoStringType UInt64ToString(arc_ui64 number) { - return StrCat("arc_ui64{", number, "u}"); + return y_absl::StrCat("::arc_ui64{", number, "u}"); } TProtoStringType DefaultValue(const FieldDescriptor* field) { @@ -745,7 +788,7 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie case FieldDescriptor::CPPTYPE_INT32: return Int32ToString(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return StrCat(field->default_value_uint32()) + "u"; + return y_absl::StrCat(field->default_value_uint32(), "u"); case FieldDescriptor::CPPTYPE_INT64: return Int64ToString(field->default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: @@ -759,7 +802,7 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie } else if (value != value) { return "std::numeric_limits<double>::quiet_NaN()"; } else { - return SimpleDtoa(value); + return io::SimpleDtoa(value); } } case FieldDescriptor::CPPTYPE_FLOAT: { @@ -771,7 +814,7 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie } else if (value != value) { return "std::numeric_limits<float>::quiet_NaN()"; } else { - TProtoStringType float_value = SimpleFtoa(value); + TProtoStringType float_value = io::SimpleFtoa(value); // If floating point value contains a period (.) or an exponent // (either E or e), then append suffix 'f' to make it a float // literal. @@ -786,73 +829,73 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie case FieldDescriptor::CPPTYPE_ENUM: // Lazy: Generate a static_cast because we don't have a helper function // that constructs the full name of an enum value. - return strings::Substitute( + return y_absl::Substitute( "static_cast< $0 >($1)", ClassName(field->enum_type(), true), Int32ToString(field->default_value_enum()->number())); case FieldDescriptor::CPPTYPE_STRING: - return "\"" + - EscapeTrigraphs(CEscape(field->default_value_string())) + - "\""; + return y_absl::StrCat( + "\"", EscapeTrigraphs(y_absl::CEscape(field->default_value_string())), + "\""); case FieldDescriptor::CPPTYPE_MESSAGE: - return "*" + FieldMessageTypeName(field, options) + - "::internal_default_instance()"; + return y_absl::StrCat("*", FieldMessageTypeName(field, options), + "::internal_default_instance()"); } // Can't actually get here; make compiler happy. (We could add a default // case above but then we wouldn't get the nice compiler warning when a // new type is added.) - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } // Convert a file name into a valid identifier. -TProtoStringType FilenameIdentifier(const TProtoStringType& filename) { +TProtoStringType FilenameIdentifier(y_absl::string_view filename) { TProtoStringType result; for (int i = 0; i < filename.size(); i++) { - if (ascii_isalnum(filename[i])) { + if (y_absl::ascii_isalnum(filename[i])) { result.push_back(filename[i]); } else { // Not alphanumeric. To avoid any possibility of name conflicts we // use the hex code for the character. - StrAppend(&result, "_", - strings::Hex(static_cast<uint8_t>(filename[i]))); + y_absl::StrAppend(&result, "_", + y_absl::Hex(static_cast<uint8_t>(filename[i]))); } } return result; } -TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename, +TProtoStringType UniqueName(y_absl::string_view name, y_absl::string_view filename, const Options& options) { - return name + "_" + FilenameIdentifier(filename); + return y_absl::StrCat(name, "_", FilenameIdentifier(filename)); } // Return the qualified C++ name for a file level symbol. TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file, - const TProtoStringType& name, + y_absl::string_view name, const Options& options) { if (file->package().empty()) { - return StrCat("::", name); + return y_absl::StrCat("::", name); } - return StrCat(Namespace(file, options), "::", name); + return y_absl::StrCat(Namespace(file, options), "::", name); } // Escape C++ trigraphs by escaping question marks to \? -TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape) { - return StringReplace(to_escape, "?", "\\?", true); +TProtoStringType EscapeTrigraphs(y_absl::string_view to_escape) { + return y_absl::StrReplaceAll(to_escape, {{"?", "\\?"}}); } // Escaped function name to eliminate naming conflict. TProtoStringType SafeFunctionName(const Descriptor* descriptor, const FieldDescriptor* field, - const TProtoStringType& prefix) { + y_absl::string_view prefix) { // Do not use FieldName() since it will escape keywords. TProtoStringType name = field->name(); - LowerString(&name); - TProtoStringType function_name = prefix + name; + y_absl::AsciiStrToLower(&name); + TProtoStringType function_name = y_absl::StrCat(prefix, name); if (descriptor->FindFieldByName(function_name)) { // Single underscore will also make it conflicting with the private data // member. We use double underscore to escape function names. function_name.append("__"); - } else if (kKeywords.count(name) > 0) { + } else if (Keywords().count(name) > 0) { // If the field name is a keyword, we append the underscore back to keep it // consistent with other function names. function_name.append("_"); @@ -860,6 +903,9 @@ TProtoStringType SafeFunctionName(const Descriptor* descriptor, return function_name; } +bool IsProfileDriven(const Options& options) { + return options.access_info_map != nullptr; +} bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options) { (void)descriptor; @@ -907,6 +953,13 @@ bool HasLazyFields(const FileDescriptor* file, const Options& options, bool ShouldSplit(const Descriptor*, const Options&) { return false; } bool ShouldSplit(const FieldDescriptor*, const Options&) { return false; } +bool ShouldForceAllocationOnConstruction(const Descriptor* desc, + const Options& options) { + (void)desc; + (void)options; + return false; +} + static bool HasRepeatedFields(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); ++i) { if (descriptor->field(i)->label() == FieldDescriptor::LABEL_REPEATED) { @@ -1045,7 +1098,7 @@ bool ShouldVerify(const FileDescriptor* file, const Options& options, bool IsUtf8String(const FieldDescriptor* field) { return IsProto3(field->file()) && - field->type() == FieldDescriptor::TYPE_STRING; + field->type() == FieldDescriptor::TYPE_STRING; } VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor) { @@ -1069,13 +1122,13 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return true; } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return false; } FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, const Options& options) { - GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); + Y_ABSL_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); if (options.opensource_runtime) { // Open-source protobuf release only supports STRING ctype. return FieldOptions::STRING; @@ -1095,7 +1148,7 @@ bool IsAnyMessage(const Descriptor* descriptor, const Options& options) { } bool IsWellKnownMessage(const FileDescriptor* file) { - static const std::unordered_set<TProtoStringType> well_known_files{ + static const auto* well_known_files = new y_absl::flat_hash_set<TProtoStringType>{ "google/protobuf/any.proto", "google/protobuf/api.proto", "google/protobuf/compiler/plugin.proto", @@ -1109,94 +1162,127 @@ bool IsWellKnownMessage(const FileDescriptor* file) { "google/protobuf/type.proto", "google/protobuf/wrappers.proto", }; - return well_known_files.find(file->name()) != well_known_files.end(); -} - -static bool FieldEnforceUtf8(const FieldDescriptor* field, - const Options& options) { - return true; + return well_known_files->find(file->name()) != well_known_files->end(); } -static bool FileUtf8Verification(const FileDescriptor* file, - const Options& options) { - return true; -} +void NamespaceOpener::ChangeTo(y_absl::string_view name) { + std::vector<TProtoStringType> new_stack = + y_absl::StrSplit(name, "::", y_absl::SkipEmpty()); + size_t len = std::min(name_stack_.size(), new_stack.size()); + size_t common_idx = 0; + while (common_idx < len) { + if (name_stack_[common_idx] != new_stack[common_idx]) { + break; + } + ++common_idx; + } -// Which level of UTF-8 enforcemant is placed on this file. -Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, - const Options& options) { - if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && - FieldEnforceUtf8(field, options)) { - return Utf8CheckMode::kStrict; - } else if (GetOptimizeFor(field->file(), options) != - FileOptions::LITE_RUNTIME && - FileUtf8Verification(field->file(), options)) { - return Utf8CheckMode::kVerify; - } else { - return Utf8CheckMode::kNone; + for (size_t i = name_stack_.size(); i > common_idx; i--) { + const auto& ns = name_stack_[i - 1]; + if (ns == "PROTOBUF_NAMESPACE_ID") { + p_->Emit(R"cc( + PROTOBUF_NAMESPACE_CLOSE + )cc"); + } else { + p_->Emit({{"ns", ns}}, R"( + } // namespace $ns$ + )"); + } + } + for (size_t i = common_idx; i < new_stack.size(); ++i) { + const auto& ns = new_stack[i]; + if (ns == "PROTOBUF_NAMESPACE_ID") { + p_->Emit(R"cc( + PROTOBUF_NAMESPACE_OPEN + )cc"); + } else { + p_->Emit({{"ns", ns}}, R"( + namespace $ns$ { + )"); + } } + + name_stack_ = std::move(new_stack); } -static void GenerateUtf8CheckCode(const FieldDescriptor* field, +static void GenerateUtf8CheckCode(io::Printer* p, const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, - const char* strict_function, - const char* verify_function, - const Formatter& format) { - switch (GetUtf8CheckMode(field, options)) { - case Utf8CheckMode::kStrict: { + y_absl::string_view params, + y_absl::string_view strict_function, + y_absl::string_view verify_function) { + if (field->type() != FieldDescriptor::TYPE_STRING) return; + + auto v = p->WithVars({ + {"params", params}, + {"Strict", strict_function}, + {"Verify", verify_function}, + }); + + bool is_lite = + GetOptimizeFor(field->file(), options) == FileOptions::LITE_RUNTIME; + switch (internal::cpp::GetUtf8CheckMode(field, is_lite)) { + case internal::cpp::Utf8CheckMode::kStrict: if (for_parse) { - format("DO_("); - } - format("::$proto_ns$::internal::WireFormatLite::$1$(\n", strict_function); - format.Indent(); - format(parameters); - if (for_parse) { - format("::$proto_ns$::internal::WireFormatLite::PARSE,\n"); + p->Emit(R"cc( + DO_($pbi$::WireFormatLite::$Strict$( + $params$ $pbi$::WireFormatLite::PARSE, "$pkg.Msg.field$")); + )cc"); } else { - format("::$proto_ns$::internal::WireFormatLite::SERIALIZE,\n"); + p->Emit(R"cc( + $pbi$::WireFormatLite::$Strict$( + $params$ $pbi$::WireFormatLite::SERIALIZE, "$pkg.Msg.field$"); + )cc"); } - format("\"$1$\")", field->full_name()); - if (for_parse) { - format(")"); - } - format(";\n"); - format.Outdent(); break; - } - case Utf8CheckMode::kVerify: { - format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function); - format.Indent(); - format(parameters); + + case internal::cpp::Utf8CheckMode::kVerify: if (for_parse) { - format("::$proto_ns$::internal::WireFormat::PARSE,\n"); + p->Emit(R"cc( + $pbi$::WireFormat::$Verify$($params$ $pbi$::WireFormat::PARSE, + "$pkg.Msg.field$"); + )cc"); } else { - format("::$proto_ns$::internal::WireFormat::SERIALIZE,\n"); + p->Emit(R"cc( + $pbi$::WireFormat::$Verify$($params$ $pbi$::WireFormat::SERIALIZE, + "$pkg.Msg.field$"); + )cc"); } - format("\"$1$\");\n", field->full_name()); - format.Outdent(); break; - } - case Utf8CheckMode::kNone: + + case internal::cpp::Utf8CheckMode::kNone: break; } } void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, + y_absl::string_view parameters, const Formatter& format) { - GenerateUtf8CheckCode(field, options, for_parse, parameters, - "VerifyUtf8String", "VerifyUTF8StringNamedField", - format); + GenerateUtf8CheckCode(format.printer(), field, options, for_parse, parameters, + "VerifyUtf8String", "VerifyUTF8StringNamedField"); } void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, + y_absl::string_view parameters, const Formatter& format) { - GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8Cord", - "VerifyUTF8CordNamedField", format); + GenerateUtf8CheckCode(format.printer(), field, options, for_parse, parameters, + "VerifyUtf8Cord", "VerifyUTF8CordNamedField"); +} + +void GenerateUtf8CheckCodeForString(io::Printer* p, + const FieldDescriptor* field, + const Options& options, bool for_parse, + y_absl::string_view parameters) { + GenerateUtf8CheckCode(p, field, options, for_parse, parameters, + "VerifyUtf8String", "VerifyUTF8StringNamedField"); +} + +void GenerateUtf8CheckCodeForCord(io::Printer* p, const FieldDescriptor* field, + const Options& options, bool for_parse, + y_absl::string_view parameters) { + GenerateUtf8CheckCode(p, field, options, for_parse, parameters, + "VerifyUtf8Cord", "VerifyUTF8CordNamedField"); } void FlattenMessagesInFile(const FileDescriptor* file, @@ -1243,7 +1329,9 @@ bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, } MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { - if (analysis_cache_.count(scc)) return analysis_cache_[scc]; + auto it = analysis_cache_.find(scc); + if (it != analysis_cache_.end()) return it->second; + MessageAnalysis result; if (UsingImplicitWeakFields(scc->GetFile(), options_)) { result.contains_weak = true; @@ -1298,7 +1386,7 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { // in the graph, the graph should be a DAG. Hence we shouldn't need to mark // nodes visited as we can never return to them. By inserting them here // we will go in an infinite loop if the SCC is not correct. - return analysis_cache_[scc] = result; + return analysis_cache_[scc] = std::move(result); } void ListAllFields(const Descriptor* d, @@ -1341,23 +1429,26 @@ void ListAllTypesForServices(const FileDescriptor* fd, } } -bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename, +bool GetBootstrapBasename(const Options& options, y_absl::string_view basename, TProtoStringType* bootstrap_basename) { if (options.opensource_runtime) { return false; } - std::unordered_map<TProtoStringType, TProtoStringType> bootstrap_mapping{ - {"net/proto2/proto/descriptor", - "third_party/protobuf/descriptor"}, - {"net/proto2/compiler/proto/plugin", - "net/proto2/compiler/proto/plugin"}, - {"net/proto2/compiler/proto/profile", - "net/proto2/compiler/proto/profile_bootstrap"}, - }; - auto iter = bootstrap_mapping.find(basename); - if (iter == bootstrap_mapping.end()) { - *bootstrap_basename = basename; + static const auto* bootstrap_mapping = + // TODO(b/242858704) Replace these with string_view once we remove + // StringPiece. + new y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>{ + {"net/proto2/proto/descriptor", + "third_party/protobuf/descriptor"}, + {"net/proto2/compiler/proto/plugin", + "net/proto2/compiler/proto/plugin"}, + {"net/proto2/compiler/proto/profile", + "net/proto2/compiler/proto/profile_bootstrap"}, + }; + auto iter = bootstrap_mapping->find(basename); + if (iter == bootstrap_mapping->end()) { + *bootstrap_basename = TProtoStringType(basename); return false; } else { *bootstrap_basename = iter->second; @@ -1381,70 +1472,64 @@ bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, // Adjust basename, but don't abort code generation. *basename = bootstrap_basename; return false; - } else { - const TProtoStringType& forward_to_basename = bootstrap_basename; - - // Generate forwarding headers and empty .pb.cc. - { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(*basename + ".pb.h")); - io::Printer printer(output.get(), '$', nullptr); - printer.Print( - "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n" - "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n" - "#include \"$forward_to_basename$.pb.h\" // IWYU pragma: export\n" - "#endif // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n", - "forward_to_basename", forward_to_basename, "filename_identifier", - FilenameIdentifier(*basename)); - - if (!options.opensource_runtime) { - // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG - // protocoltype is SWIG'ed and we need to forward - if (*basename == "net/proto/protocoltype") { - printer.Print( - "#ifdef SWIG\n" - "%include \"$forward_to_basename$.pb.h\"\n" - "#endif // SWIG\n", - "forward_to_basename", forward_to_basename); - } - } - } - - { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(*basename + ".proto.h")); - io::Printer printer(output.get(), '$', nullptr); - printer.Print( - "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n" - "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n" - "#include \"$forward_to_basename$.proto.h\" // IWYU pragma: " - "export\n" - "#endif // " - "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n", - "forward_to_basename", forward_to_basename, "filename_identifier", - FilenameIdentifier(*basename)); - } - - { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(*basename + ".pb.cc")); - io::Printer printer(output.get(), '$', nullptr); - printer.Print("\n"); - } - - { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(*basename + ".pb.h.meta")); - } - - { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(*basename + ".proto.h.meta")); - } - - // Abort code generation. - return true; } + + auto pb_h = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".pb.h"))); + + io::Printer p(pb_h.get()); + p.Emit( + { + {"fwd_to", bootstrap_basename}, + {"file", FilenameIdentifier(*basename)}, + {"fwd_to_suffix", options.opensource_runtime ? "pb" : "proto"}, + {"swig_evil", + [&] { + if (options.opensource_runtime) { + return; + } + p.Emit(R"( + #ifdef SWIG + %include "$fwd_to$.pb.h" + #endif // SWIG + )"); + }}, + }, + R"( + #ifndef PROTOBUF_INCLUDED_$file$_FORWARD_PB_H + #define PROTOBUF_INCLUDED_$file$_FORWARD_PB_H + #include "$fwd_to$.$fwd_to_suffix$.h" // IWYU pragma: export + #endif // PROTOBUF_INCLUDED_$file$_FORWARD_PB_H + $swig_evil$; + )"); + + auto proto_h = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".proto.h"))); + io::Printer(proto_h.get()) + .Emit( + { + {"fwd_to", bootstrap_basename}, + {"file", FilenameIdentifier(*basename)}, + }, + R"( + #ifndef PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H + #define PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H + #include "$fwd_to$.proto.h" // IWYU pragma: export + #endif // PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H + )"); + + auto pb_cc = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".pb.cc"))); + io::Printer(pb_cc.get()).PrintRaw("\n"); + + (void)y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".pb.h.meta"))); + + (void)y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".proto.h.meta"))); + + // Abort code generation. + return true; } static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file, @@ -1492,9 +1577,18 @@ static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file, static bool HasBootstrapProblem(const FileDescriptor* file, const Options& options, bool* has_opt_codesize_extension) { - static auto& cache = *new std::unordered_map<const FileDescriptor*, bool>; - auto it = cache.find(file); - if (it != cache.end()) return it->second; + struct BoostrapGlobals { + y_absl::Mutex mutex; + y_absl::flat_hash_set<const FileDescriptor*> cached Y_ABSL_GUARDED_BY(mutex); + y_absl::flat_hash_set<const FileDescriptor*> non_cached + Y_ABSL_GUARDED_BY(mutex); + }; + static auto& bootstrap_cache = *new BoostrapGlobals(); + + y_absl::MutexLock lock(&bootstrap_cache.mutex); + if (bootstrap_cache.cached.contains(file)) return true; + if (bootstrap_cache.non_cached.contains(file)) return false; + // In order to build the data structures for the reflective parse, it needs // to parse the serialized descriptor describing all the messages defined in // this file. Obviously this presents a bootstrap problem for descriptor @@ -1530,9 +1624,13 @@ static bool HasBootstrapProblem(const FileDescriptor* file, Message* fd_proto = factory.GetPrototype(fd_proto_descriptor)->New(); fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString()); - bool& res = cache[file]; - res = HasExtensionFromFile(*fd_proto, file, options, - has_opt_codesize_extension); + bool res = HasExtensionFromFile(*fd_proto, file, options, + has_opt_codesize_extension); + if (res) { + bootstrap_cache.cached.insert(file); + } else { + bootstrap_cache.non_cached.insert(file); + } delete fd_proto; return res; } @@ -1557,38 +1655,21 @@ FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, case EnforceOptimizeMode::kNoEnforcement: if (file->options().optimize_for() == FileOptions::CODE_SIZE) { if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) { - GOOGLE_LOG(WARNING) << "Proto states optimize_for = CODE_SIZE, but we " - "cannot honor that because it contains custom option " - "extensions defined in the same proto."; + Y_ABSL_LOG(WARNING) + << "Proto states optimize_for = CODE_SIZE, but we " + "cannot honor that because it contains custom option " + "extensions defined in the same proto."; return FileOptions::SPEED; } } return file->options().optimize_for(); } - GOOGLE_LOG(FATAL) << "Unknown optimization enforcement requested."; + Y_ABSL_LOG(FATAL) << "Unknown optimization enforcement requested."; // The phony return below serves to silence a warning from GCC 8. return FileOptions::SPEED; } -inline bool IsMessageOwnedArenaEligible(const Descriptor* desc, - const Options& options) { - return GetOptimizeFor(desc->file(), options) != FileOptions::LITE_RUNTIME && - !options.bootstrap && !options.opensource_runtime && - AllocExpected(desc); -} - -bool EnableMessageOwnedArena(const Descriptor* desc, const Options& options) { - (void)desc; - (void)options; - return false; -} - -bool EnableMessageOwnedArenaTrial(const Descriptor* desc, - const Options& options) { - return false; -} - bool HasMessageFieldOrExtension(const Descriptor* desc) { if (desc->extension_range_count() > 0) return true; for (const auto* f : FieldRange(desc)) { @@ -1597,6 +1678,21 @@ bool HasMessageFieldOrExtension(const Descriptor* desc) { return false; } +std::vector<io::Printer::Sub> AnnotatedAccessors( + const FieldDescriptor* field, y_absl::Span<const y_absl::string_view> prefixes, + y_absl::optional<google::protobuf::io::AnnotationCollector::Semantic> semantic) { + auto field_name = FieldName(field); + + std::vector<io::Printer::Sub> vars; + for (auto prefix : prefixes) { + vars.push_back(io::Printer::Sub(y_absl::StrCat(prefix, "name"), + y_absl::StrCat(prefix, field_name)) + .AnnotatedAs({field, semantic})); + } + + return vars; +} + } // namespace cpp } // namespace compiler } // namespace protobuf |