aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/cpp/cpp_message_field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_message_field.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc101
1 files changed, 85 insertions, 16 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index ca7bae02..91449657 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -45,7 +45,7 @@ namespace cpp {
namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables,
+ std::map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
@@ -218,7 +218,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
return;
}
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
// For the CRTP base class, all mutation methods are dependent, and so
// they must be in the header.
variables["dependent_classname"] =
@@ -349,7 +349,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
// for dependent fields we cannot access its internal_default_instance,
// because the type is incomplete.
// TODO(gerbens) deprecate dependent base class.
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
"$inline$const $type$& $classname$::$name$() const {\n"
@@ -360,7 +360,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
return;
}
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
"$inline$const $type$& $classname$::$name$() const {\n"
@@ -469,7 +469,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (!HasFieldPresence(descriptor_->file())) {
// If we don't have has-bits, message presence is indicated only by ptr !=
@@ -486,6 +486,26 @@ GenerateClearingCode(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateMessageClearingCode(io::Printer* printer) const {
+ std::map<string, string> variables(variables_);
+ variables["type"] = FieldMessageTypeName(descriptor_);
+
+ if (!HasFieldPresence(descriptor_->file())) {
+ // If we don't have has-bits, message presence is indicated only by ptr !=
+ // NULL. Thus on clear, we need to delete the object.
+ printer->Print(variables_,
+ "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n"
+ " delete $name$_;\n"
+ "}\n"
+ "$name$_ = NULL;\n");
+ } else {
+ printer->Print(variables_,
+ "GOOGLE_DCHECK($name$_ != NULL);\n"
+ "$name$_->$type$::Clear();\n");
+ }
+}
+
+void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
@@ -497,11 +517,51 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+ // In google3 a default instance will never get deleted so we don't need to
+ // worry about that but in opensource protobuf default instances are deleted
+ // in shutdown process and we need to take special care when handling them.
+ printer->Print(variables_,
+ "if (this != internal_default_instance()) {\n"
+ " delete $name$_;\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = NULL;\n");
}
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.
+
+ printer->Print(variables_,
+ "if (from.has_$name$()) {\n"
+ " $name$_ = new $type$(*from.$name$_);\n"
+ "} else {\n"
+ " $name$_ = NULL;\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(variables_,
@@ -581,7 +641,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
if (!dependent_base_) {
return;
}
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["inline"] = "inline ";
variables["dependent_classname"] =
DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
@@ -601,7 +661,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
if (dependent_base_) {
return;
}
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
variables["dependent_classname"] = variables["classname"];
variables["this_message"] = "";
@@ -615,16 +675,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageOneofFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["field_member"] =
variables["oneof_prefix"] + variables["name"] + "_";
//printer->Print(variables,
}
-void MessageOneofFieldGenerator::
-InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
- io::Printer* printer) const {
+void MessageOneofFieldGenerator::InternalGenerateInlineAccessorDefinitions(
+ const std::map<string, string>& variables, io::Printer* printer) const {
printer->Print(variables,
"$tmpl$"
"$inline$ "
@@ -794,7 +853,7 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
@@ -808,11 +867,22 @@ GenerateClearingCode(io::Printer* printer) const {
}
void MessageOneofFieldGenerator::
+GenerateMessageClearingCode(io::Printer* printer) const {
+ GenerateClearingCode(printer);
+}
+
+void MessageOneofFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
// Don't print any swapping code. Swapping the union will swap this field.
}
void MessageOneofFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+ // We inherit from MessageFieldGenerator, so we need to override the default
+ // behavior.
+}
+
+void MessageOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
// Don't print any constructor code. The field is in a union. We allocate
// space only when this field is used.
@@ -884,7 +954,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
if (!dependent_field_) {
return;
}
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
// For the CRTP base class, all mutation methods are dependent, and so
// they must be in the header.
variables["dependent_classname"] =
@@ -915,7 +985,6 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
" return $this_message$$name$_.Add();\n"
"}\n");
-
if (dependent_getter_) {
printer->Print(variables,
"template <class T>\n"
@@ -939,7 +1008,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
if (!dependent_getter_) {
@@ -989,7 +1058,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- map<string, string> variables(variables_);
+ std::map<string, string> variables(variables_);
variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
printer->Print(variables, "$this_message$$name$_.Clear();\n");
}