// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include "google/protobuf/compiler/cpp/file.h"

#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "google/protobuf/compiler/scc.h"
#include "absl/container/btree_map.h"
#include "absl/container/btree_set.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "google/protobuf/compiler/cpp/enum.h"
#include "google/protobuf/compiler/cpp/extension.h"
#include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/cpp/message.h"
#include "google/protobuf/compiler/cpp/names.h"
#include "google/protobuf/compiler/cpp/service.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/printer.h"

// Must be last.
#include "google/protobuf/port_def.inc"

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
namespace {
absl::flat_hash_map<absl::string_view, std::string> FileVars(
    const FileDescriptor* file, const Options& options) {
  return {
      {"filename", file->name()},
      {"package_ns", Namespace(file, options)},
      {"tablename", UniqueName("TableStruct", file, options)},
      {"desc_table", DescriptorTableName(file, options)},
      {"dllexport_decl", options.dllexport_decl},
      {"file_level_metadata", UniqueName("file_level_metadata", file, options)},
      {"file_level_enum_descriptors",
       UniqueName("file_level_enum_descriptors", file, options)},
      {"file_level_service_descriptors",
       UniqueName("file_level_service_descriptors", file, options)},
  };
}

// TODO(b/203101078): remove pragmas that suppresses uninitialized warnings when
// clang bug is fixed.
void MuteWuninitialized(io::Printer* p) {
  p->Emit(R"(
    #if defined(__llvm__)
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wuninitialized"
    #endif  // __llvm__
  )");
}

void UnmuteWuninitialized(io::Printer* p) {
  p->Emit(R"(
    #if defined(__llvm__)
    #pragma clang diagnostic pop
    #endif  // __llvm__
  )");
}
}  // namespace

FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
    : file_(file), options_(options), scc_analyzer_(options) {
  std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);

  for (int i = 0; i < msgs.size(); ++i) {
    message_generators_.push_back(std::make_unique<MessageGenerator>(
        msgs[i], variables_, i, options, &scc_analyzer_));
    message_generators_.back()->AddGenerators(&enum_generators_,
                                              &extension_generators_);
  }

  for (int i = 0; i < file->enum_type_count(); ++i) {
    enum_generators_.push_back(
        std::make_unique<EnumGenerator>(file->enum_type(i), options));
  }

  for (int i = 0; i < file->service_count(); ++i) {
    service_generators_.push_back(std::make_unique<ServiceGenerator>(
        file->service(i), variables_, options));
  }
  if (HasGenericServices(file_, options_)) {
    for (int i = 0; i < service_generators_.size(); ++i) {
      service_generators_[i]->index_in_metadata_ = i;
    }
  }

  for (int i = 0; i < file->extension_count(); ++i) {
    extension_generators_.push_back(std::make_unique<ExtensionGenerator>(
        file->extension(i), options, &scc_analyzer_));
  }

  for (int i = 0; i < file->weak_dependency_count(); ++i) {
    weak_deps_.insert(file->weak_dependency(i));
  }
}

void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type,
                                 std::function<void()> cb) {
  auto v = p->WithVars(FileVars(file_, options_));
  auto guard = IncludeGuard(file_, file_type, options_);
  p->Emit({{"cb", cb}, {"guard", guard}}, R"(
    // Generated by the protocol buffer compiler.  DO NOT EDIT!
    // source: $filename$

    #ifndef $guard$
    #define $guard$

    #include <limits>
    #include <string>
    #include <type_traits>

    $cb$;

    #endif  // $guard$
  )");
}

void FileGenerator::GenerateMacroUndefs(io::Printer* p) {
  // Only do this for protobuf's own types. There are some google3 protos using
  // macros as field names and the generated code compiles after the macro
  // expansion. Undefing these macros actually breaks such code.
  if (file_->name() != "net/proto2/compiler/proto/plugin.proto" &&
      file_->name() != "google/protobuf/compiler/plugin.proto") {
    return;
  }

  std::vector<const FieldDescriptor*> fields;
  ListAllFields(file_, &fields);

  absl::flat_hash_set<absl::string_view> all_fields;
  for (const FieldDescriptor* field : fields) {
    all_fields.insert(field->name());
  }

  for (absl::string_view name : {"major", "minor"}) {
    if (!all_fields.contains(name)) {
      continue;
    }

    p->Emit({{"name", std::string(name)}}, R"(
      #ifdef $name$
      #undef $name$
      #endif  // $name$
    )");
  }
}


void FileGenerator::GenerateSharedHeaderCode(io::Printer* p) {
  p->Emit(
      {
          {"port_def",
           [&] { IncludeFile("net/proto2/public/port_def.inc", p); }},
          {"port_undef",
           [&] { IncludeFile("net/proto2/public/port_undef.inc", p); }},
          {"dllexport_macro", FileDllExport(file_, options_)},
          {"undefs", [&] { GenerateMacroUndefs(p); }},
          {"global_state_decls",
           [&] { GenerateGlobalStateFunctionDeclarations(p); }},
          {"fwd_decls", [&] { GenerateForwardDeclarations(p); }},
          {"proto2_ns_enums",
           [&] { GenerateProto2NamespaceEnumSpecializations(p); }},
          {"main_decls",
           [&] {
             NamespaceOpener ns(Namespace(file_, options_), p);
             p->Emit(
                 {
                     {"enums", [&] { GenerateEnumDefinitions(p); }},
                     {"messages", [&] { GenerateMessageDefinitions(p); }},
                     {"services", [&] { GenerateServiceDefinitions(p); }},
                     {"extensions", [&] { GenerateExtensionIdentifiers(p); }},
                     {"inline_fns",
                      [&] { GenerateInlineFunctionDefinitions(p); }},
                 },
                 R"(
                   $enums$

                   $hrule_thick$

                   $messages$

                   $hrule_thick$

                   $services$

                   $extensions$

                   $hrule_thick$

                   $inline_fns$

                   // @@protoc_insertion_point(namespace_scope)
                 )");
           }},
      },
      R"(
          // Must be included last.
          $port_def$

          #define $dllexport_macro$$ dllexport_decl$
          $undefs$

          PROTOBUF_NAMESPACE_OPEN
          namespace internal {
          class AnyMetadata;
          }  // namespace internal
          PROTOBUF_NAMESPACE_CLOSE

          $global_state_decls$;
          $fwd_decls$

          $main_decls$

          $proto2_ns_enums$

          // @@protoc_insertion_point(global_scope)

          $port_undef$
      )");
}

void FileGenerator::GenerateProtoHeader(io::Printer* p,
                                        absl::string_view info_path) {
  if (!options_.proto_h) {
    return;
  }

  GenerateFile(p, GeneratedFileType::kProtoH, [&] {
    if (!options_.opensource_runtime) {
      p->Emit(R"(
          #ifdef SWIG
          #error "Do not SWIG-wrap protobufs."
          #endif  // SWIG
        )");
    }
    if (IsBootstrapProto(options_, file_)) {
      p->Emit({{"name", StripProto(file_->name())}}, R"cc(
        // IWYU pragma: private, include "$name$.proto.h"
      )cc");
    }

    p->Emit(
        {
            {"library_includes", [&] { GenerateLibraryIncludes(p); }},
            {"proto_includes",
             [&] {
               for (int i = 0; i < file_->public_dependency_count(); ++i) {
                 const FileDescriptor* dep = file_->public_dependency(i);
                 p->Emit({{"name", StripProto(dep->name())}}, R"(
                    #include "$name$.proto.h"
                 )");
               }
             }},
            {"metadata_pragma", [&] { GenerateMetadataPragma(p, info_path); }},
            {"header_main", [&] { GenerateSharedHeaderCode(p); }},
        },
        R"cc(
          $library_includes$;
          $proto_includes$;
          // @@protoc_insertion_point(includes)

          $metadata_pragma$;
          $header_main$;
        )cc");
  });
}

void FileGenerator::GeneratePBHeader(io::Printer* p,
                                     absl::string_view info_path) {
  GenerateFile(p, GeneratedFileType::kPbH, [&] {
    p->Emit(
        {
            {"library_includes",
             [&] {
               if (options_.proto_h) {
                 std::string target_basename = StripProto(file_->name());
                 if (!options_.opensource_runtime) {
                   GetBootstrapBasename(options_, target_basename,
                                        &target_basename);
                 }
                 p->Emit({{"name", target_basename}}, R"(
              #include "$name$.proto.h"  // IWYU pragma: export
              )");
               } else {
                 GenerateLibraryIncludes(p);
               }
             }},
            {"proto_includes",
             [&] {
               if (options_.transitive_pb_h) {
                 GenerateDependencyIncludes(p);
               }
             }},
            {"metadata_pragma", [&] { GenerateMetadataPragma(p, info_path); }},
            {"header_main",
             [&] {
               if (!options_.proto_h) {
                 GenerateSharedHeaderCode(p);
                 return;
               }

               {
                 NamespaceOpener ns(Namespace(file_, options_), p);
                 p->Emit(R"cc(

                   // @@protoc_insertion_point(namespace_scope)
                 )cc");
               }
               p->Emit(R"cc(

                 // @@protoc_insertion_point(global_scope)
               )cc");
             }},
        },
        R"cc(
          $library_includes$;
          $proto_includes$;
          // @@protoc_insertion_point(includes)

          $metadata_pragma$;
          $header_main$;
        )cc");
  });
}

void FileGenerator::DoIncludeFile(absl::string_view google3_name,
                                  bool do_export, io::Printer* p) {
  constexpr absl::string_view prefix = "net/proto2/";
  GOOGLE_CHECK(absl::StartsWith(google3_name, prefix)) << google3_name;

  auto v = p->WithVars(
      {{"export_suffix", do_export ? "// IWYU pragma: export" : ""}});

  if (options_.opensource_runtime) {
    absl::ConsumePrefix(&google3_name, prefix);
    absl::ConsumePrefix(&google3_name, "internal/");
    absl::ConsumePrefix(&google3_name, "proto/");
    absl::ConsumePrefix(&google3_name, "public/");

    std::string path;
    if (absl::ConsumePrefix(&google3_name, "io/public/")) {
      path = absl::StrCat("io/", google3_name);
    } else {
      path = std::string(google3_name);
    }

    if (options_.runtime_include_base.empty()) {
      p->Emit({{"path", path}}, R"(
        #include "google/protobuf/$path$"$  export_suffix$
      )");
    } else {
      p->Emit({{"base", options_.runtime_include_base}, {"path", path}},
              R"(
        #include "$base$google/protobuf/$path$"$  export_suffix$
      )");
    }
  } else {
    std::string path(google3_name);
    // The bootstrapped proto generated code needs to use the
    // third_party/protobuf header paths to avoid circular dependencies.
    if (options_.bootstrap) {
      constexpr absl::string_view bootstrap_prefix = "net/proto2/public";
      if (absl::ConsumePrefix(&google3_name, bootstrap_prefix)) {
        path = absl::StrCat("third_party/protobuf", google3_name);
      }
    }

    p->Emit({{"path", path}}, R"(
      #include "$path$"$  export_suffix$
    )");
  }
}

std::string FileGenerator::CreateHeaderInclude(absl::string_view basename,
                                               const FileDescriptor* file) {
  if (options_.opensource_runtime && IsWellKnownMessage(file) &&
      !options_.runtime_include_base.empty()) {
    return absl::StrCat("\"", options_.runtime_include_base, basename, "\"");
  }

  return absl::StrCat("\"", basename, "\"");
}

void FileGenerator::GenerateSourceIncludes(io::Printer* p) {
  std::string target_basename = StripProto(file_->name());
  if (!options_.opensource_runtime) {
    GetBootstrapBasename(options_, target_basename, &target_basename);
  }

  absl::StrAppend(&target_basename, options_.proto_h ? ".proto.h" : ".pb.h");
  p->Emit({{"h_include", CreateHeaderInclude(target_basename, file_)}},
          R"(
        // Generated by the protocol buffer compiler.  DO NOT EDIT!
        // source: $filename$

        #include $h_include$

        #include <algorithm>
      )");

  IncludeFile("net/proto2/io/public/coded_stream.h", p);
  // TODO(gerbens) This is to include parse_context.h, we need a better way
  IncludeFile("net/proto2/public/extension_set.h", p);
  IncludeFile("net/proto2/public/wire_format_lite.h", p);

  // Unknown fields implementation in lite mode uses StringOutputStream
  if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
    IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", p);
  }

  if (HasDescriptorMethods(file_, options_)) {
    IncludeFile("net/proto2/public/descriptor.h", p);
    IncludeFile("net/proto2/public/generated_message_reflection.h", p);
    IncludeFile("net/proto2/public/reflection_ops.h", p);
    IncludeFile("net/proto2/public/wire_format.h", p);
  }

  if (HasGeneratedMethods(file_, options_) &&
      options_.tctable_mode != Options::kTCTableNever) {
    IncludeFile("net/proto2/public/generated_message_tctable_impl.h", p);
  }

  if (options_.proto_h) {
    // Use the smaller .proto.h files.
    for (int i = 0; i < file_->dependency_count(); ++i) {
      const FileDescriptor* dep = file_->dependency(i);

      if (!options_.opensource_runtime &&
          IsDepWeak(dep)) {  // Do not import weak deps.
        continue;
      }

      std::string basename = StripProto(dep->name());
      if (IsBootstrapProto(options_, file_)) {
        GetBootstrapBasename(options_, basename, &basename);
      }
      p->Emit({{"name", basename}}, R"(
        #include "$name$.proto.h"
      )");
    }
  }

  if (HasCordFields(file_, options_)) {
    p->Emit(R"(
      #include "third_party/absl/strings/internal/string_constant.h"
    )");
  }

  p->Emit(R"cc(
    // @@protoc_insertion_point(includes)

    // Must be included last.
  )cc");
  IncludeFile("net/proto2/public/port_def.inc", p);
}

void FileGenerator::GenerateSourcePrelude(io::Printer* p) {
  // For MSVC builds, we use #pragma init_seg to move the initialization of our
  // libraries to happen before the user code.
  // This worksaround the fact that MSVC does not do constant initializers when
  // required by the standard.
  p->Emit(R"cc(
    PROTOBUF_PRAGMA_INIT_SEG
    namespace _pb = ::$proto_ns$;
    namespace _pbi = ::$proto_ns$::internal;
  )cc");

  if (HasGeneratedMethods(file_, options_) &&
      options_.tctable_mode != Options::kTCTableNever) {
    p->Emit(R"cc(
      namespace _fl = ::$proto_ns$::internal::field_layout;
    )cc");
  }
}

void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* p) {
  MessageGenerator* generator = message_generators_[idx].get();

  // Generate the split instance first because it's needed in the constexpr
  // constructor.
  if (ShouldSplit(generator->descriptor(), options_)) {
    // Use a union to disable the destructor of the _instance member.
    // We can constant initialize, but the object will still have a non-trivial
    // destructor that we need to elide.
    //
    // NO_DESTROY is not necessary for correctness. The empty destructor is
    // enough. However, the empty destructor fails to be elided in some
    // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
    // there just to improve performance and binary size in these builds.
    p->Emit(
        {
            {"type", DefaultInstanceType(generator->descriptor(), options_,
                                         /*split=*/true)},
            {"name", DefaultInstanceName(generator->descriptor(), options_,
                                         /*split=*/true)},
            {"default",
             [&] { generator->GenerateInitDefaultSplitInstance(p); }},
            {"class", absl::StrCat(ClassName(generator->descriptor()),
                                   "::Impl_::Split")},
        },
        R"cc(
          struct $type$ {
            PROTOBUF_CONSTEXPR $type$() : _instance{$default$} {}
            union {
              $class$ _instance;
            };
          };

          PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
              PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const $type$ $name$;
        )cc");
  }

  generator->GenerateConstexprConstructor(p);

  p->Emit(
      {
          {"type", DefaultInstanceType(generator->descriptor(), options_)},
          {"name", DefaultInstanceName(generator->descriptor(), options_)},
          {"default", [&] { generator->GenerateInitDefaultSplitInstance(p); }},
          {"class", ClassName(generator->descriptor())},
      },
      R"cc(
        struct $type$ {
          PROTOBUF_CONSTEXPR $type$() : _instance(::_pbi::ConstantInitialized{}) {}
          ~$type$() {}
          union {
            $class$ _instance;
          };
        };

        PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
            PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $type$ $name$;
      )cc");

  for (int i = 0; i < generator->descriptor()->field_count(); ++i) {
    const FieldDescriptor* field = generator->descriptor()->field(i);
    if (!IsStringInlined(field, options_)) {
      continue;
    }

    // Force the initialization of the inlined string in the default instance.
    p->Emit(
        {
            {"class", ClassName(generator->descriptor())},
            {"field", FieldName(field)},
            {"default", DefaultInstanceName(generator->descriptor(), options_)},
            {"member", FieldMemberName(field, ShouldSplit(field, options_))},
        },
        R"cc(
          PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type
              $class$::Impl_::_init_inline_$field$_ =
                  ($default$._instance.$member$.Init(), std::true_type{});
        )cc");
  }

  if (options_.lite_implicit_weak_fields) {
    p->Emit(
        {
            {"ptr", DefaultInstancePtr(generator->descriptor(), options_)},
            {"name", DefaultInstanceName(generator->descriptor(), options_)},
        },
        R"cc(
          PROTOBUF_CONSTINIT const void* $ptr$ = &$name$;
        )cc");
  }
}

// A list of things defined in one .pb.cc file that we need to reference from
// another .pb.cc file.
struct FileGenerator::CrossFileReferences {
  // When we forward-declare things, we want to create a sorted order so our
  // output is deterministic and minimizes namespace changes.
  struct DescCompare {
    template <typename T>
    bool operator()(const T* const& a, const T* const& b) const {
      return a->full_name() < b->full_name();
    }

    bool operator()(const FileDescriptor* const& a,
                    const FileDescriptor* const& b) const {
      return a->name() < b->name();
    }
  };

  // Populated if we are referencing from messages or files.
  absl::btree_set<const Descriptor*, DescCompare> weak_default_instances;

  // Only if we are referencing from files.
  absl::btree_set<const FileDescriptor*, DescCompare> strong_reflection_files;
  absl::btree_set<const FileDescriptor*, DescCompare> weak_reflection_files;
};

void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field,
                                                   CrossFileReferences* refs) {
  const Descriptor* msg = field->message_type();
  if (msg == nullptr) {
    return;
  }

  if (IsImplicitWeakField(field, options_, &scc_analyzer_) ||
      IsWeak(field, options_)) {
    refs->weak_default_instances.insert(msg);
  }
}

void FileGenerator::GetCrossFileReferencesForFile(const FileDescriptor* file,
                                                  CrossFileReferences* refs) {
  ForEachField(file, [this, refs](const FieldDescriptor* field) {
    GetCrossFileReferencesForField(field, refs);
  });

  if (!HasDescriptorMethods(file, options_)) {
    return;
  }

  for (int i = 0; i < file->dependency_count(); ++i) {
    const FileDescriptor* dep = file->dependency(i);

    if (IsDepWeak(dep)) {
      refs->weak_reflection_files.insert(dep);
    } else {
      refs->strong_reflection_files.insert(dep);
    }
  }
}

// Generates references to variables defined in other files.
void FileGenerator::GenerateInternalForwardDeclarations(
    const CrossFileReferences& refs, io::Printer* p) {
  {
    NamespaceOpener ns(p);
    for (auto instance : refs.weak_default_instances) {
      ns.ChangeTo(Namespace(instance, options_));

      if (options_.lite_implicit_weak_fields) {
        p->Emit({{"ptr", DefaultInstancePtr(instance, options_)}}, R"cc(
          PROTOBUF_CONSTINIT __attribute__((weak)) const void* $ptr$ =
              &::_pbi::implicit_weak_message_default_instance;
        )cc");
      } else {
        p->Emit({{"type", DefaultInstanceType(instance, options_)},
                 {"name", DefaultInstanceName(instance, options_)}},
                R"cc(
                  extern __attribute__((weak)) $type$ $name$;
                )cc");
      }
    }
  }

  for (auto file : refs.weak_reflection_files) {
    p->Emit({{"table", DescriptorTableName(file, options_)}}, R"cc(
      extern __attribute__((weak)) const ::_pbi::DescriptorTable $table$;
    )cc");
  }
}

void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) {
  auto v = p->WithVars(FileVars(file_, options_));

  GenerateSourceIncludes(p);
  GenerateSourcePrelude(p);

  if (IsAnyMessage(file_, options_)) {
    MuteWuninitialized(p);
  }

  CrossFileReferences refs;
  ForEachField(message_generators_[idx]->descriptor(),
               [this, &refs](const FieldDescriptor* field) {
                 GetCrossFileReferencesForField(field, &refs);
               });

  GenerateInternalForwardDeclarations(refs, p);

  {
    NamespaceOpener ns(Namespace(file_, options_), p);
    p->Emit(
        {
            {"defaults", [&] { GenerateSourceDefaultInstance(idx, p); }},
            {"class_methods",
             [&] { message_generators_[idx]->GenerateClassMethods(p); }},
        },
        R"cc(
          $defaults$;

          $class_methods$;

          // @@protoc_insertion_point(namespace_scope)
        )cc");
  }

  {
    NamespaceOpener proto_ns(ProtobufNamespace(options_), p);
    message_generators_[idx]->GenerateSourceInProto2Namespace(p);
  }

  if (IsAnyMessage(file_, options_)) {
    UnmuteWuninitialized(p);
  }

  p->Emit(R"cc(
    // @@protoc_insertion_point(global_scope)
  )cc");
}

void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* p) {
  auto v = p->WithVars(FileVars(file_, options_));
  GenerateSourceIncludes(p);
  GenerateSourcePrelude(p);

  NamespaceOpener ns(Namespace(file_, options_), p);
  extension_generators_[idx]->GenerateDefinition(p);
}

void FileGenerator::GenerateGlobalSource(io::Printer* p) {
  auto v = p->WithVars(FileVars(file_, options_));
  GenerateSourceIncludes(p);
  GenerateSourcePrelude(p);

  {
    // Define the code to initialize reflection. This code uses a global
    // constructor to register reflection data with the runtime pre-main.
    if (HasDescriptorMethods(file_, options_)) {
      GenerateReflectionInitializationCode(p);
    }
  }

  NamespaceOpener ns(Namespace(file_, options_), p);
  for (int i = 0; i < enum_generators_.size(); ++i) {
    enum_generators_[i]->GenerateMethods(i, p);
  }
}

void FileGenerator::GenerateSource(io::Printer* p) {
  auto v = p->WithVars(FileVars(file_, options_));

  GenerateSourceIncludes(p);
  GenerateSourcePrelude(p);
  CrossFileReferences refs;
  GetCrossFileReferencesForFile(file_, &refs);
  GenerateInternalForwardDeclarations(refs, p);

  if (IsAnyMessage(file_, options_)) {
    MuteWuninitialized(p);
  }

  {
    NamespaceOpener ns(Namespace(file_, options_), p);
    for (int i = 0; i < message_generators_.size(); ++i) {
      GenerateSourceDefaultInstance(i, p);
    }
  }

  {
    if (HasDescriptorMethods(file_, options_)) {
      // Define the code to initialize reflection. This code uses a global
      // constructor to register reflection data with the runtime pre-main.
      GenerateReflectionInitializationCode(p);
    }
  }

  {
    NamespaceOpener ns(Namespace(file_, options_), p);

    // Actually implement the protos

    // Generate enums.
    for (int i = 0; i < enum_generators_.size(); ++i) {
      enum_generators_[i]->GenerateMethods(i, p);
    }

    // Generate classes.
    for (int i = 0; i < message_generators_.size(); ++i) {
      p->Emit(R"(
        $hrule_thick$
      )");
      message_generators_[i]->GenerateClassMethods(p);
    }

    if (HasGenericServices(file_, options_)) {
      // Generate services.
      for (int i = 0; i < service_generators_.size(); ++i) {
        p->Emit(R"(
          $hrule_thick$
        )");
        service_generators_[i]->GenerateImplementation(p);
      }
    }

    // Define extensions.
    for (int i = 0; i < extension_generators_.size(); ++i) {
      extension_generators_[i]->GenerateDefinition(p);
    }

    p->Emit(R"cc(
      // @@protoc_insertion_point(namespace_scope)
    )cc");
  }

  {
    NamespaceOpener proto_ns(ProtobufNamespace(options_), p);
    for (int i = 0; i < message_generators_.size(); ++i) {
      message_generators_[i]->GenerateSourceInProto2Namespace(p);
    }
  }

  p->Emit(R"cc(
    // @@protoc_insertion_point(global_scope)
  )cc");

  if (IsAnyMessage(file_, options_)) {
    UnmuteWuninitialized(p);
  }

  IncludeFile("net/proto2/public/port_undef.inc", p);
}

void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) {
  if (!message_generators_.empty()) {
    p->Emit({{"len", message_generators_.size()}}, R"cc(
      static ::_pb::Metadata $file_level_metadata$[$len$];
    )cc");
  }

  if (!enum_generators_.empty()) {
    p->Emit({{"len", enum_generators_.size()}}, R"cc(
      static const ::_pb::EnumDescriptor* $file_level_enum_descriptors$[$len$];
    )cc");
  } else {
    p->Emit(R"cc(
      static constexpr const ::_pb::EnumDescriptor**
          $file_level_enum_descriptors$ = nullptr;
    )cc");
  }

  if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
    p->Emit({{"len", file_->service_count()}}, R"cc(
      static const ::_pb::ServiceDescriptor*
          $file_level_service_descriptors$[$len$];
    )cc");
  } else {
    p->Emit(R"cc(
      static constexpr const ::_pb::ServiceDescriptor**
          $file_level_service_descriptors$ = nullptr;
    )cc");
  }

  if (!message_generators_.empty()) {
    std::vector<std::pair<size_t, size_t>> offsets;
    offsets.reserve(message_generators_.size());

    p->Emit(
        {
            {"offsets",
             [&] {
               for (int i = 0; i < message_generators_.size(); ++i) {
                 offsets.push_back(message_generators_[i]->GenerateOffsets(p));
               }
             }},
            {"schemas",
             [&] {
               int offset = 0;
               for (int i = 0; i < message_generators_.size(); ++i) {
                 message_generators_[i]->GenerateSchema(p, offset,
                                                        offsets[i].second);
                 offset += offsets[i].first;
               }
             }},
            {"defaults",
             [&] {
               for (auto& gen : message_generators_) {
                 p->Emit(
                     {
                         {"ns", Namespace(gen->descriptor(), options_)},
                         {"class", ClassName(gen->descriptor())},
                     },
                     R"cc(
                       &$ns$::_$class$_default_instance_._instance,
                     )cc");
               }
             }},
        },
        R"cc(
          const ::uint32_t $tablename$::offsets[] PROTOBUF_SECTION_VARIABLE(
              protodesc_cold) = {
              $offsets$,
          };

          static const ::_pbi::MigrationSchema
              schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
                  $schemas$,
          };

          static const ::_pb::Message* const file_default_instances[] = {
              $defaults$,
          };
        )cc");
  } else {
    // Ee still need these symbols to exist.
    //
    // MSVC doesn't like empty arrays, so we add a dummy.
    p->Emit(R"cc(
      const ::uint32_t $tablename$::offsets[1] = {};
      static constexpr ::_pbi::MigrationSchema* schemas = nullptr;
      static constexpr ::_pb::Message* const* file_default_instances = nullptr;
    )cc");
  }

  // ---------------------------------------------------------------

  // Embed the descriptor.  We simply serialize the entire
  // FileDescriptorProto/ and embed it as a string literal, which is parsed and
  // built into real descriptors at initialization time.

  FileDescriptorProto file_proto;
  file_->CopyTo(&file_proto);
  std::string file_data;
  file_proto.SerializeToString(&file_data);

  auto desc_name = UniqueName("descriptor_table_protodef", file_, options_);
  p->Emit(
      {{"desc_name", desc_name},
       {"encoded_file_proto",
        [&] {
          absl::string_view data = file_data;
          if (data.size() <= 65535) {
            static constexpr size_t kBytesPerLine = 40;
            while (!data.empty()) {
              auto to_write = std::min(kBytesPerLine, data.size());
              auto chunk = data.substr(0, to_write);
              data = data.substr(to_write);

              p->Emit({{"text", EscapeTrigraphs(absl::CEscape(chunk))}}, R"cc(
                "$text$"
              )cc");
            }
            return;
          }

          // Workaround for MSVC: "Error C1091: compiler limit: string exceeds
          // 65535 bytes in length". Declare a static array of chars rather than
          // use a string literal. Only write 25 bytes per line.
          static constexpr size_t kBytesPerLine = 25;
          while (!data.empty()) {
            auto to_write = std::min(kBytesPerLine, data.size());
            auto chunk = data.substr(0, to_write);
            data = data.substr(to_write);

            std::string line;
            for (char c : chunk) {
              absl::StrAppend(&line, "'",
                              absl::CEscape(absl::string_view(&c, 1)), "', ");
            }

            p->Emit({{"line", line}}, R"cc(
              $line$
            )cc");
          }
        }}},
      R"cc(
        const char $desc_name$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
            $encoded_file_proto$,
        };
      )cc");

  CrossFileReferences refs;
  GetCrossFileReferencesForFile(file_, &refs);
  size_t num_deps =
      refs.strong_reflection_files.size() + refs.weak_reflection_files.size();

  // Build array of DescriptorTable deps.
  if (num_deps > 0) {
    p->Emit(
        {
            {"len", num_deps},
            {"deps",
             [&] {
               for (auto dep : refs.strong_reflection_files) {
                 p->Emit({{"name", DescriptorTableName(dep, options_)}}, R"cc(
                   &::$name$,
                 )cc");
               }
               for (auto dep : refs.weak_reflection_files) {
                 p->Emit({{"name", DescriptorTableName(dep, options_)}}, R"cc(
                   &::$name$,
                 )cc");
               }
             }},
        },
        R"cc(
          static const ::_pbi::DescriptorTable* const $desc_table$_deps[$len$] =
              {
                  $deps$,
          };
        )cc");
  }

  // The DescriptorTable itself.
  // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);"
  // however this might cause a tsan failure in superroot b/148382879,
  // so disable for now.
  bool eager = false;
  p->Emit(
      {
          {"eager", eager ? "true" : "false"},
          {"file_proto_len", file_data.size()},
          {"proto_name", desc_name},
          {"deps_ptr", num_deps == 0
                           ? "nullptr"
                           : absl::StrCat(p->LookupVar("desc_table"), "_deps")},
          {"num_deps", num_deps},
          {"num_msgs", message_generators_.size()},
          {"msgs_ptr", message_generators_.empty()
                           ? "nullptr"
                           : std::string(p->LookupVar("file_level_metadata"))},
      },
      R"cc(
        static ::absl::once_flag $desc_table$_once;
        const ::_pbi::DescriptorTable $desc_table$ = {
            false,
            $eager$,
            $file_proto_len$,
            $proto_name$,
            "$filename$",
            &$desc_table$_once,
            $deps_ptr$,
            $num_deps$,
            $num_msgs$,
            schemas,
            file_default_instances,
            $tablename$::offsets,
            $msgs_ptr$,
            $file_level_enum_descriptors$,
            $file_level_service_descriptors$,
        };

        // This function exists to be marked as weak.
        // It can significantly speed up compilation by breaking up LLVM's SCC
        // in the .pb.cc translation units. Large translation units see a
        // reduction of more than 35% of walltime for optimized builds. Without
        // the weak attribute all the messages in the file, including all the
        // vtables and everything they use become part of the same SCC through
        // a cycle like:
        // GetMetadata -> descriptor table -> default instances ->
        //   vtables -> GetMetadata
        // By adding a weak function here we break the connection from the
        // individual vtables back into the descriptor table.
        PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* $desc_table$_getter() {
          return &$desc_table$;
        }
      )cc");

  // For descriptor.proto we want to avoid doing any dynamic initialization,
  // because in some situations that would otherwise pull in a lot of
  // unnecessary code that can't be stripped by --gc-sections. Descriptor
  // initialization will still be performed lazily when it's needed.
  if (file_->name() == "net/proto2/proto/descriptor.proto") {
    return;
  }

  p->Emit({{"dummy", UniqueName("dynamic_init_dummy", file_, options_)}}, R"cc(
    // Force running AddDescriptors() at dynamic initialization time.
    PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
    static ::_pbi::AddDescriptorsRunner $dummy$(&$desc_table$);
  )cc");
}

class FileGenerator::ForwardDeclarations {
 public:
  void AddMessage(const Descriptor* d) { classes_.emplace(ClassName(d), d); }
  void AddEnum(const EnumDescriptor* d) { enums_.emplace(ClassName(d), d); }
  void AddSplit(const Descriptor* d) { splits_.emplace(ClassName(d), d); }

  void Print(io::Printer* p, const Options& options) const {
    for (const auto& e : enums_) {
      p->Emit({{"enum", e.first, e.second}}, R"cc(
        enum $enum$ : int;
        bool $enum$_IsValid(int value);
      )cc");
    }

    for (const auto& c : classes_) {
      const Descriptor* desc = c.second;
      p->Emit(
          {
              {"class", c.first, desc},
              {"default_type", DefaultInstanceType(desc, options)},
              {"default_name", DefaultInstanceName(desc, options)},
          },
          R"cc(
            class $class$;
            struct $default_type$;
            $dllexport_decl $extern $default_type$ $default_name$;
          )cc");
    }

    for (const auto& s : splits_) {
      const Descriptor* desc = s.second;
      p->Emit(
          {
              {"default_type",
               DefaultInstanceType(desc, options, /*split=*/true)},
              {"default_name",
               DefaultInstanceName(desc, options, /*split=*/true)},
          },
          R"cc(
            struct $default_type$;
            $dllexport_decl $extern const $default_type$ $default_name$;
          )cc");
    }
  }

  void PrintTopLevelDecl(io::Printer* p, const Options& options) const {
    for (const auto& c : classes_) {
      p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc(
        template <>
        $dllexport_decl $$class$* Arena::CreateMaybeMessage<$class$>(Arena*);
      )cc");
    }
  }

 private:
  absl::btree_map<std::string, const Descriptor*> classes_;
  absl::btree_map<std::string, const EnumDescriptor*> enums_;
  absl::btree_map<std::string, const Descriptor*> splits_;
};

static void PublicImportDFS(
    const FileDescriptor* fd,
    absl::flat_hash_set<const FileDescriptor*>& fd_set) {
  for (int i = 0; i < fd->public_dependency_count(); ++i) {
    const FileDescriptor* dep = fd->public_dependency(i);
    if (fd_set.insert(dep).second) {
      PublicImportDFS(dep, fd_set);
    }
  }
}

void FileGenerator::GenerateForwardDeclarations(io::Printer* p) {
  std::vector<const Descriptor*> classes;
  FlattenMessagesInFile(file_, &classes);  // All messages need forward decls.

  std::vector<const EnumDescriptor*> enums;
  if (options_.proto_h) {  // proto.h needs extra forward declarations.
    // All classes / enums referred to as field members
    std::vector<const FieldDescriptor*> fields;
    ListAllFields(file_, &fields);
    for (const auto* field : fields) {
      classes.push_back(field->containing_type());
      classes.push_back(field->message_type());
      enums.push_back(field->enum_type());
    }

    ListAllTypesForServices(file_, &classes);
  }

  // Calculate the set of files whose definitions we get through include.
  // No need to forward declare types that are defined in these.
  absl::flat_hash_set<const FileDescriptor*> public_set;
  PublicImportDFS(file_, public_set);

  absl::btree_map<std::string, ForwardDeclarations> decls;
  for (const auto* d : classes) {
    if (d != nullptr && !public_set.count(d->file()))
      decls[Namespace(d, options_)].AddMessage(d);
  }
  for (const auto* e : enums) {
    if (e != nullptr && !public_set.count(e->file()))
      decls[Namespace(e, options_)].AddEnum(e);
  }
  for (const auto& mg : message_generators_) {
    const Descriptor* d = mg->descriptor();
    if (d != nullptr && public_set.count(d->file()) == 0u &&
        ShouldSplit(mg->descriptor(), options_))
      decls[Namespace(d, options_)].AddSplit(d);
  }

  NamespaceOpener ns(p);
  for (const auto& decl : decls) {
    ns.ChangeTo(decl.first);
    decl.second.Print(p, options_);
  }

  ns.ChangeTo("PROTOBUF_NAMESPACE_ID");
  for (const auto& decl : decls) {
    decl.second.PrintTopLevelDecl(p, options_);
  }
}

void FileGenerator::GenerateLibraryIncludes(io::Printer* p) {
  if (UsingImplicitWeakFields(file_, options_)) {
    IncludeFile("net/proto2/public/implicit_weak_message.h", p);
  }
  if (HasWeakFields(file_, options_)) {
    GOOGLE_CHECK(!options_.opensource_runtime);
    IncludeFile("net/proto2/public/weak_field_map.h", p);
  }
  if (HasLazyFields(file_, options_, &scc_analyzer_)) {
    GOOGLE_CHECK(!options_.opensource_runtime);
    IncludeFile("net/proto2/public/lazy_field.h", p);
  }
  if (ShouldVerify(file_, options_, &scc_analyzer_)) {
    IncludeFile("net/proto2/public/wire_format_verify.h", p);
  }

  if (options_.opensource_runtime) {
    // Verify the protobuf library header version is compatible with the protoc
    // version before going any further.
    IncludeFile("net/proto2/public/port_def.inc", p);
    p->Emit(
        {
            {"min_version", PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC},
            {"version", PROTOBUF_VERSION},
        },
        R"(
        #if PROTOBUF_VERSION < $min_version$
        #error "This file was generated by a newer version of protoc which is"
        #error "incompatible with your Protocol Buffer headers. Please update"
        #error "your headers."
        #endif  // PROTOBUF_VERSION

        #if $version$ < PROTOBUF_MIN_PROTOC_VERSION
        #error "This file was generated by an older version of protoc which is"
        #error "incompatible with your Protocol Buffer headers. Please"
        #error "regenerate this file with a newer version of protoc."
        #endif  // PROTOBUF_MIN_PROTOC_VERSION
    )");
    IncludeFile("net/proto2/public/port_undef.inc", p);
  }

  // OK, it's now safe to #include other files.
  IncludeFile("net/proto2/io/public/coded_stream.h", p);
  IncludeFile("net/proto2/public/arena.h", p);
  IncludeFile("net/proto2/public/arenastring.h", p);
  if ((options_.force_inline_string || options_.profile_driven_inline_string) &&
      !options_.opensource_runtime) {
    IncludeFile("net/proto2/public/inlined_string_field.h", p);
  }
  if (HasSimpleBaseClasses(file_, options_)) {
    IncludeFile("net/proto2/public/generated_message_bases.h", p);
  }
  if (HasGeneratedMethods(file_, options_) &&
      options_.tctable_mode != Options::kTCTableNever) {
    IncludeFile("net/proto2/public/generated_message_tctable_decl.h", p);
  }
  IncludeFile("net/proto2/public/generated_message_util.h", p);
  IncludeFile("net/proto2/public/metadata_lite.h", p);

  if (HasDescriptorMethods(file_, options_)) {
    IncludeFile("net/proto2/public/generated_message_reflection.h", p);
  }

  if (!message_generators_.empty()) {
    if (HasDescriptorMethods(file_, options_)) {
      IncludeFile("net/proto2/public/message.h", p);
    } else {
      IncludeFile("net/proto2/public/message_lite.h", p);
    }
  }
  if (options_.opensource_runtime) {
    // Open-source relies on unconditional includes of these.
    IncludeFileAndExport("net/proto2/public/repeated_field.h", p);
    IncludeFileAndExport("net/proto2/public/extension_set.h", p);
  } else {
    // Google3 includes these files only when they are necessary.
    if (HasExtensionsOrExtendableMessage(file_)) {
      IncludeFileAndExport("net/proto2/public/extension_set.h", p);
    }
    if (HasRepeatedFields(file_)) {
      IncludeFileAndExport("net/proto2/public/repeated_field.h", p);
    }
    if (HasStringPieceFields(file_, options_)) {
      IncludeFile("net/proto2/public/string_piece_field_support.h", p);
    }
    if (HasCordFields(file_, options_)) {
      p->Emit(R"(
        #include "third_party/absl/strings/cord.h"
      )");
    }
  }
  if (HasMapFields(file_)) {
    IncludeFileAndExport("net/proto2/public/map.h", p);
    if (HasDescriptorMethods(file_, options_)) {
      IncludeFile("net/proto2/public/map_entry.h", p);
      IncludeFile("net/proto2/public/map_field_inl.h", p);
    } else {
      IncludeFile("net/proto2/public/map_entry_lite.h", p);
      IncludeFile("net/proto2/public/map_field_lite.h", p);
    }
  }

  if (HasEnumDefinitions(file_)) {
    if (HasDescriptorMethods(file_, options_)) {
      IncludeFile("net/proto2/public/generated_enum_reflection.h", p);
    } else {
      IncludeFile("net/proto2/public/generated_enum_util.h", p);
    }
  }

  if (HasGenericServices(file_, options_)) {
    IncludeFile("net/proto2/public/service.h", p);
  }

  if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
    IncludeFile("net/proto2/public/unknown_field_set.h", p);
  }
}

void FileGenerator::GenerateMetadataPragma(io::Printer* p,
                                           absl::string_view info_path) {
  if (info_path.empty() || options_.annotation_pragma_name.empty() ||
      options_.annotation_guard_name.empty()) {
    return;
  }

  p->Emit(
      {
          {"guard", options_.annotation_guard_name},
          {"pragma", options_.annotation_pragma_name},
          {"info_path", std::string(info_path)},
      },
      R"(
        #ifdef $guard$
        #pragma $pragma$ "$info_path$"
        #endif  // $guard$
      )");
}

void FileGenerator::GenerateDependencyIncludes(io::Printer* p) {
  for (int i = 0; i < file_->dependency_count(); ++i) {
    const FileDescriptor* dep = file_->dependency(i);

    // Do not import weak deps.
    if (IsDepWeak(dep)) {
      continue;
    }

    std::string basename = StripProto(dep->name());
    if (IsBootstrapProto(options_, file_)) {
      GetBootstrapBasename(options_, basename, &basename);
    }

    p->Emit(
        {{"name", CreateHeaderInclude(absl::StrCat(basename, ".pb.h"), dep)}},
        R"(
          #include $name$
        )");
  }
}

void FileGenerator::GenerateGlobalStateFunctionDeclarations(io::Printer* p) {
  // Forward-declare the DescriptorTable because this is referenced by .pb.cc
  // files depending on this file.
  //
  // The TableStruct is also outputted in weak_message_field.cc, because the
  // weak fields must refer to table struct but cannot include the header.
  // Also it annotates extra weak attributes.
  // TODO(gerbens) make sure this situation is handled better.
  p->Emit(R"cc(
    // Internal implementation detail -- do not use these members.
    struct $dllexport_decl $$tablename$ {
      static const ::uint32_t offsets[];
    };
  )cc");

  if (HasDescriptorMethods(file_, options_)) {
    p->Emit(R"cc(
      $dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable
          $desc_table$;
    )cc");
  }
}

void FileGenerator::GenerateMessageDefinitions(io::Printer* p) {
  for (int i = 0; i < message_generators_.size(); ++i) {
    p->Emit(R"cc(
      $hrule_thin$
    )cc");
    message_generators_[i]->GenerateClassDefinition(p);
  }
}

void FileGenerator::GenerateEnumDefinitions(io::Printer* p) {
  for (int i = 0; i < enum_generators_.size(); ++i) {
    enum_generators_[i]->GenerateDefinition(p);
  }
}

void FileGenerator::GenerateServiceDefinitions(io::Printer* p) {
  if (!HasGenericServices(file_, options_)) {
    return;
  }

  for (int i = 0; i < service_generators_.size(); ++i) {
    p->Emit(R"cc(
      $hrule_thin$
    )cc");
    service_generators_[i]->GenerateDeclarations(p);
  }

  p->Emit(R"cc(
    $hrule_thick$
  )cc");
}

void FileGenerator::GenerateExtensionIdentifiers(io::Printer* p) {
  // Declare extension identifiers. These are in global scope and so only
  // the global scope extensions.
  for (auto& extension_generator : extension_generators_) {
    if (extension_generator->IsScoped()) {
      continue;
    }
    extension_generator->GenerateDeclaration(p);
  }
}

void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* p) {
  // TODO(gerbens) remove pragmas when gcc is no longer used. Current version
  // of gcc fires a bogus error when compiled with strict-aliasing.
  p->Emit(R"(
      #ifdef __GNUC__
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wstrict-aliasing"
      #endif  // __GNUC__
  )");

  for (int i = 0; i < message_generators_.size(); ++i) {
    p->Emit(R"cc(
      $hrule_thin$
    )cc");
    message_generators_[i]->GenerateInlineMethods(p);
  }

  p->Emit(R"(
      #ifdef __GNUC__
      #pragma GCC diagnostic pop
      #endif  // __GNUC__
  )");
}

void FileGenerator::GenerateProto2NamespaceEnumSpecializations(io::Printer* p) {
  // Emit GetEnumDescriptor specializations into google::protobuf namespace.
  if (!HasEnumDefinitions(file_)) {
    return;
  }

  p->PrintRaw("\n");
  NamespaceOpener ns(ProtobufNamespace(options_), p);
  p->PrintRaw("\n");
  for (auto& gen : enum_generators_) {
    gen->GenerateGetEnumDescriptorSpecializations(p);
  }
  p->PrintRaw("\n");
}
}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf
}  // namespace google
