• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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