1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s 2f4a2713aSLionel Sambuc 3*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns > %t 4*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s 5*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s 6*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s 7*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s 8*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s 9*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t %s 10*0a6a1f1dSLionel Sambuc 11*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck --check-prefix=COFF %s 12f4a2713aSLionel Sambuc 13f4a2713aSLionel Sambuc namespace test1 { 14*0a6a1f1dSLionel Sambuc // Test that we produce the apropriate comdats when creating aliases to 15*0a6a1f1dSLionel Sambuc // weak_odr constructors and destructors. 16f4a2713aSLionel Sambuc 17*0a6a1f1dSLionel Sambuc // CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev 18*0a6a1f1dSLionel Sambuc // CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev 19*0a6a1f1dSLionel Sambuc // CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev) 20*0a6a1f1dSLionel Sambuc // CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) 21*0a6a1f1dSLionel Sambuc // CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) 22*0a6a1f1dSLionel Sambuc // CHECK1-NOT: comdat 23f4a2713aSLionel Sambuc 24*0a6a1f1dSLionel Sambuc // COFF doesn't support comdats with arbitrary names (C5/D5). 25*0a6a1f1dSLionel Sambuc // COFF-NOT: comdat 26*0a6a1f1dSLionel Sambuc 27*0a6a1f1dSLionel Sambuc template <typename T> 28*0a6a1f1dSLionel Sambuc struct foobar { foobartest1::foobar29f4a2713aSLionel Sambuc foobar() {} ~foobartest1::foobar30*0a6a1f1dSLionel Sambuc virtual ~foobar() {} 31f4a2713aSLionel Sambuc }; 32f4a2713aSLionel Sambuc 33f4a2713aSLionel Sambuc template struct foobar<void>; 34f4a2713aSLionel Sambuc } 35f4a2713aSLionel Sambuc 36f4a2713aSLionel Sambuc namespace test2 { 37f4a2713aSLionel Sambuc // test that when the destrucor is linkonce_odr we just replace every use of 38f4a2713aSLionel Sambuc // C1 with C2. 39f4a2713aSLionel Sambuc 40*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @__cxx_global_var_init() 41*0a6a1f1dSLionel Sambuc // CHECK1: call void @_ZN5test26foobarIvEC2Ev 42*0a6a1f1dSLionel Sambuc // CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev( 43f4a2713aSLionel Sambuc void g(); 44f4a2713aSLionel Sambuc template <typename T> struct foobar { foobartest2::foobar45f4a2713aSLionel Sambuc foobar() { g(); } 46f4a2713aSLionel Sambuc }; 47f4a2713aSLionel Sambuc foobar<void> x; 48f4a2713aSLionel Sambuc } 49f4a2713aSLionel Sambuc 50f4a2713aSLionel Sambuc namespace test3 { 51f4a2713aSLionel Sambuc // test that instead of an internal alias we just use the other destructor 52f4a2713aSLionel Sambuc // directly. 53f4a2713aSLionel Sambuc 54*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @__cxx_global_var_init1() 55*0a6a1f1dSLionel Sambuc // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev 56*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev( 57f4a2713aSLionel Sambuc namespace { 58f4a2713aSLionel Sambuc struct A { ~Atest3::__anon97c009620111::A59f4a2713aSLionel Sambuc ~A() {} 60f4a2713aSLionel Sambuc }; 61f4a2713aSLionel Sambuc 62f4a2713aSLionel Sambuc struct B : public A {}; 63f4a2713aSLionel Sambuc } 64f4a2713aSLionel Sambuc 65f4a2713aSLionel Sambuc B x; 66f4a2713aSLionel Sambuc } 67f4a2713aSLionel Sambuc 68f4a2713aSLionel Sambuc namespace test4 { 69f4a2713aSLionel Sambuc // Test that we don't produce aliases from B to A. We cannot because we cannot 70f4a2713aSLionel Sambuc // guarantee that they will be present in every TU. Instead, we just call 71f4a2713aSLionel Sambuc // A's destructor directly. 72f4a2713aSLionel Sambuc 73*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @__cxx_global_var_init2() 74*0a6a1f1dSLionel Sambuc // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev 75*0a6a1f1dSLionel Sambuc // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev( 76f4a2713aSLionel Sambuc 77f4a2713aSLionel Sambuc // test that we don't do this optimization at -O0 so that the debugger can 78f4a2713aSLionel Sambuc // see both destructors. 79*0a6a1f1dSLionel Sambuc // NOOPT: define internal void @__cxx_global_var_init2() 80*0a6a1f1dSLionel Sambuc // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev 81*0a6a1f1dSLionel Sambuc // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev 82f4a2713aSLionel Sambuc struct A { ~Atest4::A83f4a2713aSLionel Sambuc virtual ~A() {} 84f4a2713aSLionel Sambuc }; 85f4a2713aSLionel Sambuc struct B : public A{ ~Btest4::B86f4a2713aSLionel Sambuc ~B() {} 87f4a2713aSLionel Sambuc }; 88f4a2713aSLionel Sambuc B X; 89f4a2713aSLionel Sambuc } 90f4a2713aSLionel Sambuc 91f4a2713aSLionel Sambuc namespace test5 { 92f4a2713aSLionel Sambuc // similar to test4, but with an internal B. 93f4a2713aSLionel Sambuc 94*0a6a1f1dSLionel Sambuc // CHECK2: define internal void @__cxx_global_var_init3() 95*0a6a1f1dSLionel Sambuc // CHECK2: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev 96*0a6a1f1dSLionel Sambuc // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev( 97f4a2713aSLionel Sambuc struct A { ~Atest5::A98f4a2713aSLionel Sambuc virtual ~A() {} 99f4a2713aSLionel Sambuc }; 100f4a2713aSLionel Sambuc namespace { 101f4a2713aSLionel Sambuc struct B : public A{ ~Btest5::__anon97c009620211::B102f4a2713aSLionel Sambuc ~B() {} 103f4a2713aSLionel Sambuc }; 104f4a2713aSLionel Sambuc } 105f4a2713aSLionel Sambuc B X; 106f4a2713aSLionel Sambuc } 107f4a2713aSLionel Sambuc 108f4a2713aSLionel Sambuc namespace test6 { 109f4a2713aSLionel Sambuc // Test that we use ~A directly, even when ~A is not defined. The symbol for 110f4a2713aSLionel Sambuc // ~B would have been internal and still contain a reference to ~A. 111f4a2713aSLionel Sambuc struct A { 112f4a2713aSLionel Sambuc virtual ~A(); 113f4a2713aSLionel Sambuc }; 114f4a2713aSLionel Sambuc namespace { 115f4a2713aSLionel Sambuc struct B : public A { ~Btest6::__anon97c009620311::B116f4a2713aSLionel Sambuc ~B() {} 117f4a2713aSLionel Sambuc }; 118f4a2713aSLionel Sambuc } 119f4a2713aSLionel Sambuc B X; 120*0a6a1f1dSLionel Sambuc // CHECK3: define internal void @__cxx_global_var_init4() 121*0a6a1f1dSLionel Sambuc // CHECK3: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev 122f4a2713aSLionel Sambuc } 123f4a2713aSLionel Sambuc 124f4a2713aSLionel Sambuc namespace test7 { 125f4a2713aSLionel Sambuc // Test that we don't produce an alias from ~B to ~A<int> (or crash figuring 126f4a2713aSLionel Sambuc // out if we should). 127f4a2713aSLionel Sambuc // pr17875. 128*0a6a1f1dSLionel Sambuc // CHECK3: define void @_ZN5test71BD2Ev 129f4a2713aSLionel Sambuc template <typename> struct A { ~Atest7::A130f4a2713aSLionel Sambuc ~A() {} 131f4a2713aSLionel Sambuc }; 132f4a2713aSLionel Sambuc class B : A<int> { 133f4a2713aSLionel Sambuc ~B(); 134f4a2713aSLionel Sambuc }; 135f4a2713aSLionel Sambuc template class A<int>; ~B()136f4a2713aSLionel Sambuc B::~B() {} 137f4a2713aSLionel Sambuc } 138f4a2713aSLionel Sambuc 139f4a2713aSLionel Sambuc namespace test8 { 140f4a2713aSLionel Sambuc // Test that we replace ~zed with ~bar which is an alias to ~foo. 141*0a6a1f1dSLionel Sambuc // CHECK4: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev 142*0a6a1f1dSLionel Sambuc // CHECK4: define internal void @__cxx_global_var_init5() 143*0a6a1f1dSLionel Sambuc // CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev 144f4a2713aSLionel Sambuc struct foo { 145f4a2713aSLionel Sambuc ~foo(); 146f4a2713aSLionel Sambuc }; ~foo()147f4a2713aSLionel Sambuc foo::~foo() {} 148f4a2713aSLionel Sambuc struct bar : public foo { 149f4a2713aSLionel Sambuc ~bar(); 150f4a2713aSLionel Sambuc }; ~bar()151f4a2713aSLionel Sambuc bar::~bar() {} 152f4a2713aSLionel Sambuc struct zed : public bar {}; 153f4a2713aSLionel Sambuc zed foo; 154f4a2713aSLionel Sambuc } 155f4a2713aSLionel Sambuc 156*0a6a1f1dSLionel Sambuc namespace test9 { 157*0a6a1f1dSLionel Sambuc struct foo { ~footest9::foo158*0a6a1f1dSLionel Sambuc __attribute__((stdcall)) ~foo() { 159*0a6a1f1dSLionel Sambuc } 160*0a6a1f1dSLionel Sambuc }; 161*0a6a1f1dSLionel Sambuc 162*0a6a1f1dSLionel Sambuc struct bar : public foo {}; 163*0a6a1f1dSLionel Sambuc zed()164*0a6a1f1dSLionel Sambucvoid zed() { 165*0a6a1f1dSLionel Sambuc // Test that we produce a call to bar's destructor. We used to call foo's, but 166*0a6a1f1dSLionel Sambuc // it has a different calling conversion. 167*0a6a1f1dSLionel Sambuc // CHECK4: call void @_ZN5test93barD2Ev 168*0a6a1f1dSLionel Sambuc bar ptr; 169*0a6a1f1dSLionel Sambuc } 170*0a6a1f1dSLionel Sambuc } 171*0a6a1f1dSLionel Sambuc 172*0a6a1f1dSLionel Sambuc // CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}] 173f4a2713aSLionel Sambuc // r194296 replaced C::~C with B::~B without emitting the later. 174f4a2713aSLionel Sambuc 175f4a2713aSLionel Sambuc class A { 176f4a2713aSLionel Sambuc public: 177f4a2713aSLionel Sambuc A(int); 178f4a2713aSLionel Sambuc virtual ~A(); 179f4a2713aSLionel Sambuc }; 180f4a2713aSLionel Sambuc 181f4a2713aSLionel Sambuc template <class> 182f4a2713aSLionel Sambuc class B : A { 183f4a2713aSLionel Sambuc public: B()184f4a2713aSLionel Sambuc B() 185f4a2713aSLionel Sambuc : A(0) { 186f4a2713aSLionel Sambuc } ~B()187f4a2713aSLionel Sambuc __attribute__((always_inline)) ~B() { 188f4a2713aSLionel Sambuc } 189f4a2713aSLionel Sambuc }; 190f4a2713aSLionel Sambuc 191f4a2713aSLionel Sambuc extern template class B<char>; 192f4a2713aSLionel Sambuc 193f4a2713aSLionel Sambuc class C : B<char> { 194f4a2713aSLionel Sambuc }; 195f4a2713aSLionel Sambuc 196f4a2713aSLionel Sambuc void fn1()197f4a2713aSLionel Sambucfn1() { 198f4a2713aSLionel Sambuc new C; 199f4a2713aSLionel Sambuc } 200*0a6a1f1dSLionel Sambuc 201*0a6a1f1dSLionel Sambuc namespace test10 { 202*0a6a1f1dSLionel Sambuc // Test that if a destructor is in a comdat, we don't try to emit is as an 203*0a6a1f1dSLionel Sambuc // alias to a base class destructor. 204*0a6a1f1dSLionel Sambuc struct bar { 205*0a6a1f1dSLionel Sambuc ~bar(); 206*0a6a1f1dSLionel Sambuc }; ~bar()207*0a6a1f1dSLionel Sambucbar::~bar() { 208*0a6a1f1dSLionel Sambuc } 209*0a6a1f1dSLionel Sambuc } // closing the namespace causes ~bar to be sent to CodeGen 210*0a6a1f1dSLionel Sambuc namespace test10 { 211*0a6a1f1dSLionel Sambuc template <typename T> 212*0a6a1f1dSLionel Sambuc struct foo : public bar { 213*0a6a1f1dSLionel Sambuc ~foo(); 214*0a6a1f1dSLionel Sambuc }; 215*0a6a1f1dSLionel Sambuc template <typename T> ~foo()216*0a6a1f1dSLionel Sambucfoo<T>::~foo() {} 217*0a6a1f1dSLionel Sambuc template class foo<int>; 218*0a6a1f1dSLionel Sambuc // CHECK5: define weak_odr void @_ZN6test103fooIiED2Ev({{.*}} comdat($_ZN6test103fooIiED5Ev) 219*0a6a1f1dSLionel Sambuc } 220*0a6a1f1dSLionel Sambuc 221*0a6a1f1dSLionel Sambuc namespace test11 { 222*0a6a1f1dSLionel Sambuc // Test that when we don't have to worry about COMDATs we produce an alias 223*0a6a1f1dSLionel Sambuc // from complate to base and from base to base class base. 224*0a6a1f1dSLionel Sambuc struct bar { 225*0a6a1f1dSLionel Sambuc ~bar(); 226*0a6a1f1dSLionel Sambuc }; ~bar()227*0a6a1f1dSLionel Sambucbar::~bar() {} 228*0a6a1f1dSLionel Sambuc struct foo : public bar { 229*0a6a1f1dSLionel Sambuc ~foo(); 230*0a6a1f1dSLionel Sambuc }; ~foo()231*0a6a1f1dSLionel Sambucfoo::~foo() {} 232*0a6a1f1dSLionel Sambuc // CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev 233*0a6a1f1dSLionel Sambuc // CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev 234*0a6a1f1dSLionel Sambuc } 235*0a6a1f1dSLionel Sambuc 236*0a6a1f1dSLionel Sambuc namespace test12 { 237*0a6a1f1dSLionel Sambuc template <int> 238*0a6a1f1dSLionel Sambuc struct foo { ~footest12::foo239*0a6a1f1dSLionel Sambuc ~foo() { delete this; } 240*0a6a1f1dSLionel Sambuc }; 241*0a6a1f1dSLionel Sambuc 242*0a6a1f1dSLionel Sambuc template class foo<1>; 243*0a6a1f1dSLionel Sambuc // CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr alias {{.*}} @_ZN6test123fooILi1EED2Ev 244*0a6a1f1dSLionel Sambuc // CHECK6: define weak_odr void @_ZN6test123fooILi1EED2Ev({{.*}}) {{.*}} comdat($_ZN6test123fooILi1EED5Ev) 245*0a6a1f1dSLionel Sambuc } 246