Implement copy constructor and assignment operator.

PiperOrigin-RevId: 524941810
pull/13171/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 565c8fe66e
commit 433e737c0e
  1. 3
      BUILD
  2. 1
      protos_generator/BUILD
  3. 56
      protos_generator/gen_messages.cc
  4. 1
      protos_generator/protoc-gen-upb-protos.cc
  5. 58
      protos_generator/tests/test_generated.cc

@ -421,9 +421,11 @@ cc_library(
cc_library( cc_library(
name = "generated_cpp_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", name = "generated_cpp_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me",
hdrs = [ hdrs = [
"upb/message/copy.h",
"upb/message/extension_internal.h", "upb/message/extension_internal.h",
"upb/message/internal.h", "upb/message/internal.h",
"upb/message/message.h", "upb/message/message.h",
"upb/mini_table/common.h",
"upb/mini_table/enum_internal.h", "upb/mini_table/enum_internal.h",
"upb/mini_table/extension_internal.h", "upb/mini_table/extension_internal.h",
"upb/mini_table/field_internal.h", "upb/mini_table/field_internal.h",
@ -444,6 +446,7 @@ cc_library(
":base", ":base",
":collections_internal", ":collections_internal",
":hash", ":hash",
":message_copy",
":mini_table", ":mini_table",
":upb", ":upb",
], ],

@ -65,6 +65,7 @@ cc_library(
], ],
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
deps = [ deps = [
"//:message_copy",
"//upbc:common", "//upbc:common",
"//upbc:file_layout", "//upbc:file_layout",
"//upbc:keywords", "//upbc:keywords",

@ -97,8 +97,8 @@ void WriteMessageClassDeclarations(
output("} // namespace internal\n"); output("} // namespace internal\n");
WriteModelPublicDeclaration(descriptor, file_exts, file_enums, output); WriteModelPublicDeclaration(descriptor, file_exts, file_enums, output);
output("namespace internal {\n"); output("namespace internal {\n");
WriteModelProxyDeclaration(descriptor, output);
WriteModelCProxyDeclaration(descriptor, output); WriteModelCProxyDeclaration(descriptor, output);
WriteModelProxyDeclaration(descriptor, output);
output("} // namespace internal\n"); output("} // namespace internal\n");
} }
@ -151,22 +151,38 @@ void WriteModelPublicDeclaration(
using Access = internal::$0Access; using Access = internal::$0Access;
using Proxy = internal::$0Proxy; using Proxy = internal::$0Proxy;
using CProxy = internal::$0CProxy; using CProxy = internal::$0CProxy;
$0(); $0();
$0(const $0& m) = delete;
$0& operator=(const $0& m) = delete; $0(const $0& from);
inline $0& operator=(const $3& from) {
arena_ = owned_arena_.ptr();
msg_ = ($2*)upb_Message_DeepClone(from.msg_, &$1, arena_);
return *this;
}
$0(const CProxy& from);
$0(const Proxy& from);
inline $0& operator=(const CProxy& from) {
arena_ = owned_arena_.ptr();
msg_ = ($2*)upb_Message_DeepClone(
::protos::internal::GetInternalMsg(from), &$1, arena_);
return *this;
}
$0($0&& m) $0($0&& m)
: Access(m.msg_, m.arena_), : Access(absl::exchange(m.msg_, nullptr),
absl::exchange(m.arena_, nullptr)),
owned_arena_(std::move(m.owned_arena_)) {} owned_arena_(std::move(m.owned_arena_)) {}
$0& operator=($0&& m) { $0& operator=($0&& m) {
msg_ = m.msg_; msg_ = absl::exchange(m.msg_, nullptr);
arena_ = m.arena_; arena_ = absl::exchange(m.arena_, nullptr);
m.msg_ = nullptr;
m.arena_ = nullptr;
owned_arena_ = std::move(m.owned_arena_); owned_arena_ = std::move(m.owned_arena_);
return *this; return *this;
} }
)cc", )cc",
ClassName(descriptor)); ClassName(descriptor), ::upbc::MessageInit(descriptor->full_name()),
MessageName(descriptor), QualifiedClassName(descriptor));
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, output); WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, output);
WriteUsingEnumsInHeader(descriptor, file_enums, output); WriteUsingEnumsInHeader(descriptor, file_enums, output);
@ -274,6 +290,7 @@ void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
public: public:
$0CProxy() = delete; $0CProxy() = delete;
$0CProxy(const $0* m) : internal::$0Access(m->msg_, nullptr) {} $0CProxy(const $0* m) : internal::$0Access(m->msg_, nullptr) {}
$0CProxy($0Proxy m);
using $0Access::GetInternalArena; using $0Access::GetInternalArena;
)cc", )cc",
ClassName(descriptor), MessageName(descriptor)); ClassName(descriptor), MessageName(descriptor));
@ -318,15 +335,32 @@ void WriteMessageImplementation(
arena_ = owned_arena_.ptr(); arena_ = owned_arena_.ptr();
msg_ = $1_new(arena_); msg_ = $1_new(arena_);
} }
$0::$0(const $0& from) : $0Access() {
arena_ = owned_arena_.ptr();
msg_ = ($1*)upb_Message_DeepClone(from.msg_, &$2, arena_);
}
$0::$0(const CProxy& from) : $0Access() {
arena_ = owned_arena_.ptr();
msg_ = ($1*)upb_Message_DeepClone(
::protos::internal::GetInternalMsg(from), &$2, arena_);
}
$0::$0(const Proxy& from) : $0(static_cast<const CProxy&>(from)) {}
internal::$0CProxy::$0CProxy($0Proxy m) : $0Access() {
arena_ = m.arena_;
msg_ = ($1*)::protos::internal::GetInternalMsg(m);
}
)cc", )cc",
ClassName(descriptor), MessageName(descriptor)); ClassName(descriptor), MessageName(descriptor),
::upbc::MessageInit(descriptor->full_name()),
QualifiedClassName(descriptor));
output("\n");
// Minitable // Minitable
OutputIndenter i(output);
output( output(
R"cc( R"cc(
const upb_MiniTable* $0::minitable() { return &$1; } const upb_MiniTable* $0::minitable() { return &$1; }
)cc", )cc",
ClassName(descriptor), ::upbc::MessageInit(descriptor->full_name())); ClassName(descriptor), ::upbc::MessageInit(descriptor->full_name()));
output("\n");
} }
WriteAccessorsInSource(descriptor, output); WriteAccessorsInSource(descriptor, output);

@ -134,6 +134,7 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) {
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "upb/message/internal.h" #include "upb/message/internal.h"
#include "upb/message/copy.h"
)cc", )cc",
ToPreproc(file->name())); ToPreproc(file->name()));

@ -25,6 +25,7 @@
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <utility>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "protos/protos.h" #include "protos/protos.h"
@ -640,3 +641,60 @@ TEST(CppGeneratedCode, UniquePointer) {
auto bytes = protos::Serialize(model, arena); auto bytes = protos::Serialize(model, arena);
EXPECT_TRUE(protos::Parse(model, bytes.value())); EXPECT_TRUE(protos::Parse(model, bytes.value()));
} }
TEST(CppGeneratedCode, Assignment) {
TestModel model;
model.set_category(5);
model.mutable_child_model_1()->set_child_str1("text in child");
TestModel model2 = model;
EXPECT_EQ(5, model2.category());
EXPECT_EQ(model2.child_model_1()->child_str1(), "text in child");
}
TEST(CppGeneratedCode, PtrAssignment) {
TestModel model;
model.mutable_child_model_1()->set_child_str1("text in child");
ChildModel1 child_from_const_ptr = *model.child_model_1();
EXPECT_EQ(child_from_const_ptr.child_str1(), "text in child");
ChildModel1 child_from_ptr = *model.mutable_child_model_1();
EXPECT_EQ(child_from_ptr.child_str1(), "text in child");
}
TEST(CppGeneratedCode, CopyConstructor) {
TestModel model;
model.set_category(6);
TestModel model2(model);
EXPECT_EQ(6, model2.category());
}
TEST(CppGeneratedCode, PtrConstructor) {
TestModel model;
model.mutable_child_model_1()->set_child_str1("text in child");
ChildModel1 child_from_ptr(*model.mutable_child_model_1());
EXPECT_EQ(child_from_ptr.child_str1(), "text in child");
ChildModel1 child_from_const_ptr(*model.child_model_1());
EXPECT_EQ(child_from_const_ptr.child_str1(), "text in child");
}
TEST(CppGeneratedCode, MutableToProxy) {
TestModel model;
::protos::Ptr<ChildModel1> child = model.mutable_child_model_1();
(void)child;
}
TEST(CppGeneratedCode, ProxyToCProxy) {
TestModel model;
::protos::Ptr<ChildModel1> child = model.mutable_child_model_1();
::protos::Ptr<const ChildModel1> child2 = child;
(void)child2;
}
bool ProxyToCProxyMethod(::protos::Ptr<const ChildModel1> child) {
return child->child_str1() == "text in child";
}
TEST(CppGeneratedCode, PassProxyToCProxy) {
TestModel model;
model.mutable_child_model_1()->set_child_str1("text in child");
EXPECT_TRUE(ProxyToCProxyMethod(model.mutable_child_model_1()));
}

Loading…
Cancel
Save