[PATCH] D47108: Add -fforce-emit-vtables

Krzysztof Pszeniczny via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon May 21 05:12:30 PDT 2018


amharc requested changes to this revision.
amharc added a comment.
This revision now requires changes to proceed.

This is not sound: sometimes the forcefully emitted vtable is incorrect due to destructor aliasing. This happens e.g. in the Bullet benchmark from the llvm test suite. A simplified example follows.

For a translation unit:

  struct Base {
    virtual int foo() { return 42; }
    virtual ~Base() { }
  };
  
  struct Derived : Base {
    Derived();
  };
  
  int foo() {
    Derived *der = new Derived();
    return der->foo();
  }

it emits:

  ; Function Attrs: nounwind
  declare dso_local void @_ZN7DerivedD1Ev(%struct.Derived*) unnamed_addr #6
  
  ; Function Attrs: nounwind
  declare dso_local void @_ZN7DerivedD0Ev(%struct.Derived*) unnamed_addr #6
  
  @_ZTV7Derived = linkonce_odr dso_local unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI7Derived to i8*), i8* bitcast (i32 (%struct.Base*)* @_ZN4Base3fooEv to i8*), i8* bitcast (void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*), i8* bitcast (void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*)] }, comdat, align 8

whereas for TU:

  struct Base {
    virtual int foo() { return 42; }
    virtual ~Base() { }
  };
  
  struct Derived : Base {
    Derived();
  };
  
  Derived::Derived() { }

which emits the whole vtable (even without this patch):

  @_ZTV7Derived = linkonce_odr dso_local unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI7Derived to i8*), i8* bitcast (i32 (%struct.Base*)* @_ZN4Base3fooEv to i8*), i8* bitcast (void (%struct.Base*)* @_ZN4BaseD2Ev to i8*), i8* bitcast (void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*)] }, comdat, align 8

Please note that the complete object destructor `@_ZN7DerivedD1Ev` has been RAUWed with the base object destructor `@_ZN4BaseD2Ev`.
Since this triggers the RAUW case (as opposed to the Alias case) in `ItaniumCXXABI::emitCXXStructor`, the complete object destructor is **not** emitted at all.

Because `Derived` lacks a key function, the vtable is `linkonce_odr` and any of those definitions can be picked. Hence, this code can stop linking at the whim of the linker. :(


Repository:
  rL LLVM

https://reviews.llvm.org/D47108





More information about the cfe-commits mailing list