There are situations when clang knows that the C1 and C2 constructors or the D1 and D2 destructors are identical. We already optimize some of these cases, but cannot optimize it when the GlobalValue is weak_odr. The problem with weak_odr is that an old TU seeing the same code will have a C1 and a C2 comdat with the corresponding symbols. We cannot suddenly start putting the C2 symbol in the C1 comdat as we cannot guarantee that the linker will not pick a .o with only C1 in it. The solution implemented by GCC is to expand the ABI to have a comdat whose name uses a C5/D5 suffix and always has both symbols. That is what this patch implements. llvm-svn: 217874
60 lines
1.5 KiB
C++
60 lines
1.5 KiB
C++
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
|
|
|
|
struct Member {
|
|
~Member();
|
|
};
|
|
|
|
struct A {
|
|
virtual ~A();
|
|
};
|
|
|
|
struct B : A {
|
|
Member m;
|
|
virtual ~B();
|
|
};
|
|
|
|
// Complete dtor: just an alias because there are no virtual bases.
|
|
// CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
|
|
|
|
// (aliases from C)
|
|
// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
|
|
// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
|
|
|
|
// Base dtor: actually calls A's base dtor.
|
|
// CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
|
|
// CHECK: call void @_ZN6MemberD1Ev
|
|
// CHECK: call void @_ZN1AD2Ev
|
|
|
|
// Deleting dtor: defers to the complete dtor.
|
|
// CHECK-LABEL: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr
|
|
// CHECK: call void @_ZN1BD1Ev
|
|
// CHECK: call void @_ZdlPv
|
|
|
|
B::~B() { }
|
|
|
|
struct C : B {
|
|
~C();
|
|
};
|
|
|
|
C::~C() { }
|
|
|
|
// Complete dtor: just an alias (checked above).
|
|
|
|
// Deleting dtor: defers to the complete dtor.
|
|
// CHECK-LABEL: define void @_ZN1CD0Ev(%struct.C* %this) unnamed_addr
|
|
// CHECK: call void @_ZN1CD1Ev
|
|
// CHECK: call void @_ZdlPv
|
|
|
|
// Base dtor: just an alias to B's base dtor.
|
|
|
|
namespace PR12798 {
|
|
// A qualified call to a base class destructor should not undergo virtual
|
|
// dispatch. Template instantiation used to lose the qualifier.
|
|
struct A { virtual ~A(); };
|
|
template<typename T> void f(T *p) { p->A::~A(); }
|
|
|
|
// CHECK: define {{.*}} @_ZN7PR127981fINS_1AEEEvPT_(
|
|
// CHECK: call void @_ZN7PR127981AD1Ev(
|
|
template void f(A*);
|
|
}
|