diff options
author | Owen Anderson <resistor@mac.com> | 2011-07-06 22:36:59 +0000 |
---|---|---|
committer | Owen Anderson <resistor@mac.com> | 2011-07-06 22:36:59 +0000 |
commit | 9cbd7afb76f20ce874464c238764c54f86b3ce3b (patch) | |
tree | 7acc01733408ee1b1164841128edad753982669e /include | |
parent | 4fd3c5957e6a272b60d6446e745136187d07f812 (diff) | |
download | llvm-9cbd7afb76f20ce874464c238764c54f86b3ce3b.tar.gz llvm-9cbd7afb76f20ce874464c238764c54f86b3ce3b.tar.bz2 llvm-9cbd7afb76f20ce874464c238764c54f86b3ce3b.tar.xz |
Fix a subtle issue in SmallVector. The following code did not work as expected:
vec.insert(vec.begin(), vec[3]);
The issue was that vec[3] returns a reference into the vector, which is invalidated when insert() memmove's the elements down to make space. The method needs to specifically detect and handle this case to correctly match std::vector's semantics.
Thanks to Howard Hinnant for clarifying the correct behavior, and explaining how std::vector solves this problem.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134554 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/ADT/SmallVector.h | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 8b0a13d6ed..5f0a55bec4 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -410,7 +410,14 @@ public: this->setEnd(this->end()+1); // Push everything else over. std::copy_backward(I, this->end()-1, this->end()); - *I = Elt; + + // If we just moved the element we're inserting, be sure to update + // the reference. + const T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->EndX) + ++EltPtr; + + *I = *EltPtr; return I; } size_t EltNo = I-this->begin(); |