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.cc616
1 files changed, 482 insertions, 134 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index ba318d10..b4545892 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -63,6 +63,14 @@ 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);
+ }
}
} // namespace
@@ -85,7 +93,21 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+}
+
+void MessageFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
+ // Arena manipulation code is out-of-line in the derived message class.
+ printer->Print(variables_,
+ "$type$* mutable_$name$()$deprecation$;\n"
+ "$type$* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
}
void MessageFieldGenerator::
@@ -103,11 +125,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$type$* _slow_$release_name$()$deprecation$;\n"
"public:\n");
}
- printer->Print(variables_,
- "const $type$& $name$() const$deprecation$;\n"
- "$type$* mutable_$name$()$deprecation$;\n"
- "$type$* $release_name$()$deprecation$;\n"
- "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ GenerateGetterDeclaration(printer);
+ if (!dependent_field_) {
+ printer->Print(variables_,
+ "$type$* mutable_$name$()$deprecation$;\n"
+ "$type$* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ }
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
"$type$* unsafe_arena_release_$name$()$deprecation$;\n"
@@ -123,12 +147,12 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
"void $classname$::_slow_mutable_$name$() {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
} else {
printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
}
printer->Print(variables_,
"}\n"
@@ -151,7 +175,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
if (SupportsArenas(descriptor_->message_type())) {
// NOTE: the same logic is mirrored in weak_message_field.cc. Any
// arena-related semantics changes should be made in both places.
- printer->Print(variables_,
+ printer->Print(variables_,
"void $classname$::_slow_set_allocated_$name$(\n"
" ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
" if (message_arena != NULL && \n"
@@ -189,15 +213,139 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
void MessageFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
+
+ 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"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = DependentBaseDownCast();
+ 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 <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if ($name$_ == NULL) {\n"
+ " $this_message$_slow_mutable_$name$();\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::$release_name$() {\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $clear_hasbit$\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+ " return $this_message$_slow_$release_name$();\n"
+ " } else {\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "template <class T>\n"
+ "inline void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if (message_arena == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$ != NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ // If we're on an arena and the incoming message is not, simply Own() it
+ // rather than copy to the arena -- either way we need a heap dealloc,
+ // so we might as well defer it. Otherwise, if incoming message is on a
+ // different ownership domain (specific arena, or the heap) than we are,
+ // copy to our arena (or heap, as the case may be).
+ printer->Print(variables,
+ " $this_message$_slow_set_allocated_$name$(message_arena, "
+ "&$name$);\n");
+ } else {
+ printer->Print(variables,
+ " if (message_arena != NULL) {\n"
+ " message_arena->Own($name$);\n"
+ " }\n");
+ }
+ printer->Print(variables,
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ // TODO(dlj): move insertion points to message class.
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if ($name$_ == NULL) {\n"
+ " $name$_ = new $dependent_typename$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " delete $name$_;\n");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables,
+ " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)"
+ "->GetArena() != NULL) {\n"
+ " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+
+ printer->Print(variables,
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ }
}
void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
+ "$inline$const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
@@ -206,19 +354,25 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
+ printer->Print(variables, "}\n");
+
+ if (dependent_field_) {
+ return;
+ }
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
+ "$inline$"
+ "$type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
- " _slow_mutable_$name$();"
+ " _slow_mutable_$name$();\n"
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
+ "$inline$"
+ "$type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" if (GetArenaNoVirtual() != NULL) {\n"
" return _slow_$release_name$();\n"
@@ -228,7 +382,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return temp;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ "
+ "void $classname$::set_allocated_$name$($type$* $name$) {\n"
" ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
" if (message_arena == NULL) {\n"
" delete $name$_;\n"
@@ -260,8 +415,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n");
} else {
printer->Print(variables,
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
+ "$inline$"
+ "$type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
" $name$_ = new $type$;\n"
@@ -269,13 +424,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
+ "$inline$"
+ "$type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$"
+ "void $classname$::set_allocated_$name$($type$* $name$) {\n"
" delete $name$_;\n");
if (SupportsArenas(descriptor_->message_type())) {
@@ -301,15 +458,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ 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 !=
// NULL. Thus on clear, we need to delete the object.
- printer->Print(variables_,
- "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n"
- "$name$_ = NULL;\n");
+ printer->Print(variables,
+ "if ($this_message$GetArenaNoVirtual() == NULL && "
+ "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
+ "$this_message$$name$_ = NULL;\n");
} else {
- printer->Print(variables_,
- "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ printer->Print(variables,
+ "if ($this_message$$name$_ != NULL) $this_message$$name$_->"
+ "$dependent_type$::Clear();\n");
}
}
@@ -370,79 +531,149 @@ GenerateByteSize(io::Printer* printer) const {
MessageOneofFieldGenerator::
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : MessageFieldGenerator(descriptor, options) {
+ : MessageFieldGenerator(descriptor, options),
+ dependent_base_(options.proto_h) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ // Oneof field getters must be dependent as they call default_instance().
+ // Otherwise, the logic is the same as MessageFields.
+ if (!dependent_field_) {
+ return;
+ }
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+ MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+ // Oneof field getters must be dependent as they call default_instance().
+ // Unlike MessageField, this means there is no (non-dependent) getter to
+ // generate.
+ if (dependent_field_) {
+ return;
+ }
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\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;
+ }
+ map<string, string> variables(variables_);
+ variables["inline"] = "inline ";
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = "reinterpret_cast<T*>(this)->";
+ // Const message access is needed for the dependent getter.
+ variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ variables["tmpl"] = "template <class T>\n";
+ variables["field_member"] = variables["this_message"] +
+ variables["oneof_prefix"] + variables["name"] +
+ "_";
+ InternalGenerateInlineAccessorDefinitions(variables, printer);
}
void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
+ if (dependent_base_) {
+ return;
+ }
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
+ 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"];
+ InternalGenerateInlineAccessorDefinitions(variables, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
+ 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 {
+ printer->Print(variables,
+ "$tmpl$"
+ "$inline$ "
+ "const $type$& $dependent_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"
+ " : $dependent_type$::default_instance();\n"
+ "}\n");
+
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n");
+ "$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,
- " $oneof_prefix$$name$_ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $field_member$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n");
} else {
printer->Print(variables,
- " $oneof_prefix$$name$_ = \n"
- " ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $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 $oneof_prefix$$name$_;\n"
+ " return $field_member$;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " if (GetArenaNoVirtual() != NULL) {\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::$release_name$() {\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
// N.B.: safe to use the underlying field pointer here because we are sure
// that it is non-NULL (because has_$name$() returned true).
- " $type$* temp = new $type$;\n"
- " temp->MergeFrom(*$oneof_prefix$$name$_);\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " $dependent_typename$* temp = new $dependent_typename$;\n"
+ " temp->MergeFrom(*$field_member$);\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " $dependent_typename$* temp = $field_member$;\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" }\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
- " return temp;\n"
- " } else {\n"
- " return NULL;\n"
- " }\n"
- "}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $this_message$clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
@@ -450,32 +681,42 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
// If incoming message is on the heap and we are on an arena, just Own()
// it (see above). If it's on a different arena than we are or one of us
// is on the heap, we make a copy to our arena/heap.
- " if (GetArenaNoVirtual() != NULL &&\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL &&\n"
" ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
- " } else if (GetArenaNoVirtual() !=\n"
+ " $this_message$GetArenaNoVirtual()->Own($name$);\n"
+ " } else if ($this_message$GetArenaNoVirtual() !=\n"
" ::google::protobuf::Arena::GetArena($name$)) {\n"
- " $type$* new_$name$ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n"
+ " $dependent_typename$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
} else {
printer->Print(variables,
- " if (GetArenaNoVirtual() != NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+ " $this_message$GetArenaNoVirtual()->Own($name$);\n"
" }\n");
}
printer->Print(variables,
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
- "$type$* $name$) {\n"
+ "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " $type$* temp = $oneof_prefix$$name$_;\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$"
+ "($type$* $name$) {\n"
// We rely on the oneof clear method to free the earlier contents of this
// oneof. We can directly use the pointer we're given to set the new
// value.
@@ -489,44 +730,47 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n");
} else {
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new $type$;\n"
+ "$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 $oneof_prefix$$name$_;\n"
+ " return $field_member$;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::$release_name$() {\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " $dependent_typename$* temp = $field_member$;\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $this_message$clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables,
- " if ($name$->GetArena() != NULL) {\n"
- " $type$* new_$name$ = new $type$;\n"
+ " if (static_cast< $dependent_typename$*>($name$)->"
+ "GetArena() != NULL) {\n"
+ " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
}
printer->Print(variables,
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
@@ -535,14 +779,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "if (GetArenaNoVirtual() == NULL) {\n"
- " delete $oneof_prefix$$name$_;\n"
+ printer->Print(variables,
+ "if ($this_message$GetArenaNoVirtual() == NULL) {\n"
+ " delete $this_message$$oneof_prefix$$name$_;\n"
"}\n");
} else {
- printer->Print(variables_,
- "delete $oneof_prefix$$name$_;\n");
+ printer->Print(variables,
+ "delete $this_message$$oneof_prefix$$name$_;\n");
}
}
@@ -562,7 +808,9 @@ GenerateConstructorCode(io::Printer* printer) const {
RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
+ dependent_getter_(dependent_field_ && options.safe_boundary_check) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -575,60 +823,160 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
-GenerateDependentAccessorDeclarations(io::Printer* printer) const {
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateAccessorDeclarations(io::Printer* printer) const {
+InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "const $type$& $name$(int index) const$deprecation$;\n"
"$type$* mutable_$name$(int index)$deprecation$;\n"
"$type$* add_$name$()$deprecation$;\n");
+ if (dependent_getter_) {
+ printer->Print(variables_,
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n");
+ }
printer->Print(variables_,
- "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- " $name$() const$deprecation$;\n"
"::google::protobuf::RepeatedPtrField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
-GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ if (dependent_getter_) {
+ printer->Print(variables_,
+ "const $type$& $name$(int index) const$deprecation$;\n");
+ }
+ if (dependent_field_) {
+ InternalGenerateTypeDependentAccessorDeclarations(printer);
+ }
}
void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
- bool is_inline) const {
+GenerateAccessorDeclarations(io::Printer* printer) const {
+ if (!dependent_getter_) {
+ printer->Print(variables_,
+ "const $type$& $name$(int index) const$deprecation$;\n");
+ }
+ if (!dependent_field_) {
+ InternalGenerateTypeDependentAccessorDeclarations(printer);
+ }
+ if (!dependent_getter_) {
+ printer->Print(variables_,
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ // 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()) + "<T>";
+ variables["this_message"] = DependentBaseDownCast();
+ variables["this_const_message"] = DependentBaseConstDownCast();
+
+ if (dependent_getter_) {
+ printer->Print(variables,
+ "template <class T>\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,
- "$inline$ const $type$& $classname$::$name$(int index) const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return $name$_.$cppget$(index);\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$(int index) {\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
+ // TODO(dlj): move insertion points
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_.Mutable(index);\n"
+ " return $this_message$$name$_.Mutable(index);\n"
"}\n"
- "$inline$ $type$* $classname$::add_$name$() {\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
- " return $name$_.Add();\n"
+ " return $this_message$$name$_.Add();\n"
"}\n");
+
+
+ if (dependent_getter_) {
+ printer->Print(variables,
+ "template <class T>\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,
- "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_list:$full_name$)\n"
- " return $name$_;\n"
- "}\n"
- "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
+ "template <class T>\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$dependent_classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
- " return &$name$_;\n"
+ " return &$this_message$$name$_;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline " : "";
+
+ if (!dependent_getter_) {
+ 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"
+ "}\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"
+ " 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");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Clear();\n");
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+ printer->Print(variables, "$this_message$$name$_.Clear();\n");
}
void RepeatedMessageFieldGenerator::