aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler
diff options
context:
space:
mode:
authorGravatar Adam Cozzette <acozzette@google.com>2017-09-12 10:32:01 -0700
committerGravatar Adam Cozzette <acozzette@google.com>2017-09-14 10:03:57 -0700
commit13fd045dbb2b4dacea32be162a41d5a4b0d1802f (patch)
treec219e7eb18b82523e36c6748861c403a14ea66ae /src/google/protobuf/compiler
parentd1bc27caef8377a710370189675cb0958443e8f1 (diff)
Integrated internal changes from Google
Diffstat (limited to 'src/google/protobuf/compiler')
-rw-r--r--src/google/protobuf/compiler/code_generator.h3
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc55
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h3
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc32
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc38
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h11
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc40
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc1009
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h35
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc31
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc223
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h125
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc41
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc681
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h16
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc336
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h61
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_options.h8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc220
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h64
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc7
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc46
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto4
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc15
-rw-r--r--src/google/protobuf/compiler/importer.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h15
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc175
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc292
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc11
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc92
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc12
-rw-r--r--src/google/protobuf/compiler/parser.cc79
-rw-r--r--src/google/protobuf/compiler/parser.h6
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc98
-rw-r--r--src/google/protobuf/compiler/plugin.cc11
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc905
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h62
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc2
43 files changed, 2635 insertions, 2252 deletions
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index dd6a59d8..4b1d90b8 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -51,6 +51,7 @@ class FileDescriptor;
namespace compiler {
class AccessInfoMap;
+
class Version;
// Defined in this file.
@@ -165,7 +166,7 @@ typedef GeneratorContext OutputDirectory;
// "foo=bar,baz,qux=corge"
// parses to the pairs:
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
-LIBPROTOC_EXPORT void ParseGeneratorParameter(
+void ParseGeneratorParameter(
const string&, std::vector<std::pair<string, string> >*);
} // namespace compiler
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 5f864041..6c2fc164 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -69,9 +69,6 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/compiler/subprocess.h>
#include <google/protobuf/compiler/zip_writer.h>
#include <google/protobuf/compiler/plugin.pb.h>
@@ -83,16 +80,11 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/text_format.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/io_win32.h>
-#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/io_win32.h>
namespace google {
@@ -232,7 +224,7 @@ bool IsInstalledProtoPath(const string& path) {
return access(file_path.c_str(), F_OK) != -1;
}
-// Add the paths where google/protobuf/descritor.proto and other well-known
+// Add the paths where google/protobuf/descriptor.proto and other well-known
// type protos are installed.
void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
// TODO(xiaofeng): The code currently only checks relative paths of where
@@ -876,6 +868,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
return 1;
}
+
// We construct a separate GeneratorContext for each output location. Note
// that two code generators may output to the same location, in which case
// they should share a single GeneratorContext so that OpenForInsert() works.
@@ -1019,7 +1012,8 @@ bool CommandLineInterface::PopulateSimpleDescriptorDatabase(
bool parsed = file_descriptor_set.ParseFromFileDescriptor(fd);
if (close(fd) != 0) {
std::cerr << descriptor_set_in_names_[i] << ": close: "
- << strerror(errno);
+ << strerror(errno)
+ << std::endl;
return false;
}
@@ -1172,6 +1166,21 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative(
return true;
}
+bool CommandLineInterface::ExpandArgumentFile(const string& file,
+ std::vector<string>* arguments) {
+ // The argument file is searched in the working directory only. We don't
+ // use the proto import path here.
+ std::ifstream file_stream(file.c_str());
+ if (!file_stream.is_open()) {
+ return false;
+ }
+ string argument;
+ // We don't support any kind of shell expansion right now.
+ while (std::getline(file_stream, argument)) {
+ arguments->push_back(argument);
+ }
+ return true;
+}
CommandLineInterface::ParseArgumentStatus
CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
@@ -1179,11 +1188,19 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
std::vector<string> arguments;
for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] == '@') {
+ if (!ExpandArgumentFile(argv[i] + 1, &arguments)) {
+ std::cerr << "Failed to open argument file: " << (argv[i] + 1)
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ continue;
+ }
arguments.push_back(argv[i]);
}
// if no arguments are given, show help
- if(arguments.empty()) {
+ if (arguments.empty()) {
PrintHelpText();
return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
}
@@ -1749,6 +1766,20 @@ void CommandLineInterface::PrintHelpText() {
<< string(19 - iter->first.size(), ' ') // Spaces for alignment.
<< iter->second.help_text << std::endl;
}
+ std::cerr <<
+" @<filename> Read options and filenames from file. If a\n"
+" relative file path is specified, the file\n"
+" will be searched in the working directory.\n"
+" The --proto_path option will not affect how\n"
+" this argument file is searched. Content of\n"
+" the file will be expanded in the position of\n"
+" @<filename> as in the argument list. Note\n"
+" that shell expansion is not applied to the\n"
+" content of the file (i.e., you cannot use\n"
+" quotes, wildcards, escapes, commands, etc.).\n"
+" Each line corresponds to a single argument,\n"
+" even if it contains spaces."
+ << std::endl;
}
bool CommandLineInterface::GenerateOutput(
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index e6596575..d5d85f2d 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -227,6 +227,9 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Parse all command-line arguments.
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
+ // Read an argument file and append the file's content to the list of
+ // arguments. Return false if the file cannot be read.
+ bool ExpandArgumentFile(const string& file, std::vector<string>* arguments);
// Parses a command-line argument into a name/value pair. Returns
// true if the next argument in the argv should be used as the value,
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 73d3e4c9..38d0e388 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -35,6 +35,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+
#ifndef _MSC_VER
#include <unistd.h>
#endif
@@ -84,6 +85,7 @@ using google::protobuf::internal::win32::write;
// which case tcmalloc will print warnings that fail the plugin tests.
#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+
namespace {
bool FileExists(const string& path) {
@@ -1559,6 +1561,36 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
}
#endif // !_WIN32
+TEST_F(CommandLineInterfaceTest, TestArgumentFile) {
+ // Test parsing multiple input files using an argument file.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+ CreateTempFile("arguments.txt",
+ "--test_out=$tmpdir\n"
+ "--plug_out=$tmpdir\n"
+ "--proto_path=$tmpdir\n"
+ "--direct_dependencies_violation_msg=%s is not imported\n"
+ "foo.proto\n"
+ "bar.proto");
+
+ Run("protocol_compiler @$tmpdir/arguments.txt");
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+}
+
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 3b4b97e6..8adee0f5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -197,6 +197,8 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
vars["nested_name"] = descriptor_->name();
vars["classname"] = classname_;
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
+ vars["{"] = "";
+ vars["}"] = "";
printer->Print(vars, "typedef $classname$ $nested_name$;\n");
for (int j = 0; j < descriptor_->value_count(); j++) {
@@ -204,22 +206,27 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ?
"GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
printer->Print(vars,
- "$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n"
+ "$deprecated_attr$static $constexpr$const $nested_name$ ${$$tag$$}$ =\n"
" $classname$_$tag$;\n");
+ printer->Annotate("{", "}", descriptor_->value(j));
}
printer->Print(vars,
"static inline bool $nested_name$_IsValid(int value) {\n"
" return $classname$_IsValid(value);\n"
"}\n"
- "static const $nested_name$ $nested_name$_MIN =\n"
- " $classname$_$nested_name$_MIN;\n"
- "static const $nested_name$ $nested_name$_MAX =\n"
+ "static const $nested_name$ ${$$nested_name$_MIN$}$ =\n"
+ " $classname$_$nested_name$_MIN;\n");
+ printer->Annotate("{", "}", descriptor_);
+ printer->Print(vars,
+ "static const $nested_name$ ${$$nested_name$_MAX$}$ =\n"
" $classname$_$nested_name$_MAX;\n");
+ printer->Annotate("{", "}", descriptor_);
if (generate_array_size_) {
printer->Print(vars,
- "static const int $nested_name$_ARRAYSIZE =\n"
+ "static const int ${$$nested_name$_ARRAYSIZE$}$ =\n"
" $classname$_$nested_name$_ARRAYSIZE;\n");
+ printer->Annotate("{", "}", descriptor_);
}
if (HasDescriptorMethods(descriptor_->file(), options_)) {
@@ -242,27 +249,10 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
}
}
-void EnumGenerator::GenerateDescriptorInitializer(io::Printer* printer) {
- std::map<string, string> vars;
- vars["index"] = SimpleItoa(descriptor_->index());
- vars["index_in_metadata"] = SimpleItoa(index_in_metadata_);
-
- if (descriptor_->containing_type() == NULL) {
- printer->Print(vars,
- "file_level_enum_descriptors[$index_in_metadata$] = "
- "file->enum_type($index$);\n");
- } else {
- vars["parent"] = ClassName(descriptor_->containing_type(), false);
- printer->Print(vars,
- "file_level_enum_descriptors[$index_in_metadata$] = "
- "$parent$_descriptor->enum_type($index$);\n");
- }
-}
-
-void EnumGenerator::GenerateMethods(io::Printer* printer) {
+void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
std::map<string, string> vars;
vars["classname"] = classname_;
- vars["index_in_metadata"] = SimpleItoa(index_in_metadata_);
+ vars["index_in_metadata"] = SimpleItoa(idx);
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 0b568c57..0d2488a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -86,13 +86,10 @@ class EnumGenerator {
// Source file stuff.
- // Generate code that initializes the global variable storing the enum's
- // descriptor.
- void GenerateDescriptorInitializer(io::Printer* printer);
-
// Generate non-inline methods related to the enum, such as IsValidValue().
- // Goes in the .cc file.
- void GenerateMethods(io::Printer* printer);
+ // Goes in the .cc file. EnumDescriptors are stored in an array, idx is
+ // the index in this array that corresponds with this enum.
+ void GenerateMethods(int idx, io::Printer* printer);
private:
const EnumDescriptor* descriptor_;
@@ -101,8 +98,6 @@ class EnumGenerator {
// whether to generate the *_ARRAYSIZE constant.
const bool generate_array_size_;
- int index_in_metadata_;
-
friend class FileGenerator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 08a635fa..008490ed 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -232,9 +232,8 @@ GenerateSwappingCode(io::Printer* printer) const {
void EnumOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
- printer->Print(
- variables_,
- "_$classname$_default_instance_.$name$_ = $default$;\n");
+ printer->Print(variables_,
+ "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
}
// ===================================================================
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 6b1673b2..0a4e0bb9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -167,46 +167,6 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
" $name$($constant_name$, $default$);\n");
}
-void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
- std::map<string, string> vars;
- vars["extendee" ] = ExtendeeClassName(descriptor_);
- vars["number" ] = SimpleItoa(descriptor_->number());
- vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
- vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
- vars["is_packed" ] = (descriptor_->is_repeated() &&
- descriptor_->options().packed())
- ? "true" : "false";
-
- switch (descriptor_->cpp_type()) {
- case FieldDescriptor::CPPTYPE_ENUM:
- printer->Print(
- vars,
- "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
- " $extendee$::internal_default_instance(),\n"
- " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
- printer->Print(
- " &$type$_IsValid);\n",
- "type", ClassName(descriptor_->enum_type(), true));
- break;
- case FieldDescriptor::CPPTYPE_MESSAGE:
- printer->Print(
- vars,
- "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
- " $extendee$::internal_default_instance(),\n"
- " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
- printer->Print(" $type$::internal_default_instance());\n", "type",
- ClassName(descriptor_->message_type(), true));
- break;
- default:
- printer->Print(
- vars,
- "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
- " $extendee$::internal_default_instance(),\n"
- " $number$, $field_type$, $is_repeated$, $is_packed$);\n");
- break;
- }
-}
-
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h
index 1c1caf1f..30236d71 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -67,9 +67,6 @@ class ExtensionGenerator {
// Source file stuff.
void GenerateDefinition(io::Printer* printer);
- // Generate code to register the extension.
- void GenerateRegistration(io::Printer* printer);
-
private:
const FieldDescriptor* descriptor_;
string type_traits_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index dce9617c..f8e11855 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -61,6 +61,7 @@ using internal::WireFormat;
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
std::map<string, string>* variables,
const Options& options) {
+ (*variables)["ns"] = Namespace(descriptor);
(*variables)["name"] = FieldName(descriptor);
(*variables)["index"] = SimpleItoa(descriptor->index());
(*variables)["number"] = SimpleItoa(descriptor->number());
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index a066a6a7..0e74f215 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -55,70 +55,24 @@ namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
-namespace {
-// The list of names that are defined as macros on some platforms. We need to
-// #undef them for the generated code to compile.
-const char* kMacroNames[] = {"major", "minor"};
-
-bool IsMacroName(const string& name) {
- // Just do a linear search as the number of elements is very small.
- for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) {
- if (name == kMacroNames[i]) return true;
- }
- return false;
-}
-
-void CollectMacroNames(const Descriptor* message, std::vector<string>* names) {
- for (int i = 0; i < message->field_count(); ++i) {
- const FieldDescriptor* field = message->field(i);
- if (IsMacroName(field->name())) {
- names->push_back(field->name());
- }
- }
- for (int i = 0; i < message->nested_type_count(); ++i) {
- CollectMacroNames(message->nested_type(i), names);
- }
-}
-
-void CollectMacroNames(const FileDescriptor* file, std::vector<string>* names) {
- // 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() != "google/protobuf/compiler/plugin.proto") {
- return;
- }
- for (int i = 0; i < file->message_type_count(); ++i) {
- CollectMacroNames(file->message_type(i), names);
- }
-}
-
-
-} // namespace
-
-// ===================================================================
FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
: file_(file),
options_(options),
scc_analyzer_(options),
- message_generators_owner_(
- new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
enum_generators_owner_(
new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
service_generators_owner_(
new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
extension_generators_owner_(
new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
-
- for (int i = 0; i < file->message_type_count(); i++) {
- message_generators_owner_[i].reset(
- new MessageGenerator(file->message_type(i), options, &scc_analyzer_));
- message_generators_owner_[i]->Flatten(&message_generators_);
- }
-
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->AddGenerators(&enum_generators_,
- &extension_generators_);
+ std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);
+ for (int i = 0; i < msgs.size(); i++) {
+ // Deleted in destructor
+ MessageGenerator* msg_gen =
+ new MessageGenerator(msgs[i], i, options, &scc_analyzer_);
+ message_generators_.push_back(msg_gen);
+ msg_gen->AddGenerators(&enum_generators_, &extension_generators_);
}
for (int i = 0; i < file->enum_type_count(); i++) {
@@ -126,9 +80,6 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
new EnumGenerator(file->enum_type(i), options));
enum_generators_.push_back(enum_generators_owner_[i].get());
}
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->index_in_metadata_ = i;
- }
for (int i = 0; i < file->service_count(); i++) {
service_generators_owner_[i].reset(
@@ -147,14 +98,36 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
extension_generators_.push_back(extension_generators_owner_[i].get());
}
+
package_parts_ = Split(file_->package(), ".", true);
}
-FileGenerator::~FileGenerator() {}
+FileGenerator::~FileGenerator() {
+ for (int i = 0; i < message_generators_.size(); i++) {
+ delete message_generators_[i];
+ }
+}
void FileGenerator::GenerateMacroUndefs(io::Printer* printer) {
+ // 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() != "google/protobuf/compiler/plugin.proto") {
+ return;
+ }
std::vector<string> names_to_undef;
- CollectMacroNames(file_, &names_to_undef);
+ std::vector<const FieldDescriptor*> fields;
+ ListAllFields(file_, &fields);
+ for (int i = 0; i < fields.size(); i++) {
+ const string& name = fields[i]->name();
+ static const char* kMacroNames[] = {"major", "minor"};
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) {
+ if (name == kMacroNames[i]) {
+ names_to_undef.push_back(name);
+ break;
+ }
+ }
+ }
for (int i = 0; i < names_to_undef.size(); ++i) {
printer->Print(
"#ifdef $name$\n"
@@ -170,43 +143,41 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
GenerateMacroUndefs(printer);
- GenerateForwardDeclarations(printer);
-
- // Open namespace.
- GenerateNamespaceOpeners(printer);
-
GenerateGlobalStateFunctionDeclarations(printer);
- printer->Print("\n");
+ GenerateForwardDeclarations(printer);
- GenerateEnumDefinitions(printer);
+ {
+ NamespaceOpener ns(Namespace(file_), printer);
- printer->Print(kThickSeparator);
- printer->Print("\n");
+ printer->Print("\n");
- GenerateMessageDefinitions(printer);
+ GenerateEnumDefinitions(printer);
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
- GenerateServiceDefinitions(printer);
+ GenerateMessageDefinitions(printer);
- GenerateExtensionIdentifiers(printer);
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
+ GenerateServiceDefinitions(printer);
- GenerateInlineFunctionDefinitions(printer);
+ GenerateExtensionIdentifiers(printer);
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n"
- "\n");
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateInlineFunctionDefinitions(printer);
- // Close up namespace.
- GenerateNamespaceClosers(printer);
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n"
+ "\n");
+ }
// We need to specialize some templates in the ::google::protobuf namespace:
GenerateProto2NamespaceEnumSpecializations(printer);
@@ -269,15 +240,12 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer,
// TODO(gerbens) remove this.
printer->Print(
"// @@protoc_insertion_point(includes)\n");
-
- // Open namespace.
- GenerateNamespaceOpeners(printer);
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
- // Close up namespace.
- GenerateNamespaceClosers(printer);
-
+ {
+ NamespaceOpener ns(Namespace(file_), printer);
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+ }
printer->Print(
"\n"
"// @@protoc_insertion_point(global_scope)\n"
@@ -287,7 +255,7 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer,
GenerateBottomHeaderGuard(printer, filename_identifier);
}
-void FileGenerator::GenerateSource(io::Printer* printer) {
+void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
const bool use_system_include = IsWellKnownMessage(file_);
string header =
StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
@@ -295,9 +263,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"// 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 $left$$header$$right$\n"
"\n"
"#include <algorithm>\n" // for swap()
@@ -340,101 +305,129 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print(
"// @@protoc_insertion_point(includes)\n");
+}
+
+void FileGenerator::GenerateSourceDefaultInstance(int idx,
+ io::Printer* printer) {
+ printer->Print(
+ "class $classname$DefaultTypeInternal {\n"
+ " public:\n"
+ " ::google::protobuf::internal::ExplicitlyConstructed<$classname$>\n"
+ " _instance;\n",
+ "classname", message_generators_[idx]->classname_);
+ printer->Indent();
+ message_generators_[idx]->GenerateExtraDefaultFields(printer);
+ printer->Outdent();
+ printer->Print("} _$classname$_default_instance_;\n", "classname",
+ message_generators_[idx]->classname_);
+}
- GenerateNamespaceOpeners(printer);
+namespace {
- for (int i = 0; i < message_generators_.size(); i++) {
- string parent;
- if (IsMapEntryMessage(message_generators_[i]->descriptor_)) {
- parent = ClassName(message_generators_[i]->descriptor_->containing_type(),
- false) +
- "::";
+// Generates weak symbol declarations for types that are to be considered weakly
+// referenced.
+void GenerateWeakDeclarations(
+ const FileDescriptor* file, const Options& options,
+ SCCAnalyzer* scc_analyzer,
+ io::Printer* printer) {
+ std::vector<const FieldDescriptor*> fields;
+ ListAllFields(file, &fields);
+
+ // To ensure determinism and minimize the number of namespace statements,
+ // we output the forward declarations sorted on namespace and type / function
+ // name.
+ std::set<std::pair<string, string> > messages;
+ std::set<std::pair<string, string> > inits;
+ for (int i = 0; i < fields.size(); ++i) {
+ const FieldDescriptor* field = fields[i];
+ bool is_weak = IsImplicitWeakField(field, options);
+ if (is_weak) {
+ const Descriptor* msg = field->message_type();
+ string flns = FileLevelNamespace(msg);
+ string repr = ClassName(scc_analyzer->GetSCC(msg)->GetRepresentative());
+ inits.insert(std::make_pair(flns, "InitDefaults" + repr));
+ inits.insert(std::make_pair(flns, "AddDescriptors"));
+ messages.insert(std::make_pair(Namespace(msg), ClassName(msg)));
}
- printer->Print(
- "class $classname$DefaultTypeInternal {\n"
- "public:\n"
- " ::google::protobuf::internal::ExplicitlyConstructed<$parent$$classname$>\n"
- " _instance;\n",
- "parent", parent, "classname", message_generators_[i]->classname_);
- printer->Indent();
- message_generators_[i]->GenerateExtraDefaultFields(printer);
- printer->Outdent();
- printer->Print(
- "} _$classname$_default_instance_;\n",
- "classname", message_generators_[i]->classname_);
}
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->index_in_metadata_ = i;
+ if (messages.empty()) {
+ return;
}
- if (HasGenericServices(file_, options_)) {
- for (int i = 0; i < service_generators_.size(); i++) {
- service_generators_[i]->index_in_metadata_ = i;
- }
+
+ printer->Print("\n");
+ NamespaceOpener ns(printer);
+ for (std::set<std::pair<string, string> >::const_iterator it =
+ messages.begin();
+ it != messages.end(); ++it) {
+ ns.ChangeTo(it->first);
+ printer->Print(
+ "extern __attribute__((weak)) $classname$DefaultTypeInternal "
+ "_$classname$_default_instance_;\n",
+ "classname", it->second);
+ }
+ for (std::set<std::pair<string, string> >::const_iterator it = inits.begin();
+ it != inits.end(); ++it) {
+ ns.ChangeTo(it->first);
+ printer->Print("void $name$() __attribute__((weak));\n",
+ "name", it->second);
}
+}
- printer->Print(
- "\n"
- "namespace $file_namespace$ {\n"
- "\n",
- "file_namespace", FileLevelNamespace(file_->name()));
+} // namespace
- if (HasDescriptorMethods(file_, options_)) {
- printer->Print(
- "\n"
- "namespace {\n"
- "\n");
+void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
+ GenerateSourceIncludes(printer);
+ GenerateWeakDeclarations(file_, options_, &scc_analyzer_, printer);
- if (!message_generators_.empty()) {
- printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n",
- "size", SimpleItoa(message_generators_.size()));
- }
- if (!enum_generators_.empty()) {
- printer->Print(
- "const ::google::protobuf::EnumDescriptor* "
- "file_level_enum_descriptors[$size$];\n",
- "size", SimpleItoa(enum_generators_.size()));
- }
- if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
- printer->Print(
- "const ::google::protobuf::ServiceDescriptor* "
- "file_level_service_descriptors[$size$];\n",
- "size", SimpleItoa(file_->service_count()));
- }
+ { // package namespace
+ NamespaceOpener ns(Namespace(file_), printer);
+
+ // Define default instances
+ GenerateSourceDefaultInstance(idx, printer);
+
+ // Generate classes.
+ printer->Print("\n");
+ message_generators_[idx]->GenerateClassMethods(printer);
printer->Print(
- "\n"
- "} // namespace\n"
- "\n");
- }
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+ } // end package namespace
- // Define our externally-visible BuildDescriptors() function. (For the lite
- // library, all this does is initialize default instances.)
- GenerateBuildDescriptors(printer);
+ if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
+ NamespaceOpener ns(FileLevelNamespace(file_), printer);
+ GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
+ }
printer->Print(
"\n"
- "} // namespace $file_namespace$\n"
- "\n",
- "file_namespace", FileLevelNamespace(file_->name()));
+ "// @@protoc_insertion_point(global_scope)\n");
+}
+
+void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
+ GenerateSourceIncludes(printer);
+ GenerateWeakDeclarations(file_, options_, &scc_analyzer_, printer);
+
+ // TODO(gerbens) Generate tables here
+
+ // 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_)) {
+ NamespaceOpener ns(FileLevelNamespace(file_), printer);
+ GenerateReflectionInitializationCode(printer);
+ }
+
+ NamespaceOpener ns(Namespace(file_), printer);
// Generate enums.
for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->GenerateMethods(printer);
+ enum_generators_[i]->GenerateMethods(i, printer);
}
- // Generate classes.
- for (int i = 0; i < message_generators_.size(); i++) {
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- message_generators_[i]->GenerateClassMethods(printer);
-
- printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
- // Generate class inline methods.
- message_generators_[i]->GenerateInlineMethods(printer,
- /* is_inline = */ false);
- printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+ // Define extensions.
+ for (int i = 0; i < extension_generators_.size(); i++) {
+ extension_generators_[i]->GenerateDefinition(printer);
}
if (HasGenericServices(file_, options_)) {
@@ -446,18 +439,76 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
service_generators_[i]->GenerateImplementation(printer);
}
}
+}
- // Define extensions.
- for (int i = 0; i < extension_generators_.size(); i++) {
- extension_generators_[i]->GenerateDefinition(printer);
+void FileGenerator::GenerateSource(io::Printer* printer) {
+ GenerateSourceIncludes(printer);
+ GenerateWeakDeclarations(file_, options_, &scc_analyzer_, printer);
+
+ {
+ NamespaceOpener ns(Namespace(file_), printer);
+
+ // Define default instances
+ for (int i = 0; i < message_generators_.size(); i++) {
+ GenerateSourceDefaultInstance(i, printer);
+ if (UsingImplicitWeakFields(file_, options_)) {
+ printer->Print("void $classname$_Reference() {}\n", "classname",
+ message_generators_[i]->classname_);
+ }
+ }
}
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
+ {
+ NamespaceOpener ns(FileLevelNamespace(file_), printer);
+ // Define the initialization code to initialize the default instances.
+ // This code doesn't use a global constructor.
+ GenerateInitializationCode(printer);
- GenerateNamespaceClosers(printer);
+ // 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(printer);
+ }
+ }
+
+
+ {
+ NamespaceOpener ns(Namespace(file_), printer);
+
+ // Actually implement the protos
+
+ // Generate enums.
+ for (int i = 0; i < enum_generators_.size(); i++) {
+ enum_generators_[i]->GenerateMethods(i, printer);
+ }
+ // Generate classes.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+ message_generators_[i]->GenerateClassMethods(printer);
+ }
+
+ if (HasGenericServices(file_, options_)) {
+ // Generate services.
+ for (int i = 0; i < service_generators_.size(); i++) {
+ if (i == 0) printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+ service_generators_[i]->GenerateImplementation(printer);
+ }
+ }
+
+ // Define extensions.
+ for (int i = 0; i < extension_generators_.size(); i++) {
+ extension_generators_[i]->GenerateDefinition(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+ }
printer->Print(
"\n"
"// @@protoc_insertion_point(global_scope)\n");
@@ -512,6 +563,10 @@ class FileGenerator::ForwardDeclarations {
options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ",
"classname",
it->first);
+ if (options.lite_implicit_weak_fields) {
+ printer->Print("void $classname$_Reference();\n",
+ "classname", it->first);
+ }
}
for (std::map<string, ForwardDeclarations *>::const_iterator
it = namespaces_.begin(),
@@ -532,13 +587,11 @@ class FileGenerator::ForwardDeclarations {
std::map<string, const EnumDescriptor*> enums_;
};
-void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
+void FileGenerator::GenerateReflectionInitializationCode(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 ordinarily runs at
- // static initialization time, but is not used at all in LITE_RUNTIME mode
- // except when extensions are used. This procedure also constructs default
- // instances and registers extensions.
+ // static initialization time, but is not used at all in LITE_RUNTIME mode.
//
// Its sibling, AssignDescriptors(), actually pulls the compiled
// FileDescriptor from the DescriptorPool and uses it to populate all of
@@ -547,172 +600,83 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// anyone calls descriptor() or GetReflection() on one of the types defined
// in the file.
- // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
- // and we only use AddDescriptors() to allocate default instances.
-
- // TODO(ckennelly): Gate this with the same options flag to enable
- // table-driven parsing.
-
- printer->Print("PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n"
- " const TableStruct::entries[] "
- "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
-
- std::vector<size_t> entries;
- size_t count = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- size_t value = message_generators_[i]->GenerateParseOffsets(printer);
- entries.push_back(value);
- count += value;
- }
-
- // We need these arrays to exist, and MSVC does not like empty arrays.
- if (count == 0) {
- printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n");
- }
-
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n"
- "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n"
- " const TableStruct::aux[] "
- "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
-
- std::vector<size_t> aux_entries;
- count = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- size_t value = message_generators_[i]->GenerateParseAuxTable(printer);
- aux_entries.push_back(value);
- count += value;
- }
-
- if (count == 0) {
- printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n");
+ if (!message_generators_.empty()) {
+ printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n", "size",
+ SimpleItoa(message_generators_.size()));
}
-
- printer->Outdent();
- printer->Print(
- "};\n"
- "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n"
- " TableStruct::schema[] "
- "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
-
- size_t offset = 0;
- size_t aux_offset = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateParseTable(printer, offset, aux_offset);
- offset += entries[i];
- aux_offset += aux_entries[i];
+ if (!enum_generators_.empty()) {
+ printer->Print(
+ "const ::google::protobuf::EnumDescriptor* "
+ "file_level_enum_descriptors[$size$];\n",
+ "size", SimpleItoa(enum_generators_.size()));
}
-
- if (message_generators_.empty()) {
- printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n");
+ if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
+ printer->Print(
+ "const ::google::protobuf::ServiceDescriptor* "
+ "file_level_service_descriptors[$size$];\n",
+ "size", SimpleItoa(file_->service_count()));
}
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n");
-
- if (!message_generators_.empty() && options_.table_driven_serialization) {
+ if (!message_generators_.empty()) {
printer->Print(
- "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] "
- "= {\n");
+ "\n"
+ "const ::google::protobuf::uint32 TableStruct::offsets[] "
+ "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
printer->Indent();
- std::vector<int> field_metadata_offsets;
- int idx = 0;
+ std::vector<std::pair<size_t, size_t> > pairs;
+ pairs.reserve(message_generators_.size());
for (int i = 0; i < message_generators_.size(); i++) {
- field_metadata_offsets.push_back(idx);
- idx += message_generators_[i]->GenerateFieldMetadata(printer);
+ pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
}
- field_metadata_offsets.push_back(idx);
printer->Outdent();
printer->Print(
"};\n"
- "const ::google::protobuf::internal::SerializationTable "
- "TableStruct::serialization_table[] = {\n");
+ "static const ::google::protobuf::internal::MigrationSchema schemas[] "
+ "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+ printer->Indent();
+ {
+ int offset = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ message_generators_[i]->GenerateSchema(printer, offset,
+ pairs[i].second);
+ offset += pairs[i].first;
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\nstatic "
+ "::google::protobuf::Message const * const file_default_instances[] = {\n");
printer->Indent();
- // We rely on the order we layout the tables to match the order we
- // calculate them with FlattenMessagesInFile, so we check here that
- // these match exactly.
- std::vector<const Descriptor*> calculated_order =
- FlattenMessagesInFile(file_);
- GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size());
for (int i = 0; i < message_generators_.size(); i++) {
- GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_);
+ const Descriptor* descriptor = message_generators_[i]->descriptor_;
printer->Print(
- "{$num_fields$, TableStruct::field_metadata + $index$},\n",
- "classname", message_generators_[i]->classname_, "num_fields",
- SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]),
- "index", SimpleItoa(field_metadata_offsets[i]));
+ "reinterpret_cast<const "
+ "::google::protobuf::Message*>(&$ns$::_$classname$_default_instance_),\n",
+ "classname", ClassName(descriptor), "ns", Namespace(descriptor));
}
printer->Outdent();
printer->Print(
"};\n"
"\n");
+ } else {
+ // we still need these symbols to exist
+ printer->Print(
+ // MSVC doesn't like empty arrays, so we add a dummy.
+ "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n"
+ "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n"
+ "static const ::google::protobuf::Message* const* "
+ "file_default_instances = NULL;\n"
+ "\n");
}
- if (HasDescriptorMethods(file_, options_)) {
- if (!message_generators_.empty()) {
- printer->Print("const ::google::protobuf::uint32 TableStruct::offsets[] "
- "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- std::vector<std::pair<size_t, size_t> > pairs;
- for (int i = 0; i < message_generators_.size(); i++) {
- pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "static const ::google::protobuf::internal::MigrationSchema schemas[] "
- "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
- printer->Indent();
- {
- int offset = 0;
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateSchema(printer, offset,
- pairs[i].second);
- offset += pairs[i].first;
- }
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\nstatic "
- "::google::protobuf::Message const * const file_default_instances[] = {\n");
- printer->Indent();
- for (int i = 0; i < message_generators_.size(); i++) {
- const Descriptor* descriptor = message_generators_[i]->descriptor_;
- printer->Print(
- "reinterpret_cast<const "
- "::google::protobuf::Message*>(&_$classname$_default_instance_),\n",
- "classname", ClassName(descriptor, false));
- }
- printer->Outdent();
- printer->Print(
- "};\n"
- "\n");
- } else {
- // we still need these symbols to exist
- printer->Print(
- // MSVC doesn't like empty arrays, so we add a dummy.
- "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n"
- "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n"
- "static const ::google::protobuf::Message* const* "
- "file_default_instances = NULL;\n");
- }
- // ---------------------------------------------------------------
+ // ---------------------------------------------------------------
- // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
- // AssignDescriptors(). All later times, waits for the first call to
- // complete and then returns.
- string message_factory = "NULL";
+ // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
+ // AssignDescriptors(). All later times, waits for the first call to
+ // complete and then returns.
+ string message_factory = "NULL";
printer->Print(
- "namespace {\n"
- "\n"
"void protobuf_AssignDescriptors() {\n"
// Make sure the file has found its way into the pool. If a descriptor
// is requested *during* static init then AddDescriptors() may not have
@@ -733,20 +697,6 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
? "file_level_service_descriptors"
: "NULL",
"factory", message_factory);
- // TODO(gerbens) have the compiler include the schemas for map types
- // so that this can go away, and we can potentially use table driven
- // serialization for map types as well.
- for (int i = 0; i < message_generators_.size(); i++) {
- if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) continue;
- printer->Print(
- "file_level_metadata[$index$].reflection = "
- "$parent$::$classname$::CreateReflection(file_level_metadata[$index$]"
- ".descriptor, _$classname$_default_instance_._instance.get_mutable());\n",
- "index", SimpleItoa(i), "parent",
- ClassName(message_generators_[i]->descriptor_->containing_type(),
- false),
- "classname", ClassName(message_generators_[i]->descriptor_, false));
- }
printer->Print(
"}\n"
"\n"
@@ -769,7 +719,8 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// protobuf_AssignDescriptorsOnce, because that is called from all the
// GetMetadata member methods.
printer->Print(
- "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n"
+ "void protobuf_RegisterTypes(const ::std::string&) "
+ "GOOGLE_PROTOBUF_ATTRIBUTE_COLD;\n"
"void protobuf_RegisterTypes(const ::std::string&) {\n"
" protobuf_AssignDescriptorsOnce();\n");
printer->Indent();
@@ -783,63 +734,15 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
printer->Outdent();
printer->Print(
- "}\n"
- "\n"
- "} // namespace\n");
- }
-
- // Now generate the InitDefaultsImpl() function.
- printer->Print(
- "void TableStruct::InitDefaultsImpl() {\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"
- // Force initialization of primitive values we depend on.
- " ::google::protobuf::internal::InitProtobufDefaults();\n");
-
- printer->Indent();
-
- // Call the InitDefaults() methods for all of our dependencies, to make
- // sure they get added first.
- for (int i = 0; i < file_->dependency_count(); i++) {
- const FileDescriptor* dependency = file_->dependency(i);
- // Print the namespace prefix for the dependency.
- string file_namespace = QualifiedFileLevelSymbol(
- dependency->package(), FileLevelNamespace(dependency->name()));
- // Call its AddDescriptors function.
- printer->Print("$file_namespace$::InitDefaults();\n", "file_namespace",
- file_namespace);
- }
-
- // Allocate and initialize default instances. This can't be done lazily
- // since default instances are returned by simple accessors and are used with
- // extensions. Speaking of which, we also register extensions at this time.
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
- }
- for (int i = 0; i < extension_generators_.size(); i++) {
- extension_generators_[i]->GenerateRegistration(printer);
- }
- for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
- }
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n"
- "void InitDefaults() {\n"
- " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
- " ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);\n"
- "}\n");
-
- // -----------------------------------------------------------------
+ "}\n"
+ "\n");
- // Now generate the AddDescriptors() function.
- printer->Print(
- "namespace {\n"
- "void AddDescriptorsImpl() {\n"
- " InitDefaults();\n");
+ // Now generate the AddDescriptors() function.
+ printer->Print(
+ "void AddDescriptorsImpl() {\n"
+ " InitDefaults();\n");
+ printer->Indent();
- printer->Indent();
- if (HasDescriptorMethods(file_, options_)) {
// Embed the descriptor. We simply serialize the entire
// FileDescriptorProto
// and embed it as a string literal, which is parsed and built into real
@@ -850,10 +753,11 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
file_proto.SerializeToString(&file_data);
printer->Print("static const char descriptor[] "
- "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+ "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) "
+ "= {\n");
printer->Indent();
- if (file_data.size() > 66535) {
+ if (file_data.size() > 65535) {
// Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
// bytes in length". Declare a static array of characters rather than use
// a string literal. Only write 25 bytes per line.
@@ -887,31 +791,27 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
" \"$filename$\", &protobuf_RegisterTypes);\n",
"filename", file_->name());
- }
// Call the AddDescriptors() methods for all of our dependencies, to make
// sure they get added first.
for (int i = 0; i < file_->dependency_count(); i++) {
const FileDescriptor* dependency = file_->dependency(i);
// Print the namespace prefix for the dependency.
- string file_namespace = QualifiedFileLevelSymbol(
- dependency->package(), FileLevelNamespace(dependency->name()));
+ string file_namespace = FileLevelNamespace(dependency);
// Call its AddDescriptors function.
- printer->Print("$file_namespace$::AddDescriptors();\n", "file_namespace",
+ printer->Print("::$file_namespace$::AddDescriptors();\n", "file_namespace",
file_namespace);
}
printer->Outdent();
printer->Print(
"}\n"
- "} // anonymous namespace\n"
"\n"
"void AddDescriptors() {\n"
" static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
" ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);\n"
"}\n");
- if (StaticInitializersForced(file_, options_)) {
printer->Print(
"// Force AddDescriptors() to be called at dynamic initialization "
"time.\n"
@@ -920,24 +820,213 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
" AddDescriptors();\n"
" }\n"
"} static_descriptor_initializer;\n");
- }
}
-void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
- if (package_parts_.size() > 0) printer->Print("\n");
+void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
+ const string scc_name = ClassName(scc->GetRepresentative());
+ printer->Print(
+ "void InitDefaults$scc_name$Impl() {\n"
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"
+ // Force initialization of primitive values we depend on.
+ " ::google::protobuf::internal::InitProtobufDefaults();\n",
+ "scc_name", scc_name);
- for (int i = 0; i < package_parts_.size(); i++) {
- printer->Print("namespace $part$ {\n",
- "part", package_parts_[i]);
+ printer->Indent();
+
+ // Call the InitDefaults() methods for all of our dependencies, to make
+ // sure they get added first.
+ for (int i = 0; i < scc->children.size(); i++) {
+ const SCC* child_scc = scc->children[i];
+ const FileDescriptor* dependency = child_scc->GetRepresentative()->file();
+ // Print the namespace prefix for the dependency.
+ string file_namespace = FileLevelNamespace(dependency);
+ std::map<string, string> variables;
+ variables["file_namespace"] = file_namespace;
+ variables["scc_name"] = ClassName(child_scc->GetRepresentative(), false);
+ bool using_weak_fields = UsingImplicitWeakFields(file_, options_);
+ if (using_weak_fields) {
+ // We're building for lite with implicit weak fields, so we need to handle
+ // the possibility that this InitDefaults function is not linked into the
+ // binary. Some of these might actually be guaranteed to be non-null since
+ // we might have a strong reference to the dependency (via a required
+ // field, for example), but it's simplest to just assume that any of them
+ // could be null.
+ printer->Print(
+ variables,
+ "if (&$file_namespace$::InitDefaults$scc_name$ != NULL) {\n"
+ " $file_namespace$::InitDefaults$scc_name$();\n"
+ "}\n");
+ } else {
+ printer->Print(variables,
+ "$file_namespace$::InitDefaults$scc_name$();\n");
+ }
+ }
+
+ // First construct all the necessary default instances.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
+ continue;
+ }
+ // TODO(gerbens) This requires this function to be friend. Remove
+ // the need for this.
+ message_generators_[i]->GenerateFieldDefaultInstances(printer);
+ printer->Print(
+ "{\n"
+ " void* ptr = &$ns$::_$classname$_default_instance_;\n"
+ " new (ptr) $ns$::$classname$();\n",
+ "ns", Namespace(message_generators_[i]->descriptor_),
+ "classname", ClassName(message_generators_[i]->descriptor_));
+ if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) {
+ printer->Print(
+ " ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);\n");
+ }
+ printer->Print("}\n");
}
+
+ // TODO(gerbens) make default instances be the same as normal instances.
+ // Default instances differ from normal instances because they have cross
+ // linked message fields.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
+ continue;
+ }
+ printer->Print("$classname$::InitAsDefaultInstance();\n", "classname",
+ QualifiedClassName(message_generators_[i]->descriptor_));
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ printer->Print(
+ "void InitDefaults$scc_name$() {\n"
+ " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
+ " ::google::protobuf::GoogleOnceInit(&once, "
+ "&InitDefaults$scc_name$Impl);\n"
+ "}\n\n",
+ "scc_name", scc_name);
}
-void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
- if (package_parts_.size() > 0) printer->Print("\n");
+void FileGenerator::GenerateInitializationCode(io::Printer* printer) {
+ // Messages depend on the existence of a default instance, which has to
+ // initialized properly. The default instances are allocated in the data
+ // segment, but we can't quite allocate the type directly. The destructors
+ // cannot run at program exit as this could lead to segfaults in a threaded
+ // environment. Hence these instances must be inplace constructed at first
+ // use.
+
+ if (options_.table_driven_parsing) {
+ // TODO(ckennelly): Gate this with the same options flag to enable
+ // table-driven parsing.
+ printer->Print(
+ "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n"
+ " const TableStruct::entries[] "
+ "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+ printer->Indent();
- for (int i = package_parts_.size() - 1; i >= 0; i--) {
- printer->Print("} // namespace $part$\n",
- "part", package_parts_[i]);
+ std::vector<size_t> entries;
+ size_t count = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ size_t value = message_generators_[i]->GenerateParseOffsets(printer);
+ entries.push_back(value);
+ count += value;
+ }
+
+ // We need these arrays to exist, and MSVC does not like empty arrays.
+ if (count == 0) {
+ printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n"
+ "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n"
+ " const TableStruct::aux[] "
+ "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+ printer->Indent();
+
+ std::vector<size_t> aux_entries;
+ count = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ size_t value = message_generators_[i]->GenerateParseAuxTable(printer);
+ aux_entries.push_back(value);
+ count += value;
+ }
+
+ if (count == 0) {
+ printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n"
+ " TableStruct::schema[] "
+ "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+ printer->Indent();
+
+ size_t offset = 0;
+ size_t aux_offset = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ message_generators_[i]->GenerateParseTable(printer, offset, aux_offset);
+ offset += entries[i];
+ aux_offset += aux_entries[i];
+ }
+
+ if (message_generators_.empty()) {
+ printer->Print("{ NULL, NULL, 0, -1, -1, false },\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+ }
+
+ if (!message_generators_.empty() && options_.table_driven_serialization) {
+ printer->Print(
+ "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] "
+ "= {\n");
+ printer->Indent();
+ std::vector<int> field_metadata_offsets;
+ int idx = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ field_metadata_offsets.push_back(idx);
+ idx += message_generators_[i]->GenerateFieldMetadata(printer);
+ }
+ field_metadata_offsets.push_back(idx);
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "const ::google::protobuf::internal::SerializationTable "
+ "TableStruct::serialization_table[] = {\n");
+ printer->Indent();
+ // We rely on the order we layout the tables to match the order we
+ // calculate them with FlattenMessagesInFile, so we check here that
+ // these match exactly.
+ std::vector<const Descriptor*> calculated_order =
+ FlattenMessagesInFile(file_);
+ GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size());
+ for (int i = 0; i < message_generators_.size(); i++) {
+ GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_);
+ printer->Print(
+ "{$num_fields$, TableStruct::field_metadata + $index$},\n",
+ "classname", message_generators_[i]->classname_, "num_fields",
+ SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]),
+ "index", SimpleItoa(field_metadata_offsets[i]));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+ }
+
+ // -----------------------------------------------------------------
+ // All functionality that need private access.
+
+ // Now generate the InitDefaults for each SCC.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
+ GenerateInitForSCC(GetSCC(message_generators_[i]->descriptor_), printer);
+ }
}
}
@@ -985,6 +1074,9 @@ void FileGenerator::GenerateBottomHeaderGuard(
}
void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
+ if (UsingImplicitWeakFields(file_, options_)) {
+ printer->Print("#include <google/protobuf/implicit_weak_message.h>\n");
+ }
printer->Print(
"#include <google/protobuf/stubs/common.h>\n"
@@ -1114,31 +1206,56 @@ void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
void FileGenerator::GenerateGlobalStateFunctionDeclarations(
io::Printer* printer) {
- // Forward-declare the AddDescriptors, AssignDescriptors
- // functions, so that we can declare them to be friends of each class.
+// Forward-declare the AddDescriptors, InitDefaults because these are called
+// by .pb.cc files depending on this file.
printer->Print(
"\n"
"namespace $file_namespace$ {\n"
- "// Internal implementation detail -- do not call these.\n"
+ "// Internal implementation detail -- do not use these members.\n"
"struct $dllexport_decl$TableStruct {\n"
+ // These tables describe how to serialize and parse messages. Used
+ // for table driven code.
" static const ::google::protobuf::internal::ParseTableField entries[];\n"
" static const ::google::protobuf::internal::AuxillaryParseTableField aux[];\n"
- " static const ::google::protobuf::internal::ParseTable schema[];\n"
- " static const ::google::protobuf::uint32 offsets[];\n"
+ " static const ::google::protobuf::internal::ParseTable schema[$num$];\n"
" static const ::google::protobuf::internal::FieldMetadata field_metadata[];\n"
" static const ::google::protobuf::internal::SerializationTable "
"serialization_table[];\n"
- // The following function(s) need to be able to access private members of
- // the messages defined in the file. So we make them static members.
- // This is the internal implementation of InitDefaults. It should only
- // be called by InitDefaults which makes sure it will be called only once.
- " static void InitDefaultsImpl();\n"
- "};\n"
- "void $dllexport_decl$AddDescriptors();\n"
- "void $dllexport_decl$InitDefaults();\n"
- "} // namespace $file_namespace$\n",
- "file_namespace", FileLevelNamespace(file_->name()), "dllexport_decl",
+ " static const ::google::protobuf::uint32 offsets[];\n"
+ "};\n",
+ "file_namespace", FileLevelNamespace(file_), "dllexport_decl",
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ",
+ "num", SimpleItoa(std::max(size_t(1), message_generators_.size())));
+ if (HasDescriptorMethods(file_, options_)) {
+ printer->Print(
+ "void $dllexport_decl$AddDescriptors();\n", "dllexport_decl",
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+ }
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
+ string scc_name = ClassName(message_generators_[i]->descriptor_);
+ // TODO(gerbens) Remove the Impl from header. This is solely because
+ // it currently still needs to be a friend of the protos.
+ printer->Print(
+ "void $dllexport_decl$InitDefaults$scc_name$Impl();\n"
+ "void $dllexport_decl$InitDefaults$scc_name$();\n",
+ "scc_name", scc_name, "dllexport_decl",
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+ }
+ // TODO(gerbens) This is for proto1 interoperability. Remove when proto1
+ // is gone.
+ printer->Print(
+ "inline void $dllexport_decl$InitDefaults() {\n", "dllexport_decl",
options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
+ string scc_name = ClassName(message_generators_[i]->descriptor_);
+ printer->Print(" InitDefaults$scc_name$();\n", "scc_name", scc_name);
+ }
+ printer->Print("}\n");
+ printer->Print(
+ "} // namespace $file_namespace$\n",
+ "file_namespace", FileLevelNamespace(file_));
}
void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
@@ -1187,41 +1304,6 @@ void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
}
void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
- // An aside about inline functions in .proto.h mode:
- //
- // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
- // moving much of the inline functions to the .pb.cc file, which can be a
- // significant performance benefit for compilation time, at the expense
- // of non-inline function calls.
- //
- // However, in .proto.h mode, the definition of the internal dependent
- // base class must remain in the header, and can never be out-lined. The
- // dependent base class also needs access to has-bit manipuation
- // functions, so the has-bit functions must be unconditionally inlined in
- // proto_h mode.
- //
- // This gives us three flavors of functions:
- //
- // 1. Functions on the message not used by the internal dependent base
- // class: in .proto.h mode, only some functions are defined on the
- // message class; others are defined on the dependent base class.
- // These are guarded and can be out-lined. These are generated by
- // GenerateInlineMethods, and include has_* bit functions in
- // non-proto_h mode.
- //
- // 2. Functions on the internal dependent base class: these functions
- // are dependent on a template parameter, so they always need to
- // remain in the header.
- //
- // 3. Functions on the message that are used by the dependent base: the
- // dependent base class down casts itself to the message
- // implementation class to access these functions (the has_* bit
- // manipulation functions). Unlike #1, these functions must
- // unconditionally remain in the header. These are emitted by
- // GenerateDependentInlineMethods, even though they are not actually
- // dependent.
-
- printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
// TODO(gerbens) remove pragmas when gcc is no longer used. Current version
// of gcc fires a bogus error when compiled with strict-aliasing.
printer->Print(
@@ -1242,7 +1324,6 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
"#ifdef __GNUC__\n"
" #pragma GCC diagnostic pop\n"
"#endif // __GNUC__\n");
- printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
for (int i = 0; i < message_generators_.size(); i++) {
if (i > 0) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index e10fe2f3..7e61cbad 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -35,10 +35,12 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
+#include <algorithm>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <set>
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
@@ -82,16 +84,21 @@ class FileGenerator {
const string& info_path);
void GenerateSource(io::Printer* printer);
+ int NumMessages() const { return message_generators_.size(); }
+ // Similar to GenerateSource but generates only one message
+ void GenerateSourceForMessage(int idx, io::Printer* printer);
+ void GenerateGlobalSource(io::Printer* printer);
+
private:
// Internal type used by GenerateForwardDeclarations (defined in file.cc).
class ForwardDeclarations;
- // Generate the BuildDescriptors() procedure, which builds all descriptors
- // for types defined in the file.
- void GenerateBuildDescriptors(io::Printer* printer);
+ void GenerateSourceIncludes(io::Printer* printer);
+ void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
- void GenerateNamespaceOpeners(io::Printer* printer);
- void GenerateNamespaceClosers(io::Printer* printer);
+ void GenerateInitForSCC(const SCC* scc, io::Printer* printer);
+ void GenerateInitializationCode(io::Printer* printer);
+ void GenerateReflectionInitializationCode(io::Printer* printer);
// For other imports, generates their forward-declarations.
void GenerateForwardDeclarations(io::Printer* printer);
@@ -143,11 +150,23 @@ class FileGenerator {
// a breaking change so we prefer the #undef approach.
void GenerateMacroUndefs(io::Printer* printer);
+ bool IsSCCRepresentative(const Descriptor* d) {
+ return GetSCCRepresentative(d) == d;
+ }
+ const Descriptor* GetSCCRepresentative(const Descriptor* d) {
+ return GetSCC(d)->GetRepresentative();
+ }
+ const SCC* GetSCC(const Descriptor* d) {
+ return scc_analyzer_.GetSCC(d);
+ }
+
+
const FileDescriptor* file_;
const Options options_;
SCCAnalyzer scc_analyzer_;
+
// Contains the post-order walk of all the messages (and child messages) in
// this file. If you need a pre-order walk just reverse iterate.
std::vector<MessageGenerator*> message_generators_;
@@ -155,10 +174,8 @@ class FileGenerator {
std::vector<ServiceGenerator*> service_generators_;
std::vector<ExtensionGenerator*> extension_generators_;
- // These members are just for owning (and thus proper deleting). Some of the
- // message_ and enum_generators above are owned by child messages.
- google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> >
- message_generators_owner_;
+ // These members are just for owning (and thus proper deleting).
+ // Nested (enum/extension)_generators are owned by child messages.
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_owner_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> >
service_generators_owner_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 68abd0ef..e01e5dca 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -46,6 +46,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
@@ -84,7 +85,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// __declspec(dllimport) depending on what is being compiled.
//
Options file_options;
-
+ bool split_source = false;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "dllexport_decl") {
file_options.dllexport_decl = options[i].second;
@@ -98,10 +99,14 @@ bool CppGenerator::Generate(const FileDescriptor* file,
file_options.annotation_guard_name = options[i].second;
} else if (options[i].first == "lite") {
file_options.enforce_lite = true;
+ } else if (options[i].first == "lite_implicit_weak_fields") {
+ file_options.lite_implicit_weak_fields = true;
} else if (options[i].first == "table_driven_parsing") {
file_options.table_driven_parsing = true;
} else if (options[i].first == "table_driven_serialization") {
file_options.table_driven_serialization = true;
+ } else if (options[i].first == "split_source") {
+ split_source = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
@@ -135,14 +140,13 @@ bool CppGenerator::Generate(const FileDescriptor* file,
}
}
- basename.append(".pb");
{
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
- generator_context->Open(basename + ".h"));
+ generator_context->Open(basename + ".pb.h"));
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
- string info_path = basename + ".h.meta";
+ string info_path = basename + ".pb.h.meta";
io::Printer printer(output.get(), '$', file_options.annotate_headers
? &annotation_collector
: NULL);
@@ -156,9 +160,24 @@ bool CppGenerator::Generate(const FileDescriptor* file,
}
// Generate cc file.
- {
+ if (split_source) {
+ {
+ // This is the global .cc file, containing enum/services/tables/reflection
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".pb.cc"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateGlobalSource(&printer);
+ }
+ for (int i = 0; i < file_generator.NumMessages(); i++) {
+ // TODO(gerbens) Agree on naming scheme.
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + "." + SimpleItoa(i) + ".cc"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSourceForMessage(i, &printer);
+ }
+ } else {
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
- generator_context->Open(basename + ".cc"));
+ generator_context->Open(basename + ".pb.cc"));
io::Printer printer(output.get(), '$');
file_generator.GenerateSource(&printer);
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 00959796..4aa77d06 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -32,10 +32,11 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <map>
+#include <queue>
#include <vector>
-#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@@ -105,6 +106,30 @@ bool HasExtension(const Descriptor* descriptor) {
return false;
}
+// Encode [0..63] as 'A'-'Z', 'a'-'z', '0'-'9', '_'
+char Base63Char(int value) {
+ GOOGLE_CHECK_GE(value, 0);
+ if (value < 26) return 'A' + value;
+ value -= 26;
+ if (value < 26) return 'a' + value;
+ value -= 26;
+ if (value < 10) return '0' + value;
+ GOOGLE_CHECK_EQ(value, 10);
+ return '_';
+}
+
+// Given a c identifier has 63 legal characters we can't implement base64
+// encoding. So we return the k least significant "digits" in base 63.
+template <typename I>
+string Base63(I n, int k) {
+ string res;
+ while (k-- > 0) {
+ res += Base63Char(static_cast<int>(n % 63));
+ n /= 63;
+ }
+ return res;
+}
+
} // namespace
string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
@@ -137,44 +162,63 @@ const char kThickSeparator[] =
const char kThinSeparator[] =
"// -------------------------------------------------------------------\n";
-string ClassName(const Descriptor* descriptor, bool qualified) {
-
- // Find "outer", the descriptor of the top-level message in which
- // "descriptor" is embedded.
- const Descriptor* outer = descriptor;
- while (outer->containing_type() != NULL) outer = outer->containing_type();
-
- const string& outer_name = outer->full_name();
- string inner_name = descriptor->full_name().substr(outer_name.size());
-
- if (qualified) {
- return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name);
- } else {
- return outer->name() + DotsToUnderscores(inner_name);
+bool CanInitializeByZeroing(const FieldDescriptor* field) {
+ if (field->is_repeated() || field->is_extension()) return false;
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return field->default_value_enum()->number() == 0;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return field->default_value_int32() == 0;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return field->default_value_int64() == 0;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return field->default_value_uint32() == 0;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return field->default_value_uint64() == 0;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return field->default_value_float() == 0;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return field->default_value_double() == 0;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() == false;
+ default:
+ return false;
}
}
-string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
+string ClassName(const Descriptor* descriptor) {
+ const Descriptor* parent = descriptor->containing_type();
+ string res;
+ if (parent) res += ClassName(parent) + "_";
+ res += descriptor->name();
+ if (IsMapEntryMessage(descriptor)) res += "_DoNotUse";
+ return res;
+}
+
+string ClassName(const EnumDescriptor* enum_descriptor) {
if (enum_descriptor->containing_type() == NULL) {
- if (qualified) {
- return "::" + DotsToColons(enum_descriptor->full_name());
- } else {
- return enum_descriptor->name();
- }
+ return enum_descriptor->name();
} else {
- string result = ClassName(enum_descriptor->containing_type(), qualified);
- result += '_';
- result += enum_descriptor->name();
- return result;
+ return ClassName(enum_descriptor->containing_type()) + "_" +
+ enum_descriptor->name();
}
}
+string Namespace(const string& package) {
+ if (package.empty()) return "";
+ return "::" + DotsToColons(package);
+}
+
string DefaultInstanceName(const Descriptor* descriptor) {
string prefix = descriptor->file()->package().empty() ? "" : "::";
return prefix + DotsToColons(descriptor->file()->package()) + "::_" +
ClassName(descriptor, false) + "_default_instance_";
}
+string ReferenceFunctionName(const Descriptor* descriptor) {
+ return QualifiedClassName(descriptor) + "_Reference";
+}
+
string DependentBaseClassTemplateName(const Descriptor* descriptor) {
return ClassName(descriptor, false) + "_InternalBase";
}
@@ -210,6 +254,30 @@ string EnumValueName(const EnumValueDescriptor* enum_value) {
return result;
}
+int EstimateAlignmentSize(const FieldDescriptor* field) {
+ if (field == NULL) return 0;
+ if (field->is_repeated()) return 8;
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return 1;
+
+ case FieldDescriptor::CPPTYPE_INT32:
+ case FieldDescriptor::CPPTYPE_UINT32:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return 4;
+
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT64:
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return 8;
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1; // Make compiler happy.
+}
+
string FieldConstantName(const FieldDescriptor *field) {
string field_name = UnderscoresToCamelCase(field->name(), true);
string result = "k" + field_name + "FieldNumber";
@@ -484,19 +552,6 @@ string SafeFunctionName(const Descriptor* descriptor,
return function_name;
}
-bool StaticInitializersForced(const FileDescriptor* file,
- const Options& options) {
- if (HasDescriptorMethods(file, options) || file->extension_count() > 0) {
- return true;
- }
- for (int i = 0; i < file->message_type_count(); ++i) {
- if (HasExtension(file->message_type(i))) {
- return true;
- }
- }
- return false;
-}
-
static bool HasMapFields(const Descriptor* descriptor) {
for (int i = 0; i < descriptor->field_count(); ++i) {
@@ -672,13 +727,11 @@ void Flatten(const Descriptor* descriptor,
} // namespace
-std::vector<const Descriptor*> FlattenMessagesInFile(
- const FileDescriptor* file) {
- std::vector<const Descriptor*> result;
+void FlattenMessagesInFile(const FileDescriptor* file,
+ std::vector<const Descriptor*>* result) {
for (int i = 0; i < file->message_type_count(); i++) {
- Flatten(file->message_type(i), &result);
+ Flatten(file->message_type(i), result);
}
- return result;
}
bool HasWeakFields(const Descriptor* descriptor) {
@@ -689,6 +742,27 @@ bool HasWeakFields(const FileDescriptor* file) {
return false;
}
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+ const Options& options) {
+ return options.lite_implicit_weak_fields &&
+ GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME;
+}
+
+
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options) {
+ return UsingImplicitWeakFields(field->file(), options) &&
+ field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ !field->is_required() && !field->is_repeated() && !field->is_map() &&
+ field->containing_oneof() == NULL &&
+ field->message_type()->file() != field->file();
+}
+
+struct CompareDescriptors {
+ bool operator()(const Descriptor* a, const Descriptor* b) {
+ return a->full_name() < b->full_name();
+ }
+};
+
SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) {
// Must not have visited already.
GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0);
@@ -728,10 +802,33 @@ SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) {
if (scc_desc == descriptor) break;
}
+
+ // The order of descriptors is random and depends how this SCC was
+ // discovered. In-order to ensure maximum stability we sort it by name.
+ std::sort(scc->descriptors.begin(), scc->descriptors.end(),
+ CompareDescriptors());
+ AddChildren(scc);
}
return result;
}
+void SCCAnalyzer::AddChildren(SCC* scc) {
+ std::set<const SCC*> seen;
+ for (int i = 0; i < scc->descriptors.size(); i++) {
+ const Descriptor* descriptor = scc->descriptors[i];
+ for (int j = 0; j < descriptor->field_count(); j++) {
+ const Descriptor* child_msg = descriptor->field(j)->message_type();
+ if (child_msg) {
+ const SCC* child = GetSCC(child_msg);
+ if (child == scc) continue;
+ if (seen.insert(child).second) {
+ scc->children.push_back(child);
+ }
+ }
+ }
+ }
+}
+
MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
if (analysis_cache_.count(scc)) return analysis_cache_[scc];
MessageAnalysis result = MessageAnalysis();
@@ -784,6 +881,46 @@ MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
return analysis_cache_[scc] = result;
}
+void ListAllFields(const Descriptor* d,
+ std::vector<const FieldDescriptor*>* fields) {
+ // Collect sub messages
+ for (int i = 0; i < d->nested_type_count(); i++) {
+ ListAllFields(d->nested_type(i), fields);
+ }
+ // Collect message level extensions.
+ for (int i = 0; i < d->extension_count(); i++) {
+ fields->push_back(d->extension(i));
+ }
+ // Add types of fields necessary
+ for (int i = 0; i < d->field_count(); i++) {
+ fields->push_back(d->field(i));
+ }
+}
+
+void ListAllFields(const FileDescriptor* d,
+ std::vector<const FieldDescriptor*>* fields) {
+ // Collect file level message.
+ for (int i = 0; i < d->message_type_count(); i++) {
+ ListAllFields(d->message_type(i), fields);
+ }
+ // Collect message level extensions.
+ for (int i = 0; i < d->extension_count(); i++) {
+ fields->push_back(d->extension(i));
+ }
+}
+
+void ListAllTypesForServices(const FileDescriptor* fd,
+ std::vector<const Descriptor*>* types) {
+ for (int i = 0; i < fd->service_count(); i++) {
+ const ServiceDescriptor* sd = fd->service(i);
+ for (int j = 0; j < sd->method_count(); j++) {
+ const MethodDescriptor* method = sd->method(j);
+ types->push_back(method->input_type());
+ types->push_back(method->output_type());
+ }
+ }
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 6ae68591..550438dd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -38,16 +38,13 @@
#include <map>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
-
-namespace io {
-class Printer;
-}
-
namespace compiler {
namespace cpp {
@@ -56,6 +53,31 @@ namespace cpp {
extern const char kThickSeparator[];
extern const char kThinSeparator[];
+// Name space of the proto file. This namespace is such that the string
+// "<namespace>::some_name" is the correct fully qualified namespace.
+// This means if the package is empty the namespace is "", and otherwise
+// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
+string Namespace(const string& package);
+inline string Namespace(const FileDescriptor* d) {
+ return Namespace(d->package());
+}
+template <typename Desc>
+string Namespace(const Desc* d) {
+ return Namespace(d->file());
+}
+
+// Returns true if it's safe to reset "field" to zero.
+bool CanInitializeByZeroing(const FieldDescriptor* field);
+
+string ClassName(const Descriptor* descriptor);
+string ClassName(const EnumDescriptor* enum_descriptor);
+template <typename Desc>
+string QualifiedClassName(const Desc* d) {
+ return Namespace(d) + "::" + ClassName(d);
+}
+
+// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
+// unreadable at the callsite.
// Returns the non-nested type name for the given type. If "qualified" is
// true, prefix the type with the full namespace. For example, if you had:
// package foo.bar;
@@ -64,12 +86,22 @@ extern const char kThinSeparator[];
// ::foo::bar::Baz_Qux
// While the non-qualified version would be:
// Baz_Qux
-string ClassName(const Descriptor* descriptor, bool qualified);
-string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+inline string ClassName(const Descriptor* descriptor, bool qualified) {
+ return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor);
+}
+
+inline string ClassName(const EnumDescriptor* descriptor, bool qualified) {
+ return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor);
+}
// Fully qualified name of the default_instance of this message.
string DefaultInstanceName(const Descriptor* descriptor);
+// Returns the name of a no-op function that we can call to introduce a linker
+// dependency on the given message type. This is used to implement implicit weak
+// fields.
+string ReferenceFunctionName(const Descriptor* descriptor);
+
// Name of the CRTP class template (for use with proto_h).
// This is a class name, like "ProtoName_InternalBase".
string DependentBaseClassTemplateName(const Descriptor* descriptor);
@@ -92,6 +124,12 @@ string FieldName(const FieldDescriptor* field);
// Get the sanitized name that should be used for the given enum in C++ code.
string EnumValueName(const EnumValueDescriptor* enum_value);
+// Returns an estimate of the compiler's alignment for the field. This
+// can't guarantee to be correct because the generated code could be compiled on
+// different systems with different alignment rules. The estimates below assume
+// 64-bit pointers.
+int EstimateAlignmentSize(const FieldDescriptor* field);
+
// Get the unqualified name that should be used for a field's field
// number constant.
string FieldConstantName(const FieldDescriptor *field);
@@ -150,6 +188,12 @@ string FilenameIdentifier(const string& filename);
// For each .proto file generates a unique namespace. In this namespace global
// definitions are put to prevent collisions.
string FileLevelNamespace(const string& filename);
+inline string FileLevelNamespace(const FileDescriptor* file) {
+ return FileLevelNamespace(file->name());
+}
+inline string FileLevelNamespace(const Descriptor* d) {
+ return FileLevelNamespace(d->file());
+}
// Return the qualified C++ name for a file level symbol.
string QualifiedFileLevelSymbol(const string& package, const string& name);
@@ -225,10 +269,6 @@ inline bool HasFastArraySerialization(const FileDescriptor* file,
return GetOptimizeFor(file, options) == FileOptions::SPEED;
}
-// Returns whether we have to generate code with static initializers.
-bool StaticInitializersForced(const FileDescriptor* file,
- const Options& options);
-
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
return descriptor->options().map_entry();
@@ -289,12 +329,25 @@ inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
}
// This orders the messages in a .pb.cc as it's outputted by file.cc
-std::vector<const Descriptor*> FlattenMessagesInFile(
- const FileDescriptor* file);
+void FlattenMessagesInFile(const FileDescriptor* file,
+ std::vector<const Descriptor*>* result);
+inline std::vector<const Descriptor*> FlattenMessagesInFile(
+ const FileDescriptor* file) {
+ std::vector<const Descriptor*> result;
+ FlattenMessagesInFile(file, &result);
+ return result;
+}
bool HasWeakFields(const Descriptor* desc);
bool HasWeakFields(const FileDescriptor* desc);
+// Indicates whether we should use implicit weak fields for this file.
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+ const Options& options);
+
+// Indicates whether to treat this field as implicitly weak.
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options);
+
// Returns true if the "required" restriction check should be ignored for the
// given field.
inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
@@ -302,8 +355,46 @@ inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
return false;
}
+class LIBPROTOC_EXPORT NamespaceOpener {
+ public:
+ explicit NamespaceOpener(io::Printer* printer) : printer_(printer) {}
+ NamespaceOpener(const string& name, io::Printer* printer)
+ : printer_(printer) {
+ ChangeTo(name);
+ }
+ ~NamespaceOpener() { ChangeTo(""); }
+
+ void ChangeTo(const string& name) {
+ std::vector<string> new_stack_ =
+ Split(name, "::", true);
+ int len = std::min(name_stack_.size(), new_stack_.size());
+ int common_idx = 0;
+ while (common_idx < len) {
+ if (name_stack_[common_idx] != new_stack_[common_idx]) break;
+ common_idx++;
+ }
+ for (int i = name_stack_.size() - 1; i >= common_idx; i--) {
+ printer_->Print("} // namespace $ns$\n", "ns", name_stack_[i]);
+ }
+ name_stack_.swap(new_stack_);
+ for (int i = common_idx; i < name_stack_.size(); i++) {
+ printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
+ }
+ }
+
+ private:
+ io::Printer* printer_;
+ std::vector<string> name_stack_;
+};
+
+// Description of each strongly connected component. Note that the order
+// of both the descriptors in this SCC and the order of children is
+// deterministic.
struct SCC {
std::vector<const Descriptor*> descriptors;
+ std::vector<const SCC*> children;
+
+ const Descriptor* GetRepresentative() const { return descriptors[0]; }
};
struct MessageAnalysis {
@@ -357,8 +448,16 @@ class LIBPROTOC_EXPORT SCCAnalyzer {
// Tarjan's Strongly Connected Components algo
NodeData DFS(const Descriptor* descriptor);
+
+ // Add the SCC's that are children of this SCC to its children.
+ void AddChildren(SCC* scc);
};
+void ListAllFields(const FileDescriptor* d,
+ std::vector<const FieldDescriptor*>* fields);
+void ListAllTypesForServices(const FileDescriptor* fd,
+ std::vector<const Descriptor*>* types);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index da33d29b..d06a1d39 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -114,50 +114,13 @@ MapFieldGenerator::~MapFieldGenerator() {}
void MapFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
- if (HasDescriptorMethods(descriptor_->file(), options_)) {
- printer->Print(
- variables_,
- "public:\n"
- "class $map_classname$ : public "
- "::google::protobuf::internal::MapEntry<$map_classname$, \n"
- " $key_cpp$, $val_cpp$,\n"
- " $key_wire_type$,\n"
- " $val_wire_type$,\n"
- " $default_enum_value$ > {\n"
- "public:\n"
- " typedef ::google::protobuf::internal::MapEntry<$map_classname$, \n"
- " $key_cpp$, $val_cpp$,\n"
- " $key_wire_type$,\n"
- " $val_wire_type$,\n"
- " $default_enum_value$ > SuperType;\n"
- " $map_classname$();\n"
- " $map_classname$(::google::protobuf::Arena* arena);\n"
- " void MergeFrom(const ::google::protobuf::Message& other) PROTOBUF_FINAL;\n"
- " void MergeFrom(const $map_classname$& other);\n"
- " static const Message* internal_default_instance() { return "
- "reinterpret_cast<const "
- "Message*>(&_$map_classname$_default_instance_); }\n"
- " ::google::protobuf::Metadata GetMetadata() const;\n"
- "};\n");
- } else {
- printer->Print(variables_,
- "public:\n"
- "typedef ::google::protobuf::internal::MapEntryLite<\n"
- " $key_cpp$, $val_cpp$,\n"
- " $key_wire_type$,\n"
- " $val_wire_type$,\n"
- " $default_enum_value$ >\n"
- " $map_classname$;\n");
- }
printer->Print(variables_,
- "private:\n"
"::google::protobuf::internal::MapField$lite$<\n"
" $map_classname$,\n"
" $key_cpp$, $val_cpp$,\n"
" $key_wire_type$,\n"
" $val_wire_type$,\n"
- " $default_enum_value$ > $name$_;\n"
- "private:\n");
+ " $default_enum_value$ > $name$_;\n");
}
void MapFieldGenerator::
@@ -262,7 +225,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
" unknown_fields_stream.WriteVarint32($tag$u);\n"
" unknown_fields_stream.WriteVarint32(\n"
- " static_cast<google::protobuf::uint32>(data.size()));\n"
+ " static_cast< ::google::protobuf::uint32>(data.size()));\n"
" unknown_fields_stream.WriteString(data);\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 63ebb3c5..cf9c1233 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -48,6 +48,7 @@
#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
@@ -109,106 +110,6 @@ struct ExtensionRangeSorter {
}
};
-// This returns an estimate of the compiler's alignment for the field. This
-// can't guarantee to be correct because the generated code could be compiled on
-// different systems with different alignment rules. The estimates below assume
-// 64-bit pointers.
-int EstimateAlignmentSize(const FieldDescriptor* field) {
- if (field == NULL) return 0;
- if (field->is_repeated()) return 8;
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_BOOL:
- return 1;
-
- case FieldDescriptor::CPPTYPE_INT32:
- case FieldDescriptor::CPPTYPE_UINT32:
- case FieldDescriptor::CPPTYPE_ENUM:
- case FieldDescriptor::CPPTYPE_FLOAT:
- return 4;
-
- case FieldDescriptor::CPPTYPE_INT64:
- case FieldDescriptor::CPPTYPE_UINT64:
- case FieldDescriptor::CPPTYPE_DOUBLE:
- case FieldDescriptor::CPPTYPE_STRING:
- case FieldDescriptor::CPPTYPE_MESSAGE:
- return 8;
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return -1; // Make compiler happy.
-}
-
-// FieldGroup is just a helper for OptimizePadding below. It holds a vector of
-// fields that are grouped together because they have compatible alignment, and
-// a preferred location in the final field ordering.
-class FieldGroup {
- public:
- FieldGroup()
- : preferred_location_(0) {}
-
- // A group with a single field.
- FieldGroup(float preferred_location, const FieldDescriptor* field)
- : preferred_location_(preferred_location),
- fields_(1, field) {}
-
- // Append the fields in 'other' to this group.
- void Append(const FieldGroup& other) {
- if (other.fields_.empty()) {
- return;
- }
- // Preferred location is the average among all the fields, so we weight by
- // the number of fields on each FieldGroup object.
- preferred_location_ =
- (preferred_location_ * fields_.size() +
- (other.preferred_location_ * other.fields_.size())) /
- (fields_.size() + other.fields_.size());
- fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
- }
-
- void SetPreferredLocation(float location) { preferred_location_ = location; }
- const std::vector<const FieldDescriptor*>& fields() const { return fields_; }
-
- // FieldGroup objects sort by their preferred location.
- bool operator<(const FieldGroup& other) const {
- return preferred_location_ < other.preferred_location_;
- }
-
- private:
- // "preferred_location_" is an estimate of where this group should go in the
- // final list of fields. We compute this by taking the average index of each
- // field in this group in the original ordering of fields. This is very
- // approximate, but should put this group close to where its member fields
- // originally went.
- float preferred_location_;
- std::vector<const FieldDescriptor*> fields_;
- // We rely on the default copy constructor and operator= so this type can be
- // used in a vector.
-};
-
-// Helper for the code that emits the Clear() method.
-bool CanInitializeByZeroing(const FieldDescriptor* field) {
- if (field->is_repeated() || field->is_extension()) return false;
- switch (field->cpp_type()) {
- case internal::WireFormatLite::CPPTYPE_ENUM:
- return field->default_value_enum()->number() == 0;
- case internal::WireFormatLite::CPPTYPE_INT32:
- return field->default_value_int32() == 0;
- case internal::WireFormatLite::CPPTYPE_INT64:
- return field->default_value_int64() == 0;
- case internal::WireFormatLite::CPPTYPE_UINT32:
- return field->default_value_uint32() == 0;
- case internal::WireFormatLite::CPPTYPE_UINT64:
- return field->default_value_uint64() == 0;
- case internal::WireFormatLite::CPPTYPE_FLOAT:
- return field->default_value_float() == 0;
- case internal::WireFormatLite::CPPTYPE_DOUBLE:
- return field->default_value_double() == 0;
- case internal::WireFormatLite::CPPTYPE_BOOL:
- return field->default_value_bool() == false;
- default:
- return false;
- }
-}
-
bool IsPOD(const FieldDescriptor* field) {
if (field->is_repeated() || field->is_extension()) return false;
switch (field->cpp_type()) {
@@ -242,133 +143,6 @@ bool CanConstructByZeroing(const FieldDescriptor* field,
return ret;
}
-// Reorder 'fields' so that if the fields are output into a c++ class in the new
-// order, fields of similiar family (see below) are together and within each
-// family, alignment padding is minimized.
-//
-// We try to do this while keeping each field as close as possible to its field
-// number order so that we don't reduce cache locality much for function that
-// access each field in order. Originally, OptimizePadding used declaration
-// order for its decisions, but generated code minus the serializer/parsers uses
-// the output of OptimizePadding as well (stored in
-// MessageGenerator::optimized_order_). Since the serializers use field number
-// order, we use that as a tie-breaker.
-//
-// TODO(ckennelly): If/when we have profiles available for the compiler, use
-// those rather than respect declaration order.
-//
-// We classify each field into a particular "family" of fields, that we perform
-// the same operation on in our generated functions.
-//
-// REPEATED is placed first, as the C++ compiler automatically initializes
-// these fields in layout order.
-//
-// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
-// calls ArenaStringPtr::Destroy on each.
-//
-//
-// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
-// delete on each. We initialize these fields with a NULL pointer (see
-// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
-// memset.
-//
-// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
-//
-// OTHER these fields are initialized one-by-one.
-void OptimizePadding(std::vector<const FieldDescriptor*>* fields,
- const Options& options) {
- // The sorted numeric order of Family determines the declaration order in the
- // memory layout.
- enum Family {
- REPEATED = 0,
- STRING = 1,
- MESSAGE = 3,
- ZERO_INITIALIZABLE = 4,
- OTHER = 5,
- kMaxFamily
- };
-
- // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
- std::vector<FieldGroup> aligned_to_1[kMaxFamily];
- std::vector<FieldGroup> aligned_to_4[kMaxFamily];
- std::vector<FieldGroup> aligned_to_8[kMaxFamily];
- for (int i = 0; i < fields->size(); ++i) {
- const FieldDescriptor* field = (*fields)[i];
-
- Family f = OTHER;
- if (field->is_repeated()) {
- f = REPEATED;
- } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
- f = STRING;
- } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- f = MESSAGE;
-
- } else if (CanInitializeByZeroing(field)) {
- f = ZERO_INITIALIZABLE;
- }
-
- const int j = field->number();
- switch (EstimateAlignmentSize(field)) {
- case 1: aligned_to_1[f].push_back(FieldGroup(j, field)); break;
- case 4: aligned_to_4[f].push_back(FieldGroup(j, field)); break;
- case 8: aligned_to_8[f].push_back(FieldGroup(j, field)); break;
- default:
- GOOGLE_LOG(FATAL) << "Unknown alignment size.";
- }
- }
-
- // For each family, group fields to optimize padding.
- for (int f = 0; f < kMaxFamily; f++) {
- // Now group fields aligned to 1 byte into sets of 4, and treat those like a
- // single field aligned to 4 bytes.
- for (int i = 0; i < aligned_to_1[f].size(); i += 4) {
- FieldGroup field_group;
- for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
- field_group.Append(aligned_to_1[f][j]);
- }
- aligned_to_4[f].push_back(field_group);
- }
- // Sort by preferred location to keep fields as close to their field number
- // order as possible. Using stable_sort ensures that the output is
- // consistent across runs.
- std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end());
-
- // Now group fields aligned to 4 bytes (or the 4-field groups created above)
- // into pairs, and treat those like a single field aligned to 8 bytes.
- for (int i = 0; i < aligned_to_4[f].size(); i += 2) {
- FieldGroup field_group;
- for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
- field_group.Append(aligned_to_4[f][j]);
- }
- if (i == aligned_to_4[f].size() - 1) {
- if (f == OTHER) {
- // Move incomplete 4-byte block to the beginning. This is done to
- // pair with the (possible) leftover blocks from the
- // ZERO_INITIALIZABLE family.
- field_group.SetPreferredLocation(-1);
- } else {
- // Move incomplete 4-byte block to the end.
- field_group.SetPreferredLocation(fields->size() + 1);
- }
- }
- aligned_to_8[f].push_back(field_group);
- }
- // Sort by preferred location.
- std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
- }
-
- // Now pull out all the FieldDescriptors in order.
- fields->clear();
- for (int f = 0; f < kMaxFamily; ++f) {
- for (int i = 0; i < aligned_to_8[f].size(); ++i) {
- fields->insert(fields->end(),
- aligned_to_8[f][i].fields().begin(),
- aligned_to_8[f][i].fields().end());
- }
- }
-}
-
-
// Emits an if-statement with a condition that evaluates to true if |field| is
// considered non-default (will be sent over the wire), for message types
// without true field presence. Should only be called if
@@ -423,25 +197,31 @@ bool HasHasMethod(const FieldDescriptor* field) {
void CollectMapInfo(const Descriptor* descriptor,
std::map<string, string>* variables) {
GOOGLE_CHECK(IsMapEntryMessage(descriptor));
+ std::map<string, string>& vars = *variables;
const FieldDescriptor* key = descriptor->FindFieldByName("key");
const FieldDescriptor* val = descriptor->FindFieldByName("value");
- (*variables)["key"] = PrimitiveTypeName(key->cpp_type());
+ vars["key_cpp"] = PrimitiveTypeName(key->cpp_type());
switch (val->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
- (*variables)["val"] = FieldMessageTypeName(val);
+ vars["val_cpp"] = FieldMessageTypeName(val);
break;
case FieldDescriptor::CPPTYPE_ENUM:
- (*variables)["val"] = ClassName(val->enum_type(), true);
+ vars["val_cpp"] = ClassName(val->enum_type(), true);
break;
default:
- (*variables)["val"] = PrimitiveTypeName(val->cpp_type());
- }
- (*variables)["key_wire_type"] =
- "::google::protobuf::internal::WireFormatLite::TYPE_" +
- ToUpper(DeclaredTypeMethodName(key->type()));
- (*variables)["val_wire_type"] =
- "::google::protobuf::internal::WireFormatLite::TYPE_" +
- ToUpper(DeclaredTypeMethodName(val->type()));
+ vars["val_cpp"] = PrimitiveTypeName(val->cpp_type());
+ }
+ vars["key_wire_type"] = "::google::protobuf::internal::WireFormatLite::TYPE_" +
+ ToUpper(DeclaredTypeMethodName(key->type()));
+ vars["val_wire_type"] = "::google::protobuf::internal::WireFormatLite::TYPE_" +
+ ToUpper(DeclaredTypeMethodName(val->type()));
+ if (descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
+ val->type() == FieldDescriptor::TYPE_ENUM) {
+ const EnumValueDescriptor* default_value = val->default_value_enum();
+ vars["default_enum_value"] = Int32ToString(default_value->number());
+ } else {
+ vars["default_enum_value"] = "0";
+ }
}
// Does the given field have a private (internal helper only) has_$name$()
@@ -531,21 +311,22 @@ void SetUnknkownFieldsVariable(const Descriptor* descriptor,
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+ int index_in_file_messages,
const Options& options,
SCCAnalyzer* scc_analyzer)
: descriptor_(descriptor),
+ index_in_file_messages_(index_in_file_messages),
classname_(ClassName(descriptor, false)),
options_(options),
field_generators_(descriptor, options),
max_has_bit_index_(0),
- nested_generators_(new google::protobuf::scoped_ptr<
- MessageGenerator>[descriptor->nested_type_count()]),
enum_generators_(
new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
extension_generators_(new google::protobuf::scoped_ptr<
ExtensionGenerator>[descriptor->extension_count()]),
use_dependent_base_(false),
num_weak_fields_(0),
+ message_layout_helper_(new PaddingOptimizer()),
scc_analyzer_(scc_analyzer) {
// Compute optimized field order to be used for layout and initialization
// purposes.
@@ -557,7 +338,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
optimized_order_.push_back(field);
}
}
- OptimizePadding(&optimized_order_, options_);
+
+ message_layout_helper_->OptimizeLayout(&optimized_order_, options_);
if (HasFieldPresence(descriptor_->file())) {
// We use -1 as a sentinel.
@@ -573,11 +355,6 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
}
}
- for (int i = 0; i < descriptor->nested_type_count(); i++) {
- nested_generators_[i].reset(new MessageGenerator(descriptor->nested_type(i),
- options, scc_analyzer));
- }
-
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enum_generators_[i].reset(
new EnumGenerator(descriptor->enum_type(i), options));
@@ -603,6 +380,9 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
}
table_driven_ = TableDrivenParsingEnabled(descriptor_, options_);
+
+ scc_name_ =
+ ClassName(scc_analyzer_->GetSCC(descriptor_)->GetRepresentative(), false);
}
MessageGenerator::~MessageGenerator() {}
@@ -620,14 +400,6 @@ size_t MessageGenerator::HasBitsSize() const {
return sizeof_has_bits;
}
-void MessageGenerator::Flatten(std::vector<MessageGenerator*>* list) {
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- nested_generators_[i]->Flatten(list);
- }
- index_in_file_messages_ = list->size();
- list->push_back(this);
-}
-
void MessageGenerator::AddGenerators(
std::vector<EnumGenerator*>* enum_generators,
std::vector<ExtensionGenerator*>* extension_generators) {
@@ -1010,8 +782,8 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
}
// Generate type-specific accessors.
- field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
- is_inline);
+ field_generators_.get(field).GenerateInlineAccessorDefinitions(
+ printer, /* is_inline = */ true);
printer->Print("\n");
}
@@ -1056,7 +828,42 @@ GenerateDependentBaseClassDefinition(io::Printer* printer) {
void MessageGenerator::
GenerateClassDefinition(io::Printer* printer) {
- if (IsMapEntryMessage(descriptor_)) return;
+ if (IsMapEntryMessage(descriptor_)) {
+ std::map<string, string> vars;
+ vars["classname"] = classname_;
+ CollectMapInfo(descriptor_, &vars);
+ vars["lite"] =
+ HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite";
+ printer->Print(
+ vars,
+ "class $classname$ : public "
+ "::google::protobuf::internal::MapEntry$lite$<$classname$, \n"
+ " $key_cpp$, $val_cpp$,\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
+ " $default_enum_value$ > {\n"
+ "public:\n"
+ " typedef ::google::protobuf::internal::MapEntry$lite$<$classname$, \n"
+ " $key_cpp$, $val_cpp$,\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
+ " $default_enum_value$ > SuperType;\n"
+ " $classname$();\n"
+ " $classname$(::google::protobuf::Arena* arena);\n"
+ " void MergeFrom(const $classname$& other);\n"
+ " static const $classname$* internal_default_instance() { return "
+ "reinterpret_cast<const "
+ "$classname$*>(&_$classname$_default_instance_); }\n");
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ printer->Print(
+ " void MergeFrom(const ::google::protobuf::Message& other) PROTOBUF_FINAL;\n"
+ " ::google::protobuf::Metadata GetMetadata() const;\n"
+ "};\n");
+ } else {
+ printer->Print("};\n");
+ }
+ return;
+ }
if (use_dependent_base_) {
GenerateDependentBaseClassDefinition(printer);
printer->Print("\n");
@@ -1109,26 +916,23 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
- // Generate move constructor and move assignment operator for types other than
- // Any.
- if (!IsAnyMessage(descriptor_)) {
- printer->Print(vars,
- "#if LANG_CXX11\n"
- "$classname$($classname$&& from) noexcept\n"
- " : $classname$() {\n"
- " *this = ::std::move(from);\n"
- "}\n"
- "\n"
- "inline $classname$& operator=($classname$&& from) noexcept {\n"
- " if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n"
- " if (this != &from) InternalSwap(&from);\n"
- " } else {\n"
- " CopyFrom(from);\n"
- " }\n"
- " return *this;\n"
- "}\n"
- "#endif\n");
- }
+ // Generate move constructor and move assignment operator.
+ printer->Print(vars,
+ "#if LANG_CXX11\n"
+ "$classname$($classname$&& from) noexcept\n"
+ " : $classname$() {\n"
+ " *this = ::std::move(from);\n"
+ "}\n"
+ "\n"
+ "inline $classname$& operator=($classname$&& from) noexcept {\n"
+ " if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n"
+ " if (this != &from) InternalSwap(&from);\n"
+ " } else {\n"
+ " CopyFrom(from);\n"
+ " }\n"
+ " return *this;\n"
+ "}\n"
+ "#endif\n");
SetUnknkownFieldsVariable(descriptor_, options_, &vars);
if (PublicUnknownFieldsAccessors(descriptor_)) {
@@ -1199,6 +1003,7 @@ GenerateClassDefinition(io::Printer* printer) {
vars["message_index"] = SimpleItoa(index_in_file_messages_);
printer->Print(
vars,
+ "static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY\n"
"static inline const $classname$* internal_default_instance() {\n"
" return reinterpret_cast<const $classname$*>(\n"
" &_$classname$_default_instance_);\n"
@@ -1358,6 +1163,8 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print("typedef $nested_full_name$ $nested_name$;\n",
"nested_name", nested_type->name(),
"nested_full_name", ClassName(nested_type, false));
+ printer->Annotate("nested_full_name", nested_type);
+ printer->Annotate("nested_name", nested_type);
}
}
@@ -1548,14 +1355,13 @@ GenerateClassDefinition(io::Printer* printer) {
// The TableStruct struct needs access to the private parts, in order to
// construct the offsets of all members.
- //
- // Some InitDefault and Shutdown are defined as static member functions of
- // TableStruct such that they are also allowed to access private members.
+ // TODO(gerbens) Remove the friend for InitDefaults.
printer->Print(
- "friend struct $file_namespace$::TableStruct;\n",
+ "friend struct ::$file_namespace$::TableStruct;\n"
+ "friend void ::$file_namespace$::InitDefaults$scc_name$Impl();\n",
// Vars.
- "file_namespace",
- FileLevelNamespace(descriptor_->file()->name()));
+ "scc_name", scc_name_, "file_namespace",
+ FileLevelNamespace(descriptor_));
printer->Outdent();
printer->Print("};");
@@ -1577,7 +1383,7 @@ GenerateDependentInlineMethods(io::Printer* printer) {
void MessageGenerator::
GenerateInlineMethods(io::Printer* printer, bool is_inline) {
if (IsMapEntryMessage(descriptor_)) return;
- GenerateFieldAccessorDefinitions(printer, is_inline);
+ GenerateFieldAccessorDefinitions(printer, /* is_inline = */ true);
// Generate oneof_case() functions.
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
@@ -1634,7 +1440,8 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
std::map<string, string> vars;
- vars["classname"] = classname_;
+ vars["classname"] = ClassName(descriptor_);
+ vars["classtype"] = QualifiedClassName(descriptor_);
vars["offset"] = SimpleItoa(offset);
vars["aux_offset"] = SimpleItoa(aux_offset);
@@ -1661,48 +1468,34 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
printer->Print(vars, "-1,\n");
} else {
printer->Print(vars,
- "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
- " $classname$, _has_bits_),\n");
+ "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+ " $classtype$, _has_bits_),\n");
}
if (descriptor_->oneof_decl_count() > 0) {
printer->Print(vars,
"GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
- " $classname$, _oneof_case_),\n");
+ " $classtype$, _oneof_case_),\n");
} else {
printer->Print("-1, // no _oneof_case_\n");
}
if (descriptor_->extension_range_count() > 0) {
printer->Print(vars,
- "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
- "_extensions_),\n");
+ "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classtype$, "
+ "_extensions_),\n");
} else {
printer->Print("-1, // no _extensions_\n");
}
// TODO(ckennelly): Consolidate this with the calculation for
// AuxillaryParseTableField.
- std::vector<string> package_parts;
-
- const Descriptor* outer = descriptor_;
- while (outer->containing_type() != NULL) {
- outer = outer->containing_type();
- }
-
- package_parts = Split(
- outer->full_name(), ".", true);
- // outer->full_name() contains the class itself. Remove it as it is
- // used in the name of the default instance variable.
- GOOGLE_DCHECK_NE(package_parts.size(), 0);
- package_parts.back().clear();
-
- vars["ns"] = Join(package_parts, "::");
+ vars["ns"] = Namespace(descriptor_);
printer->Print(vars,
- "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
- " $classname$, _internal_metadata_),\n"
- "&::$ns$_$classname$_default_instance_,\n");
+ "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+ " $classtype$, _internal_metadata_),\n"
+ "&$ns$::_$classname$_default_instance_,\n");
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(vars, "true,\n");
@@ -1717,15 +1510,14 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
int has_offset) {
- if (IsMapEntryMessage(descriptor_)) return;
-
std::map<string, string> vars;
- vars["classname"] = classname_;
+ vars["classname"] = QualifiedClassName(descriptor_);
vars["offset"] = SimpleItoa(offset);
- vars["has_bits_offsets"] = HasFieldPresence(descriptor_->file())
- ? SimpleItoa(offset + has_offset)
- : "-1";
+ vars["has_bits_offsets"] =
+ HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)
+ ? SimpleItoa(offset + has_offset)
+ : "-1";
printer->Print(vars,
"{ $offset$, $has_bits_offsets$, sizeof($classname$)},\n");
@@ -1804,6 +1596,8 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
return 0;
}
+ string full_classname = QualifiedClassName(descriptor_);
+
std::vector<const FieldDescriptor*> sorted = SortFieldsByNumber(descriptor_);
if (IsMapEntryMessage(descriptor_)) {
for (int i = 0; i < 2; i++) {
@@ -1812,9 +1606,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
field->number(), WireFormat::WireTypeForFieldType(field->type()));
std::map<string, string> vars;
- vars["classname"] = classname_;
- vars["parent_classname"] =
- ClassName(descriptor_->containing_type(), false);
+ vars["classname"] = QualifiedClassName(descriptor_);
vars["field_name"] = FieldName(field);
vars["tag"] = SimpleItoa(tag);
vars["hasbit"] = SimpleItoa(i);
@@ -1824,23 +1616,18 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
GOOGLE_CHECK(!IsMapEntryMessage(field->message_type()));
{
vars["ptr"] =
- QualifiedFileLevelSymbol(
- field->message_type()->file()->package(),
- FileLevelNamespace(field->message_type()->file()->name())) +
+ "::" + FileLevelNamespace(field->message_type()) +
"::TableStruct::serialization_table + " +
SimpleItoa(FindMessageIndexInFile(field->message_type()));
}
}
- vars["extra"] = HasDescriptorMethods(descriptor_->file(), options_)
- ? "::SuperType"
- : "";
printer->Print(vars,
"{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
- "::google::protobuf::internal::MapEntryHelper<$parent_classname$::$"
- "classname$$extra$>, $field_name$_), $tag$,"
+ "::google::protobuf::internal::MapEntryHelper<$classname$::"
+ "SuperType>, $field_name$_), $tag$,"
"GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
- "::google::protobuf::internal::MapEntryHelper<$parent_classname$::$"
- "classname$$extra$>, _has_bits_) * 8 + $hasbit$, $type$, "
+ "::google::protobuf::internal::MapEntryHelper<$classname$::"
+ "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, "
"$ptr$},\n");
}
return 2;
@@ -1848,7 +1635,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
printer->Print(
"{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
"_cached_size_), 0, 0, 0, NULL},\n",
- "classname", classname_);
+ "classname", full_classname);
std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
@@ -1868,7 +1655,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
"::google::protobuf::internal::FieldMetadata::kSpecial, "
"reinterpret_cast<const "
"void*>(::google::protobuf::internal::ExtensionSerializer)},\n",
- "classname", classname_, "start", SimpleItoa(range->start), "end",
+ "classname", full_classname, "start", SimpleItoa(range->start), "end",
SimpleItoa(range->end));
}
if (i == sorted.size()) break;
@@ -1886,14 +1673,14 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
classfieldname = field->containing_oneof()->name();
}
std::map<string, string> vars;
- vars["classname"] = classname_;
+ vars["classname"] = full_classname;
vars["field_name"] = classfieldname;
vars["tag"] = SimpleItoa(tag);
vars["ptr"] = "NULL";
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (IsMapEntryMessage(field->message_type())) {
vars["idx"] = SimpleItoa(FindMessageIndexInFile(field->message_type()));
- vars["fieldclassname"] = ClassName(field->message_type(), false);
+ vars["fieldclassname"] = QualifiedClassName(field->message_type());
printer->Print(vars,
"{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
"classname$, $field_name$_), $tag$, $idx$, "
@@ -1901,15 +1688,13 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
"reinterpret_cast<const void*>(static_cast< "
"::google::protobuf::internal::SpecialSerializer>("
"::google::protobuf::internal::MapFieldSerializer< "
- "::google::protobuf::internal::MapEntryToMapField<$classname$::$"
- "fieldclassname$>::MapFieldType, "
+ "::google::protobuf::internal::MapEntryToMapField<"
+ "$fieldclassname$>::MapFieldType, "
"TableStruct::serialization_table>))},\n");
continue;
} else {
vars["ptr"] =
- QualifiedFileLevelSymbol(
- field->message_type()->file()->package(),
- FileLevelNamespace(field->message_type()->file()->name())) +
+ "::" + FileLevelNamespace(field->message_type()) +
"::TableStruct::serialization_table + " +
SimpleItoa(FindMessageIndexInFile(field->message_type()));
}
@@ -1960,40 +1745,20 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
"_internal_metadata_), 0, ~0u, "
"::google::protobuf::internal::FieldMetadata::kSpecial, reinterpret_cast<const "
"void*>($serializer$)},\n",
- "classname", classname_, "serializer", serializer);
+ "classname", full_classname, "serializer", serializer);
return num_field_metadata;
}
-void MessageGenerator::
-GenerateDefaultInstanceAllocator(io::Printer* printer) {
- // Construct the default instances of all fields, as they will be used
- // when creating the default instance of the entire message.
+void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) {
+ // Construct the default instances for all fields that need one.
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
.GenerateDefaultInstanceAllocator(printer);
}
-
- // Construct the default instance. We can't call InitAsDefaultInstance() yet
- // because we need to make sure all default instances that this one might
- // depend on are constructed first.
- printer->Print("_$classname$_default_instance_._instance.DefaultConstruct();\n"
- "::google::protobuf::internal::OnShutdownDestroyMessage(\n"
- " &_$classname$_default_instance_);",
- "classname", classname_);
}
void MessageGenerator::
GenerateDefaultInstanceInitializer(io::Printer* printer) {
- if (IsMapEntryMessage(descriptor_)) {
- printer->Print(
- "_$classname$_default_instance_._instance.get_mutable()->set_default_instance(_$"
- "classname$_default_instance_._instance.get_mutable());\n"
- "_$classname$_default_instance_._instance.get_mutable()->InitAsDefaultInstance();"
- "\n",
- "classname", classname_);
- return;
- }
-
// The default instance needs all of its embedded message pointers
// cross-linked to other default instances. We can't do this initialization
// in the constructor because some other default instances may not have been
@@ -2016,10 +1781,11 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
}
name += FieldName(field);
printer->Print(
- "$name$_ = const_cast< $type$*>(\n"
+ "$ns$::$name$_ = const_cast< $type$*>(\n"
" $type$::internal_default_instance());\n",
// Vars.
- "name", name, "type", FieldMessageTypeName(field));
+ "name", name, "type", FieldMessageTypeName(field), "ns",
+ Namespace(descriptor_));
} else if (field->containing_oneof() &&
HasDescriptorMethods(descriptor_->file(), options_)) {
field_generators_.get(descriptor_->field(i))
@@ -2031,31 +1797,41 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
void MessageGenerator::
GenerateClassMethods(io::Printer* printer) {
if (IsMapEntryMessage(descriptor_)) {
+ printer->Print(
+ "$classname$::$classname$() {}\n"
+ "$classname$::$classname$(::google::protobuf::Arena* arena) : "
+ "SuperType(arena) {}\n"
+ "void $classname$::MergeFrom(const $classname$& other) {\n"
+ " MergeFromInternal(other);\n"
+ "}\n",
+ "classname", classname_);
if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(
- "$parent$::$classname$::$classname$() {}\n"
- "$parent$::$classname$::$classname$(::google::protobuf::Arena* arena) : "
- "SuperType(arena) {}\n"
- "::google::protobuf::Metadata $parent$::$classname$::GetMetadata() const {\n"
- " $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
- " return $file_namespace$::file_level_metadata[$index$];\n"
+ "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
+ " ::$file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+ " return ::$file_namespace$::file_level_metadata[$index$];\n"
"}\n"
- "void $parent$::$classname$::MergeFrom(\n"
+ "void $classname$::MergeFrom(\n"
" const ::google::protobuf::Message& other) {\n"
" ::google::protobuf::Message::MergeFrom(other);\n"
"}\n"
- "void $parent$::$classname$::MergeFrom(const $classname$& other) {\n"
- " MergeFromInternal(other);\n"
- "}\n"
"\n",
- "file_namespace", FileLevelNamespace(descriptor_->file()->name()),
- "parent", ClassName(descriptor_->containing_type(), false),
+ "file_namespace", FileLevelNamespace(descriptor_),
"classname", classname_, "index",
SimpleItoa(index_in_file_messages_));
}
return;
}
+ // TODO(gerbens) Remove this function. With a little bit of cleanup and
+ // refactoring this is superfluous.
+ printer->Print("void $classname$::InitAsDefaultInstance() {\n", "classname",
+ classname_);
+ printer->Indent();
+ GenerateDefaultInstanceInitializer(printer);
+ printer->Outdent();
+ printer->Print("}\n");
+
if (IsAnyMessage(descriptor_)) {
printer->Print(
"void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
@@ -2134,23 +1910,24 @@ GenerateClassMethods(io::Printer* printer) {
if (options_.table_driven_serialization) {
printer->Print(
- "const void* $classname$::InternalGetTable() const {\n"
- " return $file_namespace$::TableStruct::serialization_table + $index$;\n"
- "}\n"
- "\n",
- "classname", classname_, "index", SimpleItoa(index_in_file_messages_),
- "file_namespace", FileLevelNamespace(descriptor_->file()->name()));
+ "const void* $classname$::InternalGetTable() const {\n"
+ " return ::$file_namespace$::TableStruct::serialization_table + "
+ "$index$;\n"
+ "}\n"
+ "\n",
+ "classname", classname_, "index", SimpleItoa(index_in_file_messages_),
+ "file_namespace", FileLevelNamespace(descriptor_));
}
if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(
"::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
" $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
- " return "
+ " return ::"
"$file_namespace$::file_level_metadata[kIndexInFileMessages];\n"
"}\n"
"\n",
"classname", classname_, "file_namespace",
- FileLevelNamespace(descriptor_->file()->name()));
+ FileLevelNamespace(descriptor_));
} else {
printer->Print(
"::std::string $classname$::GetTypeName() const {\n"
@@ -2224,7 +2001,7 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) {
WireFormat::TagSize(field->number(), field->type());
std::map<string, string> vars;
- vars["classname"] = classname_;
+ vars["classname"] = QualifiedClassName(descriptor_);
if (field->containing_oneof() != NULL) {
vars["name"] = field->containing_oneof()->name();
vars["presence"] = SimpleItoa(field->containing_oneof()->index());
@@ -2280,23 +2057,8 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
last_field_number++;
break;
case FieldDescriptor::CPPTYPE_MESSAGE: {
- std::vector<string> package_parts;
-
- const Descriptor* outer = field->message_type();
- while (outer->containing_type() != NULL) {
- outer = outer->containing_type();
- }
-
- package_parts = Split(
- outer->full_name(), ".", true);
- // outer->full_name() contains the class itself. Remove it as it is
- // used in the name of the default instance variable.
- GOOGLE_DCHECK_NE(package_parts.size(), 0);
- package_parts.back().clear();
-
if (field->is_map()) {
- vars["classname"] = ClassName(field->containing_type(), false) +
- "::" + ClassName(field->message_type(), false);
+ vars["classname"] = QualifiedClassName(field->message_type());
printer->Print(vars,
"{::google::protobuf::internal::AuxillaryParseTableField::map_"
"aux{&::google::protobuf::internal::ParseMap<$classname$>}},\n");
@@ -2305,13 +2067,15 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
} else {
vars["classname"] = ClassName(field->message_type(), false);
}
- vars["ns"] = Join(package_parts, "::");
+ vars["ns"] = Namespace(field->message_type());
vars["type"] = FieldMessageTypeName(field);
- vars["file_namespace"] = FileLevelNamespace(outer->file()->name());
+ vars["file_namespace"] =
+ FileLevelNamespace(field->message_type());
- printer->Print(vars,
+ printer->Print(
+ vars,
"{::google::protobuf::internal::AuxillaryParseTableField::message_aux{\n"
- " &::$ns$_$classname$_default_instance_,\n");
+ " &$ns$::_$classname$_default_instance_,\n");
bool dont_emit_table =
!TableDrivenParsingEnabled(field->message_type(), options_);
@@ -2320,8 +2084,8 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
printer->Print(" NULL,\n");
} else {
printer->Print(vars,
- " ::$ns$$file_namespace$::TableStruct::schema +\n"
- " ::$ns$$classname$::kIndexInFileMessages,\n");
+ " ::$file_namespace$::TableStruct::schema +\n"
+ " $ns$::$classname$::kIndexInFileMessages,\n");
}
printer->Print("}},\n");
@@ -2333,8 +2097,9 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
case FieldOptions::STRING:
vars["default"] =
field->default_value_string().empty()
- ? "&::google::protobuf::internal::fixed_address_empty_string"
- : "&" + classname_ + "::_default_" + FieldName(field) + "_";
+ ? "&::google::protobuf::internal::fixed_address_empty_string"
+ : "&" + Namespace(field) + " ::" + classname_ +
+ "::_default_" + FieldName(field) + "_";
break;
case FieldOptions::CORD:
case FieldOptions::STRING_PIECE:
@@ -2360,11 +2125,11 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
io::Printer* printer) {
- if (IsMapEntryMessage(descriptor_)) return std::make_pair(0, 0);
std::map<string, string> variables;
- variables["classname"] = classname_;
+ string full_classname = QualifiedClassName(descriptor_);
+ variables["classname"] = full_classname;
- if (HasFieldPresence(descriptor_->file())) {
+ if (HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)) {
printer->Print(
variables,
"GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
@@ -2405,27 +2170,29 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->containing_oneof() || field->options().weak()) {
- printer->Print(
- "offsetof($classname$DefaultTypeInternal, $name$_),\n",
- "classname", classname_, "name", FieldName(field));
+ printer->Print("offsetof($classname$DefaultTypeInternal, $name$_),\n",
+ "classname", full_classname, "name", FieldName(field));
} else {
printer->Print(
"GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
- "$name$_),\n",
- "classname", classname_,
- "name", FieldName(field));
+ "$name$_),\n",
+ "classname", full_classname, "name", FieldName(field));
}
}
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
printer->Print(
- "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
- "classname", classname_,
- "name", oneof->name());
+ "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
+ "classname", full_classname, "name", oneof->name());
}
- if (HasFieldPresence(descriptor_->file())) {
+ if (IsMapEntryMessage(descriptor_)) {
+ entries += 2;
+ printer->Print(
+ "0,\n"
+ "1,\n");
+ } else if (HasFieldPresence(descriptor_->file())) {
entries += has_bit_indices_.size();
for (int i = 0; i < has_bit_indices_.size(); i++) {
const string index = has_bit_indices_[i] >= 0 ?
@@ -2700,27 +2467,28 @@ GenerateStructors(io::Printer* printer) {
"$classname$::$classname$()\n"
" : $initializer$ {\n"
" if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {\n"
- " $file_namespace$::InitDefaults();\n"
+ " ::$file_namespace$::InitDefaults$scc_name$();\n"
" }\n"
" SharedCtor();\n"
" // @@protoc_insertion_point(constructor:$full_name$)\n"
"}\n",
"classname", classname_, "full_name", descriptor_->full_name(),
- "initializer", initializer_null, "file_namespace",
- FileLevelNamespace(descriptor_->file()->name()));
+ "scc_name", scc_name_, "initializer", initializer_null, "file_namespace",
+ FileLevelNamespace(descriptor_));
if (SupportsArenas(descriptor_)) {
printer->Print(
"$classname$::$classname$(::google::protobuf::Arena* arena)\n"
" : $initializer$ {\n"
- " $file_namespace$::InitDefaults();\n"
+ " ::$file_namespace$::InitDefaults$scc_name$();\n"
" SharedCtor();\n"
" RegisterArenaDtor(arena);\n"
" // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
"}\n",
"initializer", initializer_with_arena, "classname", classname_,
"superclass", superclass, "full_name", descriptor_->full_name(),
- "file_namespace", FileLevelNamespace(descriptor_->file()->name()));
+ "scc_name", scc_name_, "file_namespace",
+ FileLevelNamespace(descriptor_));
}
// Generate the copy constructor.
@@ -2865,23 +2633,23 @@ GenerateStructors(io::Printer* printer) {
!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(
"const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
- " $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
- " return "
+ " ::$file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+ " return ::"
"$file_namespace$::file_level_metadata[kIndexInFileMessages]."
"descriptor;\n"
"}\n"
"\n",
"classname", classname_, "file_namespace",
- FileLevelNamespace(descriptor_->file()->name()));
+ FileLevelNamespace(descriptor_));
}
printer->Print(
"const $classname$& $classname$::default_instance() {\n"
- " $file_namespace$::InitDefaults();\n"
+ " ::$file_namespace$::InitDefaults$scc_name$();\n"
" return *internal_default_instance();\n"
"}\n\n",
- "classname", classname_, "file_namespace",
- FileLevelNamespace(descriptor_->file()->name()));
+ "classname", classname_, "scc_name", scc_name_, "file_namespace",
+ FileLevelNamespace(descriptor_));
if (SupportsArenas(descriptor_)) {
printer->Print(
@@ -2930,6 +2698,9 @@ bool MessageGenerator::MaybeGenerateOptionalFieldCondition(
void MessageGenerator::
GenerateClear(io::Printer* printer) {
+ // Performance tuning parameters
+ const int kMaxUnconditionalPrimitiveBytesClear = 4;
+
printer->Print(
"void $classname$::Clear() {\n"
"// @@protoc_insertion_point(message_clear_start:$full_name$)\n",
@@ -2951,6 +2722,17 @@ GenerateClear(io::Printer* printer) {
}
int last_i = -1;
+ int unconditional_budget = kMaxUnconditionalPrimitiveBytesClear;
+ for (int i = 0; i < optimized_order_.size(); i++) {
+ const FieldDescriptor* field = optimized_order_[i];
+
+ if (!CanInitializeByZeroing(field)) {
+ continue;
+ }
+
+ unconditional_budget -= EstimateAlignmentSize(field);
+ }
+
for (int i = 0; i < optimized_order_.size(); ) {
// Detect infinite loops.
GOOGLE_CHECK_NE(i, last_i);
@@ -2998,7 +2780,8 @@ GenerateClear(io::Printer* printer) {
if (last_chunk == -1) {
last_chunk = chunk;
last_chunk_start = i;
- } else if (chunk != last_chunk) {
+ } else if ((memset_run_start == -1 || unconditional_budget < 0) &&
+ chunk != last_chunk) {
// Emit the fields for this chunk so far.
break;
}
@@ -3012,6 +2795,11 @@ GenerateClear(io::Printer* printer) {
last_chunk_mask |= static_cast<uint32>(1) << (index % 32);
}
+ if (memset_run_start != memset_run_end && unconditional_budget >= 0) {
+ // Flush the memset fields.
+ goto flush;
+ }
+
// Step 4: Non-repeated, non-zero initializable fields.
for (; i < optimized_order_.size(); i++) {
const FieldDescriptor* field = optimized_order_[i];
@@ -3037,6 +2825,8 @@ GenerateClear(io::Printer* printer) {
last_chunk_mask |= static_cast<uint32>(1) << (index % 32);
}
+flush:
+
if (last_chunk != -1) {
GOOGLE_DCHECK_NE(-1, last_chunk_start);
GOOGLE_DCHECK_NE(-1, last_chunk_end);
@@ -3044,7 +2834,10 @@ GenerateClear(io::Printer* printer) {
const int count = popcnt(last_chunk_mask);
const bool have_outer_if = HasFieldPresence(descriptor_->file()) &&
- (last_chunk_start != last_chunk_end);
+ (last_chunk_start != last_chunk_end) &&
+ (memset_run_start != last_chunk_start ||
+ memset_run_end != last_chunk_end ||
+ unconditional_budget < 0);
if (have_outer_if) {
// Check (up to) 8 has_bits at a time if we have more than one field in
@@ -3613,12 +3406,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Print(
"return ::google::protobuf::internal::MergePartialFromCodedStream$lite$(\n"
" this,\n"
- " $file_namespace$::TableStruct::schema[\n"
+ " ::$file_namespace$::TableStruct::schema[\n"
" $classname$::kIndexInFileMessages],\n"
" input);\n",
- "classname", classname_,
- "file_namespace", FileLevelNamespace(descriptor_->file()->name()),
- "lite", lite);
+ "classname", classname_, "file_namespace",
+ FileLevelNamespace(descriptor_), "lite", lite);
printer->Outdent();
@@ -3631,17 +3423,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
" ::google::protobuf::uint32 tag;\n");
if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
- // Use LazyStringOutputString to avoid initializing unknown fields string
- // unless it is actually needed. For the same reason, disable eager refresh
- // on the CodedOutputStream.
printer->Print(
- " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
- " ::google::protobuf::NewPermanentCallback(&_internal_metadata_,\n"
- " &::google::protobuf::internal::InternalMetadataWithArenaLite::\n"
- " mutable_unknown_fields));\n"
- " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
- " &unknown_fields_string, false);\n",
- "classname", classname_);
+ " ::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(\n"
+ " &_internal_metadata_);\n"
+ " ::google::protobuf::io::StringOutputStream unknown_fields_output(\n"
+ " unknown_fields_setter.buffer());\n"
+ " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
+ " &unknown_fields_output, false);\n",
+ "classname", classname_);
}
printer->Print(
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 352069eb..cf64f483 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -43,6 +43,7 @@
#include <string>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
@@ -62,12 +63,10 @@ class ExtensionGenerator; // extension.h
class MessageGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- MessageGenerator(const Descriptor* descriptor, const Options& options,
- SCCAnalyzer* scc_analyzer);
+ MessageGenerator(const Descriptor* descriptor, int index_in_file_messages,
+ const Options& options, SCCAnalyzer* scc_analyzer);
~MessageGenerator();
- // Appends the pre-order walk of the nested generators to list.
- void Flatten(std::vector<MessageGenerator*>* list);
// Append the two types of nested generators to the corresponding vector.
void AddGenerators(std::vector<EnumGenerator*>* enum_generators,
std::vector<ExtensionGenerator*>* extension_generators);
@@ -96,8 +95,8 @@ class MessageGenerator {
// Generate extra fields
void GenerateExtraDefaultFields(io::Printer* printer);
- // Generates code that allocates the message's default instance.
- void GenerateDefaultInstanceAllocator(io::Printer* printer);
+ // Generates code that creates default instances for fields.
+ void GenerateFieldDefaultInstances(io::Printer* printer);
// Generates code that initializes the message's default instance. This
// is separate from allocating because all default instances must be
@@ -208,6 +207,7 @@ class MessageGenerator {
std::vector<uint32> RequiredFieldsBitMask() const;
const Descriptor* descriptor_;
+ int index_in_file_messages_;
string classname_;
Options options_;
FieldGeneratorMap field_generators_;
@@ -218,7 +218,6 @@ class MessageGenerator {
std::vector<const FieldDescriptor *> optimized_order_;
std::vector<int> has_bit_indices_;
int max_has_bit_index_;
- google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
int num_required_fields_;
@@ -227,9 +226,10 @@ class MessageGenerator {
// table_driven_ indicates the generated message uses table-driven parsing.
bool table_driven_;
- int index_in_file_messages_;
+ google::protobuf::scoped_ptr<MessageLayoutHelper> message_layout_helper_;
SCCAnalyzer* scc_analyzer_;
+ string scc_name_;
friend class FileGenerator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index da4c3950..5888f51a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -45,13 +45,42 @@ namespace cpp {
namespace {
+// When we are generating code for implicit weak fields, we need to insert some
+// additional casts. These functions return the casted expression if
+// implicit_weak_field is true but otherwise return the original expression.
+// Ordinarily a static_cast is enough to cast google::protobuf::MessageLite* to a class
+// deriving from it, but we need a reinterpret_cast in cases where the generated
+// message is forward-declared but its full definition is not visible.
+string StaticCast(const string& type, const string& expression,
+ bool implicit_weak_field) {
+ if (implicit_weak_field) {
+ return "static_cast< " + type + " >(" + expression + ")";
+ } else {
+ return expression;
+ }
+}
+
+string ReinterpretCast(const string& type, const string& expression,
+ bool implicit_weak_field) {
+ if (implicit_weak_field) {
+ return "reinterpret_cast< " + type + " >(" + expression + ")";
+ } else {
+ return expression;
+ }
+}
+
void SetMessageVariables(const FieldDescriptor* descriptor,
std::map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
+ (*variables)["casted_member"] =
+ StaticCast((*variables)["type"] + "*", (*variables)["name"] + "_",
+ IsImplicitWeakField(descriptor, options));
(*variables)["type_default_instance"] =
DefaultInstanceName(descriptor->message_type());
+ (*variables)["type_reference_function"] =
+ ReferenceFunctionName(descriptor->message_type());
if (descriptor->options().weak() || !descriptor->containing_oneof()) {
(*variables)["non_null_ptr_to_name"] =
StrCat("this->", (*variables)["name"], "_");
@@ -85,7 +114,8 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: FieldGenerator(options),
descriptor_(descriptor),
- dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
+ implicit_weak_field_(IsImplicitWeakField(descriptor, options)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -93,7 +123,11 @@ MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
- printer->Print(variables_, "$type$* $name$_;\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables_, "google::protobuf::MessageLite* $name$_;\n");
+ } else {
+ printer->Print(variables_, "$type$* $name$_;\n");
+ }
}
void MessageFieldGenerator::
@@ -108,7 +142,11 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const {
if (!dependent_field_) {
return;
}
- // Arena manipulation code is out-of-line in the derived message class.
+ // Arena manipulation code is out-of-line in the derived message class. The
+ // one exception is unsafe_arena_release_; this method has to be inline so
+ // that when the implicit weak field optimization is enabled, the method does
+ // not introduce a strong dependency on the submessage type unless the
+ // accessor actually gets called somewhere.
printer->Print(variables_,
"$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
printer->Annotate("{", "}", descriptor_);
@@ -118,14 +156,22 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const {
"$deprecated_attr$void ${$set_allocated_$name$$}$"
"($type$* $name$);\n");
printer->Annotate("{", "}", descriptor_);
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ variables_,
+ "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
}
void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "private:\n"
- "void _slow_mutable_$name$();\n");
+ "private:\n");
+ if (!implicit_weak_field_) {
+ printer->Print(variables_, "void _slow_mutable_$name$();\n");
+ }
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables_,
"void _slow_set_allocated_$name$(\n"
@@ -135,6 +181,16 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$type$* _slow_$release_name$();\n"
"public:\n");
}
+ if (implicit_weak_field_) {
+ // These private accessors are used by MergeFrom and
+ // MergePartialFromCodedStream, and their purpose is to provide access to
+ // the field without creating a strong dependency on the message type.
+ printer->Print(variables_,
+ "private:\n"
+ "const google::protobuf::MessageLite& _internal_$name$() const;\n"
+ "google::protobuf::MessageLite* _internal_mutable_$name$();\n"
+ "public:\n");
+ }
GenerateGetterDeclaration(printer);
if (!dependent_field_) {
printer->Print(variables_,
@@ -146,12 +202,14 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$deprecated_attr$void ${$set_allocated_$name$$}$"
"($type$* $name$);\n");
printer->Annotate("{", "}", descriptor_);
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ variables_,
+ "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
}
if (SupportsArenas(descriptor_)) {
- printer->Print(
- variables_,
- "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n");
- printer->Annotate("{", "}", descriptor_);
printer->Print(variables_,
"$deprecated_attr$void "
"${$unsafe_arena_set_allocated_$name$$}$(\n"
@@ -162,9 +220,39 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
io::Printer* printer) const {
- if (SupportsArenas(descriptor_)) {
+ if (implicit_weak_field_) {
printer->Print(variables_,
- "void $classname$::_slow_mutable_$name$() {\n");
+ "const google::protobuf::MessageLite& $classname$::_internal_$name$() const {\n"
+ " if ($name$_ != NULL) {\n"
+ " return *$name$_;\n"
+ " } else if (&$type_default_instance$ != NULL) {\n"
+ " return *reinterpret_cast<const google::protobuf::MessageLite*>(\n"
+ " &$type_default_instance$);\n"
+ " } else {\n"
+ " return *reinterpret_cast<const google::protobuf::MessageLite*>(\n"
+ " &::google::protobuf::internal::implicit_weak_message_default_instance);\n"
+ " }\n"
+ "}\n");
+ }
+ if (SupportsArenas(descriptor_)) {
+ if (implicit_weak_field_) {
+ printer->Print(variables_,
+ "google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " if ($name$_ == NULL) {\n"
+ " if (&$type_default_instance$ == NULL) {\n"
+ " $name$_ = ::google::protobuf::Arena::CreateMessage<\n"
+ " ::google::protobuf::internal::ImplicitWeakMessage>(\n"
+ " GetArenaNoVirtual());\n"
+ " } else {\n"
+ " $name$_ = reinterpret_cast<const google::protobuf::MessageLite*>(\n"
+ " &$type_default_instance$)->New(GetArenaNoVirtual());\n"
+ " }\n"
+ " }\n"
+ " return $name$_;\n");
+ } else {
+ printer->Print(variables_,
+ "void $classname$::_slow_mutable_$name$() {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables_,
" $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
@@ -174,23 +262,27 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
" $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
" GetArenaNoVirtual());\n");
}
+ }
printer->Print(variables_,
"}\n"
"$type$* $classname$::_slow_$release_name$() {\n"
" if ($name$_ == NULL) {\n"
" return NULL;\n"
- " } else {\n"
- " $type$* temp = new $type$(*$name$_);\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
+ " } else {\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables_,
+ " google::protobuf::MessageLite* temp = $name$_->New();\n"
+ " temp->CheckTypeAndMergeFrom(*$name$_);\n");
+ } else {
+ printer->Print(variables_,
+ " $type$* temp = new $type$(*$name$_);\n");
+ }
+ printer->Print(variables_, " $name$_ = NULL;\n");
+ printer->Print(
+ " return $result$;\n", "result",
+ StaticCast(variables_.at("type") + "*", "temp", implicit_weak_field_));
+ printer->Print(variables_,
" }\n"
- "}\n"
- "$type$* $classname$::unsafe_arena_release_$name$() {\n"
- " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
- " $clear_hasbit$\n"
- " $type$* temp = $name$_;\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
"}\n");
if (SupportsArenas(descriptor_->message_type())) {
// NOTE: the same logic is mirrored in weak_message_field.cc. Any
@@ -202,12 +294,23 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
" ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
" message_arena->Own(*$name$);\n"
" } else if (message_arena !=\n"
- " ::google::protobuf::Arena::GetArena(*$name$)) {\n"
- " $type$* new_$name$ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " message_arena);\n"
- " new_$name$->CopyFrom(**$name$);\n"
- " *$name$ = new_$name$;\n"
+ " ::google::protobuf::Arena::GetArena(*$name$)) {\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables_,
+ " google::protobuf::MessageLite* new_$name$ =\n"
+ " reinterpret_cast<const google::protobuf::MessageLite*>(\n"
+ " &$type_default_instance$)->New(GetArenaNoVirtual());\n"
+ " new_$name$->CheckTypeAndMergeFrom(**$name$);\n"
+ " *$name$ = static_cast< $type$* >(new_$name$);\n");
+ } else {
+ printer->Print(variables_,
+ " $type$* new_$name$ =\n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " message_arena);\n"
+ " new_$name$->CopyFrom(**$name$);\n"
+ " *$name$ = new_$name$;\n");
+ }
+ printer->Print(variables_,
" }\n"
"}\n");
}
@@ -228,6 +331,20 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
":$full_name$)\n"
"}\n");
+ } else if (implicit_weak_field_) {
+ printer->Print(variables_,
+ "google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " if ($name$_ == NULL) {\n"
+ " if (&$type_default_instance$ == NULL) {\n"
+ " $name$_ = new ::google::protobuf::internal::ImplicitWeakMessage;\n"
+ " } else {\n"
+ " $name$_ = reinterpret_cast<const google::protobuf::MessageLite*>(\n"
+ " &$type_default_instance$)->New();\n"
+ " }\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
}
}
@@ -243,6 +360,10 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
variables["dependent_classname"] =
DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
variables["this_message"] = DependentBaseDownCast();
+ variables["casted_reference"] =
+ ReinterpretCast(variables["dependent_typename"] + "*&",
+ variables["this_message"] + variables["name"] + "_",
+ implicit_weak_field_);
if (!variables["set_hasbit"].empty()) {
variables["set_hasbit"] =
variables["this_message"] + variables["set_hasbit"];
@@ -255,19 +376,39 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
"template <class T>\n"
- "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables, " $type_reference_function$();\n");
+ }
+ printer->Print(variables,
" $set_hasbit$\n"
- " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
- " if ($name$_ == NULL) {\n"
- " $this_message$_slow_mutable_$name$();\n"
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
+ " if ($name$_ == NULL) {\n");
+ if (implicit_weak_field_) {
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables,
+ " $name$_ = reinterpret_cast<$dependent_typename$*>(\n"
+ " reinterpret_cast<const google::protobuf::MessageLite*>(\n"
+ " &$type_default_instance$)->New(\n"
+ " $this_message$GetArenaNoVirtual()));\n");
+ }
+ } else {
+ printer->Print(variables,
+ " $this_message$_slow_mutable_$name$();\n");
+ }
+ printer->Print(variables,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
"template <class T>\n"
"inline $type$* $dependent_classname$::$release_name$() {\n"
- " // @@protoc_insertion_point(field_release:$full_name$)\n"
- " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables, " $type_reference_function$();\n");
+ }
+ printer->Print(variables,
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
" $clear_hasbit$\n"
" if ($this_message$GetArenaNoVirtual() != NULL) {\n"
" return $this_message$_slow_$release_name$();\n"
@@ -281,7 +422,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
"inline void $dependent_classname$::"
"set_allocated_$name$($type$* $name$) {\n"
" ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
- " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
" if (message_arena == NULL) {\n"
" delete $name$_;\n"
" }\n"
@@ -311,13 +452,27 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
" }\n"
// TODO(dlj): move insertion points to message class.
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::unsafe_arena_release_$name$() {\n"
+ " // @@protoc_insertion_point("
+ "field_unsafe_arena_release:$full_name$)\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables, " $type_reference_function$();\n");
+ }
+ printer->Print(variables,
+ " $clear_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
"}\n");
} else {
printer->Print(variables,
"template <class T>\n"
"inline $type$* $dependent_classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
- " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
" if ($name$_ == NULL) {\n"
" $name$_ = new $dependent_typename$;\n"
" }\n"
@@ -326,9 +481,13 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
"}\n"
"template <class T>\n"
"inline $type$* $dependent_classname$::$release_name$() {\n"
- " // @@protoc_insertion_point(field_release:$full_name$)\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables, " $type_reference_function$();\n");
+ }
+ printer->Print(variables,
" $clear_hasbit$\n"
- " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
" $dependent_typename$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
@@ -336,7 +495,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
"template <class T>\n"
"inline void $dependent_classname$::"
"set_allocated_$name$($type$* $name$) {\n"
- " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$*& $name$_ = $casted_reference$;\n"
" delete $name$_;\n");
if (SupportsArenas(descriptor_->message_type())) {
@@ -366,9 +525,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
+ variables["const_member"] = ReinterpretCast(
+ "const " + variables["type"] + "*", variables["name"] + "_",
+ implicit_weak_field_);
printer->Print(variables,
- "$inline$const $type$& $classname$::$name$() const {\n"
- " const $type$* p = $name$_;\n"
+ "$inline$const $type$& $classname$::$name$() const {\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables, " $type_reference_function$();\n");
+ }
+ printer->Print(variables,
+ " const $type$* p = $const_member$;\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n"
" &$type_default_instance$);\n"
@@ -381,11 +547,18 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"$inline$"
"$type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
- " if ($name$_ == NULL) {\n"
- " _slow_mutable_$name$();\n"
+ " if ($name$_ == NULL) {\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables,
+ " _internal_mutable_$name$();\n");
+ } else {
+ printer->Print(variables,
+ " _slow_mutable_$name$();\n");
+ }
+ printer->Print(variables,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_;\n"
+ " return $casted_member$;\n"
"}\n"
"$inline$"
"$type$* $classname$::$release_name$() {\n"
@@ -394,7 +567,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" if (GetArenaNoVirtual() != NULL) {\n"
" return _slow_$release_name$();\n"
" } else {\n"
- " $type$* temp = $name$_;\n"
+ " $type$* temp = $casted_member$;\n"
" $name$_ = NULL;\n"
" return temp;\n"
" }\n"
@@ -429,6 +602,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $clear_hasbit$\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "$inline$"
+ "$type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " // @@protoc_insertion_point("
+ "field_unsafe_arena_release:$full_name$)\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables, " $type_reference_function$();\n");
+ }
+ printer->Print(variables,
+ " $clear_hasbit$\n"
+ " $type$* temp = $casted_member$;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
"}\n");
} else {
printer->Print(variables,
@@ -439,13 +625,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $name$_ = new $type$;\n"
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_;\n"
+ " return $casted_member$;\n"
"}\n"
"$inline$"
"$type$* $classname$::$release_name$() {\n"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
- " $type$* temp = $name$_;\n"
+ " $type$* temp = $casted_member$;\n"
" $name$_ = NULL;\n"
" return temp;\n"
"}\n"
@@ -485,6 +671,9 @@ GenerateClearingCode(io::Printer* printer) const {
"if ($this_message$GetArenaNoVirtual() == NULL && "
"$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
"$this_message$$name$_ = NULL;\n");
+ } else if (implicit_weak_field_) {
+ printer->Print(variables,
+ "if ($this_message$$name$_ != NULL) $this_message$$name$_->Clear();\n");
} else {
printer->Print(variables,
"if ($this_message$$name$_ != NULL) $this_message$$name$_->"
@@ -502,6 +691,10 @@ GenerateMessageClearingCode(io::Printer* printer) const {
" delete $name$_;\n"
"}\n"
"$name$_ = NULL;\n");
+ } else if (implicit_weak_field_) {
+ printer->Print(variables_,
+ "GOOGLE_DCHECK($name$_ != NULL);\n"
+ "$name$_->Clear();\n");
} else {
printer->Print(variables_,
"GOOGLE_DCHECK($name$_ != NULL);\n"
@@ -511,8 +704,14 @@ GenerateMessageClearingCode(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
+ if (implicit_weak_field_) {
+ printer->Print(variables_,
+ "_internal_mutable_$name$()->CheckTypeAndMergeFrom(\n"
+ " from._internal_$name$());\n");
+ } else {
+ printer->Print(variables_,
+ "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
+ }
}
void MessageFieldGenerator::
@@ -557,17 +756,24 @@ GenerateCopyConstructorCode(io::Printer* printer) const {
// wasn't copied, so both of these methods allocate the submessage on the
// heap.
- printer->Print(variables_,
- "if (from.has_$name$()) {\n"
- " $name$_ = new $type$(*from.$name$_);\n"
- "} else {\n"
- " $name$_ = NULL;\n"
- "}\n");
+ string new_expression = (implicit_weak_field_ ? "from.$name$_->New()"
+ : "new $type$(*from.$name$_)");
+ string output =
+ "if (from.has_$name$()) {\n"
+ " $name$_ = " + new_expression + ";\n"
+ "} else {\n"
+ " $name$_ = NULL;\n"
+ "}\n";
+ printer->Print(variables_, output.c_str());
}
void MessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
+ if (implicit_weak_field_) {
+ printer->Print(variables_,
+ "DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n"
+ " input, _internal_mutable_$name$()));\n");
+ } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
" input, mutable_$name$()));\n");
@@ -595,9 +801,11 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
- printer->Print(variables_,
+ std::map<string, string> variables = variables_;
+ variables["no_virtual"] = (implicit_weak_field_ ? "" : "NoVirtual");
+ printer->Print(variables,
"total_size += $tag_size$ +\n"
- " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
+ " ::google::protobuf::internal::WireFormatLite::$declared_type$Size$no_virtual$(\n"
" *$non_null_ptr_to_name$);\n");
}
@@ -771,13 +979,15 @@ void MessageOneofFieldGenerator::InternalGenerateInlineAccessorDefinitions(
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::unsafe_arena_release_$name$() {\n"
" // @@protoc_insertion_point(field_unsafe_arena_release"
":$full_name$)\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " $dependent_typename$* temp = $this_message$$oneof_prefix$$name$_;\n"
+ " $this_message$$oneof_prefix$$name$_ = NULL;\n"
" return temp;\n"
" } else {\n"
" return NULL;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index cd9737f0..14698992 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -44,6 +44,8 @@ namespace protobuf {
namespace compiler {
namespace cpp {
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options);
+
class MessageFieldGenerator : public FieldGenerator {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor,
@@ -78,6 +80,7 @@ class MessageFieldGenerator : public FieldGenerator {
const FieldDescriptor* descriptor_;
const bool dependent_field_;
+ const bool implicit_weak_field_;
std::map<string, string> variables_;
private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
new file mode 100644
index 00000000..d502a6f0
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
@@ -0,0 +1,61 @@
+// 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: seongkim@google.com (Seong Beom Kim)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
+
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Provides an abstract interface to optimize message layout
+// by rearranging the fields of a message.
+class MessageLayoutHelper {
+ public:
+ virtual ~MessageLayoutHelper() {}
+
+ virtual void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
+ const Options& options) = 0;
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 04338083..4a29ad0e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -39,6 +39,8 @@
namespace google {
namespace protobuf {
namespace compiler {
+class AccessInfoMap;
+
namespace cpp {
// Generator options (see generator.cc for a description of each):
@@ -50,7 +52,9 @@ struct Options {
annotate_headers(false),
enforce_lite(false),
table_driven_parsing(false),
- table_driven_serialization(false) {}
+ table_driven_serialization(false),
+ lite_implicit_weak_fields(false),
+ access_info_map(NULL) {}
string dllexport_decl;
bool safe_boundary_check;
@@ -60,8 +64,10 @@ struct Options {
bool enforce_lite;
bool table_driven_parsing;
bool table_driven_serialization;
+ bool lite_implicit_weak_fields;
string annotation_pragma_name;
string annotation_guard_name;
+ const AccessInfoMap* access_info_map;
};
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
new file mode 100644
index 00000000..e9303865
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
@@ -0,0 +1,220 @@
+// 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.
+
+#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+// FieldGroup is just a helper for PaddingOptimizer below. It holds a vector of
+// fields that are grouped together because they have compatible alignment, and
+// a preferred location in the final field ordering.
+class FieldGroup {
+ public:
+ FieldGroup() : preferred_location_(0) {}
+
+ // A group with a single field.
+ FieldGroup(float preferred_location, const FieldDescriptor* field)
+ : preferred_location_(preferred_location), fields_(1, field) {}
+
+ // Append the fields in 'other' to this group.
+ void Append(const FieldGroup& other) {
+ if (other.fields_.empty()) {
+ return;
+ }
+ // Preferred location is the average among all the fields, so we weight by
+ // the number of fields on each FieldGroup object.
+ preferred_location_ = (preferred_location_ * fields_.size() +
+ (other.preferred_location_ * other.fields_.size())) /
+ (fields_.size() + other.fields_.size());
+ fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
+ }
+
+ void SetPreferredLocation(float location) { preferred_location_ = location; }
+ const std::vector<const FieldDescriptor*>& fields() const { return fields_; }
+
+ // FieldGroup objects sort by their preferred location.
+ bool operator<(const FieldGroup& other) const {
+ return preferred_location_ < other.preferred_location_;
+ }
+
+ private:
+ // "preferred_location_" is an estimate of where this group should go in the
+ // final list of fields. We compute this by taking the average index of each
+ // field in this group in the original ordering of fields. This is very
+ // approximate, but should put this group close to where its member fields
+ // originally went.
+ float preferred_location_;
+ std::vector<const FieldDescriptor*> fields_;
+ // We rely on the default copy constructor and operator= so this type can be
+ // used in a vector.
+};
+
+} // namespace
+
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, fields of similar family (see below) are together and within each
+// family, alignment padding is minimized.
+//
+// We try to do this while keeping each field as close as possible to its field
+// number order so that we don't reduce cache locality much for function that
+// access each field in order. Originally, OptimizePadding used declaration
+// order for its decisions, but generated code minus the serializer/parsers uses
+// the output of OptimizePadding as well (stored in
+// MessageGenerator::optimized_order_). Since the serializers use field number
+// order, we use that as a tie-breaker.
+//
+// We classify each field into a particular "family" of fields, that we perform
+// the same operation on in our generated functions.
+//
+// REPEATED is placed first, as the C++ compiler automatically initializes
+// these fields in layout order.
+//
+// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
+// calls ArenaStringPtr::Destroy on each.
+//
+//
+// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
+// delete on each. We initialize these fields with a NULL pointer (see
+// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
+// memset.
+//
+// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
+//
+// OTHER these fields are initialized one-by-one.
+void PaddingOptimizer::OptimizeLayout(
+ std::vector<const FieldDescriptor*>* fields, const Options& options) {
+ // The sorted numeric order of Family determines the declaration order in the
+ // memory layout.
+ enum Family {
+ REPEATED = 0,
+ STRING = 1,
+ MESSAGE = 3,
+ ZERO_INITIALIZABLE = 4,
+ OTHER = 5,
+ kMaxFamily
+ };
+
+ // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
+ std::vector<FieldGroup> aligned_to_1[kMaxFamily];
+ std::vector<FieldGroup> aligned_to_4[kMaxFamily];
+ std::vector<FieldGroup> aligned_to_8[kMaxFamily];
+ for (int i = 0; i < fields->size(); ++i) {
+ const FieldDescriptor* field = (*fields)[i];
+
+ Family f = OTHER;
+ if (field->is_repeated()) {
+ f = REPEATED;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ f = STRING;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ f = MESSAGE;
+
+ } else if (CanInitializeByZeroing(field)) {
+ f = ZERO_INITIALIZABLE;
+ }
+
+ const int j = field->number();
+ switch (EstimateAlignmentSize(field)) {
+ case 1:
+ aligned_to_1[f].push_back(FieldGroup(j, field));
+ break;
+ case 4:
+ aligned_to_4[f].push_back(FieldGroup(j, field));
+ break;
+ case 8:
+ aligned_to_8[f].push_back(FieldGroup(j, field));
+ break;
+ default:
+ GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field)
+ << "for a field " << field->full_name() << ".";
+ }
+ }
+
+ // For each family, group fields to optimize padding.
+ for (int f = 0; f < kMaxFamily; f++) {
+ // Now group fields aligned to 1 byte into sets of 4, and treat those like a
+ // single field aligned to 4 bytes.
+ for (int i = 0; i < aligned_to_1[f].size(); i += 4) {
+ FieldGroup field_group;
+ for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
+ field_group.Append(aligned_to_1[f][j]);
+ }
+ aligned_to_4[f].push_back(field_group);
+ }
+ // Sort by preferred location to keep fields as close to their field number
+ // order as possible. Using stable_sort ensures that the output is
+ // consistent across runs.
+ std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end());
+
+ // Now group fields aligned to 4 bytes (or the 4-field groups created above)
+ // into pairs, and treat those like a single field aligned to 8 bytes.
+ for (int i = 0; i < aligned_to_4[f].size(); i += 2) {
+ FieldGroup field_group;
+ for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
+ field_group.Append(aligned_to_4[f][j]);
+ }
+ if (i == aligned_to_4[f].size() - 1) {
+ if (f == OTHER) {
+ // Move incomplete 4-byte block to the beginning. This is done to
+ // pair with the (possible) leftover blocks from the
+ // ZERO_INITIALIZABLE family.
+ field_group.SetPreferredLocation(-1);
+ } else {
+ // Move incomplete 4-byte block to the end.
+ field_group.SetPreferredLocation(fields->size() + 1);
+ }
+ }
+ aligned_to_8[f].push_back(field_group);
+ }
+ // Sort by preferred location.
+ std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
+ }
+
+ // Now pull out all the FieldDescriptors in order.
+ fields->clear();
+ for (int f = 0; f < kMaxFamily; ++f) {
+ for (int i = 0; i < aligned_to_8[f].size(); ++i) {
+ fields->insert(fields->end(), aligned_to_8[f][i].fields().begin(),
+ aligned_to_8[f][i].fields().end());
+ }
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
new file mode 100644
index 00000000..9641ba40
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
@@ -0,0 +1,64 @@
+// 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: seongkim@google.com (Seong Beom Kim)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
+
+#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Rearranges the fields of a message to minimize padding.
+// Fields are grouped by the type and the size.
+// For example, grouping four boolean fields and one int32
+// field results in zero padding overhead. See OptimizeLayout's
+// comment for details.
+class PaddingOptimizer : public MessageLayoutHelper {
+ public:
+ PaddingOptimizer() {}
+ ~PaddingOptimizer() {}
+
+ void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
+ const Options& options);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index b05fcc4e..67cfc405 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -245,9 +245,8 @@ GenerateSwappingCode(io::Printer* printer) const {
void PrimitiveOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
- printer->Print(
- variables_,
- "_$classname$_default_instance_.$name$_ = $default$;\n");
+ printer->Print(variables_,
+ "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
}
void PrimitiveOneofFieldGenerator::
@@ -433,7 +432,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
" target);\n"
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
- " static_cast< ::google::protobuf::uint32>(\n"
+ " static_cast< ::google::protobuf::int32>(\n"
" _$name$_cached_byte_size_), target);\n"
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoTagToArray(this->$name$_, target);\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index fec13b6d..8e675751 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -58,8 +58,8 @@ void SetStringVariables(const FieldDescriptor* descriptor,
(*variables)["default_variable"] =
descriptor->default_value_string().empty()
? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
- : "&" + (*variables)["classname"] + "::" + default_variable_string +
- ".get()";
+ : "&" + Namespace(descriptor) + "::" + (*variables)["classname"] +
+ "::" + default_variable_string + ".get()";
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
(*variables)["null_check"] = "GOOGLE_DCHECK(value != NULL);\n";
@@ -71,6 +71,9 @@ void SetStringVariables(const FieldDescriptor* descriptor,
(*variables)["full_name"] = descriptor->full_name();
(*variables)["string_piece"] = "::std::string";
+
+ (*variables)["lite"] =
+ HasDescriptorMethods(descriptor->file(), options) ? "" : "Lite";
}
} // namespace
@@ -79,7 +82,8 @@ void SetStringVariables(const FieldDescriptor* descriptor,
StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : FieldGenerator(options), descriptor_(descriptor) {
+ : FieldGenerator(options), descriptor_(descriptor),
+ lite_(!HasDescriptorMethods(descriptor->file(), options)) {
SetStringVariables(descriptor, &variables_, options);
}
@@ -207,13 +211,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n"
"$inline$void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
- " $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
+ " $name$_.Set$lite$($default_variable$, value, GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"#if LANG_CXX11\n"
"$inline$void $classname$::set_$name$(::std::string&& value) {\n"
" $set_hasbit$\n"
- " $name$_.Set(\n"
+ " $name$_.Set$lite$(\n"
" $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
"}\n"
@@ -221,7 +225,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"$inline$void $classname$::set_$name$(const char* value) {\n"
" $null_check$"
" $set_hasbit$\n"
- " $name$_.Set($default_variable$, $string_piece$(value),\n"
+ " $name$_.Set$lite$($default_variable$, $string_piece$(value),\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
@@ -229,7 +233,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" $set_hasbit$\n"
- " $name$_.Set($default_variable$, $string_piece$(\n"
+ " $name$_.Set$lite$($default_variable$, $string_piece$(\n"
" reinterpret_cast<const char*>(value), size), "
"GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
@@ -453,7 +457,7 @@ GenerateCopyConstructorCode(io::Printer* printer) const {
if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
// TODO(gpike): improve this
printer->Print(variables_,
- "$name$_.Set($default_variable$, from.$name$(),\n"
+ "$name$_.Set$lite$($default_variable$, from.$name$(),\n"
" GetArenaNoVirtual());\n");
} else {
printer->Print(variables_,
@@ -480,13 +484,14 @@ GenerateDestructorCode(io::Printer* printer) const {
void StringFieldGenerator::
GenerateDefaultInstanceAllocator(io::Printer* printer) const {
if (!descriptor_->default_value_string().empty()) {
- printer->Print(variables_,
- "$classname$::$default_variable_name$.DefaultConstruct();\n"
- "*$classname$::$default_variable_name$.get_mutable() = "
- "::std::string($default$, $default_length$);\n"
- "::google::protobuf::internal::OnShutdownDestroyString(\n"
- " $classname$::$default_variable_name$.get_mutable());\n"
- );
+ printer->Print(
+ variables_,
+ "$ns$::$classname$::$default_variable_name$.DefaultConstruct();\n"
+ "*$ns$::$classname$::$default_variable_name$.get_mutable() = "
+ "::std::string($default$, $default_length$);\n"
+ "::google::protobuf::internal::OnShutdownDestroyString(\n"
+ " $ns$::$classname$::$default_variable_name$.get_mutable());\n"
+ );
}
}
@@ -572,7 +577,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" set_has_$name$();\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
- " $oneof_prefix$$name$_.Set($default_variable$, value,\n"
+ " $oneof_prefix$$name$_.Set$lite$($default_variable$, value,\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
@@ -584,7 +589,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" set_has_$name$();\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
- " $oneof_prefix$$name$_.Set(\n"
+ " $oneof_prefix$$name$_.Set$lite$(\n"
" $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
"}\n"
@@ -596,7 +601,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" set_has_$name$();\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
- " $oneof_prefix$$name$_.Set($default_variable$,\n"
+ " $oneof_prefix$$name$_.Set$lite$($default_variable$,\n"
" $string_piece$(value), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
@@ -608,7 +613,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" set_has_$name$();\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
- " $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
+ " $oneof_prefix$$name$_.Set$lite$(\n"
+ " $default_variable$, $string_piece$(\n"
" reinterpret_cast<const char*>(value), size),\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
@@ -806,7 +812,7 @@ void StringOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(
variables_,
- "_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n"
+ "$ns$::_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n"
" $default_variable$);\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 531252b0..933f3c6b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -73,6 +73,7 @@ class StringFieldGenerator : public FieldGenerator {
protected:
const FieldDescriptor* descriptor_;
std::map<string, string> variables_;
+ const bool lite_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 4e25b2ea..7fe98759 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -151,6 +151,10 @@ enum ConflictingEnum { // NO_PROTO3
message DummyMessage {}
+// Message names that could conflict.
+message Shutdown {}
+message TableStruct {}
+
service TestConflictingMethodNames {
rpc Closure(DummyMessage) returns (DummyMessage);
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index fdde771b..61cc32a4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -744,21 +744,6 @@ TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
TestUtil::ExpectAllFieldsSet(message1);
}
-#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
- !defined(GOOGLE_PROTOBUF_NO_RTTI)
-#ifdef PROTOBUF_HAS_DEATH_TEST
-#ifndef NDEBUG
-
-TEST(GeneratedMessageTest, MergeFromSelf) {
- unittest::TestAllTypes message;
- EXPECT_DEATH(message.MergeFrom(message), "pb[.]cc.*Check failed:");
- EXPECT_DEATH(message.MergeFrom(implicit_cast<const Message&>(message)),
- "pb[.]cc.*Check failed:");
-}
-
-#endif // NDEBUG
-#endif // PROTOBUF_HAS_DEATH_TEST
-#endif // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI
// Test the generated SerializeWithCachedSizesToArray(),
TEST(GeneratedMessageTest, SerializationToArray) {
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index 4c357aa0..9792ffe8 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -54,13 +54,17 @@
#include <google/protobuf/compiler/parser.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/io_win32.h>
#ifdef _WIN32
#include <ctype.h>
#endif
+namespace google {
+namespace protobuf {
+namespace compiler {
+
#ifdef _MSC_VER
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
@@ -68,10 +72,6 @@ using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::open;
#endif
-namespace google {
-namespace protobuf {
-namespace compiler {
-
// Returns true if the text looks like a Windows-style absolute path, starting
// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with
// copy in command_line_interface.cc?
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index bd565ced..1ab168c4 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -136,6 +136,13 @@ inline string ShortMutableJavaClassName(const Descriptor* descriptor) {
return descriptor->name();
}
+// Whether the given descriptor is for one of the core descriptor protos. We
+// cannot currently use the new runtime with core protos since there is a
+// bootstrapping problem with obtaining their descriptors.
+inline bool IsDescriptorProto(const Descriptor* descriptor) {
+ return descriptor->file()->name() == "google/protobuf/descriptor.proto";
+}
+
// Whether we should generate multiple java files for messages.
inline bool MultipleJavaFiles(
@@ -371,6 +378,10 @@ inline bool IsAnyMessage(const Descriptor* descriptor) {
return descriptor->full_name() == "google.protobuf.Any";
}
+inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) {
+ return descriptor->name() == "google/protobuf/wrappers.proto";
+}
+
inline bool CheckUtf8(const FieldDescriptor* descriptor) {
return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
descriptor->file()->options().java_string_check_utf8();
@@ -379,6 +390,10 @@ inline bool CheckUtf8(const FieldDescriptor* descriptor) {
inline string GeneratedCodeVersionSuffix() {
return "V3";
}
+
+inline bool EnableExperimentalRuntime(Context* context) {
+ return false;
+}
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index ecc67575..df0c95c8 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -379,7 +379,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"}\n");
if (context_->HasGeneratedMethods(descriptor_)) {
- GenerateParsingConstructor(printer);
+ if (!EnableExperimentalRuntime(context_) ||
+ IsDescriptorProto(descriptor_)) {
+ GenerateParsingConstructor(printer);
+ }
}
GenerateDescriptorMethods(printer);
@@ -537,6 +540,17 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
+ // 'of' method for Wrappers
+ if (IsWrappersProtoFile(descriptor_->file())) {
+ printer->Print(
+ "public static $classname$ of($field_type$ value) {\n"
+ " return newBuilder().setValue(value).build();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
+ }
+
GenerateParser(printer);
printer->Print(
@@ -576,95 +590,103 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
" throws java.io.IOException {\n");
printer->Indent();
- if (HasPackedFields(descriptor_)) {
- // writeTo(CodedOutputStream output) might be invoked without
- // getSerializedSize() ever being called, but we need the memoized
- // sizes in case this message has packed fields. Rather than emit checks for
- // each packed field, just call getSerializedSize() up front.
- // In most cases, getSerializedSize() will have already been called anyway
- // by one of the wrapper writeTo() methods, making this call cheap.
- printer->Print(
- "getSerializedSize();\n");
- }
- if (descriptor_->extension_range_count() > 0) {
- if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "com.google.protobuf.GeneratedMessage$ver$\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter\n"
- " extensionWriter = newMessageSetExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "ver", GeneratedCodeVersionSuffix());
- } else {
- printer->Print(
- "com.google.protobuf.GeneratedMessage$ver$\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter\n"
- " extensionWriter = newExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "ver", GeneratedCodeVersionSuffix());
+ if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) {
+ printer->Print("writeToInternal(output);\n");
+ } else {
+ if (HasPackedFields(descriptor_)) {
+ // writeTo(CodedOutputStream output) might be invoked without
+ // getSerializedSize() ever being called, but we need the memoized
+ // sizes in case this message has packed fields. Rather than emit checks
+ // for each packed field, just call getSerializedSize() up front. In most
+ // cases, getSerializedSize() will have already been called anyway by one
+ // of the wrapper writeTo() methods, making this call cheap.
+ printer->Print("getSerializedSize();\n");
}
- }
- // Merge the fields and the extension ranges, both sorted by field number.
- for (int i = 0, j = 0;
- i < descriptor_->field_count() || j < sorted_extensions.size();
- ) {
- if (i == descriptor_->field_count()) {
- GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
- } else if (j == sorted_extensions.size()) {
- GenerateSerializeOneField(printer, sorted_fields[i++]);
- } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
- GenerateSerializeOneField(printer, sorted_fields[i++]);
- } else {
- GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessage$ver$\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newMessageSetExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
+ } else {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessage$ver$\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
+ }
}
- }
- if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "unknownFields.writeAsMessageSetTo(output);\n");
- } else {
- printer->Print(
- "unknownFields.writeTo(output);\n");
+ // Merge the fields and the extension ranges, both sorted by field number.
+ for (int i = 0, j = 0;
+ i < descriptor_->field_count() || j < sorted_extensions.size();) {
+ if (i == descriptor_->field_count()) {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ } else if (j == sorted_extensions.size()) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ }
+ }
+
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print("unknownFields.writeAsMessageSetTo(output);\n");
+ } else {
+ printer->Print("unknownFields.writeTo(output);\n");
+ }
}
printer->Outdent();
printer->Print(
- "}\n"
- "\n"
- "public int getSerializedSize() {\n"
- " int size = memoizedSize;\n"
- " if (size != -1) return size;\n"
- "\n"
- " size = 0;\n");
+ "}\n"
+ "\n"
+ "public int getSerializedSize() {\n"
+ " int size = memoizedSize;\n"
+ " if (size != -1) return size;\n"
+ "\n");
printer->Indent();
+ if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) {
+ printer->Print(
+ "memoizedSize = getSerializedSizeInternal();\n"
+ "return memoizedSize;\n");
+ } else {
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
- }
+ printer->Print("size = 0;\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i])
+ .GenerateSerializedSizeCode(printer);
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
+ } else {
+ printer->Print("size += extensionsSerializedSize();\n");
+ }
+ }
- if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
printer->Print(
- "size += extensionsSerializedSizeAsMessageSet();\n");
+ "size += unknownFields.getSerializedSizeAsMessageSet();\n");
} else {
- printer->Print(
- "size += extensionsSerializedSize();\n");
+ printer->Print("size += unknownFields.getSerializedSize();\n");
}
- }
- if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "size += unknownFields.getSerializedSizeAsMessageSet();\n");
- } else {
printer->Print(
- "size += unknownFields.getSerializedSize();\n");
+ "memoizedSize = size;\n"
+ "return size;\n");
}
printer->Outdent();
printer->Print(
- " memoizedSize = size;\n"
- " return size;\n"
"}\n"
"\n");
}
@@ -1199,7 +1221,10 @@ GenerateParsingConstructor(io::Printer* printer) {
// Initialize all fields to default.
printer->Print(
- "this();\n");
+ "this();\n"
+ "if (extensionRegistry == null) {\n"
+ " throw new java.lang.NullPointerException();\n"
+ "}\n");
// Use builder bits to track mutable repeated fields.
int totalBuilderBits = 0;
@@ -1335,10 +1360,18 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n",
"classname", descriptor_->name());
- if (context_->HasGeneratedMethods(descriptor_)) {
+ if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) {
+ printer->Indent();
printer->Print(
- " return new $classname$(input, extensionRegistry);\n",
+ "$classname$ msg = new $classname$();\n"
+ "msg.mergeFromInternal(input, extensionRegistry);\n"
+ "msg.makeImmutableInternal();\n"
+ "return msg;\n",
"classname", descriptor_->name());
+ printer->Outdent();
+ } else if (context_->HasGeneratedMethods(descriptor_)) {
+ printer->Print(" return new $classname$(input, extensionRegistry);\n",
+ "classname", descriptor_->name());
} else {
// When parsing constructor isn't generated, use builder to parse
// messages. Note, will fallback to use reflection based mergeFieldFrom()
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 26f16439..29b4f98b 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -332,17 +332,19 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
- GenerateMessageSerializationMethods(printer);
+ if (!EnableExperimentalRuntime(context_)) {
+ GenerateMessageSerializationMethods(printer);
+ }
GenerateParseFromMethods(printer);
GenerateBuilder(printer);
if (HasRequiredFields(descriptor_)) {
// Memoizes whether the protocol buffer is fully initialized (has all
- // required fields). -1 means not yet computed. 0 means false and 1 means
- // true.
+ // required fields). 0 means false, 1 means true, and all other values
+ // mean not yet computed.
printer->Print(
- "private byte memoizedIsInitialized = -1;\n");
+ "private byte memoizedIsInitialized = 2;\n");
}
printer->Print(
@@ -415,13 +417,33 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
" }\n"
" }\n"
" }\n"
- " return PARSER;\n"
- "}\n",
+ " return PARSER;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Outdent();
- printer->Outdent();
+ if (HasRequiredFields(descriptor_)) {
+ printer->Print(
+ "}\n"
+ "case GET_MEMOIZED_IS_INITIALIZED: {\n"
+ " return memoizedIsInitialized;\n"
+ "}\n"
+ "case SET_MEMOIZED_IS_INITIALIZED: {\n"
+ " memoizedIsInitialized = (byte) (arg0 == null ? 0 : 1);\n"
+ " return null;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "}\n"
+ "case GET_MEMOIZED_IS_INITIALIZED: {\n"
+ " return (byte) 1;\n"
+ "}\n"
+ "case SET_MEMOIZED_IS_INITIALIZED: {\n"
+ " return null;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
printer->Print(
" }\n"
" throw new UnsupportedOperationException();\n"
@@ -455,6 +477,17 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
+ // 'of' method for Wrappers
+ if (IsWrappersProtoFile(descriptor_->file())) {
+ printer->Print(
+ "public static $classname$ of($field_type$ value) {\n"
+ " return newBuilder().setValue(value).build();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
+ }
+
GenerateParser(printer);
// Extensions must be declared after the DEFAULT_INSTANCE is initialized
@@ -490,36 +523,34 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
if (HasPackedFields(descriptor_)) {
// writeTo(CodedOutputStream output) might be invoked without
// getSerializedSize() ever being called, but we need the memoized
- // sizes in case this message has packed fields. Rather than emit checks for
- // each packed field, just call getSerializedSize() up front.
- // In most cases, getSerializedSize() will have already been called anyway
- // by one of the wrapper writeTo() methods, making this call cheap.
- printer->Print(
- "getSerializedSize();\n");
+ // sizes in case this message has packed fields. Rather than emit checks
+ // for each packed field, just call getSerializedSize() up front. In most
+ // cases, getSerializedSize() will have already been called anyway by one
+ // of the wrapper writeTo() methods, making this call cheap.
+ printer->Print("getSerializedSize();\n");
}
if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
printer->Print(
- "com.google.protobuf.GeneratedMessageLite\n"
- " .ExtendableMessage<$classname$, $classname$.Builder>\n"
- " .ExtensionWriter extensionWriter =\n"
- " newMessageSetExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "com.google.protobuf.GeneratedMessageLite\n"
+ " .ExtendableMessage<$classname$, $classname$.Builder>\n"
+ " .ExtensionWriter extensionWriter =\n"
+ " newMessageSetExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
} else {
printer->Print(
- "com.google.protobuf.GeneratedMessageLite\n"
- " .ExtendableMessage<$classname$, $classname$.Builder>\n"
- " .ExtensionWriter extensionWriter =\n"
- " newExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "com.google.protobuf.GeneratedMessageLite\n"
+ " .ExtendableMessage<$classname$, $classname$.Builder>\n"
+ " .ExtensionWriter extensionWriter =\n"
+ " newExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
}
}
// Merge the fields and the extension ranges, both sorted by field number.
for (int i = 0, j = 0;
- i < descriptor_->field_count() || j < sorted_extensions.size();
- ) {
+ i < descriptor_->field_count() || j < sorted_extensions.size();) {
if (i == descriptor_->field_count()) {
GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
} else if (j == sorted_extensions.size()) {
@@ -532,23 +563,22 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "unknownFields.writeAsMessageSetTo(output);\n");
+ printer->Print("unknownFields.writeAsMessageSetTo(output);\n");
} else {
- printer->Print(
- "unknownFields.writeTo(output);\n");
+ printer->Print("unknownFields.writeTo(output);\n");
}
printer->Outdent();
printer->Print(
- "}\n"
- "\n"
- "public int getSerializedSize() {\n"
- " int size = memoizedSerializedSize;\n"
- " if (size != -1) return size;\n"
- "\n"
- " size = 0;\n");
+ "}\n"
+ "\n"
+ "public int getSerializedSize() {\n"
+ " int size = memoizedSerializedSize;\n"
+ " if (size != -1) return size;\n"
+ "\n");
printer->Indent();
+ printer->Print(
+ "size = 0;\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
@@ -556,26 +586,24 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "size += extensionsSerializedSizeAsMessageSet();\n");
+ printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
} else {
- printer->Print(
- "size += extensionsSerializedSize();\n");
+ printer->Print("size += extensionsSerializedSize();\n");
}
}
if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "size += unknownFields.getSerializedSizeAsMessageSet();\n");
+ printer->Print("size += unknownFields.getSerializedSizeAsMessageSet();\n");
} else {
- printer->Print(
- "size += unknownFields.getSerializedSize();\n");
+ printer->Print("size += unknownFields.getSerializedSize();\n");
}
+ printer->Print(
+ "memoizedSerializedSize = size;\n"
+ "return size;\n");
+
printer->Outdent();
printer->Print(
- " memoizedSerializedSize = size;\n"
- " return size;\n"
"}\n"
"\n");
}
@@ -702,7 +730,10 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
return;
}
- // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+ // TODO(xiaofeng): Remove this when b/64445758 is fixed. We don't need to
+ // check memoizedIsInitialized here because the caller does that already,
+ // but right now proguard proto shrinker asserts on the bytecode layout of
+ // this code so it can't be removed until proguard is updated.
printer->Print(
"byte isInitialized = memoizedIsInitialized;\n"
"if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
@@ -720,9 +751,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
if (field->is_required()) {
printer->Print(
"if (!has$name$()) {\n"
- " if (shouldMemoize) {\n"
- " memoizedIsInitialized = 0;\n"
- " }\n"
" return null;\n"
"}\n",
"name", info->capitalized_name);
@@ -739,9 +767,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
case FieldDescriptor::LABEL_REQUIRED:
printer->Print(
"if (!get$name$().isInitialized()) {\n"
- " if (shouldMemoize) {\n"
- " memoizedIsInitialized = 0;\n"
- " }\n"
" return null;\n"
"}\n",
"type", name_resolver_->GetImmutableClassName(
@@ -765,9 +790,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
}
printer->Print(
" if (!get$name$().isInitialized()) {\n"
- " if (shouldMemoize) {\n"
- " memoizedIsInitialized = 0;\n"
- " }\n"
" return null;\n"
" }\n"
"}\n",
@@ -778,9 +800,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
printer->Print(
"for ($type$ item : get$name$Map().values()) {\n"
" if (!item.isInitialized()) {\n"
- " if (shouldMemoize) {\n"
- " memoizedIsInitialized = 0;\n"
- " }\n"
" return null;\n"
" }\n"
"}\n",
@@ -791,9 +810,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
printer->Print(
"for (int i = 0; i < get$name$Count(); i++) {\n"
" if (!get$name$(i).isInitialized()) {\n"
- " if (shouldMemoize) {\n"
- " memoizedIsInitialized = 0;\n"
- " }\n"
" return null;\n"
" }\n"
"}\n",
@@ -809,17 +825,11 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"if (!extensionsAreInitialized()) {\n"
- " if (shouldMemoize) {\n"
- " memoizedIsInitialized = 0;\n"
- " }\n"
" return null;\n"
"}\n");
}
printer->Print(
- "if (shouldMemoize) memoizedIsInitialized = 1;\n");
-
- printer->Print(
"return DEFAULT_INSTANCE;\n"
"\n");
}
@@ -946,99 +956,107 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream(
"com.google.protobuf.CodedInputStream input =\n"
" (com.google.protobuf.CodedInputStream) arg0;\n"
"com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n"
- " (com.google.protobuf.ExtensionRegistryLite) arg1;\n");
+ " (com.google.protobuf.ExtensionRegistryLite) arg1;\n"
+ "if (extensionRegistry == null) {\n"
+ " throw new java.lang.NullPointerException();\n"
+ "}\n");
printer->Print(
"try {\n");
printer->Indent();
- printer->Print(
- "boolean done = false;\n"
- "while (!done) {\n");
- printer->Indent();
-
- printer->Print(
- "int tag = input.readTag();\n"
- "switch (tag) {\n");
- printer->Indent();
+ if (EnableExperimentalRuntime(context_)) {
+ printer->Print(
+ "mergeFromInternal(input, extensionRegistry);\n"
+ "return DEFAULT_INSTANCE;\n");
+ } else {
+ printer->Print(
+ "boolean done = false;\n"
+ "while (!done) {\n");
+ printer->Indent();
- printer->Print(
- "case 0:\n" // zero signals EOF / limit reached
- " done = true;\n"
- " break;\n");
+ printer->Print(
+ "int tag = input.readTag();\n"
+ "switch (tag) {\n");
+ printer->Indent();
- if (descriptor_->extension_range_count() > 0) {
- if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "default: {\n"
- " if (!parseUnknownFieldAsMessageSet(\n"
- " getDefaultInstanceForType(), input, extensionRegistry,\n"
- " tag)) {\n"
- " done = true;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n");
+ printer->Print(
+ "case 0:\n" // zero signals EOF / limit reached
+ " done = true;\n"
+ " break;\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownFieldAsMessageSet(\n"
+ " getDefaultInstanceForType(), input, extensionRegistry,\n"
+ " tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(getDefaultInstanceForType(),\n"
+ " input, extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
} else {
printer->Print(
"default: {\n"
- " if (!parseUnknownField(getDefaultInstanceForType(),\n"
- " input, extensionRegistry, tag)) {\n"
+ " if (!parseUnknownField(tag, input)) {\n"
" done = true;\n" // it's an endgroup tag
" }\n"
" break;\n"
"}\n");
}
- } else {
- printer->Print(
- "default: {\n"
- " if (!parseUnknownField(tag, input)) {\n"
- " done = true;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n");
- }
- google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
- SortFieldsByNumber(descriptor_));
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = sorted_fields[i];
- uint32 tag = WireFormatLite::MakeTag(field->number(),
- WireFormat::WireTypeForFieldType(field->type()));
-
- printer->Print(
- "case $tag$: {\n",
- "tag", SimpleItoa(static_cast<int32>(tag)));
- printer->Indent();
-
- field_generators_.get(field).GenerateParsingCode(printer);
-
- printer->Outdent();
- printer->Print(
- " break;\n"
- "}\n");
+ google::protobuf::scoped_array<const FieldDescriptor* > sorted_fields(
+ SortFieldsByNumber(descriptor_));
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ uint32 tag = WireFormatLite::MakeTag(
+ field->number(), WireFormat::WireTypeForFieldType(field->type()));
- if (field->is_packable()) {
- // To make packed = true wire compatible, we generate parsing code from a
- // packed version of this field regardless of field->options().packed().
- uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
- WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
- printer->Print(
- "case $tag$: {\n",
- "tag", SimpleItoa(static_cast<int32>(packed_tag)));
+ printer->Print("case $tag$: {\n", "tag",
+ SimpleItoa(static_cast<int32>(tag)));
printer->Indent();
- field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+ field_generators_.get(field).GenerateParsingCode(printer);
printer->Outdent();
printer->Print(
" break;\n"
"}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from
+ // a packed version of this field regardless of
+ // field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(
+ field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print("case $tag$: {\n", "tag",
+ SimpleItoa(static_cast<int32>(packed_tag)));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
}
- }
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " }\n" // switch (tag)
- "}\n"); // while (!done)
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ "}\n"); // while (!done)
+ }
printer->Outdent();
printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index f73bfb04..9a42aba9 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -140,13 +140,16 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
"java.lang.String[] descriptorData = {\n");
printer->Indent();
- // Only write 40 bytes per line.
+ // Limit the number of bytes per line.
static const int kBytesPerLine = 40;
+ // Limit the number of lines per string part.
+ static const int kLinesPerPart = 400;
+ // Every block of bytes, start a new string literal, in order to avoid the
+ // 64k length limit. Note that this value needs to be <64k.
+ static const int kBytesPerPart = kBytesPerLine * kLinesPerPart;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
if (i > 0) {
- // Every 400 lines, start a new string literal, in order to avoid the
- // 64k length limit.
- if (i % 400 == 0) {
+ if (i % kBytesPerPart == 0) {
printer->Print(",\n");
} else {
printer->Print(" +\n");
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 73d32762..812ca9d8 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -1082,6 +1082,40 @@ string JSReturnClause(const FieldDescriptor* desc) {
return "";
}
+string JSTypeTag(const FieldDescriptor* desc) {
+ switch (desc->type()) {
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ if (IsIntegralFieldWithStringJSType(desc)) {
+ return "StringInt";
+ } else {
+ return "Int";
+ }
+ case FieldDescriptor::TYPE_BOOL:
+ return "Boolean";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ default:
+ assert(false);
+ }
+ return "";
+}
+
string JSReturnDoc(const GeneratorOptions& options,
const FieldDescriptor* desc) {
return "";
@@ -2569,26 +2603,44 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
/* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field));
}
- printer->Print(
- "$class$.prototype.set$name$ = function(value) {\n"
- " jspb.Message.set$oneoftag$Field(this, $index$",
- "class", GetMessagePath(options, field->containing_type()),
- "name", JSGetterName(options, field),
- "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
- "index", JSFieldIndex(field));
- printer->Print(
- "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
- "};\n"
- "\n"
- "\n",
- "type",
- untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
- "typeclose", untyped ? ")" : "",
- "oneofgroup",
- (field->containing_oneof() ? (", " + JSOneofArray(options, field))
- : ""),
- "returnvalue", JSReturnClause(field), "rptvalueinit",
- (field->is_repeated() ? " || []" : ""));
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ !field->is_repeated() && !field->is_map() &&
+ !HasFieldPresence(options, field)) {
+ // Proto3 non-repeated and non-map fields without presence use the
+ // setProto3*Field function.
+ printer->Print(
+ "$class$.prototype.set$name$ = function(value) {\n"
+ " jspb.Message.setProto3$typetag$Field(this, $index$, "
+ "value);$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetMessagePath(options, field->containing_type()), "name",
+ JSGetterName(options, field), "typetag", JSTypeTag(field), "index",
+ JSFieldIndex(field), "returnvalue", JSReturnClause(field));
+ } else {
+ // Otherwise, use the regular setField function.
+ printer->Print(
+ "$class$.prototype.set$name$ = function(value) {\n"
+ " jspb.Message.set$oneoftag$Field(this, $index$",
+ "class", GetMessagePath(options, field->containing_type()), "name",
+ JSGetterName(options, field), "oneoftag",
+ (field->containing_oneof() ? "Oneof" : ""), "index",
+ JSFieldIndex(field));
+ printer->Print(
+ "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "type",
+ untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+ "typeclose", untyped ? ")" : "", "oneofgroup",
+ (field->containing_oneof() ? (", " + JSOneofArray(options, field))
+ : ""),
+ "returnvalue", JSReturnClause(field), "rptvalueinit",
+ (field->is_repeated() ? " || []" : ""));
+ }
if (untyped) {
printer->Print(
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index cc660f4a..bfcb83df 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -57,12 +57,12 @@
#include <google/protobuf/stubs/substitute.h>
#include <gtest/gtest.h>
-#ifdef major
-#undef major
-#endif
-#ifdef minor
-#undef minor
-#endif
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index bb4a44c3..03d05ad4 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -1540,7 +1540,6 @@ bool Parser::ParseReserved(DescriptorProto* message,
}
}
-
bool Parser::ParseReservedNames(DescriptorProto* message,
const LocationRecorder& parent_location) {
do {
@@ -1601,6 +1600,81 @@ bool Parser::ParseReservedNumbers(DescriptorProto* message,
return true;
}
+bool Parser::ParseReserved(EnumDescriptorProto* message,
+ const LocationRecorder& message_location) {
+ // Parse the declaration.
+ DO(Consume("reserved"));
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedNameFieldNumber);
+ return ParseReservedNames(message, location);
+ } else {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedRangeFieldNumber);
+ return ParseReservedNumbers(message, location);
+ }
+}
+
+bool Parser::ParseReservedNames(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ do {
+ LocationRecorder location(parent_location, message->reserved_name_size());
+ DO(ConsumeString(message->add_reserved_name(), "Expected enum value."));
+ } while (TryConsume(","));
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseReservedNumbers(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ bool first = true;
+ do {
+ LocationRecorder location(parent_location, message->reserved_range_size());
+
+ EnumDescriptorProto::EnumReservedRange* range =
+ message->add_reserved_range();
+ int start, end;
+ io::Tokenizer::Token start_token;
+ {
+ LocationRecorder start_location(
+ location, EnumDescriptorProto::EnumReservedRange::kStartFieldNumber);
+ start_token = input_->current();
+ DO(ConsumeSignedInteger(&start, (first ?
+ "Expected enum value or number range." :
+ "Expected enum number range.")));
+ }
+
+ if (TryConsume("to")) {
+ LocationRecorder end_location(
+ location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
+ if (TryConsume("max")) {
+ // This is in the enum descriptor path, which doesn't have the message
+ // set duality to fix up, so it doesn't integrate with the sentinel.
+
+ // Evaluate 'max' to INT_MAX - 1 so that incrementing to create the
+ // exclusive range end doesn't cause an overflow.
+ // Note, this prevents reserving the actual INT_MAX enum value.
+ end = INT_MAX;
+ } else {
+ DO(ConsumeSignedInteger(&end, "Expected integer."));
+ }
+ } else {
+ LocationRecorder end_location(
+ location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
+ end_location.StartAt(start_token);
+ end_location.EndAt(start_token);
+ end = start;
+ }
+
+ range->set_start(start);
+ range->set_end(end);
+ first = false;
+ } while (TryConsume(","));
+
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
@@ -1781,6 +1855,8 @@ bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
EnumDescriptorProto::kOptionsFieldNumber);
return ParseOption(enum_type->mutable_options(), location,
containing_file, OPTION_STATEMENT);
+ } else if (LookingAt("reserved")) {
+ return ParseReserved(enum_type, enum_location);
} else {
LocationRecorder location(enum_location,
EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
@@ -2167,4 +2243,5 @@ void SourceLocationTable::Clear() {
} // namespace compiler
} // namespace protobuf
+
} // namespace google
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index dd8b6586..33b4c700 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -371,6 +371,12 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& parent_location);
bool ParseReservedNumbers(DescriptorProto* message,
const LocationRecorder& parent_location);
+ bool ParseReserved(EnumDescriptorProto* message,
+ const LocationRecorder& message_location);
+ bool ParseReservedNames(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location);
+ bool ParseReservedNumbers(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location);
// Parse an "extend" declaration. (See also comments for
// ParseMessageField().)
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 97831f71..9b59842e 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -994,6 +994,42 @@ TEST_F(ParseEnumTest, ValueOptions) {
"}");
}
+TEST_F(ParseEnumTest, ReservedRange) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 0;\n"
+ " reserved -2147483648, -6 to -4, -1 to 1, 2, 15, 9 to 11, 3, 20 to max;\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name:\"FOO\" number:0 }"
+ " reserved_range { start:-2147483648 end:-2147483648 }"
+ " reserved_range { start:-6 end:-4 }"
+ " reserved_range { start:-1 end:1 }"
+ " reserved_range { start:2 end:2 }"
+ " reserved_range { start:15 end:15 }"
+ " reserved_range { start:9 end:11 }"
+ " reserved_range { start:3 end:3 }"
+ " reserved_range { start:20 end:2147483647 }"
+ "}");
+}
+
+TEST_F(ParseEnumTest, ReservedNames) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 0;\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name:\"FOO\" number:0 }"
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}");
+}
+
// ===================================================================
typedef ParserTest ParseServiceTest;
@@ -1488,6 +1524,51 @@ TEST_F(ParseErrorTest, EnumValueMissingNumber) {
"1:5: Missing numeric value for enum constant.\n");
}
+TEST_F(ParseErrorTest, EnumReservedStandaloneMaxNotAllowed) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO = 1;\n"
+ " reserved max;\n"
+ "}\n",
+ "2:11: Expected enum value or number range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedMixNameAndNumber) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO = 1;\n"
+ " reserved 10, \"foo\";\n"
+ "}\n",
+ "2:15: Expected enum number range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedPositiveNumberOutOfRange) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ "FOO = 1;\n"
+ " reserved 2147483648;\n"
+ "}\n",
+ "2:11: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedNegativeNumberOutOfRange) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ "FOO = 1;\n"
+ " reserved -2147483649;\n"
+ "}\n",
+ "2:12: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedMissingQuotes) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO = 1;\n"
+ " reserved foo;\n"
+ "}\n",
+ "2:11: Expected enum value or number range.\n");
+}
+
// -------------------------------------------------------------------
// Reserved field number errors
@@ -1515,6 +1596,23 @@ TEST_F(ParseErrorTest, ReservedMissingQuotes) {
"1:11: Expected field name or number range.\n");
}
+TEST_F(ParseErrorTest, ReservedNegativeNumber) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved -10;\n"
+ "}\n",
+ "1:11: Expected field name or number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedNumberOutOfRange) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 2147483648;\n"
+ "}\n",
+ "1:11: Integer out of range.\n");
+}
+
+
// -------------------------------------------------------------------
// Service errors
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index cb5e37bb..7f975510 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -41,13 +41,18 @@
#include <unistd.h>
#endif
-#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/io_win32.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
#if defined(_MSC_VER)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
@@ -55,10 +60,6 @@
using google::protobuf::internal::win32::setmode;
#endif
-namespace google {
-namespace protobuf {
-namespace compiler {
-
class GeneratorResponseContext : public GeneratorContext {
public:
GeneratorResponseContext(
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 07883a37..557e2d7a 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -1,7 +1,6 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/compiler/plugin.proto
-#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include <google/protobuf/compiler/plugin.pb.h>
#include <algorithm>
@@ -16,121 +15,168 @@
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)
-
namespace google {
namespace protobuf {
namespace compiler {
class VersionDefaultTypeInternal {
-public:
- ::google::protobuf::internal::ExplicitlyConstructed<Version>
- _instance;
+ public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Version>
+ _instance;
} _Version_default_instance_;
class CodeGeneratorRequestDefaultTypeInternal {
-public:
- ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest>
- _instance;
+ public:
+ ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest>
+ _instance;
} _CodeGeneratorRequest_default_instance_;
class CodeGeneratorResponse_FileDefaultTypeInternal {
-public:
- ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File>
- _instance;
+ public:
+ ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File>
+ _instance;
} _CodeGeneratorResponse_File_default_instance_;
class CodeGeneratorResponseDefaultTypeInternal {
-public:
- ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse>
- _instance;
+ public:
+ ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse>
+ _instance;
} _CodeGeneratorResponse_default_instance_;
-
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+void InitDefaultsVersionImpl() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+ ::google::protobuf::internal::InitProtobufDefaults();
+ {
+ void* ptr = &::google::protobuf::compiler::_Version_default_instance_;
+ new (ptr) ::google::protobuf::compiler::Version();
+ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+ }
+ ::google::protobuf::compiler::Version::InitAsDefaultInstance();
+}
-namespace {
+void InitDefaultsVersion() {
+ static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+ ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsVersionImpl);
+}
-::google::protobuf::Metadata file_level_metadata[4];
+void InitDefaultsCodeGeneratorRequestImpl() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
-} // namespace
+ ::google::protobuf::internal::InitProtobufDefaults();
+ protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaultsFileDescriptorProto();
+ protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsVersion();
+ {
+ void* ptr = &::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_;
+ new (ptr) ::google::protobuf::compiler::CodeGeneratorRequest();
+ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+ }
+ ::google::protobuf::compiler::CodeGeneratorRequest::InitAsDefaultInstance();
+}
-PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
- const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
- {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
-};
+void InitDefaultsCodeGeneratorRequest() {
+ static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+ ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsCodeGeneratorRequestImpl);
+}
-PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
- const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
- ::google::protobuf::internal::AuxillaryParseTableField(),
-};
-PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
- TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
- { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
- { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
- { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
- { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
-};
+void InitDefaultsCodeGeneratorResponse_FileImpl() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::internal::InitProtobufDefaults();
+ {
+ void* ptr = &::google::protobuf::compiler::_CodeGeneratorResponse_File_default_instance_;
+ new (ptr) ::google::protobuf::compiler::CodeGeneratorResponse_File();
+ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+ }
+ ::google::protobuf::compiler::CodeGeneratorResponse_File::InitAsDefaultInstance();
+}
-const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, _has_bits_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, _internal_metadata_),
+void InitDefaultsCodeGeneratorResponse_File() {
+ static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+ ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsCodeGeneratorResponse_FileImpl);
+}
+
+void InitDefaultsCodeGeneratorResponseImpl() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::internal::InitProtobufDefaults();
+ protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponse_File();
+ {
+ void* ptr = &::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_;
+ new (ptr) ::google::protobuf::compiler::CodeGeneratorResponse();
+ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+ }
+ ::google::protobuf::compiler::CodeGeneratorResponse::InitAsDefaultInstance();
+}
+
+void InitDefaultsCodeGeneratorResponse() {
+ static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+ ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsCodeGeneratorResponseImpl);
+}
+
+::google::protobuf::Metadata file_level_metadata[4];
+
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, _has_bits_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, _internal_metadata_),
~0u, // no _extensions_
~0u, // no _oneof_case_
~0u, // no _weak_field_map_
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, major_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, minor_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, patch_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, suffix_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, major_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, minor_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, patch_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, suffix_),
1,
2,
3,
0,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _has_bits_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _internal_metadata_),
~0u, // no _extensions_
~0u, // no _oneof_case_
~0u, // no _weak_field_map_
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, compiler_version_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, file_to_generate_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, parameter_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, proto_file_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, compiler_version_),
~0u,
0,
~0u,
1,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _has_bits_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _internal_metadata_),
~0u, // no _extensions_
~0u, // no _oneof_case_
~0u, // no _weak_field_map_
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, insertion_point_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, content_),
0,
1,
2,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _has_bits_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _internal_metadata_),
~0u, // no _extensions_
~0u, // no _oneof_case_
~0u, // no _weak_field_map_
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, error_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, file_),
0,
~0u,
};
-static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
- { 0, 9, sizeof(Version)},
- { 13, 22, sizeof(CodeGeneratorRequest)},
- { 26, 34, sizeof(CodeGeneratorResponse_File)},
- { 37, 44, sizeof(CodeGeneratorResponse)},
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+ { 0, 9, sizeof(::google::protobuf::compiler::Version)},
+ { 13, 22, sizeof(::google::protobuf::compiler::CodeGeneratorRequest)},
+ { 26, 34, sizeof(::google::protobuf::compiler::CodeGeneratorResponse_File)},
+ { 37, 44, sizeof(::google::protobuf::compiler::CodeGeneratorResponse)},
};
static ::google::protobuf::Message const * const file_default_instances[] = {
- reinterpret_cast<const ::google::protobuf::Message*>(&_Version_default_instance_),
- reinterpret_cast<const ::google::protobuf::Message*>(&_CodeGeneratorRequest_default_instance_),
- reinterpret_cast<const ::google::protobuf::Message*>(&_CodeGeneratorResponse_File_default_instance_),
- reinterpret_cast<const ::google::protobuf::Message*>(&_CodeGeneratorResponse_default_instance_),
+ reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_Version_default_instance_),
+ reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_),
+ reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorResponse_File_default_instance_),
+ reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_),
};
-namespace {
-
void protobuf_AssignDescriptors() {
AddDescriptors();
::google::protobuf::MessageFactory* factory = NULL;
@@ -144,38 +190,15 @@ void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
}
-void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4);
}
-} // namespace
-void TableStruct::InitDefaultsImpl() {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
-
- ::google::protobuf::internal::InitProtobufDefaults();
- ::google::protobuf::protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults();
- _Version_default_instance_._instance.DefaultConstruct();
- ::google::protobuf::internal::OnShutdownDestroyMessage(
- &_Version_default_instance_);_CodeGeneratorRequest_default_instance_._instance.DefaultConstruct();
- ::google::protobuf::internal::OnShutdownDestroyMessage(
- &_CodeGeneratorRequest_default_instance_);_CodeGeneratorResponse_File_default_instance_._instance.DefaultConstruct();
- ::google::protobuf::internal::OnShutdownDestroyMessage(
- &_CodeGeneratorResponse_File_default_instance_);_CodeGeneratorResponse_default_instance_._instance.DefaultConstruct();
- ::google::protobuf::internal::OnShutdownDestroyMessage(
- &_CodeGeneratorResponse_default_instance_);_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>(
- ::google::protobuf::compiler::Version::internal_default_instance());
-}
-
-void InitDefaults() {
- static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
- ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
-}
-namespace {
void AddDescriptorsImpl() {
InitDefaults();
- static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+ static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
"\n%google/protobuf/compiler/plugin.proto\022"
"\030google.protobuf.compiler\032 google/protob"
"uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030"
@@ -197,9 +220,8 @@ void AddDescriptorsImpl() {
descriptor, 638);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
- ::google::protobuf::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors();
+ ::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors();
}
-} // anonymous namespace
void AddDescriptors() {
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
@@ -211,12 +233,15 @@ struct StaticDescriptorInitializer {
AddDescriptors();
}
} static_descriptor_initializer;
-
} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto
-
+namespace google {
+namespace protobuf {
+namespace compiler {
// ===================================================================
+void Version::InitAsDefaultInstance() {
+}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Version::kMajorFieldNumber;
const int Version::kMinorFieldNumber;
@@ -227,7 +252,7 @@ const int Version::kSuffixFieldNumber;
Version::Version()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsVersion();
}
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.Version)
@@ -271,12 +296,12 @@ void Version::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Version::descriptor() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
}
const Version& Version::default_instance() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsVersion();
return *internal_default_instance();
}
@@ -599,151 +624,16 @@ void Version::InternalSwap(Version* other) {
::google::protobuf::Metadata Version::GetMetadata() const {
protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
-}
-
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// Version
-
-// optional int32 major = 1;
-bool Version::has_major() const {
- return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void Version::set_has_major() {
- _has_bits_[0] |= 0x00000002u;
-}
-void Version::clear_has_major() {
- _has_bits_[0] &= ~0x00000002u;
-}
-void Version::clear_major() {
- major_ = 0;
- clear_has_major();
-}
-::google::protobuf::int32 Version::major() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major)
- return major_;
-}
-void Version::set_major(::google::protobuf::int32 value) {
- set_has_major();
- major_ = value;
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major)
-}
-
-// optional int32 minor = 2;
-bool Version::has_minor() const {
- return (_has_bits_[0] & 0x00000004u) != 0;
-}
-void Version::set_has_minor() {
- _has_bits_[0] |= 0x00000004u;
-}
-void Version::clear_has_minor() {
- _has_bits_[0] &= ~0x00000004u;
-}
-void Version::clear_minor() {
- minor_ = 0;
- clear_has_minor();
-}
-::google::protobuf::int32 Version::minor() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor)
- return minor_;
-}
-void Version::set_minor(::google::protobuf::int32 value) {
- set_has_minor();
- minor_ = value;
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor)
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
}
-// optional int32 patch = 3;
-bool Version::has_patch() const {
- return (_has_bits_[0] & 0x00000008u) != 0;
-}
-void Version::set_has_patch() {
- _has_bits_[0] |= 0x00000008u;
-}
-void Version::clear_has_patch() {
- _has_bits_[0] &= ~0x00000008u;
-}
-void Version::clear_patch() {
- patch_ = 0;
- clear_has_patch();
-}
-::google::protobuf::int32 Version::patch() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch)
- return patch_;
-}
-void Version::set_patch(::google::protobuf::int32 value) {
- set_has_patch();
- patch_ = value;
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch)
-}
-
-// optional string suffix = 4;
-bool Version::has_suffix() const {
- return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void Version::set_has_suffix() {
- _has_bits_[0] |= 0x00000001u;
-}
-void Version::clear_has_suffix() {
- _has_bits_[0] &= ~0x00000001u;
-}
-void Version::clear_suffix() {
- suffix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- clear_has_suffix();
-}
-const ::std::string& Version::suffix() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix)
- return suffix_.GetNoArena();
-}
-void Version::set_suffix(const ::std::string& value) {
- set_has_suffix();
- suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix)
-}
-#if LANG_CXX11
-void Version::set_suffix(::std::string&& value) {
- set_has_suffix();
- suffix_.SetNoArena(
- &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
- // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix)
-}
-#endif
-void Version::set_suffix(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- set_has_suffix();
- suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix)
-}
-void Version::set_suffix(const char* value, size_t size) {
- set_has_suffix();
- suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
- ::std::string(reinterpret_cast<const char*>(value), size));
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix)
-}
-::std::string* Version::mutable_suffix() {
- set_has_suffix();
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix)
- return suffix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* Version::release_suffix() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix)
- clear_has_suffix();
- return suffix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void Version::set_allocated_suffix(::std::string* suffix) {
- if (suffix != NULL) {
- set_has_suffix();
- } else {
- clear_has_suffix();
- }
- suffix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), suffix);
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix)
-}
-
-#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
+void CodeGeneratorRequest::InitAsDefaultInstance() {
+ ::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>(
+ ::google::protobuf::compiler::Version::internal_default_instance());
+}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
const int CodeGeneratorRequest::kParameterFieldNumber;
@@ -754,7 +644,7 @@ const int CodeGeneratorRequest::kCompilerVersionFieldNumber;
CodeGeneratorRequest::CodeGeneratorRequest()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorRequest();
}
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
@@ -801,12 +691,12 @@ void CodeGeneratorRequest::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
}
const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorRequest();
return *internal_default_instance();
}
@@ -1150,224 +1040,14 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
}
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// CodeGeneratorRequest
-
-// repeated string file_to_generate = 1;
-int CodeGeneratorRequest::file_to_generate_size() const {
- return file_to_generate_.size();
-}
-void CodeGeneratorRequest::clear_file_to_generate() {
- file_to_generate_.Clear();
-}
-const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- return file_to_generate_.Get(index);
-}
-::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- return file_to_generate_.Mutable(index);
-}
-void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- file_to_generate_.Mutable(index)->assign(value);
-}
-#if LANG_CXX11
-void CodeGeneratorRequest::set_file_to_generate(int index, ::std::string&& value) {
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- file_to_generate_.Mutable(index)->assign(std::move(value));
-}
-#endif
-void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
- GOOGLE_DCHECK(value != NULL);
- file_to_generate_.Mutable(index)->assign(value);
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
-void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
- file_to_generate_.Mutable(index)->assign(
- reinterpret_cast<const char*>(value), size);
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
-::std::string* CodeGeneratorRequest::add_file_to_generate() {
- // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- return file_to_generate_.Add();
-}
-void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
- file_to_generate_.Add()->assign(value);
- // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
-#if LANG_CXX11
-void CodeGeneratorRequest::add_file_to_generate(::std::string&& value) {
- file_to_generate_.Add(std::move(value));
- // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
-#endif
-void CodeGeneratorRequest::add_file_to_generate(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- file_to_generate_.Add()->assign(value);
- // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
-void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
- file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
- // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
-const ::google::protobuf::RepeatedPtrField< ::std::string>&
-CodeGeneratorRequest::file_to_generate() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- return file_to_generate_;
-}
-::google::protobuf::RepeatedPtrField< ::std::string>*
-CodeGeneratorRequest::mutable_file_to_generate() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
- return &file_to_generate_;
-}
-
-// optional string parameter = 2;
-bool CodeGeneratorRequest::has_parameter() const {
- return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void CodeGeneratorRequest::set_has_parameter() {
- _has_bits_[0] |= 0x00000001u;
-}
-void CodeGeneratorRequest::clear_has_parameter() {
- _has_bits_[0] &= ~0x00000001u;
-}
-void CodeGeneratorRequest::clear_parameter() {
- parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- clear_has_parameter();
-}
-const ::std::string& CodeGeneratorRequest::parameter() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- return parameter_.GetNoArena();
-}
-void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
- set_has_parameter();
- parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-#if LANG_CXX11
-void CodeGeneratorRequest::set_parameter(::std::string&& value) {
- set_has_parameter();
- parameter_.SetNoArena(
- &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
- // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-#endif
-void CodeGeneratorRequest::set_parameter(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- set_has_parameter();
- parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
- set_has_parameter();
- parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
- ::std::string(reinterpret_cast<const char*>(value), size));
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-::std::string* CodeGeneratorRequest::mutable_parameter() {
- set_has_parameter();
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* CodeGeneratorRequest::release_parameter() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- clear_has_parameter();
- return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
- if (parameter != NULL) {
- set_has_parameter();
- } else {
- clear_has_parameter();
- }
- parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-
-// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-int CodeGeneratorRequest::proto_file_size() const {
- return proto_file_.size();
-}
-void CodeGeneratorRequest::clear_proto_file() {
- proto_file_.Clear();
-}
-const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_.Get(index);
-}
-::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_.Mutable(index);
-}
-::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
- // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_.Add();
-}
-::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
-CodeGeneratorRequest::mutable_proto_file() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return &proto_file_;
-}
-const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-CodeGeneratorRequest::proto_file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_;
-}
-
-// optional .google.protobuf.compiler.Version compiler_version = 3;
-bool CodeGeneratorRequest::has_compiler_version() const {
- return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void CodeGeneratorRequest::set_has_compiler_version() {
- _has_bits_[0] |= 0x00000002u;
-}
-void CodeGeneratorRequest::clear_has_compiler_version() {
- _has_bits_[0] &= ~0x00000002u;
-}
-void CodeGeneratorRequest::clear_compiler_version() {
- if (compiler_version_ != NULL) compiler_version_->::google::protobuf::compiler::Version::Clear();
- clear_has_compiler_version();
-}
-const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const {
- const ::google::protobuf::compiler::Version* p = compiler_version_;
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
- return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::compiler::Version*>(
- &::google::protobuf::compiler::_Version_default_instance_);
-}
-::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
- set_has_compiler_version();
- if (compiler_version_ == NULL) {
- compiler_version_ = new ::google::protobuf::compiler::Version;
- }
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
- return compiler_version_;
-}
-::google::protobuf::compiler::Version* CodeGeneratorRequest::release_compiler_version() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
- clear_has_compiler_version();
- ::google::protobuf::compiler::Version* temp = compiler_version_;
- compiler_version_ = NULL;
- return temp;
-}
-void CodeGeneratorRequest::set_allocated_compiler_version(::google::protobuf::compiler::Version* compiler_version) {
- delete compiler_version_;
- compiler_version_ = compiler_version;
- if (compiler_version) {
- set_has_compiler_version();
- } else {
- clear_has_compiler_version();
- }
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
-}
-
-#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
+void CodeGeneratorResponse_File::InitAsDefaultInstance() {
+}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int CodeGeneratorResponse_File::kNameFieldNumber;
const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
@@ -1377,7 +1057,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber;
CodeGeneratorResponse_File::CodeGeneratorResponse_File()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponse_File();
}
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -1427,12 +1107,12 @@ void CodeGeneratorResponse_File::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
}
const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponse_File();
return *internal_default_instance();
}
@@ -1752,205 +1432,14 @@ void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other)
::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
-}
-
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// CodeGeneratorResponse_File
-
-// optional string name = 1;
-bool CodeGeneratorResponse_File::has_name() const {
- return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void CodeGeneratorResponse_File::set_has_name() {
- _has_bits_[0] |= 0x00000001u;
-}
-void CodeGeneratorResponse_File::clear_has_name() {
- _has_bits_[0] &= ~0x00000001u;
-}
-void CodeGeneratorResponse_File::clear_name() {
- name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- clear_has_name();
-}
-const ::std::string& CodeGeneratorResponse_File::name() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- return name_.GetNoArena();
-}
-void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
- set_has_name();
- name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-#if LANG_CXX11
-void CodeGeneratorResponse_File::set_name(::std::string&& value) {
- set_has_name();
- name_.SetNoArena(
- &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
- // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-#endif
-void CodeGeneratorResponse_File::set_name(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- set_has_name();
- name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
- set_has_name();
- name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
- ::std::string(reinterpret_cast<const char*>(value), size));
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-::std::string* CodeGeneratorResponse_File::mutable_name() {
- set_has_name();
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* CodeGeneratorResponse_File::release_name() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- clear_has_name();
- return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
- if (name != NULL) {
- set_has_name();
- } else {
- clear_has_name();
- }
- name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-
-// optional string insertion_point = 2;
-bool CodeGeneratorResponse_File::has_insertion_point() const {
- return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void CodeGeneratorResponse_File::set_has_insertion_point() {
- _has_bits_[0] |= 0x00000002u;
-}
-void CodeGeneratorResponse_File::clear_has_insertion_point() {
- _has_bits_[0] &= ~0x00000002u;
-}
-void CodeGeneratorResponse_File::clear_insertion_point() {
- insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- clear_has_insertion_point();
-}
-const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
- return insertion_point_.GetNoArena();
-}
-void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
- set_has_insertion_point();
- insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-#if LANG_CXX11
-void CodeGeneratorResponse_File::set_insertion_point(::std::string&& value) {
- set_has_insertion_point();
- insertion_point_.SetNoArena(
- &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
- // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-#endif
-void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- set_has_insertion_point();
- insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
- set_has_insertion_point();
- insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
- ::std::string(reinterpret_cast<const char*>(value), size));
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
- set_has_insertion_point();
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
- return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* CodeGeneratorResponse_File::release_insertion_point() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
- clear_has_insertion_point();
- return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
- if (insertion_point != NULL) {
- set_has_insertion_point();
- } else {
- clear_has_insertion_point();
- }
- insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-
-// optional string content = 15;
-bool CodeGeneratorResponse_File::has_content() const {
- return (_has_bits_[0] & 0x00000004u) != 0;
-}
-void CodeGeneratorResponse_File::set_has_content() {
- _has_bits_[0] |= 0x00000004u;
-}
-void CodeGeneratorResponse_File::clear_has_content() {
- _has_bits_[0] &= ~0x00000004u;
-}
-void CodeGeneratorResponse_File::clear_content() {
- content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- clear_has_content();
-}
-const ::std::string& CodeGeneratorResponse_File::content() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- return content_.GetNoArena();
-}
-void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
- set_has_content();
- content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-#if LANG_CXX11
-void CodeGeneratorResponse_File::set_content(::std::string&& value) {
- set_has_content();
- content_.SetNoArena(
- &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
- // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-#endif
-void CodeGeneratorResponse_File::set_content(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- set_has_content();
- content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
- set_has_content();
- content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
- ::std::string(reinterpret_cast<const char*>(value), size));
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-::std::string* CodeGeneratorResponse_File::mutable_content() {
- set_has_content();
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* CodeGeneratorResponse_File::release_content() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- clear_has_content();
- return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
- if (content != NULL) {
- set_has_content();
- } else {
- clear_has_content();
- }
- content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
}
-#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
+void CodeGeneratorResponse::InitAsDefaultInstance() {
+}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int CodeGeneratorResponse::kErrorFieldNumber;
const int CodeGeneratorResponse::kFileFieldNumber;
@@ -1959,7 +1448,7 @@ const int CodeGeneratorResponse::kFileFieldNumber;
CodeGeneratorResponse::CodeGeneratorResponse()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponse();
}
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
@@ -1998,12 +1487,12 @@ void CodeGeneratorResponse::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
}
const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
- protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults();
+ ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponse();
return *internal_default_instance();
}
@@ -2250,109 +1739,11 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
- return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
-}
-
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// CodeGeneratorResponse
-
-// optional string error = 1;
-bool CodeGeneratorResponse::has_error() const {
- return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void CodeGeneratorResponse::set_has_error() {
- _has_bits_[0] |= 0x00000001u;
-}
-void CodeGeneratorResponse::clear_has_error() {
- _has_bits_[0] &= ~0x00000001u;
-}
-void CodeGeneratorResponse::clear_error() {
- error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- clear_has_error();
-}
-const ::std::string& CodeGeneratorResponse::error() const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
- return error_.GetNoArena();
-}
-void CodeGeneratorResponse::set_error(const ::std::string& value) {
- set_has_error();
- error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
- // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-#if LANG_CXX11
-void CodeGeneratorResponse::set_error(::std::string&& value) {
- set_has_error();
- error_.SetNoArena(
- &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
- // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-#endif
-void CodeGeneratorResponse::set_error(const char* value) {
- GOOGLE_DCHECK(value != NULL);
- set_has_error();
- error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
- // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-void CodeGeneratorResponse::set_error(const char* value, size_t size) {
- set_has_error();
- error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
- ::std::string(reinterpret_cast<const char*>(value), size));
- // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-::std::string* CodeGeneratorResponse::mutable_error() {
- set_has_error();
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
- return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* CodeGeneratorResponse::release_error() {
- // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
- clear_has_error();
- return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
- if (error != NULL) {
- set_has_error();
- } else {
- clear_has_error();
- }
- error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-
-// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-int CodeGeneratorResponse::file_size() const {
- return file_.size();
-}
-void CodeGeneratorResponse::clear_file() {
- file_.Clear();
-}
-const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
- // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_.Get(index);
-}
-::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
- // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_.Mutable(index);
-}
-::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
- // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_.Add();
-}
-::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
-CodeGeneratorResponse::mutable_file() {
- // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
- return &file_;
-}
-const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
-CodeGeneratorResponse::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_;
+ return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
}
-#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
-
} // namespace compiler
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 2d66f035..0c2ad703 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -37,6 +37,33 @@
#ifdef minor
#undef minor
#endif
+
+namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+// Internal implementation detail -- do not use these members.
+struct LIBPROTOC_EXPORT TableStruct {
+ static const ::google::protobuf::internal::ParseTableField entries[];
+ static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
+ static const ::google::protobuf::internal::ParseTable schema[4];
+ static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+ static const ::google::protobuf::internal::SerializationTable serialization_table[];
+ static const ::google::protobuf::uint32 offsets[];
+};
+void LIBPROTOC_EXPORT AddDescriptors();
+void LIBPROTOC_EXPORT InitDefaultsVersionImpl();
+void LIBPROTOC_EXPORT InitDefaultsVersion();
+void LIBPROTOC_EXPORT InitDefaultsCodeGeneratorRequestImpl();
+void LIBPROTOC_EXPORT InitDefaultsCodeGeneratorRequest();
+void LIBPROTOC_EXPORT InitDefaultsCodeGeneratorResponse_FileImpl();
+void LIBPROTOC_EXPORT InitDefaultsCodeGeneratorResponse_File();
+void LIBPROTOC_EXPORT InitDefaultsCodeGeneratorResponseImpl();
+void LIBPROTOC_EXPORT InitDefaultsCodeGeneratorResponse();
+inline void LIBPROTOC_EXPORT InitDefaults() {
+ InitDefaultsVersion();
+ InitDefaultsCodeGeneratorRequest();
+ InitDefaultsCodeGeneratorResponse_File();
+ InitDefaultsCodeGeneratorResponse();
+}
+} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto
namespace google {
namespace protobuf {
namespace compiler {
@@ -55,26 +82,10 @@ LIBPROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
} // namespace compiler
} // namespace protobuf
} // namespace google
-
namespace google {
namespace protobuf {
namespace compiler {
-namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
-// Internal implementation detail -- do not call these.
-struct LIBPROTOC_EXPORT TableStruct {
- static const ::google::protobuf::internal::ParseTableField entries[];
- static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
- static const ::google::protobuf::internal::ParseTable schema[];
- static const ::google::protobuf::uint32 offsets[];
- static const ::google::protobuf::internal::FieldMetadata field_metadata[];
- static const ::google::protobuf::internal::SerializationTable serialization_table[];
- static void InitDefaultsImpl();
-};
-void LIBPROTOC_EXPORT AddDescriptors();
-void LIBPROTOC_EXPORT InitDefaults();
-} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto
-
// ===================================================================
class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ {
@@ -113,6 +124,7 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_
static const ::google::protobuf::Descriptor* descriptor();
static const Version& default_instance();
+ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const Version* internal_default_instance() {
return reinterpret_cast<const Version*>(
&_Version_default_instance_);
@@ -219,7 +231,8 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_
::google::protobuf::int32 major_;
::google::protobuf::int32 minor_;
::google::protobuf::int32 patch_;
- friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend void ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsVersionImpl();
};
// -------------------------------------------------------------------
@@ -259,6 +272,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorRequest& default_instance();
+ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const CodeGeneratorRequest* internal_default_instance() {
return reinterpret_cast<const CodeGeneratorRequest*>(
&_CodeGeneratorRequest_default_instance_);
@@ -383,7 +397,8 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
::google::protobuf::internal::ArenaStringPtr parameter_;
::google::protobuf::compiler::Version* compiler_version_;
- friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend void ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorRequestImpl();
};
// -------------------------------------------------------------------
@@ -423,6 +438,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse_File& default_instance();
+ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const CodeGeneratorResponse_File* internal_default_instance() {
return reinterpret_cast<const CodeGeneratorResponse_File*>(
&_CodeGeneratorResponse_File_default_instance_);
@@ -535,7 +551,8 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::internal::ArenaStringPtr insertion_point_;
::google::protobuf::internal::ArenaStringPtr content_;
- friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend void ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponse_FileImpl();
};
// -------------------------------------------------------------------
@@ -575,6 +592,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse& default_instance();
+ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const CodeGeneratorResponse* internal_default_instance() {
return reinterpret_cast<const CodeGeneratorResponse*>(
&_CodeGeneratorResponse_default_instance_);
@@ -666,14 +684,14 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
::google::protobuf::internal::ArenaStringPtr error_;
- friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+ friend void ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaultsCodeGeneratorResponseImpl();
};
// ===================================================================
// ===================================================================
-#if !PROTOBUF_INLINE_NOT_IN_HEADERS
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
@@ -1320,7 +1338,6 @@ CodeGeneratorResponse::file() const {
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
-#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
// -------------------------------------------------------------------
@@ -1330,7 +1347,6 @@ CodeGeneratorResponse::file() const {
// @@protoc_insertion_point(namespace_scope)
-
} // namespace compiler
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 97769835..5ca6b4ee 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -1151,7 +1151,7 @@ void Generator::PrintFieldDescriptor(
" has_default_value=$has_default_value$, default_value=$default_value$,\n"
" message_type=None, enum_type=None, containing_type=None,\n"
" is_extension=$is_extension$, extension_scope=None,\n"
- " options=$options$$json_name$)";
+ " options=$options$$json_name$, file=DESCRIPTOR)";
printer_->Print(m, field_descriptor_decl);
}