1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

ADT: Fix reference invalidation in SmallVector::resize

For small enough, trivially copyable `T`, take the parameter by-value in
`SmallVector::resize`.  Otherwise, when growing, update the arugment
appropriately.

Differential Revision: https://reviews.llvm.org/D93781
This commit is contained in:
Duncan P. N. Exon Smith 2020-11-19 17:12:27 -08:00
parent 1518e520f8
commit 48a93fb6cc
2 changed files with 10 additions and 11 deletions

View File

@ -565,7 +565,7 @@ public:
/// 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) {
void resize(size_type N, ValueParamT NV) {
if (N == this->size())
return;
@ -575,11 +575,8 @@ public:
return;
}
this->assertSafeToReferenceAfterResize(&NV, N);
if (this->capacity() < N)
this->grow(N);
std::uninitialized_fill(this->end(), this->begin() + N, NV);
this->set_size(N);
// N > this->size(). Defer to append.
this->append(N - this->size(), NV);
}
void reserve(size_type N) {

View File

@ -1135,12 +1135,14 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) {
auto &V = this->V;
(void)V;
int N = this->NumBuiltinElts(V);
#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
EXPECT_DEATH(V.resize(N + 1, V.back()), this->AssertionMessage);
#endif
V.resize(N + 1, V.back());
EXPECT_EQ(N, V.back());
// No assertion when shrinking, since the parameter isn't accessed.
V.resize(N - 1, V.back());
// Resize to add enough elements that V will grow again. If reference
// invalidation breaks in the future, sanitizers should be able to catch a
// use-after-free here.
V.resize(V.capacity() + 1, V.front());
EXPECT_EQ(1, V.back());
}
TYPED_TEST(SmallVectorReferenceInvalidationTest, Append) {