blob: 37e4bae44daa18bfc4ffacc184c049069470408e [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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>
Feng Xiaoeee38b02015-08-22 18:25:48 -070036#include <map>
jieluo@google.com4de8f552014-07-18 00:47:59 +000037#include <memory>
Feng Xiao6ef984a2014-11-10 17:34:54 -080038#ifndef _SHARED_PTR_H
39#include <google/protobuf/stubs/shared_ptr.h>
40#endif
jieluo@google.com4de8f552014-07-18 00:47:59 +000041#include <set>
42
temporal40ee5512008-07-10 02:12:20 +000043#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>
kenton@google.comfccb1462009-12-18 02:11:36 +000048#include <google/protobuf/compiler/cpp/cpp_field.h>
temporal40ee5512008-07-10 02:12:20 +000049#include <google/protobuf/io/printer.h>
50#include <google/protobuf/descriptor.pb.h>
51#include <google/protobuf/stubs/strutil.h>
52
53namespace google {
54namespace protobuf {
55namespace compiler {
56namespace cpp {
57
58// ===================================================================
59
jieluo@google.com4de8f552014-07-18 00:47:59 +000060FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
61 : file_(file),
62 message_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080063 new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000064 enum_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080065 new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000066 service_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080067 new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000068 extension_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080069 new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000070 options_(options) {
temporal40ee5512008-07-10 02:12:20 +000071
72 for (int i = 0; i < file->message_type_count(); i++) {
73 message_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000074 new MessageGenerator(file->message_type(i), options));
temporal40ee5512008-07-10 02:12:20 +000075 }
76
77 for (int i = 0; i < file->enum_type_count(); i++) {
78 enum_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000079 new EnumGenerator(file->enum_type(i), options));
temporal40ee5512008-07-10 02:12:20 +000080 }
81
82 for (int i = 0; i < file->service_count(); i++) {
83 service_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000084 new ServiceGenerator(file->service(i), options));
temporal40ee5512008-07-10 02:12:20 +000085 }
86
87 for (int i = 0; i < file->extension_count(); i++) {
88 extension_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000089 new ExtensionGenerator(file->extension(i), options));
temporal40ee5512008-07-10 02:12:20 +000090 }
91
92 SplitStringUsing(file_->package(), ".", &package_parts_);
93}
94
95FileGenerator::~FileGenerator() {}
96
Feng Xiaoeee38b02015-08-22 18:25:48 -070097void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
98 if (!options_.proto_h) {
99 return;
100 }
101
102 string filename_identifier = FilenameIdentifier(file_->name());
103 GenerateTopHeaderGuard(printer, filename_identifier);
104
temporal40ee5512008-07-10 02:12:20 +0000105
Bo Yang5db21732015-05-21 14:28:59 -0700106 GenerateLibraryIncludes(printer);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700107
108 for (int i = 0; i < file_->public_dependency_count(); i++) {
109 const FileDescriptor* dep = file_->public_dependency(i);
110 const char* extension = ".proto.h";
111 string dependency = StripProto(dep->name()) + extension;
112 printer->Print(
113 "#include \"$dependency$\" // IWYU pragma: export\n",
114 "dependency", dependency);
115 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000116
kenton@google.comfccb1462009-12-18 02:11:36 +0000117 printer->Print(
118 "// @@protoc_insertion_point(includes)\n");
119
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000120
Feng Xiaoeee38b02015-08-22 18:25:48 -0700121 GenerateForwardDeclarations(printer);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800122
temporal40ee5512008-07-10 02:12:20 +0000123 // Open namespace.
124 GenerateNamespaceOpeners(printer);
125
Bo Yang5db21732015-05-21 14:28:59 -0700126 GenerateGlobalStateFunctionDeclarations(printer);
temporal40ee5512008-07-10 02:12:20 +0000127
128 printer->Print("\n");
129
Bo Yang5db21732015-05-21 14:28:59 -0700130 GenerateEnumDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +0000131
132 printer->Print(kThickSeparator);
133 printer->Print("\n");
134
Bo Yang5db21732015-05-21 14:28:59 -0700135 GenerateMessageDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +0000136
137 printer->Print("\n");
138 printer->Print(kThickSeparator);
139 printer->Print("\n");
140
Bo Yang5db21732015-05-21 14:28:59 -0700141 GenerateServiceDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +0000142
Bo Yang5db21732015-05-21 14:28:59 -0700143 GenerateExtensionIdentifiers(printer);
temporal40ee5512008-07-10 02:12:20 +0000144
145 printer->Print("\n");
146 printer->Print(kThickSeparator);
147 printer->Print("\n");
148
Bo Yang5db21732015-05-21 14:28:59 -0700149 GenerateInlineFunctionDefinitions(printer);
kenton@google.comfccb1462009-12-18 02:11:36 +0000150
Feng Xiaoeee38b02015-08-22 18:25:48 -0700151 printer->Print(
152 "\n"
153 "// @@protoc_insertion_point(namespace_scope)\n"
154 "\n");
155
temporal40ee5512008-07-10 02:12:20 +0000156 // Close up namespace.
157 GenerateNamespaceClosers(printer);
158
Bo Yang5db21732015-05-21 14:28:59 -0700159 // We need to specialize some templates in the ::google::protobuf namespace:
160 GenerateProto2NamespaceEnumSpecializations(printer);
kenton@google.com80b1d622009-07-29 01:13:20 +0000161
temporal40ee5512008-07-10 02:12:20 +0000162 printer->Print(
kenton@google.comfccb1462009-12-18 02:11:36 +0000163 "\n"
164 "// @@protoc_insertion_point(global_scope)\n"
165 "\n");
166
Feng Xiaoeee38b02015-08-22 18:25:48 -0700167 GenerateBottomHeaderGuard(printer, filename_identifier);
168}
169
170void FileGenerator::GeneratePBHeader(io::Printer* printer) {
171 string filename_identifier =
172 FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
173 GenerateTopHeaderGuard(printer, filename_identifier);
174
175 if (options_.proto_h) {
176 printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
177 "basename", StripProto(file_->name()));
178 } else {
179 GenerateLibraryIncludes(printer);
180 }
181 GenerateDependencyIncludes(printer);
182
183 printer->Print(
184 "// @@protoc_insertion_point(includes)\n");
185
186
187
188 // Open namespace.
189 GenerateNamespaceOpeners(printer);
190
191 if (!options_.proto_h) {
192 GenerateGlobalStateFunctionDeclarations(printer);
193 GenerateMessageForwardDeclarations(printer);
194
195 printer->Print("\n");
196
197 GenerateEnumDefinitions(printer);
198
199 printer->Print(kThickSeparator);
200 printer->Print("\n");
201
202 GenerateMessageDefinitions(printer);
203
204 printer->Print("\n");
205 printer->Print(kThickSeparator);
206 printer->Print("\n");
207
208 GenerateServiceDefinitions(printer);
209
210 GenerateExtensionIdentifiers(printer);
211
212 printer->Print("\n");
213 printer->Print(kThickSeparator);
214 printer->Print("\n");
215
216 GenerateInlineFunctionDefinitions(printer);
217 }
218
219 printer->Print(
220 "\n"
221 "// @@protoc_insertion_point(namespace_scope)\n");
222
223 // Close up namespace.
224 GenerateNamespaceClosers(printer);
225
226 if (!options_.proto_h) {
227 // We need to specialize some templates in the ::google::protobuf namespace:
228 GenerateProto2NamespaceEnumSpecializations(printer);
229 }
230
231 printer->Print(
232 "\n"
233 "// @@protoc_insertion_point(global_scope)\n"
234 "\n");
235
236 GenerateBottomHeaderGuard(printer, filename_identifier);
temporal40ee5512008-07-10 02:12:20 +0000237}
238
239void FileGenerator::GenerateSource(io::Printer* printer) {
Bo Yang1f0286a2015-12-04 13:18:44 -0800240 bool well_known = IsWellKnownMessage(file_);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700241 string header =
242 StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
temporal40ee5512008-07-10 02:12:20 +0000243 printer->Print(
244 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000245 "// source: $filename$\n"
temporal40ee5512008-07-10 02:12:20 +0000246 "\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000247 // The generated code calls accessors that might be deprecated. We don't
248 // want the compiler to warn in generated code.
249 "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
Bo Yang1f0286a2015-12-04 13:18:44 -0800250 "#include $left$$header$$right$\n"
kenton@google.comc65c0412010-02-01 20:35:34 +0000251 "\n"
252 "#include <algorithm>\n" // for swap()
253 "\n"
pliard@google.com75575df2012-10-02 00:15:46 +0000254 "#include <google/protobuf/stubs/common.h>\n"
Feng Xiaoe841bac2015-12-11 17:09:20 -0800255 "#include <google/protobuf/stubs/port.h>\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000256 "#include <google/protobuf/stubs/once.h>\n"
temporal40ee5512008-07-10 02:12:20 +0000257 "#include <google/protobuf/io/coded_stream.h>\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000258 "#include <google/protobuf/wire_format_lite_inl.h>\n",
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000259 "filename", file_->name(),
Bo Yang1f0286a2015-12-04 13:18:44 -0800260 "header", header,
261 "left", well_known ? "<" : "\"",
262 "right", well_known ? ">" : "\"");
temporal40ee5512008-07-10 02:12:20 +0000263
jieluo@google.com4de8f552014-07-18 00:47:59 +0000264 // Unknown fields implementation in lite mode uses StringOutputStream
265 if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
266 printer->Print(
267 "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
268 }
269
kenton@google.com80b1d622009-07-29 01:13:20 +0000270 if (HasDescriptorMethods(file_)) {
271 printer->Print(
272 "#include <google/protobuf/descriptor.h>\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000273 "#include <google/protobuf/generated_message_reflection.h>\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000274 "#include <google/protobuf/reflection_ops.h>\n"
275 "#include <google/protobuf/wire_format.h>\n");
276 }
277
Feng Xiaoeee38b02015-08-22 18:25:48 -0700278 if (options_.proto_h) {
279 // Use the smaller .proto.h files.
280 for (int i = 0; i < file_->dependency_count(); i++) {
281 const FileDescriptor* dep = file_->dependency(i);
282 const char* extension = ".proto.h";
283 string dependency = StripProto(dep->name()) + extension;
284 printer->Print(
285 "#include \"$dependency$\"\n",
286 "dependency", dependency);
287 }
288 }
289
kenton@google.comfccb1462009-12-18 02:11:36 +0000290 printer->Print(
291 "// @@protoc_insertion_point(includes)\n");
292
temporal40ee5512008-07-10 02:12:20 +0000293 GenerateNamespaceOpeners(printer);
294
kenton@google.com80b1d622009-07-29 01:13:20 +0000295 if (HasDescriptorMethods(file_)) {
temporal40ee5512008-07-10 02:12:20 +0000296 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000297 "\n"
298 "namespace {\n"
299 "\n");
300 for (int i = 0; i < file_->message_type_count(); i++) {
301 message_generators_[i]->GenerateDescriptorDeclarations(printer);
302 }
303 for (int i = 0; i < file_->enum_type_count(); i++) {
304 printer->Print(
305 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
306 "name", ClassName(file_->enum_type(i), false));
307 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000308
309 if (HasGenericServices(file_)) {
310 for (int i = 0; i < file_->service_count(); i++) {
311 printer->Print(
312 "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
313 "name", file_->service(i)->name());
314 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000315 }
316
temporal40ee5512008-07-10 02:12:20 +0000317 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000318 "\n"
319 "} // namespace\n"
320 "\n");
temporal40ee5512008-07-10 02:12:20 +0000321 }
322
kenton@google.com80b1d622009-07-29 01:13:20 +0000323 // Define our externally-visible BuildDescriptors() function. (For the lite
324 // library, all this does is initialize default instances.)
temporal40ee5512008-07-10 02:12:20 +0000325 GenerateBuildDescriptors(printer);
326
327 // Generate enums.
328 for (int i = 0; i < file_->enum_type_count(); i++) {
329 enum_generators_[i]->GenerateMethods(printer);
330 }
331
332 // Generate classes.
333 for (int i = 0; i < file_->message_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -0800334 if (i == 0 && HasGeneratedMethods(file_)) {
335 printer->Print(
336 "\n"
337 "namespace {\n"
338 "\n"
339 "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
340 "static void MergeFromFail(int line) {\n"
341 " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
342 "}\n"
343 "\n"
344 "} // namespace\n"
345 "\n");
346 }
temporal40ee5512008-07-10 02:12:20 +0000347 printer->Print("\n");
348 printer->Print(kThickSeparator);
349 printer->Print("\n");
350 message_generators_[i]->GenerateClassMethods(printer);
Jisi Liu885b6122015-02-28 14:51:22 -0800351
352 printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
353 // Generate class inline methods.
354 message_generators_[i]->GenerateInlineMethods(printer,
355 /* is_inline = */ false);
356 printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
temporal40ee5512008-07-10 02:12:20 +0000357 }
358
kenton@google.comfccb1462009-12-18 02:11:36 +0000359 if (HasGenericServices(file_)) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000360 // Generate services.
361 for (int i = 0; i < file_->service_count(); i++) {
362 if (i == 0) printer->Print("\n");
363 printer->Print(kThickSeparator);
364 printer->Print("\n");
365 service_generators_[i]->GenerateImplementation(printer);
366 }
temporal40ee5512008-07-10 02:12:20 +0000367 }
368
369 // Define extensions.
370 for (int i = 0; i < file_->extension_count(); i++) {
371 extension_generators_[i]->GenerateDefinition(printer);
372 }
373
kenton@google.comfccb1462009-12-18 02:11:36 +0000374 printer->Print(
375 "\n"
376 "// @@protoc_insertion_point(namespace_scope)\n");
377
temporal40ee5512008-07-10 02:12:20 +0000378 GenerateNamespaceClosers(printer);
kenton@google.comfccb1462009-12-18 02:11:36 +0000379
380 printer->Print(
381 "\n"
382 "// @@protoc_insertion_point(global_scope)\n");
temporal40ee5512008-07-10 02:12:20 +0000383}
384
Feng Xiaoeee38b02015-08-22 18:25:48 -0700385class FileGenerator::ForwardDeclarations {
386 public:
387 ~ForwardDeclarations() {
388 for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
389 end = namespaces_.end();
390 it != end; ++it) {
391 delete it->second;
392 }
393 namespaces_.clear();
394 }
395
396 ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
397 ForwardDeclarations*& ns = namespaces_[ns_name];
398 if (ns == NULL) {
399 ns = new ForwardDeclarations;
400 }
401 return ns;
402 }
403
404 set<string>& classes() { return classes_; }
405 set<string>& enums() { return enums_; }
406
407 void Print(io::Printer* printer) const {
408 for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
409 it != end; ++it) {
410 printer->Print("enum $enumname$ : int;\n"
411 "bool $enumname$_IsValid(int value);\n",
412 "enumname", it->c_str());
413 }
414 for (set<string>::const_iterator it = classes_.begin(),
415 end = classes_.end();
416 it != end; ++it) {
417 printer->Print("class $classname$;\n", "classname", it->c_str());
418 }
419 for (map<string, ForwardDeclarations *>::const_iterator
420 it = namespaces_.begin(),
421 end = namespaces_.end();
422 it != end; ++it) {
423 printer->Print("namespace $nsname$ {\n",
424 "nsname", it->first);
425 it->second->Print(printer);
426 printer->Print("} // namespace $nsname$\n",
427 "nsname", it->first);
428 }
429 }
430
431
432 private:
433 map<string, ForwardDeclarations*> namespaces_;
434 set<string> classes_;
435 set<string> enums_;
436};
437
temporal40ee5512008-07-10 02:12:20 +0000438void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000439 // AddDescriptors() is a file-level procedure which adds the encoded
pliard@google.com6103d4e2012-05-04 11:16:09 +0000440 // FileDescriptorProto for this .proto file to the global DescriptorPool for
441 // generated files (DescriptorPool::generated_pool()). It either runs at
442 // static initialization time (by default) or when default_instance() is
443 // called for the first time (in LITE_RUNTIME mode with
444 // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
445 // constructs default instances and registers extensions.
temporal779f61c2008-08-13 03:15:00 +0000446 //
kenton@google.comd37d46d2009-04-25 02:53:47 +0000447 // Its sibling, AssignDescriptors(), actually pulls the compiled
448 // FileDescriptor from the DescriptorPool and uses it to populate all of
449 // the global variables which store pointers to the descriptor objects.
450 // It also constructs the reflection objects. It is called the first time
451 // anyone calls descriptor() or GetReflection() on one of the types defined
452 // in the file.
kenton@google.com24bf56f2008-09-24 20:31:01 +0000453
kenton@google.com80b1d622009-07-29 01:13:20 +0000454 // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
455 // and we only use AddDescriptors() to allocate default instances.
456 if (HasDescriptorMethods(file_)) {
457 printer->Print(
458 "\n"
459 "void $assigndescriptorsname$() {\n",
460 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
461 printer->Indent();
kenton@google.comd37d46d2009-04-25 02:53:47 +0000462
kenton@google.com80b1d622009-07-29 01:13:20 +0000463 // Make sure the file has found its way into the pool. If a descriptor
464 // is requested *during* static init then AddDescriptors() may not have
465 // been called yet, so we call it manually. Note that it's fine if
466 // AddDescriptors() is called multiple times.
467 printer->Print(
468 "$adddescriptorsname$();\n",
469 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000470
kenton@google.com80b1d622009-07-29 01:13:20 +0000471 // Get the file's descriptor from the pool.
472 printer->Print(
473 "const ::google::protobuf::FileDescriptor* file =\n"
474 " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
475 " \"$filename$\");\n"
476 // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
477 // being unused when compiling an empty .proto file.
478 "GOOGLE_CHECK(file != NULL);\n",
479 "filename", file_->name());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000480
kenton@google.com80b1d622009-07-29 01:13:20 +0000481 // Go through all the stuff defined in this file and generated code to
482 // assign the global descriptor pointers based on the file descriptor.
483 for (int i = 0; i < file_->message_type_count(); i++) {
484 message_generators_[i]->GenerateDescriptorInitializer(printer, i);
485 }
486 for (int i = 0; i < file_->enum_type_count(); i++) {
487 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
488 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000489 if (HasGenericServices(file_)) {
490 for (int i = 0; i < file_->service_count(); i++) {
491 service_generators_[i]->GenerateDescriptorInitializer(printer, i);
492 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000493 }
494
495 printer->Outdent();
496 printer->Print(
497 "}\n"
498 "\n");
499
500 // ---------------------------------------------------------------
501
502 // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
503 // AssignDescriptors(). All later times, waits for the first call to
504 // complete and then returns.
505 printer->Print(
506 "namespace {\n"
507 "\n"
508 "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
509 "inline void protobuf_AssignDescriptorsOnce() {\n"
510 " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
511 " &$assigndescriptorsname$);\n"
512 "}\n"
513 "\n",
514 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
515
516 // protobuf_RegisterTypes(): Calls
517 // MessageFactory::InternalRegisterGeneratedType() for each message type.
518 printer->Print(
519 "void protobuf_RegisterTypes(const ::std::string&) {\n"
520 " protobuf_AssignDescriptorsOnce();\n");
521 printer->Indent();
522
523 for (int i = 0; i < file_->message_type_count(); i++) {
524 message_generators_[i]->GenerateTypeRegistrations(printer);
525 }
526
527 printer->Outdent();
528 printer->Print(
529 "}\n"
530 "\n"
531 "} // namespace\n");
kenton@google.com24bf56f2008-09-24 20:31:01 +0000532 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000533
kenton@google.comd37d46d2009-04-25 02:53:47 +0000534 // -----------------------------------------------------------------
535
kenton@google.com63e646b2009-05-06 19:27:03 +0000536 // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
537 printer->Print(
538 "\n"
539 "void $shutdownfilename$() {\n",
540 "shutdownfilename", GlobalShutdownFileName(file_->name()));
541 printer->Indent();
542
543 for (int i = 0; i < file_->message_type_count(); i++) {
544 message_generators_[i]->GenerateShutdownCode(printer);
545 }
546
547 printer->Outdent();
548 printer->Print(
pliard@google.com6103d4e2012-05-04 11:16:09 +0000549 "}\n\n");
kenton@google.com63e646b2009-05-06 19:27:03 +0000550
551 // -----------------------------------------------------------------
552
kenton@google.comd37d46d2009-04-25 02:53:47 +0000553 // Now generate the AddDescriptors() function.
pliard@google.com6103d4e2012-05-04 11:16:09 +0000554 PrintHandlingOptionalStaticInitializers(
555 file_, printer,
556 // With static initializers.
557 // Note that we don't need any special synchronization in the following code
558 // because it is called at static init time before any threads exist.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000559 "void $adddescriptorsname$() {\n"
temporal40ee5512008-07-10 02:12:20 +0000560 " static bool already_here = false;\n"
561 " if (already_here) return;\n"
562 " already_here = true;\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000563 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
564 "\n",
pliard@google.com6103d4e2012-05-04 11:16:09 +0000565 // Without.
566 "void $adddescriptorsname$_impl() {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000567 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
568 "\n",
pliard@google.com6103d4e2012-05-04 11:16:09 +0000569 // Vars.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000570 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
pliard@google.com6103d4e2012-05-04 11:16:09 +0000571
temporal40ee5512008-07-10 02:12:20 +0000572 printer->Indent();
573
kenton@google.comd37d46d2009-04-25 02:53:47 +0000574 // Call the AddDescriptors() methods for all of our dependencies, to make
575 // sure they get added first.
temporal40ee5512008-07-10 02:12:20 +0000576 for (int i = 0; i < file_->dependency_count(); i++) {
577 const FileDescriptor* dependency = file_->dependency(i);
578 // Print the namespace prefix for the dependency.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000579 string add_desc_name = QualifiedFileLevelSymbol(
580 dependency->package(), GlobalAddDescriptorsName(dependency->name()));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000581 // Call its AddDescriptors function.
temporal40ee5512008-07-10 02:12:20 +0000582 printer->Print(
583 "$name$();\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000584 "name", add_desc_name);
temporal40ee5512008-07-10 02:12:20 +0000585 }
586
kenton@google.com80b1d622009-07-29 01:13:20 +0000587 if (HasDescriptorMethods(file_)) {
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);
temporal40ee5512008-07-10 02:12:20 +0000595
Feng Xiaoeee38b02015-08-22 18:25:48 -0700596#ifdef _MSC_VER
597 bool breakdown_large_file = true;
598#else
599 bool breakdown_large_file = false;
600#endif
Qartar2fe6d7b2015-06-07 14:22:51 -0700601 // 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.
Feng Xiaoeee38b02015-08-22 18:25:48 -0700604 if (breakdown_large_file && file_data.size() > 65535) {
Brian Silverman21f3d372015-09-08 18:57:04 -0400605 // 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.
Qartar2fe6d7b2015-06-07 14:22:51 -0700610 printer->Print(
Brian Silverman21f3d372015-09-08 18:57:04 -0400611 "static const signed char descriptor[] = {\n");
Qartar2fe6d7b2015-06-07 14:22:51 -0700612 printer->Indent();
temporal40ee5512008-07-10 02:12:20 +0000613
Qartar2fe6d7b2015-06-07 14:22:51 -0700614 // 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(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700619 "$char$, ",
620 "char", SimpleItoa(file_data[i]));
Qartar2fe6d7b2015-06-07 14:22:51 -0700621 }
622 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700623 "\n");
Qartar2fe6d7b2015-06-07 14:22:51 -0700624 }
625
626 printer->Outdent();
627 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700628 "};\n");
Qartar2fe6d7b2015-06-07 14:22:51 -0700629
630 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700631 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
632 "size", SimpleItoa(file_data.size()));
Qartar2fe6d7b2015-06-07 14:22:51 -0700633
634 } else {
Qartar2fe6d7b2015-06-07 14:22:51 -0700635 printer->Print(
636 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
Feng Xiaoeee38b02015-08-22 18:25:48 -0700637
Qartar2fe6d7b2015-06-07 14:22:51 -0700638 // 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))));
Feng Xiaoeee38b02015-08-22 18:25:48 -0700645 }
646 printer->Print(
647 ", $size$);\n",
Qartar2fe6d7b2015-06-07 14:22:51 -0700648 "size", SimpleItoa(file_data.size()));
kenton@google.com80b1d622009-07-29 01:13:20 +0000649 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000650
651 // Call MessageFactory::InternalRegisterGeneratedFile().
652 printer->Print(
653 "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
654 " \"$filename$\", &protobuf_RegisterTypes);\n",
655 "filename", file_->name());
temporal40ee5512008-07-10 02:12:20 +0000656 }
kenton@google.comd37d46d2009-04-25 02:53:47 +0000657
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 }
temporal40ee5512008-07-10 02:12:20 +0000670
kenton@google.com63e646b2009-05-06 19:27:03 +0000671 printer->Print(
672 "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
673 "shutdownfilename", GlobalShutdownFileName(file_->name()));
674
temporal40ee5512008-07-10 02:12:20 +0000675 printer->Outdent();
temporal40ee5512008-07-10 02:12:20 +0000676 printer->Print(
677 "}\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000678 "\n");
679
680 PrintHandlingOptionalStaticInitializers(
681 file_, printer,
682 // With static initializers.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000683 "// Force AddDescriptors() to be called at static initialization time.\n"
temporal40ee5512008-07-10 02:12:20 +0000684 "struct StaticDescriptorInitializer_$filename$ {\n"
685 " StaticDescriptorInitializer_$filename$() {\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000686 " $adddescriptorsname$();\n"
temporal40ee5512008-07-10 02:12:20 +0000687 " }\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000688 "} static_descriptor_initializer_$filename$_;\n",
689 // Without.
pliard@google.coma269a2c2012-05-10 08:04:04 +0000690 "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000691 "void $adddescriptorsname$() {\n"
xiaofeng@google.comd8331262013-07-30 18:35:45 +0000692 " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000693 " &$adddescriptorsname$_impl);\n"
694 "}\n",
695 // Vars.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000696 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
temporal40ee5512008-07-10 02:12:20 +0000697 "filename", FilenameIdentifier(file_->name()));
698}
699
700void 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
709void 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
Feng Xiaoeee38b02015-08-22 18:25:48 -0700718void 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
728void 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
750void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
751 const string& filename_identifier) {
Bo Yang5db21732015-05-21 14:28:59 -0700752 // 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 "\n",
762 "filename", file_->name(),
763 "filename_identifier", filename_identifier);
764}
765
Feng Xiaoeee38b02015-08-22 18:25:48 -0700766void FileGenerator::GenerateBottomHeaderGuard(
767 io::Printer* printer, const string& filename_identifier) {
Bo Yang5db21732015-05-21 14:28:59 -0700768 printer->Print(
769 "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
770 "filename_identifier", filename_identifier);
771}
772
773void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
774
775 printer->Print(
776 "#include <google/protobuf/stubs/common.h>\n"
777 "\n");
778
779 // Verify the protobuf library header version is compatible with the protoc
780 // version before going any further.
781 printer->Print(
782 "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
783 "#error This file was generated by a newer version of protoc which is\n"
784 "#error incompatible with your Protocol Buffer headers. Please update\n"
785 "#error your headers.\n"
786 "#endif\n"
787 "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
788 "#error This file was generated by an older version of protoc which is\n"
789 "#error incompatible with your Protocol Buffer headers. Please\n"
790 "#error regenerate this file with a newer version of protoc.\n"
791 "#endif\n"
792 "\n",
793 "min_header_version",
794 SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
795 "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
796
797 // OK, it's now safe to #include other files.
798 printer->Print(
799 "#include <google/protobuf/arena.h>\n"
800 "#include <google/protobuf/arenastring.h>\n"
801 "#include <google/protobuf/generated_message_util.h>\n");
802 if (UseUnknownFieldSet(file_)) {
803 printer->Print(
804 "#include <google/protobuf/metadata.h>\n");
805 }
806 if (file_->message_type_count() > 0) {
807 if (HasDescriptorMethods(file_)) {
808 printer->Print(
809 "#include <google/protobuf/message.h>\n");
810 } else {
811 printer->Print(
812 "#include <google/protobuf/message_lite.h>\n");
813 }
814 }
815 printer->Print(
816 "#include <google/protobuf/repeated_field.h>\n"
817 "#include <google/protobuf/extension_set.h>\n");
818 if (HasMapFields(file_)) {
819 printer->Print(
820 "#include <google/protobuf/map.h>\n");
821 if (HasDescriptorMethods(file_)) {
822 printer->Print(
823 "#include <google/protobuf/map_field_inl.h>\n");
824 } else {
825 printer->Print(
826 "#include <google/protobuf/map_field_lite.h>\n");
827 }
828 }
829
830 if (HasEnumDefinitions(file_)) {
831 if (HasDescriptorMethods(file_)) {
832 printer->Print(
833 "#include <google/protobuf/generated_enum_reflection.h>\n");
834 } else {
835 printer->Print(
836 "#include <google/protobuf/generated_enum_util.h>\n");
837 }
838 }
839
840 if (HasGenericServices(file_)) {
841 printer->Print(
842 "#include <google/protobuf/service.h>\n");
843 }
844
845 if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
846 printer->Print(
847 "#include <google/protobuf/unknown_field_set.h>\n");
848 }
849
850
851 if (IsAnyMessage(file_)) {
852 printer->Print(
Matthew Wu187cfc52015-10-22 16:09:56 -0700853 "#include <google/protobuf/any.h>\n");
Bo Yang5db21732015-05-21 14:28:59 -0700854 }
855}
856
857void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
858 set<string> public_import_names;
859 for (int i = 0; i < file_->public_dependency_count(); i++) {
860 public_import_names.insert(file_->public_dependency(i)->name());
861 }
862
863 for (int i = 0; i < file_->dependency_count(); i++) {
Bo Yang1f0286a2015-12-04 13:18:44 -0800864 bool well_known = IsWellKnownMessage(file_->dependency(i));
Bo Yang5db21732015-05-21 14:28:59 -0700865 const string& name = file_->dependency(i)->name();
866 bool public_import = (public_import_names.count(name) != 0);
867
Bo Yang5db21732015-05-21 14:28:59 -0700868 printer->Print(
Bo Yang1f0286a2015-12-04 13:18:44 -0800869 "#include $left$$dependency$.pb.h$right$$iwyu$\n",
Bo Yang5db21732015-05-21 14:28:59 -0700870 "dependency", StripProto(name),
Bo Yang1f0286a2015-12-04 13:18:44 -0800871 "iwyu", (public_import) ? " // IWYU pragma: export" : "",
872 "left", well_known ? "<" : "\"",
873 "right", well_known ? ">" : "\"");
Bo Yang5db21732015-05-21 14:28:59 -0700874 }
875}
876
877void FileGenerator::GenerateGlobalStateFunctionDeclarations(
878 io::Printer* printer) {
879 // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
880 // functions, so that we can declare them to be friends of each class.
881 printer->Print(
882 "\n"
883 "// Internal implementation detail -- do not call these.\n"
884 "void $dllexport_decl$$adddescriptorsname$();\n",
885 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
886 "dllexport_decl",
887 options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
888
889 printer->Print(
890 // Note that we don't put dllexport_decl on these because they are only
891 // called by the .pb.cc file in which they are defined.
892 "void $assigndescriptorsname$();\n"
893 "void $shutdownfilename$();\n"
894 "\n",
895 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
896 "shutdownfilename", GlobalShutdownFileName(file_->name()));
897}
898
899void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700900 set<string> classes;
Bo Yang5db21732015-05-21 14:28:59 -0700901 for (int i = 0; i < file_->message_type_count(); i++) {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700902 message_generators_[i]->FillMessageForwardDeclarations(&classes);
903 }
904 for (set<string>::const_iterator it = classes.begin(), end = classes.end();
905 it != end; ++it) {
906 printer->Print("class $classname$;\n", "classname", it->c_str());
Bo Yang5db21732015-05-21 14:28:59 -0700907 }
908}
909
910void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
911 // Generate class definitions.
912 for (int i = 0; i < file_->message_type_count(); i++) {
913 if (i > 0) {
914 printer->Print("\n");
915 printer->Print(kThinSeparator);
916 printer->Print("\n");
917 }
918 message_generators_[i]->GenerateClassDefinition(printer);
919 }
920}
921
922void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
923 // Generate enum definitions.
924 for (int i = 0; i < file_->message_type_count(); i++) {
925 message_generators_[i]->GenerateEnumDefinitions(printer);
926 }
927 for (int i = 0; i < file_->enum_type_count(); i++) {
928 enum_generators_[i]->GenerateDefinition(printer);
929 }
930}
931
932void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
933 if (HasGenericServices(file_)) {
934 // Generate service definitions.
935 for (int i = 0; i < file_->service_count(); i++) {
936 if (i > 0) {
937 printer->Print("\n");
938 printer->Print(kThinSeparator);
939 printer->Print("\n");
940 }
941 service_generators_[i]->GenerateDeclarations(printer);
942 }
943
944 printer->Print("\n");
945 printer->Print(kThickSeparator);
946 printer->Print("\n");
947 }
948}
949
950void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
951 // Declare extension identifiers.
952 for (int i = 0; i < file_->extension_count(); i++) {
953 extension_generators_[i]->GenerateDeclaration(printer);
954 }
955}
956
957void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
958 // An aside about inline functions in .proto.h mode:
959 //
960 // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
961 // moving much of the inline functions to the .pb.cc file, which can be a
962 // significant performance benefit for compilation time, at the expense
963 // of non-inline function calls.
964 //
965 // However, in .proto.h mode, the definition of the internal dependent
966 // base class must remain in the header, and can never be out-lined. The
967 // dependent base class also needs access to has-bit manipuation
968 // functions, so the has-bit functions must be unconditionally inlined in
969 // proto_h mode.
970 //
971 // This gives us three flavors of functions:
972 //
973 // 1. Functions on the message not used by the internal dependent base
974 // class: in .proto.h mode, only some functions are defined on the
975 // message class; others are defined on the dependent base class.
976 // These are guarded and can be out-lined. These are generated by
977 // GenerateInlineMethods, and include has_* bit functions in
978 // non-proto_h mode.
979 //
980 // 2. Functions on the internal dependent base class: these functions
981 // are dependent on a template parameter, so they always need to
982 // remain in the header.
983 //
984 // 3. Functions on the message that are used by the dependent base: the
985 // dependent base class down casts itself to the message
986 // implementation class to access these functions (the has_* bit
987 // manipulation functions). Unlike #1, these functions must
988 // unconditionally remain in the header. These are emitted by
989 // GenerateDependentInlineMethods, even though they are not actually
990 // dependent.
991
992 printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
993 // Generate class inline methods.
994 for (int i = 0; i < file_->message_type_count(); i++) {
995 if (i > 0) {
996 printer->Print(kThinSeparator);
997 printer->Print("\n");
998 }
999 message_generators_[i]->GenerateInlineMethods(printer,
1000 /* is_inline = */ true);
1001 }
1002 printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1003
1004 for (int i = 0; i < file_->message_type_count(); i++) {
1005 if (i > 0) {
1006 printer->Print(kThinSeparator);
1007 printer->Print("\n");
1008 }
1009 // Methods of the dependent base class must always be inline in the header.
1010 message_generators_[i]->GenerateDependentInlineMethods(printer);
1011 }
Bo Yang5db21732015-05-21 14:28:59 -07001012}
1013
1014void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
1015 io::Printer* printer) {
1016 // Emit GetEnumDescriptor specializations into google::protobuf namespace:
1017 if (HasEnumDefinitions(file_)) {
1018 // The SWIG conditional is to avoid a null-pointer dereference
1019 // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
1020 // namespace X { void Y<Z::W>(); }
1021 // which appears in GetEnumDescriptor() specializations.
1022 printer->Print(
1023 "\n"
1024 "#ifndef SWIG\n"
1025 "namespace google {\nnamespace protobuf {\n"
1026 "\n");
1027 for (int i = 0; i < file_->message_type_count(); i++) {
1028 message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1029 }
1030 for (int i = 0; i < file_->enum_type_count(); i++) {
1031 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1032 }
1033 printer->Print(
1034 "\n"
1035 "} // namespace protobuf\n} // namespace google\n"
1036 "#endif // SWIG\n");
1037 }
1038}
1039
temporal40ee5512008-07-10 02:12:20 +00001040} // namespace cpp
1041} // namespace compiler
1042} // namespace protobuf
1043} // namespace google