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 if (i == 0 && HasGeneratedMethods(file_, options_)) {
340 printer->Print(
341 "\n"
342 "namespace {\n"
343 "\n"
344 "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
345 "static void MergeFromFail(int line) {\n"
346 " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
347 "}\n"
348 "\n"
349 "} // namespace\n"
350 "\n");
351 }
352 printer->Print("\n");
353 printer->Print(kThickSeparator);
354 printer->Print("\n");
355 message_generators_[i]->GenerateClassMethods(printer);
356
357 printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
358 // Generate class inline methods.
359 message_generators_[i]->GenerateInlineMethods(printer,
360 /* is_inline = */ false);
361 printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
362 }
363
364 if (HasGenericServices(file_, options_)) {
365 // Generate services.
366 for (int i = 0; i < file_->service_count(); i++) {
367 if (i == 0) printer->Print("\n");
368 printer->Print(kThickSeparator);
369 printer->Print("\n");
370 service_generators_[i]->GenerateImplementation(printer);
371 }
372 }
373
374 // Define extensions.
375 for (int i = 0; i < file_->extension_count(); i++) {
376 extension_generators_[i]->GenerateDefinition(printer);
377 }
378
379 printer->Print(
380 "\n"
381 "// @@protoc_insertion_point(namespace_scope)\n");
382
383 GenerateNamespaceClosers(printer);
384
385 printer->Print(
386 "\n"
387 "// @@protoc_insertion_point(global_scope)\n");
388 }
389
390 class FileGenerator::ForwardDeclarations {
391 public:
~ForwardDeclarations()392 ~ForwardDeclarations() {
393 for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
394 end = namespaces_.end();
395 it != end; ++it) {
396 delete it->second;
397 }
398 namespaces_.clear();
399 }
400
AddOrGetNamespace(const string & ns_name)401 ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
402 ForwardDeclarations*& ns = namespaces_[ns_name];
403 if (ns == NULL) {
404 ns = new ForwardDeclarations;
405 }
406 return ns;
407 }
408
classes()409 map<string, const Descriptor*>& classes() { return classes_; }
enums()410 map<string, const EnumDescriptor*>& enums() { return enums_; }
411
Print(io::Printer * printer) const412 void Print(io::Printer* printer) const {
413 for (map<string, const EnumDescriptor *>::const_iterator
414 it = enums_.begin(),
415 end = enums_.end();
416 it != end; ++it) {
417 printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
418 printer->Annotate("enumname", it->second);
419 printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
420 it->first);
421 }
422 for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
423 end = classes_.end();
424 it != end; ++it) {
425 printer->Print("class $classname$;\n", "classname", it->first);
426 printer->Annotate("classname", it->second);
427 }
428 for (map<string, ForwardDeclarations *>::const_iterator
429 it = namespaces_.begin(),
430 end = namespaces_.end();
431 it != end; ++it) {
432 printer->Print("namespace $nsname$ {\n",
433 "nsname", it->first);
434 it->second->Print(printer);
435 printer->Print("} // namespace $nsname$\n",
436 "nsname", it->first);
437 }
438 }
439
440
441 private:
442 map<string, ForwardDeclarations*> namespaces_;
443 map<string, const Descriptor*> classes_;
444 map<string, const EnumDescriptor*> enums_;
445 };
446
GenerateBuildDescriptors(io::Printer * printer)447 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
448 // AddDescriptors() is a file-level procedure which adds the encoded
449 // FileDescriptorProto for this .proto file to the global DescriptorPool for
450 // generated files (DescriptorPool::generated_pool()). It either runs at
451 // static initialization time (by default) or when default_instance() is
452 // called for the first time (in LITE_RUNTIME mode with
453 // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
454 // constructs default instances and registers extensions.
455 //
456 // Its sibling, AssignDescriptors(), actually pulls the compiled
457 // FileDescriptor from the DescriptorPool and uses it to populate all of
458 // the global variables which store pointers to the descriptor objects.
459 // It also constructs the reflection objects. It is called the first time
460 // anyone calls descriptor() or GetReflection() on one of the types defined
461 // in the file.
462
463 // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
464 // and we only use AddDescriptors() to allocate default instances.
465 if (HasDescriptorMethods(file_, options_)) {
466 printer->Print(
467 "\n"
468 "void $assigndescriptorsname$() {\n",
469 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
470 printer->Indent();
471
472 // Make sure the file has found its way into the pool. If a descriptor
473 // is requested *during* static init then AddDescriptors() may not have
474 // been called yet, so we call it manually. Note that it's fine if
475 // AddDescriptors() is called multiple times.
476 printer->Print(
477 "$adddescriptorsname$();\n",
478 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
479
480 // Get the file's descriptor from the pool.
481 printer->Print(
482 "const ::google::protobuf::FileDescriptor* file =\n"
483 " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
484 " \"$filename$\");\n"
485 // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
486 // being unused when compiling an empty .proto file.
487 "GOOGLE_CHECK(file != NULL);\n",
488 "filename", file_->name());
489
490 // Go through all the stuff defined in this file and generated code to
491 // assign the global descriptor pointers based on the file descriptor.
492 for (int i = 0; i < file_->message_type_count(); i++) {
493 message_generators_[i]->GenerateDescriptorInitializer(printer, i);
494 }
495 for (int i = 0; i < file_->enum_type_count(); i++) {
496 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
497 }
498 if (HasGenericServices(file_, options_)) {
499 for (int i = 0; i < file_->service_count(); i++) {
500 service_generators_[i]->GenerateDescriptorInitializer(printer, i);
501 }
502 }
503
504 printer->Outdent();
505 printer->Print(
506 "}\n"
507 "\n");
508
509 // ---------------------------------------------------------------
510
511 // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
512 // AssignDescriptors(). All later times, waits for the first call to
513 // complete and then returns.
514 printer->Print(
515 "namespace {\n"
516 "\n"
517 "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
518 "inline void protobuf_AssignDescriptorsOnce() {\n"
519 " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
520 " &$assigndescriptorsname$);\n"
521 "}\n"
522 "\n",
523 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
524
525 // protobuf_RegisterTypes(): Calls
526 // MessageFactory::InternalRegisterGeneratedType() for each message type.
527 printer->Print(
528 "void protobuf_RegisterTypes(const ::std::string&) {\n"
529 " protobuf_AssignDescriptorsOnce();\n");
530 printer->Indent();
531
532 for (int i = 0; i < file_->message_type_count(); i++) {
533 message_generators_[i]->GenerateTypeRegistrations(printer);
534 }
535
536 printer->Outdent();
537 printer->Print(
538 "}\n"
539 "\n"
540 "} // namespace\n");
541 }
542
543 // -----------------------------------------------------------------
544
545 // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
546 printer->Print(
547 "\n"
548 "void $shutdownfilename$() {\n",
549 "shutdownfilename", GlobalShutdownFileName(file_->name()));
550 printer->Indent();
551
552 for (int i = 0; i < file_->message_type_count(); i++) {
553 message_generators_[i]->GenerateShutdownCode(printer);
554 }
555
556 printer->Outdent();
557 printer->Print(
558 "}\n\n");
559
560 // -----------------------------------------------------------------
561
562 // Now generate the AddDescriptors() function.
563 PrintHandlingOptionalStaticInitializers(
564 file_, options_, printer,
565 // With static initializers.
566 // Note that we don't need any special synchronization in the following
567 // code
568 // because it is called at static init time before any threads exist.
569 "void $adddescriptorsname$() {\n"
570 " static bool already_here = false;\n"
571 " if (already_here) return;\n"
572 " already_here = true;\n"
573 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
574 "\n",
575 // Without.
576 "void $adddescriptorsname$_impl() {\n"
577 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
578 "\n",
579 // Vars.
580 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
581
582 printer->Indent();
583
584 // Call the AddDescriptors() methods for all of our dependencies, to make
585 // sure they get added first.
586 for (int i = 0; i < file_->dependency_count(); i++) {
587 const FileDescriptor* dependency = file_->dependency(i);
588 // Print the namespace prefix for the dependency.
589 string add_desc_name = QualifiedFileLevelSymbol(
590 dependency->package(), GlobalAddDescriptorsName(dependency->name()));
591 // Call its AddDescriptors function.
592 printer->Print(
593 "$name$();\n",
594 "name", add_desc_name);
595 }
596
597 if (HasDescriptorMethods(file_, options_)) {
598 // Embed the descriptor. We simply serialize the entire FileDescriptorProto
599 // and embed it as a string literal, which is parsed and built into real
600 // descriptors at initialization time.
601 FileDescriptorProto file_proto;
602 file_->CopyTo(&file_proto);
603 string file_data;
604 file_proto.SerializeToString(&file_data);
605
606 #ifdef _MSC_VER
607 bool breakdown_large_file = true;
608 #else
609 bool breakdown_large_file = false;
610 #endif
611 // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
612 // bytes in length". Declare a static array of characters rather than use a
613 // string literal.
614 if (breakdown_large_file && file_data.size() > 65535) {
615 // This has to be explicitly marked as a signed char because the generated
616 // code puts negative values in the array, and sometimes plain char is
617 // unsigned. That implicit narrowing conversion is not allowed in C++11.
618 // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
619 // has details on why.
620 printer->Print(
621 "static const signed char descriptor[] = {\n");
622 printer->Indent();
623
624 // Only write 25 bytes per line.
625 static const int kBytesPerLine = 25;
626 for (int i = 0; i < file_data.size();) {
627 for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
628 printer->Print(
629 "$char$, ",
630 "char", SimpleItoa(file_data[i]));
631 }
632 printer->Print(
633 "\n");
634 }
635
636 printer->Outdent();
637 printer->Print(
638 "};\n");
639
640 printer->Print(
641 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
642 "size", SimpleItoa(file_data.size()));
643
644 } else {
645 printer->Print(
646 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
647
648 // Only write 40 bytes per line.
649 static const int kBytesPerLine = 40;
650 for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
651 printer->Print("\n \"$data$\"",
652 "data",
653 EscapeTrigraphs(
654 CEscape(file_data.substr(i, kBytesPerLine))));
655 }
656 printer->Print(
657 ", $size$);\n",
658 "size", SimpleItoa(file_data.size()));
659 }
660
661 // Call MessageFactory::InternalRegisterGeneratedFile().
662 printer->Print(
663 "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
664 " \"$filename$\", &protobuf_RegisterTypes);\n",
665 "filename", file_->name());
666 }
667
668 // Allocate and initialize default instances. This can't be done lazily
669 // since default instances are returned by simple accessors and are used with
670 // extensions. Speaking of which, we also register extensions at this time.
671 for (int i = 0; i < file_->message_type_count(); i++) {
672 message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
673 }
674 for (int i = 0; i < file_->extension_count(); i++) {
675 extension_generators_[i]->GenerateRegistration(printer);
676 }
677 for (int i = 0; i < file_->message_type_count(); i++) {
678 message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
679 }
680
681 printer->Print(
682 "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
683 "shutdownfilename", GlobalShutdownFileName(file_->name()));
684
685 printer->Outdent();
686 printer->Print(
687 "}\n"
688 "\n");
689
690 PrintHandlingOptionalStaticInitializers(
691 file_, options_, printer,
692 // With static initializers.
693 "// Force AddDescriptors() to be called at static initialization time.\n"
694 "struct StaticDescriptorInitializer_$filename$ {\n"
695 " StaticDescriptorInitializer_$filename$() {\n"
696 " $adddescriptorsname$();\n"
697 " }\n"
698 "} static_descriptor_initializer_$filename$_;\n",
699 // Without.
700 "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
701 "void $adddescriptorsname$() {\n"
702 " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
703 " &$adddescriptorsname$_impl);\n"
704 "}\n",
705 // Vars.
706 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename",
707 FilenameIdentifier(file_->name()));
708 }
709
GenerateNamespaceOpeners(io::Printer * printer)710 void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
711 if (package_parts_.size() > 0) printer->Print("\n");
712
713 for (int i = 0; i < package_parts_.size(); i++) {
714 printer->Print("namespace $part$ {\n",
715 "part", package_parts_[i]);
716 }
717 }
718
GenerateNamespaceClosers(io::Printer * printer)719 void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
720 if (package_parts_.size() > 0) printer->Print("\n");
721
722 for (int i = package_parts_.size() - 1; i >= 0; i--) {
723 printer->Print("} // namespace $part$\n",
724 "part", package_parts_[i]);
725 }
726 }
727
GenerateForwardDeclarations(io::Printer * printer)728 void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
729 ForwardDeclarations decls;
730 for (int i = 0; i < file_->dependency_count(); i++) {
731 FileGenerator dependency(file_->dependency(i), options_);
732 dependency.FillForwardDeclarations(&decls);
733 }
734 FillForwardDeclarations(&decls);
735 decls.Print(printer);
736 }
737
FillForwardDeclarations(ForwardDeclarations * decls)738 void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
739 for (int i = 0; i < file_->public_dependency_count(); i++) {
740 FileGenerator dependency(file_->public_dependency(i), options_);
741 dependency.FillForwardDeclarations(decls);
742 }
743 for (int i = 0; i < package_parts_.size(); i++) {
744 decls = decls->AddOrGetNamespace(package_parts_[i]);
745 }
746 // Generate enum definitions.
747 for (int i = 0; i < file_->message_type_count(); i++) {
748 message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
749 }
750 for (int i = 0; i < file_->enum_type_count(); i++) {
751 enum_generators_[i]->FillForwardDeclaration(&decls->enums());
752 }
753 // Generate forward declarations of classes.
754 for (int i = 0; i < file_->message_type_count(); i++) {
755 message_generators_[i]->FillMessageForwardDeclarations(
756 &decls->classes());
757 }
758 }
759
GenerateTopHeaderGuard(io::Printer * printer,const string & filename_identifier)760 void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
761 const string& filename_identifier) {
762 // Generate top of header.
763 printer->Print(
764 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
765 "// source: $filename$\n"
766 "\n"
767 "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
768 "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
769 "\n"
770 "#include <string>\n",
771 "filename", file_->name(), "filename_identifier", filename_identifier);
772 printer->Print("\n");
773 }
774
GenerateBottomHeaderGuard(io::Printer * printer,const string & filename_identifier)775 void FileGenerator::GenerateBottomHeaderGuard(
776 io::Printer* printer, const string& filename_identifier) {
777 printer->Print(
778 "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
779 "filename_identifier", filename_identifier);
780 }
781
GenerateLibraryIncludes(io::Printer * printer)782 void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
783
784 printer->Print(
785 "#include <google/protobuf/stubs/common.h>\n"
786 "\n");
787
788 // Verify the protobuf library header version is compatible with the protoc
789 // version before going any further.
790 printer->Print(
791 "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
792 "#error This file was generated by a newer version of protoc which is\n"
793 "#error incompatible with your Protocol Buffer headers. Please update\n"
794 "#error your headers.\n"
795 "#endif\n"
796 "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
797 "#error This file was generated by an older version of protoc which is\n"
798 "#error incompatible with your Protocol Buffer headers. Please\n"
799 "#error regenerate this file with a newer version of protoc.\n"
800 "#endif\n"
801 "\n",
802 "min_header_version",
803 SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
804 "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
805
806 // OK, it's now safe to #include other files.
807 printer->Print(
808 "#include <google/protobuf/arena.h>\n"
809 "#include <google/protobuf/arenastring.h>\n"
810 "#include <google/protobuf/generated_message_util.h>\n");
811 if (UseUnknownFieldSet(file_, options_)) {
812 printer->Print(
813 "#include <google/protobuf/metadata.h>\n");
814 }
815 if (file_->message_type_count() > 0) {
816 if (HasDescriptorMethods(file_, options_)) {
817 printer->Print(
818 "#include <google/protobuf/message.h>\n");
819 } else {
820 printer->Print(
821 "#include <google/protobuf/message_lite.h>\n");
822 }
823 }
824 printer->Print(
825 "#include <google/protobuf/repeated_field.h>\n"
826 "#include <google/protobuf/extension_set.h>\n");
827 if (HasMapFields(file_)) {
828 printer->Print(
829 "#include <google/protobuf/map.h>\n");
830 if (HasDescriptorMethods(file_, options_)) {
831 printer->Print(
832 "#include <google/protobuf/map_field_inl.h>\n");
833 } else {
834 printer->Print(
835 "#include <google/protobuf/map_field_lite.h>\n");
836 }
837 }
838
839 if (HasEnumDefinitions(file_)) {
840 if (HasDescriptorMethods(file_, options_)) {
841 printer->Print(
842 "#include <google/protobuf/generated_enum_reflection.h>\n");
843 } else {
844 printer->Print(
845 "#include <google/protobuf/generated_enum_util.h>\n");
846 }
847 }
848
849 if (HasGenericServices(file_, options_)) {
850 printer->Print(
851 "#include <google/protobuf/service.h>\n");
852 }
853
854 if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
855 printer->Print(
856 "#include <google/protobuf/unknown_field_set.h>\n");
857 }
858
859
860 if (IsAnyMessage(file_)) {
861 printer->Print(
862 "#include <google/protobuf/any.h>\n");
863 }
864 }
865
GenerateMetadataPragma(io::Printer * printer,const string & info_path)866 void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
867 const string& info_path) {
868 if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
869 !options_.annotation_guard_name.empty()) {
870 printer->Print(
871 "#ifdef $guard$\n"
872 "#pragma $pragma$ \"$info_path$\"\n"
873 "#endif // $guard$\n",
874 "guard", options_.annotation_guard_name, "pragma",
875 options_.annotation_pragma_name, "info_path", info_path);
876 }
877 }
878
GenerateDependencyIncludes(io::Printer * printer)879 void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
880 set<string> public_import_names;
881 for (int i = 0; i < file_->public_dependency_count(); i++) {
882 public_import_names.insert(file_->public_dependency(i)->name());
883 }
884
885 for (int i = 0; i < file_->dependency_count(); i++) {
886 const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
887 const string& name = file_->dependency(i)->name();
888 bool public_import = (public_import_names.count(name) != 0);
889
890
891 printer->Print(
892 "#include $left$$dependency$.pb.h$right$$iwyu$\n",
893 "dependency", StripProto(name),
894 "iwyu", (public_import) ? " // IWYU pragma: export" : "",
895 "left", use_system_include ? "<" : "\"",
896 "right", use_system_include ? ">" : "\"");
897 }
898 }
899
GenerateGlobalStateFunctionDeclarations(io::Printer * printer)900 void FileGenerator::GenerateGlobalStateFunctionDeclarations(
901 io::Printer* printer) {
902 // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
903 // functions, so that we can declare them to be friends of each class.
904 printer->Print(
905 "\n"
906 "// Internal implementation detail -- do not call these.\n"
907 "void $dllexport_decl$$adddescriptorsname$();\n",
908 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
909 "dllexport_decl",
910 options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
911
912 printer->Print(
913 // Note that we don't put dllexport_decl on these because they are only
914 // called by the .pb.cc file in which they are defined.
915 "void $assigndescriptorsname$();\n"
916 "void $shutdownfilename$();\n"
917 "\n",
918 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
919 "shutdownfilename", GlobalShutdownFileName(file_->name()));
920 }
921
GenerateMessageForwardDeclarations(io::Printer * printer)922 void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
923 map<string, const Descriptor*> classes;
924 for (int i = 0; i < file_->message_type_count(); i++) {
925 message_generators_[i]->FillMessageForwardDeclarations(&classes);
926 }
927 for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
928 end = classes.end();
929 it != end; ++it) {
930 printer->Print("class $classname$;\n", "classname", it->first);
931 printer->Annotate("classname", it->second);
932 }
933 }
934
GenerateMessageDefinitions(io::Printer * printer)935 void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
936 // Generate class definitions.
937 for (int i = 0; i < file_->message_type_count(); i++) {
938 if (i > 0) {
939 printer->Print("\n");
940 printer->Print(kThinSeparator);
941 printer->Print("\n");
942 }
943 message_generators_[i]->GenerateClassDefinition(printer);
944 }
945 }
946
GenerateEnumDefinitions(io::Printer * printer)947 void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
948 // Generate enum definitions.
949 for (int i = 0; i < file_->message_type_count(); i++) {
950 message_generators_[i]->GenerateEnumDefinitions(printer);
951 }
952 for (int i = 0; i < file_->enum_type_count(); i++) {
953 enum_generators_[i]->GenerateDefinition(printer);
954 }
955 }
956
GenerateServiceDefinitions(io::Printer * printer)957 void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
958 if (HasGenericServices(file_, options_)) {
959 // Generate service definitions.
960 for (int i = 0; i < file_->service_count(); i++) {
961 if (i > 0) {
962 printer->Print("\n");
963 printer->Print(kThinSeparator);
964 printer->Print("\n");
965 }
966 service_generators_[i]->GenerateDeclarations(printer);
967 }
968
969 printer->Print("\n");
970 printer->Print(kThickSeparator);
971 printer->Print("\n");
972 }
973 }
974
GenerateExtensionIdentifiers(io::Printer * printer)975 void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
976 // Declare extension identifiers.
977 for (int i = 0; i < file_->extension_count(); i++) {
978 extension_generators_[i]->GenerateDeclaration(printer);
979 }
980 }
981
GenerateInlineFunctionDefinitions(io::Printer * printer)982 void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
983 // An aside about inline functions in .proto.h mode:
984 //
985 // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
986 // moving much of the inline functions to the .pb.cc file, which can be a
987 // significant performance benefit for compilation time, at the expense
988 // of non-inline function calls.
989 //
990 // However, in .proto.h mode, the definition of the internal dependent
991 // base class must remain in the header, and can never be out-lined. The
992 // dependent base class also needs access to has-bit manipuation
993 // functions, so the has-bit functions must be unconditionally inlined in
994 // proto_h mode.
995 //
996 // This gives us three flavors of functions:
997 //
998 // 1. Functions on the message not used by the internal dependent base
999 // class: in .proto.h mode, only some functions are defined on the
1000 // message class; others are defined on the dependent base class.
1001 // These are guarded and can be out-lined. These are generated by
1002 // GenerateInlineMethods, and include has_* bit functions in
1003 // non-proto_h mode.
1004 //
1005 // 2. Functions on the internal dependent base class: these functions
1006 // are dependent on a template parameter, so they always need to
1007 // remain in the header.
1008 //
1009 // 3. Functions on the message that are used by the dependent base: the
1010 // dependent base class down casts itself to the message
1011 // implementation class to access these functions (the has_* bit
1012 // manipulation functions). Unlike #1, these functions must
1013 // unconditionally remain in the header. These are emitted by
1014 // GenerateDependentInlineMethods, even though they are not actually
1015 // dependent.
1016
1017 printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1018 // Generate class inline methods.
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 message_generators_[i]->GenerateInlineMethods(printer,
1025 /* is_inline = */ true);
1026 }
1027 printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1028
1029 for (int i = 0; i < file_->message_type_count(); i++) {
1030 if (i > 0) {
1031 printer->Print(kThinSeparator);
1032 printer->Print("\n");
1033 }
1034 // Methods of the dependent base class must always be inline in the header.
1035 message_generators_[i]->GenerateDependentInlineMethods(printer);
1036 }
1037 }
1038
GenerateProto2NamespaceEnumSpecializations(io::Printer * printer)1039 void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
1040 io::Printer* printer) {
1041 // Emit GetEnumDescriptor specializations into google::protobuf namespace:
1042 if (HasEnumDefinitions(file_)) {
1043 // The SWIG conditional is to avoid a null-pointer dereference
1044 // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
1045 // namespace X { void Y<Z::W>(); }
1046 // which appears in GetEnumDescriptor() specializations.
1047 printer->Print(
1048 "\n"
1049 "#ifndef SWIG\n"
1050 "namespace google {\nnamespace protobuf {\n"
1051 "\n");
1052 for (int i = 0; i < file_->message_type_count(); i++) {
1053 message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1054 }
1055 for (int i = 0; i < file_->enum_type_count(); i++) {
1056 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1057 }
1058 printer->Print(
1059 "\n"
1060 "} // namespace protobuf\n} // namespace google\n"
1061 "#endif // SWIG\n");
1062 }
1063 }
1064
1065 } // namespace cpp
1066 } // namespace compiler
1067 } // namespace protobuf
1068 } // namespace google
1069