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 de2047673c0d052a61c878bbd410c6c1dcfdb3c4..d8fda59c3b8e147e62bcae5d7f9a327cc7ccdeb5 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 |
@@ -60,63 +60,50 @@ namespace cpp { |
FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) |
: file_(file), |
options_(options), |
- 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()]) { |
+ message_generators_owner_( |
+ new google::protobuf::scoped_ptr<MessageGenerator>[ file->message_type_count() ]), |
+ enum_generators_owner_( |
+ new google::protobuf::scoped_ptr<EnumGenerator>[ file->enum_type_count() ]), |
+ service_generators_owner_( |
+ new google::protobuf::scoped_ptr<ServiceGenerator>[ file->service_count() ]), |
+ extension_generators_owner_( |
+ new google::protobuf::scoped_ptr<ExtensionGenerator>[ file->extension_count() ]) { |
for (int i = 0; i < file->message_type_count(); i++) { |
- message_generators_[i].reset( |
- new MessageGenerator(file->message_type(i), options)); |
+ message_generators_owner_[i].reset( |
+ new MessageGenerator(file->message_type(i), options)); |
+ message_generators_owner_[i]->Flatten(&message_generators_); |
+ } |
+ |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ message_generators_[i]->AddGenerators(&enum_generators_, |
+ &extension_generators_); |
} |
for (int i = 0; i < file->enum_type_count(); i++) { |
- enum_generators_[i].reset( |
- new EnumGenerator(file->enum_type(i), options)); |
+ enum_generators_owner_[i].reset( |
+ new EnumGenerator(file->enum_type(i), options)); |
+ enum_generators_.push_back(enum_generators_owner_[i].get()); |
} |
for (int i = 0; i < file->service_count(); i++) { |
- service_generators_[i].reset( |
- new ServiceGenerator(file->service(i), options)); |
+ service_generators_owner_[i].reset( |
+ new ServiceGenerator(file->service(i), options)); |
+ service_generators_.push_back(service_generators_owner_[i].get()); |
} |
for (int i = 0; i < file->extension_count(); i++) { |
- extension_generators_[i].reset( |
- new ExtensionGenerator(file->extension(i), options)); |
+ extension_generators_owner_[i].reset( |
+ new ExtensionGenerator(file->extension(i), options)); |
+ extension_generators_.push_back(extension_generators_owner_[i].get()); |
} |
- SplitStringUsing(file_->package(), ".", &package_parts_); |
+ package_parts_ = Split(file_->package(), ".", true); |
} |
FileGenerator::~FileGenerator() {} |
-void FileGenerator::GenerateProtoHeader(io::Printer* printer, |
- const string& info_path) { |
- if (!options_.proto_h) { |
- return; |
- } |
- |
- string filename_identifier = FilenameIdentifier(file_->name()); |
- GenerateTopHeaderGuard(printer, filename_identifier); |
- |
- |
- GenerateLibraryIncludes(printer); |
- |
- 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); |
- } |
- |
- GenerateMetadataPragma(printer, info_path); |
- |
+void FileGenerator::GenerateHeader(io::Printer* printer) { |
printer->Print( |
"// @@protoc_insertion_point(includes)\n"); |
@@ -166,6 +153,32 @@ void FileGenerator::GenerateProtoHeader(io::Printer* printer, |
"\n" |
"// @@protoc_insertion_point(global_scope)\n" |
"\n"); |
+} |
+ |
+void FileGenerator::GenerateProtoHeader(io::Printer* printer, |
+ const string& info_path) { |
+ if (!options_.proto_h) { |
+ return; |
+ } |
+ |
+ string filename_identifier = FilenameIdentifier(file_->name()); |
+ GenerateTopHeaderGuard(printer, filename_identifier); |
+ |
+ |
+ GenerateLibraryIncludes(printer); |
+ |
+ 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); |
+ } |
+ |
+ GenerateMetadataPragma(printer, info_path); |
+ |
+ GenerateHeader(printer); |
GenerateBottomHeaderGuard(printer, filename_identifier); |
} |
@@ -185,59 +198,29 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer, |
GenerateDependencyIncludes(printer); |
GenerateMetadataPragma(printer, info_path); |
- printer->Print( |
- "// @@protoc_insertion_point(includes)\n"); |
- |
- |
- |
- // Open namespace. |
- GenerateNamespaceOpeners(printer); |
- |
if (!options_.proto_h) { |
- GenerateGlobalStateFunctionDeclarations(printer); |
- GenerateMessageForwardDeclarations(printer); |
- |
- printer->Print("\n"); |
- |
- GenerateEnumDefinitions(printer); |
- |
- printer->Print(kThickSeparator); |
- printer->Print("\n"); |
- |
- GenerateMessageDefinitions(printer); |
- |
- printer->Print("\n"); |
- printer->Print(kThickSeparator); |
- printer->Print("\n"); |
- |
- GenerateServiceDefinitions(printer); |
- |
- GenerateExtensionIdentifiers(printer); |
- |
- printer->Print("\n"); |
- printer->Print(kThickSeparator); |
- printer->Print("\n"); |
- |
- GenerateInlineFunctionDefinitions(printer); |
- } |
- |
- printer->Print( |
- "\n" |
- "// @@protoc_insertion_point(namespace_scope)\n"); |
+ GenerateHeader(printer); |
+ } else { |
+ // This is unfortunately necessary for some plugins. I don't see why we |
+ // need two of the same insertion points. |
+ // TODO(gerbens) remove this. |
+ printer->Print( |
+ "// @@protoc_insertion_point(includes)\n"); |
- // Close up namespace. |
- GenerateNamespaceClosers(printer); |
+ // Open namespace. |
+ GenerateNamespaceOpeners(printer); |
+ printer->Print( |
+ "\n" |
+ "// @@protoc_insertion_point(namespace_scope)\n"); |
+ // Close up namespace. |
+ GenerateNamespaceClosers(printer); |
- if (!options_.proto_h) { |
- // We need to specialize some templates in the ::google::protobuf namespace: |
- GenerateProto2NamespaceEnumSpecializations(printer); |
+ printer->Print( |
+ "\n" |
+ "// @@protoc_insertion_point(global_scope)\n" |
+ "\n"); |
} |
- printer->Print( |
- "\n" |
- "// @@protoc_insertion_point(global_scope)\n" |
- "\n"); |
- |
GenerateBottomHeaderGuard(printer, filename_identifier); |
} |
@@ -267,7 +250,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
"right", use_system_include ? ">" : "\""); |
// Unknown fields implementation in lite mode uses StringOutputStream |
- if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) { |
+ if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { |
printer->Print( |
"#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n"); |
} |
@@ -297,25 +280,48 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
GenerateNamespaceOpeners(printer); |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ if (IsMapEntryMessage(message_generators_[i]->descriptor_)) continue; |
+ printer->Print( |
+ "class $classname$DefaultTypeInternal : " |
+ "public ::google::protobuf::internal::ExplicitlyConstructed<$classname$> {};\n" |
+ "$classname$DefaultTypeInternal _$classname$_default_instance_;\n", |
+ "classname", message_generators_[i]->classname_); |
+ } |
+ |
if (HasDescriptorMethods(file_, options_)) { |
printer->Print( |
"\n" |
"namespace {\n" |
"\n"); |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateDescriptorDeclarations(printer); |
+ |
+ if (!message_generators_.empty()) { |
+ printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n", |
+ "size", SimpleItoa(message_generators_.size())); |
} |
- for (int i = 0; i < file_->enum_type_count(); i++) { |
+ if (!enum_generators_.empty()) { |
printer->Print( |
- "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", |
- "name", ClassName(file_->enum_type(i), false)); |
+ "const ::google::protobuf::EnumDescriptor* " |
+ "file_level_enum_descriptors[$size$];\n", |
+ "size", SimpleItoa(enum_generators_.size())); |
+ } |
+ if (HasGenericServices(file_, options_) && file_->service_count() > 0) { |
+ printer->Print( |
+ "const ::google::protobuf::ServiceDescriptor* " |
+ "file_level_service_descriptors[$size$];\n", |
+ "size", SimpleItoa(file_->service_count())); |
} |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ message_generators_[i]->index_in_metadata_ = i; |
+ message_generators_[i]->GenerateDescriptorDeclarations(printer); |
+ } |
+ for (int i = 0; i < enum_generators_.size(); i++) { |
+ enum_generators_[i]->index_in_metadata_ = i; |
+ } |
if (HasGenericServices(file_, options_)) { |
- for (int i = 0; i < file_->service_count(); i++) { |
- printer->Print( |
- "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", |
- "name", file_->service(i)->name()); |
+ for (int i = 0; i < service_generators_.size(); i++) { |
+ service_generators_[i]->index_in_metadata_ = i; |
} |
} |
@@ -330,25 +336,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
GenerateBuildDescriptors(printer); |
// Generate enums. |
- for (int i = 0; i < file_->enum_type_count(); i++) { |
+ for (int i = 0; i < enum_generators_.size(); i++) { |
enum_generators_[i]->GenerateMethods(printer); |
} |
// Generate classes. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- if (i == 0 && HasGeneratedMethods(file_, options_)) { |
- 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"); |
- } |
+ for (int i = 0; i < message_generators_.size(); i++) { |
printer->Print("\n"); |
printer->Print(kThickSeparator); |
printer->Print("\n"); |
@@ -363,7 +356,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
if (HasGenericServices(file_, options_)) { |
// Generate services. |
- for (int i = 0; i < file_->service_count(); i++) { |
+ for (int i = 0; i < service_generators_.size(); i++) { |
if (i == 0) printer->Print("\n"); |
printer->Print(kThickSeparator); |
printer->Print("\n"); |
@@ -372,7 +365,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
} |
// Define extensions. |
- for (int i = 0; i < file_->extension_count(); i++) { |
+ for (int i = 0; i < extension_generators_.size(); i++) { |
extension_generators_[i]->GenerateDefinition(printer); |
} |
@@ -390,8 +383,9 @@ void FileGenerator::GenerateSource(io::Printer* printer) { |
class FileGenerator::ForwardDeclarations { |
public: |
~ForwardDeclarations() { |
- for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(), |
- end = namespaces_.end(); |
+ for (std::map<string, ForwardDeclarations*>::iterator |
+ it = namespaces_.begin(), |
+ end = namespaces_.end(); |
it != end; ++it) { |
delete it->second; |
} |
@@ -406,11 +400,11 @@ class FileGenerator::ForwardDeclarations { |
return ns; |
} |
- map<string, const Descriptor*>& classes() { return classes_; } |
- map<string, const EnumDescriptor*>& enums() { return enums_; } |
+ std::map<string, const Descriptor*>& classes() { return classes_; } |
+ std::map<string, const EnumDescriptor*>& enums() { return enums_; } |
- void Print(io::Printer* printer) const { |
- for (map<string, const EnumDescriptor *>::const_iterator |
+ void Print(io::Printer* printer, const Options& options) const { |
+ for (std::map<string, const EnumDescriptor *>::const_iterator |
it = enums_.begin(), |
end = enums_.end(); |
it != end; ++it) { |
@@ -419,19 +413,30 @@ class FileGenerator::ForwardDeclarations { |
printer->Print("bool $enumname$_IsValid(int value);\n", "enumname", |
it->first); |
} |
- for (map<string, const Descriptor *>::const_iterator it = classes_.begin(), |
- end = classes_.end(); |
+ for (std::map<string, const Descriptor*>::const_iterator |
+ it = classes_.begin(), |
+ end = classes_.end(); |
it != end; ++it) { |
printer->Print("class $classname$;\n", "classname", it->first); |
printer->Annotate("classname", it->second); |
+ |
+ printer->Print( |
+ "class $classname$DefaultTypeInternal;\n" |
+ "$dllexport_decl$" |
+ "extern $classname$DefaultTypeInternal " |
+ "_$classname$_default_instance_;\n", // NOLINT |
+ "dllexport_decl", |
+ options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ", |
+ "classname", |
+ it->first); |
} |
- for (map<string, ForwardDeclarations *>::const_iterator |
+ for (std::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); |
+ it->second->Print(printer, options); |
printer->Print("} // namespace $nsname$\n", |
"nsname", it->first); |
} |
@@ -439,9 +444,9 @@ class FileGenerator::ForwardDeclarations { |
private: |
- map<string, ForwardDeclarations*> namespaces_; |
- map<string, const Descriptor*> classes_; |
- map<string, const EnumDescriptor*> enums_; |
+ std::map<string, ForwardDeclarations*> namespaces_; |
+ std::map<string, const Descriptor*> classes_; |
+ std::map<string, const EnumDescriptor*> enums_; |
}; |
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
@@ -462,74 +467,137 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
// In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors() |
// and we only use AddDescriptors() to allocate default instances. |
- if (HasDescriptorMethods(file_, options_)) { |
- printer->Print( |
- "\n" |
- "void $assigndescriptorsname$() {\n", |
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); |
- printer->Indent(); |
- // Make sure the file has found its way into the pool. If a descriptor |
- // is requested *during* static init then AddDescriptors() may not have |
- // been called yet, so we call it manually. Note that it's fine if |
- // AddDescriptors() is called multiple times. |
- printer->Print( |
- "$adddescriptorsname$();\n", |
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); |
+ if (HasDescriptorMethods(file_, options_)) { |
+ if (!message_generators_.empty()) { |
+ printer->Print( |
+ "\n" |
+ "const ::google::protobuf::uint32* $offsetfunname$() GOOGLE_ATTRIBUTE_COLD;\n" |
+ "const ::google::protobuf::uint32* $offsetfunname$() {\n", |
+ "offsetfunname", GlobalOffsetTableName(file_->name())); |
+ printer->Indent(); |
- // Get the file's descriptor from the pool. |
- printer->Print( |
- "const ::google::protobuf::FileDescriptor* file =\n" |
- " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n" |
- " \"$filename$\");\n" |
- // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file" |
- // being unused when compiling an empty .proto file. |
- "GOOGLE_CHECK(file != NULL);\n", |
- "filename", file_->name()); |
+ printer->Print("static const ::google::protobuf::uint32 offsets[] = {\n"); |
+ printer->Indent(); |
+ std::vector<std::pair<size_t, size_t> > pairs; |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ pairs.push_back(message_generators_[i]->GenerateOffsets(printer)); |
+ } |
+ printer->Outdent(); |
+ printer->Outdent(); |
+ printer->Print( |
+ " };\n" |
+ " return offsets;\n" |
+ "}\n" |
+ "\n"); |
- // Go through all the stuff defined in this file and generated code to |
- // assign the global descriptor pointers based on the file descriptor. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateDescriptorInitializer(printer, i); |
- } |
- for (int i = 0; i < file_->enum_type_count(); i++) { |
- enum_generators_[i]->GenerateDescriptorInitializer(printer, i); |
- } |
- if (HasGenericServices(file_, options_)) { |
- for (int i = 0; i < file_->service_count(); i++) { |
- service_generators_[i]->GenerateDescriptorInitializer(printer, i); |
+ printer->Print( |
+ "static const ::google::protobuf::internal::MigrationSchema schemas[] = {\n"); |
+ printer->Indent(); |
+ { |
+ int offset = 0; |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ message_generators_[i]->GenerateSchema(printer, offset, |
+ pairs[i].second); |
+ offset += pairs[i].first; |
+ } |
} |
+ printer->Outdent(); |
+ printer->Print( |
+ "};\n" |
+ "\n" |
+ "static const ::google::protobuf::internal::DefaultInstanceData " |
+ "file_default_instances[] = {\n"); |
+ printer->Indent(); |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ const Descriptor* descriptor = message_generators_[i]->descriptor_; |
+ if (IsMapEntryMessage(descriptor)) continue; |
+ |
+ string oneof_default = "NULL"; |
+ if (message_generators_[i]->descriptor_->oneof_decl_count()) { |
+ oneof_default = |
+ "&" + ClassName(descriptor, false) + "_default_oneof_instance_"; |
+ } |
+ printer->Print( |
+ "{reinterpret_cast<const " |
+ "::google::protobuf::Message*>(&_$classname$_default_instance_), " |
+ "$oneof_default$},\n", |
+ "classname", ClassName(descriptor, false), "oneof_default", |
+ oneof_default); |
+ } |
+ printer->Outdent(); |
+ printer->Print( |
+ "};\n" |
+ "\n"); |
+ } else { |
+ // we still need these symbols to exist |
+ printer->Print( |
+ "inline ::google::protobuf::uint32* $offsetfunname$() { return NULL; }\n" |
+ "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n" |
+ "static const ::google::protobuf::internal::DefaultInstanceData* " |
+ "file_default_instances = NULL;\n", |
+ "offsetfunname", |
+ GlobalOffsetTableName(file_->name())); |
} |
- printer->Outdent(); |
- printer->Print( |
- "}\n" |
- "\n"); |
- |
// --------------------------------------------------------------- |
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls |
// AssignDescriptors(). All later times, waits for the first call to |
// complete and then returns. |
+ string message_factory = "NULL"; |
printer->Print( |
- "namespace {\n" |
- "\n" |
- "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n" |
- "inline void protobuf_AssignDescriptorsOnce() {\n" |
- " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n" |
- " &$assigndescriptorsname$);\n" |
- "}\n" |
- "\n", |
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); |
- |
- // protobuf_RegisterTypes(): Calls |
- // MessageFactory::InternalRegisterGeneratedType() for each message type. |
+ "namespace {\n" |
+ "\n" |
+ "void protobuf_AssignDescriptors() {\n" |
+ // Make sure the file has found its way into the pool. If a descriptor |
+ // is requested *during* static init then AddDescriptors() may not have |
+ // been called yet, so we call it manually. Note that it's fine if |
+ // AddDescriptors() is called multiple times. |
+ " $adddescriptorsname$();\n" |
+ " ::google::protobuf::MessageFactory* factory = $factory$;\n" |
+ " AssignDescriptors(\n" |
+ " \"$filename$\", schemas, file_default_instances, " |
+ "$offsetfunname$(), factory,\n" |
+ " $metadata$, $enum_descriptors$, $service_descriptors$);\n" |
+ "}\n" |
+ "\n" |
+ "void protobuf_AssignDescriptorsOnce() {\n" |
+ " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" |
+ " ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);\n" |
+ "}\n" |
+ "\n", |
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), |
+ "offsetfunname", GlobalOffsetTableName(file_->name()), "filename", |
+ file_->name(), "metadata", |
+ !message_generators_.empty() ? "file_level_metadata" : "NULL", |
+ "enum_descriptors", |
+ !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL", |
+ "service_descriptors", |
+ HasGenericServices(file_, options_) && file_->service_count() > 0 |
+ ? "file_level_service_descriptors" |
+ : "NULL", |
+ "factory", message_factory); |
+ |
+ // Only here because of useless string reference that we don't want in |
+ // protobuf_AssignDescriptorsOnce, because that is called from all the |
+ // GetMetadata member methods. |
printer->Print( |
- "void protobuf_RegisterTypes(const ::std::string&) {\n" |
- " protobuf_AssignDescriptorsOnce();\n"); |
+ "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n" |
+ "void protobuf_RegisterTypes(const ::std::string&) {\n" |
+ " protobuf_AssignDescriptorsOnce();\n"); |
printer->Indent(); |
- for (int i = 0; i < file_->message_type_count(); i++) { |
+ // All normal messages can be done generically |
+ if (!message_generators_.empty()) { |
+ printer->Print( |
+ "::google::protobuf::internal::RegisterAllTypes(file_level_metadata, $size$);\n", |
+ "size", SimpleItoa(message_generators_.size())); |
+ } |
+ |
+ // Map types are treated special |
+ // TODO(gerbens) find a way to treat maps more like normal messages. |
+ for (int i = 0; i < message_generators_.size(); i++) { |
message_generators_[i]->GenerateTypeRegistrations(printer); |
} |
@@ -549,7 +617,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
"shutdownfilename", GlobalShutdownFileName(file_->name())); |
printer->Indent(); |
- for (int i = 0; i < file_->message_type_count(); i++) { |
+ for (int i = 0; i < message_generators_.size(); i++) { |
message_generators_[i]->GenerateShutdownCode(printer); |
} |
@@ -559,43 +627,68 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
// ----------------------------------------------------------------- |
- // Now generate the AddDescriptors() function. |
- PrintHandlingOptionalStaticInitializers( |
- file_, options_, printer, |
- // With static initializers. |
- // Note that we don't need any special synchronization in the following |
- // code |
- // because it is called at static init time before any threads exist. |
- "void $adddescriptorsname$() {\n" |
- " static bool already_here = false;\n" |
- " if (already_here) return;\n" |
- " already_here = true;\n" |
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" |
- "\n", |
- // Without. |
- "void $adddescriptorsname$_impl() {\n" |
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" |
- "\n", |
+ // Now generate the InitDefaults() function. |
+ printer->Print( |
+ "void $initdefaultsname$_impl() {\n" |
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n" |
+ "", |
// Vars. |
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); |
+ "initdefaultsname", GlobalInitDefaultsName(file_->name())); |
printer->Indent(); |
- // Call the AddDescriptors() methods for all of our dependencies, to make |
+ // Call the InitDefaults() methods for all of our dependencies, to make |
// sure they get added first. |
for (int i = 0; i < file_->dependency_count(); i++) { |
const FileDescriptor* dependency = file_->dependency(i); |
// Print the namespace prefix for the dependency. |
string add_desc_name = QualifiedFileLevelSymbol( |
- dependency->package(), GlobalAddDescriptorsName(dependency->name())); |
+ dependency->package(), GlobalInitDefaultsName(dependency->name())); |
// Call its AddDescriptors function. |
printer->Print( |
"$name$();\n", |
"name", add_desc_name); |
} |
+ // Force initialization of primitive values we depend on. |
+ printer->Print("::google::protobuf::internal::InitProtobufDefaults();\n"); |
+ |
+ // Allocate and initialize default instances. This can't be done lazily |
+ // since default instances are returned by simple accessors and are used with |
+ // extensions. Speaking of which, we also register extensions at this time. |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ message_generators_[i]->GenerateDefaultInstanceAllocator(printer); |
+ } |
+ for (int i = 0; i < extension_generators_.size(); i++) { |
+ extension_generators_[i]->GenerateRegistration(printer); |
+ } |
+ for (int i = 0; i < message_generators_.size(); i++) { |
+ message_generators_[i]->GenerateDefaultInstanceInitializer(printer); |
+ } |
+ printer->Outdent(); |
+ printer->Print( |
+ "}\n" |
+ "\n" |
+ "void $initdefaultsname$() {\n" |
+ " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" |
+ " ::google::protobuf::GoogleOnceInit(&once, &$initdefaultsname$_impl);\n" |
+ "}\n", |
+ "initdefaultsname", GlobalInitDefaultsName(file_->name())); |
+ |
+ // ----------------------------------------------------------------- |
+ |
+ // Now generate the AddDescriptors() function. |
+ printer->Print( |
+ "void $adddescriptorsname$_impl() {\n" |
+ " $initdefaultsname$();\n", |
+ // Vars. |
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), |
+ "initdefaultsname", GlobalInitDefaultsName(file_->name())); |
+ |
+ printer->Indent(); |
if (HasDescriptorMethods(file_, options_)) { |
- // Embed the descriptor. We simply serialize the entire FileDescriptorProto |
+ // Embed the descriptor. We simply serialize the entire |
+ // FileDescriptorProto |
// and embed it as a string literal, which is parsed and built into real |
// descriptors at initialization time. |
FileDescriptorProto file_proto; |
@@ -603,60 +696,42 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
string file_data; |
file_proto.SerializeToString(&file_data); |
+ printer->Print("static const char descriptor[] = {\n"); |
+ printer->Indent(); |
+ |
#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. |
+ if (breakdown_large_file && file_data.size() > 66538) { |
+ // 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. 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"); |
+ for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { |
+ printer->Print("'$char$', ", "char", |
+ CEscape(file_data.substr(i, 1))); |
+ } |
+ 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(" \"$data$\"\n", "data", |
+ EscapeTrigraphs(CEscape( |
+ file_data.substr(i, kBytesPerLine)))); |
+ } |
} |
+ |
+ printer->Outdent(); |
+ printer->Print("};\n"); |
printer->Print( |
- ", $size$);\n", |
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(\n" |
+ " descriptor, $size$);\n", |
"size", SimpleItoa(file_data.size())); |
- } |
// Call MessageFactory::InternalRegisterGeneratedFile(). |
printer->Print( |
@@ -665,30 +740,37 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
"filename", file_->name()); |
} |
- // Allocate and initialize default instances. This can't be done lazily |
- // since default instances are returned by simple accessors and are used with |
- // extensions. Speaking of which, we also register extensions at this time. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateDefaultInstanceAllocator(printer); |
- } |
- for (int i = 0; i < file_->extension_count(); i++) { |
- extension_generators_[i]->GenerateRegistration(printer); |
- } |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->GenerateDefaultInstanceInitializer(printer); |
+ // Call the AddDescriptors() methods for all of our dependencies, to make |
+ // sure they get added first. |
+ for (int i = 0; i < file_->dependency_count(); i++) { |
+ const FileDescriptor* dependency = file_->dependency(i); |
+ // Print the namespace prefix for the dependency. |
+ string add_desc_name = QualifiedFileLevelSymbol( |
+ dependency->package(), GlobalAddDescriptorsName(dependency->name())); |
+ // Call its AddDescriptors function. |
+ printer->Print("$adddescriptorsname$();\n", "adddescriptorsname", |
+ add_desc_name); |
} |
printer->Print( |
- "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n", |
- "shutdownfilename", GlobalShutdownFileName(file_->name())); |
+ "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n", |
+ "shutdownfilename", GlobalShutdownFileName(file_->name())); |
printer->Outdent(); |
printer->Print( |
- "}\n" |
- "\n"); |
+ "}\n" |
+ "\n" |
+ "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" |
+ "void $adddescriptorsname$() {\n" |
+ " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" |
+ " &$adddescriptorsname$_impl);\n" |
+ "}\n", |
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); |
- PrintHandlingOptionalStaticInitializers( |
- file_, options_, printer, |
+ if (!StaticInitializersForced(file_, options_)) { |
+ printer->Print("#ifndef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"); |
+ } |
+ printer->Print( |
// With static initializers. |
"// Force AddDescriptors() to be called at static initialization time.\n" |
"struct StaticDescriptorInitializer_$filename$ {\n" |
@@ -696,15 +778,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { |
" $adddescriptorsname$();\n" |
" }\n" |
"} static_descriptor_initializer_$filename$_;\n", |
- // Without. |
- "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" |
- "void $adddescriptorsname$() {\n" |
- " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" |
- " &$adddescriptorsname$_impl);\n" |
- "}\n", |
// Vars. |
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename", |
FilenameIdentifier(file_->name())); |
+ if (!StaticInitializersForced(file_, options_)) { |
+ printer->Print("#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"); |
+ } |
} |
void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) { |
@@ -732,7 +811,7 @@ void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { |
dependency.FillForwardDeclarations(&decls); |
} |
FillForwardDeclarations(&decls); |
- decls.Print(printer); |
+ decls.Print(printer, options_); |
} |
void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { |
@@ -744,14 +823,11 @@ void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { |
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++) { |
+ for (int i = 0; i < enum_generators_.size(); i++) { |
enum_generators_[i]->FillForwardDeclaration(&decls->enums()); |
} |
// Generate forward declarations of classes. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
+ for (int i = 0; i < message_generators_.size(); i++) { |
message_generators_[i]->FillMessageForwardDeclarations( |
&decls->classes()); |
} |
@@ -807,12 +883,10 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { |
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_, options_)) { |
- printer->Print( |
- "#include <google/protobuf/metadata.h>\n"); |
- } |
- if (file_->message_type_count() > 0) { |
+ "#include <google/protobuf/generated_message_util.h>\n" |
+ "#include <google/protobuf/metadata.h>\n"); |
+ |
+ if (!message_generators_.empty()) { |
if (HasDescriptorMethods(file_, options_)) { |
printer->Print( |
"#include <google/protobuf/message.h>\n"); |
@@ -822,8 +896,10 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { |
} |
} |
printer->Print( |
- "#include <google/protobuf/repeated_field.h>\n" |
- "#include <google/protobuf/extension_set.h>\n"); |
+ "#include <google/protobuf/repeated_field.h>" |
+ " // IWYU pragma: export\n" |
+ "#include <google/protobuf/extension_set.h>" |
+ " // IWYU pragma: export\n"); |
if (HasMapFields(file_)) { |
printer->Print( |
"#include <google/protobuf/map.h>\n"); |
@@ -851,7 +927,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { |
"#include <google/protobuf/service.h>\n"); |
} |
- if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) { |
+ if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { |
printer->Print( |
"#include <google/protobuf/unknown_field_set.h>\n"); |
} |
@@ -877,7 +953,7 @@ void FileGenerator::GenerateMetadataPragma(io::Printer* printer, |
} |
void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { |
- set<string> public_import_names; |
+ std::set<string> public_import_names; |
for (int i = 0; i < file_->public_dependency_count(); i++) { |
public_import_names.insert(file_->public_dependency(i)->name()); |
} |
@@ -902,39 +978,19 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations( |
// 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) { |
- map<string, const Descriptor*> classes; |
- for (int i = 0; i < file_->message_type_count(); i++) { |
- message_generators_[i]->FillMessageForwardDeclarations(&classes); |
- } |
- for (map<string, const Descriptor *>::const_iterator it = classes.begin(), |
- end = classes.end(); |
- it != end; ++it) { |
- printer->Print("class $classname$;\n", "classname", it->first); |
- printer->Annotate("classname", it->second); |
- } |
+ "\n" |
+ "// Internal implementation detail -- do not call these.\n" |
+ "void $dllexport_decl$$adddescriptorsname$();\n" |
+ "void $dllexport_decl$$initdefaultsname$();\n", |
+ "initdefaultsname", GlobalInitDefaultsName(file_->name()), |
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), |
+ "dllexport_decl", |
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); |
} |
void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) { |
// Generate class definitions. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
+ for (int i = 0; i < message_generators_.size(); i++) { |
if (i > 0) { |
printer->Print("\n"); |
printer->Print(kThinSeparator); |
@@ -946,10 +1002,7 @@ void FileGenerator::GenerateMessageDefinitions(io::Printer* 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++) { |
+ for (int i = 0; i < enum_generators_.size(); i++) { |
enum_generators_[i]->GenerateDefinition(printer); |
} |
} |
@@ -957,7 +1010,7 @@ void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { |
void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { |
if (HasGenericServices(file_, options_)) { |
// Generate service definitions. |
- for (int i = 0; i < file_->service_count(); i++) { |
+ for (int i = 0; i < service_generators_.size(); i++) { |
if (i > 0) { |
printer->Print("\n"); |
printer->Print(kThinSeparator); |
@@ -973,9 +1026,10 @@ void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { |
} |
void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { |
- // Declare extension identifiers. |
+ // Declare extension identifiers. These are in global scope and so only |
+ // the global scope extensions. |
for (int i = 0; i < file_->extension_count(); i++) { |
- extension_generators_[i]->GenerateDeclaration(printer); |
+ extension_generators_owner_[i]->GenerateDeclaration(printer); |
} |
} |
@@ -1016,7 +1070,7 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { |
printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); |
// Generate class inline methods. |
- for (int i = 0; i < file_->message_type_count(); i++) { |
+ for (int i = 0; i < message_generators_.size(); i++) { |
if (i > 0) { |
printer->Print(kThinSeparator); |
printer->Print("\n"); |
@@ -1026,7 +1080,7 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { |
} |
printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); |
- for (int i = 0; i < file_->message_type_count(); i++) { |
+ for (int i = 0; i < message_generators_.size(); i++) { |
if (i > 0) { |
printer->Print(kThinSeparator); |
printer->Print("\n"); |
@@ -1049,10 +1103,7 @@ void FileGenerator::GenerateProto2NamespaceEnumSpecializations( |
"#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++) { |
+ for (int i = 0; i < enum_generators_.size(); i++) { |
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
} |
printer->Print( |