On Thu, 4 Jun 2020, Ville Voutilainen wrote:

On Thu, 4 Jun 2020 at 11:53, Marc Glisse <marc.gli...@inria.fr> wrote:

On Thu, 4 Jun 2020, Ville Voutilainen wrote:

On Thu, 4 Jun 2020 at 11:00, Marc Glisse <marc.gli...@inria.fr> wrote:
Maybe create a buffer, fill it with some non-zero values (-1?), then call
placement new, and read some value in the middle of the buffer, possibly
with some protection against optimizations? Ah, no, actual constructors
are fine, it is only the inlined initialization that happens with the
defaulted constructor that zeroes things.

The zero-init is part of value-initialization of a class type with a
defaulted default constructor, so value-initialization with placement
new should indeed show us whether the target buffer is zeroed.

Ah, yes, I had forgotten the empty () at the end of the operator new line
when testing. Now the patch makes this runtime test go from abort to
success at -O0 (with optimizations, the memset is removed as dead code). I
am still not sure we want this kind of test though. And I added launder
more to quiet a warning than with confidence that it does the right thing.

#include <optional>
struct A {
   int a[1024];
};
typedef std::optional<A> O;
int main(){
   unsigned char t[sizeof(O)];
   __builtin_memset(t, -1, sizeof(t));
   new(t)O();
   if(std::launder(t)[512] != (unsigned char)(-1)) __builtin_abort();
}

Yeah, I think the patch is OK with or without the test. As a side
note, you don't need the launder
if the check uses the pointer value returned by placement-new.

Yes, -fno-lifetime-dse is a better way to quiet the warning if
optimizations are enabled and documents why this test is unsafe. Here is
a version closer to what could go in the testsuite, although I'd still
rather not add it at this point. We'll see what Jonathan thinks.
(I didn't test this exact version)

// { dg-options "-std=gnu++17 -fno-lifetime-dse" }
// { dg-do run { target c++17 } }

#include <optional>
#include <testsuite_hooks.h>

struct A
{
  int a[1024];
};
typedef std::optional<A> O;

void
test01()
{
  unsigned char t[sizeof(O)];
  __builtin_memset(t, -1, sizeof(t));
  new (t) O();
  VERIFY( t[512] == (unsigned char)(-1) );
}

int
main()
{
  test01();
}


--
Marc Glisse

Reply via email to