Add copy constructors to the C++ Dawn interface

This removes the need for Clone() so it is removed and also adds tests
for the new constructors.

BUG=dawn:11

Change-Id: Ia45c765c2d30e40b0e036427793a62327b2008fc
Reviewed-on: https://dawn-review.googlesource.com/c/1901
Reviewed-by: Stephen White <senorblanco@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index 77b2ad8..869f95f 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -232,9 +232,9 @@
     dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
 
     dawn::ComputePipelineDescriptor csDesc;
-    csDesc.module = module.Clone();
+    csDesc.module = module;
     csDesc.entryPoint = "main";
-    csDesc.layout = pl.Clone();
+    csDesc.layout = pl;
     updatePipeline = device.CreateComputePipeline(&csDesc);
 
     dawn::BufferView updateParamsView = updateParams.CreateBufferViewBuilder()
diff --git a/generator/templates/apicpp.h b/generator/templates/apicpp.h
index 68873ac..af142b0 100644
--- a/generator/templates/apicpp.h
+++ b/generator/templates/apicpp.h
@@ -70,19 +70,29 @@
                 if (mHandle) Derived::DawnRelease(mHandle);
             }
 
-            ObjectBase(ObjectBase const& other) = delete;
-            Derived& operator=(ObjectBase const& other) = delete;
+            ObjectBase(ObjectBase const& other)
+                : ObjectBase(other.Get()) {
+            }
+            Derived& operator=(ObjectBase const& other) {
+                if (&other != this) {
+                    if (mHandle) Derived::DawnRelease(mHandle);
+                    mHandle = other.mHandle;
+                    if (mHandle) Derived::DawnReference(mHandle);
+                }
+
+                return static_cast<Derived&>(*this);
+            }
 
             ObjectBase(ObjectBase&& other) {
                 mHandle = other.mHandle;
                 other.mHandle = 0;
             }
             Derived& operator=(ObjectBase&& other) {
-                if (&other == this) return static_cast<Derived&>(*this);
-
-                if (mHandle) Derived::DawnRelease(mHandle);
-                mHandle = other.mHandle;
-                other.mHandle = 0;
+                if (&other != this) {
+                    if (mHandle) Derived::DawnRelease(mHandle);
+                    mHandle = other.mHandle;
+                    other.mHandle = 0;
+                }
 
                 return static_cast<Derived&>(*this);
             }
@@ -98,9 +108,6 @@
                 mHandle = 0;
                 return result;
             }
-            Derived Clone() const {
-                return Derived(mHandle);
-            }
             static Derived Acquire(CType handle) {
                 Derived result;
                 result.mHandle = handle;
diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp
index ad88763..f58dd2b 100644
--- a/src/tests/DawnTest.cpp
+++ b/src/tests/DawnTest.cpp
@@ -258,15 +258,13 @@
                                                    uint32_t offset,
                                                    uint32_t size,
                                                    detail::Expectation* expectation) {
-    dawn::Buffer source = buffer.Clone();
-
     auto readback = ReserveReadback(size);
 
     // We need to enqueue the copy immediately because by the time we resolve the expectation,
     // the buffer might have been modified.
     dawn::CommandBuffer commands =
         device.CreateCommandBufferBuilder()
-            .CopyBufferToBuffer(source, offset, readback.buffer, readback.offset, size)
+            .CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size)
             .GetResult();
 
     queue.Submit(1, &commands);
@@ -296,7 +294,6 @@
                                                     uint32_t level,
                                                     uint32_t pixelSize,
                                                     detail::Expectation* expectation) {
-    dawn::Texture source = texture.Clone();
     uint32_t rowPitch = Align(width * pixelSize, kTextureRowPitchAlignment);
     uint32_t size = rowPitch * (height - 1) + width * pixelSize;
 
@@ -306,7 +303,7 @@
     // the texture might have been modified.
     dawn::CommandBuffer commands =
         device.CreateCommandBufferBuilder()
-            .CopyTextureToBuffer(source, x, y, 0, width, height, 1, level, 0, readback.buffer,
+            .CopyTextureToBuffer(texture, x, y, 0, width, height, 1, level, 0, readback.buffer,
                                  readback.offset, rowPitch)
             .GetResult();
 
@@ -359,7 +356,7 @@
     slot.buffer = device.CreateBuffer(&descriptor);
 
     ReadbackReservation reservation;
-    reservation.buffer = slot.buffer.Clone();
+    reservation.buffer = slot.buffer;
     reservation.slot = mReadbackSlots.size();
     reservation.offset = 0;
 
diff --git a/src/tests/end2end/BindGroupTests.cpp b/src/tests/end2end/BindGroupTests.cpp
index 9510e06..8585151 100644
--- a/src/tests/end2end/BindGroupTests.cpp
+++ b/src/tests/end2end/BindGroupTests.cpp
@@ -52,9 +52,9 @@
     dawn::ShaderModule module =
         utils::CreateShaderModule(device, dawn::ShaderStage::Compute, shader);
     dawn::ComputePipelineDescriptor cpDesc;
-    cpDesc.module = module.Clone();
+    cpDesc.module = module;
     cpDesc.entryPoint = "main";
-    cpDesc.layout = pl.Clone();
+    cpDesc.layout = pl;
     dawn::ComputePipeline cp = device.CreateComputePipeline(&cpDesc);
 
     dawn::BufferDescriptor bufferDesc;
diff --git a/src/tests/end2end/ComputeCopyStorageBufferTests.cpp b/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
index 9ee3021..d047ec1 100644
--- a/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
+++ b/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
@@ -39,9 +39,9 @@
     auto pl = utils::MakeBasicPipelineLayout(device, &bgl);
 
     dawn::ComputePipelineDescriptor csDesc;
-    csDesc.module = module.Clone();
+    csDesc.module = module;
     csDesc.entryPoint = "main";
-    csDesc.layout = pl.Clone();
+    csDesc.layout = pl;
     dawn::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);
 
     // Set up src storage buffer
diff --git a/src/tests/end2end/PushConstantTests.cpp b/src/tests/end2end/PushConstantTests.cpp
index 070abec..80fa857 100644
--- a/src/tests/end2end/PushConstantTests.cpp
+++ b/src/tests/end2end/PushConstantTests.cpp
@@ -146,9 +146,9 @@
             );
 
             dawn::ComputePipelineDescriptor descriptor;
-            descriptor.module = module.Clone();
+            descriptor.module = module;
             descriptor.entryPoint = "main";
-            descriptor.layout = pl.Clone();
+            descriptor.layout = pl;
             return device.CreateComputePipeline(&descriptor);
         }
 
diff --git a/src/tests/unittests/ObjectBaseTests.cpp b/src/tests/unittests/ObjectBaseTests.cpp
index 1e6058a..2c9dccb 100644
--- a/src/tests/unittests/ObjectBaseTests.cpp
+++ b/src/tests/unittests/ObjectBaseTests.cpp
@@ -22,7 +22,7 @@
         using ObjectBase::operator=;
 
         static void DawnReference(int* handle) {
-            ASSERT_LT(0, *handle);
+            ASSERT_LE(0, *handle);
             *handle += 1;
         }
         static void DawnRelease(int* handle) {
@@ -52,16 +52,14 @@
     ASSERT_EQ(0, refcount);
 }
 
-// Test that cloning takes a new ref. Also test .Get().
-TEST(ObjectBase, Clone) {
+// Test .Get().
+TEST(ObjectBase, Get) {
     int refcount = 1;
     {
         Object obj1(&refcount);
-        Object obj2 = obj1.Clone();
 
-        ASSERT_EQ(3, refcount);
+        ASSERT_EQ(2, refcount);
         ASSERT_EQ(&refcount, obj1.Get());
-        ASSERT_EQ(&refcount, obj2.Get());
     }
     ASSERT_EQ(1, refcount);
 }
@@ -91,6 +89,51 @@
     }
 }
 
+// Test the copy constructor of C++ objects
+TEST(ObjectBase, CopyConstructor) {
+    int refcount = 1;
+
+    Object source(&refcount);
+    Object destination(source);
+
+    ASSERT_EQ(source.Get(), &refcount);
+    ASSERT_EQ(destination.Get(), &refcount);
+    ASSERT_EQ(3, refcount);
+
+    destination = Object();
+    ASSERT_EQ(refcount, 2);
+}
+
+// Test the copy assignment of C++ objects
+TEST(ObjectBase, CopyAssignment) {
+    int refcount = 1;
+    Object source(&refcount);
+
+    Object destination;
+    destination = source;
+
+    ASSERT_EQ(source.Get(), &refcount);
+    ASSERT_EQ(destination.Get(), &refcount);
+    ASSERT_EQ(3, refcount);
+
+    destination = Object();
+    ASSERT_EQ(refcount, 2);
+}
+
+// Test the copy assignment of C++ objects onto themselves
+TEST(ObjectBase, CopyAssignmentSelf) {
+    int refcount = 1;
+
+    Object obj(&refcount);
+
+    // Fool the compiler to avoid a -Wself-assign-overload
+    Object* objPtr = &obj;
+    obj = *objPtr;
+
+    ASSERT_EQ(obj.Get(), &refcount);
+    ASSERT_EQ(refcount, 2);
+}
+
 // Test the move constructor of C++ objects
 TEST(ObjectBase, MoveConstructor) {
     int refcount = 1;
@@ -121,3 +164,16 @@
     ASSERT_EQ(refcount, 1);
 }
 
+// Test the move assignment of C++ objects onto themselves
+TEST(ObjectBase, MoveAssignmentSelf) {
+    int refcount = 1;
+
+    Object obj(&refcount);
+
+    // Fool the compiler to avoid a -Wself-move
+    Object* objPtr = &obj;
+    obj = std::move(*objPtr);
+
+    ASSERT_EQ(obj.Get(), &refcount);
+    ASSERT_EQ(refcount, 2);
+}