aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/cpp/cpp_message.cc
diff options
context:
space:
mode:
authorFeng Xiao <xfxyjwf@gmail.com>2014-11-26 16:15:29 -0800
committerFeng Xiao <xfxyjwf@gmail.com>2014-11-26 16:15:29 -0800
commitc25d9feb4d791513c101061578e9e54fe180aa5f (patch)
treef264d2d9edbea0cf30c875ec41e322790f852110 /src/google/protobuf/compiler/cpp/cpp_message.cc
parent90f2f50233fc42a9e6f551ac8454c46a5df00454 (diff)
downloadprotobuf-c25d9feb4d791513c101061578e9e54fe180aa5f.tar.gz
protobuf-c25d9feb4d791513c101061578e9e54fe180aa5f.tar.bz2
protobuf-c25d9feb4d791513c101061578e9e54fe180aa5f.zip
Down-integrate from internal code base.
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_message.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc42
1 files changed, 39 insertions, 3 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index b42f32b8..212bc3e9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -561,7 +561,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
} else {
printer->Print(vars,
"inline bool $classname$::has_$name$() const {\n"
- " return $name$_ != NULL;\n"
+ " return !_is_default_instance_ && $name$_ != NULL;\n"
"}\n");
}
}
@@ -1051,6 +1051,22 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(cached_size_decl.c_str());
need_to_emit_cached_size = false;
}
+ } else {
+ // Without field presence, we need another way to disambiguate the default
+ // instance, because the default instance's submessage fields (if any) store
+ // pointers to the default instances of the submessages even when they
+ // aren't present. Alternatives to this approach might be to (i) use a
+ // tagged pointer on all message fields, setting a tag bit for "not really
+ // present, just default instance"; or (ii) comparing |this| against the
+ // return value from GeneratedMessageFactory::GetPrototype() in all
+ // has_$field$() calls. However, both of these options are much more
+ // expensive (in code size and CPU overhead) than just checking a field in
+ // the message. Long-term, the best solution would be to rearchitect the
+ // default instance design not to store pointers to submessage default
+ // instances, and have reflection get those some other way; but that change
+ // would have too much impact on proto2.
+ printer->Print(
+ "bool _is_default_instance_;\n");
}
// Field members:
@@ -1323,11 +1339,21 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
- "$classname$, _internal_metadata_));\n");
+ "$classname$, _internal_metadata_),\n");
+ } else {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _arena_),\n");
+ }
+
+ // is_default_instance_ offset.
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(vars,
+ " -1);\n");
} else {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
- "$classname$, _arena_));\n");
+ "$classname$, _is_default_instance_));\n");
}
// Handle nested types.
@@ -1612,6 +1638,11 @@ GenerateSharedConstructorCode(io::Printer* printer) {
"classname", classname_);
printer->Indent();
+ if (!HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ " _is_default_instance_ = false;\n");
+ }
+
printer->Print(StrCat(
uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
"_cached_size_ = 0;\n").c_str());
@@ -1809,6 +1840,11 @@ GenerateStructors(io::Printer* printer) {
"void $classname$::InitAsDefaultInstance() {\n",
"classname", classname_);
+ if (!HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ " _is_default_instance_ = true;\n");
+ }
+
// The default instance needs all of its embedded message pointers
// cross-linked to other default instances. We can't do this initialization
// in the constructor because some other default instances may not have been