[PATCH] D94739: ADT: Fix reference invalidation in SmallVector::emplace_back and the size+value version of SmallVector::assign

Duncan P. N. Exon Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 14 18:42:28 PST 2021


dexonsmith created this revision.
dexonsmith added reviewers: njames93, dblaikie.
Herald added subscribers: ributzka, hiraditya.
dexonsmith requested review of this revision.
Herald added a project: LLVM.

Fix the final (I think?) reference invalidation in `SmallVector` that
we need to fix to align with `std::vector`. (There is still some left in
the range insert / append / assign, but the standard calls that UB for
`std::vector` so I think we don't care?)

Avoid reference invalidation during `SmallVector::emplace_back` when one
of the arguments is an internal reference to storage and the vector has
to grow.

For POD-like types, reimplement `emplace_back` in terms of `push_back`.

For other types, split the grow operation in three and construct the new
element in the middle.

Also reimplement `SmallVector:assign(size_type, const T&)` to avoid
invalidating the argument during `clear()` when it's an internal
reference.

There is a minor semantic change when not growing. Previously, assign
would start with `clear()`, and so the old elements were destructed and
all elements of the new vector were copy-constructed.  The new
implementation skips destruction and uses copy-assignment for the prefix
of the new vector less than `size()`. The new semantics match what
libc++ does for `std::vector::assign`.

Note that the following is another possible implementation:

  void assign(size_type NumElts, ValueParamT Elt) {
    std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt);
    this->resize(NumElts, Elt);
  }

The downside of this is that if the vector has to grow there will be
`size()` redundant copy operations.

I should probably split this patch up into three for committing:

1. NFC refactoring to split up `grow()`.
2. Fix `emplace_back()`.
3. Fix `assign()`.

... but I wanted to start the review all together since the patches
will be interdependent.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94739

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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D94739.316827.patch
Type: text/x-patch
Size: 17604 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210115/c0875658/attachment.bin>


More information about the llvm-commits mailing list