LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/compiler/cpp - cpp_file.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 273 362 75.4 %
Date: 2015-10-10 Functions: 19 25 76.0 %

          Line data    Source code
       1             : // Protocol Buffers - Google's data interchange format
       2             : // Copyright 2008 Google Inc.  All rights reserved.
       3             : // https://developers.google.com/protocol-buffers/
       4             : //
       5             : // Redistribution and use in source and binary forms, with or without
       6             : // modification, are permitted provided that the following conditions are
       7             : // met:
       8             : //
       9             : //     * Redistributions of source code must retain the above copyright
      10             : // notice, this list of conditions and the following disclaimer.
      11             : //     * Redistributions in binary form must reproduce the above
      12             : // copyright notice, this list of conditions and the following disclaimer
      13             : // in the documentation and/or other materials provided with the
      14             : // distribution.
      15             : //     * Neither the name of Google Inc. nor the names of its
      16             : // contributors may be used to endorse or promote products derived from
      17             : // this software without specific prior written permission.
      18             : //
      19             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      20             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      21             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      22             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      23             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      24             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      25             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      28             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      29             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30             : 
      31             : // Author: kenton@google.com (Kenton Varda)
      32             : //  Based on original Protocol Buffers design by
      33             : //  Sanjay Ghemawat, Jeff Dean, and others.
      34             : 
      35             : #include <google/protobuf/compiler/cpp/cpp_file.h>
      36             : #include <map>
      37             : #include <memory>
      38             : #ifndef _SHARED_PTR_H
      39             : #include <google/protobuf/stubs/shared_ptr.h>
      40             : #endif
      41             : #include <set>
      42             : 
      43             : #include <google/protobuf/compiler/cpp/cpp_enum.h>
      44             : #include <google/protobuf/compiler/cpp/cpp_service.h>
      45             : #include <google/protobuf/compiler/cpp/cpp_extension.h>
      46             : #include <google/protobuf/compiler/cpp/cpp_helpers.h>
      47             : #include <google/protobuf/compiler/cpp/cpp_message.h>
      48             : #include <google/protobuf/compiler/cpp/cpp_field.h>
      49             : #include <google/protobuf/io/printer.h>
      50             : #include <google/protobuf/descriptor.pb.h>
      51             : #include <google/protobuf/stubs/strutil.h>
      52             : 
      53             : namespace google {
      54             : namespace protobuf {
      55             : namespace compiler {
      56             : namespace cpp {
      57             : 
      58             : // ===================================================================
      59             : 
      60        1499 : FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
      61             :     : file_(file),
      62             :       message_generators_(
      63         340 :           new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
      64             :       enum_generators_(
      65         128 :           new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
      66             :       service_generators_(
      67         119 :           new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
      68             :       extension_generators_(
      69         334 :           new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
      70         539 :       options_(options) {
      71             : 
      72         582 :   for (int i = 0; i < file->message_type_count(); i++) {
      73         242 :     message_generators_[i].reset(
      74         726 :       new MessageGenerator(file->message_type(i), options));
      75             :   }
      76             : 
      77         109 :   for (int i = 0; i < file->enum_type_count(); i++) {
      78          30 :     enum_generators_[i].reset(
      79          90 :       new EnumGenerator(file->enum_type(i), options));
      80             :   }
      81             : 
      82          91 :   for (int i = 0; i < file->service_count(); i++) {
      83          21 :     service_generators_[i].reset(
      84          63 :       new ServiceGenerator(file->service(i), options));
      85             :   }
      86             : 
      87         521 :   for (int i = 0; i < file->extension_count(); i++) {
      88         236 :     extension_generators_[i].reset(
      89         708 :       new ExtensionGenerator(file->extension(i), options));
      90             :   }
      91             : 
      92          49 :   SplitStringUsing(file_->package(), ".", &package_parts_);
      93          49 : }
      94             : 
      95          98 : FileGenerator::~FileGenerator() {}
      96             : 
      97           0 : void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
      98           0 :   if (!options_.proto_h) {
      99           0 :     return;
     100             :   }
     101             : 
     102           0 :   string filename_identifier = FilenameIdentifier(file_->name());
     103           0 :   GenerateTopHeaderGuard(printer, filename_identifier);
     104             : 
     105             : 
     106           0 :   GenerateLibraryIncludes(printer);
     107             : 
     108           0 :   for (int i = 0; i < file_->public_dependency_count(); i++) {
     109           0 :     const FileDescriptor* dep = file_->public_dependency(i);
     110           0 :     const char* extension = ".proto.h";
     111           0 :     string dependency = StripProto(dep->name()) + extension;
     112             :     printer->Print(
     113             :       "#include \"$dependency$\"  // IWYU pragma: export\n",
     114           0 :       "dependency", dependency);
     115             :   }
     116             : 
     117             :   printer->Print(
     118           0 :     "// @@protoc_insertion_point(includes)\n");
     119             : 
     120             : 
     121           0 :   GenerateForwardDeclarations(printer);
     122             : 
     123             :   // Open namespace.
     124           0 :   GenerateNamespaceOpeners(printer);
     125             : 
     126           0 :   GenerateGlobalStateFunctionDeclarations(printer);
     127             : 
     128           0 :   printer->Print("\n");
     129             : 
     130           0 :   GenerateEnumDefinitions(printer);
     131             : 
     132           0 :   printer->Print(kThickSeparator);
     133           0 :   printer->Print("\n");
     134             : 
     135           0 :   GenerateMessageDefinitions(printer);
     136             : 
     137           0 :   printer->Print("\n");
     138           0 :   printer->Print(kThickSeparator);
     139           0 :   printer->Print("\n");
     140             : 
     141           0 :   GenerateServiceDefinitions(printer);
     142             : 
     143           0 :   GenerateExtensionIdentifiers(printer);
     144             : 
     145           0 :   printer->Print("\n");
     146           0 :   printer->Print(kThickSeparator);
     147           0 :   printer->Print("\n");
     148             : 
     149           0 :   GenerateInlineFunctionDefinitions(printer);
     150             : 
     151             :   printer->Print(
     152             :     "\n"
     153             :     "// @@protoc_insertion_point(namespace_scope)\n"
     154           0 :     "\n");
     155             : 
     156             :   // Close up namespace.
     157           0 :   GenerateNamespaceClosers(printer);
     158             : 
     159             :   // We need to specialize some templates in the ::google::protobuf namespace:
     160           0 :   GenerateProto2NamespaceEnumSpecializations(printer);
     161             : 
     162             :   printer->Print(
     163             :     "\n"
     164             :     "// @@protoc_insertion_point(global_scope)\n"
     165           0 :     "\n");
     166             : 
     167           0 :   GenerateBottomHeaderGuard(printer, filename_identifier);
     168             : }
     169             : 
     170          49 : void FileGenerator::GeneratePBHeader(io::Printer* printer) {
     171             :   string filename_identifier =
     172          98 :       FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
     173          49 :   GenerateTopHeaderGuard(printer, filename_identifier);
     174             : 
     175          49 :   if (options_.proto_h) {
     176             :     printer->Print("#include \"$basename$.proto.h\"  // IWYU pragma: export\n",
     177           0 :                    "basename", StripProto(file_->name()));
     178             :   } else {
     179          49 :     GenerateLibraryIncludes(printer);
     180             :   }
     181          49 :   GenerateDependencyIncludes(printer);
     182             : 
     183             :   printer->Print(
     184          49 :     "// @@protoc_insertion_point(includes)\n");
     185             : 
     186             : 
     187             : 
     188             :   // Open namespace.
     189          49 :   GenerateNamespaceOpeners(printer);
     190             : 
     191          49 :   if (!options_.proto_h) {
     192          49 :     GenerateGlobalStateFunctionDeclarations(printer);
     193          49 :     GenerateMessageForwardDeclarations(printer);
     194             : 
     195          49 :     printer->Print("\n");
     196             : 
     197          49 :     GenerateEnumDefinitions(printer);
     198             : 
     199          49 :     printer->Print(kThickSeparator);
     200          49 :     printer->Print("\n");
     201             : 
     202          49 :     GenerateMessageDefinitions(printer);
     203             : 
     204          49 :     printer->Print("\n");
     205          49 :     printer->Print(kThickSeparator);
     206          49 :     printer->Print("\n");
     207             : 
     208          49 :     GenerateServiceDefinitions(printer);
     209             : 
     210          49 :     GenerateExtensionIdentifiers(printer);
     211             : 
     212          49 :     printer->Print("\n");
     213          49 :     printer->Print(kThickSeparator);
     214          49 :     printer->Print("\n");
     215             : 
     216          49 :     GenerateInlineFunctionDefinitions(printer);
     217             :   }
     218             : 
     219             :   printer->Print(
     220             :     "\n"
     221          49 :     "// @@protoc_insertion_point(namespace_scope)\n");
     222             : 
     223             :   // Close up namespace.
     224          49 :   GenerateNamespaceClosers(printer);
     225             : 
     226          49 :   if (!options_.proto_h) {
     227             :     // We need to specialize some templates in the ::google::protobuf namespace:
     228          49 :     GenerateProto2NamespaceEnumSpecializations(printer);
     229             :   }
     230             : 
     231             :   printer->Print(
     232             :     "\n"
     233             :     "// @@protoc_insertion_point(global_scope)\n"
     234          49 :     "\n");
     235             : 
     236          49 :   GenerateBottomHeaderGuard(printer, filename_identifier);
     237          49 : }
     238             : 
     239          49 : void FileGenerator::GenerateSource(io::Printer* printer) {
     240             :   string header =
     241        1180 :       StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
     242             :   printer->Print(
     243             :     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     244             :     "// source: $filename$\n"
     245             :     "\n"
     246             :     // The generated code calls accessors that might be deprecated. We don't
     247             :     // want the compiler to warn in generated code.
     248             :     "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
     249             :     "#include \"$header$\"\n"
     250             :     "\n"
     251             :     "#include <algorithm>\n"    // for swap()
     252             :     "\n"
     253             :     "#include <google/protobuf/stubs/common.h>\n"
     254             :     "#include <google/protobuf/stubs/once.h>\n"
     255             :     "#include <google/protobuf/io/coded_stream.h>\n"
     256             :     "#include <google/protobuf/wire_format_lite_inl.h>\n",
     257          98 :     "filename", file_->name(),
     258          49 :     "header", header);
     259             : 
     260             :   // Unknown fields implementation in lite mode uses StringOutputStream
     261         104 :   if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
     262             :     printer->Print(
     263           6 :       "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
     264             :   }
     265             : 
     266          98 :   if (HasDescriptorMethods(file_)) {
     267             :     printer->Print(
     268             :       "#include <google/protobuf/descriptor.h>\n"
     269             :       "#include <google/protobuf/generated_message_reflection.h>\n"
     270             :       "#include <google/protobuf/reflection_ops.h>\n"
     271          43 :       "#include <google/protobuf/wire_format.h>\n");
     272             :   }
     273             : 
     274          49 :   if (options_.proto_h) {
     275             :     // Use the smaller .proto.h files.
     276           0 :     for (int i = 0; i < file_->dependency_count(); i++) {
     277           0 :       const FileDescriptor* dep = file_->dependency(i);
     278           0 :       const char* extension = ".proto.h";
     279           0 :       string dependency = StripProto(dep->name()) + extension;
     280             :       printer->Print(
     281             :           "#include \"$dependency$\"\n",
     282           0 :           "dependency", dependency);
     283             :     }
     284             :   }
     285             : 
     286             :   printer->Print(
     287          49 :     "// @@protoc_insertion_point(includes)\n");
     288             : 
     289          49 :   GenerateNamespaceOpeners(printer);
     290             : 
     291          98 :   if (HasDescriptorMethods(file_)) {
     292             :     printer->Print(
     293             :       "\n"
     294             :       "namespace {\n"
     295          43 :       "\n");
     296         479 :     for (int i = 0; i < file_->message_type_count(); i++) {
     297         654 :       message_generators_[i]->GenerateDescriptorDeclarations(printer);
     298             :     }
     299          93 :     for (int i = 0; i < file_->enum_type_count(); i++) {
     300             :       printer->Print(
     301             :         "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
     302          75 :         "name", ClassName(file_->enum_type(i), false));
     303             :     }
     304             : 
     305          86 :     if (HasGenericServices(file_)) {
     306          11 :       for (int i = 0; i < file_->service_count(); i++) {
     307             :         printer->Print(
     308             :           "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
     309           8 :           "name", file_->service(i)->name());
     310             :       }
     311             :     }
     312             : 
     313             :     printer->Print(
     314             :       "\n"
     315             :       "}  // namespace\n"
     316          43 :       "\n");
     317             :   }
     318             : 
     319             :   // Define our externally-visible BuildDescriptors() function.  (For the lite
     320             :   // library, all this does is initialize default instances.)
     321          49 :   GenerateBuildDescriptors(printer);
     322             : 
     323             :   // Generate enums.
     324         109 :   for (int i = 0; i < file_->enum_type_count(); i++) {
     325          90 :     enum_generators_[i]->GenerateMethods(printer);
     326             :   }
     327             : 
     328             :   // Generate classes.
     329         533 :   for (int i = 0; i < file_->message_type_count(); i++) {
     330         287 :     if (i == 0 && HasGeneratedMethods(file_)) {
     331             :       printer->Print(
     332             :           "\n"
     333             :           "namespace {\n"
     334             :           "\n"
     335             :           "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
     336             :           "static void MergeFromFail(int line) {\n"
     337             :           "  GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
     338             :           "}\n"
     339             :           "\n"
     340             :           "}  // namespace\n"
     341          43 :           "\n");
     342             :     }
     343         242 :     printer->Print("\n");
     344         242 :     printer->Print(kThickSeparator);
     345         242 :     printer->Print("\n");
     346         726 :     message_generators_[i]->GenerateClassMethods(printer);
     347             : 
     348         242 :     printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
     349             :     // Generate class inline methods.
     350         484 :     message_generators_[i]->GenerateInlineMethods(printer,
     351         242 :                                                   /* is_inline = */ false);
     352         242 :     printer->Print("#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
     353             :   }
     354             : 
     355          98 :   if (HasGenericServices(file_)) {
     356             :     // Generate services.
     357          11 :     for (int i = 0; i < file_->service_count(); i++) {
     358           4 :       if (i == 0) printer->Print("\n");
     359           4 :       printer->Print(kThickSeparator);
     360           4 :       printer->Print("\n");
     361          12 :       service_generators_[i]->GenerateImplementation(printer);
     362             :     }
     363             :   }
     364             : 
     365             :   // Define extensions.
     366         521 :   for (int i = 0; i < file_->extension_count(); i++) {
     367         708 :     extension_generators_[i]->GenerateDefinition(printer);
     368             :   }
     369             : 
     370             :   printer->Print(
     371             :     "\n"
     372          49 :     "// @@protoc_insertion_point(namespace_scope)\n");
     373             : 
     374          49 :   GenerateNamespaceClosers(printer);
     375             : 
     376             :   printer->Print(
     377             :     "\n"
     378          49 :     "// @@protoc_insertion_point(global_scope)\n");
     379          49 : }
     380             : 
     381           0 : class FileGenerator::ForwardDeclarations {
     382             :  public:
     383           0 :   ~ForwardDeclarations() {
     384           0 :     for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
     385           0 :                                                       end = namespaces_.end();
     386             :          it != end; ++it) {
     387           0 :       delete it->second;
     388             :     }
     389           0 :     namespaces_.clear();
     390           0 :   }
     391             : 
     392           0 :   ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
     393           0 :     ForwardDeclarations*& ns = namespaces_[ns_name];
     394           0 :     if (ns == NULL) {
     395           0 :       ns = new ForwardDeclarations;
     396             :     }
     397           0 :     return ns;
     398             :   }
     399             : 
     400             :   set<string>& classes() { return classes_; }
     401             :   set<string>& enums() { return enums_; }
     402             : 
     403           0 :   void Print(io::Printer* printer) const {
     404           0 :     for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
     405             :          it != end; ++it) {
     406             :       printer->Print("enum $enumname$ : int;\n"
     407             :                      "bool $enumname$_IsValid(int value);\n",
     408           0 :                      "enumname", it->c_str());
     409             :     }
     410           0 :     for (set<string>::const_iterator it = classes_.begin(),
     411           0 :                                      end = classes_.end();
     412             :          it != end; ++it) {
     413           0 :       printer->Print("class $classname$;\n", "classname", it->c_str());
     414             :     }
     415           0 :     for (map<string, ForwardDeclarations *>::const_iterator
     416           0 :              it = namespaces_.begin(),
     417           0 :              end = namespaces_.end();
     418             :          it != end; ++it) {
     419             :       printer->Print("namespace $nsname$ {\n",
     420           0 :                      "nsname", it->first);
     421           0 :       it->second->Print(printer);
     422             :       printer->Print("}  // namespace $nsname$\n",
     423           0 :                      "nsname", it->first);
     424             :     }
     425           0 :   }
     426             : 
     427             : 
     428             :  private:
     429             :   map<string, ForwardDeclarations*> namespaces_;
     430             :   set<string> classes_;
     431             :   set<string> enums_;
     432             : };
     433             : 
     434          49 : void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
     435             :   // AddDescriptors() is a file-level procedure which adds the encoded
     436             :   // FileDescriptorProto for this .proto file to the global DescriptorPool for
     437             :   // generated files (DescriptorPool::generated_pool()). It either runs at
     438             :   // static initialization time (by default) or when default_instance() is
     439             :   // called for the first time (in LITE_RUNTIME mode with
     440             :   // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
     441             :   // constructs default instances and registers extensions.
     442             :   //
     443             :   // Its sibling, AssignDescriptors(), actually pulls the compiled
     444             :   // FileDescriptor from the DescriptorPool and uses it to populate all of
     445             :   // the global variables which store pointers to the descriptor objects.
     446             :   // It also constructs the reflection objects.  It is called the first time
     447             :   // anyone calls descriptor() or GetReflection() on one of the types defined
     448             :   // in the file.
     449             : 
     450             :   // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
     451             :   // and we only use AddDescriptors() to allocate default instances.
     452        2421 :   if (HasDescriptorMethods(file_)) {
     453             :     printer->Print(
     454             :       "\n"
     455             :       "void $assigndescriptorsname$() {\n",
     456          86 :       "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
     457          43 :     printer->Indent();
     458             : 
     459             :     // Make sure the file has found its way into the pool.  If a descriptor
     460             :     // is requested *during* static init then AddDescriptors() may not have
     461             :     // been called yet, so we call it manually.  Note that it's fine if
     462             :     // AddDescriptors() is called multiple times.
     463             :     printer->Print(
     464             :       "$adddescriptorsname$();\n",
     465         129 :       "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
     466             : 
     467             :     // Get the file's descriptor from the pool.
     468             :     printer->Print(
     469             :       "const ::google::protobuf::FileDescriptor* file =\n"
     470             :       "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
     471             :       "    \"$filename$\");\n"
     472             :       // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
     473             :       // being unused when compiling an empty .proto file.
     474             :       "GOOGLE_CHECK(file != NULL);\n",
     475          86 :       "filename", file_->name());
     476             : 
     477             :     // Go through all the stuff defined in this file and generated code to
     478             :     // assign the global descriptor pointers based on the file descriptor.
     479         522 :     for (int i = 0; i < file_->message_type_count(); i++) {
     480         654 :       message_generators_[i]->GenerateDescriptorInitializer(printer, i);
     481             :     }
     482          93 :     for (int i = 0; i < file_->enum_type_count(); i++) {
     483          75 :       enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
     484             :     }
     485          86 :     if (HasGenericServices(file_)) {
     486          11 :       for (int i = 0; i < file_->service_count(); i++) {
     487          12 :         service_generators_[i]->GenerateDescriptorInitializer(printer, i);
     488             :       }
     489             :     }
     490             : 
     491          43 :     printer->Outdent();
     492             :     printer->Print(
     493             :       "}\n"
     494          43 :       "\n");
     495             : 
     496             :     // ---------------------------------------------------------------
     497             : 
     498             :     // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
     499             :     // AssignDescriptors().  All later times, waits for the first call to
     500             :     // complete and then returns.
     501             :     printer->Print(
     502             :       "namespace {\n"
     503             :       "\n"
     504             :       "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
     505             :       "inline void protobuf_AssignDescriptorsOnce() {\n"
     506             :       "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
     507             :       "                 &$assigndescriptorsname$);\n"
     508             :       "}\n"
     509             :       "\n",
     510         129 :       "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
     511             : 
     512             :     // protobuf_RegisterTypes():  Calls
     513             :     // MessageFactory::InternalRegisterGeneratedType() for each message type.
     514             :     printer->Print(
     515             :       "void protobuf_RegisterTypes(const ::std::string&) {\n"
     516          43 :       "  protobuf_AssignDescriptorsOnce();\n");
     517          43 :     printer->Indent();
     518             : 
     519         522 :     for (int i = 0; i < file_->message_type_count(); i++) {
     520         654 :       message_generators_[i]->GenerateTypeRegistrations(printer);
     521             :     }
     522             : 
     523          43 :     printer->Outdent();
     524             :     printer->Print(
     525             :       "}\n"
     526             :       "\n"
     527          43 :       "}  // namespace\n");
     528             :   }
     529             : 
     530             :   // -----------------------------------------------------------------
     531             : 
     532             :   // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
     533             :   printer->Print(
     534             :     "\n"
     535             :     "void $shutdownfilename$() {\n",
     536         147 :     "shutdownfilename", GlobalShutdownFileName(file_->name()));
     537          49 :   printer->Indent();
     538             : 
     539         582 :   for (int i = 0; i < file_->message_type_count(); i++) {
     540         726 :     message_generators_[i]->GenerateShutdownCode(printer);
     541             :   }
     542             : 
     543          49 :   printer->Outdent();
     544             :   printer->Print(
     545          49 :     "}\n\n");
     546             : 
     547             :   // -----------------------------------------------------------------
     548             : 
     549             :   // Now generate the AddDescriptors() function.
     550             :   PrintHandlingOptionalStaticInitializers(
     551             :     file_, printer,
     552             :     // With static initializers.
     553             :     // Note that we don't need any special synchronization in the following code
     554             :     // because it is called at static init time before any threads exist.
     555             :     "void $adddescriptorsname$() {\n"
     556             :     "  static bool already_here = false;\n"
     557             :     "  if (already_here) return;\n"
     558             :     "  already_here = true;\n"
     559             :     "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
     560             :     "\n",
     561             :     // Without.
     562             :     "void $adddescriptorsname$_impl() {\n"
     563             :     "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
     564             :     "\n",
     565             :     // Vars.
     566         196 :     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
     567             : 
     568          49 :   printer->Indent();
     569             : 
     570             :   // Call the AddDescriptors() methods for all of our dependencies, to make
     571             :   // sure they get added first.
     572         200 :   for (int i = 0; i < file_->dependency_count(); i++) {
     573         153 :     const FileDescriptor* dependency = file_->dependency(i);
     574             :     // Print the namespace prefix for the dependency.
     575             :     string add_desc_name = QualifiedFileLevelSymbol(
     576         153 :         dependency->package(), GlobalAddDescriptorsName(dependency->name()));
     577             :     // Call its AddDescriptors function.
     578             :     printer->Print(
     579             :       "$name$();\n",
     580          51 :       "name", add_desc_name);
     581             :   }
     582             : 
     583          98 :   if (HasDescriptorMethods(file_)) {
     584             :     // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
     585             :     // and embed it as a string literal, which is parsed and built into real
     586             :     // descriptors at initialization time.
     587          43 :     FileDescriptorProto file_proto;
     588          43 :     file_->CopyTo(&file_proto);
     589             :     string file_data;
     590          43 :     file_proto.SerializeToString(&file_data);
     591             : 
     592             : #ifdef _MSC_VER
     593             :     bool breakdown_large_file = true;
     594             : #else
     595          43 :     bool breakdown_large_file = false;
     596             : #endif
     597             :     // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
     598             :     // bytes in length". Declare a static array of characters rather than use a
     599             :     // string literal.
     600             :     if (breakdown_large_file && file_data.size() > 65535) {
     601             :       printer->Print(
     602             :           "static const char descriptor[] = {\n");
     603             :       printer->Indent();
     604             : 
     605             :       // Only write 25 bytes per line.
     606             :       static const int kBytesPerLine = 25;
     607             :       for (int i = 0; i < file_data.size();) {
     608             :           for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
     609             :             printer->Print(
     610             :                 "$char$, ",
     611             :                 "char", SimpleItoa(file_data[i]));
     612             :           }
     613             :           printer->Print(
     614             :               "\n");
     615             :       }
     616             : 
     617             :       printer->Outdent();
     618             :       printer->Print(
     619             :           "};\n");
     620             : 
     621             :       printer->Print(
     622             :           "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
     623             :           "size", SimpleItoa(file_data.size()));
     624             : 
     625             :     } else {
     626             :       printer->Print(
     627          43 :         "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
     628             : 
     629             :       // Only write 40 bytes per line.
     630             :       static const int kBytesPerLine = 40;
     631       15359 :       for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
     632             :         printer->Print("\n  \"$data$\"",
     633             :                        "data",
     634             :                        EscapeTrigraphs(
     635       30632 :                            CEscape(file_data.substr(i, kBytesPerLine))));
     636             :     }
     637             :     printer->Print(
     638             :         ", $size$);\n",
     639          86 :         "size", SimpleItoa(file_data.size()));
     640             :     }
     641             : 
     642             :     // Call MessageFactory::InternalRegisterGeneratedFile().
     643             :     printer->Print(
     644             :       "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
     645             :       "  \"$filename$\", &protobuf_RegisterTypes);\n",
     646         129 :       "filename", file_->name());
     647             :   }
     648             : 
     649             :   // Allocate and initialize default instances.  This can't be done lazily
     650             :   // since default instances are returned by simple accessors and are used with
     651             :   // extensions.  Speaking of which, we also register extensions at this time.
     652         533 :   for (int i = 0; i < file_->message_type_count(); i++) {
     653         726 :     message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
     654             :   }
     655         521 :   for (int i = 0; i < file_->extension_count(); i++) {
     656         708 :     extension_generators_[i]->GenerateRegistration(printer);
     657             :   }
     658         533 :   for (int i = 0; i < file_->message_type_count(); i++) {
     659         726 :     message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
     660             :   }
     661             : 
     662             :   printer->Print(
     663             :     "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
     664          98 :     "shutdownfilename", GlobalShutdownFileName(file_->name()));
     665             : 
     666          49 :   printer->Outdent();
     667             :   printer->Print(
     668             :     "}\n"
     669          49 :     "\n");
     670             : 
     671             :   PrintHandlingOptionalStaticInitializers(
     672             :     file_, printer,
     673             :     // With static initializers.
     674             :     "// Force AddDescriptors() to be called at static initialization time.\n"
     675             :     "struct StaticDescriptorInitializer_$filename$ {\n"
     676             :     "  StaticDescriptorInitializer_$filename$() {\n"
     677             :     "    $adddescriptorsname$();\n"
     678             :     "  }\n"
     679             :     "} static_descriptor_initializer_$filename$_;\n",
     680             :     // Without.
     681             :     "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
     682             :     "void $adddescriptorsname$() {\n"
     683             :     "  ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
     684             :     "                 &$adddescriptorsname$_impl);\n"
     685             :     "}\n",
     686             :     // Vars.
     687          98 :     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
     688         245 :     "filename", FilenameIdentifier(file_->name()));
     689          49 : }
     690             : 
     691          98 : void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
     692         748 :   if (package_parts_.size() > 0) printer->Print("\n");
     693             : 
     694        1006 :   for (int i = 0; i < package_parts_.size(); i++) {
     695             :     printer->Print("namespace $part$ {\n",
     696         356 :                    "part", package_parts_[i]);
     697             :   }
     698          98 : }
     699             : 
     700          98 : void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
     701         570 :   if (package_parts_.size() > 0) printer->Print("\n");
     702             : 
     703         570 :   for (int i = package_parts_.size() - 1; i >= 0; i--) {
     704             :     printer->Print("}  // namespace $part$\n",
     705         534 :                    "part", package_parts_[i]);
     706             :   }
     707          98 : }
     708             : 
     709           0 : void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
     710             :   ForwardDeclarations decls;
     711           0 :   for (int i = 0; i < file_->dependency_count(); i++) {
     712           0 :     FileGenerator dependency(file_->dependency(i), options_);
     713           0 :     dependency.FillForwardDeclarations(&decls);
     714           0 :   }
     715           0 :   FillForwardDeclarations(&decls);
     716           0 :   decls.Print(printer);
     717           0 : }
     718             : 
     719           0 : void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
     720           0 :   for (int i = 0; i < file_->public_dependency_count(); i++) {
     721           0 :     FileGenerator dependency(file_->public_dependency(i), options_);
     722           0 :     dependency.FillForwardDeclarations(decls);
     723           0 :   }
     724           0 :   for (int i = 0; i < package_parts_.size(); i++) {
     725           0 :     decls = decls->AddOrGetNamespace(package_parts_[i]);
     726             :   }
     727             :   // Generate enum definitions.
     728           0 :   for (int i = 0; i < file_->message_type_count(); i++) {
     729           0 :     message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
     730             :   }
     731           0 :   for (int i = 0; i < file_->enum_type_count(); i++) {
     732           0 :     enum_generators_[i]->FillForwardDeclaration(&decls->enums());
     733             :   }
     734             :   // Generate forward declarations of classes.
     735           0 :   for (int i = 0; i < file_->message_type_count(); i++) {
     736           0 :     message_generators_[i]->FillMessageForwardDeclarations(
     737           0 :         &decls->classes());
     738             :   }
     739           0 : }
     740             : 
     741          49 : void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
     742             :                                            const string& filename_identifier) {
     743             :   // Generate top of header.
     744             :   printer->Print(
     745             :     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     746             :     "// source: $filename$\n"
     747             :     "\n"
     748             :     "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
     749             :     "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
     750             :     "\n"
     751             :     "#include <string>\n"
     752             :     "\n",
     753          49 :     "filename", file_->name(),
     754          49 :     "filename_identifier", filename_identifier);
     755          49 : }
     756             : 
     757          49 : void FileGenerator::GenerateBottomHeaderGuard(
     758             :     io::Printer* printer, const string& filename_identifier) {
     759             :   printer->Print(
     760             :     "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
     761          49 :     "filename_identifier", filename_identifier);
     762          49 : }
     763             : 
     764          49 : void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
     765             : 
     766             :   printer->Print(
     767             :     "#include <google/protobuf/stubs/common.h>\n"
     768          49 :     "\n");
     769             : 
     770             :   // Verify the protobuf library header version is compatible with the protoc
     771             :   // version before going any further.
     772             :   printer->Print(
     773             :     "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
     774             :     "#error This file was generated by a newer version of protoc which is\n"
     775             :     "#error incompatible with your Protocol Buffer headers.  Please update\n"
     776             :     "#error your headers.\n"
     777             :     "#endif\n"
     778             :     "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
     779             :     "#error This file was generated by an older version of protoc which is\n"
     780             :     "#error incompatible with your Protocol Buffer headers.  Please\n"
     781             :     "#error regenerate this file with a newer version of protoc.\n"
     782             :     "#endif\n"
     783             :     "\n",
     784             :     "min_header_version",
     785             :       SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
     786         147 :     "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
     787             : 
     788             :   // OK, it's now safe to #include other files.
     789             :   printer->Print(
     790             :     "#include <google/protobuf/arena.h>\n"
     791             :     "#include <google/protobuf/arenastring.h>\n"
     792          49 :     "#include <google/protobuf/generated_message_util.h>\n");
     793         190 :   if (UseUnknownFieldSet(file_)) {
     794             :     printer->Print(
     795          43 :       "#include <google/protobuf/metadata.h>\n");
     796             :   }
     797          98 :   if (file_->message_type_count() > 0) {
     798          90 :     if (HasDescriptorMethods(file_)) {
     799             :       printer->Print(
     800          39 :         "#include <google/protobuf/message.h>\n");
     801             :     } else {
     802             :       printer->Print(
     803           6 :         "#include <google/protobuf/message_lite.h>\n");
     804             :     }
     805             :   }
     806             :   printer->Print(
     807             :     "#include <google/protobuf/repeated_field.h>\n"
     808          49 :     "#include <google/protobuf/extension_set.h>\n");
     809          49 :   if (HasMapFields(file_)) {
     810             :     printer->Print(
     811           7 :         "#include <google/protobuf/map.h>\n");
     812          14 :     if (HasDescriptorMethods(file_)) {
     813             :       printer->Print(
     814           6 :           "#include <google/protobuf/map_field_inl.h>\n");
     815             :     } else {
     816             :       printer->Print(
     817           1 :           "#include <google/protobuf/map_field_lite.h>\n");
     818             :     }
     819             :   }
     820             : 
     821          49 :   if (HasEnumDefinitions(file_)) {
     822          42 :     if (HasDescriptorMethods(file_)) {
     823             :       printer->Print(
     824          18 :           "#include <google/protobuf/generated_enum_reflection.h>\n");
     825             :     } else {
     826             :       printer->Print(
     827           3 :           "#include <google/protobuf/generated_enum_util.h>\n");
     828             :     }
     829             :   }
     830             : 
     831          98 :   if (HasGenericServices(file_)) {
     832             :     printer->Print(
     833           3 :       "#include <google/protobuf/service.h>\n");
     834             :   }
     835             : 
     836         141 :   if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
     837             :     printer->Print(
     838          39 :       "#include <google/protobuf/unknown_field_set.h>\n");
     839             :   }
     840             : 
     841             : 
     842          49 :   if (IsAnyMessage(file_)) {
     843             :     printer->Print(
     844           0 :       "#include \"google/protobuf/any.h\"\n");
     845             :   }
     846          49 : }
     847             : 
     848          49 : void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
     849             :   set<string> public_import_names;
     850         102 :   for (int i = 0; i < file_->public_dependency_count(); i++) {
     851         206 :     public_import_names.insert(file_->public_dependency(i)->name());
     852             :   }
     853             : 
     854         151 :   for (int i = 0; i < file_->dependency_count(); i++) {
     855         102 :     const string& name = file_->dependency(i)->name();
     856          51 :     bool public_import = (public_import_names.count(name) != 0);
     857             : 
     858             : 
     859             :     printer->Print(
     860             :       "#include \"$dependency$.pb.h\"$iwyu$\n",
     861             :       "dependency", StripProto(name),
     862         153 :       "iwyu", (public_import) ? "  // IWYU pragma: export" : "");
     863             :   }
     864          49 : }
     865             : 
     866          49 : void FileGenerator::GenerateGlobalStateFunctionDeclarations(
     867             :     io::Printer* printer) {
     868             :   // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
     869             :   // functions, so that we can declare them to be friends of each class.
     870             :   printer->Print(
     871             :     "\n"
     872             :     "// Internal implementation detail -- do not call these.\n"
     873             :     "void $dllexport_decl$$adddescriptorsname$();\n",
     874         147 :     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
     875             :     "dllexport_decl",
     876         245 :     options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
     877             : 
     878             :   printer->Print(
     879             :     // Note that we don't put dllexport_decl on these because they are only
     880             :     // called by the .pb.cc file in which they are defined.
     881             :     "void $assigndescriptorsname$();\n"
     882             :     "void $shutdownfilename$();\n"
     883             :     "\n",
     884          98 :     "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
     885         245 :     "shutdownfilename", GlobalShutdownFileName(file_->name()));
     886          49 : }
     887             : 
     888          49 : void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
     889             :   set<string> classes;
     890         291 :   for (int i = 0; i < file_->message_type_count(); i++) {
     891         726 :     message_generators_[i]->FillMessageForwardDeclarations(&classes);
     892             :   }
     893         438 :   for (set<string>::const_iterator it = classes.begin(), end = classes.end();
     894             :        it != end; ++it) {
     895         873 :     printer->Print("class $classname$;\n", "classname", it->c_str());
     896             :   }
     897          49 : }
     898             : 
     899          49 : void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
     900             :   // Generate class definitions.
     901         291 :   for (int i = 0; i < file_->message_type_count(); i++) {
     902         242 :     if (i > 0) {
     903         197 :       printer->Print("\n");
     904         197 :       printer->Print(kThinSeparator);
     905         197 :       printer->Print("\n");
     906             :     }
     907         726 :     message_generators_[i]->GenerateClassDefinition(printer);
     908             :   }
     909          49 : }
     910             : 
     911          49 : void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
     912             :   // Generate enum definitions.
     913         370 :   for (int i = 0; i < file_->message_type_count(); i++) {
     914         726 :     message_generators_[i]->GenerateEnumDefinitions(printer);
     915             :   }
     916         109 :   for (int i = 0; i < file_->enum_type_count(); i++) {
     917          90 :     enum_generators_[i]->GenerateDefinition(printer);
     918             :   }
     919          49 : }
     920             : 
     921          49 : void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
     922         105 :   if (HasGenericServices(file_)) {
     923             :     // Generate service definitions.
     924          11 :     for (int i = 0; i < file_->service_count(); i++) {
     925           4 :       if (i > 0) {
     926           1 :         printer->Print("\n");
     927           1 :         printer->Print(kThinSeparator);
     928           1 :         printer->Print("\n");
     929             :       }
     930          12 :       service_generators_[i]->GenerateDeclarations(printer);
     931             :     }
     932             : 
     933           3 :     printer->Print("\n");
     934           3 :     printer->Print(kThickSeparator);
     935           3 :     printer->Print("\n");
     936             :   }
     937          49 : }
     938             : 
     939          49 : void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
     940             :   // Declare extension identifiers.
     941         285 :   for (int i = 0; i < file_->extension_count(); i++) {
     942         708 :     extension_generators_[i]->GenerateDeclaration(printer);
     943             :   }
     944          49 : }
     945             : 
     946          49 : void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
     947             :   // An aside about inline functions in .proto.h mode:
     948             :   //
     949             :   // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
     950             :   // moving much of the inline functions to the .pb.cc file, which can be a
     951             :   // significant performance benefit for compilation time, at the expense
     952             :   // of non-inline function calls.
     953             :   //
     954             :   // However, in .proto.h mode, the definition of the internal dependent
     955             :   // base class must remain in the header, and can never be out-lined. The
     956             :   // dependent base class also needs access to has-bit manipuation
     957             :   // functions, so the has-bit functions must be unconditionally inlined in
     958             :   // proto_h mode.
     959             :   //
     960             :   // This gives us three flavors of functions:
     961             :   //
     962             :   //  1. Functions on the message not used by the internal dependent base
     963             :   //     class: in .proto.h mode, only some functions are defined on the
     964             :   //     message class; others are defined on the dependent base class.
     965             :   //     These are guarded and can be out-lined. These are generated by
     966             :   //     GenerateInlineMethods, and include has_* bit functions in
     967             :   //     non-proto_h mode.
     968             :   //
     969             :   //  2. Functions on the internal dependent base class: these functions
     970             :   //     are dependent on a template parameter, so they always need to
     971             :   //     remain in the header.
     972             :   //
     973             :   //  3. Functions on the message that are used by the dependent base: the
     974             :   //     dependent base class down casts itself to the message
     975             :   //     implementation class to access these functions (the has_* bit
     976             :   //     manipulation functions). Unlike #1, these functions must
     977             :   //     unconditionally remain in the header. These are emitted by
     978             :   //     GenerateDependentInlineMethods, even though they are not actually
     979             :   //     dependent.
     980             : 
     981          49 :   printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
     982             :   // Generate class inline methods.
     983         582 :   for (int i = 0; i < file_->message_type_count(); i++) {
     984         242 :     if (i > 0) {
     985         197 :       printer->Print(kThinSeparator);
     986         197 :       printer->Print("\n");
     987             :     }
     988         484 :     message_generators_[i]->GenerateInlineMethods(printer,
     989         242 :                                                   /* is_inline = */ true);
     990             :   }
     991          49 :   printer->Print("#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
     992             : 
     993         582 :   for (int i = 0; i < file_->message_type_count(); i++) {
     994         242 :     if (i > 0) {
     995         197 :       printer->Print(kThinSeparator);
     996         197 :       printer->Print("\n");
     997             :     }
     998             :     // Methods of the dependent base class must always be inline in the header.
     999         726 :     message_generators_[i]->GenerateDependentInlineMethods(printer);
    1000             :   }
    1001          49 : }
    1002             : 
    1003          49 : void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
    1004             :     io::Printer* printer) {
    1005             :   // Emit GetEnumDescriptor specializations into google::protobuf namespace:
    1006         308 :   if (HasEnumDefinitions(file_)) {
    1007             :     // The SWIG conditional is to avoid a null-pointer dereference
    1008             :     // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
    1009             :     //   namespace X { void Y<Z::W>(); }
    1010             :     // which appears in GetEnumDescriptor() specializations.
    1011             :     printer->Print(
    1012             :         "\n"
    1013             :         "#ifndef SWIG\n"
    1014             :         "namespace google {\nnamespace protobuf {\n"
    1015          21 :         "\n");
    1016         416 :     for (int i = 0; i < file_->message_type_count(); i++) {
    1017         561 :       message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
    1018             :     }
    1019          81 :     for (int i = 0; i < file_->enum_type_count(); i++) {
    1020          90 :       enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
    1021             :     }
    1022             :     printer->Print(
    1023             :         "\n"
    1024             :         "}  // namespace protobuf\n}  // namespace google\n"
    1025          21 :         "#endif  // SWIG\n");
    1026             :   }
    1027          49 : }
    1028             : 
    1029             : }  // namespace cpp
    1030             : }  // namespace compiler
    1031             : }  // namespace protobuf
    1032             : }  // namespace google

Generated by: LCOV version 1.10