| 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(
|
|
|