| 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/file.h> | 
| 36 |  | 
| 37 | #include <iostream> | 
| 38 | #include <map> | 
| 39 | #include <memory> | 
| 40 | #include <set> | 
| 41 | #include <unordered_map> | 
| 42 | #include <unordered_set> | 
| 43 | #include <vector> | 
| 44 |  | 
| 45 | #include <google/protobuf/compiler/scc.h> | 
| 46 | #include <google/protobuf/io/printer.h> | 
| 47 | #include <google/protobuf/stubs/strutil.h> | 
| 48 | #include <google/protobuf/compiler/cpp/enum.h> | 
| 49 | #include <google/protobuf/compiler/cpp/extension.h> | 
| 50 | #include <google/protobuf/compiler/cpp/field.h> | 
| 51 | #include <google/protobuf/compiler/cpp/helpers.h> | 
| 52 | #include <google/protobuf/compiler/cpp/message.h> | 
| 53 | #include <google/protobuf/compiler/cpp/service.h> | 
| 54 | #include <google/protobuf/descriptor.pb.h> | 
| 55 |  | 
| 56 | // Must be last. | 
| 57 | #include <google/protobuf/port_def.inc> | 
| 58 |  | 
| 59 | namespace google { | 
| 60 | namespace protobuf { | 
| 61 | namespace compiler { | 
| 62 | namespace cpp { | 
| 63 |  | 
| 64 | namespace { | 
| 65 |  | 
| 66 | // When we forward-declare things, we want to create a sorted order so our | 
| 67 | // output is deterministic and minimizes namespace changes. | 
| 68 | template <class T> | 
| 69 | std::string GetSortKey(const T& val) { | 
| 70 |   return val.full_name(); | 
| 71 | } | 
| 72 |  | 
| 73 | template <> | 
| 74 | std::string GetSortKey<FileDescriptor>(const FileDescriptor& val) { | 
| 75 |   return val.name(); | 
| 76 | } | 
| 77 |  | 
| 78 | template <class T> | 
| 79 | bool CompareSortKeys(const T* a, const T* b) { | 
| 80 |   return GetSortKey(*a) < GetSortKey(*b); | 
| 81 | } | 
| 82 |  | 
| 83 | template <class T> | 
| 84 | std::vector<const T*> Sorted(const std::unordered_set<const T*>& vals) { | 
| 85 |   std::vector<const T*> sorted(vals.begin(), vals.end()); | 
| 86 |   std::sort(sorted.begin(), sorted.end(), CompareSortKeys<T>); | 
| 87 |   return sorted; | 
| 88 | } | 
| 89 |  | 
| 90 | // TODO(b/203101078): remove pragmas that suppresses uninitialized warnings when | 
| 91 | // clang bug is fixed. | 
| 92 | inline void MuteWuninitialized(Formatter& format) { | 
| 93 |   format( | 
| 94 |       "#if defined(__llvm__)\n"  | 
| 95 |       "  #pragma clang diagnostic push\n"  | 
| 96 |       "  #pragma clang diagnostic ignored \"-Wuninitialized\"\n"  | 
| 97 |       "#endif  // __llvm__\n" ); | 
| 98 | } | 
| 99 |  | 
| 100 | inline void UnmuteWuninitialized(Formatter& format) { | 
| 101 |   format( | 
| 102 |       "#if defined(__llvm__)\n"  | 
| 103 |       "  #pragma clang diagnostic pop\n"  | 
| 104 |       "#endif  // __llvm__\n" ); | 
| 105 | } | 
| 106 |  | 
| 107 | }  // namespace | 
| 108 |  | 
| 109 | FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) | 
| 110 |     : file_(file), options_(options), scc_analyzer_(options) { | 
| 111 |   // These variables are the same on a file level | 
| 112 |   SetCommonVars(options, variables: &variables_); | 
| 113 |   variables_["dllexport_decl" ] = options.dllexport_decl; | 
| 114 |   variables_["tablename" ] = UniqueName(name: "TableStruct" , d: file_, options: options_); | 
| 115 |   variables_["file_level_metadata" ] = | 
| 116 |       UniqueName(name: "file_level_metadata" , d: file_, options: options_); | 
| 117 |   variables_["desc_table" ] = DescriptorTableName(file: file_, options: options_); | 
| 118 |   variables_["file_level_enum_descriptors" ] = | 
| 119 |       UniqueName(name: "file_level_enum_descriptors" , d: file_, options: options_); | 
| 120 |   variables_["file_level_service_descriptors" ] = | 
| 121 |       UniqueName(name: "file_level_service_descriptors" , d: file_, options: options_); | 
| 122 |   variables_["filename" ] = file_->name(); | 
| 123 |   variables_["package_ns" ] = Namespace(d: file_, options); | 
| 124 |  | 
| 125 |   std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file); | 
| 126 |   for (int i = 0; i < msgs.size(); i++) { | 
| 127 |     // Deleted in destructor | 
| 128 |     MessageGenerator* msg_gen = | 
| 129 |         new MessageGenerator(msgs[i], variables_, i, options, &scc_analyzer_); | 
| 130 |     message_generators_.emplace_back(args&: msg_gen); | 
| 131 |     msg_gen->AddGenerators(enum_generators: &enum_generators_, extension_generators: &extension_generators_); | 
| 132 |   } | 
| 133 |  | 
| 134 |   for (int i = 0; i < file->enum_type_count(); i++) { | 
| 135 |     enum_generators_.emplace_back( | 
| 136 |         args: new EnumGenerator(file->enum_type(index: i), variables_, options)); | 
| 137 |   } | 
| 138 |  | 
| 139 |   for (int i = 0; i < file->service_count(); i++) { | 
| 140 |     service_generators_.emplace_back( | 
| 141 |         args: new ServiceGenerator(file->service(index: i), variables_, options)); | 
| 142 |   } | 
| 143 |   if (HasGenericServices(file: file_, options: options_)) { | 
| 144 |     for (int i = 0; i < service_generators_.size(); i++) { | 
| 145 |       service_generators_[i]->index_in_metadata_ = i; | 
| 146 |     } | 
| 147 |   } | 
| 148 |   for (int i = 0; i < file->extension_count(); i++) { | 
| 149 |     extension_generators_.emplace_back( | 
| 150 |         args: new ExtensionGenerator(file->extension(index: i), options, &scc_analyzer_)); | 
| 151 |   } | 
| 152 |   for (int i = 0; i < file->weak_dependency_count(); ++i) { | 
| 153 |     weak_deps_.insert(x: file->weak_dependency(index: i)); | 
| 154 |   } | 
| 155 | } | 
| 156 |  | 
| 157 | FileGenerator::~FileGenerator() = default; | 
| 158 |  | 
| 159 | void FileGenerator::GenerateMacroUndefs(io::Printer* printer) { | 
| 160 |   Formatter format(printer, variables_); | 
| 161 |   // Only do this for protobuf's own types. There are some google3 protos using | 
| 162 |   // macros as field names and the generated code compiles after the macro | 
| 163 |   // expansion. Undefing these macros actually breaks such code. | 
| 164 |   if (file_->name() != "net/proto2/compiler/proto/plugin.proto"  && | 
| 165 |       file_->name() != "google/protobuf/compiler/plugin.proto" ) { | 
| 166 |     return; | 
| 167 |   } | 
| 168 |   std::vector<std::string> names_to_undef; | 
| 169 |   std::vector<const FieldDescriptor*> fields; | 
| 170 |   ListAllFields(d: file_, fields: &fields); | 
| 171 |   for (int i = 0; i < fields.size(); i++) { | 
| 172 |     const std::string& name = fields[i]->name(); | 
| 173 |     static const char* kMacroNames[] = {"major" , "minor" }; | 
| 174 |     for (int j = 0; j < GOOGLE_ARRAYSIZE(kMacroNames); ++j) { | 
| 175 |       if (name == kMacroNames[j]) { | 
| 176 |         names_to_undef.push_back(x: name); | 
| 177 |         break; | 
| 178 |       } | 
| 179 |     } | 
| 180 |   } | 
| 181 |   for (int i = 0; i < names_to_undef.size(); ++i) { | 
| 182 |     format( | 
| 183 |         "#ifdef $1$\n"  | 
| 184 |         "#undef $1$\n"  | 
| 185 |         "#endif\n" , | 
| 186 |         names_to_undef[i]); | 
| 187 |   } | 
| 188 | } | 
| 189 |  | 
| 190 | void FileGenerator::(io::Printer* printer) { | 
| 191 |   Formatter format(printer, variables_); | 
| 192 |  | 
| 193 |   // port_def.inc must be included after all other includes. | 
| 194 |   IncludeFile(google3_name: "net/proto2/public/port_def.inc" , printer); | 
| 195 |   format("#define $1$$ dllexport_decl$\n" , FileDllExport(file: file_, options: options_)); | 
| 196 |   GenerateMacroUndefs(printer); | 
| 197 |  | 
| 198 |   // For Any support with lite protos, we need to friend AnyMetadata, so we | 
| 199 |   // forward-declare it here. | 
| 200 |   format( | 
| 201 |       "PROTOBUF_NAMESPACE_OPEN\n"  | 
| 202 |       "namespace internal {\n"  | 
| 203 |       "class AnyMetadata;\n"  | 
| 204 |       "}  // namespace internal\n"  | 
| 205 |       "PROTOBUF_NAMESPACE_CLOSE\n" ); | 
| 206 |  | 
| 207 |   GenerateGlobalStateFunctionDeclarations(printer); | 
| 208 |  | 
| 209 |   GenerateForwardDeclarations(printer); | 
| 210 |  | 
| 211 |   { | 
| 212 |     NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 213 |  | 
| 214 |     format("\n" ); | 
| 215 |  | 
| 216 |     GenerateEnumDefinitions(printer); | 
| 217 |  | 
| 218 |     format(kThickSeparator); | 
| 219 |     format("\n" ); | 
| 220 |  | 
| 221 |     GenerateMessageDefinitions(printer); | 
| 222 |  | 
| 223 |     format("\n" ); | 
| 224 |     format(kThickSeparator); | 
| 225 |     format("\n" ); | 
| 226 |  | 
| 227 |     GenerateServiceDefinitions(printer); | 
| 228 |  | 
| 229 |     GenerateExtensionIdentifiers(printer); | 
| 230 |  | 
| 231 |     format("\n" ); | 
| 232 |     format(kThickSeparator); | 
| 233 |     format("\n" ); | 
| 234 |  | 
| 235 |     GenerateInlineFunctionDefinitions(printer); | 
| 236 |  | 
| 237 |     format( | 
| 238 |         "\n"  | 
| 239 |         "// @@protoc_insertion_point(namespace_scope)\n"  | 
| 240 |         "\n" ); | 
| 241 |   } | 
| 242 |  | 
| 243 |   // We need to specialize some templates in the ::google::protobuf namespace: | 
| 244 |   GenerateProto2NamespaceEnumSpecializations(printer); | 
| 245 |  | 
| 246 |   format( | 
| 247 |       "\n"  | 
| 248 |       "// @@protoc_insertion_point(global_scope)\n"  | 
| 249 |       "\n" ); | 
| 250 |   IncludeFile(google3_name: "net/proto2/public/port_undef.inc" , printer); | 
| 251 | } | 
| 252 |  | 
| 253 | void FileGenerator::(io::Printer* printer, | 
| 254 |                                         const std::string& info_path) { | 
| 255 |   Formatter format(printer, variables_); | 
| 256 |   if (!options_.proto_h) { | 
| 257 |     return; | 
| 258 |   } | 
| 259 |  | 
| 260 |   GenerateTopHeaderGuard(printer, pb_h: false); | 
| 261 |  | 
| 262 |   if (!options_.opensource_runtime) { | 
| 263 |     format( | 
| 264 |         "#ifdef SWIG\n"  | 
| 265 |         "#error \"Do not SWIG-wrap protobufs.\"\n"  | 
| 266 |         "#endif  // SWIG\n"  | 
| 267 |         "\n" ); | 
| 268 |   } | 
| 269 |  | 
| 270 |   if (IsBootstrapProto(options: options_, file: file_)) { | 
| 271 |     format("// IWYU pragma: private, include \"$1$.proto.h\"\n\n" , | 
| 272 |            StripProto(filename: file_->name())); | 
| 273 |   } | 
| 274 |  | 
| 275 |   GenerateLibraryIncludes(printer); | 
| 276 |  | 
| 277 |   for (int i = 0; i < file_->public_dependency_count(); i++) { | 
| 278 |     const FileDescriptor* dep = file_->public_dependency(index: i); | 
| 279 |     format("#include \"$1$.proto.h\"\n" , StripProto(filename: dep->name())); | 
| 280 |   } | 
| 281 |  | 
| 282 |   format("// @@protoc_insertion_point(includes)\n" ); | 
| 283 |  | 
| 284 |   GenerateMetadataPragma(printer, info_path); | 
| 285 |  | 
| 286 |   GenerateHeader(printer); | 
| 287 |  | 
| 288 |   GenerateBottomHeaderGuard(printer, pb_h: false); | 
| 289 | } | 
| 290 |  | 
| 291 | void FileGenerator::(io::Printer* printer, | 
| 292 |                                      const std::string& info_path) { | 
| 293 |   Formatter format(printer, variables_); | 
| 294 |   GenerateTopHeaderGuard(printer, pb_h: true); | 
| 295 |  | 
| 296 |   if (options_.proto_h) { | 
| 297 |     std::string target_basename = StripProto(filename: file_->name()); | 
| 298 |     if (!options_.opensource_runtime) { | 
| 299 |       GetBootstrapBasename(options: options_, basename: target_basename, bootstrap_basename: &target_basename); | 
| 300 |     } | 
| 301 |     format("#include \"$1$.proto.h\"  // IWYU pragma: export\n" , | 
| 302 |            target_basename); | 
| 303 |   } else { | 
| 304 |     GenerateLibraryIncludes(printer); | 
| 305 |   } | 
| 306 |  | 
| 307 |   if (options_.transitive_pb_h) { | 
| 308 |     GenerateDependencyIncludes(printer); | 
| 309 |   } | 
| 310 |  | 
| 311 |   // This is unfortunately necessary for some plugins. I don't see why we | 
| 312 |   // need two of the same insertion points. | 
| 313 |   // TODO(gerbens) remove this. | 
| 314 |   format("// @@protoc_insertion_point(includes)\n" ); | 
| 315 |  | 
| 316 |   GenerateMetadataPragma(printer, info_path); | 
| 317 |  | 
| 318 |   if (!options_.proto_h) { | 
| 319 |     GenerateHeader(printer); | 
| 320 |   } else { | 
| 321 |     { | 
| 322 |       NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 323 |       format( | 
| 324 |           "\n"  | 
| 325 |           "// @@protoc_insertion_point(namespace_scope)\n" ); | 
| 326 |     } | 
| 327 |     format( | 
| 328 |         "\n"  | 
| 329 |         "// @@protoc_insertion_point(global_scope)\n"  | 
| 330 |         "\n" ); | 
| 331 |   } | 
| 332 |  | 
| 333 |   GenerateBottomHeaderGuard(printer, pb_h: true); | 
| 334 | } | 
| 335 |  | 
| 336 | void FileGenerator::DoIncludeFile(const std::string& google3_name, | 
| 337 |                                   bool do_export, io::Printer* printer) { | 
| 338 |   Formatter format(printer, variables_); | 
| 339 |   const std::string prefix = "net/proto2/" ; | 
| 340 |   GOOGLE_CHECK(google3_name.find(prefix) == 0) << google3_name; | 
| 341 |  | 
| 342 |   if (options_.opensource_runtime) { | 
| 343 |     std::string path = google3_name.substr(pos: prefix.size()); | 
| 344 |  | 
| 345 |     path = StringReplace(s: path, oldsub: "internal/" , newsub: "" , replace_all: false); | 
| 346 |     path = StringReplace(s: path, oldsub: "proto/" , newsub: "" , replace_all: false); | 
| 347 |     path = StringReplace(s: path, oldsub: "public/" , newsub: "" , replace_all: false); | 
| 348 |     if (options_.runtime_include_base.empty()) { | 
| 349 |       format("#include <google/protobuf/$1$>" , path); | 
| 350 |     } else { | 
| 351 |       format("#include \"$1$google/protobuf/$2$\"" , | 
| 352 |              options_.runtime_include_base, path); | 
| 353 |     } | 
| 354 |   } else { | 
| 355 |     std::string path = google3_name; | 
| 356 |     // The bootstrapped proto generated code needs to use the | 
| 357 |     // third_party/protobuf header paths to avoid circular dependencies. | 
| 358 |     if (options_.bootstrap) { | 
| 359 |       path = StringReplace(s: google3_name, oldsub: "net/proto2/public" , | 
| 360 |                            newsub: "third_party/protobuf" , replace_all: false); | 
| 361 |     } | 
| 362 |     format("#include \"$1$\"" , path); | 
| 363 |   } | 
| 364 |  | 
| 365 |   if (do_export) { | 
| 366 |     format("  // IWYU pragma: export" ); | 
| 367 |   } | 
| 368 |  | 
| 369 |   format("\n" ); | 
| 370 | } | 
| 371 |  | 
| 372 | std::string FileGenerator::(const std::string& basename, | 
| 373 |                                                const FileDescriptor* file) { | 
| 374 |   bool use_system_include = false; | 
| 375 |   std::string name = basename; | 
| 376 |  | 
| 377 |   if (options_.opensource_runtime) { | 
| 378 |     if (IsWellKnownMessage(descriptor: file)) { | 
| 379 |       if (options_.runtime_include_base.empty()) { | 
| 380 |         use_system_include = true; | 
| 381 |       } else { | 
| 382 |         name = options_.runtime_include_base + basename; | 
| 383 |       } | 
| 384 |     } | 
| 385 |   } | 
| 386 |  | 
| 387 |   std::string left = "\"" ; | 
| 388 |   std::string right = "\"" ; | 
| 389 |   if (use_system_include) { | 
| 390 |     left = "<" ; | 
| 391 |     right = ">" ; | 
| 392 |   } | 
| 393 |   return left + name + right; | 
| 394 | } | 
| 395 |  | 
| 396 | void FileGenerator::GenerateSourceIncludes(io::Printer* printer) { | 
| 397 |   Formatter format(printer, variables_); | 
| 398 |   std::string target_basename = StripProto(filename: file_->name()); | 
| 399 |   if (!options_.opensource_runtime) { | 
| 400 |     GetBootstrapBasename(options: options_, basename: target_basename, bootstrap_basename: &target_basename); | 
| 401 |   } | 
| 402 |   target_basename += options_.proto_h ? ".proto.h"  : ".pb.h" ; | 
| 403 |   format( | 
| 404 |       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"  | 
| 405 |       "// source: $filename$\n"  | 
| 406 |       "\n"  | 
| 407 |       "#include $1$\n"  | 
| 408 |       "\n"  | 
| 409 |       "#include <algorithm>\n"   // for swap() | 
| 410 |       "\n" , | 
| 411 |       CreateHeaderInclude(basename: target_basename, file: file_)); | 
| 412 |  | 
| 413 |   IncludeFile(google3_name: "net/proto2/io/public/coded_stream.h" , printer); | 
| 414 |   // TODO(gerbens) This is to include parse_context.h, we need a better way | 
| 415 |   IncludeFile(google3_name: "net/proto2/public/extension_set.h" , printer); | 
| 416 |   IncludeFile(google3_name: "net/proto2/public/wire_format_lite.h" , printer); | 
| 417 |  | 
| 418 |   // Unknown fields implementation in lite mode uses StringOutputStream | 
| 419 |   if (!UseUnknownFieldSet(file: file_, options: options_) && !message_generators_.empty()) { | 
| 420 |     IncludeFile(google3_name: "net/proto2/io/public/zero_copy_stream_impl_lite.h" , printer); | 
| 421 |   } | 
| 422 |  | 
| 423 |   if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 424 |     IncludeFile(google3_name: "net/proto2/public/descriptor.h" , printer); | 
| 425 |     IncludeFile(google3_name: "net/proto2/public/generated_message_reflection.h" , printer); | 
| 426 |     IncludeFile(google3_name: "net/proto2/public/reflection_ops.h" , printer); | 
| 427 |     IncludeFile(google3_name: "net/proto2/public/wire_format.h" , printer); | 
| 428 |   } | 
| 429 |  | 
| 430 |   if (HasGeneratedMethods(file: file_, options: options_) && | 
| 431 |       options_.tctable_mode != Options::kTCTableNever) { | 
| 432 |     IncludeFile(google3_name: "net/proto2/public/generated_message_tctable_impl.h" , printer); | 
| 433 |   } | 
| 434 |  | 
| 435 |   if (options_.proto_h) { | 
| 436 |     // Use the smaller .proto.h files. | 
| 437 |     for (int i = 0; i < file_->dependency_count(); i++) { | 
| 438 |       const FileDescriptor* dep = file_->dependency(index: i); | 
| 439 |       // Do not import weak deps. | 
| 440 |       if (!options_.opensource_runtime && IsDepWeak(dep)) continue; | 
| 441 |       std::string basename = StripProto(filename: dep->name()); | 
| 442 |       if (IsBootstrapProto(options: options_, file: file_)) { | 
| 443 |         GetBootstrapBasename(options: options_, basename, bootstrap_basename: &basename); | 
| 444 |       } | 
| 445 |       format("#include \"$1$.proto.h\"\n" , basename); | 
| 446 |     } | 
| 447 |   } | 
| 448 |   if (HasCordFields(file: file_, options: options_)) { | 
| 449 |     format( | 
| 450 |         "#include \"third_party/absl/strings/internal/string_constant.h\"\n" ); | 
| 451 |   } | 
| 452 |  | 
| 453 |   format("// @@protoc_insertion_point(includes)\n" ); | 
| 454 |   IncludeFile(google3_name: "net/proto2/public/port_def.inc" , printer); | 
| 455 | } | 
| 456 |  | 
| 457 | void FileGenerator::GenerateSourcePrelude(io::Printer* printer) { | 
| 458 |   Formatter format(printer, variables_); | 
| 459 |  | 
| 460 |   // For MSVC builds, we use #pragma init_seg to move the initialization of our | 
| 461 |   // libraries to happen before the user code. | 
| 462 |   // This worksaround the fact that MSVC does not do constant initializers when | 
| 463 |   // required by the standard. | 
| 464 |   format("\nPROTOBUF_PRAGMA_INIT_SEG\n" ); | 
| 465 |  | 
| 466 |   // Generate convenience aliases. | 
| 467 |   format( | 
| 468 |       "\n"  | 
| 469 |       "namespace _pb = ::$1$;\n"  | 
| 470 |       "namespace _pbi = _pb::internal;\n" , | 
| 471 |       ProtobufNamespace(options_)); | 
| 472 |   if (HasGeneratedMethods(file: file_, options: options_) && | 
| 473 |       options_.tctable_mode != Options::kTCTableNever) { | 
| 474 |     format("namespace _fl = _pbi::field_layout;\n" ); | 
| 475 |   } | 
| 476 |   format("\n" ); | 
| 477 | } | 
| 478 |  | 
| 479 | void FileGenerator::GenerateSourceDefaultInstance(int idx, | 
| 480 |                                                   io::Printer* printer) { | 
| 481 |   Formatter format(printer, variables_); | 
| 482 |   MessageGenerator* generator = message_generators_[idx].get(); | 
| 483 |   // Generate the split instance first because it's needed in the constexpr | 
| 484 |   // constructor. | 
| 485 |   if (ShouldSplit(desc: generator->descriptor_, options: options_)) { | 
| 486 |     // Use a union to disable the destructor of the _instance member. | 
| 487 |     // We can constant initialize, but the object will still have a non-trivial | 
| 488 |     // destructor that we need to elide. | 
| 489 |     format( | 
| 490 |         "struct $1$ {\n"  | 
| 491 |         "  PROTOBUF_CONSTEXPR $1$()\n"  | 
| 492 |         "      : _instance{" , | 
| 493 |         DefaultInstanceType(descriptor: generator->descriptor_, options: options_, | 
| 494 |                             /*split=*/true)); | 
| 495 |     generator->GenerateInitDefaultSplitInstance(printer); | 
| 496 |     format( | 
| 497 |         "} {}\n"  | 
| 498 |         "  ~$1$() {}\n"  | 
| 499 |         "  union {\n"  | 
| 500 |         "    $2$ _instance;\n"  | 
| 501 |         "  };\n"  | 
| 502 |         "};\n" , | 
| 503 |         DefaultInstanceType(descriptor: generator->descriptor_, options: options_, /*split=*/true), | 
| 504 |         StrCat(a: generator->classname_, b: "::Impl_::Split" )); | 
| 505 |     // NO_DESTROY is not necessary for correctness. The empty destructor is | 
| 506 |     // enough. However, the empty destructor fails to be elided in some | 
| 507 |     // configurations (like non-opt or with certain sanitizers). NO_DESTROY is | 
| 508 |     // there just to improve performance and binary size in these builds. | 
| 509 |     format( | 
| 510 |         "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT "  | 
| 511 |         "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n" , | 
| 512 |         DefaultInstanceType(descriptor: generator->descriptor_, options: options_, /*split=*/true), | 
| 513 |         DefaultInstanceName(descriptor: generator->descriptor_, options: options_, /*split=*/true)); | 
| 514 |   } | 
| 515 |  | 
| 516 |   generator->GenerateConstexprConstructor(printer); | 
| 517 |   format( | 
| 518 |       "struct $1$ {\n"  | 
| 519 |       "  PROTOBUF_CONSTEXPR $1$()\n"  | 
| 520 |       "      : _instance(::_pbi::ConstantInitialized{}) {}\n"  | 
| 521 |       "  ~$1$() {}\n"  | 
| 522 |       "  union {\n"  | 
| 523 |       "    $2$ _instance;\n"  | 
| 524 |       "  };\n"  | 
| 525 |       "};\n" , | 
| 526 |       DefaultInstanceType(descriptor: generator->descriptor_, options: options_), | 
| 527 |       generator->classname_); | 
| 528 |   format( | 
| 529 |       "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT "  | 
| 530 |       "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n" , | 
| 531 |       DefaultInstanceType(descriptor: generator->descriptor_, options: options_), | 
| 532 |       DefaultInstanceName(descriptor: generator->descriptor_, options: options_)); | 
| 533 |  | 
| 534 |   for (int i = 0; i < generator->descriptor_->field_count(); i++) { | 
| 535 |     const FieldDescriptor* field = generator->descriptor_->field(index: i); | 
| 536 |     if (IsStringInlined(descriptor: field, options: options_)) { | 
| 537 |       // Force the initialization of the inlined string in the default instance. | 
| 538 |       format( | 
| 539 |           "PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type "  | 
| 540 |           "$1$::Impl_::_init_inline_$2$_ = "  | 
| 541 |           "($3$._instance.$4$.Init(), std::true_type{});\n" , | 
| 542 |           ClassName(descriptor: generator->descriptor_), FieldName(field), | 
| 543 |           DefaultInstanceName(descriptor: generator->descriptor_, options: options_), | 
| 544 |           FieldMemberName(field, split: ShouldSplit(field, options: options_))); | 
| 545 |     } | 
| 546 |   } | 
| 547 |  | 
| 548 |   if (options_.lite_implicit_weak_fields) { | 
| 549 |     format( | 
| 550 |         "PROTOBUF_CONSTINIT const void* $1$ =\n"  | 
| 551 |         "    &$2$;\n" , | 
| 552 |         DefaultInstancePtr(descriptor: generator->descriptor_, options: options_), | 
| 553 |         DefaultInstanceName(descriptor: generator->descriptor_, options: options_)); | 
| 554 |   } | 
| 555 | } | 
| 556 |  | 
| 557 | // A list of things defined in one .pb.cc file that we need to reference from | 
| 558 | // another .pb.cc file. | 
| 559 | struct FileGenerator::CrossFileReferences { | 
| 560 |   // Populated if we are referencing from messages or files. | 
| 561 |   std::unordered_set<const Descriptor*> weak_default_instances; | 
| 562 |  | 
| 563 |   // Only if we are referencing from files. | 
| 564 |   std::unordered_set<const FileDescriptor*> strong_reflection_files; | 
| 565 |   std::unordered_set<const FileDescriptor*> weak_reflection_files; | 
| 566 | }; | 
| 567 |  | 
| 568 | void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field, | 
| 569 |                                                    CrossFileReferences* refs) { | 
| 570 |   const Descriptor* msg = field->message_type(); | 
| 571 |   if (msg == nullptr) return; | 
| 572 |  | 
| 573 |   if (IsImplicitWeakField(field, options: options_, scc_analyzer: &scc_analyzer_) || | 
| 574 |       IsWeak(field, options: options_)) { | 
| 575 |     refs->weak_default_instances.insert(x: msg); | 
| 576 |   } | 
| 577 | } | 
| 578 |  | 
| 579 | void FileGenerator::GetCrossFileReferencesForFile(const FileDescriptor* file, | 
| 580 |                                                   CrossFileReferences* refs) { | 
| 581 |   ForEachField(d: file, func: [this, refs](const FieldDescriptor* field) { | 
| 582 |     GetCrossFileReferencesForField(field, refs); | 
| 583 |   }); | 
| 584 |  | 
| 585 |   if (!HasDescriptorMethods(file, options: options_)) return; | 
| 586 |  | 
| 587 |   for (int i = 0; i < file->dependency_count(); i++) { | 
| 588 |     const FileDescriptor* dep = file->dependency(index: i); | 
| 589 |     if (IsDepWeak(dep)) { | 
| 590 |       refs->weak_reflection_files.insert(x: dep); | 
| 591 |     } else { | 
| 592 |       refs->strong_reflection_files.insert(x: dep); | 
| 593 |     } | 
| 594 |   } | 
| 595 | } | 
| 596 |  | 
| 597 | // Generates references to variables defined in other files. | 
| 598 | void FileGenerator::GenerateInternalForwardDeclarations( | 
| 599 |     const CrossFileReferences& refs, io::Printer* printer) { | 
| 600 |   Formatter format(printer, variables_); | 
| 601 |  | 
| 602 |   { | 
| 603 |     NamespaceOpener ns(format); | 
| 604 |     for (auto instance : Sorted(vals: refs.weak_default_instances)) { | 
| 605 |       ns.ChangeTo(name: Namespace(d: instance, options: options_)); | 
| 606 |       if (options_.lite_implicit_weak_fields) { | 
| 607 |         format( | 
| 608 |             "PROTOBUF_CONSTINIT __attribute__((weak)) const void* $1$ =\n"  | 
| 609 |             "    &::_pbi::implicit_weak_message_default_instance;\n" , | 
| 610 |             DefaultInstancePtr(descriptor: instance, options: options_)); | 
| 611 |       } else { | 
| 612 |         format("extern __attribute__((weak)) $1$ $2$;\n" , | 
| 613 |                DefaultInstanceType(descriptor: instance, options: options_), | 
| 614 |                DefaultInstanceName(descriptor: instance, options: options_)); | 
| 615 |       } | 
| 616 |     } | 
| 617 |   } | 
| 618 |  | 
| 619 |   for (auto file : Sorted(vals: refs.weak_reflection_files)) { | 
| 620 |     format( | 
| 621 |         "extern __attribute__((weak)) const ::_pbi::DescriptorTable $1$;\n" , | 
| 622 |         DescriptorTableName(file, options: options_)); | 
| 623 |   } | 
| 624 | } | 
| 625 |  | 
| 626 | void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { | 
| 627 |   Formatter format(printer, variables_); | 
| 628 |   GenerateSourceIncludes(printer); | 
| 629 |   GenerateSourcePrelude(printer); | 
| 630 |  | 
| 631 |   if (IsAnyMessage(descriptor: file_, options: options_)) MuteWuninitialized(format); | 
| 632 |  | 
| 633 |   CrossFileReferences refs; | 
| 634 |   ForEachField(d: message_generators_[idx]->descriptor_, | 
| 635 |                func: [this, &refs](const FieldDescriptor* field) { | 
| 636 |                  GetCrossFileReferencesForField(field, refs: &refs); | 
| 637 |                }); | 
| 638 |   GenerateInternalForwardDeclarations(refs, printer); | 
| 639 |  | 
| 640 |   {  // package namespace | 
| 641 |     NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 642 |  | 
| 643 |     // Define default instances | 
| 644 |     GenerateSourceDefaultInstance(idx, printer); | 
| 645 |  | 
| 646 |     // Generate classes. | 
| 647 |     format("\n" ); | 
| 648 |     message_generators_[idx]->GenerateClassMethods(printer); | 
| 649 |  | 
| 650 |     format( | 
| 651 |         "\n"  | 
| 652 |         "// @@protoc_insertion_point(namespace_scope)\n" ); | 
| 653 |   }  // end package namespace | 
| 654 |  | 
| 655 |   { | 
| 656 |     NamespaceOpener proto_ns(ProtobufNamespace(options_), format); | 
| 657 |     message_generators_[idx]->GenerateSourceInProto2Namespace(printer); | 
| 658 |   } | 
| 659 |  | 
| 660 |   if (IsAnyMessage(descriptor: file_, options: options_)) UnmuteWuninitialized(format); | 
| 661 |  | 
| 662 |   format( | 
| 663 |       "\n"  | 
| 664 |       "// @@protoc_insertion_point(global_scope)\n" ); | 
| 665 | } | 
| 666 |  | 
| 667 | void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* printer) { | 
| 668 |   Formatter format(printer, variables_); | 
| 669 |   GenerateSourceIncludes(printer); | 
| 670 |   GenerateSourcePrelude(printer); | 
| 671 |   NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 672 |   extension_generators_[idx]->GenerateDefinition(printer); | 
| 673 | } | 
| 674 |  | 
| 675 | void FileGenerator::GenerateGlobalSource(io::Printer* printer) { | 
| 676 |   Formatter format(printer, variables_); | 
| 677 |   GenerateSourceIncludes(printer); | 
| 678 |   GenerateSourcePrelude(printer); | 
| 679 |  | 
| 680 |   { | 
| 681 |     // Define the code to initialize reflection. This code uses a global | 
| 682 |     // constructor to register reflection data with the runtime pre-main. | 
| 683 |     if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 684 |       GenerateReflectionInitializationCode(printer); | 
| 685 |     } | 
| 686 |   } | 
| 687 |  | 
| 688 |   NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 689 |  | 
| 690 |   // Generate enums. | 
| 691 |   for (int i = 0; i < enum_generators_.size(); i++) { | 
| 692 |     enum_generators_[i]->GenerateMethods(idx: i, printer); | 
| 693 |   } | 
| 694 | } | 
| 695 |  | 
| 696 | void FileGenerator::GenerateSource(io::Printer* printer) { | 
| 697 |   Formatter format(printer, variables_); | 
| 698 |   GenerateSourceIncludes(printer); | 
| 699 |   GenerateSourcePrelude(printer); | 
| 700 |   CrossFileReferences refs; | 
| 701 |   GetCrossFileReferencesForFile(file: file_, refs: &refs); | 
| 702 |   GenerateInternalForwardDeclarations(refs, printer); | 
| 703 |  | 
| 704 |   if (IsAnyMessage(descriptor: file_, options: options_)) MuteWuninitialized(format); | 
| 705 |  | 
| 706 |   { | 
| 707 |     NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 708 |  | 
| 709 |     // Define default instances | 
| 710 |     for (int i = 0; i < message_generators_.size(); i++) { | 
| 711 |       GenerateSourceDefaultInstance(idx: i, printer); | 
| 712 |     } | 
| 713 |   } | 
| 714 |  | 
| 715 |   { | 
| 716 |     if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 717 |       // Define the code to initialize reflection. This code uses a global | 
| 718 |       // constructor to register reflection data with the runtime pre-main. | 
| 719 |       GenerateReflectionInitializationCode(printer); | 
| 720 |     } | 
| 721 |   } | 
| 722 |  | 
| 723 |   { | 
| 724 |     NamespaceOpener ns(Namespace(d: file_, options: options_), format); | 
| 725 |  | 
| 726 |     // Actually implement the protos | 
| 727 |  | 
| 728 |     // Generate enums. | 
| 729 |     for (int i = 0; i < enum_generators_.size(); i++) { | 
| 730 |       enum_generators_[i]->GenerateMethods(idx: i, printer); | 
| 731 |     } | 
| 732 |  | 
| 733 |     // Generate classes. | 
| 734 |     for (int i = 0; i < message_generators_.size(); i++) { | 
| 735 |       format("\n" ); | 
| 736 |       format(kThickSeparator); | 
| 737 |       format("\n" ); | 
| 738 |       message_generators_[i]->GenerateClassMethods(printer); | 
| 739 |     } | 
| 740 |  | 
| 741 |     if (HasGenericServices(file: file_, options: options_)) { | 
| 742 |       // Generate services. | 
| 743 |       for (int i = 0; i < service_generators_.size(); i++) { | 
| 744 |         if (i == 0) format("\n" ); | 
| 745 |         format(kThickSeparator); | 
| 746 |         format("\n" ); | 
| 747 |         service_generators_[i]->GenerateImplementation(printer); | 
| 748 |       } | 
| 749 |     } | 
| 750 |  | 
| 751 |     // Define extensions. | 
| 752 |     for (int i = 0; i < extension_generators_.size(); i++) { | 
| 753 |       extension_generators_[i]->GenerateDefinition(printer); | 
| 754 |     } | 
| 755 |  | 
| 756 |     format( | 
| 757 |         "\n"  | 
| 758 |         "// @@protoc_insertion_point(namespace_scope)\n" ); | 
| 759 |   } | 
| 760 |  | 
| 761 |   { | 
| 762 |     NamespaceOpener proto_ns(ProtobufNamespace(options_), format); | 
| 763 |     for (int i = 0; i < message_generators_.size(); i++) { | 
| 764 |       message_generators_[i]->GenerateSourceInProto2Namespace(printer); | 
| 765 |     } | 
| 766 |   } | 
| 767 |  | 
| 768 |   format( | 
| 769 |       "\n"  | 
| 770 |       "// @@protoc_insertion_point(global_scope)\n" ); | 
| 771 |  | 
| 772 |   if (IsAnyMessage(descriptor: file_, options: options_)) UnmuteWuninitialized(format); | 
| 773 |  | 
| 774 |   IncludeFile(google3_name: "net/proto2/public/port_undef.inc" , printer); | 
| 775 | } | 
| 776 |  | 
| 777 | void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { | 
| 778 |   Formatter format(printer, variables_); | 
| 779 |  | 
| 780 |   if (!message_generators_.empty()) { | 
| 781 |     format("static ::_pb::Metadata $file_level_metadata$[$1$];\n" , | 
| 782 |            message_generators_.size()); | 
| 783 |   } | 
| 784 |   if (!enum_generators_.empty()) { | 
| 785 |     format( | 
| 786 |         "static const ::_pb::EnumDescriptor* "  | 
| 787 |         "$file_level_enum_descriptors$[$1$];\n" , | 
| 788 |         enum_generators_.size()); | 
| 789 |   } else { | 
| 790 |     format( | 
| 791 |         "static "  | 
| 792 |         "constexpr ::_pb::EnumDescriptor const** "  | 
| 793 |         "$file_level_enum_descriptors$ = nullptr;\n" ); | 
| 794 |   } | 
| 795 |   if (HasGenericServices(file: file_, options: options_) && file_->service_count() > 0) { | 
| 796 |     format( | 
| 797 |         "static "  | 
| 798 |         "const ::_pb::ServiceDescriptor* "  | 
| 799 |         "$file_level_service_descriptors$[$1$];\n" , | 
| 800 |         file_->service_count()); | 
| 801 |   } else { | 
| 802 |     format( | 
| 803 |         "static "  | 
| 804 |         "constexpr ::_pb::ServiceDescriptor const** "  | 
| 805 |         "$file_level_service_descriptors$ = nullptr;\n" ); | 
| 806 |   } | 
| 807 |  | 
| 808 |   if (!message_generators_.empty()) { | 
| 809 |     format( | 
| 810 |         "\n"  | 
| 811 |         "const $uint32$ $tablename$::offsets[] "  | 
| 812 |         "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n" ); | 
| 813 |     format.Indent(); | 
| 814 |     std::vector<std::pair<size_t, size_t> > pairs; | 
| 815 |     pairs.reserve(n: message_generators_.size()); | 
| 816 |     for (int i = 0; i < message_generators_.size(); i++) { | 
| 817 |       pairs.push_back(x: message_generators_[i]->GenerateOffsets(printer)); | 
| 818 |     } | 
| 819 |     format.Outdent(); | 
| 820 |     format( | 
| 821 |         "};\n"  | 
| 822 |         "static const ::_pbi::MigrationSchema schemas[] "  | 
| 823 |         "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n" ); | 
| 824 |     format.Indent(); | 
| 825 |     { | 
| 826 |       int offset = 0; | 
| 827 |       for (int i = 0; i < message_generators_.size(); i++) { | 
| 828 |         message_generators_[i]->GenerateSchema(printer, offset, | 
| 829 |                                                has_offset: pairs[i].second); | 
| 830 |         offset += pairs[i].first; | 
| 831 |       } | 
| 832 |     } | 
| 833 |     format.Outdent(); | 
| 834 |     format( | 
| 835 |         "};\n"  | 
| 836 |         "\nstatic const ::_pb::Message* const file_default_instances[] = {\n" ); | 
| 837 |     format.Indent(); | 
| 838 |     for (int i = 0; i < message_generators_.size(); i++) { | 
| 839 |       const Descriptor* descriptor = message_generators_[i]->descriptor_; | 
| 840 |       format("&$1$::_$2$_default_instance_._instance,\n" , | 
| 841 |              Namespace(d: descriptor, options: options_),  // 1 | 
| 842 |              ClassName(descriptor));           // 2 | 
| 843 |     } | 
| 844 |     format.Outdent(); | 
| 845 |     format( | 
| 846 |         "};\n"  | 
| 847 |         "\n" ); | 
| 848 |   } else { | 
| 849 |     // we still need these symbols to exist | 
| 850 |     format( | 
| 851 |         // MSVC doesn't like empty arrays, so we add a dummy. | 
| 852 |         "const $uint32$ $tablename$::offsets[1] = {};\n"  | 
| 853 |         "static constexpr ::_pbi::MigrationSchema* schemas = nullptr;\n"  | 
| 854 |         "static constexpr ::_pb::Message* const* "  | 
| 855 |         "file_default_instances = nullptr;\n"  | 
| 856 |         "\n" ); | 
| 857 |   } | 
| 858 |  | 
| 859 |   // --------------------------------------------------------------- | 
| 860 |  | 
| 861 |   // Embed the descriptor.  We simply serialize the entire | 
| 862 |   // FileDescriptorProto/ and embed it as a string literal, which is parsed and | 
| 863 |   // built into real descriptors at initialization time. | 
| 864 |   const std::string protodef_name = | 
| 865 |       UniqueName(name: "descriptor_table_protodef" , d: file_, options: options_); | 
| 866 |   format("const char $1$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =\n" , | 
| 867 |          protodef_name); | 
| 868 |   format.Indent(); | 
| 869 |   FileDescriptorProto file_proto; | 
| 870 |   file_->CopyTo(proto: &file_proto); | 
| 871 |   std::string file_data; | 
| 872 |   file_proto.SerializeToString(output: &file_data); | 
| 873 |  | 
| 874 |   { | 
| 875 |     if (file_data.size() > 65535) { | 
| 876 |       // Workaround for MSVC: "Error C1091: compiler limit: string exceeds | 
| 877 |       // 65535 bytes in length". Declare a static array of chars rather than | 
| 878 |       // use a string literal. Only write 25 bytes per line. | 
| 879 |       static const int kBytesPerLine = 25; | 
| 880 |       format("{ " ); | 
| 881 |       for (int i = 0; i < file_data.size();) { | 
| 882 |         for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { | 
| 883 |           format("'$1$', " , CEscape(src: file_data.substr(pos: i, n: 1))); | 
| 884 |         } | 
| 885 |         format("\n" ); | 
| 886 |       } | 
| 887 |       format("'\\0' }" );  // null-terminate | 
| 888 |     } else { | 
| 889 |       // Only write 40 bytes per line. | 
| 890 |       static const int kBytesPerLine = 40; | 
| 891 |       for (int i = 0; i < file_data.size(); i += kBytesPerLine) { | 
| 892 |         format( | 
| 893 |             "\"$1$\"\n" , | 
| 894 |             EscapeTrigraphs(to_escape: CEscape(src: file_data.substr(pos: i, n: kBytesPerLine)))); | 
| 895 |       } | 
| 896 |     } | 
| 897 |     format(";\n" ); | 
| 898 |   } | 
| 899 |   format.Outdent(); | 
| 900 |  | 
| 901 |   CrossFileReferences refs; | 
| 902 |   GetCrossFileReferencesForFile(file: file_, refs: &refs); | 
| 903 |   int num_deps = | 
| 904 |       refs.strong_reflection_files.size() + refs.weak_reflection_files.size(); | 
| 905 |  | 
| 906 |   // Build array of DescriptorTable deps. | 
| 907 |   if (num_deps > 0) { | 
| 908 |     format( | 
| 909 |         "static const ::_pbi::DescriptorTable* const "  | 
| 910 |         "$desc_table$_deps[$1$] = {\n" , | 
| 911 |         num_deps); | 
| 912 |  | 
| 913 |     for (auto dep : Sorted(vals: refs.strong_reflection_files)) { | 
| 914 |       format("  &::$1$,\n" , DescriptorTableName(file: dep, options: options_)); | 
| 915 |     } | 
| 916 |     for (auto dep : Sorted(vals: refs.weak_reflection_files)) { | 
| 917 |       format("  &::$1$,\n" , DescriptorTableName(file: dep, options: options_)); | 
| 918 |     } | 
| 919 |  | 
| 920 |     format("};\n" ); | 
| 921 |   } | 
| 922 |  | 
| 923 |   // The DescriptorTable itself. | 
| 924 |   // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);" | 
| 925 |   // however this might cause a tsan failure in superroot b/148382879, | 
| 926 |   // so disable for now. | 
| 927 |   bool eager = false; | 
| 928 |   format( | 
| 929 |       "static ::_pbi::once_flag $desc_table$_once;\n"  | 
| 930 |       "const ::_pbi::DescriptorTable $desc_table$ = {\n"  | 
| 931 |       "    false, $1$, $2$, $3$,\n"  | 
| 932 |       "    \"$filename$\",\n"  | 
| 933 |       "    &$desc_table$_once, $4$, $5$, $6$,\n"  | 
| 934 |       "    schemas, file_default_instances, $tablename$::offsets,\n"  | 
| 935 |       "    $7$, $file_level_enum_descriptors$,\n"  | 
| 936 |       "    $file_level_service_descriptors$,\n"  | 
| 937 |       "};\n"  | 
| 938 |       // This function exists to be marked as weak. | 
| 939 |       // It can significantly speed up compilation by breaking up LLVM's SCC in | 
| 940 |       // the .pb.cc translation units. Large translation units see a reduction | 
| 941 |       // of more than 35% of walltime for optimized builds. | 
| 942 |       // Without the weak attribute all the messages in the file, including all | 
| 943 |       // the vtables and everything they use become part of the same SCC through | 
| 944 |       // a cycle like: | 
| 945 |       // GetMetadata -> descriptor table -> default instances -> | 
| 946 |       //   vtables -> GetMetadata | 
| 947 |       // By adding a weak function here we break the connection from the | 
| 948 |       // individual vtables back into the descriptor table. | 
| 949 |       "PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* "  | 
| 950 |       "$desc_table$_getter() {\n"  | 
| 951 |       "  return &$desc_table$;\n"  | 
| 952 |       "}\n"  | 
| 953 |       "\n" , | 
| 954 |       eager ? "true"  : "false" , file_data.size(), protodef_name, | 
| 955 |       num_deps == 0 ? "nullptr"  : variables_["desc_table" ] + "_deps" , num_deps, | 
| 956 |       message_generators_.size(), | 
| 957 |       message_generators_.empty() ? "nullptr"  | 
| 958 |                                   : variables_["file_level_metadata" ]); | 
| 959 |  | 
| 960 |   // For descriptor.proto we want to avoid doing any dynamic initialization, | 
| 961 |   // because in some situations that would otherwise pull in a lot of | 
| 962 |   // unnecessary code that can't be stripped by --gc-sections. Descriptor | 
| 963 |   // initialization will still be performed lazily when it's needed. | 
| 964 |   if (file_->name() != "net/proto2/proto/descriptor.proto" ) { | 
| 965 |     format( | 
| 966 |         "// Force running AddDescriptors() at dynamic initialization time.\n"  | 
| 967 |         "PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 "  | 
| 968 |         "static ::_pbi::AddDescriptorsRunner $1$(&$desc_table$);\n" , | 
| 969 |         UniqueName(name: "dynamic_init_dummy" , d: file_, options: options_)); | 
| 970 |   } | 
| 971 | } | 
| 972 |  | 
| 973 | class FileGenerator::ForwardDeclarations { | 
| 974 |  public: | 
| 975 |   void AddMessage(const Descriptor* d) { classes_[ClassName(descriptor: d)] = d; } | 
| 976 |   void AddEnum(const EnumDescriptor* d) { enums_[ClassName(enum_descriptor: d)] = d; } | 
| 977 |   void AddSplit(const Descriptor* d) { splits_[ClassName(descriptor: d)] = d; } | 
| 978 |  | 
| 979 |   void Print(const Formatter& format, const Options& options) const { | 
| 980 |     for (const auto& p : enums_) { | 
| 981 |       const std::string& enumname = p.first; | 
| 982 |       const EnumDescriptor* enum_desc = p.second; | 
| 983 |       format( | 
| 984 |           "enum ${1$$2$$}$ : int;\n"  | 
| 985 |           "bool $2$_IsValid(int value);\n" , | 
| 986 |           enum_desc, enumname); | 
| 987 |     } | 
| 988 |     for (const auto& p : classes_) { | 
| 989 |       const std::string& classname = p.first; | 
| 990 |       const Descriptor* class_desc = p.second; | 
| 991 |       format( | 
| 992 |           "class ${1$$2$$}$;\n"  | 
| 993 |           "struct $3$;\n"  | 
| 994 |           "$dllexport_decl $extern $3$ $4$;\n" , | 
| 995 |           class_desc, classname, DefaultInstanceType(descriptor: class_desc, options), | 
| 996 |           DefaultInstanceName(descriptor: class_desc, options)); | 
| 997 |     } | 
| 998 |     for (const auto& p : splits_) { | 
| 999 |       const Descriptor* class_desc = p.second; | 
| 1000 |       format( | 
| 1001 |           "struct $1$;\n"  | 
| 1002 |           "$dllexport_decl $extern $1$ $2$;\n" , | 
| 1003 |           DefaultInstanceType(descriptor: class_desc, options, /*split=*/true), | 
| 1004 |           DefaultInstanceName(descriptor: class_desc, options, /*split=*/true)); | 
| 1005 |     } | 
| 1006 |   } | 
| 1007 |  | 
| 1008 |   void PrintTopLevelDecl(const Formatter& format, | 
| 1009 |                          const Options& options) const { | 
| 1010 |     for (const auto& pair : classes_) { | 
| 1011 |       format( | 
| 1012 |           "template<> $dllexport_decl $"  | 
| 1013 |           "$1$* Arena::CreateMaybeMessage<$1$>(Arena*);\n" , | 
| 1014 |           QualifiedClassName(d: pair.second, options)); | 
| 1015 |     } | 
| 1016 |   } | 
| 1017 |  | 
| 1018 |  private: | 
| 1019 |   std::map<std::string, const Descriptor*> classes_; | 
| 1020 |   std::map<std::string, const EnumDescriptor*> enums_; | 
| 1021 |   std::map<std::string, const Descriptor*> splits_; | 
| 1022 | }; | 
| 1023 |  | 
| 1024 | static void PublicImportDFS(const FileDescriptor* fd, | 
| 1025 |                             std::unordered_set<const FileDescriptor*>* fd_set) { | 
| 1026 |   for (int i = 0; i < fd->public_dependency_count(); i++) { | 
| 1027 |     const FileDescriptor* dep = fd->public_dependency(index: i); | 
| 1028 |     if (fd_set->insert(x: dep).second) PublicImportDFS(fd: dep, fd_set); | 
| 1029 |   } | 
| 1030 | } | 
| 1031 |  | 
| 1032 | void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { | 
| 1033 |   Formatter format(printer, variables_); | 
| 1034 |   std::vector<const Descriptor*> classes; | 
| 1035 |   std::vector<const EnumDescriptor*> enums; | 
| 1036 |  | 
| 1037 |   FlattenMessagesInFile(file: file_, result: &classes);  // All messages need forward decls. | 
| 1038 |  | 
| 1039 |   if (options_.proto_h) {  // proto.h needs extra forward declarations. | 
| 1040 |     // All classes / enums referred to as field members | 
| 1041 |     std::vector<const FieldDescriptor*> fields; | 
| 1042 |     ListAllFields(d: file_, fields: &fields); | 
| 1043 |     for (int i = 0; i < fields.size(); i++) { | 
| 1044 |       classes.push_back(x: fields[i]->containing_type()); | 
| 1045 |       classes.push_back(x: fields[i]->message_type()); | 
| 1046 |       enums.push_back(x: fields[i]->enum_type()); | 
| 1047 |     } | 
| 1048 |     ListAllTypesForServices(fd: file_, types: &classes); | 
| 1049 |   } | 
| 1050 |  | 
| 1051 |   // Calculate the set of files whose definitions we get through include. | 
| 1052 |   // No need to forward declare types that are defined in these. | 
| 1053 |   std::unordered_set<const FileDescriptor*> public_set; | 
| 1054 |   PublicImportDFS(fd: file_, fd_set: &public_set); | 
| 1055 |  | 
| 1056 |   std::map<std::string, ForwardDeclarations> decls; | 
| 1057 |   for (int i = 0; i < classes.size(); i++) { | 
| 1058 |     const Descriptor* d = classes[i]; | 
| 1059 |     if (d && !public_set.count(x: d->file())) | 
| 1060 |       decls[Namespace(d, options: options_)].AddMessage(d); | 
| 1061 |   } | 
| 1062 |   for (int i = 0; i < enums.size(); i++) { | 
| 1063 |     const EnumDescriptor* d = enums[i]; | 
| 1064 |     if (d && !public_set.count(x: d->file())) | 
| 1065 |       decls[Namespace(d, options: options_)].AddEnum(d); | 
| 1066 |   } | 
| 1067 |   for (const auto& mg : message_generators_) { | 
| 1068 |     const Descriptor* d = mg->descriptor_; | 
| 1069 |     if ((d != nullptr) && (public_set.count(x: d->file()) == 0u) && | 
| 1070 |         ShouldSplit(desc: mg->descriptor_, options: options_)) | 
| 1071 |       decls[Namespace(d, options: options_)].AddSplit(d); | 
| 1072 |   } | 
| 1073 |  | 
| 1074 |   { | 
| 1075 |     NamespaceOpener ns(format); | 
| 1076 |     for (const auto& pair : decls) { | 
| 1077 |       ns.ChangeTo(name: pair.first); | 
| 1078 |       pair.second.Print(format, options: options_); | 
| 1079 |     } | 
| 1080 |   } | 
| 1081 |   format("PROTOBUF_NAMESPACE_OPEN\n" ); | 
| 1082 |   for (const auto& pair : decls) { | 
| 1083 |     pair.second.PrintTopLevelDecl(format, options: options_); | 
| 1084 |   } | 
| 1085 |   format("PROTOBUF_NAMESPACE_CLOSE\n" ); | 
| 1086 | } | 
| 1087 |  | 
| 1088 | void FileGenerator::(io::Printer* printer, bool pb_h) { | 
| 1089 |   Formatter format(printer, variables_); | 
| 1090 |   // Generate top of header. | 
| 1091 |   format( | 
| 1092 |       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"  | 
| 1093 |       "// source: $filename$\n"  | 
| 1094 |       "\n"  | 
| 1095 |       "#ifndef $1$\n"  | 
| 1096 |       "#define $1$\n"  | 
| 1097 |       "\n"  | 
| 1098 |       "#include <limits>\n"  | 
| 1099 |       "#include <string>\n" , | 
| 1100 |       IncludeGuard(file: file_, pb_h, options: options_)); | 
| 1101 |   if (!options_.opensource_runtime && !enum_generators_.empty()) { | 
| 1102 |     // Add header to provide std::is_integral for safe Enum_Name() function. | 
| 1103 |     format("#include <type_traits>\n" ); | 
| 1104 |   } | 
| 1105 |   format("\n" ); | 
| 1106 | } | 
| 1107 |  | 
| 1108 | void FileGenerator::(io::Printer* printer, bool pb_h) { | 
| 1109 |   Formatter format(printer, variables_); | 
| 1110 |   format("#endif  // $GOOGLE_PROTOBUF$_INCLUDED_$1$\n" , | 
| 1111 |          IncludeGuard(file: file_, pb_h, options: options_)); | 
| 1112 | } | 
| 1113 |  | 
| 1114 | void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { | 
| 1115 |   Formatter format(printer, variables_); | 
| 1116 |   if (UsingImplicitWeakFields(file: file_, options: options_)) { | 
| 1117 |     IncludeFile(google3_name: "net/proto2/public/implicit_weak_message.h" , printer); | 
| 1118 |   } | 
| 1119 |   if (HasWeakFields(desc: file_, options: options_)) { | 
| 1120 |     GOOGLE_CHECK(!options_.opensource_runtime); | 
| 1121 |     IncludeFile(google3_name: "net/proto2/public/weak_field_map.h" , printer); | 
| 1122 |   } | 
| 1123 |   if (HasLazyFields(file: file_, options: options_, scc_analyzer: &scc_analyzer_)) { | 
| 1124 |     GOOGLE_CHECK(!options_.opensource_runtime); | 
| 1125 |     IncludeFile(google3_name: "net/proto2/public/lazy_field.h" , printer); | 
| 1126 |   } | 
| 1127 |   if (ShouldVerify(file: file_, options: options_, scc_analyzer: &scc_analyzer_)) { | 
| 1128 |     IncludeFile(google3_name: "net/proto2/public/wire_format_verify.h" , printer); | 
| 1129 |   } | 
| 1130 |  | 
| 1131 |   if (options_.opensource_runtime) { | 
| 1132 |     // Verify the protobuf library header version is compatible with the protoc | 
| 1133 |     // version before going any further. | 
| 1134 |     IncludeFile(google3_name: "net/proto2/public/port_def.inc" , printer); | 
| 1135 |     format( | 
| 1136 |         "#if PROTOBUF_VERSION < $1$\n"  | 
| 1137 |         "#error This file was generated by a newer version of protoc which is\n"  | 
| 1138 |         "#error incompatible with your Protocol Buffer headers. Please update\n"  | 
| 1139 |         "#error your headers.\n"  | 
| 1140 |         "#endif\n"  | 
| 1141 |         "#if $2$ < PROTOBUF_MIN_PROTOC_VERSION\n"  | 
| 1142 |         "#error This file was generated by an older version of protoc which "  | 
| 1143 |         "is\n"  | 
| 1144 |         "#error incompatible with your Protocol Buffer headers. Please\n"  | 
| 1145 |         "#error regenerate this file with a newer version of protoc.\n"  | 
| 1146 |         "#endif\n"  | 
| 1147 |         "\n" , | 
| 1148 |         PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC,  // 1 | 
| 1149 |         PROTOBUF_VERSION);                       // 2 | 
| 1150 |     IncludeFile(google3_name: "net/proto2/public/port_undef.inc" , printer); | 
| 1151 |   } | 
| 1152 |  | 
| 1153 |   // OK, it's now safe to #include other files. | 
| 1154 |   IncludeFile(google3_name: "net/proto2/io/public/coded_stream.h" , printer); | 
| 1155 |   IncludeFile(google3_name: "net/proto2/public/arena.h" , printer); | 
| 1156 |   IncludeFile(google3_name: "net/proto2/public/arenastring.h" , printer); | 
| 1157 |   if ((options_.force_inline_string || options_.profile_driven_inline_string) && | 
| 1158 |       !options_.opensource_runtime) { | 
| 1159 |     IncludeFile(google3_name: "net/proto2/public/inlined_string_field.h" , printer); | 
| 1160 |   } | 
| 1161 |   if (HasSimpleBaseClasses(file: file_, options: options_)) { | 
| 1162 |     IncludeFile(google3_name: "net/proto2/public/generated_message_bases.h" , printer); | 
| 1163 |   } | 
| 1164 |   if (HasGeneratedMethods(file: file_, options: options_) && | 
| 1165 |       options_.tctable_mode != Options::kTCTableNever) { | 
| 1166 |     IncludeFile(google3_name: "net/proto2/public/generated_message_tctable_decl.h" , printer); | 
| 1167 |   } | 
| 1168 |   IncludeFile(google3_name: "net/proto2/public/generated_message_util.h" , printer); | 
| 1169 |   IncludeFile(google3_name: "net/proto2/public/metadata_lite.h" , printer); | 
| 1170 |  | 
| 1171 |   if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 1172 |     IncludeFile(google3_name: "net/proto2/public/generated_message_reflection.h" , printer); | 
| 1173 |   } | 
| 1174 |  | 
| 1175 |   if (!message_generators_.empty()) { | 
| 1176 |     if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 1177 |       IncludeFile(google3_name: "net/proto2/public/message.h" , printer); | 
| 1178 |     } else { | 
| 1179 |       IncludeFile(google3_name: "net/proto2/public/message_lite.h" , printer); | 
| 1180 |     } | 
| 1181 |   } | 
| 1182 |   if (options_.opensource_runtime) { | 
| 1183 |     // Open-source relies on unconditional includes of these. | 
| 1184 |     IncludeFileAndExport(google3_name: "net/proto2/public/repeated_field.h" , printer); | 
| 1185 |     IncludeFileAndExport(google3_name: "net/proto2/public/extension_set.h" , printer); | 
| 1186 |   } else { | 
| 1187 |     // Google3 includes these files only when they are necessary. | 
| 1188 |     if (HasExtensionsOrExtendableMessage(file: file_)) { | 
| 1189 |       IncludeFileAndExport(google3_name: "net/proto2/public/extension_set.h" , printer); | 
| 1190 |     } | 
| 1191 |     if (HasRepeatedFields(file: file_)) { | 
| 1192 |       IncludeFileAndExport(google3_name: "net/proto2/public/repeated_field.h" , printer); | 
| 1193 |     } | 
| 1194 |     if (HasStringPieceFields(file: file_, options: options_)) { | 
| 1195 |       IncludeFile(google3_name: "net/proto2/public/string_piece_field_support.h" , printer); | 
| 1196 |     } | 
| 1197 |     if (HasCordFields(file: file_, options: options_)) { | 
| 1198 |       format("#include \"third_party/absl/strings/cord.h\"\n" ); | 
| 1199 |     } | 
| 1200 |   } | 
| 1201 |   if (HasMapFields(file: file_)) { | 
| 1202 |     IncludeFileAndExport(google3_name: "net/proto2/public/map.h" , printer); | 
| 1203 |     if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 1204 |       IncludeFile(google3_name: "net/proto2/public/map_entry.h" , printer); | 
| 1205 |       IncludeFile(google3_name: "net/proto2/public/map_field_inl.h" , printer); | 
| 1206 |     } else { | 
| 1207 |       IncludeFile(google3_name: "net/proto2/public/map_entry_lite.h" , printer); | 
| 1208 |       IncludeFile(google3_name: "net/proto2/public/map_field_lite.h" , printer); | 
| 1209 |     } | 
| 1210 |   } | 
| 1211 |  | 
| 1212 |   if (HasEnumDefinitions(file: file_)) { | 
| 1213 |     if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 1214 |       IncludeFile(google3_name: "net/proto2/public/generated_enum_reflection.h" , printer); | 
| 1215 |     } else { | 
| 1216 |       IncludeFile(google3_name: "net/proto2/public/generated_enum_util.h" , printer); | 
| 1217 |     } | 
| 1218 |   } | 
| 1219 |  | 
| 1220 |   if (HasGenericServices(file: file_, options: options_)) { | 
| 1221 |     IncludeFile(google3_name: "net/proto2/public/service.h" , printer); | 
| 1222 |   } | 
| 1223 |  | 
| 1224 |   if (UseUnknownFieldSet(file: file_, options: options_) && !message_generators_.empty()) { | 
| 1225 |     IncludeFile(google3_name: "net/proto2/public/unknown_field_set.h" , printer); | 
| 1226 |   } | 
| 1227 | } | 
| 1228 |  | 
| 1229 | void FileGenerator::GenerateMetadataPragma(io::Printer* printer, | 
| 1230 |                                            const std::string& info_path) { | 
| 1231 |   Formatter format(printer, variables_); | 
| 1232 |   if (!info_path.empty() && !options_.annotation_pragma_name.empty() && | 
| 1233 |       !options_.annotation_guard_name.empty()) { | 
| 1234 |     format.Set(key: "guard" , value: options_.annotation_guard_name); | 
| 1235 |     format.Set(key: "pragma" , value: options_.annotation_pragma_name); | 
| 1236 |     format.Set(key: "info_path" , value: info_path); | 
| 1237 |     format( | 
| 1238 |         "#ifdef $guard$\n"  | 
| 1239 |         "#pragma $pragma$ \"$info_path$\"\n"  | 
| 1240 |         "#endif  // $guard$\n" ); | 
| 1241 |   } | 
| 1242 | } | 
| 1243 |  | 
| 1244 | void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { | 
| 1245 |   Formatter format(printer, variables_); | 
| 1246 |   for (int i = 0; i < file_->dependency_count(); i++) { | 
| 1247 |     std::string basename = StripProto(filename: file_->dependency(index: i)->name()); | 
| 1248 |  | 
| 1249 |     // Do not import weak deps. | 
| 1250 |     if (IsDepWeak(dep: file_->dependency(index: i))) continue; | 
| 1251 |  | 
| 1252 |     if (IsBootstrapProto(options: options_, file: file_)) { | 
| 1253 |       GetBootstrapBasename(options: options_, basename, bootstrap_basename: &basename); | 
| 1254 |     } | 
| 1255 |  | 
| 1256 |     format("#include $1$\n" , | 
| 1257 |            CreateHeaderInclude(basename: basename + ".pb.h" , file: file_->dependency(index: i))); | 
| 1258 |   } | 
| 1259 | } | 
| 1260 |  | 
| 1261 | void FileGenerator::GenerateGlobalStateFunctionDeclarations( | 
| 1262 |     io::Printer* printer) { | 
| 1263 |   Formatter format(printer, variables_); | 
| 1264 |   // Forward-declare the DescriptorTable because this is referenced by .pb.cc | 
| 1265 |   // files depending on this file. | 
| 1266 |   // | 
| 1267 |   // The TableStruct is also outputted in weak_message_field.cc, because the | 
| 1268 |   // weak fields must refer to table struct but cannot include the header. | 
| 1269 |   // Also it annotates extra weak attributes. | 
| 1270 |   // TODO(gerbens) make sure this situation is handled better. | 
| 1271 |   format( | 
| 1272 |       "\n"  | 
| 1273 |       "// Internal implementation detail -- do not use these members.\n"  | 
| 1274 |       "struct $dllexport_decl $$tablename$ {\n"  | 
| 1275 |       "  static const $uint32$ offsets[];\n"  | 
| 1276 |       "};\n" ); | 
| 1277 |   if (HasDescriptorMethods(file: file_, options: options_)) { | 
| 1278 |     format( | 
| 1279 |         "$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable "  | 
| 1280 |         "$desc_table$;\n" ); | 
| 1281 |   } | 
| 1282 | } | 
| 1283 |  | 
| 1284 | void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) { | 
| 1285 |   Formatter format(printer, variables_); | 
| 1286 |   // Generate class definitions. | 
| 1287 |   for (int i = 0; i < message_generators_.size(); i++) { | 
| 1288 |     if (i > 0) { | 
| 1289 |       format("\n" ); | 
| 1290 |       format(kThinSeparator); | 
| 1291 |       format("\n" ); | 
| 1292 |     } | 
| 1293 |     message_generators_[i]->GenerateClassDefinition(printer); | 
| 1294 |   } | 
| 1295 | } | 
| 1296 |  | 
| 1297 | void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { | 
| 1298 |   // Generate enum definitions. | 
| 1299 |   for (int i = 0; i < enum_generators_.size(); i++) { | 
| 1300 |     enum_generators_[i]->GenerateDefinition(printer); | 
| 1301 |   } | 
| 1302 | } | 
| 1303 |  | 
| 1304 | void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { | 
| 1305 |   Formatter format(printer, variables_); | 
| 1306 |   if (HasGenericServices(file: file_, options: options_)) { | 
| 1307 |     // Generate service definitions. | 
| 1308 |     for (int i = 0; i < service_generators_.size(); i++) { | 
| 1309 |       if (i > 0) { | 
| 1310 |         format("\n" ); | 
| 1311 |         format(kThinSeparator); | 
| 1312 |         format("\n" ); | 
| 1313 |       } | 
| 1314 |       service_generators_[i]->GenerateDeclarations(printer); | 
| 1315 |     } | 
| 1316 |  | 
| 1317 |     format("\n" ); | 
| 1318 |     format(kThickSeparator); | 
| 1319 |     format("\n" ); | 
| 1320 |   } | 
| 1321 | } | 
| 1322 |  | 
| 1323 | void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { | 
| 1324 |   // Declare extension identifiers. These are in global scope and so only | 
| 1325 |   // the global scope extensions. | 
| 1326 |   for (auto& extension_generator : extension_generators_) { | 
| 1327 |     if (extension_generator->IsScoped()) continue; | 
| 1328 |     extension_generator->GenerateDeclaration(printer); | 
| 1329 |   } | 
| 1330 | } | 
| 1331 |  | 
| 1332 | void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { | 
| 1333 |   Formatter format(printer, variables_); | 
| 1334 |   // TODO(gerbens) remove pragmas when gcc is no longer used. Current version | 
| 1335 |   // of gcc fires a bogus error when compiled with strict-aliasing. | 
| 1336 |   format( | 
| 1337 |       "#ifdef __GNUC__\n"  | 
| 1338 |       "  #pragma GCC diagnostic push\n"  | 
| 1339 |       "  #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n"  | 
| 1340 |       "#endif  // __GNUC__\n" ); | 
| 1341 |   // Generate class inline methods. | 
| 1342 |   for (int i = 0; i < message_generators_.size(); i++) { | 
| 1343 |     if (i > 0) { | 
| 1344 |       format(kThinSeparator); | 
| 1345 |       format("\n" ); | 
| 1346 |     } | 
| 1347 |     message_generators_[i]->GenerateInlineMethods(printer); | 
| 1348 |   } | 
| 1349 |   format( | 
| 1350 |       "#ifdef __GNUC__\n"  | 
| 1351 |       "  #pragma GCC diagnostic pop\n"  | 
| 1352 |       "#endif  // __GNUC__\n" ); | 
| 1353 |  | 
| 1354 |   for (int i = 0; i < message_generators_.size(); i++) { | 
| 1355 |     if (i > 0) { | 
| 1356 |       format(kThinSeparator); | 
| 1357 |       format("\n" ); | 
| 1358 |     } | 
| 1359 |   } | 
| 1360 | } | 
| 1361 |  | 
| 1362 | void FileGenerator::GenerateProto2NamespaceEnumSpecializations( | 
| 1363 |     io::Printer* printer) { | 
| 1364 |   Formatter format(printer, variables_); | 
| 1365 |   // Emit GetEnumDescriptor specializations into google::protobuf namespace: | 
| 1366 |   if (HasEnumDefinitions(file: file_)) { | 
| 1367 |     format("\n" ); | 
| 1368 |     { | 
| 1369 |       NamespaceOpener proto_ns(ProtobufNamespace(options_), format); | 
| 1370 |       format("\n" ); | 
| 1371 |       for (int i = 0; i < enum_generators_.size(); i++) { | 
| 1372 |         enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); | 
| 1373 |       } | 
| 1374 |       format("\n" ); | 
| 1375 |     } | 
| 1376 |   } | 
| 1377 | } | 
| 1378 |  | 
| 1379 | }  // namespace cpp | 
| 1380 | }  // namespace compiler | 
| 1381 | }  // namespace protobuf | 
| 1382 | }  // namespace google | 
| 1383 |  |