[cxx-abi-dev] Guaranteed copy elision and tail padding

John McCall rjmccall at apple.com
Thu Jul 21 20:34:06 UTC 2016


> On Jul 21, 2016, at 1:20 PM, Jason Merrill <jason at redhat.com> wrote:
> On Thu, Jul 21, 2016 at 2:45 PM, Richard Smith
> <richardsmith at googlers.com> wrote:
>> On 21 July 2016 at 11:02, Jason Merrill <jason at redhat.com> wrote:
>>> 
>>> P0135 seems to require that we elide the copy when using the result of
>>> a function returning by value to initialize a base class subobject,
>>> but the ABI doesn't currently require that such a function avoid
>>> clobbering tail padding when initializing its return object.
>>> Thoughts?
>> 
>> If the function clobbers the tail padding of its return object, at least GCC
>> and Clang will miscompile the program today, without P0135:
>> 
>> #include <string.h>
>> struct X { ~X() {} int n; char d; };
>> struct Y { Y(); char c[3]; };
>> struct Z : X, virtual Y { Z(); };
>> 
>> X f() { X nrvo; memset(&nrvo, 0, sizeof(X)); return nrvo; }
>> Z::Z() : Y(), X(f()) {}
>> Y::Y() : c{1, 2, 3} {}
>> 
>> int main() {
>>  Z z;
>>  return z.c[0];
>> }
>> 
>> GCC -O0 returns 1 from main, as it should. GCC -O2 and Clang (any
>> optimization level, even with -fno-elide-constructors) returns 0.
> 
> Thanks for the testcase.
> 
>> (It looks like Clang gets this "wrong" in two ways: first, NRVO is apprently
>> never correct on a type whose tail padding could be reused
> 
> Hmm, I was thinking that the NRVO was fine, but the caller shouldn't
> elide the copy because the function might clobber tail padding.  But
> that gets back to my initial question, since P0135 requires that
> elision.  Avoiding NRVO here doesn't conflict with P0135, but it does
> create a new ABI requirement that existing code might violate.

P0135 is broken and cannot be implemented as written.  Given that we're telling
the committee to fix it, we should ask for something that we think can be
reasonably implemented with acceptable backwards compatibility.  We should
not be encouraging implementations to avoid NRVO.

It seems to me that the bug is that implementations should not be evaluating
call results in-place into base sub-objects that have tail padding that might be reused.

John.


More information about the cxx-abi-dev mailing list