From 92a7e778e7394386f413cec28d67a07630f784b1 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Fri, 1 Dec 2017 10:05:10 -0800 Subject: Integrated internal changes from Google --- .../protobuf/compiler/annotation_test_util.cc | 26 +- .../protobuf/compiler/annotation_test_util.h | 17 +- src/google/protobuf/compiler/code_generator.h | 2 +- src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 6 +- src/google/protobuf/compiler/cpp/cpp_field.cc | 17 +- src/google/protobuf/compiler/cpp/cpp_field.h | 4 + src/google/protobuf/compiler/cpp/cpp_file.cc | 95 ++- src/google/protobuf/compiler/cpp/cpp_generator.cc | 39 +- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 2 +- src/google/protobuf/compiler/cpp/cpp_helpers.h | 4 + src/google/protobuf/compiler/cpp/cpp_message.cc | 769 +++++++++++---------- src/google/protobuf/compiler/cpp/cpp_message.h | 3 + .../protobuf/compiler/cpp/cpp_message_field.cc | 601 ++++++---------- .../protobuf/compiler/cpp/cpp_message_field.h | 9 +- src/google/protobuf/compiler/cpp/cpp_options.h | 2 + .../protobuf/compiler/cpp/cpp_primitive_field.cc | 8 +- .../protobuf/compiler/cpp/cpp_string_field.cc | 106 +-- .../protobuf/compiler/cpp/cpp_string_field.h | 2 + src/google/protobuf/compiler/cpp/cpp_unittest.cc | 45 +- src/google/protobuf/compiler/cpp/metadata_test.cc | 4 +- src/google/protobuf/compiler/java/java_message.cc | 28 +- .../protobuf/compiler/java/java_message_lite.cc | 62 +- src/google/protobuf/compiler/js/js_generator.cc | 35 +- .../protobuf/compiler/mock_code_generator.cc | 2 +- src/google/protobuf/compiler/plugin.pb.cc | 82 +-- src/google/protobuf/compiler/plugin.pb.h | 83 ++- 26 files changed, 1010 insertions(+), 1043 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc index aa14faf6..cc8534cc 100644 --- a/src/google/protobuf/compiler/annotation_test_util.cc +++ b/src/google/protobuf/compiler/annotation_test_util.cc @@ -76,10 +76,9 @@ void AddFile(const string& filename, const string& data) { true)); } -bool CaptureMetadata(const string& filename, const string& plugin_specific_args, - const string& meta_file_suffix, CommandLineInterface* cli, - FileDescriptorProto* file, - std::vector* outputs) { +bool RunProtoCompiler(const string& filename, + const string& plugin_specific_args, + CommandLineInterface* cli, FileDescriptorProto* file) { cli->SetInputsAreProtoPathRelative(true); DescriptorCapturingGenerator capturing_generator(file); @@ -92,24 +91,7 @@ bool CaptureMetadata(const string& filename, const string& plugin_specific_args, plugin_specific_args.c_str(), capture_out.c_str(), filename.c_str()}; - if (cli->Run(5, argv) != 0) { - return false; - } - - if (outputs != NULL) { - for (std::vector::iterator i = outputs->begin(); - i != outputs->end(); ++i) { - GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/" + i->file_path, - &i->file_content, true)); - if (!DecodeMetadata( - TestTempDir() + "/" + i->file_path + meta_file_suffix, - &i->file_info)) { - return false; - } - } - } - - return true; + return cli->Run(5, argv) == 0; } bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) { diff --git a/src/google/protobuf/compiler/annotation_test_util.h b/src/google/protobuf/compiler/annotation_test_util.h index 4598a45a..90bd88b3 100644 --- a/src/google/protobuf/compiler/annotation_test_util.h +++ b/src/google/protobuf/compiler/annotation_test_util.h @@ -59,25 +59,20 @@ struct ExpectedOutput { // directory. void AddFile(const string& filename, const string& data); -// Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output -// code from the previously added file with name `filename`. +// Runs proto compiler. Captures proto file structrue in FileDescriptorProto. +// Files will be generated in TestTempDir() folder. Callers of this +// function must read generated files themselves. // // filename: source .proto file used to generate code. // plugin_specific_args: command line arguments specific to current generator. // For Java, this value might be "--java_out=annotate_code:test_temp_dir" -// meta_file_suffix: suffix of meta files that contain annotations. For Java -// it is ".pb.meta" because for file Foo.java meta file is Foo.java.pb.meta // cli: instance of command line interface to run generator. See Java's // annotation_unittest.cc for an example of how to initialize it. // file: output parameter, will be set to the descriptor of the proto file // specified in filename. -// outputs: output parameter. If not NULL, each ExpectedOutput in the vector -// should have its file_path set; CaptureMetadata will fill the rest of -// the fields appropriately. -bool CaptureMetadata(const string& filename, const string& plugin_specific_args, - const string& meta_file_suffix, CommandLineInterface* cli, - FileDescriptorProto* file, - std::vector* outputs); +bool RunProtoCompiler(const string& filename, + const string& plugin_specific_args, + CommandLineInterface* cli, FileDescriptorProto* file); bool DecodeMetadata(const string& path, GeneratedCodeInfo* info); diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index 4b1d90b8..4c2b3ee1 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -166,7 +166,7 @@ typedef GeneratorContext OutputDirectory; // "foo=bar,baz,qux=corge" // parses to the pairs: // ("foo", "bar"), ("baz", ""), ("qux", "corge") -void ParseGeneratorParameter( +LIBPROTOC_EXPORT void ParseGeneratorParameter( const string&, std::vector >*); } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 3d5b5b8d..50c7b5f3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -195,7 +195,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "inline $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" - " return static_cast< $type$ >($oneof_prefix$$name$_);\n" + " return static_cast< $type$ >($field_member$);\n" " }\n" " return static_cast< $type$ >($default$);\n" "}\n" @@ -209,14 +209,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " clear_$oneof_name$();\n" " set_has_$name$();\n" " }\n" - " $oneof_prefix$$name$_ = value;\n" + " $field_member$ = value;\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } void EnumOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); + printer->Print(variables_, "$field_member$ = $default$;\n"); } void EnumOneofFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index f8e11855..0cf25b33 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -67,12 +67,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["classname"] = ClassName(FieldScope(descriptor), false); (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - - // non_null_ptr_to_name is usable only if has_$name$ is true. It yields a - // pointer that will not be NULL. Subclasses of FieldGenerator may set - // (*variables)["non_null_ptr_to_name"] differently. - (*variables)["non_null_ptr_to_name"] = - StrCat("&this->", FieldName(descriptor), "()"); + (*variables)["field_member"] = FieldName(descriptor) + "_"; (*variables)["tag_size"] = SimpleItoa( WireFormat::TagSize(descriptor->number(), descriptor->type())); @@ -81,8 +76,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["deprecated_attr"] = descriptor->options().deprecated() ? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : ""; - (*variables)["cppget"] = "Get"; - if (HasFieldPresence(descriptor->file())) { (*variables)["set_hasbit"] = "set_has_" + FieldName(descriptor) + "();"; @@ -93,10 +86,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["clear_hasbit"] = ""; } - // By default, empty string, so that generic code used for both oneofs and - // singular fields can be written. - (*variables)["oneof_prefix"] = ""; - // These variables are placeholders to pick out the beginning and ends of // identifiers for annotations (when doing so with existing variables would // be ambiguous or impossible). They should never be set to anything but the @@ -108,10 +97,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, std::map* variables) { const string prefix = descriptor->containing_oneof()->name() + "_."; - (*variables)["oneof_prefix"] = prefix; (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); - (*variables)["non_null_ptr_to_name"] = - StrCat(prefix, (*variables)["name"], "_"); + (*variables)["field_member"] = StrCat(prefix, (*variables)["name"], "_"); } FieldGenerator::~FieldGenerator() {} diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index 891e30f6..bccfcb9a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -184,6 +184,10 @@ class FieldGenerator { // message's MergeFromCodedStream() method. virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0; + // Returns true if this field's "MergeFromCodedStream" code needs the arena + // to be defined as a variable. + virtual bool MergeFromCodedStreamNeedsArena() const { return false; } + // Generate lines to decode this field from a packed value, which will be // placed inside the message's MergeFromCodedStream() method. virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 52a16835..1f90ae43 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -397,7 +397,7 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { // Define default instances GenerateSourceDefaultInstance(idx, printer); - if (UsingImplicitWeakFields(file_, options_)) { + if (options_.lite_implicit_weak_fields) { printer->Print("void $classname$_ReferenceStrong() {}\n", "classname", message_generators_[idx]->classname_); } @@ -416,6 +416,13 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer); } + + printer->Print( + "namespace google {\nnamespace protobuf {\n"); + message_generators_[idx]->GenerateSourceInProto2Namespace(printer); + printer->Print( + "} // namespace protobuf\n} // namespace google\n"); + printer->Print( "\n" "// @@protoc_insertion_point(global_scope)\n"); @@ -467,7 +474,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // Define default instances for (int i = 0; i < message_generators_.size(); i++) { GenerateSourceDefaultInstance(i, printer); - if (UsingImplicitWeakFields(file_, options_)) { + if (options_.lite_implicit_weak_fields) { printer->Print("void $classname$_ReferenceStrong() {}\n", "classname", message_generators_[i]->classname_); } @@ -525,6 +532,15 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "\n" "// @@protoc_insertion_point(namespace_scope)\n"); } + + printer->Print( + "namespace google {\nnamespace protobuf {\n"); + for (int i = 0; i < message_generators_.size(); i++) { + message_generators_[i]->GenerateSourceInProto2Namespace(printer); + } + printer->Print( + "} // namespace protobuf\n} // namespace google\n"); + printer->Print( "\n" "// @@protoc_insertion_point(global_scope)\n"); @@ -553,7 +569,42 @@ class FileGenerator::ForwardDeclarations { std::map& classes() { return classes_; } std::map& enums() { return enums_; } - void Print(io::Printer* printer, const Options& options) const { + void PrintForwardDeclarations(io::Printer* printer, + const Options& options) const { + PrintNestedDeclarations(printer, options); + PrintTopLevelDeclarations(printer, options); + } + + + private: + void PrintNestedDeclarations(io::Printer* printer, + const Options& options) const { + PrintDeclarationsInsideNamespace(printer, options); + for (std::map::const_iterator + it = namespaces_.begin(), + end = namespaces_.end(); + it != end; ++it) { + printer->Print("namespace $nsname$ {\n", + "nsname", it->first); + it->second->PrintNestedDeclarations(printer, options); + printer->Print("} // namespace $nsname$\n", + "nsname", it->first); + } + } + + void PrintTopLevelDeclarations(io::Printer* printer, + const Options& options) const { + PrintDeclarationsOutsideNamespace(printer, options); + for (std::map::const_iterator + it = namespaces_.begin(), + end = namespaces_.end(); + it != end; ++it) { + it->second->PrintTopLevelDeclarations(printer, options); + } + } + + void PrintDeclarationsInsideNamespace(io::Printer* printer, + const Options& options) const { for (std::map::const_iterator it = enums_.begin(), end = enums_.end(); @@ -584,20 +635,36 @@ class FileGenerator::ForwardDeclarations { "classname", it->first); } } - for (std::map::const_iterator - it = namespaces_.begin(), - end = namespaces_.end(); + } + + void PrintDeclarationsOutsideNamespace(io::Printer* printer, + const Options& options) const { + if (classes_.size() == 0) return; + + printer->Print( + "namespace google {\nnamespace protobuf {\n"); + for (std::map::const_iterator + it = classes_.begin(), + end = classes_.end(); it != end; ++it) { - printer->Print("namespace $nsname$ {\n", - "nsname", it->first); - it->second->Print(printer, options); - printer->Print("} // namespace $nsname$\n", - "nsname", it->first); + const Descriptor* d = it->second; + string extra_class_qualifier; + // "class" is to disambiguate in case there is also a function with this + // name. There is code out there that does this! + printer->Print( + "template<> " + "$dllexport_decl$" + "$class$$classname$* Arena::$func$< $class$$classname$>(Arena*);\n", + "classname", QualifiedClassName(d), + "func", MessageCreateFunction(d), + "class", extra_class_qualifier, + "dllexport_decl", + options.dllexport_decl.empty() ? "" : options.dllexport_decl + " "); } + printer->Print( + "} // namespace protobuf\n} // namespace google\n"); } - - private: std::map namespaces_; std::map classes_; std::map enums_; @@ -1053,7 +1120,7 @@ void FileGenerator::GenerateInitializationCode(io::Printer* printer) { void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { ForwardDeclarations decls; FillForwardDeclarations(&decls); - decls.Print(printer, options_); + decls.PrintForwardDeclarations(printer, options_); } void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index e01e5dca..5d8ea300 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -41,12 +41,12 @@ #endif #include +#include #include #include #include #include #include -#include namespace google { namespace protobuf { @@ -85,7 +85,6 @@ 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; @@ -101,18 +100,28 @@ bool CppGenerator::Generate(const FileDescriptor* file, file_options.enforce_lite = true; } else if (options[i].first == "lite_implicit_weak_fields") { file_options.lite_implicit_weak_fields = true; + if (!options[i].second.empty()) { + file_options.num_cc_files = strto32(options[i].second.c_str(), + NULL, 10); + } } 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; } } + // The safe_boundary_check option controls behavior for Google-internal + // protobuf APIs. + if (file_options.safe_boundary_check) { + *error = + "The safe_boundary_check option is not supported outside of Google."; + return false; + } + // ----------------------------------------------------------------- @@ -159,8 +168,8 @@ bool CppGenerator::Generate(const FileDescriptor* file, } } - // Generate cc file. - if (split_source) { + // Generate cc file(s). + if (UsingImplicitWeakFields(file, file_options)) { { // This is the global .cc file, containing enum/services/tables/reflection google::protobuf::scoped_ptr output( @@ -168,12 +177,26 @@ bool CppGenerator::Generate(const FileDescriptor* file, io::Printer printer(output.get(), '$'); file_generator.GenerateGlobalSource(&printer); } - for (int i = 0; i < file_generator.NumMessages(); i++) { + + int num_cc_files = file_generator.NumMessages(); + + // If we're using implicit weak fields then we allow the user to optionally + // specify how many files to generate, not counting the global pb.cc file. + // If we have more files than messages, then some files will be generated as + // empty placeholders. + if (file_options.num_cc_files > 0) { + GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files) + << "There must be at least as many numbered .cc files as messages."; + num_cc_files = file_options.num_cc_files; + } + for (int i = 0; i < num_cc_files; i++) { // TODO(gerbens) Agree on naming scheme. google::protobuf::scoped_ptr output( generator_context->Open(basename + "." + SimpleItoa(i) + ".cc")); io::Printer printer(output.get(), '$'); - file_generator.GenerateSourceForMessage(i, &printer); + if (i < file_generator.NumMessages()) { + file_generator.GenerateSourceForMessage(i, &printer); + } } } else { google::protobuf::scoped_ptr output( diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 96950e52..172acedd 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -752,7 +752,7 @@ bool UsingImplicitWeakFields(const FileDescriptor* file, 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->is_required() && !field->is_map() && field->containing_oneof() == NULL; } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index e0f809c9..4026d0ed 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -310,6 +310,10 @@ inline bool IsCrossFileMessage(const FieldDescriptor* field) { field->message_type()->file() != field->file(); } +inline string MessageCreateFunction(const Descriptor* d) { + return SupportsArenas(d) ? "CreateMessage" : "Create"; +} + bool IsAnyMessage(const FileDescriptor* descriptor); bool IsAnyMessage(const Descriptor* descriptor); diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 60467598..8636f089 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -325,6 +325,109 @@ bool IsCrossFileMaybeMap(const FieldDescriptor* field) { return IsCrossFileMessage(field); } +bool IsRequired(const std::vector& v) { + return v.front()->is_required(); +} + +// Allows chunking repeated fields together and non-repeated fields if the +// fields share the same has_byte index. +// TODO(seongkim): use lambda with capture instead of functor. +class MatchRepeatedAndHasByte { + public: + MatchRepeatedAndHasByte(const std::vector* has_bit_indices, + bool has_field_presence) + : has_bit_indices_(*has_bit_indices), + has_field_presence_(has_field_presence) {} + + // Returns true if the following conditions are met: + // --both fields are repeated fields + // --both fields are non-repeated fields with either has_field_presence is + // false or have the same has_byte index. + bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const { + return a->is_repeated() == b->is_repeated() && + (!has_field_presence_ || a->is_repeated() || + has_bit_indices_[a->index()] / 8 == + has_bit_indices_[b->index()] / 8); + } + + private: + const std::vector& has_bit_indices_; + const bool has_field_presence_; +}; + +// Allows chunking required fields separately after chunking with +// MatchRepeatedAndHasByte. +class MatchRepeatedAndHasByteAndRequired : public MatchRepeatedAndHasByte { + public: + MatchRepeatedAndHasByteAndRequired(const std::vector* has_bit_indices, + bool has_field_presence) + : MatchRepeatedAndHasByte(has_bit_indices, has_field_presence) {} + + bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const { + return MatchRepeatedAndHasByte::operator()(a, b) && + a->is_required() == b->is_required(); + } +}; + +// Allows chunking zero-initializable fields separately after chunking with +// MatchRepeatedAndHasByte. +class MatchRepeatedAndHasByteAndZeroInits : public MatchRepeatedAndHasByte { + public: + MatchRepeatedAndHasByteAndZeroInits(const std::vector* has_bit_indices, + bool has_field_presence) + : MatchRepeatedAndHasByte(has_bit_indices, has_field_presence) {} + + bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const { + return MatchRepeatedAndHasByte::operator()(a, b) && + CanInitializeByZeroing(a) == CanInitializeByZeroing(b); + } +}; + +// Collects neighboring fields based on a given criteria (equivalent predicate). +template +std::vector > CollectFields( + const std::vector& fields, + const Predicate& equivalent) { + std::vector > chunks; + if (fields.empty()) { + return chunks; + } + + const FieldDescriptor* last_field = fields.front(); + std::vector chunk; + for (int i = 0; i < fields.size(); i++) { + if (!equivalent(last_field, fields[i]) && !chunk.empty()) { + chunks.push_back(chunk); + chunk.clear(); + } + chunk.push_back(fields[i]); + last_field = fields[i]; + } + if (!chunk.empty()) { + chunks.push_back(chunk); + } + return chunks; +} + +// Returns a bit mask based on has_bit index of "fields" that are typically on +// the same chunk. It is used in a group presence check where _has_bits_ is +// masked to tell if any thing in "fields" is present. +uint32 GenChunkMask(const std::vector& fields, + const std::vector& has_bit_indices) { + GOOGLE_CHECK(!fields.empty()); + int first_index_offset = has_bit_indices[fields.front()->index()] / 32; + uint32 chunk_mask = 0; + for (int i = 0; i < fields.size(); i++) { + const FieldDescriptor* field = fields[i]; + // "index" defines where in the _has_bits_ the field appears. + int index = has_bit_indices[field->index()]; + GOOGLE_CHECK_EQ(first_index_offset, index / 32); + chunk_mask |= static_cast(1) << (index % 32); + } + GOOGLE_CHECK_NE(0, chunk_mask); + return chunk_mask; +} + } // anonymous namespace // =================================================================== @@ -993,6 +1096,7 @@ GenerateClassDefinition(io::Printer* printer) { vars["new_final"] = " PROTOBUF_FINAL"; + vars["create_func"] = MessageCreateFunction(descriptor_); printer->Print(vars, "void Swap($classname$* other);\n" "friend void swap($classname$& a, $classname$& b) {\n" @@ -1001,9 +1105,13 @@ GenerateClassDefinition(io::Printer* printer) { "\n" "// implements Message ----------------------------------------------\n" "\n" - "inline $classname$* New() const$new_final$ { return New(NULL); }\n" + "inline $classname$* New() const$new_final$ {\n" + " return ::google::protobuf::Arena::$create_func$<$classname$>(NULL);\n" + "}\n" "\n" - "$classname$* New(::google::protobuf::Arena* arena) const$new_final$;\n"); + "$classname$* New(::google::protobuf::Arena* arena) const$new_final$ {\n" + " return ::google::protobuf::Arena::$create_func$<$classname$>(arena);\n" + "}\n"); // For instances that derive from Message (rather than MessageLite), some // methods are virtual and should be marked as final. @@ -2452,112 +2560,125 @@ GenerateStructors(io::Printer* printer) { } // Generate the copy constructor. - printer->Print( - "$classname$::$classname$(const $classname$& from)\n" - " : $superclass$()", - "classname", classname_, - "superclass", superclass, - "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Indent(); - printer->Indent(); + if (UsingImplicitWeakFields(descriptor_->file(), options_)) { + // If we are in lite mode and using implicit weak fields, we generate a + // one-liner copy constructor that delegates to MergeFrom. This saves some + // code size and also cuts down on the complexity of implicit weak fields. + // We might eventually want to do this for all lite protos. + printer->Print( + "$classname$::$classname$(const $classname$& from)\n" + " : $classname$() {\n" + " MergeFrom(from);\n" + "}\n", + "classname", classname_); + } else { + printer->Print( + "$classname$::$classname$(const $classname$& from)\n" + " : $superclass$()", + "classname", classname_, + "superclass", superclass, + "full_name", descriptor_->full_name()); + printer->Indent(); + printer->Indent(); + printer->Indent(); - printer->Print( - ",\n_internal_metadata_(NULL)"); + printer->Print( + ",\n_internal_metadata_(NULL)"); - if (HasFieldPresence(descriptor_->file())) { - printer->Print(",\n_has_bits_(from._has_bits_)"); - } + if (HasFieldPresence(descriptor_->file())) { + printer->Print(",\n_has_bits_(from._has_bits_)"); + } - bool need_to_emit_cached_size = true; - const string cached_size_decl = ",\n_cached_size_(0)"; - // We reproduce the logic used for laying out _cached_sized_ in the class - // definition, as to initialize it in-order. - if (HasFieldPresence(descriptor_->file()) && - (HasBitsSize() % 8) != 0) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } + bool need_to_emit_cached_size = true; + const string cached_size_decl = ",\n_cached_size_(0)"; + // We reproduce the logic used for laying out _cached_sized_ in the class + // definition, as to initialize it in-order. + if (HasFieldPresence(descriptor_->file()) && + (HasBitsSize() % 8) != 0) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } - std::vector processed(optimized_order_.size(), false); - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; + std::vector processed(optimized_order_.size(), false); + for (int i = 0; i < optimized_order_.size(); ++i) { + const FieldDescriptor* field = optimized_order_[i]; - if (!(field->is_repeated() && !(field->is_map())) - ) { - continue; - } + if (!(field->is_repeated() && !(field->is_map())) + ) { + continue; + } - processed[i] = true; - printer->Print(",\n$name$_(from.$name$_)", - "name", FieldName(field)); - } + processed[i] = true; + printer->Print(",\n$name$_(from.$name$_)", + "name", FieldName(field)); + } - if (need_to_emit_cached_size) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } + if (need_to_emit_cached_size) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } - if (IsAnyMessage(descriptor_)) { - printer->Print(",\n_any_metadata_(&type_url_, &value_)"); - } - if (num_weak_fields_ > 0) { - printer->Print(",\n_weak_field_map_(from._weak_field_map_)"); - } + if (IsAnyMessage(descriptor_)) { + printer->Print(",\n_any_metadata_(&type_url_, &value_)"); + } + if (num_weak_fields_ > 0) { + printer->Print(",\n_weak_field_map_(from._weak_field_map_)"); + } - printer->Outdent(); - printer->Outdent(); - printer->Print(" {\n"); + printer->Outdent(); + printer->Outdent(); + printer->Print(" {\n"); - printer->Print( - "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); + printer->Print( + "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); - if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); - } + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); + } - GenerateConstructorBody(printer, processed, true); + GenerateConstructorBody(printer, processed, true); - // Copy oneof fields. Oneof field requires oneof case check. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "clear_has_$oneofname$();\n" - "switch (from.$oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + // Copy oneof fields. Oneof field requires oneof case check. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); + "clear_has_$oneofname$();\n" + "switch (from.$oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } printer->Print( - "break;\n"); + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "oneof_index", + SimpleItoa(descriptor_->oneof_decl(i)->index()), + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); printer->Outdent(); printer->Print( "}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "oneof_index", - SimpleItoa(descriptor_->oneof_decl(i)->index()), - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); printer->Print( - "}\n"); + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" + "}\n" + "\n", + "full_name", descriptor_->full_name()); } - printer->Outdent(); - printer->Print( - " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" - "}\n" - "\n", - "full_name", descriptor_->full_name()); - // Generate the shared constructor code. GenerateSharedConstructorCode(printer); @@ -2610,24 +2731,17 @@ GenerateStructors(io::Printer* printer) { "}\n\n", "classname", classname_, "scc_name", scc_name_, "file_namespace", FileLevelNamespace(descriptor_)); +} - if (SupportsArenas(descriptor_)) { - printer->Print( - "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n" - " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" - "}\n", - "classname", classname_); - } else { - printer->Print( - "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n" - " $classname$* n = new $classname$;\n" - " if (arena != NULL) {\n" - " arena->Own(n);\n" - " }\n" - " return n;\n" +void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) { + printer->Print( + "template<> " + "GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE " + "$classname$* Arena::$create_func$< $classname$ >(Arena* arena) {\n" + " return Arena::$create_func$Internal< $classname$ >(arena);\n" "}\n", - "classname", classname_); - } + "classname", QualifiedClassName(descriptor_), + "create_func", MessageCreateFunction(descriptor_)); } // Return the number of bits set in n, a non-negative integer. @@ -2681,7 +2795,6 @@ GenerateClear(io::Printer* printer) { printer->Print("_extensions_.Clear();\n"); } - int last_i = -1; int unconditional_budget = kMaxUnconditionalPrimitiveBytesClear; for (int i = 0; i < optimized_order_.size(); i++) { const FieldDescriptor* field = optimized_order_[i]; @@ -2693,197 +2806,162 @@ GenerateClear(io::Printer* printer) { unconditional_budget -= EstimateAlignmentSize(field); } - for (int i = 0; i < optimized_order_.size(); ) { - // Detect infinite loops. - GOOGLE_CHECK_NE(i, last_i); - last_i = i; + std::vector > chunks_frag = CollectFields( + optimized_order_, + MatchRepeatedAndHasByteAndZeroInits( + &has_bit_indices_, HasFieldPresence(descriptor_->file()))); + + // Merge next non-zero initializable chunk if it has the same has_byte index + // and not meeting unconditional clear condition. + std::vector > chunks; + if (!HasFieldPresence(descriptor_->file())) { + // Don't bother with merging without has_bit field. + chunks = chunks_frag; + } else { + // Note that only the next chunk is considered for merging. + for (int i = 0; i < chunks_frag.size(); i++) { + chunks.push_back(chunks_frag[i]); + const FieldDescriptor* field = chunks_frag[i].front(); + const FieldDescriptor* next_field = + (i + 1) < chunks_frag.size() ? chunks_frag[i + 1].front() : NULL; + if (CanInitializeByZeroing(field) && + (chunks_frag[i].size() == 1 || unconditional_budget < 0) && + next_field != NULL && + has_bit_indices_[field->index()] / 8 == + has_bit_indices_[next_field->index()] / 8) { + GOOGLE_CHECK(!CanInitializeByZeroing(next_field)); + // Insert next chunk to the current one and skip next chunk. + chunks.back().insert(chunks.back().end(), chunks_frag[i + 1].begin(), + chunks_frag[i + 1].end()); + i++; + } + } + } + + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + std::vector& chunk = chunks[chunk_index]; + GOOGLE_CHECK(!chunk.empty()); // Step 2: Repeated fields don't use _has_bits_; emit code to clear them // here. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - const FieldGenerator& generator = field_generators_.get(field); + if (chunk.front()->is_repeated()) { + for (int i = 0; i < chunk.size(); i++) { + const FieldDescriptor* field = chunk[i]; + const FieldGenerator& generator = field_generators_.get(field); - if (!field->is_repeated()) { - break; + generator.GenerateMessageClearingCode(printer); } - - generator.GenerateMessageClearingCode(printer); + continue; } - // Step 3: Greedily seek runs of fields that can be cleared by - // memset-to-0. - int last_chunk = -1; - int last_chunk_start = -1; - int last_chunk_end = -1; - uint32 last_chunk_mask = 0; - + // Step 3: Non-repeated fields that can be cleared by memset-to-0, then + // non-repeated, non-zero initializable fields. + int last_chunk = HasFieldPresence(descriptor_->file()) + ? has_bit_indices_[chunk.front()->index()] / 8 + : 0; + int last_chunk_start = 0; int memset_run_start = -1; int memset_run_end = -1; - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - - if (!CanInitializeByZeroing(field)) { - break; - } - - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; - - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; - } - if (memset_run_start == -1) { - memset_run_start = i; + for (int i = 0; i < chunk.size(); i++) { + const FieldDescriptor* field = chunk[i]; + if (CanInitializeByZeroing(field)) { + if (memset_run_start == -1) { + memset_run_start = i; + } + memset_run_end = i; } - - memset_run_end = i; - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); } - if (memset_run_start != memset_run_end && unconditional_budget >= 0) { - // Flush the memset fields. - goto flush; - } + const bool have_outer_if = + HasFieldPresence(descriptor_->file()) && chunk.size() > 1 && + (memset_run_end != chunk.size() - 1 || unconditional_budget < 0); - // Step 4: Non-repeated, non-zero initializable fields. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field->is_repeated() || CanInitializeByZeroing(field)) { - break; - } + if (have_outer_if) { + uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_); + const int count = popcnt(last_chunk_mask); - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; + // Check (up to) 8 has_bits at a time if we have more than one field in + // this chunk. Due to field layout ordering, we may check + // _has_bits_[last_chunk * 8 / 32] multiple times. + GOOGLE_DCHECK_LE(2, count); + GOOGLE_DCHECK_GE(8, count); - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; + if (cached_has_bit_index != last_chunk / 4) { + cached_has_bit_index = last_chunk / 4; + printer->Print("cached_has_bits = _has_bits_[$idx$];\n", "idx", + SimpleItoa(cached_has_bit_index)); } - - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); + printer->Print("if (cached_has_bits & $mask$u) {\n", "mask", + SimpleItoa(last_chunk_mask)); + printer->Indent(); } -flush: - - if (last_chunk != -1) { - GOOGLE_DCHECK_NE(-1, last_chunk_start); - GOOGLE_DCHECK_NE(-1, last_chunk_end); - GOOGLE_DCHECK_NE(0, last_chunk_mask); - - const int count = popcnt(last_chunk_mask); - const bool have_outer_if = HasFieldPresence(descriptor_->file()) && - (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 - // this chunk. Due to field layout ordering, we may check - // _has_bits_[last_chunk * 8 / 32] multiple times. - GOOGLE_DCHECK_LE(2, count); - GOOGLE_DCHECK_GE(8, count); + if (memset_run_start != -1) { + if (memset_run_start == memset_run_end) { + // For clarity, do not memset a single field. + const FieldGenerator& generator = + field_generators_.get(chunk[memset_run_start]); + generator.GenerateMessageClearingCode(printer); + } else { + const string first_field_name = FieldName(chunk[memset_run_start]); + const string last_field_name = FieldName(chunk[memset_run_end]); - if (cached_has_bit_index != last_chunk / 4) { - cached_has_bit_index = last_chunk / 4; - printer->Print( - "cached_has_bits = _has_bits_[$idx$];\n", - "idx", SimpleItoa(cached_has_bit_index)); - } printer->Print( - "if (cached_has_bits & $mask$u) {\n", - "mask", SimpleItoa(last_chunk_mask)); - printer->Indent(); - } - - if (memset_run_start != -1) { - if (memset_run_start == memset_run_end) { - // For clarity, do not memset a single field. - const FieldGenerator& generator = - field_generators_.get(optimized_order_[memset_run_start]); - generator.GenerateMessageClearingCode(printer); - } else { - const string first_field_name = - FieldName(optimized_order_[memset_run_start]); - const string last_field_name = - FieldName(optimized_order_[memset_run_end]); - - printer->Print( "::memset(&$first$_, 0, static_cast(\n" " reinterpret_cast(&$last$_) -\n" " reinterpret_cast(&$first$_)) + sizeof($last$_));\n", - "first", first_field_name, - "last", last_field_name); - } - - // Advance last_chunk_start to skip over the fields we zeroed/memset. - last_chunk_start = memset_run_end + 1; + "first", first_field_name, "last", last_field_name); } - // Go back and emit clears for each of the fields we processed. - for (int j = last_chunk_start; j <= last_chunk_end; j++) { - const FieldDescriptor* field = optimized_order_[j]; - const string fieldname = FieldName(field); - const FieldGenerator& generator = field_generators_.get(field); + // Advance last_chunk_start to skip over the fields we zeroed/memset. + last_chunk_start = memset_run_end + 1; + } + + // Go back and emit clears for each of the fields we processed. + for (int j = last_chunk_start; j < chunk.size(); j++) { + const FieldDescriptor* field = chunk[j]; + const string fieldname = FieldName(field); + const FieldGenerator& generator = field_generators_.get(field); - // It's faster to just overwrite primitive types, but we should only - // clear strings and messages if they were set. - // - // TODO(kenton): Let the CppFieldGenerator decide this somehow. - bool should_check_bit = + // It's faster to just overwrite primitive types, but we should only + // clear strings and messages if they were set. + // + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool should_check_bit = field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; - bool have_enclosing_if = false; - if (should_check_bit && - // If no field presence, then always clear strings/messages as well. - HasFieldPresence(descriptor_->file())) { - if (!field->options().weak() && - cached_has_bit_index != (has_bit_indices_[field->index()] / 32)) { - cached_has_bit_index = (has_bit_indices_[field->index()] / 32); - printer->Print("cached_has_bits = _has_bits_[$new_index$];\n", - "new_index", SimpleItoa(cached_has_bit_index)); - } - if (!MaybeGenerateOptionalFieldCondition(printer, field, - cached_has_bit_index)) { - printer->Print( - "if (has_$name$()) {\n", - "name", fieldname); - } - printer->Indent(); - have_enclosing_if = true; + bool have_enclosing_if = false; + if (should_check_bit && + // If no field presence, then always clear strings/messages as well. + HasFieldPresence(descriptor_->file())) { + if (!field->options().weak() && + cached_has_bit_index != (has_bit_indices_[field->index()] / 32)) { + cached_has_bit_index = (has_bit_indices_[field->index()] / 32); + printer->Print("cached_has_bits = _has_bits_[$new_index$];\n", + "new_index", SimpleItoa(cached_has_bit_index)); } - - generator.GenerateMessageClearingCode(printer); - - if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); + if (!MaybeGenerateOptionalFieldCondition(printer, field, + cached_has_bit_index)) { + printer->Print("if (has_$name$()) {\n", "name", fieldname); } + printer->Indent(); + have_enclosing_if = true; } - if (have_outer_if) { + generator.GenerateMessageClearingCode(printer); + + if (have_enclosing_if) { printer->Outdent(); printer->Print("}\n"); } } + + if (have_outer_if) { + printer->Outdent(); + printer->Print("}\n"); + } } // Step 4: Unions. @@ -3349,7 +3427,6 @@ GenerateMergeFromCodedStream(io::Printer* printer) { "}\n"); return; } - std::vector ordered_fields = SortFieldsByNumber(descriptor_); @@ -3379,9 +3456,22 @@ GenerateMergeFromCodedStream(io::Printer* printer) { return; } + if (SupportsArenas(descriptor_)) { + for (int i = 0; i < ordered_fields.size(); i++) { + const FieldDescriptor* field = ordered_fields[i]; + const FieldGenerator& field_generator = field_generators_.get(field); + if (field_generator.MergeFromCodedStreamNeedsArena()) { + printer->Print( + " ::google::protobuf::Arena* arena = GetArenaNoVirtual();\n"); + break; + } + } + } + printer->Print( - "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n" - " ::google::protobuf::uint32 tag;\n"); + "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto " + "failure\n" + " ::google::protobuf::uint32 tag;\n"); if (!UseUnknownFieldSet(descriptor_->file(), options_)) { printer->Print( @@ -4141,28 +4231,30 @@ GenerateByteSize(io::Printer* printer) { } } - int last_i = -1; - for (int i = 0; i < optimized_order_.size(); ) { - // Detect infinite loops. - GOOGLE_CHECK_NE(i, last_i); - last_i = i; + std::vector > chunks = CollectFields( + optimized_order_, + MatchRepeatedAndHasByteAndRequired( + &has_bit_indices_, HasFieldPresence(descriptor_->file()))); - // Skip required fields. - for (; i < optimized_order_.size() && - optimized_order_[i]->is_required(); i++) { - } + // Remove chunks with required fields. + chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired), + chunks.end()); + + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + const std::vector& chunk = chunks[chunk_index]; + GOOGLE_CHECK(!chunk.empty()); // Handle repeated fields. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (!field->is_repeated()) { - break; - } + if (chunk.front()->is_repeated()) { + for (int i = 0; i < chunk.size(); i++) { + const FieldDescriptor* field = chunk[i]; - PrintFieldComment(printer, field); - const FieldGenerator& generator = field_generators_.get(field); - generator.GenerateByteSize(printer); - printer->Print("\n"); + PrintFieldComment(printer, field); + const FieldGenerator& generator = field_generators_.get(field); + generator.GenerateByteSize(printer); + printer->Print("\n"); + } + continue; } // Handle optional (non-repeated/oneof) fields. @@ -4174,92 +4266,62 @@ GenerateByteSize(io::Printer* printer) { // descriptor_->field(8), descriptor_->field(9), ... // descriptor_->field(15), // etc. - int last_chunk = -1; - int last_chunk_start = -1; - int last_chunk_end = -1; - uint32 last_chunk_mask = 0; - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field->is_repeated() || field->is_required()) { - break; - } + int last_chunk = HasFieldPresence(descriptor_->file()) + ? has_bit_indices_[chunk.front()->index()] / 8 + : 0; + GOOGLE_DCHECK_NE(-1, last_chunk); - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; + const bool have_outer_if = + HasFieldPresence(descriptor_->file()) && chunk.size() > 1; - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; - } + if (have_outer_if) { + uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_); + const int count = popcnt(last_chunk_mask); - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); - } + // Check (up to) 8 has_bits at a time if we have more than one field in + // this chunk. Due to field layout ordering, we may check + // _has_bits_[last_chunk * 8 / 32] multiple times. + GOOGLE_DCHECK_LE(2, count); + GOOGLE_DCHECK_GE(8, count); - if (last_chunk != -1) { - GOOGLE_DCHECK_NE(-1, last_chunk_start); - GOOGLE_DCHECK_NE(-1, last_chunk_end); - GOOGLE_DCHECK_NE(0, last_chunk_mask); + printer->Print("if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index", + SimpleItoa(last_chunk * 8), "mask", + SimpleItoa(last_chunk_mask)); + printer->Indent(); + } - const int count = popcnt(last_chunk_mask); - const bool have_outer_if = HasFieldPresence(descriptor_->file()) && - (last_chunk_start != last_chunk_end); + // Go back and emit checks for each of the fields we processed. + for (int j = 0; j < chunk.size(); j++) { + const FieldDescriptor* field = chunk[j]; + const FieldGenerator& generator = field_generators_.get(field); - if (have_outer_if) { - // Check (up to) 8 has_bits at a time if we have more than one field in - // this chunk. Due to field layout ordering, we may check - // _has_bits_[last_chunk * 8 / 32] multiple times. - GOOGLE_DCHECK_LE(2, count); - GOOGLE_DCHECK_GE(8, count); + PrintFieldComment(printer, field); - printer->Print( - "if (_has_bits_[$index$ / 32] & $mask$u) {\n", - "index", SimpleItoa(last_chunk * 8), - "mask", SimpleItoa(last_chunk_mask)); + bool have_enclosing_if = false; + if (HasFieldPresence(descriptor_->file())) { + printer->Print("if (has_$name$()) {\n", "name", FieldName(field)); printer->Indent(); + have_enclosing_if = true; + } else { + // Without field presence: field is serialized only if it has a + // non-default value. + have_enclosing_if = + EmitFieldNonDefaultCondition(printer, "this->", field); } - // Go back and emit checks for each of the fields we processed. - for (int j = last_chunk_start; j <= last_chunk_end; j++) { - const FieldDescriptor* field = optimized_order_[j]; - const FieldGenerator& generator = field_generators_.get(field); - - PrintFieldComment(printer, field); - - bool have_enclosing_if = false; - if (HasFieldPresence(descriptor_->file())) { - printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); - have_enclosing_if = true; - } else { - // Without field presence: field is serialized only if it has a - // non-default value. - have_enclosing_if = EmitFieldNonDefaultCondition( - printer, "this->", field); - } - - generator.GenerateByteSize(printer); + generator.GenerateByteSize(printer); - if (have_enclosing_if) { - printer->Outdent(); - printer->Print( + if (have_enclosing_if) { + printer->Outdent(); + printer->Print( "}\n" "\n"); - } } + } - if (have_outer_if) { - printer->Outdent(); - printer->Print("}\n"); - } + if (have_outer_if) { + printer->Outdent(); + printer->Print("}\n"); } } @@ -4359,10 +4421,17 @@ GenerateIsInitialized(io::Printer* printer) { !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { if (field->is_repeated()) { - printer->Print( - "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" - " return false;\n", - "name", FieldName(field)); + if (IsImplicitWeakField(field, options_)) { + printer->Print( + "if (!::google::protobuf::internal::AllAreInitializedWeak(this->$name$_))" + " return false;\n", + "name", FieldName(field)); + } else { + printer->Print( + "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" + " return false;\n", + "name", FieldName(field)); + } } else if (field->options().weak()) { continue; } else { diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 0387f0ca..06e2030b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -106,6 +106,9 @@ class MessageGenerator { // Generate all non-inline methods for this class. void GenerateClassMethods(io::Printer* printer); + // Generate source file code that should go outside any namespace. + void GenerateSourceInProto2Namespace(io::Printer* printer); + private: // Generate declarations and definitions of accessors for fields. void GenerateDependentBaseClassDefinition(io::Printer* printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index fe60a283..530a6392 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -80,11 +80,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*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"], "_"); - } + IsImplicitWeakField(descriptor, options) + ? (" " + ReferenceFunctionName(descriptor->message_type()) + "();\n") + : ""; (*variables)["stream_writer"] = (*variables)["declared_type"] + (HasFastArraySerialization(descriptor->message_type()->file(), options) @@ -96,14 +94,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, SafeFunctionName(descriptor->containing_type(), descriptor, "release_"); (*variables)["full_name"] = descriptor->full_name(); - if (options.proto_h && IsFieldDependent(descriptor)) { - (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor); - (*variables)["dependent_typename"] = - "typename T::" + DependentTypeName(descriptor); - } else { - (*variables)["dependent_type"] = FieldMessageTypeName(descriptor); - (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor); - } + (*variables)["create_func"] = + MessageCreateFunction(descriptor->message_type()); } } // namespace @@ -114,7 +106,6 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options) : FieldGenerator(options), descriptor_(descriptor), - dependent_field_(options.proto_h && IsFieldDependent(descriptor)), implicit_weak_field_(IsImplicitWeakField(descriptor, options)) { SetMessageVariables(descriptor, &variables_, options); } @@ -130,24 +121,8 @@ GeneratePrivateMembers(io::Printer* printer) const { } } -void MessageFieldGenerator:: -GenerateDependentAccessorDeclarations(io::Printer* printer) const { - if (!dependent_field_) { - return; - } - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); -} - void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - if (SupportsArenas(descriptor_) && !implicit_weak_field_) { - printer->Print(variables_, - "private:\n" - "void _slow_mutable_$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 @@ -163,11 +138,9 @@ GenerateAccessorDeclarations(io::Printer* printer) const { printer->Annotate("name", descriptor_); printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n"); printer->Annotate("release_name", descriptor_); - if (!dependent_field_) { - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - } + printer->Print(variables_, + "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); printer->Print(variables_, "$deprecated_attr$void ${$set_allocated_$name$$}$" "($type$* $name$);\n"); @@ -216,22 +189,9 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( " &$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" - " GetArenaNoVirtual());\n"); - } else { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } + " return $name$_;\n" + "}\n"); } - printer->Print(variables_, - "}\n"); printer->Print(variables_, "void $classname$::unsafe_arena_set_allocated_$name$(\n" @@ -267,119 +227,39 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( } } -void MessageFieldGenerator:: -GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { - if (!dependent_field_) { - return; - } - - std::map variables(variables_); - // For the CRTP base class, all mutation methods are dependent, and so - // they must be in the header. - variables["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; - 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"]; - } - if (!variables["clear_hasbit"].empty()) { - variables["clear_hasbit"] = - variables["this_message"] + variables["clear_hasbit"]; - } - - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "template \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$_ = $casted_reference$;\n" - " if ($name$_ == NULL) {\n"); - if (implicit_weak_field_) { - printer->Print(variables, - " $name$_ = reinterpret_cast<$dependent_typename$*>(\n" - " reinterpret_cast(\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"); - } else { - printer->Print(variables, - "template \n" - "inline $type$* $dependent_classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " $dependent_typename$*& $name$_ = $casted_reference$;\n" - " if ($name$_ == NULL) {\n" - " $name$_ = new $dependent_typename$;\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_;\n" - "}\n"); - } -} - void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - std::map variables(variables_); - variables["const_member"] = ReinterpretCast( - "const " + variables["type"] + "*", variables["name"] + "_", - implicit_weak_field_); - printer->Print(variables, - "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" + printer->Print(variables_, + "inline const $type$& $classname$::$name$() const {\n" + "$type_reference_function$" + " const $type$* p = $casted_member$;\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return p != NULL ? *p : *reinterpret_cast(\n" " &$type_default_instance$);\n" "}\n"); - printer->Print(variables, + printer->Print(variables_, "inline $type$* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n"); - if (implicit_weak_field_) { - printer->Print(variables, " $type_reference_function$();\n"); - } - printer->Print(variables, + " // @@protoc_insertion_point(field_release:$full_name$)\n" + "$type_reference_function$" " $clear_hasbit$\n" " $type$* temp = $casted_member$;\n"); if (SupportsArenas(descriptor_)) { - printer->Print(variables, + printer->Print(variables_, " if (GetArenaNoVirtual() != NULL) {\n" " temp = ::google::protobuf::internal::DuplicateIfNonNull(temp, NULL);\n" " }\n"); } - printer->Print(variables, + printer->Print(variables_, " $name$_ = NULL;\n" " return temp;\n" "}\n"); if (SupportsArenas(descriptor_)) { - printer->Print(variables, + printer->Print(variables_, "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, + " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" + "$type_reference_function$" " $clear_hasbit$\n" " $type$* temp = $casted_member$;\n" " $name$_ = NULL;\n" @@ -387,71 +267,58 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n"); } - if (!dependent_field_) { - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "inline $type$* $classname$::mutable_$name$() {\n" - " $set_hasbit$\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 $casted_member$;\n" - "}\n"); - } else { - printer->Print(variables, - "inline $type$* $classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " if ($name$_ == NULL) {\n" - " $name$_ = new $type$;\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $casted_member$;\n" - "}\n"); - } + printer->Print(variables_, + "inline $type$* $classname$::mutable_$name$() {\n" + "$type_reference_function$" + " $set_hasbit$\n" + " if ($name$_ == NULL) {\n"); + if (implicit_weak_field_) { + printer->Print(variables_, + " _internal_mutable_$name$();\n"); + } else { + printer->Print(variables_, + " $name$_ = ::google::protobuf::Arena::$create_func$< $type$ >(\n" + " GetArenaNoVirtual());\n"); } - + printer->Print(variables_, + " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $casted_member$;\n" + "}\n"); // We handle the most common case inline, and delegate less common cases to // the slow fallback function. - printer->Print(variables, + printer->Print(variables_, "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"); - printer->Print(variables, + printer->Print(variables_, " if (message_arena == NULL) {\n"); if (IsCrossFileMessage(descriptor_)) { - printer->Print(variables, + printer->Print(variables_, " delete reinterpret_cast< ::google::protobuf::MessageLite*>($name$_);\n"); } else { - printer->Print(variables, + printer->Print(variables_, " delete $name$_;\n"); } - printer->Print(variables, + printer->Print(variables_, " }\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type()) && IsCrossFileMessage(descriptor_)) { // We have to read the arena through the virtual method, because the type // isn't defined in this file. - printer->Print(variables, + printer->Print(variables_, " ::google::protobuf::Arena* submessage_arena =\n" " reinterpret_cast< ::google::protobuf::MessageLite*>($name$)->GetArena();\n"); } else if (!SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, + printer->Print(variables_, " ::google::protobuf::Arena* submessage_arena = NULL;\n"); } else { - printer->Print(variables, + printer->Print(variables_, " ::google::protobuf::Arena* submessage_arena =\n" " ::google::protobuf::Arena::GetArena($name$);\n"); } - printer->Print(variables, + printer->Print(variables_, " if (message_arena != submessage_arena) {\n" " $name$ = ::google::protobuf::internal::GetOwnedMessage(\n" " message_arena, $name$, submessage_arena);\n" @@ -461,13 +328,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $clear_hasbit$\n" " }\n"); if (implicit_weak_field_) { - printer->Print(variables, + printer->Print(variables_, " $name$_ = reinterpret_cast($name$);\n"); } else { - printer->Print(variables, + printer->Print(variables_, " $name$_ = $name$;\n"); } - printer->Print(variables, + printer->Print(variables_, " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } @@ -540,34 +407,12 @@ GenerateConstructorCode(io::Printer* printer) const { void MessageFieldGenerator:: GenerateCopyConstructorCode(io::Printer* printer) const { - // For non-Arena enabled messages, everything always goes on the heap. - // - // For Arena enabled messages, the logic is a bit more convoluted. - // - // In the copy constructor, we call InternalMetadataWithArena::MergeFrom, - // which does *not* copy the Arena pointer. In the generated MergeFrom - // (see MessageFieldGenerator::GenerateMergingCode), we: - // -> copy the has bits (but this is done in bulk by a memcpy in the copy - // constructor) - // -> check whether the destination field pointer is NULL (it will be, since - // we're initializing it and would have called SharedCtor) and if so: - // -> call _slow_mutable_$name$(), which calls either - // ::google::protobuf::Arena::CreateMessage<>(GetArenaNoVirtual()), or - // ::google::protobuf::Arena::Create<>(GetArenaNoVirtual()) - // - // At this point, GetArenaNoVirtual returns NULL since the Arena pointer - // wasn't copied, so both of these methods allocate the submessage on the - // heap. - - 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()); + printer->Print(variables_, + "if (from.has_$name$()) {\n" + " $name$_ = new $type$(*from.$name$_);\n" + "} else {\n" + " $name$_ = NULL;\n" + "}\n"); } void MessageFieldGenerator:: @@ -591,7 +436,7 @@ void MessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" - " $number$, *$non_null_ptr_to_name$, output);\n"); + " $number$, *$field_member$, output);\n"); } void MessageFieldGenerator:: @@ -599,7 +444,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, "target = ::google::protobuf::internal::WireFormatLite::\n" " InternalWrite$declared_type$ToArray(\n" - " $number$, *$non_null_ptr_to_name$, deterministic, target);\n"); + " $number$, *$field_member$, deterministic, target);\n"); } void MessageFieldGenerator:: @@ -607,7 +452,7 @@ GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " *$non_null_ptr_to_name$);\n"); + " *$field_member$);\n"); } // =================================================================== @@ -650,57 +495,27 @@ void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions( " message_arena, $name$, submessage_arena);\n" " }\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" + " $field_member$ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } -void MessageOneofFieldGenerator:: -GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { - // For the CRTP base class, all mutation methods are dependent, and so - // they must be in the header. - if (!dependent_base_) { - return; - } - std::map variables(variables_); - variables["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; - variables["this_message"] = "reinterpret_cast(this)->"; - // Const message access is needed for the dependent getter. - variables["this_const_message"] = "reinterpret_cast(this)->"; - variables["tmpl"] = "template \n"; - variables["field_member"] = variables["this_message"] + - variables["oneof_prefix"] + variables["name"] + - "_"; - InternalGenerateInlineAccessorDefinitions(variables, printer); -} - void MessageOneofFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - - std::map variables(variables_); - variables["dependent_classname"] = variables["classname"]; - variables["this_message"] = ""; - variables["this_const_message"] = ""; - variables["tmpl"] = ""; - variables["field_member"] = - variables["oneof_prefix"] + variables["name"] + "_"; - variables["dependent_type"] = variables["type"]; - - printer->Print(variables, + printer->Print(variables_, "inline $type$* $classname$::$release_name$() {\n" " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if ($this_message$has_$name$()) {\n" - " $this_message$clear_has_$oneof_name$();\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" " $type$* temp = $field_member$;\n"); if (SupportsArenas(descriptor_)) { - printer->Print(variables, - " if ($this_message$GetArenaNoVirtual() != NULL) {\n" + printer->Print(variables_, + " if (GetArenaNoVirtual() != NULL) {\n" " temp = ::google::protobuf::internal::DuplicateIfNonNull(temp, NULL);\n" " }\n"); } - printer->Print(variables, + printer->Print(variables_, " $field_member$ = NULL;\n" " return temp;\n" " } else {\n" @@ -708,23 +523,23 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " }\n" "}\n"); - printer->Print(variables, + printer->Print(variables_, "inline const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $this_const_message$has_$name$()\n" - " ? *$this_const_message$$oneof_prefix$$name$_\n" + " return has_$name$()\n" + " ? *$field_member$\n" " : *reinterpret_cast< $type$*>(&$type_default_instance$);\n" "}\n"); if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "inline $type$* $dependent_classname$::unsafe_arena_release_$name$() {\n" + printer->Print(variables_, + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" " // @@protoc_insertion_point(field_unsafe_arena_release" ":$full_name$)\n" - " if ($this_message$has_$name$()) {\n" - " $this_message$clear_has_$oneof_name$();\n" - " $type$* temp = $this_message$$oneof_prefix$$name$_;\n" - " $this_message$$oneof_prefix$$name$_ = NULL;\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " $type$* temp = $field_member$;\n" + " $field_member$ = NULL;\n" " return temp;\n" " } else {\n" " return NULL;\n" @@ -738,58 +553,24 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " clear_$oneof_name$();\n" " if ($name$) {\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" + " $field_member$ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" "$full_name$)\n" "}\n"); } - if (dependent_base_) { - return; - } - - InternalGenerateInlineAccessorDefinitions(variables, printer); -} - -void MessageOneofFieldGenerator::InternalGenerateInlineAccessorDefinitions( - const std::map& variables, io::Printer* printer) const { - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "$tmpl$" - "inline $type$* $dependent_classname$::mutable_$name$() {\n" - " if (!$this_message$has_$name$()) {\n" - " $this_message$clear_$oneof_name$();\n" - " $this_message$set_has_$name$();\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, - " $field_member$ = \n" - " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" - " $this_message$GetArenaNoVirtual());\n"); - } else { - printer->Print(variables, - " $this_message$$oneof_prefix$$name$_ = \n" - " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n" - " $this_message$GetArenaNoVirtual());\n"); - } - printer->Print(variables, - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $field_member$;\n" - "}\n"); - } else { - printer->Print(variables, - "$tmpl$" - "inline $type$* $dependent_classname$::mutable_$name$() {\n" - " if (!$this_message$has_$name$()) {\n" - " $this_message$clear_$oneof_name$();\n" - " $this_message$set_has_$name$();\n" - " $field_member$ = new $dependent_typename$;\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $field_member$;\n" - "}\n"); - } + printer->Print(variables_, + "inline $type$* $classname$::mutable_$name$() {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$ = ::google::protobuf::Arena::$create_func$< $type$ >(\n" + " GetArenaNoVirtual());\n" + " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $field_member$;\n" + "}\n"); } void MessageOneofFieldGenerator:: @@ -797,11 +578,11 @@ GenerateClearingCode(io::Printer* printer) const { if (SupportsArenas(descriptor_)) { printer->Print(variables_, "if (GetArenaNoVirtual() == NULL) {\n" - " delete $oneof_prefix$$name$_;\n" + " delete $field_member$;\n" "}\n"); } else { printer->Print(variables_, - "delete $oneof_prefix$$name$_;\n"); + "delete $field_member$;\n"); } } @@ -834,7 +615,7 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( : FieldGenerator(options), descriptor_(descriptor), dependent_field_(options.proto_h && IsFieldDependent(descriptor)), - dependent_getter_(dependent_field_ && options.safe_boundary_check) { + implicit_weak_field_(IsImplicitWeakField(descriptor, options)) { SetMessageVariables(descriptor, &variables_, options); } @@ -848,30 +629,12 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n"); - printer->Annotate("{", "}", descriptor_); printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n"); printer->Annotate("{", "}", descriptor_); - if (dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - } - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); } void RepeatedMessageFieldGenerator:: GenerateDependentAccessorDeclarations(io::Printer* printer) const { - if (dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - } if (dependent_field_) { InternalGenerateTypeDependentAccessorDeclarations(printer); } @@ -879,20 +642,24 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - if (!dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - } + printer->Print(variables_, + "$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); + printer->Print(variables_, + "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n" + " ${$mutable_$name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); + + printer->Print(variables_, + "$deprecated_attr$const $type$& $name$(int index) const;\n"); + printer->Annotate("name", descriptor_); if (!dependent_field_) { InternalGenerateTypeDependentAccessorDeclarations(printer); } - if (!dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - } + printer->Print(variables_, + "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + " $name$() const;\n"); + printer->Annotate("name", descriptor_); } void RepeatedMessageFieldGenerator:: @@ -908,103 +675,97 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { variables["this_message"] = DependentBaseDownCast(); variables["this_const_message"] = DependentBaseConstDownCast(); - if (dependent_getter_) { - printer->Print(variables, - "template \n" - "inline const $type$& $dependent_classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $this_const_message$$name$_.$cppget$(index);\n" - "}\n"); - } - // Generate per-element accessors: printer->Print(variables, - "template \n" - "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n" - // TODO(dlj): move insertion points - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $this_message$$name$_.Mutable(index);\n" - "}\n" "template \n" "inline $type$* $dependent_classname$::add_$name$() {\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" + "$type_reference_function$" " return $this_message$$name$_.Add();\n" "}\n"); +} - if (dependent_getter_) { - printer->Print(variables, - "template \n" - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - "$dependent_classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $this_const_message$$name$_;\n" - "}\n"); - } - - // Generate mutable access to the entire list: - printer->Print(variables, - "template \n" +void RepeatedMessageFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$* $classname$::mutable_$name$(int index) {\n" + // TODO(dlj): move insertion points + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + "$type_reference_function$" + " return $name$_.Mutable(index);\n" + "}\n" "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" - "$dependent_classname$::mutable_$name$() {\n" + "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$this_message$$name$_;\n" + "$type_reference_function$" + " return &$name$_;\n" "}\n"); -} -void RepeatedMessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - if (!dependent_getter_) { + if (options_.safe_boundary_check) { + printer->Print(variables_, + "inline const $type$& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + "$type_reference_function$" + " return $name$_.InternalCheckedGet(index,\n" + " *reinterpret_cast(&$type_default_instance$));\n" + "}\n"); + } else { printer->Print(variables_, "inline const $type$& $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.$cppget$(index);\n" + "$type_reference_function$" + " return $name$_.Get(index);\n" "}\n"); } if (!dependent_field_) { printer->Print(variables_, - "inline $type$* $classname$::mutable_$name$(int index) {\n" - // TODO(dlj): move insertion points - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.Mutable(index);\n" - "}\n" "inline $type$* $classname$::add_$name$() {\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" + "$type_reference_function$" " return $name$_.Add();\n" "}\n"); } - if (!dependent_field_) { - printer->Print(variables_, - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); - } - if (!dependent_getter_) { - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n"); - } + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + "$type_reference_function$" + " return $name$_;\n" + "}\n"); } void RepeatedMessageFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + if (implicit_weak_field_) { + printer->Print( + variables_, + "CastToBase(&$name$_)->Clear<" + "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>();\n"); + } else { + printer->Print(variables_, "$name$_.Clear();\n"); + } } void RepeatedMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + if (implicit_weak_field_) { + printer->Print( + variables_, + "CastToBase(&$name$_)->MergeFrom<" + "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase(" + "from.$name$_));\n"); + } else { + printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + } } void RepeatedMessageFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); + printer->Print( + variables_, + "CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n"); } void RepeatedMessageFieldGenerator:: @@ -1015,9 +776,18 @@ GenerateConstructorCode(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::" - "ReadMessage(input, add_$name$()));\n"); + if (implicit_weak_field_) { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::" + "ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n" + " reinterpret_cast(\n" + " &$type_default_instance$))));\n"); + } else { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::" + "ReadMessage(\n" + " input, add_$name$()));\n"); + } } else { printer->Print(variables_, "DO_(::google::protobuf::internal::WireFormatLite::" @@ -1031,7 +801,19 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "for (unsigned int i = 0,\n" " n = static_cast(this->$name$_size()); i < n; i++) {\n" " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" - " $number$, this->$name$(static_cast(i)), output);\n" + " $number$,\n"); + if (implicit_weak_field_) { + printer->Print( + variables_, + " CastToBase($name$_).Get<" + "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(" + "static_cast(i)),\n"); + } else { + printer->Print(variables_, + " this->$name$(static_cast(i)),\n"); + } + printer->Print(variables_, + " output);\n" "}\n"); } @@ -1056,9 +838,18 @@ GenerateByteSize(io::Printer* printer) const { "total_size += $tag_size$UL * count;\n" "for (unsigned int i = 0; i < count; i++) {\n" " total_size +=\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$(static_cast(i)));\n" - "}\n"); + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"); + if (implicit_weak_field_) { + printer->Print( + variables_, + " CastToBase($name$_).Get<" + "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(" + "static_cast(i)));\n"); + } else { + printer->Print(variables_, + " this->$name$(static_cast(i)));\n"); + } + printer->Print(variables_, "}\n"); printer->Outdent(); printer->Print("}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 3be505e3..e165404f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -54,9 +54,7 @@ class MessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; - void GenerateDependentAccessorDeclarations(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; @@ -73,7 +71,6 @@ class MessageFieldGenerator : public FieldGenerator { protected: const FieldDescriptor* descriptor_; - const bool dependent_field_; const bool implicit_weak_field_; std::map variables_; @@ -88,7 +85,6 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; @@ -101,9 +97,6 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { void GenerateConstructorCode(io::Printer* printer) const; private: - void InternalGenerateInlineAccessorDefinitions( - const std::map& variables, io::Printer* printer) const; - const bool dependent_base_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); }; @@ -136,7 +129,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { const FieldDescriptor* descriptor_; const bool dependent_field_; - const bool dependent_getter_; + const bool implicit_weak_field_; std::map variables_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h index 4a29ad0e..b0dd8836 100644 --- a/src/google/protobuf/compiler/cpp/cpp_options.h +++ b/src/google/protobuf/compiler/cpp/cpp_options.h @@ -54,6 +54,7 @@ struct Options { table_driven_parsing(false), table_driven_serialization(false), lite_implicit_weak_fields(false), + num_cc_files(0), access_info_map(NULL) {} string dllexport_decl; @@ -65,6 +66,7 @@ struct Options { bool table_driven_parsing; bool table_driven_serialization; bool lite_implicit_weak_fields; + int num_cc_files; string annotation_pragma_name; string annotation_guard_name; const AccessInfoMap* access_info_map; diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index bc2d02ea..701f9d2d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -215,7 +215,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "inline $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_;\n" + " return $field_member$;\n" " }\n" " return $default$;\n" "}\n" @@ -224,14 +224,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " clear_$oneof_name$();\n" " set_has_$name$();\n" " }\n" - " $oneof_prefix$$name$_ = value;\n" + " $field_member$ = value;\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } void PrimitiveOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); + printer->Print(variables_, "$field_member$ = $default$;\n"); } void PrimitiveOneofFieldGenerator:: @@ -251,7 +251,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { "clear_$oneof_name$();\n" "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" " $type$, $wire_format_field_type$>(\n" - " input, &$oneof_prefix$$name$_)));\n" + " input, &$field_member$)));\n" "set_has_$name$();\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 264f6124..c9901e84 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -402,11 +402,11 @@ GenerateMessageClearingCode(io::Printer* printer) const { // When Arenas are disabled and field presence has been checked, we can // safely treat the ArenaStringPtr as a string*. if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "(*$name$_.UnsafeRawStringPointer())->clear();\n"); + printer->Print(variables_, "$name$_.UnsafeMutablePointer()->clear();\n"); } else { - printer->Print(variables_, - "(*$name$_.UnsafeRawStringPointer())->assign(*$default_variable$);\n"); + printer->Print( + variables_, + "$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n"); } } else { if (descriptor_->default_value_string().empty()) { @@ -504,6 +504,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { } } +bool StringFieldGenerator:: +MergeFromCodedStreamNeedsArena() const { + return false; +} + void StringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { @@ -559,7 +564,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "inline const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_.Get();\n" + " return $field_member$.Get();\n" " }\n" " return *$default_variable$;\n" "}\n" @@ -567,9 +572,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.Set$lite$($default_variable$, value,\n" + " $field_member$.Set$lite$($default_variable$, value,\n" " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" @@ -579,9 +584,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.Set$lite$(\n" + " $field_member$.Set$lite$(\n" " $default_variable$, ::std::move(value), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" "}\n" @@ -591,9 +596,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.Set$lite$($default_variable$,\n" + " $field_member$.Set$lite$($default_variable$,\n" " $string_piece$(value), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" @@ -603,9 +608,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.Set$lite$(\n" + " $field_member$.Set$lite$(\n" " $default_variable$, $string_piece$(\n" " reinterpret_cast(value), size),\n" " GetArenaNoVirtual());\n" @@ -615,9 +620,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " return $oneof_prefix$$name$_.Mutable($default_variable$,\n" + " return $field_member$.Mutable($default_variable$,\n" " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" "}\n" @@ -625,7 +630,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " return $oneof_prefix$$name$_.Release($default_variable$,\n" + " return $field_member$.Release($default_variable$,\n" " GetArenaNoVirtual());\n" " } else {\n" " return NULL;\n" @@ -633,12 +638,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n" "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if (!has_$name$()) {\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" " clear_$oneof_name$();\n" " if ($name$ != NULL) {\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n" + " $field_member$.SetAllocated($default_variable$, $name$,\n" " GetArenaNoVirtual());\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" @@ -649,7 +654,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " return $oneof_prefix$$name$_.UnsafeArenaRelease(\n" + " return $field_member$.UnsafeArenaRelease(\n" " $default_variable$, GetArenaNoVirtual());\n" " } else {\n" " return NULL;\n" @@ -659,12 +664,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "::std::string* $name$) {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if (!has_$name$()) {\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" " clear_$oneof_name$();\n" " if ($name$) {\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, " + " $field_member$.UnsafeArenaSetAllocated($default_variable$, " "$name$, GetArenaNoVirtual());\n" " }\n" " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" @@ -677,7 +682,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "inline const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_.GetNoArena();\n" + " return $field_member$.GetNoArena();\n" " }\n" " return *$default_variable$;\n" "}\n" @@ -686,9 +691,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n" + " $field_member$.SetNoArena($default_variable$, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "#if LANG_CXX11\n" @@ -697,10 +702,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.SetNoArena(\n" - " $default_variable$, ::std::move(value));\n" + " $field_member$.SetNoArena($default_variable$, ::std::move(value));\n" " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" "}\n" "#endif\n" @@ -709,9 +713,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.SetNoArena($default_variable$,\n" + " $field_member$.SetNoArena($default_variable$,\n" " $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" @@ -721,10 +725,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $oneof_prefix$$name$_.SetNoArena($default_variable$, " - "$string_piece$(\n" + " $field_member$.SetNoArena($default_variable$, $string_piece$(\n" " reinterpret_cast(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" @@ -732,29 +735,28 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n" + " return $field_member$.MutableNoArena($default_variable$);\n" "}\n" "inline ::std::string* $classname$::$release_name$() {\n" " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n" + " return $field_member$.ReleaseNoArena($default_variable$);\n" " } else {\n" " return NULL;\n" " }\n" "}\n" "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if (!has_$name$()) {\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" " clear_$oneof_name$();\n" " if ($name$ != NULL) {\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n" - " $name$);\n" + " $field_member$.SetAllocatedNoArena($default_variable$, $name$);\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); @@ -765,12 +767,11 @@ void StringOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "$oneof_prefix$$name$_.Destroy($default_variable$,\n" + "$field_member$.Destroy($default_variable$,\n" " GetArenaNoVirtual());\n"); } else { printer->Print(variables_, - "$oneof_prefix$$name$_." - "DestroyNoArena($default_variable$);\n"); + "$field_member$.DestroyNoArena($default_variable$);\n"); } } @@ -796,7 +797,7 @@ void StringOneofFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { printer->Print(variables_, "if (has_$name$()) {\n" - " $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n" + " $field_member$.DestroyNoArena($default_variable$);\n" "}\n"); } @@ -912,11 +913,21 @@ GenerateAccessorDeclarations(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { + if (options_.safe_boundary_check) { + printer->Print(variables_, + "inline const ::std::string& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.InternalCheckedGet(\n" + " index, ::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n"); + } else { + printer->Print(variables_, + "inline const ::std::string& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.Get(index);\n" + "}\n"); + } printer->Print(variables_, - "inline const ::std::string& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.$cppget$(index);\n" - "}\n" "inline ::std::string* $classname$::mutable_$name$(int index) {\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" @@ -991,7 +1002,8 @@ GenerateMergingCode(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); + printer->Print(variables_, + "$name$_.InternalSwap(CastToBase(&other->$name$_));\n"); } void RepeatedStringFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index f56f0721..0c6e9ced 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -69,6 +69,8 @@ class StringFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + bool MergeFromCodedStreamNeedsArena() const; + protected: const FieldDescriptor* descriptor_; std::map variables_; diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 61cc32a4..2ad7ea4e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -995,75 +995,76 @@ TEST(GeneratedMessageTest, TestEmbedOptimizedForSize) { TEST(GeneratedMessageTest, TestSpaceUsed) { unittest::TestAllTypes message1; - // sizeof provides a lower bound on SpaceUsed(). - EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsed()); - const int empty_message_size = message1.SpaceUsed(); + // sizeof provides a lower bound on SpaceUsedLong(). + EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsedLong()); + const size_t empty_message_size = message1.SpaceUsedLong(); // Setting primitive types shouldn't affect the space used. message1.set_optional_int32(123); message1.set_optional_int64(12345); message1.set_optional_uint32(123); message1.set_optional_uint64(12345); - EXPECT_EQ(empty_message_size, message1.SpaceUsed()); + EXPECT_EQ(empty_message_size, message1.SpaceUsedLong()); // On some STL implementations, setting the string to a small value should - // only increase SpaceUsed() by the size of a string object, though this is - // not true everywhere. + // only increase SpaceUsedLong() by the size of a string object, though this + // is not true everywhere. message1.set_optional_string("abc"); - EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); + EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsedLong()); // Setting a string to a value larger than the string object itself should - // increase SpaceUsed(), because it cannot store the value internally. + // increase SpaceUsedLong(), because it cannot store the value internally. message1.set_optional_string(string(sizeof(string) + 1, 'x')); int min_expected_increase = message1.optional_string().capacity() + sizeof(string); EXPECT_LE(empty_message_size + min_expected_increase, - message1.SpaceUsed()); + message1.SpaceUsedLong()); - int previous_size = message1.SpaceUsed(); + size_t previous_size = message1.SpaceUsedLong(); // Adding an optional message should increase the size by the size of the // nested message type. NestedMessage is simple enough (1 int field) that it // is equal to sizeof(NestedMessage) message1.mutable_optional_nested_message(); ASSERT_EQ(sizeof(unittest::TestAllTypes::NestedMessage), - message1.optional_nested_message().SpaceUsed()); + message1.optional_nested_message().SpaceUsedLong()); EXPECT_EQ(previous_size + sizeof(unittest::TestAllTypes::NestedMessage), - message1.SpaceUsed()); + message1.SpaceUsedLong()); } TEST(GeneratedMessageTest, TestOneofSpaceUsed) { unittest::TestOneof2 message1; - EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed()); + EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsedLong()); - const int empty_message_size = message1.SpaceUsed(); + const size_t empty_message_size = message1.SpaceUsedLong(); // Setting primitive types shouldn't affect the space used. message1.set_foo_int(123); message1.set_bar_int(12345); - EXPECT_EQ(empty_message_size, message1.SpaceUsed()); + EXPECT_EQ(empty_message_size, message1.SpaceUsedLong()); - // Setting a string in oneof to a small value should only increase SpaceUsed() - // by the size of a string object. + // Setting a string in oneof to a small value should only increase + // SpaceUsedLong() by the size of a string object. message1.set_foo_string("abc"); - EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); + EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsedLong()); // Setting a string in oneof to a value larger than the string object itself - // should increase SpaceUsed(), because it cannot store the value internally. + // should increase SpaceUsedLong(), because it cannot store the value + // internally. message1.set_foo_string(string(sizeof(string) + 1, 'x')); int min_expected_increase = message1.foo_string().capacity() + sizeof(string); EXPECT_LE(empty_message_size + min_expected_increase, - message1.SpaceUsed()); + message1.SpaceUsedLong()); // Setting a message in oneof should delete the other fields and increase the // size by the size of the nested message type. NestedMessage is simple enough // that it is equal to sizeof(NestedMessage) message1.mutable_foo_message(); ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage), - message1.foo_message().SpaceUsed()); + message1.foo_message().SpaceUsedLong()); EXPECT_EQ(empty_message_size + sizeof(unittest::TestOneof2::NestedMessage), - message1.SpaceUsed()); + message1.SpaceUsedLong()); } #endif // !PROTOBUF_TEST_NO_DESCRIPTORS diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc index d1bb3194..456784c6 100644 --- a/src/google/protobuf/compiler/cpp/metadata_test.cc +++ b/src/google/protobuf/compiler/cpp/metadata_test.cc @@ -72,9 +72,7 @@ class CppMetadataTest : public ::testing::Test { TestTempDir(); const bool result = - atu::CaptureMetadata(filename, cpp_out, - /* meta_file_suffix */ "", &cli, file, - /* outputs */ NULL); + atu::RunProtoCompiler(filename, cpp_out, &cli, file); if (!result) { return result; diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 2486b739..f2ff2800 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -1259,19 +1259,9 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Indent(); printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n" - "default: {\n" - " if (!parseUnknownField$suffix$(\n" - " input, unknownFields, extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n", - "suffix", - descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3" - : ""); + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; @@ -1309,6 +1299,18 @@ GenerateParsingConstructor(io::Printer* printer) { } } + printer->Print( + "default: {\n" + " if (!parseUnknownField$suffix$(\n" + " input, unknownFields, extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n", + "suffix", + descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3" + : ""); + printer->Outdent(); printer->Outdent(); printer->Print( diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index d828be43..108504c7 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -1005,37 +1005,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( " 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(tag, input)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } - google::protobuf::scoped_array sorted_fields( SortFieldsByNumber(descriptor_)); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -1073,6 +1042,37 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( } } + 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(tag, input)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } + printer->Outdent(); printer->Outdent(); printer->Print( diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index 16fe19ad..fd2d3dfd 100755 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -195,9 +195,9 @@ string ModuleAlias(const string& filename) { // We'll worry about this problem if/when we actually see it. This name isn't // exposed to users so we can change it later if we need to. string basename = StripProto(filename); - StripString(&basename, "-", '$'); - StripString(&basename, "/", '_'); - StripString(&basename, ".", '_'); + ReplaceCharacters(&basename, "-", '$'); + ReplaceCharacters(&basename, "/", '_'); + ReplaceCharacters(&basename, ".", '_'); return basename + "_pb"; } @@ -1028,7 +1028,7 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options, if (!IsPrimitive(jstype)) { jstype = "!" + jstype; } - jstype = "Array.<" + jstype + ">"; + jstype = "Array<" + jstype + ">"; } } @@ -1558,6 +1558,22 @@ bool GenerateJspbAllowedSet(const GeneratorOptions& options, return true; } +// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of +// file. +void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations, + io::Printer* printer) { + // Serialize annotations proto into base64 string. + string meta_content; + annotations.SerializeToString(&meta_content); + string meta_64; + Base64Escape(meta_content, &meta_64); + + // Print base64 encoded annotations at the end of output file in + // a comment. + printer->Print("\n// Below is base64 encoded GeneratedCodeInfo proto"); + printer->Print("\n// $encoded_proto$\n", "encoded_proto", meta_64); +} + } // anonymous namespace void Generator::GenerateHeader(const GeneratorOptions& options, @@ -2822,7 +2838,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, "so that it\n" " * works in OPTIMIZED mode.\n" " *\n" - " * @type {!Object.}\n" + " * @type {!Object}\n" " */\n" "$class$.extensions = {};\n" "\n", @@ -2843,7 +2859,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, "so that it\n" " * works in OPTIMIZED mode.\n" " *\n" - " * @type {!Object.}\n" + " * @type {!Object}\n" " */\n" "$class$.extensionsBinary = {};\n" "\n", @@ -3195,7 +3211,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "/**\n" " * A tuple of {field number, class constructor} for the extension\n" " * field named `$name$`.\n" - " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n" + " * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n" " */\n" "$class$.$name$ = new jspb.ExtensionFieldInfo(\n", "name", JSObjectFieldName(options, field), @@ -3634,10 +3650,7 @@ bool Generator::GenerateAll(const std::vector& files, } if (options.annotate_code) { - const string meta_file = filename + ".meta"; - google::protobuf::scoped_ptr info_output( - context->Open(meta_file)); - annotations.SerializeToZeroCopyStream(info_output.get()); + EmbedCodeAnnotations(annotations, &printer); } } } diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index bfcb83df..7719ec3d 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -70,7 +70,7 @@ namespace compiler { // Returns the list of the names of files in all_files in the form of a // comma-separated string. -string CommaSeparatedList(const std::vector all_files) { +string CommaSeparatedList(const std::vector& all_files) { std::vector names; for (size_t i = 0; i < all_files.size(); i++) { names.push_back(all_files[i]->name()); diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 80c8c625..d13ad2b3 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -325,13 +325,6 @@ const Version& Version::default_instance() { return *internal_default_instance(); } -Version* Version::New(::google::protobuf::Arena* arena) const { - Version* n = new Version; - if (arena != NULL) { - arena->Own(n); - } - return n; -} void Version::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version) @@ -342,7 +335,7 @@ void Version::Clear() { cached_has_bits = _has_bits_[0]; if (cached_has_bits & 0x00000001u) { GOOGLE_DCHECK(!suffix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*suffix_.UnsafeRawStringPointer())->clear(); + suffix_.UnsafeMutablePointer()->clear(); } if (cached_has_bits & 14u) { ::memset(&major_, 0, static_cast( @@ -723,13 +716,6 @@ const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() { return *internal_default_instance(); } -CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const { - CodeGeneratorRequest* n = new CodeGeneratorRequest; - if (arena != NULL) { - arena->Own(n); - } - return n; -} void CodeGeneratorRequest::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest) @@ -743,7 +729,7 @@ void CodeGeneratorRequest::Clear() { if (cached_has_bits & 3u) { if (cached_has_bits & 0x00000001u) { GOOGLE_DCHECK(!parameter_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*parameter_.UnsafeRawStringPointer())->clear(); + parameter_.UnsafeMutablePointer()->clear(); } if (cached_has_bits & 0x00000002u) { GOOGLE_DCHECK(compiler_version_ != NULL); @@ -813,7 +799,8 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( case 15: { if (static_cast< ::google::protobuf::uint8>(tag) == static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_proto_file())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( + input, add_proto_file())); } else { goto handle_unusual; } @@ -870,14 +857,16 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( // optional .google.protobuf.compiler.Version compiler_version = 3; if (cached_has_bits & 0x00000002u) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, *this->compiler_version_, output); + 3, *compiler_version_, output); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; for (unsigned int i = 0, n = static_cast(this->proto_file_size()); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 15, this->proto_file(static_cast(i)), output); + 15, + this->proto_file(static_cast(i)), + output); } if (_internal_metadata_.have_unknown_fields()) { @@ -920,7 +909,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( if (cached_has_bits & 0x00000002u) { target = ::google::protobuf::internal::WireFormatLite:: InternalWriteMessageToArray( - 3, *this->compiler_version_, deterministic, target); + 3, *compiler_version_, deterministic, target); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; @@ -979,7 +968,7 @@ size_t CodeGeneratorRequest::ByteSizeLong() const { if (has_compiler_version()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSize( - *this->compiler_version_); + *compiler_version_); } } @@ -1051,8 +1040,8 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { } void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { using std::swap; - file_to_generate_.InternalSwap(&other->file_to_generate_); - proto_file_.InternalSwap(&other->proto_file_); + file_to_generate_.InternalSwap(CastToBase(&other->file_to_generate_)); + CastToBase(&proto_file_)->InternalSwap(CastToBase(&other->proto_file_)); parameter_.Swap(&other->parameter_); swap(compiler_version_, other->compiler_version_); swap(_has_bits_[0], other->_has_bits_[0]); @@ -1138,13 +1127,6 @@ const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() return *internal_default_instance(); } -CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const { - CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File; - if (arena != NULL) { - arena->Own(n); - } - return n; -} void CodeGeneratorResponse_File::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File) @@ -1156,15 +1138,15 @@ void CodeGeneratorResponse_File::Clear() { if (cached_has_bits & 7u) { if (cached_has_bits & 0x00000001u) { GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.UnsafeMutablePointer()->clear(); } if (cached_has_bits & 0x00000002u) { GOOGLE_DCHECK(!insertion_point_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*insertion_point_.UnsafeRawStringPointer())->clear(); + insertion_point_.UnsafeMutablePointer()->clear(); } if (cached_has_bits & 0x00000004u) { GOOGLE_DCHECK(!content_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*content_.UnsafeRawStringPointer())->clear(); + content_.UnsafeMutablePointer()->clear(); } } _has_bits_.Clear(); @@ -1518,13 +1500,6 @@ const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() { return *internal_default_instance(); } -CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const { - CodeGeneratorResponse* n = new CodeGeneratorResponse; - if (arena != NULL) { - arena->Own(n); - } - return n; -} void CodeGeneratorResponse::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse) @@ -1536,7 +1511,7 @@ void CodeGeneratorResponse::Clear() { cached_has_bits = _has_bits_[0]; if (cached_has_bits & 0x00000001u) { GOOGLE_DCHECK(!error_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*error_.UnsafeRawStringPointer())->clear(); + error_.UnsafeMutablePointer()->clear(); } _has_bits_.Clear(); _internal_metadata_.Clear(); @@ -1572,7 +1547,8 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( case 15: { if (static_cast< ::google::protobuf::uint8>(tag) == static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_file())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( + input, add_file())); } else { goto handle_unusual; } @@ -1620,7 +1596,9 @@ void CodeGeneratorResponse::SerializeWithCachedSizes( for (unsigned int i = 0, n = static_cast(this->file_size()); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 15, this->file(static_cast(i)), output); + 15, + this->file(static_cast(i)), + output); } if (_internal_metadata_.have_unknown_fields()) { @@ -1752,7 +1730,7 @@ void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) { } void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { using std::swap; - file_.InternalSwap(&other->file_); + CastToBase(&file_)->InternalSwap(CastToBase(&other->file_)); error_.Swap(&other->error_); swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -1769,5 +1747,21 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { } // namespace compiler } // namespace protobuf } // namespace google +namespace google { +namespace protobuf { +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::Version* Arena::Create< ::google::protobuf::compiler::Version >(Arena* arena) { + return Arena::CreateInternal< ::google::protobuf::compiler::Version >(arena); +} +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorRequest* Arena::Create< ::google::protobuf::compiler::CodeGeneratorRequest >(Arena* arena) { + return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorRequest >(arena); +} +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse_File >(Arena* arena) { + return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse_File >(arena); +} +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse >(Arena* arena) { + return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse >(arena); +} +} // namespace protobuf +} // namespace google // @@protoc_insertion_point(global_scope) diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 8f92b6ae..617fd799 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -84,6 +84,14 @@ LIBPROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; } // namespace google namespace google { namespace protobuf { +template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorRequest* Arena::Create< ::google::protobuf::compiler::CodeGeneratorRequest>(Arena*); +template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse>(Arena*); +template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse_File>(Arena*); +template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::Version* Arena::Create< ::google::protobuf::compiler::Version>(Arena*); +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { namespace compiler { // =================================================================== @@ -139,9 +147,13 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_ // implements Message ---------------------------------------------- - inline Version* New() const PROTOBUF_FINAL { return New(NULL); } + inline Version* New() const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(NULL); + } - Version* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; + Version* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(arena); + } void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void CopyFrom(const Version& from); @@ -287,9 +299,13 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message // implements Message ---------------------------------------------- - inline CodeGeneratorRequest* New() const PROTOBUF_FINAL { return New(NULL); } + inline CodeGeneratorRequest* New() const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(NULL); + } - CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; + CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(arena); + } void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void CopyFrom(const CodeGeneratorRequest& from); @@ -351,11 +367,11 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message int proto_file_size() const; void clear_proto_file(); static const int kProtoFileFieldNumber = 15; - const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); - ::google::protobuf::FileDescriptorProto* add_proto_file(); ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_proto_file(); + const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; + ::google::protobuf::FileDescriptorProto* add_proto_file(); const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& proto_file() const; @@ -453,9 +469,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M // implements Message ---------------------------------------------- - inline CodeGeneratorResponse_File* New() const PROTOBUF_FINAL { return New(NULL); } + inline CodeGeneratorResponse_File* New() const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(NULL); + } - CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; + CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(arena); + } void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void CopyFrom(const CodeGeneratorResponse_File& from); @@ -607,9 +627,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // implements Message ---------------------------------------------- - inline CodeGeneratorResponse* New() const PROTOBUF_FINAL { return New(NULL); } + inline CodeGeneratorResponse* New() const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(NULL); + } - CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; + CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL { + return ::google::protobuf::Arena::Create(arena); + } void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; void CopyFrom(const CodeGeneratorResponse& from); @@ -651,11 +675,11 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag int file_size() const; void clear_file(); static const int kFileFieldNumber = 15; - const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); - ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* mutable_file(); + const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; + ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& file() const; @@ -973,23 +997,23 @@ inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* paramet inline int CodeGeneratorRequest::proto_file_size() const { return proto_file_.size(); } -inline 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); -} inline ::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); } -inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_.Add(); -} inline ::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_; } +inline 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); +} +inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Add(); +} inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& CodeGeneratorRequest::proto_file() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) @@ -1026,7 +1050,8 @@ inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::release_comp inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() { set_has_compiler_version(); if (compiler_version_ == NULL) { - compiler_version_ = new ::google::protobuf::compiler::Version; + compiler_version_ = ::google::protobuf::Arena::Create< ::google::protobuf::compiler::Version >( + GetArenaNoVirtual()); } // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) return compiler_version_; @@ -1317,23 +1342,23 @@ inline int CodeGeneratorResponse::file_size() const { inline void CodeGeneratorResponse::clear_file() { file_.Clear(); } -inline 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); -} inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Mutable(index); } -inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_.Add(); -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } +inline 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); +} +inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Add(); +} inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& CodeGeneratorResponse::file() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) -- cgit v1.2.3