• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #include <algorithm>
32 #include <iostream>
33 #include <sstream>
34 
35 #include <google/protobuf/compiler/objectivec/objectivec_message.h>
36 #include <google/protobuf/compiler/objectivec/objectivec_enum.h>
37 #include <google/protobuf/compiler/objectivec/objectivec_extension.h>
38 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
39 #include <google/protobuf/stubs/stl_util.h>
40 #include <google/protobuf/stubs/strutil.h>
41 #include <google/protobuf/io/printer.h>
42 #include <google/protobuf/io/coded_stream.h>
43 #include <google/protobuf/io/zero_copy_stream_impl.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/wire_format_lite.h>
46 #include <google/protobuf/descriptor.pb.h>
47 
48 namespace google {
49 namespace protobuf {
50 namespace compiler {
51 namespace objectivec {
52 
53 namespace {
54 struct FieldOrderingByNumber {
operator ()google::protobuf::compiler::objectivec::__anonccb115f30111::FieldOrderingByNumber55   inline bool operator()(const FieldDescriptor* a,
56                          const FieldDescriptor* b) const {
57     return a->number() < b->number();
58   }
59 };
60 
OrderGroupForFieldDescriptor(const FieldDescriptor * descriptor)61 int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
62   // The first item in the object structure is our uint32[] for has bits.
63   // We then want to order things to make the instances as small as
64   // possible. So we follow the has bits with:
65   //   1. Anything always 4 bytes - float, *32, enums
66   //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit
67   //      builds and 4 bytes on 32bit builds.
68   //   3. Anything always 8 bytes - double, *64
69   //
70   // NOTE: Bools aren't listed, they were stored in the has bits.
71   //
72   // Why? Using 64bit builds as an example, this means worse case, we have
73   // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
74   // are wasted before the 4 byte values. Then if we have an odd number of
75   // those 4 byte values, the 8 byte values will be pushed down by 32bits to
76   // keep them aligned. But the structure will end 8 byte aligned, so no
77   // waste on the end. If you did the reverse order, you could waste 4 bytes
78   // before the first 8 byte value (after the has array), then a single
79   // bool on the end would need 7 bytes of padding to make the overall
80   // structure 8 byte aligned; so 11 bytes, wasted total.
81 
82   // Anything repeated is a GPB*Array/NSArray, so pointer.
83   if (descriptor->is_repeated()) {
84     return 3;
85   }
86 
87   switch (descriptor->type()) {
88     // All always 8 bytes.
89     case FieldDescriptor::TYPE_DOUBLE:
90     case FieldDescriptor::TYPE_INT64:
91     case FieldDescriptor::TYPE_SINT64:
92     case FieldDescriptor::TYPE_UINT64:
93     case FieldDescriptor::TYPE_SFIXED64:
94     case FieldDescriptor::TYPE_FIXED64:
95       return 4;
96 
97     // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
98     // depending on the build architecture.
99     case FieldDescriptor::TYPE_GROUP:
100     case FieldDescriptor::TYPE_MESSAGE:
101     case FieldDescriptor::TYPE_STRING:
102     case FieldDescriptor::TYPE_BYTES:
103       return 3;
104 
105     // All always 4 bytes (enums are int32s).
106     case FieldDescriptor::TYPE_FLOAT:
107     case FieldDescriptor::TYPE_INT32:
108     case FieldDescriptor::TYPE_SINT32:
109     case FieldDescriptor::TYPE_UINT32:
110     case FieldDescriptor::TYPE_SFIXED32:
111     case FieldDescriptor::TYPE_FIXED32:
112     case FieldDescriptor::TYPE_ENUM:
113       return 2;
114 
115     // 0 bytes. Stored in the has bits.
116     case FieldDescriptor::TYPE_BOOL:
117       return 99;  // End of the list (doesn't really matter).
118   }
119 
120   // Some compilers report reaching end of function even though all cases of
121   // the enum are handed in the switch.
122   GOOGLE_LOG(FATAL) << "Can't get here.";
123   return 0;
124 }
125 
126 struct FieldOrderingByStorageSize {
operator ()google::protobuf::compiler::objectivec::__anonccb115f30111::FieldOrderingByStorageSize127   inline bool operator()(const FieldDescriptor* a,
128                          const FieldDescriptor* b) const {
129     // Order by grouping.
130     const int order_group_a = OrderGroupForFieldDescriptor(a);
131     const int order_group_b = OrderGroupForFieldDescriptor(b);
132     if (order_group_a != order_group_b) {
133       return order_group_a < order_group_b;
134     }
135     // Within the group, order by field number (provides stable ordering).
136     return a->number() < b->number();
137   }
138 };
139 
140 struct ExtensionRangeOrdering {
operator ()google::protobuf::compiler::objectivec::__anonccb115f30111::ExtensionRangeOrdering141   bool operator()(const Descriptor::ExtensionRange* a,
142                   const Descriptor::ExtensionRange* b) const {
143     return a->start < b->start;
144   }
145 };
146 
147 // Sort the fields of the given Descriptor by number into a new[]'d array
148 // and return it.
SortFieldsByNumber(const Descriptor * descriptor)149 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
150   const FieldDescriptor** fields =
151       new const FieldDescriptor* [descriptor->field_count()];
152   for (int i = 0; i < descriptor->field_count(); i++) {
153     fields[i] = descriptor->field(i);
154   }
155   std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
156   return fields;
157 }
158 
159 // Sort the fields of the given Descriptor by storage size into a new[]'d
160 // array and return it.
SortFieldsByStorageSize(const Descriptor * descriptor)161 const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
162   const FieldDescriptor** fields =
163       new const FieldDescriptor* [descriptor->field_count()];
164   for (int i = 0; i < descriptor->field_count(); i++) {
165     fields[i] = descriptor->field(i);
166   }
167   std::sort(fields, fields + descriptor->field_count(),
168        FieldOrderingByStorageSize());
169   return fields;
170 }
171 }  // namespace
172 
MessageGenerator(const string & root_classname,const Descriptor * descriptor,const Options & options)173 MessageGenerator::MessageGenerator(const string& root_classname,
174                                    const Descriptor* descriptor,
175                                    const Options& options)
176     : root_classname_(root_classname),
177       descriptor_(descriptor),
178       field_generators_(descriptor, options),
179       class_name_(ClassName(descriptor_)),
180       deprecated_attribute_(
181           GetOptionalDeprecatedAttribute(descriptor, descriptor->file(), false, true)) {
182 
183   for (int i = 0; i < descriptor_->extension_count(); i++) {
184     extension_generators_.emplace_back(
185         new ExtensionGenerator(class_name_, descriptor_->extension(i)));
186   }
187 
188   for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
189     OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
190     oneof_generators_.emplace_back(generator);
191   }
192 
193   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
194     EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
195     enum_generators_.emplace_back(generator);
196   }
197 
198   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
199     MessageGenerator* generator =
200         new MessageGenerator(root_classname_,
201                              descriptor_->nested_type(i),
202                              options);
203     nested_message_generators_.emplace_back(generator);
204   }
205 }
206 
~MessageGenerator()207 MessageGenerator::~MessageGenerator() {}
208 
GenerateStaticVariablesInitialization(io::Printer * printer)209 void MessageGenerator::GenerateStaticVariablesInitialization(
210     io::Printer* printer) {
211   for (const auto& generator : extension_generators_) {
212     generator->GenerateStaticVariablesInitialization(printer);
213   }
214 
215   for (const auto& generator : nested_message_generators_) {
216     generator->GenerateStaticVariablesInitialization(printer);
217   }
218 }
219 
DetermineForwardDeclarations(std::set<string> * fwd_decls)220 void MessageGenerator::DetermineForwardDeclarations(std::set<string>* fwd_decls) {
221   if (!IsMapEntryMessage(descriptor_)) {
222     for (int i = 0; i < descriptor_->field_count(); i++) {
223       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
224       field_generators_.get(fieldDescriptor)
225           .DetermineForwardDeclarations(fwd_decls);
226     }
227   }
228 
229   for (const auto& generator : nested_message_generators_) {
230     generator->DetermineForwardDeclarations(fwd_decls);
231   }
232 }
233 
DetermineObjectiveCClassDefinitions(std::set<string> * fwd_decls)234 void MessageGenerator::DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) {
235   if (!IsMapEntryMessage(descriptor_)) {
236     for (int i = 0; i < descriptor_->field_count(); i++) {
237       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
238       field_generators_.get(fieldDescriptor)
239           .DetermineObjectiveCClassDefinitions(fwd_decls);
240     }
241   }
242 
243   for (const auto& generator : extension_generators_) {
244     generator->DetermineObjectiveCClassDefinitions(fwd_decls);
245   }
246 
247   for (const auto& generator : nested_message_generators_) {
248     generator->DetermineObjectiveCClassDefinitions(fwd_decls);
249   }
250 
251   const Descriptor* containing_descriptor = descriptor_->containing_type();
252   if (containing_descriptor != NULL) {
253     string containing_class = ClassName(containing_descriptor);
254     fwd_decls->insert(ObjCClassDeclaration(containing_class));
255   }
256 }
257 
IncludesOneOfDefinition() const258 bool MessageGenerator::IncludesOneOfDefinition() const {
259   if (!oneof_generators_.empty()) {
260     return true;
261   }
262 
263   for (const auto& generator : nested_message_generators_) {
264     if (generator->IncludesOneOfDefinition()) {
265       return true;
266     }
267   }
268 
269   return false;
270 }
271 
GenerateEnumHeader(io::Printer * printer)272 void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
273   for (const auto& generator : enum_generators_) {
274     generator->GenerateHeader(printer);
275   }
276 
277   for (const auto& generator : nested_message_generators_) {
278     generator->GenerateEnumHeader(printer);
279   }
280 }
281 
GenerateExtensionRegistrationSource(io::Printer * printer)282 void MessageGenerator::GenerateExtensionRegistrationSource(
283     io::Printer* printer) {
284   for (const auto& generator : extension_generators_) {
285     generator->GenerateRegistrationSource(printer);
286   }
287 
288   for (const auto& generator : nested_message_generators_) {
289     generator->GenerateExtensionRegistrationSource(printer);
290   }
291 }
292 
GenerateMessageHeader(io::Printer * printer)293 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
294   // This a a map entry message, just recurse and do nothing directly.
295   if (IsMapEntryMessage(descriptor_)) {
296     for (const auto& generator : nested_message_generators_) {
297       generator->GenerateMessageHeader(printer);
298     }
299     return;
300   }
301 
302   printer->Print(
303       "#pragma mark - $classname$\n"
304       "\n",
305       "classname", class_name_);
306 
307   if (descriptor_->field_count()) {
308     std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
309         SortFieldsByNumber(descriptor_));
310 
311     printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
312                    "classname", class_name_);
313     printer->Indent();
314 
315     for (int i = 0; i < descriptor_->field_count(); i++) {
316       field_generators_.get(sorted_fields[i])
317           .GenerateFieldNumberConstant(printer);
318     }
319 
320     printer->Outdent();
321     printer->Print("};\n\n");
322   }
323 
324   for (const auto& generator : oneof_generators_) {
325     generator->GenerateCaseEnum(printer);
326   }
327 
328   string message_comments;
329   SourceLocation location;
330   if (descriptor_->GetSourceLocation(&location)) {
331     message_comments = BuildCommentsString(location, false);
332   } else {
333     message_comments = "";
334   }
335 
336   printer->Print(
337       "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
338       "classname", class_name_,
339       "deprecated_attribute", deprecated_attribute_,
340       "comments", message_comments);
341 
342   std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
343   for (int i = 0; i < descriptor_->field_count(); i++) {
344     const FieldDescriptor* field = descriptor_->field(i);
345     const OneofDescriptor *oneof = field->real_containing_oneof();
346     if (oneof) {
347       const int oneof_index = oneof->index();
348       if (!seen_oneofs[oneof_index]) {
349         seen_oneofs[oneof_index] = 1;
350         oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
351             printer);
352       }
353     }
354     field_generators_.get(field).GeneratePropertyDeclaration(printer);
355   }
356 
357   printer->Print("@end\n\n");
358 
359   for (int i = 0; i < descriptor_->field_count(); i++) {
360     field_generators_.get(descriptor_->field(i))
361         .GenerateCFunctionDeclarations(printer);
362   }
363 
364   if (!oneof_generators_.empty()) {
365     for (const auto& generator : oneof_generators_) {
366       generator->GenerateClearFunctionDeclaration(printer);
367     }
368     printer->Print("\n");
369   }
370 
371   if (descriptor_->extension_count() > 0) {
372     printer->Print("@interface $classname$ (DynamicMethods)\n\n",
373                    "classname", class_name_);
374     for (const auto& generator : extension_generators_) {
375       generator->GenerateMembersHeader(printer);
376     }
377     printer->Print("@end\n\n");
378   }
379 
380   for (const auto& generator : nested_message_generators_) {
381     generator->GenerateMessageHeader(printer);
382   }
383 }
384 
GenerateSource(io::Printer * printer)385 void MessageGenerator::GenerateSource(io::Printer* printer) {
386   if (!IsMapEntryMessage(descriptor_)) {
387     printer->Print(
388         "#pragma mark - $classname$\n"
389         "\n",
390         "classname", class_name_);
391 
392     if (!deprecated_attribute_.empty()) {
393       // No warnings when compiling the impl of this deprecated class.
394       printer->Print(
395           "#pragma clang diagnostic push\n"
396           "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
397           "\n");
398     }
399 
400     printer->Print("@implementation $classname$\n\n",
401                    "classname", class_name_);
402 
403     for (const auto& generator : oneof_generators_) {
404       generator->GeneratePropertyImplementation(printer);
405     }
406 
407     for (int i = 0; i < descriptor_->field_count(); i++) {
408       field_generators_.get(descriptor_->field(i))
409           .GeneratePropertyImplementation(printer);
410     }
411 
412     std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
413         SortFieldsByNumber(descriptor_));
414     std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
415         SortFieldsByStorageSize(descriptor_));
416 
417     std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
418     sorted_extensions.reserve(descriptor_->extension_range_count());
419     for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
420       sorted_extensions.push_back(descriptor_->extension_range(i));
421     }
422 
423     std::sort(sorted_extensions.begin(), sorted_extensions.end(),
424          ExtensionRangeOrdering());
425 
426     // Assign has bits:
427     // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
428     //    who needs has bits and assigning them.
429     // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
430     //    index that groups all the elements in the oneof.
431     size_t num_has_bits = field_generators_.CalculateHasBits();
432     size_t sizeof_has_storage = (num_has_bits + 31) / 32;
433     if (sizeof_has_storage == 0) {
434       // In the case where no field needs has bits, don't let the _has_storage_
435       // end up as zero length (zero length arrays are sort of a grey area
436       // since it has to be at the start of the struct). This also ensures a
437       // field with only oneofs keeps the required negative indices they need.
438       sizeof_has_storage = 1;
439     }
440     // Tell all the fields the oneof base.
441     for (const auto& generator : oneof_generators_) {
442       generator->SetOneofIndexBase(sizeof_has_storage);
443     }
444     field_generators_.SetOneofIndexBase(sizeof_has_storage);
445     // sizeof_has_storage needs enough bits for the single fields that aren't in
446     // any oneof, and then one int32 for each oneof (to store the field number).
447     sizeof_has_storage += oneof_generators_.size();
448 
449     printer->Print(
450         "\n"
451         "typedef struct $classname$__storage_ {\n"
452         "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
453         "classname", class_name_,
454         "sizeof_has_storage", StrCat(sizeof_has_storage));
455     printer->Indent();
456 
457     for (int i = 0; i < descriptor_->field_count(); i++) {
458       field_generators_.get(size_order_fields[i])
459           .GenerateFieldStorageDeclaration(printer);
460     }
461     printer->Outdent();
462 
463     printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
464 
465 
466     printer->Print(
467         "// This method is threadsafe because it is initially called\n"
468         "// in +initialize for each subclass.\n"
469         "+ (GPBDescriptor *)descriptor {\n"
470         "  static GPBDescriptor *descriptor = nil;\n"
471         "  if (!descriptor) {\n");
472 
473     TextFormatDecodeData text_format_decode_data;
474     bool has_fields = descriptor_->field_count() > 0;
475     bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
476     string field_description_type;
477     if (need_defaults) {
478       field_description_type = "GPBMessageFieldDescriptionWithDefault";
479     } else {
480       field_description_type = "GPBMessageFieldDescription";
481     }
482     if (has_fields) {
483       printer->Indent();
484       printer->Indent();
485       printer->Print(
486           "static $field_description_type$ fields[] = {\n",
487           "field_description_type", field_description_type);
488       printer->Indent();
489       for (int i = 0; i < descriptor_->field_count(); ++i) {
490         const FieldGenerator& field_generator =
491             field_generators_.get(sorted_fields[i]);
492         field_generator.GenerateFieldDescription(printer, need_defaults);
493         if (field_generator.needs_textformat_name_support()) {
494           text_format_decode_data.AddString(sorted_fields[i]->number(),
495                                             field_generator.generated_objc_name(),
496                                             field_generator.raw_field_name());
497         }
498       }
499       printer->Outdent();
500       printer->Print(
501           "};\n");
502       printer->Outdent();
503       printer->Outdent();
504     }
505 
506     std::map<string, string> vars;
507     vars["classname"] = class_name_;
508     vars["rootclassname"] = root_classname_;
509     vars["fields"] = has_fields ? "fields" : "NULL";
510     if (has_fields) {
511       vars["fields_count"] =
512           "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
513     } else {
514       vars["fields_count"] = "0";
515     }
516 
517     std::vector<string> init_flags;
518     init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
519     init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
520     if (need_defaults) {
521       init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
522     }
523     if (descriptor_->options().message_set_wire_format()) {
524       init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
525     }
526     vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
527                                           init_flags);
528 
529     printer->Print(
530         vars,
531         "    GPBDescriptor *localDescriptor =\n"
532         "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
533         "                                     rootClass:[$rootclassname$ class]\n"
534         "                                          file:$rootclassname$_FileDescriptor()\n"
535         "                                        fields:$fields$\n"
536         "                                    fieldCount:$fields_count$\n"
537         "                                   storageSize:sizeof($classname$__storage_)\n"
538         "                                         flags:$init_flags$];\n");
539     if (!oneof_generators_.empty()) {
540       printer->Print(
541           "    static const char *oneofs[] = {\n");
542       for (const auto& generator : oneof_generators_) {
543         printer->Print("      \"$name$\",\n", "name",
544                        generator->DescriptorName());
545       }
546       printer->Print(
547           "    };\n"
548           "    [localDescriptor setupOneofs:oneofs\n"
549           "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
550           "                   firstHasIndex:$first_has_index$];\n",
551           "first_has_index", oneof_generators_[0]->HasIndexAsString());
552     }
553     if (text_format_decode_data.num_entries() != 0) {
554       const string text_format_data_str(text_format_decode_data.Data());
555       printer->Print(
556           "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
557           "    static const char *extraTextFormatInfo =");
558       static const int kBytesPerLine = 40;  // allow for escaping
559       for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
560         printer->Print(
561             "\n        \"$data$\"",
562             "data", EscapeTrigraphs(
563                 CEscape(text_format_data_str.substr(i, kBytesPerLine))));
564       }
565       printer->Print(
566           ";\n"
567           "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
568           "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
569     }
570     if (!sorted_extensions.empty()) {
571       printer->Print(
572           "    static const GPBExtensionRange ranges[] = {\n");
573       for (int i = 0; i < sorted_extensions.size(); i++) {
574         printer->Print("      { .start = $start$, .end = $end$ },\n",
575                        "start", StrCat(sorted_extensions[i]->start),
576                        "end", StrCat(sorted_extensions[i]->end));
577       }
578       printer->Print(
579           "    };\n"
580           "    [localDescriptor setupExtensionRanges:ranges\n"
581           "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
582     }
583     if (descriptor_->containing_type() != NULL) {
584       string containing_class = ClassName(descriptor_->containing_type());
585       string parent_class_ref = ObjCClass(containing_class);
586       printer->Print(
587           "    [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
588           "parent_class_ref", parent_class_ref);
589     }
590     string suffix_added;
591     ClassName(descriptor_, &suffix_added);
592     if (!suffix_added.empty()) {
593       printer->Print(
594           "    [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
595           "suffix", suffix_added);
596     }
597     printer->Print(
598         "    #if defined(DEBUG) && DEBUG\n"
599         "      NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
600         "    #endif  // DEBUG\n"
601         "    descriptor = localDescriptor;\n"
602         "  }\n"
603         "  return descriptor;\n"
604         "}\n\n"
605         "@end\n\n");
606 
607     if (!deprecated_attribute_.empty()) {
608       printer->Print(
609           "#pragma clang diagnostic pop\n"
610           "\n");
611     }
612 
613     for (int i = 0; i < descriptor_->field_count(); i++) {
614       field_generators_.get(descriptor_->field(i))
615           .GenerateCFunctionImplementations(printer);
616     }
617 
618     for (const auto& generator : oneof_generators_) {
619       generator->GenerateClearFunctionImplementation(printer);
620     }
621   }
622 
623   for (const auto& generator : enum_generators_) {
624     generator->GenerateSource(printer);
625   }
626 
627   for (const auto& generator : nested_message_generators_) {
628     generator->GenerateSource(printer);
629   }
630 }
631 
632 }  // namespace objectivec
633 }  // namespace compiler
634 }  // namespace protobuf
635 }  // namespace google
636