1 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s 2 3 // See Test9 for test description. 4 // CHECK: @_ZTTN5Test91BE = linkonce_odr unnamed_addr constant 5 namespace Test1 { 6 7 // Check that we don't initialize the vtable pointer in A::~A(), since the destructor body is trivial. 8 struct A { 9 virtual void f(); 10 ~A(); 11 }; 12 13 // CHECK-LABEL: define void @_ZN5Test11AD2Ev 14 // CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2), i8*** 15 A::~A() 16 { 17 } 18 19 } 20 21 namespace Test2 { 22 23 // Check that we do initialize the vtable pointer in A::~A() since the destructor body isn't trivial. 24 struct A { 25 virtual void f(); 26 ~A(); 27 }; 28 29 // CHECK-LABEL: define void @_ZN5Test21AD2Ev 30 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2), i8*** 31 A::~A() { 32 f(); 33 } 34 35 } 36 37 namespace Test3 { 38 39 // Check that we don't initialize the vtable pointer in A::~A(), since the destructor body is trivial 40 // and Field's destructor body is also trivial. 41 struct Field { 42 ~Field() { } 43 }; 44 45 struct A { 46 virtual void f(); 47 ~A(); 48 49 Field field; 50 }; 51 52 // CHECK-LABEL: define void @_ZN5Test31AD2Ev 53 // CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2), i8*** 54 A::~A() { 55 56 } 57 58 } 59 60 namespace Test4 { 61 62 // Check that we do initialize the vtable pointer in A::~A(), since Field's destructor body 63 // isn't trivial. 64 65 void f(); 66 67 struct Field { 68 ~Field() { f(); } 69 }; 70 71 struct A { 72 virtual void f(); 73 ~A(); 74 75 Field field; 76 }; 77 78 // CHECK-LABEL: define void @_ZN5Test41AD2Ev 79 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2), i8*** 80 A::~A() 81 { 82 } 83 84 } 85 86 namespace Test5 { 87 88 // Check that we do initialize the vtable pointer in A::~A(), since Field's destructor isn't 89 // available in this translation unit. 90 91 struct Field { 92 ~Field(); 93 }; 94 95 struct A { 96 virtual void f(); 97 ~A(); 98 99 Field field; 100 }; 101 102 // CHECK-LABEL: define void @_ZN5Test51AD2Ev 103 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2), i8*** 104 A::~A() 105 { 106 } 107 108 } 109 110 namespace Test6 { 111 112 // Check that we do initialize the vtable pointer in A::~A(), since Field has a member 113 // variable with a non-trivial destructor body. 114 115 struct NonTrivialDestructorBody { 116 ~NonTrivialDestructorBody(); 117 }; 118 119 struct Field { 120 NonTrivialDestructorBody nonTrivialDestructorBody; 121 }; 122 123 struct A { 124 virtual void f(); 125 ~A(); 126 127 Field field; 128 }; 129 130 // CHECK-LABEL: define void @_ZN5Test61AD2Ev 131 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2), i8*** 132 A::~A() 133 { 134 } 135 136 } 137 138 namespace Test7 { 139 140 // Check that we do initialize the vtable pointer in A::~A(), since Field has a base 141 // class with a non-trivial destructor body. 142 143 struct NonTrivialDestructorBody { 144 ~NonTrivialDestructorBody(); 145 }; 146 147 struct Field : NonTrivialDestructorBody { }; 148 149 struct A { 150 virtual void f(); 151 ~A(); 152 153 Field field; 154 }; 155 156 // CHECK-LABEL: define void @_ZN5Test71AD2Ev 157 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2), i8*** 158 A::~A() 159 { 160 } 161 162 } 163 164 namespace Test8 { 165 166 // Check that we do initialize the vtable pointer in A::~A(), since Field has a virtual base 167 // class with a non-trivial destructor body. 168 169 struct NonTrivialDestructorBody { 170 ~NonTrivialDestructorBody(); 171 }; 172 173 struct Field : virtual NonTrivialDestructorBody { }; 174 175 struct A { 176 virtual void f(); 177 ~A(); 178 179 Field field; 180 }; 181 182 // CHECK-LABEL: define void @_ZN5Test81AD2Ev 183 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2), i8*** 184 A::~A() 185 { 186 } 187 188 } 189 190 namespace Test9 { 191 192 // Check that we emit a VTT for B, even though we don't initialize the vtable pointer in the destructor. 193 struct A { virtual ~A () { } }; 194 struct B : virtual A {}; 195 struct C : virtual B { 196 virtual ~C(); 197 }; 198 C::~C() {} 199 200 } 201