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 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/cpp/cpp_file.h>
36 #include <map>
37 #include <memory>
38 #ifndef _SHARED_PTR_H
39 #include <google/protobuf/stubs/shared_ptr.h>
40 #endif
41 #include <set>
42 
43 #include <google/protobuf/compiler/cpp/cpp_enum.h>
44 #include <google/protobuf/compiler/cpp/cpp_service.h>
45 #include <google/protobuf/compiler/cpp/cpp_extension.h>
46 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
47 #include <google/protobuf/compiler/cpp/cpp_message.h>
48 #include <google/protobuf/compiler/cpp/cpp_field.h>
49 #include <google/protobuf/io/printer.h>
50 #include <google/protobuf/descriptor.pb.h>
51 #include <google/protobuf/stubs/strutil.h>
52 
53 namespace google {
54 namespace protobuf {
55 namespace compiler {
56 namespace cpp {
57 
58 // ===================================================================
59 
FileGenerator(const FileDescriptor * file,const Options & options)60 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
61     : file_(file),
62       options_(options),
63       message_generators_(
64           new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
65       enum_generators_(
66           new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
67       service_generators_(
68           new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
69       extension_generators_(
70           new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
71 
72   for (int i = 0; i < file->message_type_count(); i++) {
73     message_generators_[i].reset(
74       new MessageGenerator(file->message_type(i), options));
75   }
76 
77   for (int i = 0; i < file->enum_type_count(); i++) {
78     enum_generators_[i].reset(
79       new EnumGenerator(file->enum_type(i), options));
80   }
81 
82   for (int i = 0; i < file->service_count(); i++) {
83     service_generators_[i].reset(
84       new ServiceGenerator(file->service(i), options));
85   }
86 
87   for (int i = 0; i < file->extension_count(); i++) {
88     extension_generators_[i].reset(
89       new ExtensionGenerator(file->extension(i), options));
90   }
91 
92   SplitStringUsing(file_->package(), ".", &package_parts_);
93 }
94 
~FileGenerator()95 FileGenerator::~FileGenerator() {}
96 
GenerateProtoHeader(io::Printer * printer,const string & info_path)97 void FileGenerator::GenerateProtoHeader(io::Printer* printer,
98                                         const string& info_path) {
99   if (!options_.proto_h) {
100     return;
101   }
102 
103   string filename_identifier = FilenameIdentifier(file_->name());
104   GenerateTopHeaderGuard(printer, filename_identifier);
105 
106 
107   GenerateLibraryIncludes(printer);
108 
109   for (int i = 0; i < file_->public_dependency_count(); i++) {
110     const FileDescriptor* dep = file_->public_dependency(i);
111     const char* extension = ".proto.h";
112     string dependency = StripProto(dep->name()) + extension;
113     printer->Print(
114       "#include \"$dependency$\"  // IWYU pragma: export\n",
115       "dependency", dependency);
116   }
117 
118   GenerateMetadataPragma(printer, info_path);
119 
120   printer->Print(
121     "// @@protoc_insertion_point(includes)\n");
122 
123 
124   GenerateForwardDeclarations(printer);
125 
126   // Open namespace.
127   GenerateNamespaceOpeners(printer);
128 
129   GenerateGlobalStateFunctionDeclarations(printer);
130 
131   printer->Print("\n");
132 
133   GenerateEnumDefinitions(printer);
134 
135   printer->Print(kThickSeparator);
136   printer->Print("\n");
137 
138   GenerateMessageDefinitions(printer);
139 
140   printer->Print("\n");
141   printer->Print(kThickSeparator);
142   printer->Print("\n");
143 
144   GenerateServiceDefinitions(printer);
145 
146   GenerateExtensionIdentifiers(printer);
147 
148   printer->Print("\n");
149   printer->Print(kThickSeparator);
150   printer->Print("\n");
151 
152   GenerateInlineFunctionDefinitions(printer);
153 
154   printer->Print(
155     "\n"
156     "// @@protoc_insertion_point(namespace_scope)\n"
157     "\n");
158 
159   // Close up namespace.
160   GenerateNamespaceClosers(printer);
161 
162   // We need to specialize some templates in the ::google::protobuf namespace:
163   GenerateProto2NamespaceEnumSpecializations(printer);
164 
165   printer->Print(
166     "\n"
167     "// @@protoc_insertion_point(global_scope)\n"
168     "\n");
169 
170   GenerateBottomHeaderGuard(printer, filename_identifier);
171 }
172 
GeneratePBHeader(io::Printer * printer,const string & info_path)173 void FileGenerator::GeneratePBHeader(io::Printer* printer,
174                                      const string& info_path) {
175   string filename_identifier =
176       FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
177   GenerateTopHeaderGuard(printer, filename_identifier);
178 
179   if (options_.proto_h) {
180     printer->Print("#include \"$basename$.proto.h\"  // IWYU pragma: export\n",
181                    "basename", StripProto(file_->name()));
182   } else {
183     GenerateLibraryIncludes(printer);
184   }
185   GenerateDependencyIncludes(printer);
186   GenerateMetadataPragma(printer, info_path);
187 
188   printer->Print(
189     "// @@protoc_insertion_point(includes)\n");
190 
191 
192 
193   // Open namespace.
194   GenerateNamespaceOpeners(printer);
195 
196   if (!options_.proto_h) {
197     GenerateGlobalStateFunctionDeclarations(printer);
198     GenerateMessageForwardDeclarations(printer);
199 
200     printer->Print("\n");
201 
202     GenerateEnumDefinitions(printer);
203 
204     printer->Print(kThickSeparator);
205     printer->Print("\n");
206 
207     GenerateMessageDefinitions(printer);
208 
209     printer->Print("\n");
210     printer->Print(kThickSeparator);
211     printer->Print("\n");
212 
213     GenerateServiceDefinitions(printer);
214 
215     GenerateExtensionIdentifiers(printer);
216 
217     printer->Print("\n");
218     printer->Print(kThickSeparator);
219     printer->Print("\n");
220 
221     GenerateInlineFunctionDefinitions(printer);
222   }
223 
224   printer->Print(
225     "\n"
226     "// @@protoc_insertion_point(namespace_scope)\n");
227 
228   // Close up namespace.
229   GenerateNamespaceClosers(printer);
230 
231   if (!options_.proto_h) {
232     // We need to specialize some templates in the ::google::protobuf namespace:
233     GenerateProto2NamespaceEnumSpecializations(printer);
234   }
235 
236   printer->Print(
237     "\n"
238     "// @@protoc_insertion_point(global_scope)\n"
239     "\n");
240 
241   GenerateBottomHeaderGuard(printer, filename_identifier);
242 }
243 
GenerateSource(io::Printer * printer)244 void FileGenerator::GenerateSource(io::Printer* printer) {
245   const bool use_system_include = IsWellKnownMessage(file_);
246   string header =
247       StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
248   printer->Print(
249     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
250     "// source: $filename$\n"
251     "\n"
252     // The generated code calls accessors that might be deprecated. We don't
253     // want the compiler to warn in generated code.
254     "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
255     "#include $left$$header$$right$\n"
256     "\n"
257     "#include <algorithm>\n"    // for swap()
258     "\n"
259     "#include <google/protobuf/stubs/common.h>\n"
260     "#include <google/protobuf/stubs/port.h>\n"
261     "#include <google/protobuf/stubs/once.h>\n"
262     "#include <google/protobuf/io/coded_stream.h>\n"
263     "#include <google/protobuf/wire_format_lite_inl.h>\n",
264     "filename", file_->name(),
265     "header", header,
266     "left", use_system_include ? "<" : "\"",
267     "right", use_system_include ? ">" : "\"");
268 
269   // Unknown fields implementation in lite mode uses StringOutputStream
270   if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
271     printer->Print(
272       "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
273   }
274 
275   if (HasDescriptorMethods(file_, options_)) {
276     printer->Print(
277       "#include <google/protobuf/descriptor.h>\n"
278       "#include <google/protobuf/generated_message_reflection.h>\n"
279       "#include <google/protobuf/reflection_ops.h>\n"
280       "#include <google/protobuf/wire_format.h>\n");
281   }
282 
283   if (options_.proto_h) {
284     // Use the smaller .proto.h files.
285     for (int i = 0; i < file_->dependency_count(); i++) {
286       const FileDescriptor* dep = file_->dependency(i);
287       const char* extension = ".proto.h";
288       string dependency = StripProto(dep->name()) + extension;
289       printer->Print(
290           "#include \"$dependency$\"\n",
291           "dependency", dependency);
292     }
293   }
294 
295   printer->Print(
296     "// @@protoc_insertion_point(includes)\n");
297 
298   GenerateNamespaceOpeners(printer);
299 
300   if (HasDescriptorMethods(file_, options_)) {
301     printer->Print(
302       "\n"
303       "namespace {\n"
304       "\n");
305     for (int i = 0; i < file_->message_type_count(); i++) {
306       message_generators_[i]->GenerateDescriptorDeclarations(printer);
307     }
308     for (int i = 0; i < file_->enum_type_count(); i++) {
309       printer->Print(
310         "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
311         "name", ClassName(file_->enum_type(i), false));
312     }
313 
314     if (HasGenericServices(file_, options_)) {
315       for (int i = 0; i < file_->service_count(); i++) {
316         printer->Print(
317           "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
318           "name", file_->service(i)->name());
319       }
320     }
321 
322     printer->Print(
323       "\n"
324       "}  // namespace\n"
325       "\n");
326   }
327 
328   // Define our externally-visible BuildDescriptors() function.  (For the lite
329   // library, all this does is initialize default instances.)
330   GenerateBuildDescriptors(printer);
331 
332   // Generate enums.
333   for (int i = 0; i < file_->enum_type_count(); i++) {
334     enum_generators_[i]->GenerateMethods(printer);
335   }
336 
337   // Generate classes.
338   for (int i = 0; i < file_->message_type_count(); i++) {
339     printer->Print("\n");
340     printer->Print(kThickSeparator);
341     printer->Print("\n");
342     message_generators_[i]->GenerateClassMethods(printer);
343 
344     printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
345     // Generate class inline methods.
346     message_generators_[i]->GenerateInlineMethods(printer,
347                                                   /* is_inline = */ false);
348     printer->Print("#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
349   }
350 
351   if (HasGenericServices(file_, options_)) {
352     // Generate services.
353     for (int i = 0; i < file_->service_count(); i++) {
354       if (i == 0) printer->Print("\n");
355       printer->Print(kThickSeparator);
356       printer->Print("\n");
357       service_generators_[i]->GenerateImplementation(printer);
358     }
359   }
360 
361   // Define extensions.
362   for (int i = 0; i < file_->extension_count(); i++) {
363     extension_generators_[i]->GenerateDefinition(printer);
364   }
365 
366   printer->Print(
367     "\n"
368     "// @@protoc_insertion_point(namespace_scope)\n");
369 
370   GenerateNamespaceClosers(printer);
371 
372   printer->Print(
373     "\n"
374     "// @@protoc_insertion_point(global_scope)\n");
375 }
376 
377 class FileGenerator::ForwardDeclarations {
378  public:
~ForwardDeclarations()379   ~ForwardDeclarations() {
380     for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
381                                                       end = namespaces_.end();
382          it != end; ++it) {
383       delete it->second;
384     }
385     namespaces_.clear();
386   }
387 
AddOrGetNamespace(const string & ns_name)388   ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
389     ForwardDeclarations*& ns = namespaces_[ns_name];
390     if (ns == NULL) {
391       ns = new ForwardDeclarations;
392     }
393     return ns;
394   }
395 
classes()396   map<string, const Descriptor*>& classes() { return classes_; }
enums()397   map<string, const EnumDescriptor*>& enums() { return enums_; }
398 
Print(io::Printer * printer) const399   void Print(io::Printer* printer) const {
400     for (map<string, const EnumDescriptor *>::const_iterator
401              it = enums_.begin(),
402              end = enums_.end();
403          it != end; ++it) {
404       printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
405       printer->Annotate("enumname", it->second);
406       printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
407                      it->first);
408     }
409     for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
410                                                          end = classes_.end();
411          it != end; ++it) {
412       printer->Print("class $classname$;\n", "classname", it->first);
413       printer->Annotate("classname", it->second);
414     }
415     for (map<string, ForwardDeclarations *>::const_iterator
416              it = namespaces_.begin(),
417              end = namespaces_.end();
418          it != end; ++it) {
419       printer->Print("namespace $nsname$ {\n",
420                      "nsname", it->first);
421       it->second->Print(printer);
422       printer->Print("}  // namespace $nsname$\n",
423                      "nsname", it->first);
424     }
425   }
426 
427 
428  private:
429   map<string, ForwardDeclarations*> namespaces_;
430   map<string, const Descriptor*> classes_;
431   map<string, const EnumDescriptor*> enums_;
432 };
433 
GenerateBuildDescriptors(io::Printer * printer)434 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
435   // AddDescriptors() is a file-level procedure which adds the encoded
436   // FileDescriptorProto for this .proto file to the global DescriptorPool for
437   // generated files (DescriptorPool::generated_pool()). It either runs at
438   // static initialization time (by default) or when default_instance() is
439   // called for the first time (in LITE_RUNTIME mode with
440   // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
441   // constructs default instances and registers extensions.
442   //
443   // Its sibling, AssignDescriptors(), actually pulls the compiled
444   // FileDescriptor from the DescriptorPool and uses it to populate all of
445   // the global variables which store pointers to the descriptor objects.
446   // It also constructs the reflection objects.  It is called the first time
447   // anyone calls descriptor() or GetReflection() on one of the types defined
448   // in the file.
449 
450   // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
451   // and we only use AddDescriptors() to allocate default instances.
452   if (HasDescriptorMethods(file_, options_)) {
453     printer->Print(
454         "\n"
455         "void $assigndescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
456         "void $assigndescriptorsname$() {\n",
457         "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
458     printer->Indent();
459 
460     // Make sure the file has found its way into the pool.  If a descriptor
461     // is requested *during* static init then AddDescriptors() may not have
462     // been called yet, so we call it manually.  Note that it's fine if
463     // AddDescriptors() is called multiple times.
464     printer->Print(
465       "$adddescriptorsname$();\n",
466       "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
467 
468     // Get the file's descriptor from the pool.
469     printer->Print(
470       "const ::google::protobuf::FileDescriptor* file =\n"
471       "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
472       "    \"$filename$\");\n"
473       // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
474       // being unused when compiling an empty .proto file.
475       "GOOGLE_CHECK(file != NULL);\n",
476       "filename", file_->name());
477 
478     // Go through all the stuff defined in this file and generated code to
479     // assign the global descriptor pointers based on the file descriptor.
480     for (int i = 0; i < file_->message_type_count(); i++) {
481       message_generators_[i]->GenerateDescriptorInitializer(printer, i);
482     }
483     for (int i = 0; i < file_->enum_type_count(); i++) {
484       enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
485     }
486     if (HasGenericServices(file_, options_)) {
487       for (int i = 0; i < file_->service_count(); i++) {
488         service_generators_[i]->GenerateDescriptorInitializer(printer, i);
489       }
490     }
491 
492     printer->Outdent();
493     printer->Print(
494       "}\n"
495       "\n");
496 
497     // ---------------------------------------------------------------
498 
499     // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
500     // AssignDescriptors().  All later times, waits for the first call to
501     // complete and then returns.
502     printer->Print(
503       "namespace {\n"
504       "\n"
505       "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
506       "inline void protobuf_AssignDescriptorsOnce() {\n"
507       "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
508       "                 &$assigndescriptorsname$);\n"
509       "}\n"
510       "\n",
511       "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
512 
513     // protobuf_RegisterTypes():  Calls
514     // MessageFactory::InternalRegisterGeneratedType() for each message type.
515     printer->Print(
516         "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n"
517         "void protobuf_RegisterTypes(const ::std::string&) {\n"
518         "  protobuf_AssignDescriptorsOnce();\n");
519     printer->Indent();
520 
521     for (int i = 0; i < file_->message_type_count(); i++) {
522       message_generators_[i]->GenerateTypeRegistrations(printer);
523     }
524 
525     printer->Outdent();
526     printer->Print(
527       "}\n"
528       "\n"
529       "}  // namespace\n");
530   }
531 
532   // -----------------------------------------------------------------
533 
534   // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
535   printer->Print(
536     "\n"
537     "void $shutdownfilename$() {\n",
538     "shutdownfilename", GlobalShutdownFileName(file_->name()));
539   printer->Indent();
540 
541   for (int i = 0; i < file_->message_type_count(); i++) {
542     message_generators_[i]->GenerateShutdownCode(printer);
543   }
544 
545   printer->Outdent();
546   printer->Print(
547     "}\n\n");
548 
549   // -----------------------------------------------------------------
550 
551   // Now generate the AddDescriptors() function.
552   PrintHandlingOptionalStaticInitializers(
553       file_, options_, printer,
554       // With static initializers.
555       // Note that we don't need any special synchronization in the following
556       // code
557       // because it is called at static init time before any threads exist.
558       "void $adddescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
559       "void $adddescriptorsname$() {\n"
560       "  static bool already_here = false;\n"
561       "  if (already_here) return;\n"
562       "  already_here = true;\n"
563       "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
564       "\n",
565       // Without.
566       "void $adddescriptorsname$_impl() {\n"
567       "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
568       "\n",
569       // Vars.
570       "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
571 
572   printer->Indent();
573 
574   // Call the AddDescriptors() methods for all of our dependencies, to make
575   // sure they get added first.
576   for (int i = 0; i < file_->dependency_count(); i++) {
577     const FileDescriptor* dependency = file_->dependency(i);
578     // Print the namespace prefix for the dependency.
579     string add_desc_name = QualifiedFileLevelSymbol(
580         dependency->package(), GlobalAddDescriptorsName(dependency->name()));
581     // Call its AddDescriptors function.
582     printer->Print(
583       "$name$();\n",
584       "name", add_desc_name);
585   }
586 
587   if (HasDescriptorMethods(file_, options_)) {
588     // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
589     // and embed it as a string literal, which is parsed and built into real
590     // descriptors at initialization time.
591     FileDescriptorProto file_proto;
592     file_->CopyTo(&file_proto);
593     string file_data;
594     file_proto.SerializeToString(&file_data);
595 
596 #ifdef _MSC_VER
597     bool breakdown_large_file = true;
598 #else
599     bool breakdown_large_file = false;
600 #endif
601     // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
602     // bytes in length". Declare a static array of characters rather than use a
603     // string literal.
604     if (breakdown_large_file && file_data.size() > 65535) {
605       // This has to be explicitly marked as a signed char because the generated
606       // code puts negative values in the array, and sometimes plain char is
607       // unsigned. That implicit narrowing conversion is not allowed in C++11.
608       // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
609       // has details on why.
610       printer->Print(
611           "static const signed char descriptor[] = {\n");
612       printer->Indent();
613 
614       // Only write 25 bytes per line.
615       static const int kBytesPerLine = 25;
616       for (int i = 0; i < file_data.size();) {
617           for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
618             printer->Print(
619                 "$char$, ",
620                 "char", SimpleItoa(file_data[i]));
621           }
622           printer->Print(
623               "\n");
624       }
625 
626       printer->Outdent();
627       printer->Print(
628           "};\n");
629 
630       printer->Print(
631           "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
632           "size", SimpleItoa(file_data.size()));
633 
634     } else {
635       printer->Print(
636         "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
637 
638       // Only write 40 bytes per line.
639       static const int kBytesPerLine = 40;
640       for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
641         printer->Print("\n  \"$data$\"",
642                        "data",
643                        EscapeTrigraphs(
644                            CEscape(file_data.substr(i, kBytesPerLine))));
645     }
646     printer->Print(
647         ", $size$);\n",
648         "size", SimpleItoa(file_data.size()));
649     }
650 
651     // Call MessageFactory::InternalRegisterGeneratedFile().
652     printer->Print(
653       "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
654       "  \"$filename$\", &protobuf_RegisterTypes);\n",
655       "filename", file_->name());
656   }
657 
658   // Allocate and initialize default instances.  This can't be done lazily
659   // since default instances are returned by simple accessors and are used with
660   // extensions.  Speaking of which, we also register extensions at this time.
661   for (int i = 0; i < file_->message_type_count(); i++) {
662     message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
663   }
664   for (int i = 0; i < file_->extension_count(); i++) {
665     extension_generators_[i]->GenerateRegistration(printer);
666   }
667   for (int i = 0; i < file_->message_type_count(); i++) {
668     message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
669   }
670 
671   printer->Print(
672     "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
673     "shutdownfilename", GlobalShutdownFileName(file_->name()));
674 
675   printer->Outdent();
676   printer->Print(
677     "}\n"
678     "\n");
679 
680   PrintHandlingOptionalStaticInitializers(
681       file_, options_, printer,
682       // With static initializers.
683       "// Force AddDescriptors() to be called at static initialization time.\n"
684       "struct StaticDescriptorInitializer_$filename$ {\n"
685       "  StaticDescriptorInitializer_$filename$() {\n"
686       "    $adddescriptorsname$();\n"
687       "  }\n"
688       "} static_descriptor_initializer_$filename$_;\n",
689       // Without.
690       "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
691       "void $adddescriptorsname$() {\n"
692       "  ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
693       "                 &$adddescriptorsname$_impl);\n"
694       "}\n",
695       // Vars.
696       "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename",
697       FilenameIdentifier(file_->name()));
698 }
699 
GenerateNamespaceOpeners(io::Printer * printer)700 void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
701   if (package_parts_.size() > 0) printer->Print("\n");
702 
703   for (int i = 0; i < package_parts_.size(); i++) {
704     printer->Print("namespace $part$ {\n",
705                    "part", package_parts_[i]);
706   }
707 }
708 
GenerateNamespaceClosers(io::Printer * printer)709 void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
710   if (package_parts_.size() > 0) printer->Print("\n");
711 
712   for (int i = package_parts_.size() - 1; i >= 0; i--) {
713     printer->Print("}  // namespace $part$\n",
714                    "part", package_parts_[i]);
715   }
716 }
717 
GenerateForwardDeclarations(io::Printer * printer)718 void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
719   ForwardDeclarations decls;
720   for (int i = 0; i < file_->dependency_count(); i++) {
721     FileGenerator dependency(file_->dependency(i), options_);
722     dependency.FillForwardDeclarations(&decls);
723   }
724   FillForwardDeclarations(&decls);
725   decls.Print(printer);
726 }
727 
FillForwardDeclarations(ForwardDeclarations * decls)728 void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
729   for (int i = 0; i < file_->public_dependency_count(); i++) {
730     FileGenerator dependency(file_->public_dependency(i), options_);
731     dependency.FillForwardDeclarations(decls);
732   }
733   for (int i = 0; i < package_parts_.size(); i++) {
734     decls = decls->AddOrGetNamespace(package_parts_[i]);
735   }
736   // Generate enum definitions.
737   for (int i = 0; i < file_->message_type_count(); i++) {
738     message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
739   }
740   for (int i = 0; i < file_->enum_type_count(); i++) {
741     enum_generators_[i]->FillForwardDeclaration(&decls->enums());
742   }
743   // Generate forward declarations of classes.
744   for (int i = 0; i < file_->message_type_count(); i++) {
745     message_generators_[i]->FillMessageForwardDeclarations(
746         &decls->classes());
747   }
748 }
749 
GenerateTopHeaderGuard(io::Printer * printer,const string & filename_identifier)750 void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
751                                            const string& filename_identifier) {
752   // Generate top of header.
753   printer->Print(
754       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
755       "// source: $filename$\n"
756       "\n"
757       "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
758       "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
759       "\n"
760       "#include <string>\n",
761       "filename", file_->name(), "filename_identifier", filename_identifier);
762   printer->Print("\n");
763 }
764 
GenerateBottomHeaderGuard(io::Printer * printer,const string & filename_identifier)765 void FileGenerator::GenerateBottomHeaderGuard(
766     io::Printer* printer, const string& filename_identifier) {
767   printer->Print(
768     "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
769     "filename_identifier", filename_identifier);
770 }
771 
GenerateLibraryIncludes(io::Printer * printer)772 void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
773 
774   printer->Print(
775     "#include <google/protobuf/stubs/common.h>\n"
776     "\n");
777 
778   // Verify the protobuf library header version is compatible with the protoc
779   // version before going any further.
780   printer->Print(
781     "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
782     "#error This file was generated by a newer version of protoc which is\n"
783     "#error incompatible with your Protocol Buffer headers.  Please update\n"
784     "#error your headers.\n"
785     "#endif\n"
786     "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
787     "#error This file was generated by an older version of protoc which is\n"
788     "#error incompatible with your Protocol Buffer headers.  Please\n"
789     "#error regenerate this file with a newer version of protoc.\n"
790     "#endif\n"
791     "\n",
792     "min_header_version",
793       SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
794     "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
795 
796   // OK, it's now safe to #include other files.
797   printer->Print(
798     "#include <google/protobuf/arena.h>\n"
799     "#include <google/protobuf/arenastring.h>\n"
800     "#include <google/protobuf/generated_message_util.h>\n");
801   if (UseUnknownFieldSet(file_, options_)) {
802     printer->Print(
803       "#include <google/protobuf/metadata.h>\n");
804   }
805   if (file_->message_type_count() > 0) {
806     if (HasDescriptorMethods(file_, options_)) {
807       printer->Print(
808         "#include <google/protobuf/message.h>\n");
809     } else {
810       printer->Print(
811         "#include <google/protobuf/message_lite.h>\n");
812     }
813   }
814   printer->Print(
815     "#include <google/protobuf/repeated_field.h>\n"
816     "#include <google/protobuf/extension_set.h>\n");
817   if (HasMapFields(file_)) {
818     printer->Print(
819         "#include <google/protobuf/map.h>\n");
820     if (HasDescriptorMethods(file_, options_)) {
821       printer->Print(
822           "#include <google/protobuf/map_field_inl.h>\n");
823     } else {
824       printer->Print(
825           "#include <google/protobuf/map_field_lite.h>\n");
826     }
827   }
828 
829   if (HasEnumDefinitions(file_)) {
830     if (HasDescriptorMethods(file_, options_)) {
831       printer->Print(
832           "#include <google/protobuf/generated_enum_reflection.h>\n");
833     } else {
834       printer->Print(
835           "#include <google/protobuf/generated_enum_util.h>\n");
836     }
837   }
838 
839   if (HasGenericServices(file_, options_)) {
840     printer->Print(
841       "#include <google/protobuf/service.h>\n");
842   }
843 
844   if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
845     printer->Print(
846       "#include <google/protobuf/unknown_field_set.h>\n");
847   }
848 
849 
850   if (IsAnyMessage(file_)) {
851     printer->Print(
852       "#include <google/protobuf/any.h>\n");
853   }
854 }
855 
GenerateMetadataPragma(io::Printer * printer,const string & info_path)856 void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
857                                            const string& info_path) {
858   if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
859       !options_.annotation_guard_name.empty()) {
860     printer->Print(
861         "#ifdef $guard$\n"
862         "#pragma $pragma$ \"$info_path$\"\n"
863         "#endif  // $guard$\n",
864         "guard", options_.annotation_guard_name, "pragma",
865         options_.annotation_pragma_name, "info_path", info_path);
866   }
867 }
868 
GenerateDependencyIncludes(io::Printer * printer)869 void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
870   set<string> public_import_names;
871   for (int i = 0; i < file_->public_dependency_count(); i++) {
872     public_import_names.insert(file_->public_dependency(i)->name());
873   }
874 
875   for (int i = 0; i < file_->dependency_count(); i++) {
876     const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
877     const string& name = file_->dependency(i)->name();
878     bool public_import = (public_import_names.count(name) != 0);
879 
880 
881     printer->Print(
882       "#include $left$$dependency$.pb.h$right$$iwyu$\n",
883       "dependency", StripProto(name),
884       "iwyu", (public_import) ? "  // IWYU pragma: export" : "",
885       "left", use_system_include ? "<" : "\"",
886       "right", use_system_include ? ">" : "\"");
887   }
888 }
889 
GenerateGlobalStateFunctionDeclarations(io::Printer * printer)890 void FileGenerator::GenerateGlobalStateFunctionDeclarations(
891     io::Printer* printer) {
892   // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
893   // functions, so that we can declare them to be friends of each class.
894   printer->Print(
895     "\n"
896     "// Internal implementation detail -- do not call these.\n"
897     "void $dllexport_decl$$adddescriptorsname$();\n",
898     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
899     "dllexport_decl",
900     options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
901 
902   printer->Print(
903     // Note that we don't put dllexport_decl on these because they are only
904     // called by the .pb.cc file in which they are defined.
905     "void $assigndescriptorsname$();\n"
906     "void $shutdownfilename$();\n"
907     "\n",
908     "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
909     "shutdownfilename", GlobalShutdownFileName(file_->name()));
910 }
911 
GenerateMessageForwardDeclarations(io::Printer * printer)912 void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
913   map<string, const Descriptor*> classes;
914   for (int i = 0; i < file_->message_type_count(); i++) {
915     message_generators_[i]->FillMessageForwardDeclarations(&classes);
916   }
917   for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
918                                                        end = classes.end();
919        it != end; ++it) {
920     printer->Print("class $classname$;\n", "classname", it->first);
921     printer->Annotate("classname", it->second);
922   }
923 }
924 
GenerateMessageDefinitions(io::Printer * printer)925 void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
926   // Generate class definitions.
927   for (int i = 0; i < file_->message_type_count(); i++) {
928     if (i > 0) {
929       printer->Print("\n");
930       printer->Print(kThinSeparator);
931       printer->Print("\n");
932     }
933     message_generators_[i]->GenerateClassDefinition(printer);
934   }
935 }
936 
GenerateEnumDefinitions(io::Printer * printer)937 void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
938   // Generate enum definitions.
939   for (int i = 0; i < file_->message_type_count(); i++) {
940     message_generators_[i]->GenerateEnumDefinitions(printer);
941   }
942   for (int i = 0; i < file_->enum_type_count(); i++) {
943     enum_generators_[i]->GenerateDefinition(printer);
944   }
945 }
946 
GenerateServiceDefinitions(io::Printer * printer)947 void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
948   if (HasGenericServices(file_, options_)) {
949     // Generate service definitions.
950     for (int i = 0; i < file_->service_count(); i++) {
951       if (i > 0) {
952         printer->Print("\n");
953         printer->Print(kThinSeparator);
954         printer->Print("\n");
955       }
956       service_generators_[i]->GenerateDeclarations(printer);
957     }
958 
959     printer->Print("\n");
960     printer->Print(kThickSeparator);
961     printer->Print("\n");
962   }
963 }
964 
GenerateExtensionIdentifiers(io::Printer * printer)965 void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
966   // Declare extension identifiers.
967   for (int i = 0; i < file_->extension_count(); i++) {
968     extension_generators_[i]->GenerateDeclaration(printer);
969   }
970 }
971 
GenerateInlineFunctionDefinitions(io::Printer * printer)972 void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
973   // An aside about inline functions in .proto.h mode:
974   //
975   // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
976   // moving much of the inline functions to the .pb.cc file, which can be a
977   // significant performance benefit for compilation time, at the expense
978   // of non-inline function calls.
979   //
980   // However, in .proto.h mode, the definition of the internal dependent
981   // base class must remain in the header, and can never be out-lined. The
982   // dependent base class also needs access to has-bit manipuation
983   // functions, so the has-bit functions must be unconditionally inlined in
984   // proto_h mode.
985   //
986   // This gives us three flavors of functions:
987   //
988   //  1. Functions on the message not used by the internal dependent base
989   //     class: in .proto.h mode, only some functions are defined on the
990   //     message class; others are defined on the dependent base class.
991   //     These are guarded and can be out-lined. These are generated by
992   //     GenerateInlineMethods, and include has_* bit functions in
993   //     non-proto_h mode.
994   //
995   //  2. Functions on the internal dependent base class: these functions
996   //     are dependent on a template parameter, so they always need to
997   //     remain in the header.
998   //
999   //  3. Functions on the message that are used by the dependent base: the
1000   //     dependent base class down casts itself to the message
1001   //     implementation class to access these functions (the has_* bit
1002   //     manipulation functions). Unlike #1, these functions must
1003   //     unconditionally remain in the header. These are emitted by
1004   //     GenerateDependentInlineMethods, even though they are not actually
1005   //     dependent.
1006 
1007   printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1008   // Generate class inline methods.
1009   for (int i = 0; i < file_->message_type_count(); i++) {
1010     if (i > 0) {
1011       printer->Print(kThinSeparator);
1012       printer->Print("\n");
1013     }
1014     message_generators_[i]->GenerateInlineMethods(printer,
1015                                                   /* is_inline = */ true);
1016   }
1017   printer->Print("#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1018 
1019   for (int i = 0; i < file_->message_type_count(); i++) {
1020     if (i > 0) {
1021       printer->Print(kThinSeparator);
1022       printer->Print("\n");
1023     }
1024     // Methods of the dependent base class must always be inline in the header.
1025     message_generators_[i]->GenerateDependentInlineMethods(printer);
1026   }
1027 }
1028 
GenerateProto2NamespaceEnumSpecializations(io::Printer * printer)1029 void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
1030     io::Printer* printer) {
1031   // Emit GetEnumDescriptor specializations into google::protobuf namespace:
1032   if (HasEnumDefinitions(file_)) {
1033     // The SWIG conditional is to avoid a null-pointer dereference
1034     // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
1035     //   namespace X { void Y<Z::W>(); }
1036     // which appears in GetEnumDescriptor() specializations.
1037     printer->Print(
1038         "\n"
1039         "#ifndef SWIG\n"
1040         "namespace google {\nnamespace protobuf {\n"
1041         "\n");
1042     for (int i = 0; i < file_->message_type_count(); i++) {
1043       message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1044     }
1045     for (int i = 0; i < file_->enum_type_count(); i++) {
1046       enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1047     }
1048     printer->Print(
1049         "\n"
1050         "}  // namespace protobuf\n}  // namespace google\n"
1051         "#endif  // SWIG\n");
1052   }
1053 }
1054 
1055 }  // namespace cpp
1056 }  // namespace compiler
1057 }  // namespace protobuf
1058 }  // namespace google
1059