Commit 7eae8c6e authored by Richard Smith's avatar Richard Smith
Browse files

Don't update the vptr at the start of the destructor of a final class.

In this case, we know statically that we're destroying the most-derived
class, so the vptr must already point to the current class and never
needs to be updated.
parent 85e56589
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1424,6 +1424,11 @@ static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
  if (!ClassDecl->isDynamicClass())
    return true;

  // For a final class, the vtable pointer is known to already point to the
  // class's vtable.
  if (ClassDecl->isEffectivelyFinal())
    return true;

  if (!Dtor->hasTrivialBody())
    return false;

+34 −0
Original line number Diff line number Diff line
@@ -529,4 +529,38 @@ namespace test11 {
  }

}

namespace final_dtor {
  struct A {
    virtual void f();
    // CHECK6-LABEL: define {{.*}} @_ZN10final_dtor1AD2Ev(
    // CHECK6: store {{.*}} @_ZTV
    // CHECK6-LABEL: {{^}}}
    virtual ~A() { f(); }
  };
  struct B : A {
    // CHECK6-LABEL: define {{.*}} @_ZN10final_dtor1BD2Ev(
    // CHECK6: store {{.*}} @_ZTV
    // CHECK6-LABEL: {{^}}}
    virtual ~B() { f(); }
  };
  struct C final : A {
    // CHECK6-LABEL: define {{.*}} @_ZN10final_dtor1CD2Ev(
    // CHECK6-NOT: store {{.*}} @_ZTV
    // CHECK6-LABEL: {{^}}}
    virtual ~C() { f(); }
  };
  struct D : A {
    // CHECK6-LABEL: define {{.*}} @_ZN10final_dtor1DD2Ev(
    // CHECK6-NOT: store {{.*}} @_ZTV
    // CHECK6-LABEL: {{^}}}
    virtual ~D() final { f(); }
  };
  void use() {
    {A a;}
    {B b;}
    {C c;}
    {D d;}
  }
}
#endif