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

Bug#781060: g++-4.9: Broken optimization when move-constructing from virtual subclass



Hi Bastian,

The C++ standard does not allow the compiler to arbitrarily choose
which constructor to use.

In any case, explicitly deleting the copy constructor does not affect
the output. Moreover, the bug actually exists with the copy
constructor as well, as shown with the first modified program below.
(Of course, normally you would not modify the source object in a copy
constructor.) Finally, we can prove that the move constructor is in
fact executing by tracking which constructor was used to construct the
object, as in the second modified program below. This shows that the
move constructor did execute to initialize the new object, but simply
fails to modify the source object.

My hunch is that GCC is incorrectly deciding that the modifications to
the source object don't matter, perhaps because it's a temporary that
will be destroyed shortly anyway and GCC incorrectly decides that D's
destructor is trivial. It seems to be affected by the presence of
virtual inheritance.

-Kenton

=======copy constructors=======
#include <stdio.h>

class A {
public:
  mutable bool copied = false;

  A() = default;
  A(const A& other) {
    other.copied = true;
  }
  ~A() {
    printf("~A(): copied = %s\n", copied ? "true" : "false");
  }
};
class B: virtual public A {};
class C: virtual public B {};
class D: public C {};

int main() {
  A a = D();
}
=========================

=========tracking consturctor===============
#include <stdio.h>

class A {
public:
  bool moved = false;
  bool moveConstructed = false;

  A() = default;
  A(A&& other): moveConstructed(true) {
    other.moved = true;
  }
  ~A() {
    printf("~A(): moved = %s, moveConstructed = %s\n",
        moved ? "true" : "false",
        moveConstructed ? "true" : "false");
  }
};
class B: virtual public A {};
class C: virtual public B {};
class D: public C {};

int main() {
  A a = D();
}
=========================


On Tue, Mar 24, 2015 at 12:37 AM, Bastian Blank <waldi@debian.org> wrote:
> Moin
>
> On Mon, Mar 23, 2015 at 03:18:08PM -0700, Kenton Varda wrote:
>> The attached self-contained script will demonstrate the problem.
>
> Are you sure gcc does not use the implicit and easier copy constructor?
> I'm not sure what the standard say about this, but please explicitely
> remove the copy constructor with "A(A&) = delete", so you can
> distinguish between this two different results.
>
> Regards,
> Bastian
>
> --
> Immortality consists largely of boredom.
>                 -- Zefrem Cochrane, "Metamorphosis", stardate 3219.8


Reply to: