destructors.cpp revision 4b662a5684d41ea4ff6b52711929e00fefb00db1
1// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fexceptions | FileCheck %s 2 3// CHECK: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev 4// CHECK: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev 5// CHECK: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev 6// CHECK: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev 7// CHECK: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev 8 9// CHECK: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev 10// CHECK: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev 11// CHECK: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev 12 13struct A { 14 int a; 15 16 ~A(); 17}; 18 19// Base with non-trivial destructor 20struct B : A { 21 ~B(); 22}; 23 24B::~B() { } 25 26// Field with non-trivial destructor 27struct C { 28 A a; 29 30 ~C(); 31}; 32 33C::~C() { } 34 35// PR5084 36template<typename T> 37class A1 { 38 ~A1(); 39}; 40 41template<> A1<char>::~A1(); 42 43// PR5529 44namespace PR5529 { 45 struct A { 46 ~A(); 47 }; 48 49 A::~A() { } 50 struct B : A { 51 virtual ~B(); 52 }; 53 54 B::~B() {} 55} 56 57// FIXME: there's a known problem in the codegen here where, if one 58// destructor throws, the remaining destructors aren't run. Fix it, 59// then make this code check for it. 60namespace test0 { 61 void foo(); 62 struct VBase { ~VBase(); }; 63 struct Base { ~Base(); }; 64 struct Member { ~Member(); }; 65 66 struct A : Base { 67 Member M; 68 ~A(); 69 }; 70 71 // The function-try-block won't suppress -mconstructor-aliases here. 72 A::~A() try { } catch (int i) {} 73 74// complete destructor alias tested above 75 76// CHECK: define void @_ZN5test01AD2Ev 77// CHECK: invoke void @_ZN5test06MemberD1Ev 78// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] 79// CHECK: invoke void @_ZN5test04BaseD2Ev 80// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] 81 82 struct B : Base, virtual VBase { 83 Member M; 84 ~B(); 85 }; 86 B::~B() try { } catch (int i) {} 87 // It will suppress the delegation optimization here, though. 88 89// CHECK: define void @_ZN5test01BD1Ev 90// CHECK: invoke void @_ZN5test06MemberD1Ev 91// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] 92// CHECK: invoke void @_ZN5test04BaseD2Ev 93// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] 94// CHECK: invoke void @_ZN5test05VBaseD2Ev 95// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] 96 97// CHECK: define void @_ZN5test01BD2Ev 98// CHECK: invoke void @_ZN5test06MemberD1Ev 99// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] 100// CHECK: invoke void @_ZN5test04BaseD2Ev 101// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] 102} 103 104// Test base-class aliasing. 105namespace test1 { 106 struct A { ~A(); char ***m; }; // non-trivial destructor 107 struct B { ~B(); }; // non-trivial destructor 108 struct Empty { }; // trivial destructor, empty 109 struct NonEmpty { int x; }; // trivial destructor, non-empty 110 111 // There must be a definition in this translation unit for the alias 112 // optimization to apply. 113 A::~A() { delete m; } 114 115 struct M : A { ~M(); }; 116 M::~M() {} // alias tested above 117 118 struct N : A, Empty { ~N(); }; 119 N::~N() {} // alias tested above 120 121 struct O : Empty, A { ~O(); }; 122 O::~O() {} // alias tested above 123 124 struct P : NonEmpty, A { ~P(); }; 125 P::~P() {} // CHECK: define void @_ZN5test11PD2Ev 126 127 struct Q : A, B { ~Q(); }; 128 Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev 129 130 struct R : A { ~R(); }; 131 R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev 132 133 struct S : A { ~S(); int x; }; 134 S::~S() {} // alias tested above 135 136 struct T : A { ~T(); B x; }; 137 T::~T() {} // CHECK: define void @_ZN5test11TD2Ev 138 139 // The VTT parameter prevents this. We could still make this work 140 // for calling conventions that are safe against extra parameters. 141 struct U : A, virtual B { ~U(); }; 142 U::~U() {} // CHECK: define void @_ZN5test11UD2Ev 143} 144 145// PR6471 146namespace test2 { 147 struct A { ~A(); char ***m; }; 148 struct B : A { ~B(); }; 149 150 B::~B() {} 151 // CHECK: define void @_ZN5test21BD2Ev 152 // CHECK: call void @_ZN5test21AD2Ev 153} 154 155// PR7142 156namespace test3 { 157 struct A { virtual ~A(); }; 158 struct B { virtual ~B(); }; 159 namespace { // internal linkage => deferred 160 struct C : A, B {}; // ~B() in D requires a this-adjustment thunk 161 struct D : C {}; // D::~D() is an alias to C::~C() 162 } 163 164 void test() { 165 new D; // Force emission of D's vtable 166 } 167 168 // Checked at top of file: 169 // @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev 170 171 // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( 172 // CHECK: call void @_ZN5test31BD2Ev( 173 // CHECK: call void @_ZN5test31AD2Ev( 174 // CHECK: ret void 175 176 // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev( 177 // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev( 178 // CHECK: call void @_ZdlPv( 179 // CHECK: ret void 180 181 // Checked at top of file: 182 // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev 183 // @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev 184 185 // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev( 186 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 187 // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev( 188 // CHECK: ret void 189 190 // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev( 191 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 192 // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev( 193 // CHECK: ret void 194 195 // CHECK: declare void @_ZN5test31BD2Ev( 196 // CHECK: declare void @_ZN5test31AD2Ev( 197 198 // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev( 199 // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev( 200 // CHECK: call void @_ZdlPv( 201 // CHECK: ret void 202 203 // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( 204 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 205 // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev( 206 // CHECK: ret void 207 208 // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev( 209 // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 210 // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev( 211 // CHECK: ret void 212} 213