[PATCH] Fix C++ strict-aliasing issues with memcpy folding

Gabriel Dos Reis gdr@integrable-solutions.net
Fri Feb 5 10:22:00 GMT 2010


On Fri, Feb 5, 2010 at 3:42 AM, Richard Guenther <rguenther@suse.de> wrote:
> On Thu, 4 Feb 2010, Gabriel Dos Reis wrote:
>
>> On Thu, Feb 4, 2010 at 7:56 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
>> > Hi,
>> >>> About this, just wanted to point out that in Pittsburgh this paper will
>> >>> be discussed again
>> >>>
>> >>>  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2981.pdf
>> >>>
>> >>> whereas in Santa Cruz concerns have been raised exactly about those
>> >>> placement new of subobjects vs aliasing. In my opinion the proposed
>> >>> solution to the long standing issue with std::pair is otherwise very
>> >>> nice and I would really encourage you to check it vs aliasing...
>> >>>
>> >> I missed the Santa Cruz meeting.  What was the concerns about aliasing?
>> >>
>> > I don't remember the details, but essentially Doug was afraid that the
>> > scheme you can still see at the beginning of the Proposed Wording
>> > (remnant of the previous version) could not be completely safe wrt
>> > aliasing: nobody in the room could really confirm or deny that and the
>> > discussion stalled. Lately, I think I read on the reflector that Pablo
>> > has hopes it is safe, actually. Some input would be definitely welcome,
>> > I think.
>>
>> I would be more than glad to provide input.
>> However, I do not see what the aliasing issue could possibly be.
>> As far as I can tell, storage is obtained and is used to
>> construct each sub-component of the pair in distinct sub-storage.
>> I do not see what the  aliasing issue could possibly be.  If you can
>> ask Doug to
>> clarify his statements, that would help.  Otherwise, I would just declare
>> there is no issue :-)
>
> I conclude from the removed text on the bottom of Page 3 that
>
>  1) pair is not generally POD
>  2) T1 and T2 in pair<T1,T2> do not have to be POD

that is correct.  But, I still don't see how that relates to aliasing.

>
> now, constructing a pair like (simplified)
>
>  pair<X, Y> *p = ::operator new(sizeof(pair<X,Y>));
>  ::new (&p->first) X(...);
>  ::new (&p->second) Y(...);
>
> will make
>
>  pair<X, Y> *p2 = ::operator new(sizeof(pair<X,Y>));
>  *p2 = *p;
>
> have the same problem as our example with POD unions.

But, unless X and Y are PODs, user code like that is already
invalid.  The reason is that the assignment will be invoking
a non-static member function on a non-existent object
(supposedly pointed to by 'p2'.)  And that has nothing to do
with the pair 'p' being constructed piecemeal.

And if X and Y are PODs (or even standard layout), I'm
not sure why the above would be equivalent to the
union problem.

I suspect the general language feature LWG was talking
about is whether it is OK for users (not just the standard
library, which is not required to be written in standard C++)
can 'inline' constructors and pretend, at the end of of the
'inlining', that they have constructed the full object.
Obviously, that should not be allowed for polymophic
types (and other fancy types), but pair<X,Y> is none of
those.  Personally, I would prefer if the core language is
not extended in that direction.  But, that is only a personal
opinion.

> Unless of course pair<X, Y> implements proper
> operator overloads to turn the assignment into
> basically
>
>  memcpy (&p2, &p, sizeof(pair<X,Y>));

The copy-and-assignment operator for pair<X,Y> used to
be compiler-generated (so, it was the compiler's responsability).
Nowadays, it has got rvalue reference to move things around.
I would expect the rvalue reference version to be equivalent
to the memcpy.

> with all the fun that arises and complicates matters if
> X and/or Y are not POD and thus not eligible to be
> copied via memcpy.

There are only two possibilities:
  (1) the assignment operator is compiler generated -- so, no problem;
       most of the time, it is memcpy; and when it is not, it is a user
       function call
  (2) the assignment is actually a move, in that case, you get a memcpy.

>
> Thus, if pair<X,Y> ensures that copies are done either
> with lvalues of type X and Y or via memcpy things
> should be fine.

I believe that is the case.

>
> Well, fine with GCC at least.

and it should be OK in the abstract model too.

>
> Richard.



More information about the Gcc-patches mailing list