diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/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::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(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(N); } /// Like resize, but requires that \p N is less than \a size(). diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/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 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 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.