aboutsummaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/compiler/cpp/cpp_file.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_file.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc151
1 files changed, 104 insertions, 47 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 80da7e4..f7f2cdd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -33,6 +33,9 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/cpp/cpp_file.h>
+#include <memory>
+#include <set>
+
#include <google/protobuf/compiler/cpp/cpp_enum.h>
#include <google/protobuf/compiler/cpp/cpp_service.h>
#include <google/protobuf/compiler/cpp/cpp_extension.h>
@@ -50,37 +53,36 @@ namespace cpp {
// ===================================================================
-FileGenerator::FileGenerator(const FileDescriptor* file,
- const string& dllexport_decl)
- : file_(file),
- message_generators_(
- new scoped_ptr<MessageGenerator>[file->message_type_count()]),
- enum_generators_(
- new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
- service_generators_(
- new scoped_ptr<ServiceGenerator>[file->service_count()]),
- extension_generators_(
- new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
- dllexport_decl_(dllexport_decl) {
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
+ : file_(file),
+ message_generators_(
+ new scoped_ptr<MessageGenerator>[file->message_type_count()]),
+ enum_generators_(
+ new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
+ service_generators_(
+ new scoped_ptr<ServiceGenerator>[file->service_count()]),
+ extension_generators_(
+ new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
+ options_(options) {
for (int i = 0; i < file->message_type_count(); i++) {
message_generators_[i].reset(
- new MessageGenerator(file->message_type(i), dllexport_decl));
+ new MessageGenerator(file->message_type(i), options));
}
for (int i = 0; i < file->enum_type_count(); i++) {
enum_generators_[i].reset(
- new EnumGenerator(file->enum_type(i), dllexport_decl));
+ new EnumGenerator(file->enum_type(i), options));
}
for (int i = 0; i < file->service_count(); i++) {
service_generators_[i].reset(
- new ServiceGenerator(file->service(i), dllexport_decl));
+ new ServiceGenerator(file->service(i), options));
}
for (int i = 0; i < file->extension_count(); i++) {
extension_generators_[i].reset(
- new ExtensionGenerator(file->extension(i), dllexport_decl));
+ new ExtensionGenerator(file->extension(i), options));
}
SplitStringUsing(file_->package(), ".", &package_parts_);
@@ -104,6 +106,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"filename", file_->name(),
"filename_identifier", filename_identifier);
+
printer->Print(
"#include <google/protobuf/stubs/common.h>\n"
"\n");
@@ -128,13 +131,23 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// OK, it's now safe to #include other files.
printer->Print(
- "#include <google/protobuf/generated_message_util.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n");
+ if (file_->message_type_count() > 0) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/message.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/message_lite.h>\n");
+ }
+ }
+ printer->Print(
"#include <google/protobuf/repeated_field.h>\n"
"#include <google/protobuf/extension_set.h>\n");
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
printer->Print(
- "#include <google/protobuf/generated_message_reflection.h>\n");
+ "#include <google/protobuf/generated_enum_reflection.h>\n");
}
if (HasGenericServices(file_)) {
@@ -142,16 +155,32 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#include <google/protobuf/service.h>\n");
}
+ if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+ printer->Print(
+ "#include <google/protobuf/unknown_field_set.h>\n");
+ }
+
+
+ set<string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
for (int i = 0; i < file_->dependency_count(); i++) {
+ const string& name = file_->dependency(i)->name();
+ bool public_import = (public_import_names.count(name) != 0);
+
+
printer->Print(
- "#include \"$dependency$.pb.h\"\n",
- "dependency", StripProto(file_->dependency(i)->name()));
+ "#include \"$dependency$.pb.h\"$iwyu$\n",
+ "dependency", StripProto(name),
+ "iwyu", (public_import) ? " // IWYU pragma: export" : "");
}
printer->Print(
"// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -162,7 +191,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// Internal implementation detail -- do not call these.\n"
"void $dllexport_decl$ $adddescriptorsname$();\n",
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "dllexport_decl", dllexport_decl_);
+ "dllexport_decl", options_.dllexport_decl);
printer->Print(
// Note that we don't put dllexport_decl on these because they are only
@@ -230,6 +259,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(kThickSeparator);
printer->Print("\n");
+
// Generate class inline methods.
for (int i = 0; i < file_->message_type_count(); i++) {
if (i > 0) {
@@ -282,20 +312,33 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
"\n"
+
// The generated code calls accessors that might be deprecated. We don't
// want the compiler to warn in generated code.
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
"#include \"$basename$.pb.h\"\n"
-
+ "\n"
+ "#include <algorithm>\n" // for swap()
+ "\n"
+ "#include <google/protobuf/stubs/common.h>\n"
"#include <google/protobuf/stubs/once.h>\n"
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/wire_format_lite_inl.h>\n",
+ "filename", file_->name(),
"basename", StripProto(file_->name()));
+ // Unknown fields implementation in lite mode uses StringOutputStream
+ if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+ printer->Print(
+ "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
+ }
+
if (HasDescriptorMethods(file_)) {
printer->Print(
"#include <google/protobuf/descriptor.h>\n"
+ "#include <google/protobuf/generated_message_reflection.h>\n"
"#include <google/protobuf/reflection_ops.h>\n"
"#include <google/protobuf/wire_format.h>\n");
}
@@ -378,11 +421,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// AddDescriptors() is a file-level procedure which adds the encoded
- // FileDescriptorProto for this .proto file to the global DescriptorPool
- // for generated files (DescriptorPool::generated_pool()). It always runs
- // at static initialization time, so all files will be registered before
- // main() starts. This procedure also constructs default instances and
- // registers extensions.
+ // FileDescriptorProto for this .proto file to the global DescriptorPool for
+ // generated files (DescriptorPool::generated_pool()). It either runs at
+ // static initialization time (by default) or when default_instance() is
+ // called for the first time (in LITE_RUNTIME mode with
+ // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
+ // constructs default instances and registers extensions.
//
// Its sibling, AssignDescriptors(), actually pulls the compiled
// FileDescriptor from the DescriptorPool and uses it to populate all of
@@ -486,22 +530,29 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
printer->Outdent();
printer->Print(
- "}\n");
+ "}\n\n");
// -----------------------------------------------------------------
// Now generate the AddDescriptors() function.
- printer->Print(
- "\n"
+ PrintHandlingOptionalStaticInitializers(
+ file_, printer,
+ // With static initializers.
+ // Note that we don't need any special synchronization in the following code
+ // because it is called at static init time before any threads exist.
"void $adddescriptorsname$() {\n"
- // We don't need any special synchronization here because this code is
- // called at static init time before any threads exist.
" static bool already_here = false;\n"
" if (already_here) return;\n"
" already_here = true;\n"
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
"\n",
+ // Without.
+ "void $adddescriptorsname$_impl() {\n"
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
+ // Vars.
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+
printer->Indent();
// Call the AddDescriptors() methods for all of our dependencies, to make
@@ -509,17 +560,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
for (int i = 0; i < file_->dependency_count(); i++) {
const FileDescriptor* dependency = file_->dependency(i);
// Print the namespace prefix for the dependency.
- vector<string> dependency_package_parts;
- SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
- printer->Print("::");
- for (int i = 0; i < dependency_package_parts.size(); i++) {
- printer->Print("$name$::",
- "name", dependency_package_parts[i]);
- }
+ string add_desc_name = QualifiedFileLevelSymbol(
+ dependency->package(), GlobalAddDescriptorsName(dependency->name()));
// Call its AddDescriptors function.
printer->Print(
"$name$();\n",
- "name", GlobalAddDescriptorsName(dependency->name()));
+ "name", add_desc_name);
}
if (HasDescriptorMethods(file_)) {
@@ -538,10 +584,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
printer->Print("\n \"$data$\"",
- "data", CEscape(file_data.substr(i, kBytesPerLine)));
+ "data",
+ EscapeTrigraphs(
+ CEscape(file_data.substr(i, kBytesPerLine))));
}
printer->Print(
- ", $size$);\n",
+ ", $size$);\n",
"size", SimpleItoa(file_data.size()));
// Call MessageFactory::InternalRegisterGeneratedFile().
@@ -569,17 +617,26 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"shutdownfilename", GlobalShutdownFileName(file_->name()));
printer->Outdent();
-
printer->Print(
"}\n"
- "\n"
+ "\n");
+
+ PrintHandlingOptionalStaticInitializers(
+ file_, printer,
+ // With static initializers.
"// Force AddDescriptors() to be called at static initialization time.\n"
"struct StaticDescriptorInitializer_$filename$ {\n"
" StaticDescriptorInitializer_$filename$() {\n"
" $adddescriptorsname$();\n"
" }\n"
- "} static_descriptor_initializer_$filename$_;\n"
- "\n",
+ "} static_descriptor_initializer_$filename$_;\n",
+ // Without.
+ "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
+ "void $adddescriptorsname$() {\n"
+ " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
+ " &$adddescriptorsname$_impl);\n"
+ "}\n",
+ // Vars.
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
"filename", FilenameIdentifier(file_->name()));
}