summaryrefslogtreecommitdiffstats
path: root/contrib/libs/protoc/src/google/protobuf/compiler/cpp
diff options
context:
space:
mode:
authormikhnenko <[email protected]>2024-06-30 20:16:52 +0300
committermikhnenko <[email protected]>2024-06-30 20:28:14 +0300
commitb91a38fe11269c505fec071351a68e568768e6e8 (patch)
tree07d43bf92eee00e2fce98bdbf698f135386995c1 /contrib/libs/protoc/src/google/protobuf/compiler/cpp
parentb21e05a2e32e36ae9cc9826acf98084ca4b52d7d (diff)
Update protobuf to 3.21.2
a628f0376085fcf46dc6d24629f2a7dacb91ae79
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/cpp')
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h1027
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum.cc)6
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum.h)2
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum_field.cc)75
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum_field.h)19
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_extension.cc)6
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_extension.h)2
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc)58
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.h)39
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_file.cc)83
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_file.h)6
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_generator.cc)14
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_generator.h)0
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.cc)140
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h1065
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_map_field.cc)43
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_map_field.h)9
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message.cc)830
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message.h)20
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_field.cc)80
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_field.h)13
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h)2
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_names.h)10
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_options.h)5
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc)4
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h)2
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc)64
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h)4
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc)79
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_primitive_field.h)19
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_service.cc)4
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_service.h)2
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_string_field.cc)98
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_string_field.h)14
34 files changed, 2314 insertions, 1530 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h
index f7735da12f0..fe2ff1369a1 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -1,1026 +1 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: [email protected] (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
-#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
-
-#include <algorithm>
-#include <cstdint>
-#include <iterator>
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/cpp/cpp_names.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace cpp {
-
-enum class ArenaDtorNeeds { kNone = 0, kOnDemand = 1, kRequired = 2 };
-
-inline TProtoStringType ProtobufNamespace(const Options& /* options */) {
- return "PROTOBUF_NAMESPACE_ID";
-}
-
-inline TProtoStringType MacroPrefix(const Options& /* options */) {
- return "GOOGLE_PROTOBUF";
-}
-
-inline TProtoStringType DeprecatedAttribute(const Options& /* options */,
- const FieldDescriptor* d) {
- return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : "";
-}
-
-inline TProtoStringType DeprecatedAttribute(const Options& /* options */,
- const EnumValueDescriptor* d) {
- return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : "";
-}
-
-// Commonly-used separator comments. Thick is a line of '=', thin is a line
-// of '-'.
-extern const char kThickSeparator[];
-extern const char kThinSeparator[];
-
-void SetCommonVars(const Options& options,
- std::map<TProtoStringType, TProtoStringType>* variables);
-
-// Variables to access message data from the message scope.
-void SetCommonMessageDataVariables(
- std::map<TProtoStringType, TProtoStringType>* variables);
-
-void SetUnknownFieldsVariable(const Descriptor* descriptor,
- const Options& options,
- std::map<TProtoStringType, TProtoStringType>* variables);
-
-bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename,
- TProtoStringType* bootstrap_basename);
-bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
- bool bootstrap_flag, TProtoStringType* basename);
-bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
-
-// Name space of the proto file. This namespace is such that the string
-// "<namespace>::some_name" is the correct fully qualified namespace.
-// This means if the package is empty the namespace is "", and otherwise
-// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
-TProtoStringType Namespace(const FileDescriptor* d, const Options& options);
-TProtoStringType Namespace(const Descriptor* d, const Options& options);
-TProtoStringType Namespace(const FieldDescriptor* d, const Options& options);
-TProtoStringType Namespace(const EnumDescriptor* d, const Options& options);
-
-// Returns true if it's safe to reset "field" to zero.
-bool CanInitializeByZeroing(const FieldDescriptor* field);
-
-TProtoStringType ClassName(const Descriptor* descriptor);
-TProtoStringType ClassName(const EnumDescriptor* enum_descriptor);
-
-TProtoStringType QualifiedClassName(const Descriptor* d, const Options& options);
-TProtoStringType QualifiedClassName(const EnumDescriptor* d, const Options& options);
-
-TProtoStringType QualifiedClassName(const Descriptor* d);
-TProtoStringType QualifiedClassName(const EnumDescriptor* d);
-
-// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
-// unreadable at the callsite.
-// Returns the non-nested type name for the given type. If "qualified" is
-// true, prefix the type with the full namespace. For example, if you had:
-// package foo.bar;
-// message Baz { message Qux {} }
-// Then the qualified ClassName for Qux would be:
-// ::foo::bar::Baz_Qux
-// While the non-qualified version would be:
-// Baz_Qux
-inline TProtoStringType ClassName(const Descriptor* descriptor, bool qualified) {
- return qualified ? QualifiedClassName(descriptor, Options())
- : ClassName(descriptor);
-}
-
-inline TProtoStringType ClassName(const EnumDescriptor* descriptor, bool qualified) {
- return qualified ? QualifiedClassName(descriptor, Options())
- : ClassName(descriptor);
-}
-
-// Returns the extension name prefixed with the class name if nested but without
-// the package name.
-TProtoStringType ExtensionName(const FieldDescriptor* d);
-
-TProtoStringType QualifiedExtensionName(const FieldDescriptor* d,
- const Options& options);
-TProtoStringType QualifiedExtensionName(const FieldDescriptor* d);
-
-// Type name of default instance.
-TProtoStringType DefaultInstanceType(const Descriptor* descriptor,
- const Options& options);
-
-// Non-qualified name of the default_instance of this message.
-TProtoStringType DefaultInstanceName(const Descriptor* descriptor,
- const Options& options);
-
-// Non-qualified name of the default instance pointer. This is used only for
-// implicit weak fields, where we need an extra indirection.
-TProtoStringType DefaultInstancePtr(const Descriptor* descriptor,
- const Options& options);
-
-// Fully qualified name of the default_instance of this message.
-TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor,
- const Options& options);
-
-// Fully qualified name of the default instance pointer.
-TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor,
- const Options& options);
-
-// DescriptorTable variable name.
-TProtoStringType DescriptorTableName(const FileDescriptor* file,
- const Options& options);
-
-// When declaring symbol externs from another file, this macro will supply the
-// dllexport needed for the target file, if any.
-TProtoStringType FileDllExport(const FileDescriptor* file, const Options& options);
-
-// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
-TProtoStringType SuperClassName(const Descriptor* descriptor,
- const Options& options);
-
-// Adds an underscore if necessary to prevent conflicting with a keyword.
-TProtoStringType ResolveKeyword(const TProtoStringType& name);
-
-// Get the (unqualified) name that should be used for this field in C++ code.
-// The name is coerced to lower-case to emulate proto1 behavior. People
-// should be using lowercase-with-underscores style for proto field names
-// anyway, so normally this just returns field->name().
-TProtoStringType FieldName(const FieldDescriptor* field);
-
-// Returns the (unqualified) private member name for this field in C++ code.
-TProtoStringType FieldMemberName(const FieldDescriptor* field);
-
-// Returns an estimate of the compiler's alignment for the field. This
-// can't guarantee to be correct because the generated code could be compiled on
-// different systems with different alignment rules. The estimates below assume
-// 64-bit pointers.
-int EstimateAlignmentSize(const FieldDescriptor* field);
-
-// Get the unqualified name that should be used for a field's field
-// number constant.
-TProtoStringType FieldConstantName(const FieldDescriptor* field);
-
-// Returns the scope where the field was defined (for extensions, this is
-// different from the message type to which the field applies).
-inline const Descriptor* FieldScope(const FieldDescriptor* field) {
- return field->is_extension() ? field->extension_scope()
- : field->containing_type();
-}
-
-// Returns the fully-qualified type name field->message_type(). Usually this
-// is just ClassName(field->message_type(), true);
-TProtoStringType FieldMessageTypeName(const FieldDescriptor* field,
- const Options& options);
-
-// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
-const char* PrimitiveTypeName(FieldDescriptor::CppType type);
-TProtoStringType PrimitiveTypeName(const Options& options,
- FieldDescriptor::CppType type);
-
-// Get the declared type name in CamelCase format, as is used e.g. for the
-// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
-const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
-
-// Return the code that evaluates to the number when compiled.
-TProtoStringType Int32ToString(int number);
-
-// Get code that evaluates to the field's default value.
-TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* field);
-
-// Compatibility function for callers outside proto2.
-TProtoStringType DefaultValue(const FieldDescriptor* field);
-
-// Convert a file name into a valid identifier.
-TProtoStringType FilenameIdentifier(const TProtoStringType& filename);
-
-// For each .proto file generates a unique name. To prevent collisions of
-// symbols in the global namespace
-TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename,
- const Options& options);
-inline TProtoStringType UniqueName(const TProtoStringType& name, const FileDescriptor* d,
- const Options& options) {
- return UniqueName(name, d->name(), options);
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d,
- const Options& options) {
- return UniqueName(name, d->file(), options);
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name, const EnumDescriptor* d,
- const Options& options) {
- return UniqueName(name, d->file(), options);
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name,
- const ServiceDescriptor* d,
- const Options& options) {
- return UniqueName(name, d->file(), options);
-}
-
-// Versions for call sites that only support the internal runtime (like proto1
-// support).
-inline Options InternalRuntimeOptions() {
- Options options;
- options.opensource_runtime = false;
- return options;
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name,
- const TProtoStringType& filename) {
- return UniqueName(name, filename, InternalRuntimeOptions());
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name,
- const FileDescriptor* d) {
- return UniqueName(name, d->name(), InternalRuntimeOptions());
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d) {
- return UniqueName(name, d->file(), InternalRuntimeOptions());
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name,
- const EnumDescriptor* d) {
- return UniqueName(name, d->file(), InternalRuntimeOptions());
-}
-inline TProtoStringType UniqueName(const TProtoStringType& name,
- const ServiceDescriptor* d) {
- return UniqueName(name, d->file(), InternalRuntimeOptions());
-}
-
-// Return the qualified C++ name for a file level symbol.
-TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file,
- const TProtoStringType& name,
- const Options& options);
-
-// Escape C++ trigraphs by escaping question marks to \?
-TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape);
-
-// Escaped function name to eliminate naming conflict.
-TProtoStringType SafeFunctionName(const Descriptor* descriptor,
- const FieldDescriptor* field,
- const TProtoStringType& prefix);
-
-// Returns true if generated messages have public unknown fields accessors
-inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
- return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
-}
-
-// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
-FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
- const Options& options);
-
-// Determines whether unknown fields will be stored in an UnknownFieldSet or
-// a string.
-inline bool UseUnknownFieldSet(const FileDescriptor* file,
- const Options& options) {
- return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
-}
-
-inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
- if (field->options().weak()) {
- GOOGLE_CHECK(!options.opensource_runtime);
- return true;
- }
- return false;
-}
-
-bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
-
-// For a string field, returns the effective ctype. If the actual ctype is
-// not supported, returns the default of STRING.
-FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
- const Options& options);
-
-inline bool IsCord(const FieldDescriptor* field, const Options& options) {
- return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
- EffectiveStringCType(field, options) == FieldOptions::CORD;
-}
-
-inline bool IsString(const FieldDescriptor* field, const Options& options) {
- return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
- EffectiveStringCType(field, options) == FieldOptions::STRING;
-}
-
-inline bool IsStringPiece(const FieldDescriptor* field,
- const Options& options) {
- return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
- EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
-}
-
-class MessageSCCAnalyzer;
-
-// Does the given FileDescriptor use lazy fields?
-bool HasLazyFields(const FileDescriptor* file, const Options& options,
- MessageSCCAnalyzer* scc_analyzer);
-
-// Is the given field a supported lazy field?
-bool IsLazy(const FieldDescriptor* field, const Options& options,
- MessageSCCAnalyzer* scc_analyzer);
-
-// Is this an explicit (non-profile driven) lazy field, as denoted by
-// lazy/unverified_lazy in the descriptor?
-inline bool IsExplicitLazy(const FieldDescriptor* field) {
- return field->options().lazy() || field->options().unverified_lazy();
-}
-
-inline bool IsLazilyVerifiedLazy(const FieldDescriptor* field,
- const Options& options) {
- // TODO(b/211906113): Make lazy() imply eagerly verified lazy.
- return IsExplicitLazy(field) && !field->is_repeated() &&
- field->type() == FieldDescriptor::TYPE_MESSAGE &&
- GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME &&
- !options.opensource_runtime;
-}
-
-inline bool IsEagerlyVerifiedLazy(const FieldDescriptor* field,
- const Options& options,
- MessageSCCAnalyzer* scc_analyzer) {
- // TODO(b/211906113): Make lazy() imply eagerly verified lazy.
- return IsLazy(field, options, scc_analyzer) && !IsExplicitLazy(field);
-}
-
-inline bool IsFieldUsed(const FieldDescriptor* /* field */,
- const Options& /* options */) {
- return true;
-}
-
-// Returns true if "field" is stripped.
-inline bool IsFieldStripped(const FieldDescriptor* /*field*/,
- const Options& /*options*/) {
- return false;
-}
-
-// Does the file contain any definitions that need extension_set.h?
-bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
-
-// Does the file have any repeated fields, necessitating the file to include
-// repeated_field.h? This does not include repeated extensions, since those are
-// all stored internally in an ExtensionSet, not a separate RepeatedField*.
-bool HasRepeatedFields(const FileDescriptor* file);
-
-// Does the file have any string/bytes fields with ctype=STRING_PIECE? This
-// does not include extensions, since ctype is ignored for extensions.
-bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
-
-// Does the file have any string/bytes fields with ctype=CORD? This does not
-// include extensions, since ctype is ignored for extensions.
-bool HasCordFields(const FileDescriptor* file, const Options& options);
-
-// Does the file have any map fields, necessitating the file to include
-// map_field_inl.h and map.h.
-bool HasMapFields(const FileDescriptor* file);
-
-// Does this file have any enum type definitions?
-bool HasEnumDefinitions(const FileDescriptor* file);
-
-// Does this file have generated parsing, serialization, and other
-// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const FileDescriptor* file,
- const Options& options) {
- return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
-}
-
-// Do message classes in this file have descriptor and reflection methods?
-inline bool HasDescriptorMethods(const FileDescriptor* file,
- const Options& options) {
- return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
-}
-
-// Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor* file,
- const Options& options) {
- return file->service_count() > 0 &&
- GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
- file->options().cc_generic_services();
-}
-
-inline bool IsProto2MessageSet(const Descriptor* descriptor,
- const Options& options) {
- return !options.opensource_runtime &&
- options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
- !options.lite_implicit_weak_fields &&
- descriptor->options().message_set_wire_format() &&
- descriptor->full_name() == "google.protobuf.bridge.MessageSet";
-}
-
-inline bool IsMapEntryMessage(const Descriptor* descriptor) {
- return descriptor->options().map_entry();
-}
-
-// Returns true if the field's CPPTYPE is string or message.
-bool IsStringOrMessage(const FieldDescriptor* field);
-
-TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input,
- bool cap_next_letter);
-
-inline bool IsProto3(const FileDescriptor* file) {
- return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
-inline bool HasHasbit(const FieldDescriptor* field) {
- // This predicate includes proto3 message fields only if they have "optional".
- // Foo submsg1 = 1; // HasHasbit() == false
- // optional Foo submsg2 = 2; // HasHasbit() == true
- // This is slightly odd, as adding "optional" to a singular proto3 field does
- // not change the semantics or API. However whenever any field in a message
- // has a hasbit, it forces reflection to include hasbit offsets for *all*
- // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
- // causing a sudden size regression for ~all proto3 messages, we give proto3
- // message fields a hasbit only if "optional" is present. If the user is
- // explicitly writing "optional", it is likely they are writing it on
- // primitive fields also.
- return (field->has_optional_keyword() || field->is_required()) &&
- !field->options().weak();
-}
-
-// Returns true if 'enum' semantics are such that unknown values are preserved
-// in the enum field itself, rather than going to the UnknownFieldSet.
-inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
- return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
-inline bool IsCrossFileMessage(const FieldDescriptor* field) {
- return field->type() == FieldDescriptor::TYPE_MESSAGE &&
- field->message_type()->file() != field->file();
-}
-
-inline TProtoStringType MakeDefaultName(const FieldDescriptor* field) {
- return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
- "_";
-}
-
-// Semantically distinct from MakeDefaultName in that it gives the C++ code
-// referencing a default field from the message scope, rather than just the
-// variable name.
-// For example, declarations of default variables should always use just
-// MakeDefaultName to produce code like:
-// Type _i_give_permission_to_break_this_code_default_field_;
-//
-// Code that references these should use MakeDefaultFieldName, in case the field
-// exists at some nested level like:
-// internal_container_._i_give_permission_to_break_this_code_default_field_;
-inline TProtoStringType MakeDefaultFieldName(const FieldDescriptor* field) {
- return MakeDefaultName(field);
-}
-
-inline TProtoStringType MakeVarintCachedSizeName(const FieldDescriptor* field) {
- return StrCat("_", FieldName(field), "_cached_byte_size_");
-}
-
-// Semantically distinct from MakeVarintCachedSizeName in that it gives the C++
-// code referencing the object from the message scope, rather than just the
-// variable name.
-// For example, declarations of default variables should always use just
-// MakeVarintCachedSizeName to produce code like:
-// Type _field_cached_byte_size_;
-//
-// Code that references these variables should use
-// MakeVarintCachedSizeFieldName, in case the field exists at some nested level
-// like:
-// internal_container_._field_cached_byte_size_;
-inline TProtoStringType MakeVarintCachedSizeFieldName(const FieldDescriptor* field) {
- return StrCat("_", FieldName(field), "_cached_byte_size_");
-}
-
-// Note: A lot of libraries detect Any protos based on Descriptor::full_name()
-// while the two functions below use FileDescriptor::name(). In a sane world the
-// two approaches should be equivalent. But if you are dealing with descriptors
-// from untrusted sources, you might need to match semantics across libraries.
-bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options);
-bool IsAnyMessage(const Descriptor* descriptor, const Options& options);
-
-bool IsWellKnownMessage(const FileDescriptor* descriptor);
-
-inline TProtoStringType IncludeGuard(const FileDescriptor* file, bool pb_h,
- bool deps,
- const Options& options) {
- // If we are generating a .pb.h file and the proto_h option is enabled, then
- // the .pb.h gets an extra suffix.
- TProtoStringType filename_identifier = FilenameIdentifier(
- file->name() + (deps ? ".deps": "") + (pb_h && options.proto_h ? ".pb.h" : ""));
-
- if (IsWellKnownMessage(file)) {
- // For well-known messages we need third_party/protobuf and net/proto2 to
- // have distinct include guards, because some source files include both and
- // both need to be defined (the third_party copies will be in the
- // google::protobuf_opensource namespace).
- return MacroPrefix(options) + "_INCLUDED_" + filename_identifier;
- } else {
- // Ideally this case would use distinct include guards for opensource and
- // google3 protos also. (The behavior of "first #included wins" is not
- // ideal). But unfortunately some legacy code includes both and depends on
- // the identical include guards to avoid compile errors.
- //
- // We should clean this up so that this case can be removed.
- return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier;
- }
-}
-
-// Returns the OptimizeMode for this file, furthermore it updates a status
-// bool if has_opt_codesize_extension is non-null. If this status bool is true
-// it means this file contains an extension that itself is defined as
-// optimized_for = CODE_SIZE.
-FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
- const Options& options,
- bool* has_opt_codesize_extension);
-inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
- const Options& options) {
- return GetOptimizeFor(file, options, nullptr);
-}
-inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
- const Options& options) {
- bool has_opt_codesize_extension;
- if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
- FileOptions::CODE_SIZE &&
- has_opt_codesize_extension) {
- // If this filedescriptor contains an extension from another file which
- // is optimized_for = CODE_SIZE. We need to be careful in the ordering so
- // we eagerly build the descriptors in the dependencies before building
- // the descriptors of this file.
- return true;
- } else {
- // If we have a generated code based parser we never need eager
- // initialization of descriptors of our deps.
- return false;
- }
-}
-
-// This orders the messages in a .pb.cc as it's outputted by file.cc
-void FlattenMessagesInFile(const FileDescriptor* file,
- std::vector<const Descriptor*>* result);
-inline std::vector<const Descriptor*> FlattenMessagesInFile(
- const FileDescriptor* file) {
- std::vector<const Descriptor*> result;
- FlattenMessagesInFile(file, &result);
- return result;
-}
-
-template <typename F>
-void ForEachMessage(const Descriptor* descriptor, F&& func) {
- for (int i = 0; i < descriptor->nested_type_count(); i++)
- ForEachMessage(descriptor->nested_type(i), std::forward<F&&>(func));
- func(descriptor);
-}
-
-template <typename F>
-void ForEachMessage(const FileDescriptor* descriptor, F&& func) {
- for (int i = 0; i < descriptor->message_type_count(); i++)
- ForEachMessage(descriptor->message_type(i), std::forward<F&&>(func));
-}
-
-bool HasWeakFields(const Descriptor* desc, const Options& options);
-bool HasWeakFields(const FileDescriptor* desc, const Options& options);
-
-// Returns true if the "required" restriction check should be ignored for the
-// given field.
-inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
- const Options& options) {
- // Do not check "required" for lazily verified lazy fields.
- return IsLazilyVerifiedLazy(field, options);
-}
-
-struct MessageAnalysis {
- bool is_recursive = false;
- bool contains_cord = false;
- bool contains_extension = false;
- bool contains_required = false;
- bool contains_weak = false; // Implicit weak as well.
-};
-
-// This class is used in FileGenerator, to ensure linear instead of
-// quadratic performance, if we do this per message we would get O(V*(V+E)).
-// Logically this is just only used in message.cc, but in the header for
-// FileGenerator to help share it.
-class PROTOC_EXPORT MessageSCCAnalyzer {
- public:
- explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
-
- MessageAnalysis GetSCCAnalysis(const SCC* scc);
-
- bool HasRequiredFields(const Descriptor* descriptor) {
- MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
- return result.contains_required || result.contains_extension;
- }
- bool HasWeakField(const Descriptor* descriptor) {
- MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
- return result.contains_weak;
- }
- const SCC* GetSCC(const Descriptor* descriptor) {
- return analyzer_.GetSCC(descriptor);
- }
-
- private:
- struct DepsGenerator {
- std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
- std::vector<const Descriptor*> deps;
- for (int i = 0; i < desc->field_count(); i++) {
- if (desc->field(i)->message_type()) {
- deps.push_back(desc->field(i)->message_type());
- }
- }
- return deps;
- }
- };
- SCCAnalyzer<DepsGenerator> analyzer_;
- Options options_;
- std::map<const SCC*, MessageAnalysis> analysis_cache_;
-};
-
-void ListAllFields(const Descriptor* d,
- std::vector<const FieldDescriptor*>* fields);
-void ListAllFields(const FileDescriptor* d,
- std::vector<const FieldDescriptor*>* fields);
-
-template <class T>
-void ForEachField(const Descriptor* d, T&& func) {
- for (int i = 0; i < d->nested_type_count(); i++) {
- ForEachField(d->nested_type(i), std::forward<T&&>(func));
- }
- for (int i = 0; i < d->extension_count(); i++) {
- func(d->extension(i));
- }
- for (int i = 0; i < d->field_count(); i++) {
- func(d->field(i));
- }
-}
-
-template <class T>
-void ForEachField(const FileDescriptor* d, T&& func) {
- for (int i = 0; i < d->message_type_count(); i++) {
- ForEachField(d->message_type(i), std::forward<T&&>(func));
- }
- for (int i = 0; i < d->extension_count(); i++) {
- func(d->extension(i));
- }
-}
-
-void ListAllTypesForServices(const FileDescriptor* fd,
- std::vector<const Descriptor*>* types);
-
-// Indicates whether we should use implicit weak fields for this file.
-bool UsingImplicitWeakFields(const FileDescriptor* file,
- const Options& options);
-
-// Indicates whether to treat this field as implicitly weak.
-bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
- MessageSCCAnalyzer* scc_analyzer);
-
-inline bool HasSimpleBaseClass(const Descriptor* desc, const Options& options) {
- if (!HasDescriptorMethods(desc->file(), options)) return false;
- if (desc->extension_range_count() != 0) return false;
- if (desc->field_count() == 0) return true;
- // TODO(jorg): Support additional common message types with only one
- // or two fields
- return false;
-}
-
-inline bool HasSimpleBaseClasses(const FileDescriptor* file,
- const Options& options) {
- bool v = false;
- ForEachMessage(file, [&v, &options](const Descriptor* desc) {
- v |= HasSimpleBaseClass(desc, options);
- });
- return v;
-}
-
-inline TProtoStringType SimpleBaseClass(const Descriptor* desc,
- const Options& options) {
- if (!HasDescriptorMethods(desc->file(), options)) return "";
- if (desc->extension_range_count() != 0) return "";
- if (desc->field_count() == 0) {
- return "ZeroFieldsBase";
- }
- // TODO(jorg): Support additional common message types with only one
- // or two fields
- return "";
-}
-
-// Formatter is a functor class which acts as a closure around printer and
-// the variable map. It's much like printer->Print except it supports both named
-// variables that are substituted using a key value map and direct arguments. In
-// the format string $1$, $2$, etc... are substituted for the first, second, ...
-// direct argument respectively in the format call, it accepts both strings and
-// integers. The implementation verifies all arguments are used and are "first"
-// used in order of appearance in the argument list. For example,
-//
-// Format("return array[$1$];", 3) -> "return array[3];"
-// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order)
-// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;"
-//
-// The arguments can be used more than once like
-//
-// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") ->
-// "array[3] = Bla; // Index = 3"
-//
-// If you use more arguments use the following style to help the reader,
-//
-// Format("int $1$() {\n"
-// " array[$2$] = $3$;\n"
-// " return $4$;"
-// "}\n",
-// funname, // 1
-// idx, // 2
-// varname, // 3
-// retval); // 4
-//
-// but consider using named variables. Named variables like $foo$, with some
-// identifier foo, are looked up in the map. One additional feature is that
-// spaces are accepted between the '$' delimiters, $ foo$ will
-// substiture to " bar" if foo stands for "bar", but in case it's empty
-// will substitute to "". Hence, for example,
-//
-// Format(vars, "$dllexport $void fun();") -> "void fun();"
-// "__declspec(export) void fun();"
-//
-// which is convenient to prevent double, leading or trailing spaces.
-class PROTOC_EXPORT Formatter {
- public:
- explicit Formatter(io::Printer* printer) : printer_(printer) {}
- Formatter(io::Printer* printer,
- const std::map<TProtoStringType, TProtoStringType>& vars)
- : printer_(printer), vars_(vars) {}
-
- template <typename T>
- void Set(const TProtoStringType& key, const T& value) {
- vars_[key] = ToString(value);
- }
-
- void AddMap(const std::map<TProtoStringType, TProtoStringType>& vars) {
- for (const auto& keyval : vars) vars_[keyval.first] = keyval.second;
- }
-
- template <typename... Args>
- void operator()(const char* format, const Args&... args) const {
- printer_->FormatInternal({ToString(args)...}, vars_, format);
- }
-
- void Indent() const { printer_->Indent(); }
- void Outdent() const { printer_->Outdent(); }
- io::Printer* printer() const { return printer_; }
-
- class PROTOC_EXPORT ScopedIndenter {
- public:
- explicit ScopedIndenter(Formatter* format) : format_(format) {
- format_->Indent();
- }
- ~ScopedIndenter() { format_->Outdent(); }
-
- private:
- Formatter* format_;
- };
-
- PROTOBUF_NODISCARD ScopedIndenter ScopedIndent() {
- return ScopedIndenter(this);
- }
- template <typename... Args>
- PROTOBUF_NODISCARD ScopedIndenter ScopedIndent(const char* format,
- const Args&&... args) {
- (*this)(format, static_cast<Args&&>(args)...);
- return ScopedIndenter(this);
- }
-
- class PROTOC_EXPORT SaveState {
- public:
- explicit SaveState(Formatter* format)
- : format_(format), vars_(format->vars_) {}
- ~SaveState() { format_->vars_.swap(vars_); }
-
- private:
- Formatter* format_;
- std::map<TProtoStringType, TProtoStringType> vars_;
- };
-
- private:
- io::Printer* printer_;
- std::map<TProtoStringType, TProtoStringType> vars_;
-
- // Convenience overloads to accept different types as arguments.
- static TProtoStringType ToString(const TProtoStringType& s) { return s; }
- template <typename I, typename = typename std::enable_if<
- std::is_integral<I>::value>::type>
- static TProtoStringType ToString(I x) {
- return StrCat(x);
- }
- static TProtoStringType ToString(strings::Hex x) { return StrCat(x); }
- static TProtoStringType ToString(const FieldDescriptor* d) { return Payload(d); }
- static TProtoStringType ToString(const Descriptor* d) { return Payload(d); }
- static TProtoStringType ToString(const EnumDescriptor* d) { return Payload(d); }
- static TProtoStringType ToString(const EnumValueDescriptor* d) {
- return Payload(d);
- }
- static TProtoStringType ToString(const OneofDescriptor* d) { return Payload(d); }
-
- template <typename Descriptor>
- static TProtoStringType Payload(const Descriptor* descriptor) {
- std::vector<int> path;
- descriptor->GetLocationPath(&path);
- GeneratedCodeInfo::Annotation annotation;
- for (int index : path) {
- annotation.add_path(index);
- }
- annotation.set_source_file(descriptor->file()->name());
- return annotation.SerializeAsString();
- }
-};
-
-template <class T>
-void PrintFieldComment(const Formatter& format, const T* field) {
- // Print the field's (or oneof's) proto-syntax definition as a comment.
- // We don't want to print group bodies so we cut off after the first
- // line.
- DebugStringOptions options;
- options.elide_group_body = true;
- options.elide_oneof_body = true;
- TProtoStringType def = field->DebugStringWithOptions(options);
- format("// $1$\n", def.substr(0, def.find_first_of('\n')));
-}
-
-class PROTOC_EXPORT NamespaceOpener {
- public:
- explicit NamespaceOpener(const Formatter& format)
- : printer_(format.printer()) {}
- NamespaceOpener(const TProtoStringType& name, const Formatter& format)
- : NamespaceOpener(format) {
- ChangeTo(name);
- }
- ~NamespaceOpener() { ChangeTo(""); }
-
- void ChangeTo(const TProtoStringType& name) {
- std::vector<TProtoStringType> new_stack_ =
- Split(name, "::", true);
- 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++;
- }
- for (auto it = name_stack_.crbegin();
- it != name_stack_.crend() - common_idx; ++it) {
- if (*it == "PROTOBUF_NAMESPACE_ID") {
- printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n");
- } else {
- printer_->Print("} // namespace $ns$\n", "ns", *it);
- }
- }
- name_stack_.swap(new_stack_);
- for (size_t i = common_idx; i < name_stack_.size(); ++i) {
- if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
- printer_->Print("PROTOBUF_NAMESPACE_OPEN\n");
- } else {
- printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
- }
- }
- }
-
- private:
- io::Printer* printer_;
- std::vector<TProtoStringType> name_stack_;
-};
-
-enum class Utf8CheckMode {
- kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields.
- kVerify = 1, // Only log an error but parsing will succeed.
- kNone = 2, // No UTF-8 check.
-};
-
-Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
- const Options& options);
-
-void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
- const Options& options, bool for_parse,
- const char* parameters,
- const Formatter& format);
-
-void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
- const Options& options, bool for_parse,
- const char* parameters,
- const Formatter& format);
-
-template <typename T>
-struct FieldRangeImpl {
- struct Iterator {
- using iterator_category = std::forward_iterator_tag;
- using value_type = const FieldDescriptor*;
- using difference_type = int;
-
- value_type operator*() { return descriptor->field(idx); }
-
- friend bool operator==(const Iterator& a, const Iterator& b) {
- GOOGLE_DCHECK(a.descriptor == b.descriptor);
- return a.idx == b.idx;
- }
- friend bool operator!=(const Iterator& a, const Iterator& b) {
- return !(a == b);
- }
-
- Iterator& operator++() {
- idx++;
- return *this;
- }
-
- int idx;
- const T* descriptor;
- };
-
- Iterator begin() const { return {0, descriptor}; }
- Iterator end() const { return {descriptor->field_count(), descriptor}; }
-
- const T* descriptor;
-};
-
-template <typename T>
-FieldRangeImpl<T> FieldRange(const T* desc) {
- return {desc};
-}
-
-struct OneOfRangeImpl {
- struct Iterator {
- using iterator_category = std::forward_iterator_tag;
- using value_type = const OneofDescriptor*;
- using difference_type = int;
-
- value_type operator*() { return descriptor->oneof_decl(idx); }
-
- friend bool operator==(const Iterator& a, const Iterator& b) {
- GOOGLE_DCHECK(a.descriptor == b.descriptor);
- return a.idx == b.idx;
- }
- friend bool operator!=(const Iterator& a, const Iterator& b) {
- return !(a == b);
- }
-
- Iterator& operator++() {
- idx++;
- return *this;
- }
-
- int idx;
- const Descriptor* descriptor;
- };
-
- Iterator begin() const { return {0, descriptor}; }
- Iterator end() const {
- return {descriptor->real_oneof_decl_count(), descriptor};
- }
-
- const Descriptor* descriptor;
-};
-
-inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
-
-PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename);
-
-bool EnableMessageOwnedArena(const Descriptor* desc, const Options& options);
-
-bool ShouldVerify(const Descriptor* descriptor, const Options& options,
- MessageSCCAnalyzer* scc_analyzer);
-bool ShouldVerify(const FileDescriptor* file, const Options& options,
- MessageSCCAnalyzer* scc_analyzer);
-} // namespace cpp
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
+#include "helpers.h" \ No newline at end of file
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc
index 960dfcadf79..91d0b9442b7 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc
@@ -32,7 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_enum.h>
+#include <google/protobuf/compiler/cpp/enum.h>
#include <cstdint>
#include <limits>
@@ -40,8 +40,8 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_names.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/names.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h
index 652a26b6db8..550f43b1ed4 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h
@@ -40,7 +40,7 @@
#include <string>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc
index f50fca4926a..dc8dc524815 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc
@@ -32,12 +32,13 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
+#include <google/protobuf/compiler/cpp/enum_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
namespace protobuf {
@@ -55,8 +56,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = Int32ToString(default_value->number());
(*variables)["full_name"] = descriptor->full_name();
(*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
+ bool cold = ShouldSplit(descriptor, options);
(*variables)["cached_byte_size_field"] =
- MakeVarintCachedSizeFieldName(descriptor);
+ MakeVarintCachedSizeFieldName(descriptor, cold);
}
} // namespace
@@ -110,6 +112,7 @@ void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
" $field$ = value;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
+ "$maybe_prepare_split_message$"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -123,7 +126,7 @@ void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
- format("_internal_set_$name$(from._internal_$name$());\n");
+ format("_this->_internal_set_$name$(from._internal_$name$());\n");
}
void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
@@ -131,15 +134,10 @@ void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
format("swap($field$, other->$field$);\n");
}
-void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
- Formatter format(printer, variables_);
- format("$field$ = $default$;\n");
-}
-
void EnumFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$field$ = from.$field$;\n");
+ format("_this->$field$ = from.$field$;\n");
}
void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
@@ -158,10 +156,26 @@ void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
" ::_pbi::WireFormatLite::EnumSize(this->_internal_$name$());\n");
}
-void EnumFieldGenerator::GenerateConstinitInitializer(
+void EnumFieldGenerator::GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("/*decltype($field$)*/$default$");
+}
+
+void EnumFieldGenerator::GenerateAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$name$_($default$)\n");
+ if (ShouldSplit(descriptor_, options_)) {
+ format("decltype(Impl_::Split::$name$_){$default$}");
+ return;
+ }
+ format("decltype($field$){$default$}");
+}
+
+void EnumFieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("decltype($field$){}");
}
// ===================================================================
@@ -322,7 +336,7 @@ void RepeatedEnumFieldGenerator::GenerateClearingCode(
void RepeatedEnumFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$field$.MergeFrom(from.$field$);\n");
+ format("_this->$field$.MergeFrom(from.$field$);\n");
}
void RepeatedEnumFieldGenerator::GenerateSwappingCode(
@@ -336,6 +350,12 @@ void RepeatedEnumFieldGenerator::GenerateConstructorCode(
// Not needed for repeated fields.
}
+void RepeatedEnumFieldGenerator::GenerateDestructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$field$.~RepeatedField();\n");
+}
+
void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
@@ -392,13 +412,36 @@ void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
format("}\n");
}
-void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
+void RepeatedEnumFieldGenerator::GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("/*decltype($field$)*/{}");
+ if (descriptor_->is_packed() &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ format("\n, /*decltype($cached_byte_size_field$)*/{0}");
+ }
+}
+
+void RepeatedEnumFieldGenerator::GenerateAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("decltype($field$){arena}");
+ if (descriptor_->is_packed() &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ // std::atomic has no copy constructor, which prevents explicit aggregate
+ // initialization pre-C++17.
+ format("\n, /*decltype($cached_byte_size_field$)*/{0}");
+ }
+}
+
+void RepeatedEnumFieldGenerator::GenerateCopyAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$name$_()");
+ format("decltype($field$){from.$field$}");
if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->file(), options_)) {
- format("\n, $cached_byte_size_name$(0)");
+ // std::atomic has no copy constructor.
+ format("\n, /*decltype($cached_byte_size_field$)*/{0}");
}
}
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h
index 2a4ca5162bf..61bae855cd6 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h
@@ -38,7 +38,7 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/field.h>
namespace google {
namespace protobuf {
@@ -57,12 +57,15 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
- void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override {}
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@@ -98,11 +101,17 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
- void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+ void GenerateCopyConstructorCode(io::Printer* /*printer*/) const override {
+ GOOGLE_CHECK(!ShouldSplit(descriptor_, options_));
+ }
+ void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_extension.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc
index ef6cc81241f..ed85f75960a 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc
@@ -32,13 +32,13 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <google/protobuf/compiler/cpp/extension.h>
#include <map>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
@@ -78,7 +78,7 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
break;
}
SetCommonVars(options, &variables_);
- SetCommonMessageDataVariables(&variables_);
+ SetCommonMessageDataVariables(descriptor_->containing_type(), &variables_);
variables_["extendee"] =
QualifiedClassName(descriptor_->containing_type(), options_);
variables_["type_traits"] = type_traits_;
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_extension.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h
index 5a32e845540..b94b178868a 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h
@@ -39,7 +39,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc
index 895f094c701..d5359b6d247 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc
@@ -32,7 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/field.h>
#include <cstdint>
#include <memory>
@@ -40,16 +40,16 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
-#include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/primitive_field.h>
+#include <google/protobuf/compiler/cpp/string_field.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
-#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
-#include <google/protobuf/compiler/cpp/cpp_map_field.h>
-#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+#include <google/protobuf/compiler/cpp/enum_field.h>
+#include <google/protobuf/compiler/cpp/map_field.h>
+#include <google/protobuf/compiler/cpp/message_field.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
@@ -236,7 +236,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
std::map<TProtoStringType, TProtoStringType>* variables,
const Options& options) {
SetCommonVars(options, variables);
- SetCommonMessageDataVariables(variables);
+ SetCommonMessageDataVariables(descriptor->containing_type(), variables);
(*variables)["ns"] = Namespace(descriptor, options);
(*variables)["name"] = FieldName(descriptor);
@@ -244,7 +244,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["number"] = StrCat(descriptor->number());
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
- (*variables)["field"] = FieldMemberName(descriptor);
+ bool split = ShouldSplit(descriptor, options);
+ (*variables)["field"] = FieldMemberName(descriptor, split);
(*variables)["tag_size"] = StrCat(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
@@ -252,13 +253,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["set_hasbit"] = "";
(*variables)["clear_hasbit"] = "";
- if (HasHasbit(descriptor)) {
- (*variables)["set_hasbit_io"] =
- StrCat("_Internal::set_has_", FieldName(descriptor), "(&",
- (*variables)["has_bits"], ");");
- } else {
- (*variables)["set_hasbit_io"] = "";
- }
+ (*variables)["maybe_prepare_split_message"] =
+ split ? " PrepareSplitMessageForWrite();\n" : "";
AddAccessorAnnotations(descriptor, options, variables);
@@ -304,6 +300,36 @@ void FieldGenerator::SetInlinedStringIndex(arc_i32 inlined_string_index) {
"u");
}
+void FieldGenerator::GenerateAggregateInitializer(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (ShouldSplit(descriptor_, options_)) {
+ format("decltype(Impl_::Split::$name$_){arena}");
+ return;
+ }
+ format("decltype($field$){arena}");
+}
+
+void FieldGenerator::GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("/*decltype($field$)*/{}");
+}
+
+void FieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("decltype($field$){from.$field$}");
+}
+
+void FieldGenerator::GenerateCopyConstructorCode(io::Printer* printer) const {
+ if (ShouldSplit(descriptor_, options_)) {
+ // There is no copy constructor for the `Split` struct, so we need to copy
+ // the value here.
+ Formatter format(printer, variables_);
+ format("$field$ = from.$field$;\n");
+ }
+}
+
void SetCommonOneofFieldVariables(
const FieldDescriptor* descriptor,
std::map<TProtoStringType, TProtoStringType>* variables) {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h
index 9c3ec7fde4b..95eb96f499d 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h
@@ -41,8 +41,8 @@
#include <string>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
@@ -136,7 +136,7 @@ class FieldGenerator {
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
// Generates a copy constructor
- virtual void GenerateCopyConstructorCode(io::Printer* printer) const = 0;
+ virtual void GenerateCopyConstructorCode(io::Printer* printer) const;
// Generate lines of code (statements, not declarations) which swaps
// this field and the corresponding field of another message, which
@@ -150,6 +150,9 @@ class FieldGenerator {
// method, invoked by each of the generated constructors.
virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
+ // Generate initialization code for private members in the cold struct.
+ virtual void GenerateCreateSplitMessageCode(io::Printer* printer) const {}
+
// Generate any code that needs to go in the class's SharedDtor() method,
// invoked by the destructor.
// Most field types don't need this, so the default implementation is empty.
@@ -165,10 +168,32 @@ class FieldGenerator {
}
// Generate initialization code for private members declared by
- // GeneratePrivateMembers(), specifically for the constexpr constructor.
- // These go into the constructor's initializer list and must follow that
- // syntax (eg `field_(args)`). Does not include `:` or `,` separators.
- virtual void GenerateConstinitInitializer(io::Printer* printer) const {}
+ // GeneratePrivateMembers(). These go into the SharedCtor's
+ // aggregate initialization of the _impl_ struct and must follow the syntax
+ // (e.g. `decltype($field$){$default$}`). Does not include `:` or `,`
+ // separators. Default values should be specified here when possible.
+ //
+ // Note: We use `decltype($field$)` for both explicit construction and the
+ // fact that it's self-documenting. Pre-C++17, copy elision isn't guaranteed
+ // in aggregate initialization so a valid copy/move constructor must exist
+ // (even though it's not used). Because of this, we need to comment out the
+ // decltype and fallback to implicit construction.
+ virtual void GenerateAggregateInitializer(io::Printer* printer) const;
+
+ // Generate constinit initialization code for private members declared by
+ // GeneratePrivateMembers(). These go into the constexpr constructor's
+ // aggregate initialization of the _impl_ struct and must follow the syntax
+ // (e.g. `/*decltype($field$)*/{}`, see above). Does not
+ // include `:` or `,` separators.
+ virtual void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const;
+
+ // Generate copy initialization code for private members declared by
+ // GeneratePrivateMembers(). These go into the copy constructor's
+ // aggregate initialization of the _impl_ struct and must follow the syntax
+ // (e.g. `decltype($field$){from.$field$}`, see above). Does not
+ // include `:` or `,` separators.
+ virtual void GenerateCopyAggregateInitializer(io::Printer* printer) const;
// Generate lines to serialize this field directly to the array "target",
// which are placed within the message's SerializeWithCachedSizesToArray()
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_file.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc
index f27d876e2ac..2d79ec11e59 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc
@@ -32,7 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_file.h>
+#include <google/protobuf/compiler/cpp/file.h>
#include <iostream>
#include <map>
@@ -46,12 +46,12 @@
#include <google/protobuf/compiler/scc.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_enum.h>
-#include <google/protobuf/compiler/cpp/cpp_extension.h>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_message.h>
-#include <google/protobuf/compiler/cpp/cpp_service.h>
+#include <google/protobuf/compiler/cpp/enum.h>
+#include <google/protobuf/compiler/cpp/extension.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/message.h>
+#include <google/protobuf/compiler/cpp/service.h>
#include <google/protobuf/descriptor.pb.h>
// Must be last.
@@ -496,10 +496,40 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx,
io::Printer* printer) {
Formatter format(printer, variables_);
MessageGenerator* generator = message_generators_[idx].get();
+ // Generate the split instance first because it's needed in the constexpr
+ // constructor.
+ if (ShouldSplit(generator->descriptor_, options_)) {
+ // Use a union to disable the destructor of the _instance member.
+ // We can constant initialize, but the object will still have a non-trivial
+ // destructor that we need to elide.
+ format(
+ "struct $1$ {\n"
+ " PROTOBUF_CONSTEXPR $1$()\n"
+ " : _instance{",
+ DefaultInstanceType(generator->descriptor_, options_,
+ /*split=*/true));
+ generator->GenerateInitDefaultSplitInstance(printer);
+ format(
+ "} {}\n"
+ " ~$1$() {}\n"
+ " union {\n"
+ " $2$ _instance;\n"
+ " };\n"
+ "};\n",
+ DefaultInstanceType(generator->descriptor_, options_, /*split=*/true),
+ StrCat(generator->classname_, "::Impl_::Split"));
+ // NO_DESTROY is not necessary for correctness. The empty destructor is
+ // enough. However, the empty destructor fails to be elided in some
+ // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
+ // there just to improve performance and binary size in these builds.
+ format(
+ "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT "
+ "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n",
+ DefaultInstanceType(generator->descriptor_, options_, /*split=*/true),
+ DefaultInstanceName(generator->descriptor_, options_, /*split=*/true));
+ }
+
generator->GenerateConstexprConstructor(printer);
- // Use a union to disable the destructor of the _instance member.
- // We can constant initialize, but the object will still have a non-trivial
- // destructor that we need to elide.
format(
"struct $1$ {\n"
" PROTOBUF_CONSTEXPR $1$()\n"
@@ -511,14 +541,11 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx,
"};\n",
DefaultInstanceType(generator->descriptor_, options_),
generator->classname_);
- // NO_DESTROY is not necessary for correctness. The empty destructor is
- // enough. However, the empty destructor fails to be elided in some
- // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
- // there just to improve performance and binary size in these builds.
- format("PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT "
- "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n",
- DefaultInstanceType(generator->descriptor_, options_),
- DefaultInstanceName(generator->descriptor_, options_));
+ format(
+ "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT "
+ "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n",
+ DefaultInstanceType(generator->descriptor_, options_),
+ DefaultInstanceName(generator->descriptor_, options_));
for (int i = 0; i < generator->descriptor_->field_count(); i++) {
const FieldDescriptor* field = generator->descriptor_->field(i);
@@ -526,11 +553,11 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx,
// Force the initialization of the inlined string in the default instance.
format(
"PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type "
- "$1$::_init_inline_$2$_ = "
+ "$1$::Impl_::_init_inline_$2$_ = "
"($3$._instance.$4$.Init(), std::true_type{});\n",
ClassName(generator->descriptor_), FieldName(field),
DefaultInstanceName(generator->descriptor_, options_),
- FieldMemberName(field));
+ FieldMemberName(field, ShouldSplit(field, options_)));
}
}
@@ -963,6 +990,7 @@ class FileGenerator::ForwardDeclarations {
public:
void AddMessage(const Descriptor* d) { classes_[ClassName(d)] = d; }
void AddEnum(const EnumDescriptor* d) { enums_[ClassName(d)] = d; }
+ void AddSplit(const Descriptor* d) { splits_[ClassName(d)] = d; }
void Print(const Formatter& format, const Options& options) const {
for (const auto& p : enums_) {
@@ -983,6 +1011,14 @@ class FileGenerator::ForwardDeclarations {
class_desc, classname, DefaultInstanceType(class_desc, options),
DefaultInstanceName(class_desc, options));
}
+ for (const auto& p : splits_) {
+ const Descriptor* class_desc = p.second;
+ format(
+ "struct $1$;\n"
+ "$dllexport_decl $extern $1$ $2$;\n",
+ DefaultInstanceType(class_desc, options, /*split=*/true),
+ DefaultInstanceName(class_desc, options, /*split=*/true));
+ }
}
void PrintTopLevelDecl(const Formatter& format,
@@ -998,6 +1034,7 @@ class FileGenerator::ForwardDeclarations {
private:
std::map<TProtoStringType, const Descriptor*> classes_;
std::map<TProtoStringType, const EnumDescriptor*> enums_;
+ std::map<TProtoStringType, const Descriptor*> splits_;
};
static void PublicImportDFS(const FileDescriptor* fd,
@@ -1071,6 +1108,12 @@ void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
if (d && !public_set.count(d->file()))
decls[Namespace(d, options_)].AddEnum(d);
}
+ for (const auto& mg : message_generators_) {
+ const Descriptor* d = mg->descriptor_;
+ if ((d != nullptr) && (public_set.count(d->file()) == 0u) &&
+ ShouldSplit(mg->descriptor_, options_))
+ decls[Namespace(d, options_)].AddSplit(d);
+ }
{
NamespaceOpener ns(format);
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_file.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h
index d8eff2feedb..805b4979bf5 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h
@@ -42,10 +42,10 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc
index 69443f5bf2f..0da2027a1e6 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc
@@ -32,7 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/cpp/generator.h>
#include <memory>
#include <string>
@@ -42,8 +42,8 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/compiler/cpp/cpp_file.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/file.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
#include <google/protobuf/descriptor.pb.h>
namespace google {
@@ -135,12 +135,12 @@ bool CppGenerator::Generate(const FileDescriptor* file,
.insert(options[i].second.substr(pos, next_pos - pos));
pos = next_pos + 1;
} while (pos < options[i].second.size());
- } else if (options[i].first == "verified_lazy_message_sets") {
- file_options.unverified_lazy_message_sets = false;
+ } else if (options[i].first == "verified_lazy") {
+ file_options.unverified_lazy = false;
} else if (options[i].first == "unverified_lazy_message_sets") {
file_options.unverified_lazy_message_sets = true;
- } else if (options[i].first == "eagerly_verified_lazy") {
- file_options.eagerly_verified_lazy = true;
+ } else if (options[i].first == "message_owned_arena_trial") {
+ file_options.message_owned_arena_trial = true;
} else if (options[i].first == "force_eagerly_verified_lazy") {
file_options.force_eagerly_verified_lazy = true;
} else if (options[i].first == "experimental_tail_call_table_mode") {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h
index aa63845d300..aa63845d300 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_generator.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc
index f726d0fc9b5..48879f29d57 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc
@@ -32,12 +32,13 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
#include <cstdint>
#include <functional>
#include <limits>
#include <map>
+#include <memory>
#include <queue>
#include <unordered_set>
#include <vector>
@@ -45,8 +46,8 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/cpp_names.h>
-#include <google/protobuf/compiler/cpp/cpp_options.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>
@@ -182,18 +183,53 @@ void SetIntVar(const Options& options, const TProtoStringType& type,
std::map<TProtoStringType, TProtoStringType>* variables) {
(*variables)[type] = IntTypeName(options, type);
}
-bool IsEagerlyVerifiedLazyImpl(const FieldDescriptor* field,
- const Options& options,
- MessageSCCAnalyzer* scc_analyzer) {
+
+// 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;
}
+// 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
bool IsLazy(const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer) {
return IsLazilyVerifiedLazy(field, options) ||
- IsEagerlyVerifiedLazyImpl(field, options, scc_analyzer);
+ IsEagerlyVerifiedLazy(field, options, scc_analyzer);
+}
+
+// Returns true if "field" is a message field that is backed by LazyField per
+// profile (go/pdlazy).
+inline bool IsEagerlyVerifiedLazyByProfile(const FieldDescriptor* field,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ return false;
+}
+
+bool IsEagerlyVerifiedLazy(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ return false;
+}
+
+bool IsLazilyVerifiedLazy(const FieldDescriptor* field,
+ const Options& options) {
+ return false;
}
void SetCommonVars(const Options& options,
@@ -234,15 +270,20 @@ void SetCommonVars(const Options& options,
}
void SetCommonMessageDataVariables(
+ const Descriptor* descriptor,
std::map<TProtoStringType, TProtoStringType>* variables) {
- (*variables)["any_metadata"] = "_any_metadata_";
- (*variables)["cached_size"] = "_cached_size_";
- (*variables)["extensions"] = "_extensions_";
- (*variables)["has_bits"] = "_has_bits_";
- (*variables)["inlined_string_donated_array"] = "_inlined_string_donated_";
- (*variables)["oneof_case"] = "_oneof_case_";
- (*variables)["tracker"] = "_tracker_";
- (*variables)["weak_field_map"] = "_weak_field_map_";
+ 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,
@@ -407,29 +448,32 @@ TProtoStringType Namespace(const EnumDescriptor* d, const Options& options) {
}
TProtoStringType DefaultInstanceType(const Descriptor* descriptor,
- const Options& options) {
- return ClassName(descriptor) + "DefaultTypeInternal";
+ const Options& /*options*/, bool split) {
+ return ClassName(descriptor) + (split ? "__Impl_Split" : "") +
+ "DefaultTypeInternal";
}
TProtoStringType DefaultInstanceName(const Descriptor* descriptor,
- const Options& options) {
- return "_" + ClassName(descriptor, false) + "_default_instance_";
+ const Options& /*options*/, bool split) {
+ return "_" + ClassName(descriptor, false) + (split ? "__Impl_Split" : "") +
+ "_default_instance_";
}
TProtoStringType DefaultInstancePtr(const Descriptor* descriptor,
- const Options& options) {
- return DefaultInstanceName(descriptor, options) + "ptr_";
+ const Options& options, bool split) {
+ return DefaultInstanceName(descriptor, options, split) + "ptr_";
}
TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor,
- const Options& options) {
+ const Options& options, bool split) {
return QualifiedFileLevelSymbol(
- descriptor->file(), DefaultInstanceName(descriptor, options), options);
+ descriptor->file(), DefaultInstanceName(descriptor, options, split),
+ options);
}
TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor,
- const Options& options) {
- return QualifiedDefaultInstanceName(descriptor, options) + "ptr_";
+ const Options& options, bool split) {
+ return QualifiedDefaultInstanceName(descriptor, options, split) + "ptr_";
}
TProtoStringType DescriptorTableName(const FileDescriptor* file,
@@ -469,12 +513,17 @@ TProtoStringType FieldName(const FieldDescriptor* field) {
return result;
}
-TProtoStringType FieldMemberName(const FieldDescriptor* field) {
+TProtoStringType FieldMemberName(const FieldDescriptor* field, bool split) {
+ StringPiece prefix =
+ IsMapEntryMessage(field->containing_type()) ? "" : "_impl_.";
+ StringPiece split_prefix = split ? "_split_->" : "";
if (field->real_containing_oneof() == nullptr) {
- return StrCat(FieldName(field), "_");
+ return StrCat(prefix, split_prefix, FieldName(field), "_");
}
- return StrCat(field->containing_oneof()->name(), "_.", FieldName(field),
- "_");
+ // Oneof fields are never split.
+ GOOGLE_CHECK(!split);
+ return StrCat(prefix, field->containing_oneof()->name(), "_.",
+ FieldName(field), "_");
}
TProtoStringType OneofCaseConstantName(const FieldDescriptor* field) {
@@ -855,6 +904,9 @@ bool HasLazyFields(const FileDescriptor* file, const Options& options,
return false;
}
+bool ShouldSplit(const Descriptor*, const Options&) { return false; }
+bool ShouldSplit(const FieldDescriptor*, const 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) {
@@ -991,6 +1043,16 @@ bool ShouldVerify(const FileDescriptor* file, const Options& options,
return false;
}
+bool IsUtf8String(const FieldDescriptor* field) {
+ return IsProto3(field->file()) &&
+ field->type() == FieldDescriptor::TYPE_STRING;
+}
+
+VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor) {
+ (void)descriptor;
+ return VerifySimpleType::kCustom;
+}
+
bool IsStringOrMessage(const FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
@@ -1509,12 +1571,32 @@ FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
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)) {
+ if (f->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) return true;
+ }
+ return false;
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h
new file mode 100644
index 00000000000..690a577591e
--- /dev/null
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h
@@ -0,0 +1,1065 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: [email protected] (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/scc.h>
+#include <google/protobuf/compiler/code_generator.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/descriptor.h>
+#include <google/protobuf/port.h>
+#include <google/protobuf/stubs/strutil.h>
+
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+enum class ArenaDtorNeeds { kNone = 0, kOnDemand = 1, kRequired = 2 };
+
+inline TProtoStringType ProtobufNamespace(const Options& /* options */) {
+ return "PROTOBUF_NAMESPACE_ID";
+}
+
+inline TProtoStringType MacroPrefix(const Options& /* options */) {
+ return "GOOGLE_PROTOBUF";
+}
+
+inline TProtoStringType DeprecatedAttribute(const Options& /* options */,
+ const FieldDescriptor* d) {
+ return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : "";
+}
+
+inline TProtoStringType DeprecatedAttribute(const Options& /* options */,
+ const EnumValueDescriptor* d) {
+ return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : "";
+}
+
+// Commonly-used separator comments. Thick is a line of '=', thin is a line
+// of '-'.
+extern const char kThickSeparator[];
+extern const char kThinSeparator[];
+
+void SetCommonVars(const Options& options,
+ std::map<TProtoStringType, TProtoStringType>* variables);
+
+// Variables to access message data from the message scope.
+void SetCommonMessageDataVariables(
+ const Descriptor* descriptor,
+ std::map<TProtoStringType, TProtoStringType>* variables);
+
+void SetUnknownFieldsVariable(const Descriptor* descriptor,
+ const Options& options,
+ std::map<TProtoStringType, TProtoStringType>* variables);
+
+bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename,
+ TProtoStringType* bootstrap_basename);
+bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
+ bool bootstrap_flag, TProtoStringType* basename);
+bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
+
+// Name space of the proto file. This namespace is such that the string
+// "<namespace>::some_name" is the correct fully qualified namespace.
+// This means if the package is empty the namespace is "", and otherwise
+// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
+TProtoStringType Namespace(const FileDescriptor* d, const Options& options);
+TProtoStringType Namespace(const Descriptor* d, const Options& options);
+TProtoStringType Namespace(const FieldDescriptor* d, const Options& options);
+TProtoStringType Namespace(const EnumDescriptor* d, const Options& options);
+
+// Returns true if it's safe to reset "field" to zero.
+bool CanInitializeByZeroing(const FieldDescriptor* field);
+
+TProtoStringType ClassName(const Descriptor* descriptor);
+TProtoStringType ClassName(const EnumDescriptor* enum_descriptor);
+
+TProtoStringType QualifiedClassName(const Descriptor* d, const Options& options);
+TProtoStringType QualifiedClassName(const EnumDescriptor* d, const Options& options);
+
+TProtoStringType QualifiedClassName(const Descriptor* d);
+TProtoStringType QualifiedClassName(const EnumDescriptor* d);
+
+// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
+// unreadable at the callsite.
+// Returns the non-nested type name for the given type. If "qualified" is
+// true, prefix the type with the full namespace. For example, if you had:
+// package foo.bar;
+// message Baz { message Moo {} }
+// Then the qualified ClassName for Moo would be:
+// ::foo::bar::Baz_Moo
+// While the non-qualified version would be:
+// Baz_Moo
+inline TProtoStringType ClassName(const Descriptor* descriptor, bool qualified) {
+ return qualified ? QualifiedClassName(descriptor, Options())
+ : ClassName(descriptor);
+}
+
+inline TProtoStringType ClassName(const EnumDescriptor* descriptor, bool qualified) {
+ return qualified ? QualifiedClassName(descriptor, Options())
+ : ClassName(descriptor);
+}
+
+// Returns the extension name prefixed with the class name if nested but without
+// the package name.
+TProtoStringType ExtensionName(const FieldDescriptor* d);
+
+TProtoStringType QualifiedExtensionName(const FieldDescriptor* d,
+ const Options& options);
+TProtoStringType QualifiedExtensionName(const FieldDescriptor* d);
+
+// Type name of default instance.
+TProtoStringType DefaultInstanceType(const Descriptor* descriptor,
+ const Options& options, bool split = false);
+
+// Non-qualified name of the default_instance of this message.
+TProtoStringType DefaultInstanceName(const Descriptor* descriptor,
+ const Options& options, bool split = false);
+
+// Non-qualified name of the default instance pointer. This is used only for
+// implicit weak fields, where we need an extra indirection.
+TProtoStringType DefaultInstancePtr(const Descriptor* descriptor,
+ const Options& options, bool split = false);
+
+// Fully qualified name of the default_instance of this message.
+TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor,
+ const Options& options,
+ bool split = false);
+
+// Fully qualified name of the default instance pointer.
+TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor,
+ const Options& options,
+ bool split = false);
+
+// DescriptorTable variable name.
+TProtoStringType DescriptorTableName(const FileDescriptor* file,
+ const Options& options);
+
+// When declaring symbol externs from another file, this macro will supply the
+// dllexport needed for the target file, if any.
+TProtoStringType FileDllExport(const FileDescriptor* file, const Options& options);
+
+// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
+TProtoStringType SuperClassName(const Descriptor* descriptor,
+ const Options& options);
+
+// Adds an underscore if necessary to prevent conflicting with a keyword.
+TProtoStringType ResolveKeyword(const TProtoStringType& name);
+
+// Get the (unqualified) name that should be used for this field in C++ code.
+// The name is coerced to lower-case to emulate proto1 behavior. People
+// should be using lowercase-with-underscores style for proto field names
+// anyway, so normally this just returns field->name().
+TProtoStringType FieldName(const FieldDescriptor* field);
+
+// Returns the (unqualified) private member name for this field in C++ code.
+TProtoStringType FieldMemberName(const FieldDescriptor* field, bool split);
+
+// Returns an estimate of the compiler's alignment for the field. This
+// can't guarantee to be correct because the generated code could be compiled on
+// different systems with different alignment rules. The estimates below assume
+// 64-bit pointers.
+int EstimateAlignmentSize(const FieldDescriptor* field);
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+TProtoStringType FieldConstantName(const FieldDescriptor* field);
+
+// Returns the scope where the field was defined (for extensions, this is
+// different from the message type to which the field applies).
+inline const Descriptor* FieldScope(const FieldDescriptor* field) {
+ return field->is_extension() ? field->extension_scope()
+ : field->containing_type();
+}
+
+// Returns the fully-qualified type name field->message_type(). Usually this
+// is just ClassName(field->message_type(), true);
+TProtoStringType FieldMessageTypeName(const FieldDescriptor* field,
+ const Options& options);
+
+// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
+const char* PrimitiveTypeName(FieldDescriptor::CppType type);
+TProtoStringType PrimitiveTypeName(const Options& options,
+ FieldDescriptor::CppType type);
+
+// Get the declared type name in CamelCase format, as is used e.g. for the
+// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
+const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
+
+// Return the code that evaluates to the number when compiled.
+TProtoStringType Int32ToString(int number);
+
+// Get code that evaluates to the field's default value.
+TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* field);
+
+// Compatibility function for callers outside proto2.
+TProtoStringType DefaultValue(const FieldDescriptor* field);
+
+// Convert a file name into a valid identifier.
+TProtoStringType FilenameIdentifier(const TProtoStringType& filename);
+
+// For each .proto file generates a unique name. To prevent collisions of
+// symbols in the global namespace
+TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename,
+ const Options& options);
+inline TProtoStringType UniqueName(const TProtoStringType& name, const FileDescriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->name(), options);
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->file(), options);
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name, const EnumDescriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->file(), options);
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name,
+ const ServiceDescriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->file(), options);
+}
+
+// Versions for call sites that only support the internal runtime (like proto1
+// support).
+inline Options InternalRuntimeOptions() {
+ Options options;
+ options.opensource_runtime = false;
+ return options;
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name,
+ const TProtoStringType& filename) {
+ return UniqueName(name, filename, InternalRuntimeOptions());
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name,
+ const FileDescriptor* d) {
+ return UniqueName(name, d->name(), InternalRuntimeOptions());
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d) {
+ return UniqueName(name, d->file(), InternalRuntimeOptions());
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name,
+ const EnumDescriptor* d) {
+ return UniqueName(name, d->file(), InternalRuntimeOptions());
+}
+inline TProtoStringType UniqueName(const TProtoStringType& name,
+ const ServiceDescriptor* d) {
+ return UniqueName(name, d->file(), InternalRuntimeOptions());
+}
+
+// Return the qualified C++ name for a file level symbol.
+TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file,
+ const TProtoStringType& name,
+ const Options& options);
+
+// Escape C++ trigraphs by escaping question marks to \?
+TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape);
+
+// Escaped function name to eliminate naming conflict.
+TProtoStringType SafeFunctionName(const Descriptor* descriptor,
+ const FieldDescriptor* field,
+ const TProtoStringType& prefix);
+
+// Returns true if generated messages have public unknown fields accessors
+inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
+ return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
+FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options);
+
+// Determines whether unknown fields will be stored in an UnknownFieldSet or
+// a string.
+inline bool UseUnknownFieldSet(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
+}
+
+inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
+ if (field->options().weak()) {
+ GOOGLE_CHECK(!options.opensource_runtime);
+ return true;
+ }
+ return false;
+}
+
+bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
+
+// For a string field, returns the effective ctype. If the actual ctype is
+// not supported, returns the default of STRING.
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field,
+ const Options& options);
+
+inline bool IsCord(const FieldDescriptor* field, const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::CORD;
+}
+
+inline bool IsString(const FieldDescriptor* field, const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::STRING;
+}
+
+inline bool IsStringPiece(const FieldDescriptor* field,
+ const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
+}
+
+class MessageSCCAnalyzer;
+
+// Does the given FileDescriptor use lazy fields?
+bool HasLazyFields(const FileDescriptor* file, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+// Is the given field a supported lazy field?
+bool IsLazy(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+// Is this an explicit (non-profile driven) lazy field, as denoted by
+// lazy/unverified_lazy in the descriptor?
+inline bool IsExplicitLazy(const FieldDescriptor* field) {
+ return field->options().lazy() || field->options().unverified_lazy();
+}
+
+bool IsEagerlyVerifiedLazy(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+bool IsLazilyVerifiedLazy(const FieldDescriptor* field, const Options& options);
+
+// Is the given message being split (go/pdsplit)?
+bool ShouldSplit(const Descriptor* desc, const Options& options);
+
+// Is the given field being split out?
+bool ShouldSplit(const FieldDescriptor* field, const Options& options);
+
+inline bool IsFieldUsed(const FieldDescriptor* /* field */,
+ const Options& /* options */) {
+ return true;
+}
+
+// Returns true if "field" is stripped.
+inline bool IsFieldStripped(const FieldDescriptor* /*field*/,
+ const Options& /*options*/) {
+ return false;
+}
+
+// Does the file contain any definitions that need extension_set.h?
+bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
+
+// Does the file have any repeated fields, necessitating the file to include
+// repeated_field.h? This does not include repeated extensions, since those are
+// all stored internally in an ExtensionSet, not a separate RepeatedField*.
+bool HasRepeatedFields(const FileDescriptor* file);
+
+// Does the file have any string/bytes fields with ctype=STRING_PIECE? This
+// does not include extensions, since ctype is ignored for extensions.
+bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
+
+// Does the file have any string/bytes fields with ctype=CORD? This does not
+// include extensions, since ctype is ignored for extensions.
+bool HasCordFields(const FileDescriptor* file, const Options& options);
+
+// Does the file have any map fields, necessitating the file to include
+// map_field_inl.h and map.h.
+bool HasMapFields(const FileDescriptor* file);
+
+// Does this file have any enum type definitions?
+bool HasEnumDefinitions(const FileDescriptor* file);
+
+// Does this file have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+inline bool HasGeneratedMethods(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
+}
+
+// Do message classes in this file have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor* file,
+ const Options& options) {
+ return file->service_count() > 0 &&
+ GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
+ file->options().cc_generic_services();
+}
+
+inline bool IsProto2MessageSet(const Descriptor* descriptor,
+ const Options& options) {
+ return !options.opensource_runtime &&
+ options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
+ !options.lite_implicit_weak_fields &&
+ descriptor->options().message_set_wire_format() &&
+ descriptor->full_name() == "google.protobuf.bridge.MessageSet";
+}
+
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+// Returns true if the field's CPPTYPE is string or message.
+bool IsStringOrMessage(const FieldDescriptor* field);
+
+TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input,
+ bool cap_next_letter);
+
+inline bool IsProto3(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool HasHasbit(const FieldDescriptor* field) {
+ // This predicate includes proto3 message fields only if they have "optional".
+ // Foo submsg1 = 1; // HasHasbit() == false
+ // optional Foo submsg2 = 2; // HasHasbit() == true
+ // This is slightly odd, as adding "optional" to a singular proto3 field does
+ // not change the semantics or API. However whenever any field in a message
+ // has a hasbit, it forces reflection to include hasbit offsets for *all*
+ // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
+ // causing a sudden size regression for ~all proto3 messages, we give proto3
+ // message fields a hasbit only if "optional" is present. If the user is
+ // explicitly writing "optional", it is likely they are writing it on
+ // primitive fields also.
+ return (field->has_optional_keyword() || field->is_required()) &&
+ !field->options().weak();
+}
+
+// Returns true if 'enum' semantics are such that unknown values are preserved
+// in the enum field itself, rather than going to the UnknownFieldSet.
+inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
+ return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsCrossFileMessage(const FieldDescriptor* field) {
+ return field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ field->message_type()->file() != field->file();
+}
+
+inline TProtoStringType MakeDefaultName(const FieldDescriptor* field) {
+ return StrCat("_i_give_permission_to_break_this_code_default_",
+ FieldName(field), "_");
+}
+
+// Semantically distinct from MakeDefaultName in that it gives the C++ code
+// referencing a default field from the message scope, rather than just the
+// variable name.
+// For example, declarations of default variables should always use just
+// MakeDefaultName to produce code like:
+// Type _i_give_permission_to_break_this_code_default_field_;
+//
+// Code that references these should use MakeDefaultFieldName, in case the field
+// exists at some nested level like:
+// internal_container_._i_give_permission_to_break_this_code_default_field_;
+inline TProtoStringType MakeDefaultFieldName(const FieldDescriptor* field) {
+ return StrCat("Impl_::", MakeDefaultName(field));
+}
+
+inline TProtoStringType MakeVarintCachedSizeName(const FieldDescriptor* field) {
+ return StrCat("_", FieldName(field), "_cached_byte_size_");
+}
+
+// Semantically distinct from MakeVarintCachedSizeName in that it gives the C++
+// code referencing the object from the message scope, rather than just the
+// variable name.
+// For example, declarations of default variables should always use just
+// MakeVarintCachedSizeName to produce code like:
+// Type _field_cached_byte_size_;
+//
+// Code that references these variables should use
+// MakeVarintCachedSizeFieldName, in case the field exists at some nested level
+// like:
+// internal_container_._field_cached_byte_size_;
+inline TProtoStringType MakeVarintCachedSizeFieldName(const FieldDescriptor* field,
+ bool split) {
+ return StrCat("_impl_.", split ? "_split_->" : "", "_",
+ FieldName(field), "_cached_byte_size_");
+}
+
+// Note: A lot of libraries detect Any protos based on Descriptor::full_name()
+// while the two functions below use FileDescriptor::name(). In a sane world the
+// two approaches should be equivalent. But if you are dealing with descriptors
+// from untrusted sources, you might need to match semantics across libraries.
+bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options);
+bool IsAnyMessage(const Descriptor* descriptor, const Options& options);
+
+bool IsWellKnownMessage(const FileDescriptor* descriptor);
+
+inline TProtoStringType IncludeGuard(const FileDescriptor* file, bool pb_h,
+ bool deps,
+ const Options& options) {
+ // If we are generating a .pb.h file and the proto_h option is enabled, then
+ // the .pb.h gets an extra suffix.
+ TProtoStringType filename_identifier = FilenameIdentifier(
+ file->name() + (deps ? ".deps": "") + (pb_h && options.proto_h ? ".pb.h" : ""));
+
+ if (IsWellKnownMessage(file)) {
+ // For well-known messages we need third_party/protobuf and net/proto2 to
+ // have distinct include guards, because some source files include both and
+ // both need to be defined (the third_party copies will be in the
+ // google::protobuf_opensource namespace).
+ return MacroPrefix(options) + "_INCLUDED_" + filename_identifier;
+ } else {
+ // Ideally this case would use distinct include guards for opensource and
+ // google3 protos also. (The behavior of "first #included wins" is not
+ // ideal). But unfortunately some legacy code includes both and depends on
+ // the identical include guards to avoid compile errors.
+ //
+ // We should clean this up so that this case can be removed.
+ return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier;
+ }
+}
+
+// Returns the OptimizeMode for this file, furthermore it updates a status
+// bool if has_opt_codesize_extension is non-null. If this status bool is true
+// it means this file contains an extension that itself is defined as
+// optimized_for = CODE_SIZE.
+FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options,
+ bool* has_opt_codesize_extension);
+inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options, nullptr);
+}
+inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
+ const Options& options) {
+ bool has_opt_codesize_extension;
+ if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
+ FileOptions::CODE_SIZE &&
+ has_opt_codesize_extension) {
+ // If this filedescriptor contains an extension from another file which
+ // is optimized_for = CODE_SIZE. We need to be careful in the ordering so
+ // we eagerly build the descriptors in the dependencies before building
+ // the descriptors of this file.
+ return true;
+ } else {
+ // If we have a generated code based parser we never need eager
+ // initialization of descriptors of our deps.
+ return false;
+ }
+}
+
+// This orders the messages in a .pb.cc as it's outputted by file.cc
+void FlattenMessagesInFile(const FileDescriptor* file,
+ std::vector<const Descriptor*>* result);
+inline std::vector<const Descriptor*> FlattenMessagesInFile(
+ const FileDescriptor* file) {
+ std::vector<const Descriptor*> result;
+ FlattenMessagesInFile(file, &result);
+ return result;
+}
+
+template <typename F>
+void ForEachMessage(const Descriptor* descriptor, F&& func) {
+ for (int i = 0; i < descriptor->nested_type_count(); i++)
+ ForEachMessage(descriptor->nested_type(i), std::forward<F&&>(func));
+ func(descriptor);
+}
+
+template <typename F>
+void ForEachMessage(const FileDescriptor* descriptor, F&& func) {
+ for (int i = 0; i < descriptor->message_type_count(); i++)
+ ForEachMessage(descriptor->message_type(i), std::forward<F&&>(func));
+}
+
+bool HasWeakFields(const Descriptor* desc, const Options& options);
+bool HasWeakFields(const FileDescriptor* desc, const Options& options);
+
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
+ const Options& options) {
+ // Do not check "required" for lazily verified lazy fields.
+ return IsLazilyVerifiedLazy(field, options);
+}
+
+struct MessageAnalysis {
+ bool is_recursive = false;
+ bool contains_cord = false;
+ bool contains_extension = false;
+ bool contains_required = false;
+ bool contains_weak = false; // Implicit weak as well.
+};
+
+// This class is used in FileGenerator, to ensure linear instead of
+// quadratic performance, if we do this per message we would get O(V*(V+E)).
+// Logically this is just only used in message.cc, but in the header for
+// FileGenerator to help share it.
+class PROTOC_EXPORT MessageSCCAnalyzer {
+ public:
+ explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
+
+ MessageAnalysis GetSCCAnalysis(const SCC* scc);
+
+ bool HasRequiredFields(const Descriptor* descriptor) {
+ MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
+ return result.contains_required || result.contains_extension;
+ }
+ bool HasWeakField(const Descriptor* descriptor) {
+ MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
+ return result.contains_weak;
+ }
+ const SCC* GetSCC(const Descriptor* descriptor) {
+ return analyzer_.GetSCC(descriptor);
+ }
+
+ private:
+ struct DepsGenerator {
+ std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
+ std::vector<const Descriptor*> deps;
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (desc->field(i)->message_type()) {
+ deps.push_back(desc->field(i)->message_type());
+ }
+ }
+ return deps;
+ }
+ };
+ SCCAnalyzer<DepsGenerator> analyzer_;
+ Options options_;
+ std::map<const SCC*, MessageAnalysis> analysis_cache_;
+};
+
+void ListAllFields(const Descriptor* d,
+ std::vector<const FieldDescriptor*>* fields);
+void ListAllFields(const FileDescriptor* d,
+ std::vector<const FieldDescriptor*>* fields);
+
+template <class T>
+void ForEachField(const Descriptor* d, T&& func) {
+ for (int i = 0; i < d->nested_type_count(); i++) {
+ ForEachField(d->nested_type(i), std::forward<T&&>(func));
+ }
+ for (int i = 0; i < d->extension_count(); i++) {
+ func(d->extension(i));
+ }
+ for (int i = 0; i < d->field_count(); i++) {
+ func(d->field(i));
+ }
+}
+
+template <class T>
+void ForEachField(const FileDescriptor* d, T&& func) {
+ for (int i = 0; i < d->message_type_count(); i++) {
+ ForEachField(d->message_type(i), std::forward<T&&>(func));
+ }
+ for (int i = 0; i < d->extension_count(); i++) {
+ func(d->extension(i));
+ }
+}
+
+void ListAllTypesForServices(const FileDescriptor* fd,
+ std::vector<const Descriptor*>* types);
+
+// Indicates whether we should use implicit weak fields for this file.
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+ const Options& options);
+
+// Indicates whether to treat this field as implicitly weak.
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+inline bool HasSimpleBaseClass(const Descriptor* desc, const Options& options) {
+ if (!HasDescriptorMethods(desc->file(), options)) return false;
+ if (desc->extension_range_count() != 0) return false;
+ if (desc->field_count() == 0) return true;
+ // TODO(jorg): Support additional common message types with only one
+ // or two fields
+ return false;
+}
+
+inline bool HasSimpleBaseClasses(const FileDescriptor* file,
+ const Options& options) {
+ bool v = false;
+ ForEachMessage(file, [&v, &options](const Descriptor* desc) {
+ v |= HasSimpleBaseClass(desc, options);
+ });
+ return v;
+}
+
+inline TProtoStringType SimpleBaseClass(const Descriptor* desc,
+ const Options& options) {
+ if (!HasDescriptorMethods(desc->file(), options)) return "";
+ if (desc->extension_range_count() != 0) return "";
+ if (desc->field_count() == 0) {
+ return "ZeroFieldsBase";
+ }
+ // TODO(jorg): Support additional common message types with only one
+ // or two fields
+ return "";
+}
+
+// Returns true if this message has a _tracker_ field.
+inline bool HasTracker(const Descriptor* desc, const Options& options) {
+ return options.field_listener_options.inject_field_listener_events &&
+ desc->file()->options().optimize_for() !=
+ google::protobuf::FileOptions::LITE_RUNTIME;
+}
+
+// Returns true if this message needs an Impl_ struct for it's data.
+inline bool HasImplData(const Descriptor* desc, const Options& options) {
+ return !HasSimpleBaseClass(desc, options);
+}
+
+// Formatter is a functor class which acts as a closure around printer and
+// the variable map. It's much like printer->Print except it supports both named
+// variables that are substituted using a key value map and direct arguments. In
+// the format string $1$, $2$, etc... are substituted for the first, second, ...
+// direct argument respectively in the format call, it accepts both strings and
+// integers. The implementation verifies all arguments are used and are "first"
+// used in order of appearance in the argument list. For example,
+//
+// Format("return array[$1$];", 3) -> "return array[3];"
+// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order)
+// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;"
+//
+// The arguments can be used more than once like
+//
+// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") ->
+// "array[3] = Bla; // Index = 3"
+//
+// If you use more arguments use the following style to help the reader,
+//
+// Format("int $1$() {\n"
+// " array[$2$] = $3$;\n"
+// " return $4$;"
+// "}\n",
+// funname, // 1
+// idx, // 2
+// varname, // 3
+// retval); // 4
+//
+// but consider using named variables. Named variables like $foo$, with some
+// identifier foo, are looked up in the map. One additional feature is that
+// spaces are accepted between the '$' delimiters, $ foo$ will
+// substitute to " bar" if foo stands for "bar", but in case it's empty
+// will substitute to "". Hence, for example,
+//
+// Format(vars, "$dllexport $void fun();") -> "void fun();"
+// "__declspec(export) void fun();"
+//
+// which is convenient to prevent double, leading or trailing spaces.
+class PROTOC_EXPORT Formatter {
+ public:
+ explicit Formatter(io::Printer* printer) : printer_(printer) {}
+ Formatter(io::Printer* printer,
+ const std::map<TProtoStringType, TProtoStringType>& vars)
+ : printer_(printer), vars_(vars) {}
+
+ template <typename T>
+ void Set(const TProtoStringType& key, const T& value) {
+ vars_[key] = ToString(value);
+ }
+
+ void AddMap(const std::map<TProtoStringType, TProtoStringType>& vars) {
+ for (const auto& keyval : vars) vars_[keyval.first] = keyval.second;
+ }
+
+ template <typename... Args>
+ void operator()(const char* format, const Args&... args) const {
+ printer_->FormatInternal({ToString(args)...}, vars_, format);
+ }
+
+ void Indent() const { printer_->Indent(); }
+ void Outdent() const { printer_->Outdent(); }
+ io::Printer* printer() const { return printer_; }
+
+ class PROTOC_EXPORT ScopedIndenter {
+ public:
+ explicit ScopedIndenter(Formatter* format) : format_(format) {
+ format_->Indent();
+ }
+ ~ScopedIndenter() { format_->Outdent(); }
+
+ private:
+ Formatter* format_;
+ };
+
+ PROTOBUF_NODISCARD ScopedIndenter ScopedIndent() {
+ return ScopedIndenter(this);
+ }
+ template <typename... Args>
+ PROTOBUF_NODISCARD ScopedIndenter ScopedIndent(const char* format,
+ const Args&&... args) {
+ (*this)(format, static_cast<Args&&>(args)...);
+ return ScopedIndenter(this);
+ }
+
+ class PROTOC_EXPORT SaveState {
+ public:
+ explicit SaveState(Formatter* format)
+ : format_(format), vars_(format->vars_) {}
+ ~SaveState() { format_->vars_.swap(vars_); }
+
+ private:
+ Formatter* format_;
+ std::map<TProtoStringType, TProtoStringType> vars_;
+ };
+
+ private:
+ io::Printer* printer_;
+ std::map<TProtoStringType, TProtoStringType> vars_;
+
+ // Convenience overloads to accept different types as arguments.
+ static TProtoStringType ToString(const TProtoStringType& s) { return s; }
+ template <typename I, typename = typename std::enable_if<
+ std::is_integral<I>::value>::type>
+ static TProtoStringType ToString(I x) {
+ return StrCat(x);
+ }
+ static TProtoStringType ToString(strings::Hex x) { return StrCat(x); }
+ static TProtoStringType ToString(const FieldDescriptor* d) { return Payload(d); }
+ static TProtoStringType ToString(const Descriptor* d) { return Payload(d); }
+ static TProtoStringType ToString(const EnumDescriptor* d) { return Payload(d); }
+ static TProtoStringType ToString(const EnumValueDescriptor* d) {
+ return Payload(d);
+ }
+ static TProtoStringType ToString(const OneofDescriptor* d) { return Payload(d); }
+
+ template <typename Descriptor>
+ static TProtoStringType Payload(const Descriptor* descriptor) {
+ std::vector<int> path;
+ descriptor->GetLocationPath(&path);
+ GeneratedCodeInfo::Annotation annotation;
+ for (int index : path) {
+ annotation.add_path(index);
+ }
+ annotation.set_source_file(descriptor->file()->name());
+ return annotation.SerializeAsString();
+ }
+};
+
+template <class T>
+void PrintFieldComment(const Formatter& format, const T* field) {
+ // Print the field's (or oneof's) proto-syntax definition as a comment.
+ // We don't want to print group bodies so we cut off after the first
+ // line.
+ DebugStringOptions options;
+ options.elide_group_body = true;
+ options.elide_oneof_body = true;
+ TProtoStringType def = field->DebugStringWithOptions(options);
+ format("// $1$\n", def.substr(0, def.find_first_of('\n')));
+}
+
+class PROTOC_EXPORT NamespaceOpener {
+ public:
+ explicit NamespaceOpener(const Formatter& format)
+ : printer_(format.printer()) {}
+ NamespaceOpener(const TProtoStringType& name, const Formatter& format)
+ : NamespaceOpener(format) {
+ ChangeTo(name);
+ }
+ ~NamespaceOpener() { ChangeTo(""); }
+
+ void ChangeTo(const TProtoStringType& name) {
+ std::vector<TProtoStringType> new_stack_ =
+ Split(name, "::", true);
+ 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++;
+ }
+ for (auto it = name_stack_.crbegin();
+ it != name_stack_.crend() - common_idx; ++it) {
+ if (*it == "PROTOBUF_NAMESPACE_ID") {
+ printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n");
+ } else {
+ printer_->Print("} // namespace $ns$\n", "ns", *it);
+ }
+ }
+ name_stack_.swap(new_stack_);
+ for (size_t i = common_idx; i < name_stack_.size(); ++i) {
+ if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
+ printer_->Print("PROTOBUF_NAMESPACE_OPEN\n");
+ } else {
+ printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
+ }
+ }
+ }
+
+ private:
+ io::Printer* printer_;
+ std::vector<TProtoStringType> name_stack_;
+};
+
+enum class Utf8CheckMode {
+ kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields.
+ kVerify = 1, // Only log an error but parsing will succeed.
+ kNone = 2, // No UTF-8 check.
+};
+
+Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+ const Options& options);
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const Formatter& format);
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const Formatter& format);
+
+template <typename T>
+struct FieldRangeImpl {
+ struct Iterator {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const FieldDescriptor*;
+ using difference_type = int;
+
+ value_type operator*() { return descriptor->field(idx); }
+
+ friend bool operator==(const Iterator& a, const Iterator& b) {
+ GOOGLE_DCHECK(a.descriptor == b.descriptor);
+ return a.idx == b.idx;
+ }
+ friend bool operator!=(const Iterator& a, const Iterator& b) {
+ return !(a == b);
+ }
+
+ Iterator& operator++() {
+ idx++;
+ return *this;
+ }
+
+ int idx;
+ const T* descriptor;
+ };
+
+ Iterator begin() const { return {0, descriptor}; }
+ Iterator end() const { return {descriptor->field_count(), descriptor}; }
+
+ const T* descriptor;
+};
+
+template <typename T>
+FieldRangeImpl<T> FieldRange(const T* desc) {
+ return {desc};
+}
+
+struct OneOfRangeImpl {
+ struct Iterator {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const OneofDescriptor*;
+ using difference_type = int;
+
+ value_type operator*() { return descriptor->oneof_decl(idx); }
+
+ friend bool operator==(const Iterator& a, const Iterator& b) {
+ GOOGLE_DCHECK(a.descriptor == b.descriptor);
+ return a.idx == b.idx;
+ }
+ friend bool operator!=(const Iterator& a, const Iterator& b) {
+ return !(a == b);
+ }
+
+ Iterator& operator++() {
+ idx++;
+ return *this;
+ }
+
+ int idx;
+ const Descriptor* descriptor;
+ };
+
+ Iterator begin() const { return {0, descriptor}; }
+ Iterator end() const {
+ return {descriptor->real_oneof_decl_count(), descriptor};
+ }
+
+ const Descriptor* descriptor;
+};
+
+inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
+
+PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename);
+
+bool EnableMessageOwnedArena(const Descriptor* desc, const Options& options);
+
+bool EnableMessageOwnedArenaTrial(const Descriptor* desc,
+ const Options& options);
+
+bool ShouldVerify(const Descriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+bool ShouldVerify(const FileDescriptor* file, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+// Indicates whether to use predefined verify methods for a given message. If a
+// message is "simple" and needs no special verification per field (e.g. message
+// field, repeated packed, UTF8 string, etc.), we can use either VerifySimple or
+// VerifySimpleAlwaysCheckInt32 methods as all verification can be done based on
+// the wire type.
+//
+// Otherwise, we need "custom" verify methods tailored to a message to pass
+// which field needs a special verification; i.e. InternalVerify.
+enum class VerifySimpleType {
+ kSimpleInt32Never, // Use VerifySimple
+ kSimpleInt32Always, // Use VerifySimpleAlwaysCheckInt32
+ kCustom, // Use InternalVerify and check only for int32
+ kCustomInt32Never, // Use InternalVerify but never check for int32
+ kCustomInt32Always, // Use InternalVerify and always check for int32
+};
+
+// Returns VerifySimpleType if messages can be verified by predefined methods.
+VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor);
+
+bool IsUtf8String(const FieldDescriptor* field);
+
+bool HasMessageFieldOrExtension(const Descriptor* desc);
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.cc
index 4d3e00ac89b..ba363f5267b 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.cc
@@ -28,12 +28,12 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <google/protobuf/compiler/cpp/cpp_map_field.h>
+#include <google/protobuf/compiler/cpp/map_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
@@ -136,6 +136,7 @@ void MapFieldGenerator::GenerateInlineAccessorDefinitions(
"}\n"
"inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
"$classname$::_internal_mutable_$name$() {\n"
+ "$maybe_prepare_split_message$"
" return $field$.MutableMap();\n"
"}\n"
"inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
@@ -153,7 +154,7 @@ void MapFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$field$.MergeFrom(from.$field$);\n");
+ format("_this->$field$.MergeFrom(from.$field$);\n");
}
void MapFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
@@ -226,8 +227,7 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizesToArray(
format);
}
}
- format(
- "};\n");
+ format("};\n");
}
format(
@@ -271,21 +271,48 @@ void MapFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
"false;\n");
}
-void MapFieldGenerator::GenerateConstinitInitializer(
+void MapFieldGenerator::GenerateConstexprAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (HasDescriptorMethods(descriptor_->file(), options_)) {
- format("$name$_(::$proto_ns$::internal::ConstantInitialized{})");
+ format("/*decltype($field$)*/{::_pbi::ConstantInitialized()}");
} else {
- format("$name$_()");
+ format("/*decltype($field$)*/{}");
+ }
+}
+
+void MapFieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ // MapField has no move constructor, which prevents explicit aggregate
+ // initialization pre-C++17.
+ format("/*decltype($field$)*/{}");
+}
+
+void MapFieldGenerator::GenerateAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (ShouldSplit(descriptor_, options_)) {
+ format(
+ "/*decltype($classname$::Split::$name$_)*/"
+ "{::_pbi::ArenaInitialized(), arena}");
+ return;
}
+ // MapField has no move constructor.
+ format("/*decltype($field$)*/{::_pbi::ArenaInitialized(), arena}");
}
void MapFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
+ if (ShouldSplit(descriptor_, options_)) {
+ format("$cached_split_ptr$->$name$_.Destruct();\n");
+ format("$cached_split_ptr$->$name$_.~MapField$lite$();\n");
+ return;
+ }
format("$field$.Destruct();\n");
+ format("$field$.~MapField$lite$();\n");
}
void MapFieldGenerator::GenerateArenaDestructorCode(
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_map_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h
index 9e71267c0f1..678a128bd18 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h
@@ -34,8 +34,8 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/message_field.h>
namespace google {
namespace protobuf {
@@ -61,7 +61,10 @@ class MapFieldGenerator : public FieldGenerator {
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateArenaDestructorCode(io::Printer* printer) const override;
ArenaDtorNeeds NeedsArenaDestructor() const override;
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc
index a56c6fbda1e..77702a68dfc 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc
@@ -32,7 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_message.h>
+#include <google/protobuf/compiler/cpp/message.h>
#include <algorithm>
#include <cstdint>
@@ -51,13 +51,14 @@
#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/cpp/cpp_enum.h>
-#include <google/protobuf/compiler/cpp/cpp_extension.h>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
-#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
+#include <google/protobuf/compiler/cpp/enum.h>
+#include <google/protobuf/compiler/cpp/extension.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/padding_optimizer.h>
+#include <google/protobuf/compiler/cpp/parse_function_generator.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/hash.h>
@@ -83,7 +84,7 @@ static constexpr int kNoHasbit = -1;
// masks must be non-zero.
TProtoStringType ConditionalToCheckBitmasks(
const std::vector<arc_ui32>& masks, bool return_success = true,
- StringPiece has_bits_var = "_has_bits_") {
+ StringPiece has_bits_var = "_impl_._has_bits_") {
std::vector<TProtoStringType> parts;
for (int i = 0; i < masks.size(); i++) {
if (masks[i] == 0) continue;
@@ -345,10 +346,10 @@ bool IsRequired(const std::vector<const FieldDescriptor*>& v) {
return v.front()->is_required();
}
-bool HasSingularString(const Descriptor* desc, const Options& options) {
+bool HasNonSplitOptionalString(const Descriptor* desc, const Options& options) {
for (const auto* field : FieldRange(desc)) {
if (IsString(field, options) && !field->is_repeated() &&
- !field->real_containing_oneof()) {
+ !field->real_containing_oneof() && !ShouldSplit(field, options)) {
return true;
}
}
@@ -403,7 +404,7 @@ static int popcnt(arc_ui32 n) {
class ColdChunkSkipper {
public:
ColdChunkSkipper(
- const Options& options,
+ const Descriptor* descriptor, const Options& options,
const std::vector<std::vector<const FieldDescriptor*>>& chunks,
const std::vector<int>& has_bit_indices, const double cold_threshold)
: chunks_(chunks),
@@ -411,7 +412,7 @@ class ColdChunkSkipper {
access_info_map_(options.access_info_map),
cold_threshold_(cold_threshold) {
SetCommonVars(options, &variables_);
- SetCommonMessageDataVariables(&variables_);
+ SetCommonMessageDataVariables(descriptor, &variables_);
}
// May open an external if check for a batch of cold fields. "from" is the
@@ -495,7 +496,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index,
if (this_word == cached_has_word_index) {
format("(cached_has_bits & 0x$mask$u) != 0");
} else {
- format("($1$_has_bits_[$2$] & 0x$mask$u) != 0", from, this_word);
+ format("($1$_impl_._has_bits_[$2$] & 0x$mask$u) != 0", from, this_word);
}
}
format(")) {\n");
@@ -547,9 +548,7 @@ void GenerateExtensionAnnotations(
for (const auto& annotation : accessor_annotations_to_hooks) {
(*variables)[annotation.first] = "";
}
- if (!options.field_listener_options.inject_field_listener_events ||
- descriptor->file()->options().optimize_for() ==
- google::protobuf::FileOptions::LITE_RUNTIME) {
+ if (!HasTracker(descriptor, options)) {
return;
}
StringPiece tracker = (*variables)["tracker"];
@@ -617,7 +616,7 @@ MessageGenerator::MessageGenerator(
if (!message_layout_helper_) {
message_layout_helper_.reset(new PaddingOptimizer());
}
- SetCommonMessageDataVariables(&variables_);
+ SetCommonMessageDataVariables(descriptor, &variables_);
// Variables that apply to this class
variables_["classname"] = classname_;
@@ -630,9 +629,7 @@ MessageGenerator::MessageGenerator(
variables_["annotate_bytesize"] = "";
variables_["annotate_mergefrom"] = "";
- if (options.field_listener_options.inject_field_listener_events &&
- descriptor->file()->options().optimize_for() !=
- google::protobuf::FileOptions::LITE_RUNTIME) {
+ if (HasTracker(descriptor_, options_)) {
const TProtoStringType injector_template =
StrCat(" ", variables_["tracker"], ".");
@@ -649,7 +646,7 @@ MessageGenerator::MessageGenerator(
MaySetAnnotationVariable(options, "bytesize", injector_template,
"OnByteSize(this);\n", &variables_);
MaySetAnnotationVariable(options, "mergefrom", injector_template,
- "OnMergeFrom(this, &from);\n", &variables_);
+ "OnMergeFrom(_this, &from);\n", &variables_);
}
GenerateExtensionAnnotations(descriptor_, options_, &variables_);
@@ -1205,6 +1202,9 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
format.Outdent();
format("}\n");
} else {
+ if (ShouldSplit(field, options_)) {
+ format("if (IsSplitMessageDefault()) return;\n");
+ }
field_generators_.get(field).GenerateClearingCode(format.printer());
if (HasHasbit(field)) {
int has_bit_index = HasBitIndex(field);
@@ -1245,13 +1245,12 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
} else {
format(
"inline int $classname$::_internal_$name$_size() const {\n"
- " return $1$$2$.size();\n"
+ " return $field$$1$.size();\n"
"}\n"
"inline int $classname$::$name$_size() const {\n"
"$annotate_size$"
" return _internal_$name$_size();\n"
"}\n",
- FieldMemberName(field),
IsImplicitWeakField(field, options_, scc_analyzer_) &&
field->message_type()
? ".weak"
@@ -1398,6 +1397,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
format(
"inline $classname$() : $classname$("
"::$proto_ns$::Arena::InternalCreateMessageOwnedArena(), true) {}\n");
+ } else if (EnableMessageOwnedArenaTrial(descriptor_, options_)) {
+ format(
+ "inline $classname$() : $classname$(InMoaTrial() ? "
+ "::$proto_ns$::Arena::InternalCreateMessageOwnedArena() : nullptr, "
+ "InMoaTrial()) {}\n");
} else {
format("inline $classname$() : $classname$(nullptr) {}\n");
}
@@ -1510,11 +1514,13 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"bool PackFrom(const ::$proto_ns$::Message& message) {\n"
+ " $DCHK$_NE(&message, this);\n"
" return $any_metadata$.PackFrom(GetArena(), message);\n"
"}\n"
"bool PackFrom(const ::$proto_ns$::Message& message,\n"
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
"type_url_prefix) {\n"
+ " $DCHK$_NE(&message, this);\n"
" return $any_metadata$.PackFrom(GetArena(), message, "
"type_url_prefix);\n"
"}\n"
@@ -1618,27 +1624,28 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
// argument is a generic Message instance, and only define the
// custom MergeFrom and CopyFrom instances when the source of the
// merge/copy is known to be the same class as the destination.
- // TODO(jorg): Define MergeFrom in terms of MergeImpl, rather than
- // the other way around, to save even more code size.
"using $superclass$::CopyFrom;\n"
"void CopyFrom(const $classname$& from);\n"
""
"using $superclass$::MergeFrom;\n"
- "void MergeFrom(const $classname$& from);\n"
+ "void MergeFrom("
+ " const $classname$& from) {\n"
+ " $classname$::MergeImpl(*this, from);\n"
+ "}\n"
"private:\n"
- "static void MergeImpl(::$proto_ns$::Message* to, const "
- "::$proto_ns$::Message& from);\n"
+ "static void MergeImpl(::$proto_ns$::Message& to_msg, const "
+ "::$proto_ns$::Message& from_msg);\n"
"public:\n");
} else {
format(
"using $superclass$::CopyFrom;\n"
"inline void CopyFrom(const $classname$& from) {\n"
- " $superclass$::CopyImpl(this, from);\n"
+ " $superclass$::CopyImpl(*this, from);\n"
"}\n"
""
"using $superclass$::MergeFrom;\n"
"void MergeFrom(const $classname$& from) {\n"
- " $superclass$::MergeImpl(this, from);\n"
+ " $superclass$::MergeImpl(*this, from);\n"
"}\n"
"public:\n");
}
@@ -1676,7 +1683,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
"int GetCachedSize() const final { return "
"$cached_size$.Get(); }"
"\n\nprivate:\n"
- "void SharedCtor();\n"
+ "void SharedCtor(::$proto_ns$::Arena* arena, bool is_message_owned);\n"
"void SharedDtor();\n"
"void SetCachedSize(int size) const$ full_final$;\n"
"void InternalSwap($classname$* other);\n");
@@ -1747,6 +1754,17 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
"\n");
}
+ if (ShouldSplit(descriptor_, options_)) {
+ format(
+ "private:\n"
+ "inline bool IsSplitMessageDefault() const {\n"
+ " return $split$ == reinterpret_cast<Impl_::Split*>(&$1$);\n"
+ "}\n"
+ "PROTOBUF_NOINLINE void PrepareSplitMessageForWrite();\n"
+ "public:\n",
+ DefaultInstanceName(descriptor_, options_, /*split=*/true));
+ }
+
format(
"// nested types ----------------------------------------------------\n"
"\n");
@@ -1837,12 +1855,21 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
: StrCat("::$proto_ns$::internal::HasBits<",
sizeof_has_bits, "> _has_bits_;\n");
+ format(
+ "template <typename T> friend class "
+ "::$proto_ns$::Arena::InternalHelper;\n"
+ "typedef void InternalArenaConstructable_;\n"
+ "typedef void DestructorSkippable_;\n");
+
// To minimize padding, data members are divided into three sections:
// (1) members assumed to align to 8 bytes
// (2) members corresponding to message fields, re-ordered to optimize
// alignment.
// (3) members assumed to align to 4 bytes.
+ format("struct Impl_ {\n");
+ format.Indent();
+
// Members assumed to align to 8 bytes:
if (descriptor_->extension_range_count() > 0) {
@@ -1851,9 +1878,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
"\n");
}
- if (options_.field_listener_options.inject_field_listener_events &&
- descriptor_->file()->options().optimize_for() !=
- google::protobuf::FileOptions::LITE_RUNTIME) {
+ if (HasTracker(descriptor_, options_)) {
format("static ::$proto_ns$::AccessListener<$1$> _tracker_;\n",
ClassName(descriptor_));
}
@@ -1866,12 +1891,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
InlinedStringDonatedSize());
}
- format(
- "template <typename T> friend class "
- "::$proto_ns$::Arena::InternalHelper;\n"
- "typedef void InternalArenaConstructable_;\n"
- "typedef void DestructorSkippable_;\n");
-
if (!has_bit_indices_.empty()) {
// _has_bits_ is frequently accessed, so to reduce code size and improve
// speed, it should be close to the start of the object. Placing
@@ -1890,7 +1909,24 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
for (auto field : optimized_order_) {
const FieldGenerator& generator = field_generators_.get(field);
generator.GenerateStaticMembers(printer);
- generator.GeneratePrivateMembers(printer);
+ if (!ShouldSplit(field, options_)) {
+ generator.GeneratePrivateMembers(printer);
+ }
+ }
+ if (ShouldSplit(descriptor_, options_)) {
+ format("struct Split {\n");
+ format.Indent();
+ for (auto field : optimized_order_) {
+ if (!ShouldSplit(field, options_)) continue;
+ const FieldGenerator& generator = field_generators_.get(field);
+ generator.GeneratePrivateMembers(printer);
+ }
+ format.Outdent();
+ format(
+ " typedef void InternalArenaConstructable_;\n"
+ " typedef void DestructorSkippable_;\n"
+ "};\n"
+ "Split* _split_;\n");
}
// For each oneof generate a union
@@ -1941,6 +1977,22 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n");
}
+ format.Outdent();
+ format("};\n");
+
+ // Only create the _impl_ field if it contains data.
+ if (HasImplData(descriptor_, options_)) {
+ format("union { Impl_ _impl_; };\n");
+ }
+
+ if (ShouldSplit(descriptor_, options_)) {
+ format(
+ "static Impl_::Split* CreateSplitMessage("
+ "::$proto_ns$::Arena* arena);\n");
+ format("friend struct $1$;\n",
+ DefaultInstanceType(descriptor_, options_, /*split=*/true));
+ }
+
// The TableStruct struct needs access to the private parts, in order to
// construct the offsets of all members.
format("friend struct ::$tablename$;\n");
@@ -2080,7 +2132,8 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
format("};\n\n");
for (auto field : FieldRange(descriptor_)) {
if (!IsFieldStripped(field, options_)) {
- field_generators_.get(field).GenerateInternalAccessorDefinitions(printer);
+ field_generators_.get(field).GenerateInternalAccessorDefinitions(
+ printer);
}
}
@@ -2130,7 +2183,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
GenerateMergeFrom(printer);
format("\n");
- GenerateClassSpecificMergeFrom(printer);
+ GenerateClassSpecificMergeImpl(printer);
format("\n");
GenerateCopyFrom(printer);
@@ -2140,6 +2193,15 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
format("\n");
}
+ if (ShouldSplit(descriptor_, options_)) {
+ format(
+ "void $classname$::PrepareSplitMessageForWrite() {\n"
+ " if (IsSplitMessageDefault()) {\n"
+ " $split$ = CreateSplitMessage(GetArenaForAllocation());\n"
+ " }\n"
+ "}\n");
+ }
+
GenerateVerify(printer);
GenerateSwap(printer);
@@ -2172,9 +2234,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
"\n");
}
- if (options_.field_listener_options.inject_field_listener_events &&
- descriptor_->file()->options().optimize_for() !=
- google::protobuf::FileOptions::LITE_RUNTIME) {
+ if (HasTracker(descriptor_, options_)) {
format(
"::$proto_ns$::AccessListener<$classtype$> "
"$1$::$tracker$(&FullMessageName);\n",
@@ -2230,7 +2290,11 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
// Don't use the top bit because that is for unused fields.
format("::_pbi::kInvalidFieldOffsetTag");
} else {
- format("PROTOBUF_FIELD_OFFSET($classtype$, $1$)", FieldMemberName(field));
+ format("PROTOBUF_FIELD_OFFSET($classtype$$1$, $2$)",
+ ShouldSplit(field, options_) ? "::Impl_::Split" : "",
+ ShouldSplit(field, options_)
+ ? FieldName(field) + "_"
+ : FieldMemberName(field, /*cold=*/false));
}
// Some information about a field is in the pdproto profile. The profile is
@@ -2250,7 +2314,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
int count = 0;
for (auto oneof : OneOfRange(descriptor_)) {
- format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_),\n", oneof->name());
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _impl_.$1$_),\n", oneof->name());
count++;
}
GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count());
@@ -2286,18 +2350,181 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
if (HasSimpleBaseClass(descriptor_, options_)) return;
Formatter format(printer, variables_);
- format("inline void $classname$::SharedCtor() {\n");
+ format(
+ "inline void $classname$::SharedCtor(\n"
+ " ::_pb::Arena* arena, bool is_message_owned) {\n"
+ " (void)arena;\n"
+ " (void)is_message_owned;\n");
- std::vector<bool> processed(optimized_order_.size(), false);
- GenerateConstructorBody(printer, processed, false);
+ format.Indent();
+ // Impl_ _impl_.
+ format("new (&_impl_) Impl_{");
+ format.Indent();
+ const char* field_sep = " ";
+ const auto put_sep = [&] {
+ format("\n$1$ ", field_sep);
+ field_sep = ",";
+ };
+
+ // Note: any fields without move/copy constructors can't be explicitly
+ // aggregate initialized pre-C++17.
+ if (descriptor_->extension_range_count() > 0) {
+ put_sep();
+ format("/*decltype($extensions$)*/{::_pbi::ArenaInitialized(), arena}");
+ }
+ if (!inlined_string_indices_.empty()) {
+ put_sep();
+ format("decltype($inlined_string_donated_array$){}");
+ }
+ bool need_to_emit_cached_size = !HasSimpleBaseClass(descriptor_, options_);
+ if (!has_bit_indices_.empty()) {
+ put_sep();
+ format("decltype($has_bits$){}");
+ if (need_to_emit_cached_size) {
+ put_sep();
+ format("/*decltype($cached_size$)*/{}");
+ need_to_emit_cached_size = false;
+ }
+ }
+
+ // Initialize member variables with arena constructor.
+ for (auto field : optimized_order_) {
+ GOOGLE_DCHECK(!IsFieldStripped(field, options_));
+ if (ShouldSplit(field, options_)) {
+ continue;
+ }
+ put_sep();
+ field_generators_.get(field).GenerateAggregateInitializer(printer);
+ }
+ if (ShouldSplit(descriptor_, options_)) {
+ put_sep();
+ format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
+ DefaultInstanceName(descriptor_, options_, /*split=*/true));
+ }
+ for (auto oneof : OneOfRange(descriptor_)) {
+ put_sep();
+ format("decltype(_impl_.$1$_){}", oneof->name());
+ }
+
+ if (need_to_emit_cached_size) {
+ put_sep();
+ format("/*decltype($cached_size$)*/{}");
+ }
+
+ if (descriptor_->real_oneof_decl_count() != 0) {
+ put_sep();
+ format("/*decltype($oneof_case$)*/{}");
+ }
+ if (num_weak_fields_ > 0) {
+ put_sep();
+ format("decltype($weak_field_map$){arena}");
+ }
+ if (IsAnyMessage(descriptor_, options_)) {
+ put_sep();
+ // AnyMetadata has no move constructor.
+ format("/*decltype($any_metadata$)*/{&_impl_.type_url_, &_impl_.value_}");
+ }
+
+ format.Outdent();
+ format("\n};\n");
+
+ if (!inlined_string_indices_.empty()) {
+ // Donate inline string fields.
+ format.Indent();
+ // The last bit is the tracking bit for registering ArenaDtor. The bit is 1
+ // means ArenaDtor is not registered on construction, and on demand register
+ // is needed.
+ format("if (arena != nullptr) {\n");
+ if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) {
+ format(
+ " if (!is_message_owned) {\n"
+ " $inlined_string_donated_array$[0] = ~0u;\n"
+ " } else {\n"
+ // We should not register ArenaDtor for MOA.
+ " $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n"
+ " }\n");
+ } else {
+ format(" $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n");
+ }
+ for (size_t i = 1; i < InlinedStringDonatedSize(); ++i) {
+ format(" $inlined_string_donated_array$[$1$] = ~0u;\n", i);
+ }
+ format("}\n");
+ format.Outdent();
+ }
+
+ for (const FieldDescriptor* field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ continue;
+ }
+ field_generators_.get(field).GenerateConstructorCode(printer);
+ }
for (auto oneof : OneOfRange(descriptor_)) {
format("clear_has_$1$();\n", oneof->name());
}
+ format.Outdent();
format("}\n\n");
}
+void MessageGenerator::GenerateCreateSplitMessage(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ format(
+ "$classname$::Impl_::Split* "
+ "$classname$::CreateSplitMessage(::$proto_ns$::Arena* arena) {\n");
+ format.Indent();
+ const char* field_sep = " ";
+ const auto put_sep = [&] {
+ format("\n$1$ ", field_sep);
+ field_sep = ",";
+ };
+ format(
+ "const size_t size = sizeof(Impl_::Split);\n"
+ "void* chunk = (arena == nullptr) ?\n"
+ " ::operator new(size) :\n"
+ " arena->AllocateAligned(size, alignof(Impl_::Split));\n"
+ "Impl_::Split* ptr = reinterpret_cast<Impl_::Split*>(chunk);\n"
+ "new (ptr) Impl_::Split{");
+ format.Indent();
+ for (const FieldDescriptor* field : optimized_order_) {
+ GOOGLE_DCHECK(!IsFieldStripped(field, options_));
+ if (ShouldSplit(field, options_)) {
+ put_sep();
+ field_generators_.get(field).GenerateAggregateInitializer(printer);
+ }
+ }
+ format.Outdent();
+ format("};\n");
+ for (const FieldDescriptor* field : optimized_order_) {
+ GOOGLE_DCHECK(!IsFieldStripped(field, options_));
+ if (ShouldSplit(field, options_)) {
+ field_generators_.get(field).GenerateCreateSplitMessageCode(printer);
+ }
+ }
+ format("return ptr;\n");
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* printer) {
+ if (!ShouldSplit(descriptor_, options_)) return;
+
+ Formatter format(printer, variables_);
+ const char* field_sep = " ";
+ const auto put_sep = [&] {
+ format("\n$1$ ", field_sep);
+ field_sep = ",";
+ };
+ for (const auto* field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ put_sep();
+ field_generators_.get(field).GenerateConstexprAggregateInitializer(
+ printer);
+ }
+ }
+}
+
void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
if (HasSimpleBaseClass(descriptor_, options_)) return;
Formatter format(printer, variables_);
@@ -2305,11 +2532,32 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
format("inline void $classname$::SharedDtor() {\n");
format.Indent();
format("$DCHK$(GetArenaForAllocation() == nullptr);\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ format("$extensions$.~ExtensionSet();\n");
+ }
+
// Write the destructors for each field except oneof members.
// optimized_order_ does not contain oneof fields.
for (auto field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ continue;
+ }
field_generators_.get(field).GenerateDestructorCode(printer);
}
+ if (ShouldSplit(descriptor_, options_)) {
+ format("if (!IsSplitMessageDefault()) {\n");
+ format.Indent();
+ format("auto* $cached_split_ptr$ = $split$;\n");
+ for (auto field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ field_generators_.get(field).GenerateDestructorCode(printer);
+ }
+ }
+ format("delete $cached_split_ptr$;\n");
+ format.Outdent();
+ format("}\n");
+ }
// Generate code to destruct oneofs. Clearing should do the work.
for (auto oneof : OneOfRange(descriptor_)) {
@@ -2323,6 +2571,11 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
if (num_weak_fields_) {
format("$weak_field_map$.ClearAll();\n");
}
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ format("$any_metadata$.~AnyMetadata();\n");
+ }
+
format.Outdent();
format(
"}\n"
@@ -2358,10 +2611,23 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
// Process non-oneof fields first.
for (auto field : optimized_order_) {
- if (IsFieldStripped(field, options_)) continue;
+ if (IsFieldStripped(field, options_) || ShouldSplit(field, options_))
+ continue;
const FieldGenerator& fg = field_generators_.get(field);
fg.GenerateArenaDestructorCode(printer);
}
+ if (ShouldSplit(descriptor_, options_)) {
+ format("if (!_this->IsSplitMessageDefault()) {\n");
+ format.Indent();
+ for (auto field : optimized_order_) {
+ if (IsFieldStripped(field, options_) || !ShouldSplit(field, options_))
+ continue;
+ const FieldGenerator& fg = field_generators_.get(field);
+ fg.GenerateArenaDestructorCode(printer);
+ }
+ format.Outdent();
+ format("}\n");
+ }
// Process oneof fields.
for (auto oneof : OneOfRange(descriptor_)) {
@@ -2378,72 +2644,118 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
Formatter format(printer, variables_);
+ if (IsMapEntryMessage(descriptor_) || !HasImplData(descriptor_, options_)) {
+ format(
+ "PROTOBUF_CONSTEXPR $classname$::$classname$(\n"
+ " ::_pbi::ConstantInitialized) {}\n");
+ return;
+ }
+
format(
"PROTOBUF_CONSTEXPR $classname$::$classname$(\n"
" ::_pbi::ConstantInitialized)");
+
+ bool need_to_emit_cached_size = !HasSimpleBaseClass(descriptor_, options_);
+ format(": _impl_{");
format.Indent();
- const char* field_sep = ":";
+ const char* field_sep = " ";
const auto put_sep = [&] {
format("\n$1$ ", field_sep);
field_sep = ",";
};
-
- if (!IsMapEntryMessage(descriptor_)) {
- // Process non-oneof fields first.
- for (auto field : optimized_order_) {
- auto& gen = field_generators_.get(field);
+ if (descriptor_->extension_range_count() > 0) {
+ put_sep();
+ format("/*decltype($extensions$)*/{}");
+ }
+ if (!inlined_string_indices_.empty()) {
+ put_sep();
+ format("/*decltype($inlined_string_donated_array$)*/{}");
+ }
+ if (!has_bit_indices_.empty()) {
+ put_sep();
+ format("/*decltype($has_bits$)*/{}");
+ if (need_to_emit_cached_size) {
put_sep();
- gen.GenerateConstinitInitializer(printer);
+ format("/*decltype($cached_size$)*/{}");
+ need_to_emit_cached_size = false;
}
-
- if (IsAnyMessage(descriptor_, options_)) {
- put_sep();
- format("_any_metadata_(&type_url_, &value_)");
+ }
+ for (auto field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ continue;
}
+ put_sep();
+ field_generators_.get(field).GenerateConstexprAggregateInitializer(
+ printer);
+ }
+ if (ShouldSplit(descriptor_, options_)) {
+ put_sep();
+ format("/*decltype($split$)*/&$1$._instance",
+ DefaultInstanceName(descriptor_, options_, /*split=*/true));
+ }
- if (descriptor_->real_oneof_decl_count() != 0) {
- put_sep();
- format("_oneof_case_{}");
- }
+ for (auto oneof : OneOfRange(descriptor_)) {
+ put_sep();
+ format("/*decltype(_impl_.$1$_)*/{}", oneof->name());
+ }
+
+ if (need_to_emit_cached_size) {
+ put_sep();
+ format("/*decltype($cached_size$)*/{}");
+ }
+
+ if (descriptor_->real_oneof_decl_count() != 0) {
+ put_sep();
+ format("/*decltype($oneof_case$)*/{}");
+ }
+
+ if (num_weak_fields_) {
+ put_sep();
+ format("/*decltype($weak_field_map$)*/{}");
+ }
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ put_sep();
+ format(
+ "/*decltype($any_metadata$)*/{&_impl_.type_url_, "
+ "&_impl_.value_}");
}
format.Outdent();
- format("{}\n");
+ format("} {}\n");
}
-void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
- std::vector<bool> processed,
- bool copy_constructor) const {
+void MessageGenerator::GenerateCopyConstructorBody(io::Printer* printer) const {
Formatter format(printer, variables_);
- const RunMap runs = FindRuns(
- optimized_order_, [copy_constructor, this](const FieldDescriptor* field) {
- return (copy_constructor && IsPOD(field)) ||
- (!copy_constructor &&
- CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_));
+ const RunMap runs =
+ FindRuns(optimized_order_, [this](const FieldDescriptor* field) {
+ return IsPOD(field) && !ShouldSplit(field, options_);
});
- TProtoStringType pod_template;
- if (copy_constructor) {
- pod_template =
- "::memcpy(&$first$, &from.$first$,\n"
- " static_cast<size_t>(reinterpret_cast<char*>(&$last$) -\n"
- " reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n";
- } else {
- pod_template =
- "::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(\n"
- " reinterpret_cast<char*>(&$first$) - "
- "reinterpret_cast<char*>(this)),\n"
- " 0, static_cast<size_t>(reinterpret_cast<char*>(&$last$) -\n"
- " reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n";
- }
+ TProtoStringType pod_template =
+ "::memcpy(&$first$, &from.$first$,\n"
+ " static_cast<size_t>(reinterpret_cast<char*>(&$last$) -\n"
+ " reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n";
- for (int i = 0; i < optimized_order_.size(); ++i) {
- if (processed[i]) {
- continue;
+ if (ShouldSplit(descriptor_, options_)) {
+ format("if (!from.IsSplitMessageDefault()) {\n");
+ format.Indent();
+ format("_this->PrepareSplitMessageForWrite();\n");
+ for (auto field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ field_generators_.get(field).GenerateCopyConstructorCode(printer);
+ }
}
+ format.Outdent();
+ format("}\n");
+ }
+ for (size_t i = 0; i < optimized_order_.size(); ++i) {
const FieldDescriptor* field = optimized_order_[i];
+ if (ShouldSplit(field, options_)) {
+ continue;
+ }
const auto it = runs.find(field);
// We only apply the memset technique to runs of more than one field, as
@@ -2451,9 +2763,10 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
if (it != runs.end() && it->second > 1) {
// Use a memset, then skip run_length fields.
const size_t run_length = it->second;
- const TProtoStringType first_field_name = FieldMemberName(field);
+ const TProtoStringType first_field_name =
+ FieldMemberName(field, /*cold=*/false);
const TProtoStringType last_field_name =
- FieldMemberName(optimized_order_[i + run_length - 1]);
+ FieldMemberName(optimized_order_[i + run_length - 1], /*cold=*/false);
format.Set("first", first_field_name);
format.Set("last", last_field_name);
@@ -2463,11 +2776,7 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
i += run_length - 1;
// ++i at the top of the loop.
} else {
- if (copy_constructor) {
- field_generators_.get(field).GenerateCopyConstructorCode(printer);
- } else {
- field_generators_.get(field).GenerateConstructorCode(printer);
- }
+ field_generators_.get(field).GenerateCopyConstructorCode(printer);
}
}
}
@@ -2475,78 +2784,14 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
void MessageGenerator::GenerateStructors(io::Printer* printer) {
Formatter format(printer, variables_);
- TProtoStringType superclass;
- superclass = SuperClassName(descriptor_, options_);
- TProtoStringType initializer_with_arena = superclass + "(arena, is_message_owned)";
-
- if (descriptor_->extension_range_count() > 0) {
- initializer_with_arena += ",\n _extensions_(arena)";
- }
-
- // Initialize member variables with arena constructor.
- for (auto field : optimized_order_) {
- GOOGLE_DCHECK(!IsFieldStripped(field, options_));
- bool has_arena_constructor = field->is_repeated();
- if (!field->real_containing_oneof() &&
- (IsLazy(field, options_, scc_analyzer_) ||
- IsStringPiece(field, options_) ||
- (IsString(field, options_) && IsStringInlined(field, options_)))) {
- has_arena_constructor = true;
- }
- if (has_arena_constructor) {
- initializer_with_arena +=
- TProtoStringType(",\n ") + FieldName(field) + TProtoStringType("_(arena)");
- }
- }
-
- if (IsAnyMessage(descriptor_, options_)) {
- initializer_with_arena += ",\n _any_metadata_(&type_url_, &value_)";
- }
- if (num_weak_fields_ > 0) {
- initializer_with_arena += ", _weak_field_map_(arena)";
- }
-
- TProtoStringType initializer_null = superclass + "()";
- if (IsAnyMessage(descriptor_, options_)) {
- initializer_null += ", _any_metadata_(&type_url_, &value_)";
- }
- if (num_weak_fields_ > 0) {
- initializer_null += ", _weak_field_map_(nullptr)";
- }
-
format(
"$classname$::$classname$(::$proto_ns$::Arena* arena,\n"
" bool is_message_owned)\n"
- " : $1$ {\n",
- initializer_with_arena);
-
- if (!inlined_string_indices_.empty()) {
- // Donate inline string fields.
- format.Indent();
- // The last bit is the tracking bit for registering ArenaDtor. The bit is 1
- // means ArenaDtor is not registered on construction, and on demand register
- // is needed.
- format("if (arena != nullptr) {\n");
- if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) {
- format(
- " if (!is_message_owned) {\n"
- " $inlined_string_donated_array$[0] = ~0u;\n"
- " } else {\n"
- // We should not register ArenaDtor for MOA.
- " $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n"
- " }\n");
- } else {
- format(" $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n");
- }
- for (size_t i = 1; i < InlinedStringDonatedSize(); ++i) {
- format(" $inlined_string_donated_array$[$1$] = ~0u;\n", i);
- }
- format("}\n");
- format.Outdent();
- }
+ " : $1$(arena, is_message_owned) {\n",
+ SuperClassName(descriptor_, options_));
if (!HasSimpleBaseClass(descriptor_, options_)) {
- format(" SharedCtor();\n");
+ format(" SharedCtor(arena, is_message_owned);\n");
if (NeedsArenaDestructor() == ArenaDtorNeeds::kRequired) {
format(
" if (arena != nullptr && !is_message_owned) {\n"
@@ -2576,40 +2821,81 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
} else {
format(
"$classname$::$classname$(const $classname$& from)\n"
- " : $superclass$()");
- format.Indent();
- format.Indent();
+ " : $superclass$() {\n");
format.Indent();
+ format("$classname$* const _this = this; (void)_this;\n");
- // Do not copy inlined_string_donated_, because this is not an arena
- // constructor.
+ if (HasImplData(descriptor_, options_)) {
+ const char* field_sep = " ";
+ const auto put_sep = [&] {
+ format("\n$1$ ", field_sep);
+ field_sep = ",";
+ };
- if (!has_bit_indices_.empty()) {
- format(",\n_has_bits_(from._has_bits_)");
- }
+ format("new (&_impl_) Impl_{");
+ format.Indent();
- std::vector<bool> processed(optimized_order_.size(), false);
- for (int i = 0; i < optimized_order_.size(); i++) {
- auto field = optimized_order_[i];
- if (!(field->is_repeated() && !(field->is_map())) &&
- !IsCord(field, options_)) {
- continue;
+ if (descriptor_->extension_range_count() > 0) {
+ put_sep();
+ format("/*decltype($extensions$)*/{}");
+ }
+ if (!inlined_string_indices_.empty()) {
+ // Do not copy inlined_string_donated_, because this is not an arena
+ // constructor.
+ put_sep();
+ format("decltype($inlined_string_donated_array$){}");
+ }
+ bool need_to_emit_cached_size =
+ !HasSimpleBaseClass(descriptor_, options_);
+ if (!has_bit_indices_.empty()) {
+ put_sep();
+ format("decltype($has_bits$){from.$has_bits$}");
+ if (need_to_emit_cached_size) {
+ put_sep();
+ format("/*decltype($cached_size$)*/{}");
+ need_to_emit_cached_size = false;
+ }
}
- processed[i] = true;
- format(",\n$1$_(from.$1$_)", FieldName(field));
- }
+ // Initialize member variables with arena constructor.
+ for (auto field : optimized_order_) {
+ if (ShouldSplit(field, options_)) {
+ continue;
+ }
+ put_sep();
+ field_generators_.get(field).GenerateCopyAggregateInitializer(printer);
+ }
+ if (ShouldSplit(descriptor_, options_)) {
+ put_sep();
+ format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
+ DefaultInstanceName(descriptor_, options_, /*split=*/true));
+ }
+ for (auto oneof : OneOfRange(descriptor_)) {
+ put_sep();
+ format("decltype(_impl_.$1$_){}", oneof->name());
+ }
- if (IsAnyMessage(descriptor_, options_)) {
- format(",\n_any_metadata_(&type_url_, &value_)");
- }
- if (num_weak_fields_ > 0) {
- format(",\n_weak_field_map_(from._weak_field_map_)");
- }
+ if (need_to_emit_cached_size) {
+ put_sep();
+ format("/*decltype($cached_size$)*/{}");
+ }
- format.Outdent();
- format.Outdent();
- format(" {\n");
+ if (descriptor_->real_oneof_decl_count() != 0) {
+ put_sep();
+ format("/*decltype($oneof_case$)*/{}");
+ }
+ if (num_weak_fields_ > 0) {
+ put_sep();
+ format("decltype($weak_field_map$){from.$weak_field_map$}");
+ }
+ if (IsAnyMessage(descriptor_, options_)) {
+ put_sep();
+ format(
+ "/*decltype($any_metadata$)*/{&_impl_.type_url_, &_impl_.value_}");
+ }
+ format.Outdent();
+ format("};\n\n");
+ }
format(
"_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
@@ -2621,7 +2907,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
"from.$extensions$);\n");
}
- GenerateConstructorBody(printer, processed, true);
+ GenerateCopyConstructorBody(printer);
// Copy oneof fields. Oneof field requires oneof case check.
for (auto oneof : OneOfRange(descriptor_)) {
@@ -2659,6 +2945,10 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
// Generate the shared constructor code.
GenerateSharedConstructorCode(printer);
+ if (ShouldSplit(descriptor_, options_)) {
+ GenerateCreateSplitMessage(printer);
+ }
+
// Generate the destructor.
if (!HasSimpleBaseClass(descriptor_, options_)) {
format(
@@ -2756,6 +3046,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
// (memset) per chunk, and if present it will be at the beginning.
bool same = HasByteIndex(a) == HasByteIndex(b) &&
a->is_repeated() == b->is_repeated() &&
+ ShouldSplit(a, options_) == ShouldSplit(b, options_) &&
(CanInitializeByZeroing(a) == CanInitializeByZeroing(b) ||
(CanInitializeByZeroing(a) &&
(chunk_count == 1 || merge_zero_init)));
@@ -2763,7 +3054,8 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
return same;
});
- ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio);
+ ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
+ kColdRatio);
int cached_has_word_index = -1;
for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
@@ -2773,7 +3065,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
const FieldDescriptor* memset_start = nullptr;
const FieldDescriptor* memset_end = nullptr;
bool saw_non_zero_init = false;
-
+ bool chunk_is_cold = !chunk.empty() && ShouldSplit(chunk.front(), options_);
for (const auto& field : chunk) {
if (CanInitializeByZeroing(field)) {
GOOGLE_CHECK(!saw_non_zero_init);
@@ -2813,17 +3105,25 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
format.Indent();
}
+ if (chunk_is_cold) {
+ format("if (!IsSplitMessageDefault()) {\n");
+ format.Indent();
+ }
+
if (memset_start) {
if (memset_start == memset_end) {
// For clarity, do not memset a single field.
field_generators_.get(memset_start)
.GenerateMessageClearingCode(printer);
} else {
+ GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_start, options_));
+ GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_end, options_));
format(
"::memset(&$1$, 0, static_cast<size_t>(\n"
" reinterpret_cast<char*>(&$2$) -\n"
" reinterpret_cast<char*>(&$1$)) + sizeof($2$));\n",
- FieldMemberName(memset_start), FieldMemberName(memset_end));
+ FieldMemberName(memset_start, chunk_is_cold),
+ FieldMemberName(memset_end, chunk_is_cold));
}
}
@@ -2852,6 +3152,11 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
}
}
+ if (chunk_is_cold) {
+ format.Outdent();
+ format("}\n");
+ }
+
if (have_outer_if) {
format.Outdent();
format("}\n");
@@ -2950,7 +3255,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
std::map<TProtoStringType, TProtoStringType> vars;
SetUnknownFieldsVariable(descriptor_, options_, &vars);
format.AddMap(vars);
- if (HasSingularString(descriptor_, options_)) {
+ if (HasNonSplitOptionalString(descriptor_, options_)) {
format(
"auto* lhs_arena = GetArenaForAllocation();\n"
"auto* rhs_arena = other->GetArenaForAllocation();\n");
@@ -2966,11 +3271,15 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
// If possible, we swap several fields at once, including padding.
const RunMap runs =
FindRuns(optimized_order_, [this](const FieldDescriptor* field) {
- return CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_);
+ return !ShouldSplit(field, options_) &&
+ CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_);
});
- for (int i = 0; i < optimized_order_.size(); ++i) {
+ for (size_t i = 0; i < optimized_order_.size(); ++i) {
const FieldDescriptor* field = optimized_order_[i];
+ if (ShouldSplit(field, options_)) {
+ continue;
+ }
const auto it = runs.find(field);
// We only apply the memswap technique to runs of more than one field, as
@@ -2979,9 +3288,10 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
if (it != runs.end() && it->second > 1) {
// Use a memswap, then skip run_length fields.
const size_t run_length = it->second;
- const TProtoStringType first_field_name = FieldMemberName(field);
- const TProtoStringType last_field_name =
- FieldMemberName(optimized_order_[i + run_length - 1]);
+ const TProtoStringType first_field_name =
+ FieldMemberName(field, /*cold=*/false);
+ const TProtoStringType last_field_name = FieldMemberName(
+ optimized_order_[i + run_length - 1], /*cold=*/false);
format.Set("first", first_field_name);
format.Set("last", last_field_name);
@@ -3000,16 +3310,16 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
field_generators_.get(field).GenerateSwappingCode(printer);
}
}
+ if (ShouldSplit(descriptor_, options_)) {
+ format("swap($split$, other->$split$);\n");
+ }
for (auto oneof : OneOfRange(descriptor_)) {
- format("swap($1$_, other->$1$_);\n", oneof->name());
+ format("swap(_impl_.$1$_, other->_impl_.$1$_);\n", oneof->name());
}
for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
- format(
- "swap($oneof_case$[$1$], "
- "other->$oneof_case$[$1$]);\n",
- i);
+ format("swap($oneof_case$[$1$], other->$oneof_case$[$1$]);\n", i);
}
if (num_weak_fields_) {
@@ -3050,17 +3360,11 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
format(
"const ::$proto_ns$::Message::ClassData "
"$classname$::_class_data_ = {\n"
- " ::$proto_ns$::Message::CopyWithSizeCheck,\n"
+ " ::$proto_ns$::Message::CopyWithSourceCheck,\n"
" $classname$::MergeImpl\n"
"};\n"
"const ::$proto_ns$::Message::ClassData*"
"$classname$::GetClassData() const { return &_class_data_; }\n"
- "\n"
- "void $classname$::MergeImpl(::$proto_ns$::Message* to,\n"
- " const ::$proto_ns$::Message& from) {\n"
- " static_cast<$classname$ *>(to)->MergeFrom(\n"
- " static_cast<const $classname$ &>(from));\n"
- "}\n"
"\n");
} else {
// Generate CheckTypeAndMergeFrom().
@@ -3087,29 +3391,50 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
}
}
-void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
+void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) {
if (HasSimpleBaseClass(descriptor_, options_)) return;
// Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
Formatter format(printer, variables_);
+ if (!HasDescriptorMethods(descriptor_->file(), options_)) {
+ // For messages that don't inherit from Message, just implement MergeFrom
+ // directly.
+ format(
+ "void $classname$::MergeFrom(const $classname$& from) {\n"
+ " $classname$* const _this = this;\n");
+ } else {
+ format(
+ "void $classname$::MergeImpl(::$proto_ns$::Message& to_msg, const "
+ "::$proto_ns$::Message& from_msg) {\n"
+ " auto* const _this = static_cast<$classname$*>(&to_msg);\n"
+ " auto& from = static_cast<const $classname$&>(from_msg);\n");
+ }
+ format.Indent();
format(
- "void $classname$::MergeFrom(const $classname$& from) {\n"
"$annotate_mergefrom$"
"// @@protoc_insertion_point(class_specific_merge_from_start:"
- "$full_name$)\n"
- " $DCHK$_NE(&from, this);\n");
- format.Indent();
+ "$full_name$)\n");
+ format("$DCHK$_NE(&from, _this);\n");
format(
"$uint32$ cached_has_bits = 0;\n"
"(void) cached_has_bits;\n\n");
+ if (ShouldSplit(descriptor_, options_)) {
+ format(
+ "if (!from.IsSplitMessageDefault()) {\n"
+ " _this->PrepareSplitMessageForWrite();\n"
+ "}\n");
+ }
+
std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
optimized_order_,
[&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
- return HasByteIndex(a) == HasByteIndex(b);
+ return HasByteIndex(a) == HasByteIndex(b) &&
+ ShouldSplit(a, options_) == ShouldSplit(b, options_);
});
- ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio);
+ ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
+ kColdRatio);
// cached_has_word_index maintains that:
// cached_has_bits = from._has_bits_[cached_has_word_index]
@@ -3198,7 +3523,8 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
if (deferred_has_bit_changes) {
// Flush the has bits for the primitives we deferred.
GOOGLE_CHECK_LE(0, cached_has_word_index);
- format("$has_bits$[$1$] |= cached_has_bits;\n", cached_has_word_index);
+ format("_this->$has_bits$[$1$] |= cached_has_bits;\n",
+ cached_has_word_index);
}
format.Outdent();
@@ -3235,7 +3561,7 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
}
if (num_weak_fields_) {
format(
- "$weak_field_map$.MergeFrom(from.$weak_field_map$);"
+ "_this->$weak_field_map$.MergeFrom(from.$weak_field_map$);"
"\n");
}
@@ -3243,12 +3569,13 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
// the opportunity for tail calls.
if (descriptor_->extension_range_count() > 0) {
format(
- "$extensions$.MergeFrom(internal_default_instance(), "
+ "_this->$extensions$.MergeFrom(internal_default_instance(), "
"from.$extensions$);\n");
}
format(
- "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
+ "_this->_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._"
+ "internal_"
"metadata_);\n");
format.Outdent();
@@ -3263,12 +3590,12 @@ void MessageGenerator::GenerateCopyFrom(io::Printer* printer) {
// takes in the Message base class as a parameter); instead we just
// let the base Message::CopyFrom take care of it. The base MergeFrom
// knows how to quickly confirm the types exactly match, and if so, will
- // use GetClassData() to get the address of Message::CopyWithSizeCheck,
+ // use GetClassData() to get the address of Message::CopyWithSourceCheck,
// which calls Clear() and then MergeFrom(), as well as making sure that
- // clearing the destination message doesn't alter the size of the source,
- // when in debug builds.
- // Most callers avoid this by passing a "from" message that is the same
- // type as the message being merged into, rather than a generic Message.
+ // clearing the destination message doesn't alter the source, when in debug
+ // builds. Most callers avoid this by passing a "from" message that is the
+ // same type as the message being merged into, rather than a generic
+ // Message.
}
// Generate the class-specific CopyFrom.
@@ -3280,20 +3607,33 @@ void MessageGenerator::GenerateCopyFrom(io::Printer* printer) {
format("if (&from == this) return;\n");
- if (!options_.opensource_runtime) {
+ if (!options_.opensource_runtime && HasMessageFieldOrExtension(descriptor_)) {
// This check is disabled in the opensource release because we're
// concerned that many users do not define NDEBUG in their release builds.
+ // It is also disabled if a message has neither message fields nor
+ // extensions, as it's impossible to copy from its descendant.
+ //
+ // Note that FailIfCopyFromDescendant is implemented by reflection and not
+ // available for lite runtime. In that case, check if the size of the source
+ // has changed after Clear.
+ format("#ifndef NDEBUG\n");
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format("FailIfCopyFromDescendant(*this, from);\n");
+ } else {
+ format("size_t from_size = from.ByteSizeLong();\n");
+ }
format(
- "#ifndef NDEBUG\n"
- "size_t from_size = from.ByteSizeLong();\n"
"#endif\n"
- "Clear();\n"
- "#ifndef NDEBUG\n"
- "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
- " << \"Source of CopyFrom changed when clearing target. Either \"\n"
- " \"source is a nested message in target (not allowed), or \"\n"
- " \"another thread is modifying the source.\";\n"
- "#endif\n");
+ "Clear();\n");
+ if (!HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "#ifndef NDEBUG\n"
+ "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
+ " << \"Source of CopyFrom changed when clearing target. Either \"\n"
+ " \"source is a nested message in target (not allowed), or \"\n"
+ " \"another thread is modifying the source.\";\n"
+ "#endif\n");
+ }
} else {
format("Clear();\n");
}
@@ -3485,7 +3825,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(
// Reload.
int new_index = has_bit_index / 32;
- format_("cached_has_bits = _has_bits_[$1$];\n", new_index);
+ format_("cached_has_bits = _impl_._has_bits_[$1$];\n", new_index);
cached_has_bit_index_ = new_index;
}
@@ -3878,14 +4218,16 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) {
std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
optimized_order_,
[&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
- return a->label() == b->label() && HasByteIndex(a) == HasByteIndex(b);
+ return a->label() == b->label() && HasByteIndex(a) == HasByteIndex(b) &&
+ ShouldSplit(a, options_) == ShouldSplit(b, options_);
});
// Remove chunks with required fields.
chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired),
chunks.end());
- ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio);
+ ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
+ kColdRatio);
int cached_has_word_index = -1;
format(
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h
index 5e4bbe84b83..960bea8e5af 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h
@@ -40,11 +40,11 @@
#include <set>
#include <string>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
-#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/message_layout_helper.h>
+#include <google/protobuf/compiler/cpp/options.h>
+#include <google/protobuf/compiler/cpp/parse_function_generator.h>
namespace google {
namespace protobuf {
@@ -119,6 +119,9 @@ class MessageGenerator {
// default instance.
void GenerateConstexprConstructor(io::Printer* printer);
+ void GenerateCreateSplitMessage(io::Printer* printer);
+ void GenerateInitDefaultSplitInstance(io::Printer* printer);
+
// Generate standard Message methods.
void GenerateClear(io::Printer* printer);
void GenerateOneofClear(io::Printer* printer);
@@ -129,7 +132,7 @@ class MessageGenerator {
void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer);
void GenerateByteSize(io::Printer* printer);
void GenerateMergeFrom(io::Printer* printer);
- void GenerateClassSpecificMergeFrom(io::Printer* printer);
+ void GenerateClassSpecificMergeImpl(io::Printer* printer);
void GenerateCopyFrom(io::Printer* printer);
void GenerateSwap(io::Printer* printer);
void GenerateIsInitialized(io::Printer* printer);
@@ -161,9 +164,8 @@ class MessageGenerator {
void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
Formatter format);
- void GenerateConstructorBody(io::Printer* printer,
- std::vector<bool> already_processed,
- bool copy_constructor) const;
+ // Generates the body of the message's copy constructor.
+ void GenerateCopyConstructorBody(io::Printer* printer) const;
// Returns the level that this message needs ArenaDtor. If the message has
// a field that is not arena-exclusive, it needs an ArenaDtor
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.cc
index 3b9f09c8c8b..9a91fd91720 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.cc
@@ -32,10 +32,11 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_message_field.h>
+#include <google/protobuf/compiler/cpp/message_field.h>
#include <google/protobuf/io/printer.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
#include <google/protobuf/stubs/strutil.h>
@@ -157,8 +158,7 @@ void MessageFieldGenerator::GenerateAccessorDeclarations(
}
void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
- io::Printer* printer) const {
-}
+ io::Printer* printer) const {}
void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
@@ -179,6 +179,7 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
format(
"inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
" $type$* $name$) {\n"
+ "$maybe_prepare_split_message$"
// If we're not on an arena, free whatever we were holding before.
// (If we are on arena, we can just forget the earlier pointer.)
" if (GetArenaForAllocation() == nullptr) {\n"
@@ -204,6 +205,7 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
"inline $type$* $classname$::$release_name$() {\n"
"$type_reference_function$"
"$annotate_release$"
+ "$maybe_prepare_split_message$"
" $clear_hasbit$\n"
" $type$* temp = $casted_member$;\n"
" $field$ = nullptr;\n"
@@ -222,6 +224,7 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
"$annotate_release$"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
"$type_reference_function$"
+ "$maybe_prepare_split_message$"
" $clear_hasbit$\n"
" $type$* temp = $casted_member$;\n"
" $field$ = nullptr;\n"
@@ -244,6 +247,9 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
" return $casted_member$;\n"
"}\n"
"inline $type$* $classname$::mutable_$name$() {\n"
+ // TODO(b/122856539): add tests to make sure all write accessors are able
+ // to prepare split message allocation.
+ "$maybe_prepare_split_message$"
" $type$* _msg = _internal_mutable_$name$();\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
@@ -255,7 +261,9 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
format(
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
" ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n");
- format(" if (message_arena == nullptr) {\n");
+ format(
+ "$maybe_prepare_split_message$"
+ " if (message_arena == nullptr) {\n");
if (IsCrossFileMessage(descriptor_)) {
format(
" delete reinterpret_cast< ::$proto_ns$::MessageLite*>($field$);\n");
@@ -407,12 +415,12 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
- "_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n"
+ "_Internal::mutable_$name$(_this)->CheckTypeAndMergeFrom(\n"
" _Internal::$name$(&from));\n");
} else {
format(
- "_internal_mutable_$name$()->$type$::MergeFrom(from._internal_$name$())"
- ";\n");
+ "_this->_internal_mutable_$name$()->$type$::MergeFrom(\n"
+ " from._internal_$name$());\n");
}
}
@@ -435,17 +443,13 @@ void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
// care when handling them.
format("if (this != internal_default_instance()) ");
}
+ if (ShouldSplit(descriptor_, options_)) {
+ format("delete $cached_split_ptr$->$name$_;\n");
+ return;
+ }
format("delete $field$;\n");
}
-void MessageFieldGenerator::GenerateConstructorCode(
- io::Printer* printer) const {
- GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
-
- Formatter format(printer, variables_);
- format("$field$ = nullptr;\n");
-}
-
void MessageFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
@@ -453,9 +457,7 @@ void MessageFieldGenerator::GenerateCopyConstructorCode(
Formatter format(printer, variables_);
format(
"if (from._internal_has_$name$()) {\n"
- " $field$ = new $type$(*from.$field$);\n"
- "} else {\n"
- " $field$ = nullptr;\n"
+ " _this->$field$ = new $type$(*from.$field$);\n"
"}\n");
}
@@ -500,10 +502,26 @@ void MessageFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
"}\n");
}
-void MessageFieldGenerator::GenerateConstinitInitializer(
+void MessageFieldGenerator::GenerateConstexprAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$name$_(nullptr)");
+ format("/*decltype($field$)*/nullptr");
+}
+
+void MessageFieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("decltype($field$){nullptr}");
+}
+
+void MessageFieldGenerator::GenerateAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (ShouldSplit(descriptor_, options_)) {
+ format("decltype(Impl_::Split::$name$_){nullptr}");
+ return;
+ }
+ format("decltype($field$){nullptr}");
}
// ===================================================================
@@ -830,7 +848,7 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
Formatter format(printer, variables_);
- format("$field$.MergeFrom(from.$field$);\n");
+ format("_this->$field$.MergeFrom(from.$field$);\n");
}
void RepeatedMessageFieldGenerator::GenerateSwappingCode(
@@ -846,6 +864,18 @@ void RepeatedMessageFieldGenerator::GenerateConstructorCode(
// Not needed for repeated fields.
}
+void RepeatedMessageFieldGenerator::GenerateDestructorCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format("$field$.~WeakRepeatedPtrField();\n");
+ } else {
+ format("$field$.~RepeatedPtrField();\n");
+ }
+}
+
void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
@@ -922,12 +952,6 @@ void RepeatedMessageFieldGenerator::GenerateIsInitialized(
}
}
-void RepeatedMessageFieldGenerator::GenerateConstinitInitializer(
- io::Printer* printer) const {
- Formatter format(printer, variables_);
- format("$name$_()");
-}
-
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h
index 528b4197048..70c42c0eacc 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h
@@ -38,8 +38,8 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/field.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
namespace protobuf {
@@ -67,13 +67,16 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateDestructorCode(io::Printer* printer) const override;
- void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override {}
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
protected:
const bool implicit_weak_field_;
@@ -124,11 +127,11 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+ void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
void GenerateIsInitialized(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
const bool implicit_weak_field_;
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h
index 80860053f17..a8813a1f225 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h
@@ -36,7 +36,7 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_names.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h
index 39563cd0cdf..8220f7dde8c 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_names.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h
@@ -51,9 +51,9 @@ namespace cpp {
//
// For example, if you had:
// package foo.bar;
-// message Baz { message Qux {} }
+// message Baz { message Moo {} }
// Then the non-qualified version would be:
-// Baz_Qux
+// Baz_Moo
TProtoStringType ClassName(const Descriptor* descriptor);
TProtoStringType ClassName(const EnumDescriptor* enum_descriptor);
@@ -61,9 +61,9 @@ TProtoStringType ClassName(const EnumDescriptor* enum_descriptor);
//
// For example, if you had:
// package foo.bar;
-// message Baz { message Qux {} }
-// Then the qualified ClassName for Qux would be:
-// ::foo::bar::Baz_Qux
+// message Baz { message Moo {} }
+// Then the qualified ClassName for Moo would be:
+// ::foo::bar::Baz_Moo
TProtoStringType QualifiedClassName(const Descriptor* d);
TProtoStringType QualifiedClassName(const EnumDescriptor* d);
TProtoStringType QualifiedExtensionName(const FieldDescriptor* d);
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_options.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h
index 48512a64c87..14546ca6187 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h
@@ -80,9 +80,10 @@ struct Options {
bool opensource_runtime = false;
bool annotate_accessor = false;
bool unused_field_stripping = false;
- bool unverified_lazy_message_sets = true;
- bool eagerly_verified_lazy = true;
+ bool unverified_lazy_message_sets = false;
+ bool unverified_lazy = false;
bool profile_driven_inline_string = true;
+ bool message_owned_arena_trial = false;
bool force_split = false;
#ifdef PROTOBUF_STABLE_EXPERIMENTS
bool force_eagerly_verified_lazy = true;
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc
index f48ba718a54..20910520d63 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc
@@ -28,9 +28,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
+#include <google/protobuf/compiler/cpp/padding_optimizer.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h
index ebdb17de61f..9c76f38c471 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h
@@ -35,7 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
-#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
+#include <google/protobuf/compiler/cpp/message_layout_helper.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc
index e033856f0c7..1b97182acd6 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc
@@ -28,7 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <google/protobuf/compiler/cpp/cpp_parse_function_generator.h>
+#include <google/protobuf/compiler/cpp/parse_function_generator.h>
#include <algorithm>
#include <limits>
@@ -36,7 +36,7 @@
#include <utility>
#include <google/protobuf/wire_format.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
namespace protobuf {
@@ -231,8 +231,7 @@ std::vector<const FieldDescriptor*> FilterMiniParsedFields(
break;
case FieldDescriptor::TYPE_ENUM:
- if (field->is_repeated() &&
- !HasPreservingUnknownEnumSemantics(field)) {
+ if (field->is_repeated() && !HasPreservingUnknownEnumSemantics(field)) {
// TODO(b/206890171): handle packed repeated closed enums
// Non-packed repeated can be handled using tables, but we still
// need to generate fallback code for all repeated enums in order to
@@ -244,15 +243,15 @@ std::vector<const FieldDescriptor*> FilterMiniParsedFields(
}
break;
- case FieldDescriptor::TYPE_BYTES:
- case FieldDescriptor::TYPE_STRING:
- if (IsStringInlined(field, options)) {
- // TODO(b/198211897): support InilnedStringField.
- handled = false;
- } else {
- handled = true;
- }
- break;
+ case FieldDescriptor::TYPE_BYTES:
+ case FieldDescriptor::TYPE_STRING:
+ if (IsStringInlined(field, options)) {
+ // TODO(b/198211897): support InilnedStringField.
+ handled = false;
+ } else {
+ handled = true;
+ }
+ break;
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
@@ -291,8 +290,9 @@ TailCallTableInfo::TailCallTableInfo(
GOOGLE_LOG_IF(DFATAL, ordered_fields.empty())
<< "Invalid message: " << descriptor->full_name() << " has "
<< oneof_count << " oneof declarations, but no fields";
- aux_entries.push_back(StrCat(
- "_fl::Offset{offsetof(", ClassName(descriptor), ", _oneof_case_)}"));
+ aux_entries.push_back(StrCat("_fl::Offset{offsetof(",
+ ClassName(descriptor),
+ ", _impl_._oneof_case_)}"));
}
// If this message has any inlined string fields, store the donation state
@@ -301,7 +301,7 @@ TailCallTableInfo::TailCallTableInfo(
aux_entries.resize(2); // pad if necessary
aux_entries[1] =
StrCat("_fl::Offset{offsetof(", ClassName(descriptor),
- ", _inlined_string_donated_)}");
+ ", _impl_._inlined_string_donated_)}");
}
// Fill in mini table entries.
@@ -444,7 +444,7 @@ ParseFunctionGenerator::ParseFunctionGenerator(
inlined_string_indices, scc_analyzer));
}
SetCommonVars(options_, &variables_);
- SetCommonMessageDataVariables(&variables_);
+ SetCommonMessageDataVariables(descriptor_, &variables_);
SetUnknownFieldsVariable(descriptor_, options_, &variables_);
variables_["classname"] = ClassName(descriptor, false);
}
@@ -547,13 +547,13 @@ void ParseFunctionGenerator::GenerateTailcallFallbackFunction(
if (num_hasbits_ > 0) {
// Sync hasbits
- format("typed_msg->_has_bits_[0] = hasbits;\n");
+ format("typed_msg->_impl_._has_bits_[0] = hasbits;\n");
}
format("arc_ui32 tag = data.tag();\n");
format.Set("msg", "typed_msg->");
format.Set("this", "typed_msg");
- format.Set("has_bits", "typed_msg->_has_bits_");
+ format.Set("has_bits", "typed_msg->_impl_._has_bits_");
format.Set("next_tag", "goto next_tag");
GenerateParseIterationBody(format, descriptor_,
tc_table_info_->fallback_fields);
@@ -649,7 +649,7 @@ void ParseFunctionGenerator::GenerateLoopingParseFunction(Formatter& format) {
format("_Internal::HasBits has_bits{};\n");
format.Set("has_bits", "has_bits");
} else {
- format.Set("has_bits", "_has_bits_");
+ format.Set("has_bits", "_impl_._has_bits_");
}
format.Set("next_tag", "continue");
format("while (!ctx->Done(&ptr)) {\n");
@@ -665,7 +665,7 @@ void ParseFunctionGenerator::GenerateLoopingParseFunction(Formatter& format) {
format.Outdent();
format("message_done:\n");
- if (hasbits_size) format(" _has_bits_.Or(has_bits);\n");
+ if (hasbits_size) format(" _impl_._has_bits_.Or(has_bits);\n");
format(
" return ptr;\n"
@@ -774,7 +774,7 @@ void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) {
{
auto header_scope = format.ScopedIndent();
if (num_hasbits_ > 0 || IsMapEntryMessage(descriptor_)) {
- format("PROTOBUF_FIELD_OFFSET($classname$, _has_bits_),\n");
+ format("PROTOBUF_FIELD_OFFSET($classname$, _impl_._has_bits_),\n");
} else {
format("0, // no _has_bits_\n");
}
@@ -899,11 +899,14 @@ void ParseFunctionGenerator::GenerateFastFieldEntries(Formatter& format) {
if (info.func_name.empty()) {
format("{::_pbi::TcParser::MiniParse, {}},\n");
} else {
+ bool cold = ShouldSplit(info.field, options_);
format(
"{$1$,\n"
- " {$2$, $3$, $4$, PROTOBUF_FIELD_OFFSET($classname$, $5$)}},\n",
+ " {$2$, $3$, $4$, PROTOBUF_FIELD_OFFSET($classname$$5$, $6$)}},\n",
info.func_name, info.coded_tag, info.hasbit_idx, info.aux_idx,
- FieldMemberName(info.field));
+ cold ? "::Impl_::Split" : "",
+ cold ? FieldName(info.field) + "_"
+ : FieldMemberName(info.field, /*cold=*/false));
}
}
}
@@ -1048,8 +1051,11 @@ void ParseFunctionGenerator::GenerateFieldEntries(Formatter& format) {
format("/* weak */ 0, 0, 0, 0");
} else {
const OneofDescriptor* oneof = field->real_containing_oneof();
- format("PROTOBUF_FIELD_OFFSET($classname$, $1$), $2$, $3$,\n ",
- FieldMemberName(field),
+ bool cold = ShouldSplit(field, options_);
+ format("PROTOBUF_FIELD_OFFSET($classname$$1$, $2$), $3$, $4$,\n ",
+ cold ? "::Impl_::Split" : "",
+ cold ? FieldName(field) + "_"
+ : FieldMemberName(field, /*cold=*/false),
(oneof ? oneof->index() : entry.hasbit_idx), entry.aux_idx);
FormatFieldKind(format, entry, options_, scc_analyzer_);
}
@@ -1550,7 +1556,8 @@ void ParseFunctionGenerator::GenerateFieldSwitch(
format.Indent();
for (const auto* field : fields) {
- format.Set("field", FieldMemberName(field));
+ bool cold = ShouldSplit(field, options_);
+ format.Set("field", FieldMemberName(field, cold));
PrintFieldComment(format, field);
format("case $1$:\n", field->number());
format.Indent();
@@ -1559,6 +1566,9 @@ void ParseFunctionGenerator::GenerateFieldSwitch(
format("if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
expected_tag & 0xFF);
format.Indent();
+ if (cold) {
+ format("$msg$PrepareSplitMessageForWrite();\n");
+ }
auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
arc_ui32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
int tag_size = io::CodedOutputStream::VarintSize32(tag);
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h
index 3c8209534a4..7e2b674852f 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h
@@ -38,8 +38,8 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc
index 910b59a21a7..9dbf16ae7eb 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc
@@ -32,12 +32,12 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
+#include <google/protobuf/compiler/cpp/primitive_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
namespace protobuf {
@@ -105,8 +105,9 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
(*variables)["default"] = DefaultValue(options, descriptor);
(*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
+ bool cold = ShouldSplit(descriptor, options);
(*variables)["cached_byte_size_field"] =
- MakeVarintCachedSizeFieldName(descriptor);
+ MakeVarintCachedSizeFieldName(descriptor, cold);
(*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
@@ -165,6 +166,7 @@ void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
" $field$ = value;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
+ "$maybe_prepare_split_message$"
" _internal_set_$name$(value);\n"
"$annotate_set$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -178,7 +180,7 @@ void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
- format("_internal_set_$name$(from._internal_$name$());\n");
+ format("_this->_internal_set_$name$(from._internal_$name$());\n");
}
void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
@@ -186,16 +188,10 @@ void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
format("swap($field$, other->$field$);\n");
}
-void PrimitiveFieldGenerator::GenerateConstructorCode(
- io::Printer* printer) const {
- Formatter format(printer, variables_);
- format("$field$ = $default$;\n");
-}
-
void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$field$ = from.$field$;\n");
+ format("_this->$field$ = from.$field$;\n");
}
void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
@@ -230,10 +226,26 @@ void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
}
}
-void PrimitiveFieldGenerator::GenerateConstinitInitializer(
+void PrimitiveFieldGenerator::GenerateConstexprAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$name$_($default$)");
+ format("/*decltype($field$)*/$default$");
+}
+
+void PrimitiveFieldGenerator::GenerateAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (ShouldSplit(descriptor_, options_)) {
+ format("decltype(Impl_::Split::$name$_){$default$}");
+ return;
+ }
+ format("decltype($field$){$default$}");
+}
+
+void PrimitiveFieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("decltype($field$){}");
}
// ===================================================================
@@ -398,7 +410,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$field$.MergeFrom(from.$field$);\n");
+ format("_this->$field$.MergeFrom(from.$field$);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
@@ -407,6 +419,12 @@ void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
format("$field$.InternalSwap(&other->$field$);\n");
}
+void RepeatedPrimitiveFieldGenerator::GenerateDestructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$field$.~RepeatedField();\n");
+}
+
void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
@@ -460,7 +478,8 @@ void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
format(
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
- " ::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
+ " "
+ "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
"}\n");
if (FixedSize(descriptor_->type()) == -1) {
format(
@@ -480,13 +499,37 @@ void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
format("}\n");
}
-void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
+void RepeatedPrimitiveFieldGenerator::GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("/*decltype($field$)*/{}");
+ if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ format("\n, /*decltype($cached_byte_size_field$)*/{0}");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$name$_()");
+ format("decltype($field$){arena}");
+ if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ // std::atomic has no move constructor, which prevents explicit aggregate
+ // initialization pre-C++17.
+ format("\n, /*decltype($cached_byte_size_field$)*/{0}");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+
+ Formatter format(printer, variables_);
+ format("decltype($field$){from.$field$}");
if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
HasGeneratedMethods(descriptor_->file(), options_)) {
- format("\n, $cached_byte_size_name$(0)");
+ // std::atomic has no move constructor.
+ format("\n, /*decltype($cached_byte_size_field$)*/{0}");
}
}
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h
index 77ac598e905..bb8a08aa141 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h
@@ -38,7 +38,7 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/field.h>
namespace google {
namespace protobuf {
@@ -58,12 +58,15 @@ class PrimitiveFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const override;
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
- void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override {}
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
@@ -99,11 +102,17 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override {}
- void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+ void GenerateCopyConstructorCode(io::Printer* /*printer*/) const override {
+ GOOGLE_CHECK(!ShouldSplit(descriptor_, options_));
+ }
+ void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_service.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc
index 7bf589fa388..fae7128a097 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc
@@ -32,11 +32,11 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_service.h>
+#include <google/protobuf/compiler/cpp/service.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_service.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h
index d237f9d732e..56982cf566b 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_service.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h
@@ -39,7 +39,7 @@
#include <string>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/options.h>
namespace google {
namespace protobuf {
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc
index 4d8744976ba..5f30d3b511e 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc
@@ -32,11 +32,11 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/compiler/cpp/string_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/helpers.h>
#include <google/protobuf/descriptor.pb.h>
@@ -115,11 +115,7 @@ void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
// allocating arena is null. This is required to support message-owned
// arena (go/path-to-arenas) where a root proto is destroyed but
// InlinedStringField may have arena-allocated memory.
- //
- // `_init_inline_xxx` is used for initializing default instances.
- format(
- "union { ::$proto_ns$::internal::InlinedStringField $name$_; };\n"
- "static std::true_type _init_inline_$name$_;\n");
+ format("::$proto_ns$::internal::InlinedStringField $name$_;\n");
}
}
@@ -130,6 +126,10 @@ void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
"static const ::$proto_ns$::internal::LazyString"
" $default_variable_name$;\n");
}
+ if (inlined_) {
+ // `_init_inline_xxx` is used for initializing default instances.
+ format("static std::true_type _init_inline_$name$_;\n");
+ }
}
void StringFieldGenerator::GenerateAccessorDeclarations(
@@ -215,6 +215,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
"template <typename ArgT0, typename... ArgT>\n"
"inline PROTOBUF_ALWAYS_INLINE\n"
"void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+ "$maybe_prepare_split_message$"
" $set_hasbit$\n"
" $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
" args..., GetArenaForAllocation());\n"
@@ -226,6 +227,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
"template <typename ArgT0, typename... ArgT>\n"
"inline PROTOBUF_ALWAYS_INLINE\n"
"void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+ "$maybe_prepare_split_message$"
" $set_hasbit$\n"
" $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
" args..., GetArenaForAllocation(), _internal_$name$_donated(), "
@@ -240,6 +242,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
}
format(
"inline TProtoStringType* $classname$::mutable_$name$() {\n"
+ "$maybe_prepare_split_message$"
" TProtoStringType* _s = _internal_mutable_$name$();\n"
"$annotate_mutable$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
@@ -280,6 +283,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
format(
"inline TProtoStringType* $classname$::$release_name$() {\n"
"$annotate_release$"
+ "$maybe_prepare_split_message$"
" // @@protoc_insertion_point(field_release:$full_name$)\n");
if (HasHasbit(descriptor_)) {
@@ -311,6 +315,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
format(
"}\n"
"inline void $classname$::set_allocated_$name$(TProtoStringType* $name$) {\n"
+ "$maybe_prepare_split_message$"
" if ($name$ != nullptr) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -403,7 +408,7 @@ void StringFieldGenerator::GenerateMessageClearingCode(
void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
// TODO(gpike): improve this
- format("_internal_set_$name$(from._internal_$name$());\n");
+ format("_this->_internal_set_$name$(from._internal_$name$());\n");
}
void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
@@ -440,12 +445,27 @@ void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
}
}
+void StringFieldGenerator::GenerateCreateSplitMessageCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(ShouldSplit(descriptor_, options_));
+ GOOGLE_CHECK(!inlined_);
+ Formatter format(printer, variables_);
+ format("ptr->$name$_.InitDefault();\n");
+ if (IsString(descriptor_, options_) &&
+ descriptor_->default_value_string().empty()) {
+ format(
+ "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
+ " ptr->$name$_.Set(\"\", GetArenaForAllocation());\n"
+ "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
+ }
+}
+
void StringFieldGenerator::GenerateCopyConstructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
GenerateConstructorCode(printer);
if (inlined_) {
- format("new (&$field$) ::_pbi::InlinedStringField();\n");
+ format("new (&_this->$field$) ::_pbi::InlinedStringField();\n");
}
if (HasHasbit(descriptor_)) {
@@ -458,13 +478,13 @@ void StringFieldGenerator::GenerateCopyConstructorCode(
if (!inlined_) {
format(
- "$field$.Set(from._internal_$name$(), \n"
- " GetArenaForAllocation());\n");
+ "_this->$field$.Set(from._internal_$name$(), \n"
+ " _this->GetArenaForAllocation());\n");
} else {
format(
- "$field$.Set(from._internal_$name$(),\n"
- " GetArenaForAllocation(), _internal_$name$_donated(), "
- "&$donating_states_word$, $mask_for_undonate$, this);\n");
+ "_this->$field$.Set(from._internal_$name$(),\n"
+ " _this->GetArenaForAllocation(), _this->_internal_$name$_donated(), "
+ "&_this->$donating_states_word$, $mask_for_undonate$, _this);\n");
}
format.Outdent();
@@ -474,6 +494,10 @@ void StringFieldGenerator::GenerateCopyConstructorCode(
void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (!inlined_) {
+ if (ShouldSplit(descriptor_, options_)) {
+ format("$cached_split_ptr$->$name$_.Destroy();\n");
+ return;
+ }
format("$field$.Destroy();\n");
return;
}
@@ -481,6 +505,7 @@ void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
// Destructor has been implicitly skipped as a union, and even the
// message-owned arena is enabled, arena could still be missing for
// Arena::CreateMessage(nullptr).
+ GOOGLE_DCHECK(!ShouldSplit(descriptor_, options_));
format("$field$.~InlinedStringField();\n");
}
@@ -522,22 +547,43 @@ void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
" this->_internal_$name$());\n");
}
-void StringFieldGenerator::GenerateConstinitInitializer(
+void StringFieldGenerator::GenerateConstexprAggregateInitializer(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (inlined_) {
- format("$name$_(nullptr, false)");
+ format("/*decltype($field$)*/{nullptr, false}");
return;
}
if (descriptor_->default_value_string().empty()) {
format(
- "$name$_(&::_pbi::fixed_address_empty_string, "
- "::_pbi::ConstantInitialized{})");
+ "/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, "
+ "::_pbi::ConstantInitialized{}}");
+ } else {
+ format("/*decltype($field$)*/{nullptr, ::_pbi::ConstantInitialized{}}");
+ }
+}
+
+void StringFieldGenerator::GenerateAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (ShouldSplit(descriptor_, options_)) {
+ GOOGLE_CHECK(!inlined_);
+ format("decltype(Impl_::Split::$name$_){}");
+ return;
+ }
+ if (!inlined_) {
+ format("decltype($field$){}");
} else {
- format("$name$_(nullptr, ::_pbi::ConstantInitialized{})");
+ format("decltype($field$)(arena)");
}
}
+void StringFieldGenerator::GenerateCopyAggregateInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("decltype($field$){}");
+}
+
// ===================================================================
StringOneofFieldGenerator::StringOneofFieldGenerator(
@@ -858,7 +904,7 @@ void RepeatedStringFieldGenerator::GenerateClearingCode(
void RepeatedStringFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
- format("$field$.MergeFrom(from.$field$);\n");
+ format("_this->$field$.MergeFrom(from.$field$);\n");
}
void RepeatedStringFieldGenerator::GenerateSwappingCode(
@@ -867,6 +913,12 @@ void RepeatedStringFieldGenerator::GenerateSwappingCode(
format("$field$.InternalSwap(&other->$field$);\n");
}
+void RepeatedStringFieldGenerator::GenerateDestructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$field$.~RepeatedPtrField();\n");
+}
+
void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
@@ -899,12 +951,6 @@ void RepeatedStringFieldGenerator::GenerateByteSize(
"}\n");
}
-void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
- io::Printer* printer) const {
- Formatter format(printer, variables_);
- format("$name$_()");
-}
-
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_string_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h
index 845bf073a93..db5f18bfb7d 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h
@@ -38,7 +38,7 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/field.h>
namespace google {
namespace protobuf {
@@ -63,13 +63,17 @@ class StringFieldGenerator : public FieldGenerator {
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCreateSplitMessageCode(io::Printer* printer) const override;
void GenerateCopyConstructorCode(io::Printer* printer) const override;
void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateArenaDestructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
+ void GenerateConstexprAggregateInitializer(
+ io::Printer* printer) const override;
+ void GenerateAggregateInitializer(io::Printer* printer) const override;
+ void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
bool IsInlined() const override { return inlined_; }
ArenaDtorNeeds NeedsArenaDestructor() const override;
@@ -112,11 +116,13 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
void GenerateMergingCode(io::Printer* printer) const override;
void GenerateSwappingCode(io::Printer* printer) const override;
void GenerateConstructorCode(io::Printer* printer) const override {}
- void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+ void GenerateCopyConstructorCode(io::Printer* /*printer*/) const override {
+ GOOGLE_CHECK(!ShouldSplit(descriptor_, options_));
+ }
+ void GenerateDestructorCode(io::Printer* printer) const override;
void GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const override;
void GenerateByteSize(io::Printer* printer) const override;
- void GenerateConstinitInitializer(io::Printer* printer) const override;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);