[ArrayRef] Make copy use std::uninitialized_copy.
authorBenjamin Kramer <benny.kra@googlemail.com>
Tue, 4 Aug 2015 15:52:56 +0000 (15:52 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Tue, 4 Aug 2015 15:52:56 +0000 (15:52 +0000)
std::copy does not work for non-trivially copyable classes when we're
copying into uninitialized memory.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243995 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/ArrayRef.h
unittests/ADT/ArrayRefTest.cpp

index f6cc4f4e7c35ba61c84092ea7d555732724b71b4..e8063305591f95f79585d439e1dfc65ec7da3f37 100644 (file)
@@ -148,7 +148,7 @@ namespace llvm {
     // copy - Allocate copy in Allocator and return ArrayRef<T> to it.
     template <typename Allocator> ArrayRef<T> copy(Allocator &A) {
       T *Buff = A.template Allocate<T>(Length);
-      std::copy(begin(), end(), Buff);
+      std::uninitialized_copy(begin(), end(), Buff);
       return ArrayRef<T>(Buff, Length);
     }
 
index 9ad32d54d36be3f8d980d667819e41b1657b9184..064024140c49217135332bb3d9cb3f8673789b83 100644 (file)
@@ -31,7 +31,7 @@ static_assert(
     !std::is_convertible<ArrayRef<volatile int *>, ArrayRef<int *>>::value,
     "Removing volatile");
 
-namespace llvm {
+namespace {
 
 TEST(ArrayRefTest, AllocatorCopy) {
   BumpPtrAllocator Alloc;
@@ -45,6 +45,18 @@ TEST(ArrayRefTest, AllocatorCopy) {
   EXPECT_NE(Array1.data(), Array1c.data());
   EXPECT_TRUE(Array2.equals(Array2c));
   EXPECT_NE(Array2.data(), Array2c.data());
+
+  // Check that copy can cope with uninitialized memory.
+  struct NonAssignable {
+    const char *Ptr;
+
+    NonAssignable(const NonAssignable &RHS) = default;
+    void operator=(const NonAssignable &RHS) { assert(RHS.Ptr != nullptr); }
+    bool operator==(const NonAssignable &RHS) const { return Ptr == RHS.Ptr; }
+  } Array3Src[] = {{"hello"}, {"world"}};
+  ArrayRef<NonAssignable> Array3Copy = makeArrayRef(Array3Src).copy(Alloc);
+  EXPECT_EQ(makeArrayRef(Array3Src), Array3Copy);
+  EXPECT_NE(makeArrayRef(Array3Src).data(), Array3Copy.data());
 }
 
 TEST(ArrayRefTest, DropBack) {