diff --git a/src/google/protobuf/compiler/objectivec/message.cc b/src/google/protobuf/compiler/objectivec/message.cc index 372a8186ae23..7a52b40b55e3 100644 --- a/src/google/protobuf/compiler/objectivec/message.cc +++ b/src/google/protobuf/compiler/objectivec/message.cc @@ -192,6 +192,31 @@ MessageGenerator::MessageGenerator(const std::string& root_classname, oneof_generators_.push_back( std::make_unique(descriptor_->oneof_decl(i))); } + + // Assign has bits: + // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing + // who needs has bits and assigning them. + // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative + // index that groups all the elements in the oneof. + size_t num_has_bits = field_generators_.CalculateHasBits(); + size_t sizeof_has_storage = (num_has_bits + 31) / 32; + if (sizeof_has_storage == 0) { + // In the case where no field needs has bits, don't let the _has_storage_ + // end up as zero length (zero length arrays are sort of a grey area + // since it has to be at the start of the struct). This also ensures a + // field with only oneofs keeps the required negative indices they need. + sizeof_has_storage = 1; + } + // Tell all the fields the oneof base. + for (const auto& generator : oneof_generators_) { + generator->SetOneofIndexBase(sizeof_has_storage); + } + field_generators_.SetOneofIndexBase(sizeof_has_storage); + // sizeof_has_storage needs enough bits for the single fields that aren't in + // any oneof, and then one int32 for each oneof (to store the field number). + sizeof_has_storage += oneof_generators_.size(); + + sizeof_has_storage_ = sizeof_has_storage; } void MessageGenerator::AddExtensionGenerators( @@ -321,7 +346,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) const { } } -void MessageGenerator::GenerateSource(io::Printer* printer) { +void MessageGenerator::GenerateSource(io::Printer* printer) const { if (IsMapEntryMessage(descriptor_)) { return; } @@ -367,29 +392,6 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { std::sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeOrdering()); - // Assign has bits: - // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing - // who needs has bits and assigning them. - // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative - // index that groups all the elements in the oneof. - size_t num_has_bits = field_generators_.CalculateHasBits(); - size_t sizeof_has_storage = (num_has_bits + 31) / 32; - if (sizeof_has_storage == 0) { - // In the case where no field needs has bits, don't let the _has_storage_ - // end up as zero length (zero length arrays are sort of a grey area - // since it has to be at the start of the struct). This also ensures a - // field with only oneofs keeps the required negative indices they need. - sizeof_has_storage = 1; - } - // Tell all the fields the oneof base. - for (const auto& generator : oneof_generators_) { - generator->SetOneofIndexBase(sizeof_has_storage); - } - field_generators_.SetOneofIndexBase(sizeof_has_storage); - // sizeof_has_storage needs enough bits for the single fields that aren't in - // any oneof, and then one int32 for each oneof (to store the field number). - sizeof_has_storage += oneof_generators_.size(); - printer->Print( // clang-format off "\n" @@ -397,7 +399,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " uint32_t _has_storage_[$sizeof_has_storage$];\n", // clang-format on "classname", class_name_, "sizeof_has_storage", - absl::StrCat(sizeof_has_storage)); + absl::StrCat(sizeof_has_storage_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(size_order_fields[i]) diff --git a/src/google/protobuf/compiler/objectivec/message.h b/src/google/protobuf/compiler/objectivec/message.h index 9a732d61b6ef..32ec4deec33c 100644 --- a/src/google/protobuf/compiler/objectivec/message.h +++ b/src/google/protobuf/compiler/objectivec/message.h @@ -31,6 +31,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ +#include #include #include #include @@ -61,7 +62,7 @@ class MessageGenerator { std::vector>* extension_generators); void GenerateMessageHeader(io::Printer* printer) const; - void GenerateSource(io::Printer* printer); + void GenerateSource(io::Printer* printer) const; void DetermineObjectiveCClassDefinitions( absl::btree_set* fwd_decls) const; void DetermineForwardDeclarations(absl::btree_set* fwd_decls, @@ -78,6 +79,7 @@ class MessageGenerator { const std::string deprecated_attribute_; std::vector extension_generators_; std::vector> oneof_generators_; + size_t sizeof_has_storage_; }; } // namespace objectivec