This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++17 std::launder and aliasing


On 24/10/16 10:18 +0200, Richard Biener wrote:
On Mon, 24 Oct 2016, Ville Voutilainen wrote:

On 24 October 2016 at 10:41, Richard Biener <rguenther@suse.de> wrote:
>> Seems that testcase is devirtualization related.
>> With -O3 -fno-devirtualize we return 3 (but still no calls).
>> With asm ("" : "+g" (p)); before return p; in launder we don't devirtualize
>> it any more and return 3 in the end.  Is the testcase only valid
>> with std::launder and not valid otherwise (I hope so, otherwise we are in
>> big trouble with devirtualization)?
>
> I believe the testcase shows a bug in devirtualization.  (stpuid
> godbolt.org having no way to textually extract the source easily)
>
> Please file a GCC bugreport.  GCC shouldn't miscompile this even
> without std::launder.


Note that A::f() can be in a different translation unit, so we still
need the optimization
barrier in some cases, even if in this particular case as written we wouldn't.

Well, if it is valid to construct a new object in place of *this in
a virtual function call on this then GCC has an issue regardless of
std::launder.  So, for

{
  A a;
  A::f ();
}

where does the _FE_ get the knowledge what destructor to call?  IIRC
we "devirtualize" destructor calls in this case as well.

struct B {
   virtual ~B();
};
struct A : B {
   virtual ~A();
   void foo ();
};

int foo ()
{
 A a;
 a.foo();
}


foo ends up calling A::~A() with GCC 6.

How do I launder a here?

This example has undefined behaviour even if you add std::launder. The
original example doesn't.

The difference is 3.8 [basic.life] paragraph 9, which says that if the
program ends the lifetime of the automatic object 'a' then it must
ensure that another object of the same type occupies the same storage
when the implicit destructor runs. So the original example is OK
because it ends the lifetime of the original object by creating a B at
the same location, but then creates another A there, so the implicit
destructor call to A::~A() is valid, because there is an A at that
location.

I don't think we have a bug, or a defect, in the absence of
std::launder. Without std::launder our devirtualization is OK.

Again, std::launder(&a) is not the same as &a, so if we simply fold
std::launder(&a) to &a we allow devirtualization through the pointer
as though it was still a pointer to the original object &a, and that's
what std::launder is supposed to prevent.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]