Index: third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc |
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc |
index 4eb89f432064f78065b4bbaf07ca960e1c74cf41..b86f080294c5dd7461d6adb4dc5a13bcdd9bd1d9 100644 |
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc |
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc |
@@ -1,6 +1,6 @@ |
// Protocol Buffers - Google's data interchange format |
// Copyright 2008 Google Inc. All rights reserved. |
-// http://code.google.com/p/protobuf/ |
+// https://developers.google.com/protocol-buffers/ |
// |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
@@ -33,6 +33,13 @@ |
// Sanjay Ghemawat, Jeff Dean, and others. |
#include <google/protobuf/compiler/cpp/cpp_file.h> |
+#include <map> |
+#include <memory> |
+#ifndef _SHARED_PTR_H |
+#include <google/protobuf/stubs/shared_ptr.h> |
+#endif |
+#include <set> |
+ |
#include <google/protobuf/compiler/cpp/cpp_enum.h> |
#include <google/protobuf/compiler/cpp/cpp_service.h> |
#include <google/protobuf/compiler/cpp/cpp_extension.h> |
@@ -50,18 +57,17 @@ namespace cpp { |
// =================================================================== |
-FileGenerator::FileGenerator(const FileDescriptor* file, |
- const Options& options) |
- : file_(file), |
- message_generators_( |
- new scoped_ptr<MessageGenerator>[file->message_type_count()]), |
- enum_generators_( |
- new scoped_ptr<EnumGenerator>[file->enum_type_count()]), |
- service_generators_( |
- new scoped_ptr<ServiceGenerator>[file->service_count()]), |
- extension_generators_( |
- new scoped_ptr<ExtensionGenerator>[file->extension_count()]), |
- options_(options) { |
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) |
+ : file_(file), |
+ message_generators_( |
+ new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]), |
+ enum_generators_( |
+ new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]), |
+ service_generators_( |
+ new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]), |
+ extension_generators_( |
+ new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]), |
+ options_(options) { |
for (int i = 0; i < file->message_type_count(); i++) { |
message_generators_[i].reset( |
@@ -88,178 +94,126 @@ FileGenerator::FileGenerator(const FileDescriptor* file, |
FileGenerator::~FileGenerator() {} |
-void FileGenerator::GenerateHeader(io::Printer* printer) { |
+void FileGenerator::GenerateProtoHeader(io::Printer* printer) { |
+ if (!options_.proto_h) { |
+ return; |
+ } |
+ |
string filename_identifier = FilenameIdentifier(file_->name()); |
+ GenerateTopHeaderGuard(printer, filename_identifier); |
- // Generate top of header. |
- printer->Print( |
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
- "// source: $filename$\n" |
- "\n" |
- "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n" |
- "#define PROTOBUF_$filename_identifier$__INCLUDED\n" |
- "\n" |
- "#include <string>\n" |
- "\n", |
- "filename", file_->name(), |
- "filename_identifier", filename_identifier); |
+ GenerateLibraryIncludes(printer); |
- printer->Print( |
- "#include <google/protobuf/stubs/common.h>\n" |
- "\n"); |
+ for (int i = 0; i < file_->public_dependency_count(); i++) { |
+ const FileDescriptor* dep = file_->public_dependency(i); |
+ const char* extension = ".proto.h"; |
+ string dependency = StripProto(dep->name()) + extension; |
+ printer->Print( |
+ "#include \"$dependency$\" // IWYU pragma: export\n", |
+ "dependency", dependency); |
+ } |
- // Verify the protobuf library header version is compatible with the protoc |
- // version before going any further. |
printer->Print( |
- "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" |
- "#error This file was generated by a newer version of protoc which is\n" |
- "#error incompatible with your Protocol Buffer headers. Please update\n" |
- "#error your headers.\n" |
- "#endif\n" |
- "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" |
- "#error This file was generated by an older version of protoc which is\n" |
- "#error incompatible with your Protocol Buffer headers. Please\n" |
- "#error regenerate this file with a newer version of protoc.\n" |
- "#endif\n" |
- "\n", |
- "min_header_version", |
- SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), |
- "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); |
+ "// @@protoc_insertion_point(includes)\n"); |
- // OK, it's now safe to #include other files. |
- printer->Print( |
- "#include <google/protobuf/generated_message_util.h>\n"); |
- if (file_->message_type_count() > 0) { |
- if (HasDescriptorMethods(file_)) { |
- printer->Print( |
- "#include <google/protobuf/message.h>\n"); |
- } else { |
- printer->Print( |
- "#include <google/protobuf/message_lite.h>\n"); |
- } |
- } |
- printer->Print( |
- "#include <google/protobuf/repeated_field.h>\n" |
- "#include <google/protobuf/extension_set.h>\n"); |
- if (HasUnknownFields(file_)) { |
- printer->Print( |
- "#include <google/protobuf/unknown_field_set.h>\n"); |
- } |
+ GenerateForwardDeclarations(printer); |
- if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) { |
- printer->Print( |
- "#include <google/protobuf/generated_enum_reflection.h>\n"); |
- } |
+ // Open namespace. |
+ GenerateNamespaceOpeners(printer); |
- if (HasGenericServices(file_)) { |
- printer->Print( |
- "#include <google/protobuf/service.h>\n"); |
- } |
+ GenerateGlobalStateFunctionDeclarations(printer); |
- if (HasUnknownFields(file_) && file_->message_type_count() > 0) { |
- printer->Print( |
- "#include <google/protobuf/unknown_field_set.h>\n"); |
- } |
+ printer->Print("\n"); |
+ GenerateEnumDefinitions(printer); |
- for (int i = 0; i < file_->dependency_count(); i++) { |
- printer->Print( |
- "#include \"$dependency$.pb.h\"\n", |
- "dependency", StripProto(file_->dependency(i)->name())); |
- } |
+ printer->Print(kThickSeparator); |
+ printer->Print("\n"); |
+ GenerateMessageDefinitions(printer); |
- printer->Print( |
- "// @@protoc_insertion_point(includes)\n"); |
+ printer->Print("\n"); |
+ printer->Print(kThickSeparator); |
+ printer->Print("\n"); |
+ GenerateServiceDefinitions(printer); |
- // Open namespace. |
- GenerateNamespaceOpeners(printer); |
+ GenerateExtensionIdentifiers(printer); |
+ |
+ printer->Print("\n"); |
+ printer->Print(kThickSeparator); |
+ printer->Print("\n"); |
+ |
+ GenerateInlineFunctionDefinitions(printer); |
- // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile |
- // functions, so that we can declare them to be friends of each class. |
printer->Print( |
"\n" |
- "// Internal implementation detail -- do not call these.\n" |
- "void $dllexport_decl$ $adddescriptorsname$();\n", |
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), |
- "dllexport_decl", options_.dllexport_decl); |
+ "// @@protoc_insertion_point(namespace_scope)\n" |
+ "\n"); |
+ |
+ // Close up namespace. |
+ GenerateNamespaceClosers(printer); |
+ |
+ // We need to specialize some templates in the ::google::protobuf namespace: |
+ GenerateProto2NamespaceEnumSpecializations(printer); |
printer->Print( |
- // Note that we don't put dllexport_decl on these because they are only |
- // called by the .pb.cc file in which they are defined. |
- "void $assigndescriptorsname$();\n" |
- "void $shutdownfilename$();\n" |
- "\n", |
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()), |
- "shutdownfilename", GlobalShutdownFileName(file_->name())); |
+ "\n" |
+ "// @@protoc_insertion_point(global_scope)\n" |
+ "\n"); |
- // Generate forward declarations of classes. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateForwardDeclaration(printer); |
- } |
+ GenerateBottomHeaderGuard(printer, filename_identifier); |
+} |
- printer->Print("\n"); |
+void FileGenerator::GeneratePBHeader(io::Printer* printer) { |
+ string filename_identifier = |
+ FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : "")); |
+ GenerateTopHeaderGuard(printer, filename_identifier); |
- // Generate enum definitions. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateEnumDefinitions(printer); |
- } |
- for (int i = 0; i < file_->enum_type_count(); i++) { |
- enum_generators_[i]->GenerateDefinition(printer); |
+ if (options_.proto_h) { |
+ printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n", |
+ "basename", StripProto(file_->name())); |
+ } else { |
+ GenerateLibraryIncludes(printer); |
} |
+ GenerateDependencyIncludes(printer); |
- printer->Print(kThickSeparator); |
- printer->Print("\n"); |
+ printer->Print( |
+ "// @@protoc_insertion_point(includes)\n"); |
- // Generate class definitions. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- if (i > 0) { |
- printer->Print("\n"); |
- printer->Print(kThinSeparator); |
- printer->Print("\n"); |
- } |
- message_generators_[i]->GenerateClassDefinition(printer); |
- } |
- printer->Print("\n"); |
- printer->Print(kThickSeparator); |
- printer->Print("\n"); |
- if (HasGenericServices(file_)) { |
- // Generate service definitions. |
- for (int i = 0; i < file_->service_count(); i++) { |
- if (i > 0) { |
- printer->Print("\n"); |
- printer->Print(kThinSeparator); |
- printer->Print("\n"); |
- } |
- service_generators_[i]->GenerateDeclarations(printer); |
- } |
+ // Open namespace. |
+ GenerateNamespaceOpeners(printer); |
+ |
+ if (!options_.proto_h) { |
+ GenerateGlobalStateFunctionDeclarations(printer); |
+ GenerateMessageForwardDeclarations(printer); |
printer->Print("\n"); |
+ |
+ GenerateEnumDefinitions(printer); |
+ |
printer->Print(kThickSeparator); |
printer->Print("\n"); |
- } |
- // Declare extension identifiers. |
- for (int i = 0; i < file_->extension_count(); i++) { |
- extension_generators_[i]->GenerateDeclaration(printer); |
- } |
+ GenerateMessageDefinitions(printer); |
- printer->Print("\n"); |
- printer->Print(kThickSeparator); |
- printer->Print("\n"); |
+ printer->Print("\n"); |
+ printer->Print(kThickSeparator); |
+ printer->Print("\n"); |
- // Generate class inline methods. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- if (i > 0) { |
- printer->Print(kThinSeparator); |
- printer->Print("\n"); |
- } |
- message_generators_[i]->GenerateInlineMethods(printer); |
+ GenerateServiceDefinitions(printer); |
+ |
+ GenerateExtensionIdentifiers(printer); |
+ |
+ printer->Print("\n"); |
+ printer->Print(kThickSeparator); |
+ printer->Print("\n"); |
+ |
+ GenerateInlineFunctionDefinitions(printer); |
} |
printer->Print( |
@@ -269,27 +223,9 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { |
// Close up namespace. |
GenerateNamespaceClosers(printer); |
- // Emit GetEnumDescriptor specializations into google::protobuf namespace: |
- if (HasDescriptorMethods(file_)) { |
- // The SWIG conditional is to avoid a null-pointer dereference |
- // (bug 1984964) in swig-1.3.21 resulting from the following syntax: |
- // namespace X { void Y<Z::W>(); } |
- // which appears in GetEnumDescriptor() specializations. |
- printer->Print( |
- "\n" |
- "#ifndef SWIG\n" |
- "namespace google {\nnamespace protobuf {\n" |
- "\n"); |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
- } |
- for (int i = 0; i < file_->enum_type_count(); i++) { |
- enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
- } |
- printer->Print( |
- "\n" |
- "} // namespace google\n} // namespace protobuf\n" |
- "#endif // SWIG\n"); |
+ if (!options_.proto_h) { |
+ // We need to specialize some templates in the ::google::protobuf namespace: |
+ GenerateProto2NamespaceEnumSpecializations(printer); |
} |
printer->Print( |
@@ -297,30 +233,39 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { |
"// @@protoc_insertion_point(global_scope)\n" |
"\n"); |
- printer->Print( |
- "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", |
- "filename_identifier", filename_identifier); |
+ GenerateBottomHeaderGuard(printer, filename_identifier); |
} |
void FileGenerator::GenerateSource(io::Printer* printer) { |
+ bool well_known = IsWellKnownMessage(file_); |
+ string header = |
+ StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h"); |
printer->Print( |
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
"// source: $filename$\n" |
"\n" |
- |
// The generated code calls accessors that might be deprecated. We don't |
// want the compiler to warn in generated code. |
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" |
- "#include \"$basename$.pb.h\"\n" |
+ "#include $left$$header$$right$\n" |
"\n" |
"#include <algorithm>\n" // for swap() |
"\n" |
"#include <google/protobuf/stubs/common.h>\n" |
+ "#include <google/protobuf/stubs/port.h>\n" |
"#include <google/protobuf/stubs/once.h>\n" |
"#include <google/protobuf/io/coded_stream.h>\n" |
"#include <google/protobuf/wire_format_lite_inl.h>\n", |
"filename", file_->name(), |
- "basename", StripProto(file_->name())); |
+ "header", header, |
+ "left", well_known ? "<" : "\"", |
+ "right", well_known ? ">" : "\""); |
+ |
+ // Unknown fields implementation in lite mode uses StringOutputStream |
+ if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { |
+ printer->Print( |
+ "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n"); |
+ } |
if (HasDescriptorMethods(file_)) { |
printer->Print( |
@@ -330,6 +275,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
"#include <google/protobuf/wire_format.h>\n"); |
} |
+ if (options_.proto_h) { |
+ // Use the smaller .proto.h files. |
+ for (int i = 0; i < file_->dependency_count(); i++) { |
+ const FileDescriptor* dep = file_->dependency(i); |
+ const char* extension = ".proto.h"; |
+ string dependency = StripProto(dep->name()) + extension; |
+ printer->Print( |
+ "#include \"$dependency$\"\n", |
+ "dependency", dependency); |
+ } |
+ } |
+ |
printer->Print( |
"// @@protoc_insertion_point(includes)\n"); |
@@ -374,10 +331,29 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
// Generate classes. |
for (int i = 0; i < file_->message_type_count(); i++) { |
+ if (i == 0 && HasGeneratedMethods(file_)) { |
+ printer->Print( |
+ "\n" |
+ "namespace {\n" |
+ "\n" |
+ "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n" |
+ "GOOGLE_ATTRIBUTE_NOINLINE static void MergeFromFail(int line) {\n" |
+ " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n" |
+ "}\n" |
+ "\n" |
+ "} // namespace\n" |
+ "\n"); |
+ } |
printer->Print("\n"); |
printer->Print(kThickSeparator); |
printer->Print("\n"); |
message_generators_[i]->GenerateClassMethods(printer); |
+ |
+ printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n"); |
+ // Generate class inline methods. |
+ message_generators_[i]->GenerateInlineMethods(printer, |
+ /* is_inline = */ false); |
+ printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n"); |
} |
if (HasGenericServices(file_)) { |
@@ -406,6 +382,59 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
"// @@protoc_insertion_point(global_scope)\n"); |
} |
+class FileGenerator::ForwardDeclarations { |
+ public: |
+ ~ForwardDeclarations() { |
+ for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(), |
+ end = namespaces_.end(); |
+ it != end; ++it) { |
+ delete it->second; |
+ } |
+ namespaces_.clear(); |
+ } |
+ |
+ ForwardDeclarations* AddOrGetNamespace(const string& ns_name) { |
+ ForwardDeclarations*& ns = namespaces_[ns_name]; |
+ if (ns == NULL) { |
+ ns = new ForwardDeclarations; |
+ } |
+ return ns; |
+ } |
+ |
+ set<string>& classes() { return classes_; } |
+ set<string>& enums() { return enums_; } |
+ |
+ void Print(io::Printer* printer) const { |
+ for (set<string>::const_iterator it = enums_.begin(), end = enums_.end(); |
+ it != end; ++it) { |
+ printer->Print("enum $enumname$ : int;\n" |
+ "bool $enumname$_IsValid(int value);\n", |
+ "enumname", it->c_str()); |
+ } |
+ for (set<string>::const_iterator it = classes_.begin(), |
+ end = classes_.end(); |
+ it != end; ++it) { |
+ printer->Print("class $classname$;\n", "classname", it->c_str()); |
+ } |
+ for (map<string, ForwardDeclarations *>::const_iterator |
+ it = namespaces_.begin(), |
+ end = namespaces_.end(); |
+ it != end; ++it) { |
+ printer->Print("namespace $nsname$ {\n", |
+ "nsname", it->first); |
+ it->second->Print(printer); |
+ printer->Print("} // namespace $nsname$\n", |
+ "nsname", it->first); |
+ } |
+ } |
+ |
+ |
+ private: |
+ map<string, ForwardDeclarations*> namespaces_; |
+ set<string> classes_; |
+ set<string> enums_; |
+}; |
+ |
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
// AddDescriptors() is a file-level procedure which adds the encoded |
// FileDescriptorProto for this .proto file to the global DescriptorPool for |
@@ -547,17 +576,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
for (int i = 0; i < file_->dependency_count(); i++) { |
const FileDescriptor* dependency = file_->dependency(i); |
// Print the namespace prefix for the dependency. |
- vector<string> dependency_package_parts; |
- SplitStringUsing(dependency->package(), ".", &dependency_package_parts); |
- printer->Print("::"); |
- for (int j = 0; j < dependency_package_parts.size(); j++) { |
- printer->Print("$name$::", |
- "name", dependency_package_parts[j]); |
- } |
+ string add_desc_name = QualifiedFileLevelSymbol( |
+ dependency->package(), GlobalAddDescriptorsName(dependency->name())); |
// Call its AddDescriptors function. |
printer->Print( |
"$name$();\n", |
- "name", GlobalAddDescriptorsName(dependency->name())); |
+ "name", add_desc_name); |
} |
if (HasDescriptorMethods(file_)) { |
@@ -569,20 +593,60 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
string file_data; |
file_proto.SerializeToString(&file_data); |
- printer->Print( |
- "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); |
- |
- // Only write 40 bytes per line. |
- static const int kBytesPerLine = 40; |
- for (int i = 0; i < file_data.size(); i += kBytesPerLine) { |
- printer->Print("\n \"$data$\"", |
- "data", |
- EscapeTrigraphs( |
- CEscape(file_data.substr(i, kBytesPerLine)))); |
+#ifdef _MSC_VER |
+ bool breakdown_large_file = true; |
+#else |
+ bool breakdown_large_file = false; |
+#endif |
+ // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 |
+ // bytes in length". Declare a static array of characters rather than use a |
+ // string literal. |
+ if (breakdown_large_file && file_data.size() > 65535) { |
+ // This has to be explicitly marked as a signed char because the generated |
+ // code puts negative values in the array, and sometimes plain char is |
+ // unsigned. That implicit narrowing conversion is not allowed in C++11. |
+ // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin> |
+ // has details on why. |
+ printer->Print( |
+ "static const signed char descriptor[] = {\n"); |
+ printer->Indent(); |
+ |
+ // Only write 25 bytes per line. |
+ static const int kBytesPerLine = 25; |
+ for (int i = 0; i < file_data.size();) { |
+ for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { |
+ printer->Print( |
+ "$char$, ", |
+ "char", SimpleItoa(file_data[i])); |
+ } |
+ printer->Print( |
+ "\n"); |
+ } |
+ |
+ printer->Outdent(); |
+ printer->Print( |
+ "};\n"); |
+ |
+ printer->Print( |
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n", |
+ "size", SimpleItoa(file_data.size())); |
+ |
+ } else { |
+ printer->Print( |
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); |
+ |
+ // Only write 40 bytes per line. |
+ static const int kBytesPerLine = 40; |
+ for (int i = 0; i < file_data.size(); i += kBytesPerLine) { |
+ printer->Print("\n \"$data$\"", |
+ "data", |
+ EscapeTrigraphs( |
+ CEscape(file_data.substr(i, kBytesPerLine)))); |
} |
printer->Print( |
", $size$);\n", |
- "size", SimpleItoa(file_data.size())); |
+ "size", SimpleItoa(file_data.size())); |
+ } |
// Call MessageFactory::InternalRegisterGeneratedFile(). |
printer->Print( |
@@ -651,6 +715,328 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) { |
} |
} |
+void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { |
+ ForwardDeclarations decls; |
+ for (int i = 0; i < file_->dependency_count(); i++) { |
+ FileGenerator dependency(file_->dependency(i), options_); |
+ dependency.FillForwardDeclarations(&decls); |
+ } |
+ FillForwardDeclarations(&decls); |
+ decls.Print(printer); |
+} |
+ |
+void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { |
+ for (int i = 0; i < file_->public_dependency_count(); i++) { |
+ FileGenerator dependency(file_->public_dependency(i), options_); |
+ dependency.FillForwardDeclarations(decls); |
+ } |
+ for (int i = 0; i < package_parts_.size(); i++) { |
+ decls = decls->AddOrGetNamespace(package_parts_[i]); |
+ } |
+ // Generate enum definitions. |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ message_generators_[i]->FillEnumForwardDeclarations(&decls->enums()); |
+ } |
+ for (int i = 0; i < file_->enum_type_count(); i++) { |
+ enum_generators_[i]->FillForwardDeclaration(&decls->enums()); |
+ } |
+ // Generate forward declarations of classes. |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ message_generators_[i]->FillMessageForwardDeclarations( |
+ &decls->classes()); |
+ } |
+} |
+ |
+void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, |
+ const string& filename_identifier) { |
+ // Generate top of header. |
+ printer->Print( |
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
+ "// source: $filename$\n" |
+ "\n" |
+ "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n" |
+ "#define PROTOBUF_$filename_identifier$__INCLUDED\n" |
+ "\n" |
+ "#include <string>\n" |
+ "\n", |
+ "filename", file_->name(), |
+ "filename_identifier", filename_identifier); |
+} |
+ |
+void FileGenerator::GenerateBottomHeaderGuard( |
+ io::Printer* printer, const string& filename_identifier) { |
+ printer->Print( |
+ "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", |
+ "filename_identifier", filename_identifier); |
+} |
+ |
+void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { |
+ |
+ printer->Print( |
+ "#include <google/protobuf/stubs/common.h>\n" |
+ "\n"); |
+ |
+ // Verify the protobuf library header version is compatible with the protoc |
+ // version before going any further. |
+ printer->Print( |
+ "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" |
+ "#error This file was generated by a newer version of protoc which is\n" |
+ "#error incompatible with your Protocol Buffer headers. Please update\n" |
+ "#error your headers.\n" |
+ "#endif\n" |
+ "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" |
+ "#error This file was generated by an older version of protoc which is\n" |
+ "#error incompatible with your Protocol Buffer headers. Please\n" |
+ "#error regenerate this file with a newer version of protoc.\n" |
+ "#endif\n" |
+ "\n", |
+ "min_header_version", |
+ SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), |
+ "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); |
+ |
+ // OK, it's now safe to #include other files. |
+ printer->Print( |
+ "#include <google/protobuf/arena.h>\n" |
+ "#include <google/protobuf/arenastring.h>\n" |
+ "#include <google/protobuf/generated_message_util.h>\n"); |
+ if (UseUnknownFieldSet(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/metadata.h>\n"); |
+ } |
+ if (file_->message_type_count() > 0) { |
+ if (HasDescriptorMethods(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/message.h>\n"); |
+ } else { |
+ printer->Print( |
+ "#include <google/protobuf/message_lite.h>\n"); |
+ } |
+ } |
+ printer->Print( |
+ "#include <google/protobuf/repeated_field.h>\n" |
+ "#include <google/protobuf/extension_set.h>\n"); |
+ if (HasMapFields(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/map.h>\n"); |
+ if (HasDescriptorMethods(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/map_field_inl.h>\n"); |
+ } else { |
+ printer->Print( |
+ "#include <google/protobuf/map_field_lite.h>\n"); |
+ } |
+ } |
+ |
+ if (HasEnumDefinitions(file_)) { |
+ if (HasDescriptorMethods(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/generated_enum_reflection.h>\n"); |
+ } else { |
+ printer->Print( |
+ "#include <google/protobuf/generated_enum_util.h>\n"); |
+ } |
+ } |
+ |
+ if (HasGenericServices(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/service.h>\n"); |
+ } |
+ |
+ if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { |
+ printer->Print( |
+ "#include <google/protobuf/unknown_field_set.h>\n"); |
+ } |
+ |
+ |
+ if (IsAnyMessage(file_)) { |
+ printer->Print( |
+ "#include <google/protobuf/any.h>\n"); |
+ } |
+} |
+ |
+void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { |
+ set<string> public_import_names; |
+ for (int i = 0; i < file_->public_dependency_count(); i++) { |
+ public_import_names.insert(file_->public_dependency(i)->name()); |
+ } |
+ |
+ for (int i = 0; i < file_->dependency_count(); i++) { |
+ bool well_known = IsWellKnownMessage(file_->dependency(i)); |
+ const string& name = file_->dependency(i)->name(); |
+ bool public_import = (public_import_names.count(name) != 0); |
+ |
+ printer->Print( |
+ "#include $left$$dependency$.pb.h$right$$iwyu$\n", |
+ "dependency", StripProto(name), |
+ "iwyu", (public_import) ? " // IWYU pragma: export" : "", |
+ "left", well_known ? "<" : "\"", |
+ "right", well_known ? ">" : "\""); |
+ } |
+} |
+ |
+void FileGenerator::GenerateGlobalStateFunctionDeclarations( |
+ io::Printer* printer) { |
+ // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile |
+ // functions, so that we can declare them to be friends of each class. |
+ printer->Print( |
+ "\n" |
+ "// Internal implementation detail -- do not call these.\n" |
+ "void $dllexport_decl$$adddescriptorsname$();\n", |
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), |
+ "dllexport_decl", |
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); |
+ |
+ printer->Print( |
+ // Note that we don't put dllexport_decl on these because they are only |
+ // called by the .pb.cc file in which they are defined. |
+ "void $assigndescriptorsname$();\n" |
+ "void $shutdownfilename$();\n" |
+ "\n", |
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()), |
+ "shutdownfilename", GlobalShutdownFileName(file_->name())); |
+} |
+ |
+void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) { |
+ set<string> classes; |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ message_generators_[i]->FillMessageForwardDeclarations(&classes); |
+ } |
+ for (set<string>::const_iterator it = classes.begin(), end = classes.end(); |
+ it != end; ++it) { |
+ printer->Print("class $classname$;\n", "classname", it->c_str()); |
+ } |
+} |
+ |
+void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) { |
+ // Generate class definitions. |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ if (i > 0) { |
+ printer->Print("\n"); |
+ printer->Print(kThinSeparator); |
+ printer->Print("\n"); |
+ } |
+ message_generators_[i]->GenerateClassDefinition(printer); |
+ } |
+} |
+ |
+void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { |
+ // Generate enum definitions. |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ message_generators_[i]->GenerateEnumDefinitions(printer); |
+ } |
+ for (int i = 0; i < file_->enum_type_count(); i++) { |
+ enum_generators_[i]->GenerateDefinition(printer); |
+ } |
+} |
+ |
+void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { |
+ if (HasGenericServices(file_)) { |
+ // Generate service definitions. |
+ for (int i = 0; i < file_->service_count(); i++) { |
+ if (i > 0) { |
+ printer->Print("\n"); |
+ printer->Print(kThinSeparator); |
+ printer->Print("\n"); |
+ } |
+ service_generators_[i]->GenerateDeclarations(printer); |
+ } |
+ |
+ printer->Print("\n"); |
+ printer->Print(kThickSeparator); |
+ printer->Print("\n"); |
+ } |
+} |
+ |
+void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { |
+ // Declare extension identifiers. |
+ for (int i = 0; i < file_->extension_count(); i++) { |
+ extension_generators_[i]->GenerateDeclaration(printer); |
+ } |
+} |
+ |
+void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { |
+ // An aside about inline functions in .proto.h mode: |
+ // |
+ // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally |
+ // moving much of the inline functions to the .pb.cc file, which can be a |
+ // significant performance benefit for compilation time, at the expense |
+ // of non-inline function calls. |
+ // |
+ // However, in .proto.h mode, the definition of the internal dependent |
+ // base class must remain in the header, and can never be out-lined. The |
+ // dependent base class also needs access to has-bit manipuation |
+ // functions, so the has-bit functions must be unconditionally inlined in |
+ // proto_h mode. |
+ // |
+ // This gives us three flavors of functions: |
+ // |
+ // 1. Functions on the message not used by the internal dependent base |
+ // class: in .proto.h mode, only some functions are defined on the |
+ // message class; others are defined on the dependent base class. |
+ // These are guarded and can be out-lined. These are generated by |
+ // GenerateInlineMethods, and include has_* bit functions in |
+ // non-proto_h mode. |
+ // |
+ // 2. Functions on the internal dependent base class: these functions |
+ // are dependent on a template parameter, so they always need to |
+ // remain in the header. |
+ // |
+ // 3. Functions on the message that are used by the dependent base: the |
+ // dependent base class down casts itself to the message |
+ // implementation class to access these functions (the has_* bit |
+ // manipulation functions). Unlike #1, these functions must |
+ // unconditionally remain in the header. These are emitted by |
+ // GenerateDependentInlineMethods, even though they are not actually |
+ // dependent. |
+ |
+ printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); |
+ // Generate class inline methods. |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ if (i > 0) { |
+ printer->Print(kThinSeparator); |
+ printer->Print("\n"); |
+ } |
+ message_generators_[i]->GenerateInlineMethods(printer, |
+ /* is_inline = */ true); |
+ } |
+ printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); |
+ |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ if (i > 0) { |
+ printer->Print(kThinSeparator); |
+ printer->Print("\n"); |
+ } |
+ // Methods of the dependent base class must always be inline in the header. |
+ message_generators_[i]->GenerateDependentInlineMethods(printer); |
+ } |
+} |
+ |
+void FileGenerator::GenerateProto2NamespaceEnumSpecializations( |
+ io::Printer* printer) { |
+ // Emit GetEnumDescriptor specializations into google::protobuf namespace: |
+ if (HasEnumDefinitions(file_)) { |
+ // The SWIG conditional is to avoid a null-pointer dereference |
+ // (bug 1984964) in swig-1.3.21 resulting from the following syntax: |
+ // namespace X { void Y<Z::W>(); } |
+ // which appears in GetEnumDescriptor() specializations. |
+ printer->Print( |
+ "\n" |
+ "#ifndef SWIG\n" |
+ "namespace google {\nnamespace protobuf {\n" |
+ "\n"); |
+ for (int i = 0; i < file_->message_type_count(); i++) { |
+ message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
+ } |
+ for (int i = 0; i < file_->enum_type_count(); i++) { |
+ enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
+ } |
+ printer->Print( |
+ "\n" |
+ "} // namespace protobuf\n} // namespace google\n" |
+ "#endif // SWIG\n"); |
+ } |
+} |
+ |
} // namespace cpp |
} // namespace compiler |
} // namespace protobuf |