Skip to content

Commit

Permalink
[ADT] Add resize_for_overwrite method to SmallVector.
Browse files Browse the repository at this point in the history
Analagous to the std::make_(unqiue|shared)_for_overwrite added in c++20.
If T is POD, and the container gets larger, any new values added wont be initialized.
This is useful when using SmallVector as a buffer where its planned to overwrite any potential new values added.
If T is not POD, `new (Storage) T` functions identically to `new (Storage) T()` so this will function identically to `resize(size_type)`.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D93532
  • Loading branch information
njames93 committed Dec 22, 2020
1 parent be85b3e commit 5d10b8a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
14 changes: 12 additions & 2 deletions llvm/include/llvm/ADT/SmallVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,19 +460,29 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
this->Size = 0;
}

void resize(size_type N) {
private:
template <bool ForOverwrite> void resizeImpl(size_type N) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->set_size(N);
} else if (N > this->size()) {
if (this->capacity() < N)
this->grow(N);
for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
new (&*I) T();
if (ForOverwrite)
new (&*I) T;
else
new (&*I) T();
this->set_size(N);
}
}

public:
void resize(size_type N) { resizeImpl<false>(N); }

/// Like resize, but \ref T is POD, the new values won't be initialized.
void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }

void resize(size_type N, const T &NV) {
if (N == this->size())
return;
Expand Down
25 changes: 25 additions & 0 deletions llvm/unittests/ADT/SmallVectorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,31 @@ TYPED_TEST(SmallVectorTest, ResizeFillTest) {
this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77);
}

TEST(SmallVectorTest, ResizeForOverwrite) {
{
// Heap allocated storage.
SmallVector<unsigned, 0> V;
V.push_back(5);
V.pop_back();
V.resize_for_overwrite(V.size() + 1);
EXPECT_EQ(5, V.back());
V.pop_back();
V.resize(V.size() + 1);
EXPECT_EQ(0, V.back());
}
{
// Inline storage.
SmallVector<unsigned, 2> V;
V.push_back(5);
V.pop_back();
V.resize_for_overwrite(V.size() + 1);
EXPECT_EQ(5, V.back());
V.pop_back();
V.resize(V.size() + 1);
EXPECT_EQ(0, V.back());
}
}

// Overflow past fixed size.
TYPED_TEST(SmallVectorTest, OverflowTest) {
SCOPED_TRACE("OverflowTest");
Expand Down

0 comments on commit 5d10b8a

Please sign in to comment.