|
@@ -268,13 +268,6 @@ void CollectMapInfo(const Options& options, const Descriptor* descriptor,
|
|
|
"TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
|
|
|
vars["val_wire_type"] =
|
|
|
"TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
|
|
|
- if (descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
|
|
|
- val->type() == FieldDescriptor::TYPE_ENUM) {
|
|
|
- const EnumValueDescriptor* default_value = val->default_value_enum();
|
|
|
- vars["default_enum_value"] = Int32ToString(default_value->number());
|
|
|
- } else {
|
|
|
- vars["default_enum_value"] = "0";
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
// Does the given field have a private (internal helper only) has_$name$()
|
|
@@ -323,6 +316,17 @@ bool ShouldMarkNewAsFinal(const Descriptor* descriptor,
|
|
|
options.opensource_runtime;
|
|
|
}
|
|
|
|
|
|
+// Returns true to make the message serialize in order, decided by the following
|
|
|
+// factors in the order of precedence.
|
|
|
+// --options().message_set_wire_format() == true
|
|
|
+// --the message is in the allowlist (true)
|
|
|
+// --GOOGLE_PROTOBUF_SHUFFLE_SERIALIZE is defined (false)
|
|
|
+// --a ranage of message names that are allowed to stay in order (true)
|
|
|
+bool ShouldSerializeInOrder(const Descriptor* descriptor,
|
|
|
+ const Options& options) {
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
bool TableDrivenParsingEnabled(const Descriptor* descriptor,
|
|
|
const Options& options) {
|
|
|
if (!options.table_driven_parsing) {
|
|
@@ -591,7 +595,7 @@ MessageGenerator::MessageGenerator(
|
|
|
// Compute optimized field order to be used for layout and initialization
|
|
|
// purposes.
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -631,16 +635,7 @@ MessageGenerator::MessageGenerator(
|
|
|
MessageGenerator::~MessageGenerator() = default;
|
|
|
|
|
|
size_t MessageGenerator::HasBitsSize() const {
|
|
|
- size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4;
|
|
|
- if (sizeof_has_bits == 0) {
|
|
|
- // Zero-size arrays aren't technically allowed, and MSVC in particular
|
|
|
- // doesn't like them. We still need to declare these arrays to make
|
|
|
- // other code compile. Since this is an uncommon case, we'll just declare
|
|
|
- // them with size 1 and waste some space. Oh well.
|
|
|
- sizeof_has_bits = 4;
|
|
|
- }
|
|
|
-
|
|
|
- return sizeof_has_bits;
|
|
|
+ return (max_has_bit_index_ + 31) / 32;
|
|
|
}
|
|
|
|
|
|
int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
|
|
@@ -689,7 +684,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
|
|
optimized_order_.end());
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
if (!field->real_containing_oneof() && !field->options().weak() &&
|
|
|
- IsFieldUsed(field, options_)) {
|
|
|
+ !IsFieldStripped(field, options_)) {
|
|
|
continue;
|
|
|
}
|
|
|
ordered_fields.push_back(field);
|
|
@@ -718,8 +713,8 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
|
|
|
|
|
if (field->is_repeated()) {
|
|
|
format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
|
|
|
- IsFieldUsed(field, options_) ? ";" : " {__builtin_trap();}");
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
format(
|
|
|
"private:\n"
|
|
|
"int ${1$_internal_$name$_size$}$() const;\n"
|
|
@@ -728,15 +723,15 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
|
|
}
|
|
|
} else if (HasHasMethod(field)) {
|
|
|
format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field,
|
|
|
- IsFieldUsed(field, options_) ? ";" : " {__builtin_trap();}");
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
format(
|
|
|
"private:\n"
|
|
|
"bool _internal_has_$name$() const;\n"
|
|
|
"public:\n");
|
|
|
}
|
|
|
} else if (HasPrivateHasMethod(field)) {
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
format(
|
|
|
"private:\n"
|
|
|
"bool ${1$_internal_has_$name$$}$() const;\n"
|
|
@@ -745,7 +740,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
|
|
}
|
|
|
}
|
|
|
format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field,
|
|
|
- IsFieldUsed(field, options_) ? ";" : "{__builtin_trap();}");
|
|
|
+ !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
|
|
|
|
|
|
// Generate type-specific accessor declarations.
|
|
|
field_generators_.get(field).GenerateAccessorDeclarations(printer);
|
|
@@ -780,7 +775,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
|
|
|
|
|
void MessageGenerator::GenerateSingularFieldHasBits(
|
|
|
const FieldDescriptor* field, Formatter format) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
format(
|
|
|
"inline bool $classname$::has_$name$() const { "
|
|
|
"__builtin_trap(); }\n");
|
|
@@ -861,7 +856,7 @@ void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) {
|
|
|
|
|
|
void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
|
|
|
const Formatter& format) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
if (HasHasMethod(field)) {
|
|
|
format(
|
|
|
"inline bool $classname$::has_$name$() const { "
|
|
@@ -906,7 +901,7 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
|
|
|
|
|
|
void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
|
|
|
bool is_inline, Formatter format) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
format("void $classname$::clear_$name$() { __builtin_trap(); }\n");
|
|
|
return;
|
|
|
}
|
|
@@ -952,7 +947,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
PrintFieldComment(format, field);
|
|
|
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -964,7 +959,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
|
|
|
|
|
// Generate has_$name$() or $name$_size().
|
|
|
if (field->is_repeated()) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
format(
|
|
|
"inline int $classname$::$name$_size() const { "
|
|
|
"__builtin_trap(); }\n");
|
|
@@ -998,7 +993,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
|
|
}
|
|
|
|
|
|
// Generate type-specific accessors.
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
|
|
|
}
|
|
|
|
|
@@ -1026,14 +1021,13 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
"::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
|
|
|
" $key_cpp$, $val_cpp$,\n"
|
|
|
" ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
|
|
|
- " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n"
|
|
|
- " $default_enum_value$ > {\n"
|
|
|
+ " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n"
|
|
|
"public:\n"
|
|
|
" typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
|
|
|
" $key_cpp$, $val_cpp$,\n"
|
|
|
" ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
|
|
|
- " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n"
|
|
|
- " $default_enum_value$ > SuperType;\n"
|
|
|
+ " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
|
|
|
+ "SuperType;\n"
|
|
|
" $classname$();\n"
|
|
|
" explicit $classname$(::$proto_ns$::Arena* arena);\n"
|
|
|
" void MergeFrom(const $classname$& other);\n"
|
|
@@ -1122,13 +1116,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
format(" public:\n");
|
|
|
format.Indent();
|
|
|
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- format("inline $classname$() : $classname$(nullptr) {}\n");
|
|
|
- } else {
|
|
|
- format("$classname$();\n");
|
|
|
- }
|
|
|
-
|
|
|
format(
|
|
|
+ "inline $classname$() : $classname$(nullptr) {}\n"
|
|
|
"virtual ~$classname$();\n"
|
|
|
"\n"
|
|
|
"$classname$(const $classname$& from);\n"
|
|
@@ -1224,7 +1213,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
|
|
|
// TODO(gerbens) make this private, while still granting other protos access.
|
|
|
format(
|
|
|
- "static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY\n"
|
|
|
"static inline const $classname$* internal_default_instance() {\n"
|
|
|
" return reinterpret_cast<const $classname$*>(\n"
|
|
|
" &_$classname$_default_instance_);\n"
|
|
@@ -1244,7 +1232,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
" _any_metadata_.PackFrom(message);\n"
|
|
|
"}\n"
|
|
|
"void PackFrom(const ::$proto_ns$::Message& message,\n"
|
|
|
- " const std::string& type_url_prefix) {\n"
|
|
|
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
|
|
|
+ "type_url_prefix) {\n"
|
|
|
" _any_metadata_.PackFrom(message, type_url_prefix);\n"
|
|
|
"}\n"
|
|
|
"bool UnpackTo(::$proto_ns$::Message* message) const {\n"
|
|
@@ -1264,7 +1253,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
"!std::is_convertible<T, const ::$proto_ns$::Message&>"
|
|
|
"::value>::type>\n"
|
|
|
"void PackFrom(const T& message,\n"
|
|
|
- " const std::string& type_url_prefix) {\n"
|
|
|
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
|
|
|
+ "type_url_prefix) {\n"
|
|
|
" _any_metadata_.PackFrom<T>(message, type_url_prefix);"
|
|
|
"}\n"
|
|
|
"template <typename T, class = typename std::enable_if<"
|
|
@@ -1281,7 +1271,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
"}\n"
|
|
|
"template <typename T>\n"
|
|
|
"void PackFrom(const T& message,\n"
|
|
|
- " const std::string& type_url_prefix) {\n"
|
|
|
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
|
|
|
+ "type_url_prefix) {\n"
|
|
|
" _any_metadata_.PackFrom(message, type_url_prefix);\n"
|
|
|
"}\n"
|
|
|
"template <typename T>\n"
|
|
@@ -1293,7 +1284,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
"template<typename T> bool Is() const {\n"
|
|
|
" return _any_metadata_.Is<T>();\n"
|
|
|
"}\n"
|
|
|
- "static bool ParseAnyTypeUrl(const string& type_url,\n"
|
|
|
+ "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
|
|
|
+ "type_url,\n"
|
|
|
" std::string* full_type_name);\n");
|
|
|
}
|
|
|
|
|
@@ -1303,31 +1295,21 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
format(
|
|
|
"friend void swap($classname$& a, $classname$& b) {\n"
|
|
|
" a.Swap(&b);\n"
|
|
|
+ "}\n"
|
|
|
+ "inline void Swap($classname$* other) {\n"
|
|
|
+ " if (other == this) return;\n"
|
|
|
+ " if (GetArena() == other->GetArena()) {\n"
|
|
|
+ " InternalSwap(other);\n"
|
|
|
+ " } else {\n"
|
|
|
+ " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
|
|
|
+ " }\n"
|
|
|
+ "}\n"
|
|
|
+ "void UnsafeArenaSwap($classname$* other) {\n"
|
|
|
+ " if (other == this) return;\n"
|
|
|
+ " $DCHK$(GetArena() == other->GetArena());\n"
|
|
|
+ " InternalSwap(other);\n"
|
|
|
"}\n");
|
|
|
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- format(
|
|
|
- "inline void Swap($classname$* other) {\n"
|
|
|
- " if (other == this) return;\n"
|
|
|
- " if (GetArena() == other->GetArena()) {\n"
|
|
|
- " InternalSwap(other);\n"
|
|
|
- " } else {\n"
|
|
|
- " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
|
|
|
- " }\n"
|
|
|
- "}\n"
|
|
|
- "void UnsafeArenaSwap($classname$* other) {\n"
|
|
|
- " if (other == this) return;\n"
|
|
|
- " $DCHK$(GetArena() == other->GetArena());\n"
|
|
|
- " InternalSwap(other);\n"
|
|
|
- "}\n");
|
|
|
- } else {
|
|
|
- format(
|
|
|
- "inline void Swap($classname$* other) {\n"
|
|
|
- " if (other == this) return;\n"
|
|
|
- " InternalSwap(other);\n"
|
|
|
- "}\n");
|
|
|
- }
|
|
|
-
|
|
|
format(
|
|
|
"\n"
|
|
|
"// implements Message ----------------------------------------------\n"
|
|
@@ -1400,17 +1382,15 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece"
|
|
|
: "::StringPiece");
|
|
|
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- format(
|
|
|
- // TODO(gerbens) Make this private! Currently people are deriving from
|
|
|
- // protos to give access to this constructor, breaking the invariants
|
|
|
- // we rely on.
|
|
|
- "protected:\n"
|
|
|
- "explicit $classname$(::$proto_ns$::Arena* arena);\n"
|
|
|
- "private:\n"
|
|
|
- "static void ArenaDtor(void* object);\n"
|
|
|
- "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
|
|
|
- }
|
|
|
+ format(
|
|
|
+ // TODO(gerbens) Make this private! Currently people are deriving from
|
|
|
+ // protos to give access to this constructor, breaking the invariants
|
|
|
+ // we rely on.
|
|
|
+ "protected:\n"
|
|
|
+ "explicit $classname$(::$proto_ns$::Arena* arena);\n"
|
|
|
+ "private:\n"
|
|
|
+ "static void ArenaDtor(void* object);\n"
|
|
|
+ "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
|
|
|
|
|
|
format(
|
|
|
"public:\n"
|
|
@@ -1515,10 +1495,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
|
|
|
const size_t sizeof_has_bits = HasBitsSize();
|
|
|
const std::string has_bits_decl =
|
|
|
- sizeof_has_bits == 0
|
|
|
- ? ""
|
|
|
- : StrCat("::$proto_ns$::internal::HasBits<",
|
|
|
- sizeof_has_bits / 4, "> _has_bits_;\n");
|
|
|
+ sizeof_has_bits == 0 ? ""
|
|
|
+ : StrCat("::$proto_ns$::internal::HasBits<",
|
|
|
+ sizeof_has_bits, "> _has_bits_;\n");
|
|
|
|
|
|
// To minimize padding, data members are divided into three sections:
|
|
|
// (1) members assumed to align to 8 bytes
|
|
@@ -1534,13 +1513,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
"\n");
|
|
|
}
|
|
|
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- format(
|
|
|
- "template <typename T> friend class "
|
|
|
- "::$proto_ns$::Arena::InternalHelper;\n"
|
|
|
- "typedef void InternalArenaConstructable_;\n"
|
|
|
- "typedef void DestructorSkippable_;\n");
|
|
|
- }
|
|
|
+ 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
|
|
@@ -1572,14 +1549,14 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
|
|
|
camel_oneof_name);
|
|
|
format.Indent();
|
|
|
for (auto field : FieldRange(oneof)) {
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GeneratePrivateMembers(printer);
|
|
|
}
|
|
|
}
|
|
|
format.Outdent();
|
|
|
format("} $1$_;\n", oneof->name());
|
|
|
for (auto field : FieldRange(oneof)) {
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GenerateStaticMembers(printer);
|
|
|
}
|
|
|
}
|
|
@@ -1637,30 +1614,6 @@ void MessageGenerator::GenerateInlineMethods(io::Printer* printer) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void MessageGenerator::GenerateExtraDefaultFields(io::Printer* printer) {
|
|
|
- // Generate oneof default instance and weak field instances for reflection
|
|
|
- // usage.
|
|
|
- Formatter format(printer, variables_);
|
|
|
- for (auto oneof : OneOfRange(descriptor_)) {
|
|
|
- for (auto field : FieldRange(oneof)) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
|
|
|
- (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
|
|
|
- EffectiveStringCType(field, options_) != FieldOptions::STRING)) {
|
|
|
- format("const ");
|
|
|
- }
|
|
|
- field_generators_.get(field).GeneratePrivateMembers(printer);
|
|
|
- }
|
|
|
- }
|
|
|
- for (auto field : FieldRange(descriptor_)) {
|
|
|
- if (field->options().weak() && IsFieldUsed(field, options_)) {
|
|
|
- format(" const ::$proto_ns$::Message* $1$_;\n", FieldName(field));
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
|
|
|
size_t aux_offset) {
|
|
|
Formatter format(printer, variables_);
|
|
@@ -1952,66 +1905,6 @@ void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void MessageGenerator::GenerateDefaultInstanceInitializer(
|
|
|
- io::Printer* printer) {
|
|
|
- Formatter format(printer, variables_);
|
|
|
-
|
|
|
- // The default instance needs all of its embedded message pointers
|
|
|
- // cross-linked to other default instances. We can't do this initialization
|
|
|
- // in the constructor because some other default instances may not have been
|
|
|
- // constructed yet at that time.
|
|
|
- // TODO(kenton): Maybe all message fields (even for non-default messages)
|
|
|
- // should be initialized to point at default instances rather than NULL?
|
|
|
- for (auto field : FieldRange(descriptor_)) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- Formatter::SaveState saver(&format);
|
|
|
-
|
|
|
- if (!field->is_repeated() && !IsLazy(field, options_) &&
|
|
|
- field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
|
|
- (!field->real_containing_oneof() ||
|
|
|
- HasDescriptorMethods(descriptor_->file(), options_))) {
|
|
|
- std::string name;
|
|
|
- if (field->real_containing_oneof() || field->options().weak()) {
|
|
|
- name = "_" + classname_ + "_default_instance_.";
|
|
|
- } else {
|
|
|
- name =
|
|
|
- "_" + classname_ + "_default_instance_._instance.get_mutable()->";
|
|
|
- }
|
|
|
- name += FieldName(field);
|
|
|
- format.Set("name", name);
|
|
|
- if (IsWeak(field, options_)) {
|
|
|
- format(
|
|
|
- "$package_ns$::$name$_ = reinterpret_cast<const "
|
|
|
- "::$proto_ns$::Message*>(&$1$);\n"
|
|
|
- "if ($package_ns$::$name$_ == nullptr) {\n"
|
|
|
- " $package_ns$::$name$_ = "
|
|
|
- "::$proto_ns$::Empty::internal_default_instance();\n"
|
|
|
- "}\n",
|
|
|
- QualifiedDefaultInstanceName(field->message_type(),
|
|
|
- options_)); // 1
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
|
|
|
- format(
|
|
|
- "$package_ns$::$name$_ = reinterpret_cast<$1$*>(\n"
|
|
|
- " $2$);\n",
|
|
|
- FieldMessageTypeName(field, options_),
|
|
|
- QualifiedDefaultInstancePtr(field->message_type(), options_));
|
|
|
- } else {
|
|
|
- format(
|
|
|
- "$package_ns$::$name$_ = const_cast< $1$*>(\n"
|
|
|
- " $1$::internal_default_instance());\n",
|
|
|
- FieldMessageTypeName(field, options_));
|
|
|
- }
|
|
|
- } else if (field->real_containing_oneof() &&
|
|
|
- HasDescriptorMethods(descriptor_->file(), options_)) {
|
|
|
- field_generators_.get(field).GenerateConstructorCode(printer);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
|
|
|
Formatter format(printer, variables_);
|
|
|
if (IsMapEntryMessage(descriptor_)) {
|
|
@@ -2037,14 +1930,6 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // TODO(gerbens) Remove this function. With a little bit of cleanup and
|
|
|
- // refactoring this is superfluous.
|
|
|
- format("void $classname$::InitAsDefaultInstance() {\n");
|
|
|
- format.Indent();
|
|
|
- GenerateDefaultInstanceInitializer(printer);
|
|
|
- format.Outdent();
|
|
|
- format("}\n");
|
|
|
-
|
|
|
if (IsAnyMessage(descriptor_, options_)) {
|
|
|
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
|
|
format(
|
|
@@ -2057,8 +1942,9 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
|
|
|
"}\n");
|
|
|
}
|
|
|
format(
|
|
|
- "bool $classname$::ParseAnyTypeUrl(const string& type_url,\n"
|
|
|
- " std::string* full_type_name) {\n"
|
|
|
+ "bool $classname$::ParseAnyTypeUrl(\n"
|
|
|
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n"
|
|
|
+ " std::string* full_type_name) {\n"
|
|
|
" return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n"
|
|
|
" full_type_name);\n"
|
|
|
"}\n"
|
|
@@ -2075,7 +1961,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
|
|
|
}
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
field_generators_.get(field).GenerateInternalAccessorDeclarations(printer);
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
continue;
|
|
|
}
|
|
|
if (HasHasbit(field)) {
|
|
@@ -2101,14 +1987,14 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
|
|
|
format.Outdent();
|
|
|
format("};\n\n");
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GenerateInternalAccessorDefinitions(printer);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Generate non-inline field definitions.
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
continue;
|
|
|
}
|
|
|
field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer);
|
|
@@ -2413,13 +2299,16 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
|
|
|
descriptor_->real_oneof_decl_count();
|
|
|
size_t entries = offsets;
|
|
|
for (auto field : FieldRange(descriptor_)) {
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
format("~0u, // stripped\n");
|
|
|
continue;
|
|
|
}
|
|
|
- if (field->real_containing_oneof() || field->options().weak()) {
|
|
|
- format("offsetof($classtype$DefaultTypeInternal, $1$_)",
|
|
|
- FieldName(field));
|
|
|
+ // TODO(sbenza): We should not have an entry in the offset table for fields
|
|
|
+ // that do not use them.
|
|
|
+ if (field->options().weak() || field->real_containing_oneof()) {
|
|
|
+ // Mark the field to prevent unintentional access through reflection.
|
|
|
+ // Don't use the top bit because that is for unused fields.
|
|
|
+ format("::$proto_ns$::internal::kInvalidFieldOffsetTag");
|
|
|
} else {
|
|
|
format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field));
|
|
|
}
|
|
@@ -2429,7 +2318,11 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
|
|
|
format(" | $1$", tag);
|
|
|
}
|
|
|
|
|
|
- format(",\n");
|
|
|
+ if (!IsFieldUsed(field, options_)) {
|
|
|
+ format(" | 0x80000000u, // unused\n");
|
|
|
+ } else {
|
|
|
+ format(",\n");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int count = 0;
|
|
@@ -2483,9 +2376,7 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
|
|
|
|
|
|
format("void $classname$::SharedDtor() {\n");
|
|
|
format.Indent();
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- format("$DCHK$(GetArena() == nullptr);\n");
|
|
|
- }
|
|
|
+ format("$DCHK$(GetArena() == nullptr);\n");
|
|
|
// Write the destructors for each field except oneof members.
|
|
|
// optimized_order_ does not contain oneof fields.
|
|
|
for (auto field : optimized_order_) {
|
|
@@ -2541,7 +2432,7 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
|
|
|
// and returns false for oneof fields.
|
|
|
for (auto oneof : OneOfRange(descriptor_)) {
|
|
|
for (auto field : FieldRange(oneof)) {
|
|
|
- if (IsFieldUsed(field, options_) &&
|
|
|
+ if (!IsFieldStripped(field, options_) &&
|
|
|
field_generators_.get(field).GenerateArenaDestructorCode(printer)) {
|
|
|
need_registration = true;
|
|
|
}
|
|
@@ -2644,7 +2535,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
|
|
|
|
|
|
// Initialize member variables with arena constructor.
|
|
|
for (auto field : optimized_order_) {
|
|
|
- GOOGLE_DCHECK(IsFieldUsed(field, options_));
|
|
|
+ GOOGLE_DCHECK(!IsFieldStripped(field, options_));
|
|
|
bool has_arena_constructor = field->is_repeated();
|
|
|
if (!field->real_containing_oneof() &&
|
|
|
(IsLazy(field, options_) || IsStringPiece(field, options_))) {
|
|
@@ -2671,24 +2562,14 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
|
|
|
initializer_null += ", _weak_field_map_(nullptr)";
|
|
|
}
|
|
|
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- format(
|
|
|
- "$classname$::$classname$(::$proto_ns$::Arena* arena)\n"
|
|
|
- " : $1$ {\n"
|
|
|
- " SharedCtor();\n"
|
|
|
- " RegisterArenaDtor(arena);\n"
|
|
|
- " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
|
|
|
- "}\n",
|
|
|
- initializer_with_arena);
|
|
|
- } else {
|
|
|
- format(
|
|
|
- "$classname$::$classname$()\n"
|
|
|
- " : $1$ {\n"
|
|
|
- " SharedCtor();\n"
|
|
|
- " // @@protoc_insertion_point(constructor:$full_name$)\n"
|
|
|
- "}\n",
|
|
|
- initializer_null);
|
|
|
- }
|
|
|
+ format(
|
|
|
+ "$classname$::$classname$(::$proto_ns$::Arena* arena)\n"
|
|
|
+ " : $1$ {\n"
|
|
|
+ " SharedCtor();\n"
|
|
|
+ " RegisterArenaDtor(arena);\n"
|
|
|
+ " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
|
|
|
+ "}\n",
|
|
|
+ initializer_with_arena);
|
|
|
|
|
|
std::map<std::string, std::string> vars;
|
|
|
SetUnknkownFieldsVariable(descriptor_, options_, &vars);
|
|
@@ -2760,7 +2641,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
|
|
|
for (auto field : FieldRange(oneof)) {
|
|
|
format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
|
|
|
format.Indent();
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GenerateMergingCode(printer);
|
|
|
}
|
|
|
format("break;\n");
|
|
@@ -2799,9 +2680,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
|
|
|
GenerateSharedDestructorCode(printer);
|
|
|
|
|
|
// Generate the arena-specific destructor code.
|
|
|
- if (SupportsArenas(descriptor_)) {
|
|
|
- GenerateArenaDestructorCode(printer);
|
|
|
- }
|
|
|
+ GenerateArenaDestructorCode(printer);
|
|
|
|
|
|
// Generate SetCachedSize.
|
|
|
format(
|
|
@@ -2824,9 +2703,8 @@ void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
|
|
|
"template<> "
|
|
|
"PROTOBUF_NOINLINE "
|
|
|
"$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n"
|
|
|
- " return Arena::$1$Internal< $classtype$ >(arena);\n"
|
|
|
- "}\n",
|
|
|
- MessageCreateFunction(descriptor_));
|
|
|
+ " return Arena::CreateMessageInternal< $classtype$ >(arena);\n"
|
|
|
+ "}\n");
|
|
|
}
|
|
|
|
|
|
void MessageGenerator::GenerateClear(io::Printer* printer) {
|
|
@@ -3018,7 +2896,7 @@ void MessageGenerator::GenerateOneofClear(io::Printer* printer) {
|
|
|
format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
|
|
|
format.Indent();
|
|
|
// We clear only allocated objects in oneofs
|
|
|
- if (!IsStringOrMessage(field) || !IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) {
|
|
|
format("// No need to clear\n");
|
|
|
} else {
|
|
|
field_generators_.get(field).GenerateClearingCode(printer);
|
|
@@ -3065,7 +2943,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
|
|
|
"metadata_);\n");
|
|
|
|
|
|
if (!has_bit_indices_.empty()) {
|
|
|
- for (int i = 0; i < HasBitsSize() / 4; ++i) {
|
|
|
+ for (int i = 0; i < HasBitsSize(); ++i) {
|
|
|
format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i);
|
|
|
}
|
|
|
}
|
|
@@ -3307,7 +3185,7 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
|
|
|
for (auto field : FieldRange(oneof)) {
|
|
|
format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
|
|
|
format.Indent();
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GenerateMergingCode(printer);
|
|
|
}
|
|
|
format("break;\n");
|
|
@@ -3527,8 +3405,26 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray(
|
|
|
|
|
|
format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n");
|
|
|
|
|
|
+ if (!ShouldSerializeInOrder(descriptor_, options_)) {
|
|
|
+ format.Outdent();
|
|
|
+ format("#ifdef NDEBUG\n");
|
|
|
+ format.Indent();
|
|
|
+ }
|
|
|
+
|
|
|
GenerateSerializeWithCachedSizesBody(printer);
|
|
|
|
|
|
+ if (!ShouldSerializeInOrder(descriptor_, options_)) {
|
|
|
+ format.Outdent();
|
|
|
+ format("#else // NDEBUG\n");
|
|
|
+ format.Indent();
|
|
|
+
|
|
|
+ GenerateSerializeWithCachedSizesBodyShuffled(printer);
|
|
|
+
|
|
|
+ format.Outdent();
|
|
|
+ format("#endif // !NDEBUG\n");
|
|
|
+ format.Indent();
|
|
|
+ }
|
|
|
+
|
|
|
format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n");
|
|
|
|
|
|
format.Outdent();
|
|
@@ -3643,11 +3539,14 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(
|
|
|
(i < descriptor_->field_count() &&
|
|
|
ordered_fields[i]->number() < sorted_extensions[j]->start)) {
|
|
|
const FieldDescriptor* field = ordered_fields[i++];
|
|
|
- if (!IsFieldUsed(field, options_)) {
|
|
|
+ if (IsFieldStripped(field, options_)) {
|
|
|
continue;
|
|
|
}
|
|
|
if (field->options().weak()) {
|
|
|
- last_weak_field = field;
|
|
|
+ if (last_weak_field == nullptr ||
|
|
|
+ last_weak_field->number() < field->number()) {
|
|
|
+ last_weak_field = field;
|
|
|
+ }
|
|
|
PrintFieldComment(format, field);
|
|
|
} else {
|
|
|
if (last_weak_field != nullptr) {
|
|
@@ -3690,6 +3589,115 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(
|
|
|
format("}\n");
|
|
|
}
|
|
|
|
|
|
+void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled(
|
|
|
+ io::Printer* printer) {
|
|
|
+ Formatter format(printer, variables_);
|
|
|
+
|
|
|
+ std::vector<const FieldDescriptor*> ordered_fields =
|
|
|
+ SortFieldsByNumber(descriptor_);
|
|
|
+ ordered_fields.erase(
|
|
|
+ std::remove_if(ordered_fields.begin(), ordered_fields.end(),
|
|
|
+ [this](const FieldDescriptor* f) {
|
|
|
+ return !IsFieldUsed(f, options_);
|
|
|
+ }),
|
|
|
+ ordered_fields.end());
|
|
|
+
|
|
|
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
|
|
|
+ sorted_extensions.reserve(descriptor_->extension_range_count());
|
|
|
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
|
|
|
+ sorted_extensions.push_back(descriptor_->extension_range(i));
|
|
|
+ }
|
|
|
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
|
|
|
+ ExtensionRangeSorter());
|
|
|
+
|
|
|
+ int num_fields = ordered_fields.size() + sorted_extensions.size();
|
|
|
+ constexpr int kLargePrime = 1000003;
|
|
|
+ GOOGLE_CHECK_LT(num_fields, kLargePrime)
|
|
|
+ << "Prime offset must be greater than the number of fields to ensure "
|
|
|
+ "those are coprime.";
|
|
|
+
|
|
|
+ if (num_weak_fields_) {
|
|
|
+ format(
|
|
|
+ "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer("
|
|
|
+ "_weak_field_map_);\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ format(
|
|
|
+ "static const int kStart = GetInvariantPerBuild($1$UL) % $2$;\n"
|
|
|
+ "bool first_pass = true;\n"
|
|
|
+ "for (int i = kStart; i != kStart || first_pass; i = ((i + $3$) % $2$)) "
|
|
|
+ "{\n",
|
|
|
+ 0,
|
|
|
+ num_fields, kLargePrime);
|
|
|
+
|
|
|
+ format.Indent();
|
|
|
+ format("switch(i) {\n");
|
|
|
+ format.Indent();
|
|
|
+
|
|
|
+ bool first_pass_set = false;
|
|
|
+ int index = 0;
|
|
|
+ for (const auto* f : ordered_fields) {
|
|
|
+ format("case $1$: {\n", index++);
|
|
|
+ format.Indent();
|
|
|
+
|
|
|
+ if (!first_pass_set) {
|
|
|
+ first_pass_set = true;
|
|
|
+ format("first_pass = false;\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ GenerateSerializeOneField(printer, f, -1);
|
|
|
+
|
|
|
+ format("break;\n");
|
|
|
+ format.Outdent();
|
|
|
+ format("}\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const auto* r : sorted_extensions) {
|
|
|
+ format("case $1$: {\n", index++);
|
|
|
+ format.Indent();
|
|
|
+
|
|
|
+ if (!first_pass_set) {
|
|
|
+ first_pass_set = true;
|
|
|
+ format("first_pass = false;\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ GenerateSerializeOneExtensionRange(printer, r);
|
|
|
+
|
|
|
+ format("break;\n");
|
|
|
+ format.Outdent();
|
|
|
+ format("}\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ format(
|
|
|
+ "default: {\n"
|
|
|
+ " $DCHK$(false) << \"Unexpected index: \" << i;\n"
|
|
|
+ "}\n");
|
|
|
+ format.Outdent();
|
|
|
+ format("}\n");
|
|
|
+
|
|
|
+ format.Outdent();
|
|
|
+ format("}\n");
|
|
|
+
|
|
|
+ std::map<std::string, std::string> vars;
|
|
|
+ SetUnknkownFieldsVariable(descriptor_, options_, &vars);
|
|
|
+ format.AddMap(vars);
|
|
|
+ format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
|
|
|
+ format.Indent();
|
|
|
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
|
|
+ format(
|
|
|
+ "target = "
|
|
|
+ "::$proto_ns$::internal::WireFormat::"
|
|
|
+ "InternalSerializeUnknownFieldsToArray(\n"
|
|
|
+ " $unknown_fields$, target, stream);\n");
|
|
|
+ } else {
|
|
|
+ format(
|
|
|
+ "target = stream->WriteRaw($unknown_fields$.data(),\n"
|
|
|
+ " static_cast<int>($unknown_fields$.size()), target);\n");
|
|
|
+ }
|
|
|
+ format.Outdent();
|
|
|
+ format("}\n");
|
|
|
+}
|
|
|
+
|
|
|
std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const {
|
|
|
const int array_size = HasBitsSize();
|
|
|
std::vector<uint32> masks(array_size, 0);
|
|
@@ -3911,7 +3919,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) {
|
|
|
PrintFieldComment(format, field);
|
|
|
format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
|
|
|
format.Indent();
|
|
|
- if (IsFieldUsed(field, options_)) {
|
|
|
+ if (!IsFieldStripped(field, options_)) {
|
|
|
field_generators_.get(field).GenerateByteSize(printer);
|
|
|
}
|
|
|
format("break;\n");
|
|
@@ -4039,7 +4047,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
|
|
|
format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
|
|
|
format.Indent();
|
|
|
|
|
|
- if (IsFieldUsed(field, options_) &&
|
|
|
+ if (!IsFieldStripped(field, options_) &&
|
|
|
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
|
|
!ShouldIgnoreRequiredFieldCheck(field, options_) &&
|
|
|
scc_analyzer_->HasRequiredFields(field->message_type())) {
|