Re: Possible GCC bug with copy-construction of object on itself?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 02/08/2018 06:57 AM, Ole Kniemeyer wrote:
Hi,

I have a small code snippet where I'm not sure if it's a GCC bug or undefined behaviour, so maybe
someone can help? The code is

#include <new>

void Func(void*);

struct A
{
  A() = default;
  A(const A& src)
  {
    Func(src.x);
  }

  void* x;
};

void Test(void* ptr)
{
  A tmp;
  tmp.x = ptr;
  new (&tmp) A(tmp);
}

If you paste this code at gcc.godbolt.org and use -O3, GCC <= 5.X and Clang produce the code which
I'd expect:

Test(void*):
  jmp Func(void*)

But GCC 6 and 7 call Func with a nullptr:

Test(void*):
  xorl %edi, %edi
  jmp Func(void*)

I admit that the code is a bit dubious because it copy-constructs a new A object with itself and
the copy constructor doesn't copy anything, so is this undefined behavior or a GCC bug?

I think it's undefined.  If it were to be well-defined then
the copy constructor of every non-trivial type would have
to worry about self-copying not just the way copy assignment
does, but it would also have to create a temporary copy of
its argument before constructing self to avoid clobbering it.
That's a catch-22.

Martin

PS Here's a small test case where GCC detects the undefined
behavior and complains that x i uninitialized.  The change
was introduced in GCC 6 via r222135.  The change description
explains why:

	* constexpr.c (cxx_eval_store_expression): Ignore clobbers.
	(build_constexpr_constructor_member_initializers): Loop to find
	the BIND_EXPR.
	* decl.c (start_preparsed_function): Clobber the object at the
	beginning of a constructor.

The constructor marks the object under construction as clobbered
which the -Wuninitialized checker notices.

void* operator new (__SIZE_TYPE__, void *p) { return p; }

struct A
{
  A() = default;
  A(const A& src) {
    x = src.x;
  }

  void* x;
};

void* Test(void* ptr)
{
  A tmp;
  tmp.x = ptr;
  new (&tmp) A(tmp);
  return tmp.x;
}

u.C:18:14: warning: ‘tmp.A::x’ is used uninitialized in this function [-Wuninitialized]
   return tmp.x;
              ^




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux