1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/objectivec/message.h"
9
10 #include <algorithm>
11 #include <cstddef>
12 #include <memory>
13 #include <string>
14 #include <vector>
15
16 #include "absl/container/btree_set.h"
17 #include "absl/container/flat_hash_set.h"
18 #include "absl/log/absl_check.h"
19 #include "absl/log/absl_log.h"
20 #include "absl/strings/escaping.h"
21 #include "absl/strings/str_cat.h"
22 #include "absl/strings/string_view.h"
23 #include "google/protobuf/compiler/objectivec/extension.h"
24 #include "google/protobuf/compiler/objectivec/field.h"
25 #include "google/protobuf/compiler/objectivec/helpers.h"
26 #include "google/protobuf/compiler/objectivec/names.h"
27 #include "google/protobuf/compiler/objectivec/oneof.h"
28 #include "google/protobuf/compiler/objectivec/options.h"
29 #include "google/protobuf/compiler/objectivec/tf_decode_data.h"
30 #include "google/protobuf/descriptor.h"
31 #include "google/protobuf/descriptor.pb.h"
32 #include "google/protobuf/io/printer.h"
33
34 namespace google {
35 namespace protobuf {
36 namespace compiler {
37 namespace objectivec {
38
39 namespace {
40
41 struct FieldOrderingByNumber {
operator ()google::protobuf::compiler::objectivec::__anon5177d3570111::FieldOrderingByNumber42 inline bool operator()(const FieldDescriptor* a,
43 const FieldDescriptor* b) const {
44 return a->number() < b->number();
45 }
46 };
47
OrderGroupForFieldDescriptor(const FieldDescriptor * descriptor)48 int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
49 // The first item in the object structure is our uint32[] for has bits.
50 // We then want to order things to make the instances as small as
51 // possible. So we follow the has bits with:
52 // 1. Anything always 4 bytes - float, *32, enums
53 // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit
54 // builds and 4 bytes on 32bit builds.
55 // 3. Anything always 8 bytes - double, *64
56 //
57 // NOTE: Bools aren't listed, they were stored in the has bits.
58 //
59 // Why? Using 64bit builds as an example, this means worse case, we have
60 // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
61 // are wasted before the 4 byte values. Then if we have an odd number of
62 // those 4 byte values, the 8 byte values will be pushed down by 32bits to
63 // keep them aligned. But the structure will end 8 byte aligned, so no
64 // waste on the end. If you did the reverse order, you could waste 4 bytes
65 // before the first 8 byte value (after the has array), then a single
66 // bool on the end would need 7 bytes of padding to make the overall
67 // structure 8 byte aligned; so 11 bytes, wasted total.
68
69 // Anything repeated is a GPB*Array/NSArray, so pointer.
70 if (descriptor->is_repeated()) {
71 return 3;
72 }
73
74 switch (descriptor->type()) {
75 // All always 8 bytes.
76 case FieldDescriptor::TYPE_DOUBLE:
77 case FieldDescriptor::TYPE_INT64:
78 case FieldDescriptor::TYPE_SINT64:
79 case FieldDescriptor::TYPE_UINT64:
80 case FieldDescriptor::TYPE_SFIXED64:
81 case FieldDescriptor::TYPE_FIXED64:
82 return 4;
83
84 // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
85 // depending on the build architecture.
86 case FieldDescriptor::TYPE_GROUP:
87 case FieldDescriptor::TYPE_MESSAGE:
88 case FieldDescriptor::TYPE_STRING:
89 case FieldDescriptor::TYPE_BYTES:
90 return 3;
91
92 // All always 4 bytes (enums are int32s).
93 case FieldDescriptor::TYPE_FLOAT:
94 case FieldDescriptor::TYPE_INT32:
95 case FieldDescriptor::TYPE_SINT32:
96 case FieldDescriptor::TYPE_UINT32:
97 case FieldDescriptor::TYPE_SFIXED32:
98 case FieldDescriptor::TYPE_FIXED32:
99 case FieldDescriptor::TYPE_ENUM:
100 return 2;
101
102 // 0 bytes. Stored in the has bits.
103 case FieldDescriptor::TYPE_BOOL:
104 return 99; // End of the list (doesn't really matter).
105 }
106
107 // Some compilers report reaching end of function even though all cases of
108 // the enum are handed in the switch.
109 ABSL_LOG(FATAL) << "Can't get here.";
110 return 0;
111 }
112
113 struct FieldOrderingByStorageSize {
operator ()google::protobuf::compiler::objectivec::__anon5177d3570111::FieldOrderingByStorageSize114 inline bool operator()(const FieldDescriptor* a,
115 const FieldDescriptor* b) const {
116 // Order by grouping.
117 const int order_group_a = OrderGroupForFieldDescriptor(a);
118 const int order_group_b = OrderGroupForFieldDescriptor(b);
119 if (order_group_a != order_group_b) {
120 return order_group_a < order_group_b;
121 }
122 // Within the group, order by field number (provides stable ordering).
123 return a->number() < b->number();
124 }
125 };
126
127 struct ExtensionRangeOrdering {
operator ()google::protobuf::compiler::objectivec::__anon5177d3570111::ExtensionRangeOrdering128 bool operator()(const Descriptor::ExtensionRange* a,
129 const Descriptor::ExtensionRange* b) const {
130 return a->start_number() < b->start_number();
131 }
132 };
133
134 // This is a reduced case of Descriptor::ExtensionRange with just start and end.
135 struct SimpleExtensionRange {
SimpleExtensionRangegoogle::protobuf::compiler::objectivec::__anon5177d3570111::SimpleExtensionRange136 SimpleExtensionRange(int start, int end) : start(start), end(end) {};
137 int start; // inclusive
138 int end; // exclusive
139
140 // Descriptors expose extension ranges in the order they were defined in the
141 // file, but this reorders and merges the ranges that are contiguous (i.e. -
142 // [(21,30),(10,20)] -> [(10,30)])
Normalizegoogle::protobuf::compiler::objectivec::__anon5177d3570111::SimpleExtensionRange143 static std::vector<SimpleExtensionRange> Normalize(
144 const Descriptor* descriptor) {
145 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
146 sorted_extensions.reserve(descriptor->extension_range_count());
147 for (int i = 0; i < descriptor->extension_range_count(); ++i) {
148 sorted_extensions.push_back(descriptor->extension_range(i));
149 }
150
151 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
152 ExtensionRangeOrdering());
153
154 std::vector<SimpleExtensionRange> result;
155 result.reserve(sorted_extensions.size());
156 for (const auto ext : sorted_extensions) {
157 if (!result.empty() && result.back().end == ext->start_number()) {
158 result.back().end = ext->end_number();
159 } else {
160 result.emplace_back(ext->start_number(), ext->end_number());
161 }
162 }
163 return result;
164 }
165 };
166
167 // Sort the fields of the given Descriptor by number into a new[]'d array
168 // and return it.
SortFieldsByNumber(const Descriptor * descriptor)169 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
170 const FieldDescriptor** fields =
171 new const FieldDescriptor*[descriptor->field_count()];
172 for (int i = 0; i < descriptor->field_count(); i++) {
173 fields[i] = descriptor->field(i);
174 }
175 std::sort(fields, fields + descriptor->field_count(),
176 FieldOrderingByNumber());
177 return fields;
178 }
179
180 // Sort the fields of the given Descriptor by storage size into a new[]'d
181 // array and return it.
SortFieldsByStorageSize(const Descriptor * descriptor)182 const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
183 const FieldDescriptor** fields =
184 new const FieldDescriptor*[descriptor->field_count()];
185 for (int i = 0; i < descriptor->field_count(); i++) {
186 fields[i] = descriptor->field(i);
187 }
188 std::sort(fields, fields + descriptor->field_count(),
189 FieldOrderingByStorageSize());
190 return fields;
191 }
192
193 } // namespace
194
MessageGenerator(const std::string & file_description_name,const Descriptor * descriptor,const GenerationOptions & generation_options)195 MessageGenerator::MessageGenerator(const std::string& file_description_name,
196 const Descriptor* descriptor,
197 const GenerationOptions& generation_options)
198 : file_description_name_(file_description_name),
199 descriptor_(descriptor),
200 generation_options_(generation_options),
201 field_generators_(descriptor, generation_options),
202 class_name_(ClassName(descriptor_)),
203 deprecated_attribute_(
204 GetOptionalDeprecatedAttribute(descriptor, descriptor->file())) {
205 ABSL_CHECK(!descriptor->options().map_entry())
206 << "error: MessageGenerator create of a map<>!";
207 ABSL_CHECK(!descriptor->options().message_set_wire_format() ||
208 descriptor->field_count() == 0)
209 << "error: MessageGenerator message_set_wire_format should never have "
210 "fields!";
211 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
212 oneof_generators_.push_back(std::make_unique<OneofGenerator>(
213 descriptor_->real_oneof_decl(i), generation_options));
214 }
215
216 // Assign has bits:
217 // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
218 // who needs has bits and assigning them.
219 // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
220 // index that groups all the elements in the oneof.
221 size_t num_has_bits = field_generators_.CalculateHasBits();
222 size_t sizeof_has_storage = (num_has_bits + 31) / 32;
223 if (sizeof_has_storage == 0) {
224 // In the case where no field needs has bits, don't let the _has_storage_
225 // end up as zero length (zero length arrays are sort of a grey area
226 // since it has to be at the start of the struct). This also ensures a
227 // field with only oneofs keeps the required negative indices they need.
228 sizeof_has_storage = 1;
229 }
230 // Tell all the fields the oneof base.
231 for (const auto& generator : oneof_generators_) {
232 generator->SetOneofIndexBase(sizeof_has_storage);
233 }
234 field_generators_.SetOneofIndexBase(sizeof_has_storage);
235 // sizeof_has_storage needs enough bits for the single fields that aren't in
236 // any oneof, and then one int32 for each oneof (to store the field number).
237 sizeof_has_storage += oneof_generators_.size();
238
239 sizeof_has_storage_ = sizeof_has_storage;
240 }
241
AddExtensionGenerators(std::vector<std::unique_ptr<ExtensionGenerator>> * extension_generators)242 void MessageGenerator::AddExtensionGenerators(
243 std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
244 for (int i = 0; i < descriptor_->extension_count(); i++) {
245 const FieldDescriptor* extension = descriptor_->extension(i);
246 if (!generation_options_.strip_custom_options ||
247 !ExtensionIsCustomOption(extension)) {
248 extension_generators->push_back(std::make_unique<ExtensionGenerator>(
249 class_name_, extension, generation_options_));
250 extension_generators_.push_back(extension_generators->back().get());
251 }
252 }
253 }
254
DetermineForwardDeclarations(absl::btree_set<std::string> * fwd_decls,bool include_external_types) const255 void MessageGenerator::DetermineForwardDeclarations(
256 absl::btree_set<std::string>* fwd_decls,
257 bool include_external_types) const {
258 for (int i = 0; i < descriptor_->field_count(); i++) {
259 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
260 field_generators_.get(fieldDescriptor)
261 .DetermineForwardDeclarations(fwd_decls, include_external_types);
262 }
263 }
264
DetermineNeededFiles(absl::flat_hash_set<const FileDescriptor * > * deps) const265 void MessageGenerator::DetermineNeededFiles(
266 absl::flat_hash_set<const FileDescriptor*>* deps) const {
267 for (int i = 0; i < descriptor_->field_count(); i++) {
268 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
269 field_generators_.get(fieldDescriptor).DetermineNeededFiles(deps);
270 }
271 }
272
DetermineObjectiveCClassDefinitions(absl::btree_set<std::string> * fwd_decls) const273 void MessageGenerator::DetermineObjectiveCClassDefinitions(
274 absl::btree_set<std::string>* fwd_decls) const {
275 // Forward declare this class, as a linker symbol, so the symbol can be used
276 // to reference the class instead of calling +class later.
277 fwd_decls->insert(ObjCClassDeclaration(class_name_));
278
279 for (int i = 0; i < descriptor_->field_count(); i++) {
280 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
281 field_generators_.get(fieldDescriptor)
282 .DetermineObjectiveCClassDefinitions(fwd_decls);
283 }
284
285 const Descriptor* containing_descriptor = descriptor_->containing_type();
286 if (containing_descriptor != nullptr) {
287 std::string containing_class = ClassName(containing_descriptor);
288 fwd_decls->insert(ObjCClassDeclaration(containing_class));
289 }
290 }
291
GenerateMessageHeader(io::Printer * printer) const292 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) const {
293 auto vars = printer->WithVars({{"classname", class_name_}});
294 printer->Emit(
295 {io::Printer::Sub("deprecated_attribute", deprecated_attribute_)
296 .WithSuffix(";"),
297 {"message_comments",
298 [&] {
299 EmitCommentsString(printer, generation_options_, descriptor_,
300 kCommentStringFlags_ForceMultiline);
301 }},
302 {"message_fieldnum_enum",
303 [&] {
304 if (descriptor_->field_count() == 0) return;
305 printer->Emit(R"objc(
306 typedef GPB_ENUM($classname$_FieldNumber) {
307 $message_fieldnum_enum_values$,
308 };
309 )objc");
310 printer->Emit("\n");
311 }},
312 {"message_fieldnum_enum_values",
313 [&] {
314 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
315 SortFieldsByNumber(descriptor_));
316 for (size_t i = 0; i < (size_t)descriptor_->field_count(); i++) {
317 field_generators_.get(sorted_fields[i])
318 .GenerateFieldNumberConstant(printer);
319 }
320 }},
321 {"oneof_enums",
322 [&] {
323 for (const auto& generator : oneof_generators_) {
324 generator->GenerateCaseEnum(printer);
325 }
326 }},
327 {"message_properties",
328 [&] {
329 std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
330 for (int i = 0; i < descriptor_->field_count(); i++) {
331 const FieldDescriptor* field = descriptor_->field(i);
332 const OneofDescriptor* oneof = field->real_containing_oneof();
333 if (oneof) {
334 const size_t oneof_index = (size_t)oneof->index();
335 if (!seen_oneofs[oneof_index]) {
336 seen_oneofs[oneof_index] = 1;
337 oneof_generators_[oneof_index]
338 ->GeneratePublicCasePropertyDeclaration(printer);
339 }
340 }
341 field_generators_.get(field).GeneratePropertyDeclaration(printer);
342 }
343 }},
344 {"wkt_extra",
345 [&] {
346 if (!IsWKTWithObjCCategory(descriptor_)) {
347 return;
348 }
349 printer->Emit(R"objc(
350 // NOTE: There are some Objective-C specific methods/properties in
351 // GPBWellKnownTypes.h that will likely be useful.
352 )objc");
353 printer->Emit("\n");
354 }}},
355 R"objc(
356 #pragma mark - $classname$
357
358 $message_fieldnum_enum$
359 $oneof_enums$
360 $message_comments$
361 $deprecated_attribute$;
362 GPB_FINAL @interface $classname$ : GPBMessage
363
364 $message_properties$
365 $wkt_extra$
366 @end
367 )objc");
368 printer->Emit("\n");
369
370 for (int i = 0; i < descriptor_->field_count(); i++) {
371 field_generators_.get(descriptor_->field(i))
372 .GenerateCFunctionDeclarations(printer);
373 }
374
375 if (!oneof_generators_.empty()) {
376 for (const auto& generator : oneof_generators_) {
377 generator->GenerateClearFunctionDeclaration(printer);
378 }
379 printer->Emit("\n");
380 }
381
382 if (!extension_generators_.empty()) {
383 printer->Emit({{"extension_info",
384 [&] {
385 for (const auto* generator : extension_generators_) {
386 generator->GenerateMembersHeader(printer);
387 }
388 }}},
389 R"objc(
390 @interface $classname$ (DynamicMethods)
391
392 $extension_info$
393 @end
394 )objc");
395 printer->Emit("\n");
396 }
397 }
398
GenerateSource(io::Printer * printer) const399 void MessageGenerator::GenerateSource(io::Printer* printer) const {
400 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
401 SortFieldsByNumber(descriptor_));
402 std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
403 SortFieldsByStorageSize(descriptor_));
404
405 std::vector<SimpleExtensionRange> sorted_extensions(
406 SimpleExtensionRange::Normalize(descriptor_));
407
408 bool has_fields = descriptor_->field_count() > 0;
409 bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
410
411 TextFormatDecodeData text_format_decode_data;
412 for (int i = 0; i < descriptor_->field_count(); ++i) {
413 const FieldGenerator& field_generator =
414 field_generators_.get(sorted_fields[i]);
415 if (field_generator.needs_textformat_name_support()) {
416 text_format_decode_data.AddString(sorted_fields[i]->number(),
417 field_generator.generated_objc_name(),
418 field_generator.raw_field_name());
419 }
420 }
421
422 const absl::string_view field_description_type(
423 need_defaults ? "GPBMessageFieldDescriptionWithDefault"
424 : "GPBMessageFieldDescription");
425
426 std::vector<std::string> init_flags;
427 init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
428 init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
429 init_flags.push_back(
430 "GPBDescriptorInitializationFlag_ClosedEnumSupportKnown");
431 if (need_defaults) {
432 init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
433 }
434 if (descriptor_->options().message_set_wire_format()) {
435 init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
436 }
437
438 printer->Emit(
439 {{"classname", class_name_},
440 {"clang_diagnostic_push",
441 [&] {
442 if (deprecated_attribute_.empty()) return;
443 // No warnings when compiling the impl of this deprecated class.
444 printer->Emit(R"objc(
445 #pragma clang diagnostic push
446 #pragma clang diagnostic ignored "-Wdeprecated-implementations"
447 )objc");
448 printer->Emit("\n");
449 }},
450 {"clang_diagnostic_pop",
451 [&] {
452 if (deprecated_attribute_.empty()) return;
453 printer->Emit(R"objc(
454 #pragma clang diagnostic pop
455 )objc");
456 printer->Emit("\n");
457 }},
458 {"property_implementation",
459 [&] {
460 for (const auto& generator : oneof_generators_) {
461 generator->GeneratePropertyImplementation(printer);
462 }
463 for (int i = 0; i < descriptor_->field_count(); i++) {
464 field_generators_.get(descriptor_->field(i))
465 .GeneratePropertyImplementation(printer);
466 }
467 }},
468 {"sizeof_has_storage", sizeof_has_storage_},
469 {"storage_fields",
470 [&] {
471 for (int i = 0; i < descriptor_->field_count(); i++) {
472 field_generators_.get(size_order_fields[i])
473 .GenerateFieldStorageDeclaration(printer);
474 }
475 }},
476 {"descriptor_startup",
477 [&] {
478 // If the message scopes extensions, trigger the root class
479 // +initialize/+extensionRegistry as that is where the
480 // runtime support for extensions lives.
481 if (!extension_generators_.empty()) {
482 printer->Emit(R"objc(
483 // Start up the root class to support the scoped extensions.
484 __unused Class rootStartup = [$root_class_name$ class];
485 )objc");
486 } else {
487 // The Root class has a debug runtime check, so if not
488 // starting that up, add the check.
489 printer->Emit("GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
490 }
491 }},
492 {"field_description_type", field_description_type},
493 {"declare_fields_static",
494 [&] {
495 if (!has_fields) return;
496 printer->Emit(R"objc(
497 static $field_description_type$ fields[] = {
498 $declare_fields_static_fields$,
499 };
500 )objc");
501 }},
502 {"declare_fields_static_fields",
503 [&] {
504 for (int i = 0; i < descriptor_->field_count(); ++i) {
505 const FieldGenerator& field_generator =
506 field_generators_.get(sorted_fields[i]);
507 field_generator.GenerateFieldDescription(printer, need_defaults);
508 }
509 }},
510 {"message_name", descriptor_->name()},
511 {"class_reference", ObjCClass(class_name_)},
512 {"file_description_name", file_description_name_},
513 {"fields", has_fields ? "fields" : "NULL"},
514 {"fields_count",
515 has_fields ? absl::StrCat("(uint32_t)(sizeof(fields) / sizeof(",
516 field_description_type, "))")
517 : "0"},
518 {"init_flags",
519 BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, init_flags)},
520 {"oneof_support",
521 [&] {
522 if (oneof_generators_.empty()) return;
523 printer->Emit(
524 {{"first_has_index", oneof_generators_[0]->HasIndexAsString()}},
525 R"objc(
526 static const char *oneofs[] = {
527 $declare_oneof_static_oneofs$,
528 };
529 [localDescriptor setupOneofs:oneofs
530 count:(uint32_t)(sizeof(oneofs) / sizeof(char*))
531 firstHasIndex:$first_has_index$];
532 )objc");
533 }},
534 {"declare_oneof_static_oneofs",
535 [&] {
536 for (const auto& generator : oneof_generators_) {
537 printer->Emit({{"name", generator->DescriptorName()}}, R"objc(
538 "$name$",
539 )objc");
540 }
541 }},
542 {"text_format_decode_support",
543 [&] {
544 if (text_format_decode_data.num_entries() == 0) return;
545
546 printer->Emit(R"objc(
547 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
548 static const char *extraTextFormatInfo =
549 $text_format_decode_support_blob$
550 [localDescriptor setupExtraTextInfo:extraTextFormatInfo];
551 #endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
552 )objc");
553 }},
554 {"text_format_decode_support_blob",
555 [&] {
556 static const int kBytesPerLine = 40; // allow for escaping
557 const std::string text_format_data_str(
558 text_format_decode_data.Data());
559 for (size_t i = 0; i < text_format_data_str.size();
560 i += kBytesPerLine) {
561 printer->Emit(
562 {{"data", EscapeTrigraphs(absl::CEscape(
563 text_format_data_str.substr(i, kBytesPerLine)))},
564 {"ending_semi",
565 (i + kBytesPerLine) < text_format_data_str.size() ? ""
566 : ";"}},
567 R"objc(
568 "$data$"$ending_semi$
569 )objc");
570 }
571 }},
572 {"extension_range_support",
573 [&] {
574 if (sorted_extensions.empty()) return;
575 printer->Emit(
576 {{"ranges",
577 [&] {
578 for (const auto& extension_range : sorted_extensions) {
579 printer->Emit({{"start", extension_range.start},
580 {"end", extension_range.end}},
581 "{ .start = $start$, .end = $end$ },\n");
582 }
583 }}},
584 R"objc(
585 static const GPBExtensionRange ranges[] = {
586 $ranges$,
587 };
588 [localDescriptor setupExtensionRanges:ranges
589 count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];
590 )objc");
591 }},
592 {"containing_type_support",
593 [&] {
594 if (descriptor_->containing_type() == nullptr) return;
595 std::string containing_class =
596 ClassName(descriptor_->containing_type());
597 std::string parent_class_ref = ObjCClass(containing_class);
598 printer->Emit({{"parent_class_ref", parent_class_ref}}, R"objc(
599 [localDescriptor setupContainingMessageClass:$parent_class_ref$];
600 )objc");
601 }}},
602 R"objc(
603 #pragma mark - $classname$
604
605 $clang_diagnostic_push$;
606 @implementation $classname$
607
608 $property_implementation$
609
610 typedef struct $classname$__storage_ {
611 uint32_t _has_storage_[$sizeof_has_storage$];
612 $storage_fields$,
613 } $classname$__storage_;
614
615 // This method is threadsafe because it is initially called
616 // in +initialize for each subclass.
617 + (GPBDescriptor *)descriptor {
618 static GPBDescriptor *descriptor = nil;
619 if (!descriptor) {
620 $descriptor_startup$;
621 $declare_fields_static$;
622 GPBDescriptor *localDescriptor =
623 [GPBDescriptor allocDescriptorForClass:$class_reference$
624 messageName:@"$message_name$"
625 fileDescription:&$file_description_name$
626 fields:$fields$
627 fieldCount:$fields_count$
628 storageSize:sizeof($classname$__storage_)
629 flags:$init_flags$];
630 $oneof_support$;
631 $text_format_decode_support$;
632 $extension_range_support$;
633 $containing_type_support$;
634 #if defined(DEBUG) && DEBUG
635 NSAssert(descriptor == nil, @"Startup recursed!");
636 #endif // DEBUG
637 descriptor = localDescriptor;
638 }
639 return descriptor;
640 }
641
642 @end
643
644 $clang_diagnostic_pop$;
645 )objc");
646
647 for (int i = 0; i < descriptor_->field_count(); i++) {
648 field_generators_.get(descriptor_->field(i))
649 .GenerateCFunctionImplementations(printer);
650 }
651
652 for (const auto& generator : oneof_generators_) {
653 generator->GenerateClearFunctionImplementation(printer);
654 }
655 }
656
657 } // namespace objectivec
658 } // namespace compiler
659 } // namespace protobuf
660 } // namespace google
661