[PATCH] D115443: [ADT] Weaken the initialization condition in SmallVector::resize_for_overwrite

Benjamin Kramer via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 9 06:12:59 PST 2021


bkramer created this revision.
bkramer added reviewers: dexonsmith, njames93.
bkramer requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This method was originally modeled after std::make_unique_for_overwrite, which
default initializes everything, making it a lot less useful.

Using is_trivially_copyable as the condition gives uninitialized memory for
classes that have a default constructor but still allows using
resize_for_overwrite for classes with a non-trivial assignment operator or
destructor. In other words, it makes
SmallVector<std::unique_ptr>::resize_for_overwrite safe and
SmallVector<clang::SourceLocation>::resize_for_overwrite efficient.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115443

Files:
  llvm/include/llvm/ADT/SmallVector.h
  llvm/unittests/ADT/SmallVectorTest.cpp


Index: llvm/unittests/ADT/SmallVectorTest.cpp
===================================================================
--- llvm/unittests/ADT/SmallVectorTest.cpp
+++ llvm/unittests/ADT/SmallVectorTest.cpp
@@ -392,6 +392,33 @@
     V.resize(V.size() + 1);
     EXPECT_EQ(0U, V.back());
   }
+  {
+    struct DefaultConstructible {
+      unsigned U = 10;
+    };
+    SmallVector<DefaultConstructible> V;
+    V.push_back({5U});
+    V.pop_back();
+    V.resize_for_overwrite(V.size() + 1U);
+    EXPECT_EQ(5U, V.back().U);
+    V.pop_back();
+    V.resize(V.size() + 1);
+    EXPECT_EQ(10U, V.back().U);
+  }
+  {
+    struct DefaultConstructible {
+      unsigned U = 20;
+      ~DefaultConstructible() {}
+    };
+    SmallVector<DefaultConstructible> V;
+    V.push_back({5U});
+    V.pop_back();
+    V.resize_for_overwrite(V.size() + 1U);
+    EXPECT_EQ(20U, V.back().U);
+    V.pop_back();
+    V.resize(V.size() + 1);
+    EXPECT_EQ(20U, V.back().U);
+  }
 }
 
 // Overflow past fixed size.
Index: llvm/include/llvm/ADT/SmallVector.h
===================================================================
--- llvm/include/llvm/ADT/SmallVector.h
+++ llvm/include/llvm/ADT/SmallVector.h
@@ -598,10 +598,8 @@
     }
 
     this->reserve(N);
-    for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
-      if (ForOverwrite)
-        new (&*I) T;
-      else
+    if (!ForOverwrite || !is_trivially_copyable<T>::value)
+      for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
         new (&*I) T();
     this->set_size(N);
   }
@@ -609,7 +607,9 @@
 public:
   void resize(size_type N) { resizeImpl<false>(N); }
 
-  /// Like resize, but \ref T is POD, the new values won't be initialized.
+  /// Like resize, but if \ref T is trivially copyable, the new values won't be
+  /// initialized. This is similar in spirit to std::make_unique_for_overwrite,
+  /// but does not default initialize.
   void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
 
   /// Like resize, but requires that \p N is less than \a size().


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D115443.393136.patch
Type: text/x-patch
Size: 2046 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211209/6d67e95e/attachment.bin>


More information about the llvm-commits mailing list