[llvm] r178166 - Avoid undefined behavior from passing a std::vector's own contents

Jean-Luc Duprat jduprat at apple.com
Mon Apr 1 11:27:10 PDT 2013


I just ran into a similar issue with LLVM's SmallVector in case that was very similar to the one discussed in the standard library.
I light of Howard's comment, SmallVector should preserve the validity of both iterators/reference in this case:
 v.insert(v.begin(), v[3]);
if it is to behave similarly to std::vector.

I propose the attached fix to SmallVector.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: SmallVector.patch
Type: application/octet-stream
Size: 2290 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130401/d16b9956/attachment.obj>
-------------- next part --------------



JL



On Mar 27, 2013, at 13:47 , Howard Hinnant <hhinnant at apple.com> wrote:

> On Mar 27, 2013, at 4:34 PM, Dan Gohman <dan433584 at gmail.com> wrote:
> 
>> 
>> 
>> On Wed, Mar 27, 2013 at 12:16 PM, Howard Hinnant <hhinnant at apple.com> wrote:
>> On Mar 27, 2013, at 2:44 PM, Dan Gohman <dan433584 at gmail.com> wrote:
>> 
>>> Author: djg
>>> Date: Wed Mar 27 13:44:56 2013
>>> New Revision: 178166
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=178166&view=rev
>>> Log:
>>> Avoid undefined behavior from passing a std::vector's own contents
>>> in as an argument to push_back.
>> 
>> The original code is not undefined behavior.
>> 
>> My interpretation was that the push_back could cause reallocation which could invalidate the reference to the old element before it is read. Is there a guarantee that this won't happen?
> 
> There is not an allowance for the vendor to let it happen.  Such an allowance would look like the one for insert(p, i, j):
> 
>> pre: i and j are not iterators into a.
> 
> In practice, the new buffer has to be allocated and populated before the old buffer is deallocated, so there is no hardship on the vendor anyway.
> 
> The vendor does have to be careful with vector::insert(iterator, const T&), as self-referencing can be visible there.  But again in that case the standard puts the onus on the vendor, not on the client to just make things work.
> 
> Note that if you had moved from the source that would be another matter as 17.6.4.9 [res.on.arguments]/p1/b3 says:
> 
>> f a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument.
> 
> So, for example:
> 
>   v.insert(v.begin(), std::move(v[3]));
> 
> would be asking for trouble, whereas 
> 
>   v.insert(v.begin(), v[3]);
> 
> is ok.
> 
> Howard
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list