Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t
      2 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns
      3 // RUN: FileCheck %s < %t
      4 // RUN: FileCheck %s < %t.opt
      5 // RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
      6 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
      7 
      8 namespace Test1 {
      9 
     10 // Check that we emit a non-virtual thunk for C::f.
     11 
     12 struct A {
     13   virtual void f();
     14 };
     15 
     16 struct B {
     17   virtual void f();
     18 };
     19 
     20 struct C : A, B {
     21   virtual void c();
     22 
     23   virtual void f();
     24 };
     25 
     26 // CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv(
     27 void C::f() { }
     28 
     29 }
     30 
     31 namespace Test2 {
     32 
     33 // Check that we emit a thunk for B::f since it's overriding a virtual base.
     34 
     35 struct A {
     36   virtual void f();
     37 };
     38 
     39 struct B : virtual A {
     40   virtual void b();
     41   virtual void f();
     42 };
     43 
     44 // CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv(
     45 void B::f() { }
     46 
     47 }
     48 
     49 namespace Test3 {
     50 
     51 // Check that we emit a covariant thunk for B::f.
     52 
     53 struct V1 { };
     54 struct V2 : virtual V1 { };
     55 
     56 struct A {
     57   virtual V1 *f();
     58 };
     59 
     60 struct B : A {
     61   virtual void b();
     62 
     63   virtual V2 *f();
     64 };
     65 
     66 // CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv(
     67 V2 *B::f() { return 0; }
     68 
     69 }
     70 
     71 namespace Test4 {
     72 
     73 // Check that the thunk for 'C::f' has the same visibility as the function itself.
     74 
     75 struct A {
     76   virtual void f();
     77 };
     78 
     79 struct B {
     80   virtual void f();
     81 };
     82 
     83 struct __attribute__((visibility("protected"))) C : A, B {
     84   virtual void c();
     85 
     86   virtual void f();
     87 };
     88 
     89 // CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv(
     90 void C::f() { }
     91 
     92 }
     93 
     94 // Check that the thunk gets internal linkage.
     95 namespace Test4B {
     96   struct A {
     97     virtual void f();
     98   };
     99 
    100   struct B {
    101     virtual void f();
    102   };
    103 
    104   namespace {
    105     struct C : A, B {
    106       virtual void c();
    107       virtual void f();
    108     };
    109   }
    110   void C::c() {}
    111   void C::f() {}
    112 
    113   // Force C::f to be used.
    114   void f() {
    115     C c;
    116     c.f();
    117   }
    118 }
    119 
    120 namespace Test5 {
    121 
    122 // Check that the thunk for 'B::f' gets the same linkage as the function itself.
    123 struct A {
    124   virtual void f();
    125 };
    126 
    127 struct B : virtual A {
    128   virtual void f() { }
    129 };
    130 
    131 void f(B b) {
    132   b.f();
    133 }
    134 }
    135 
    136 namespace Test6 {
    137   struct X {
    138     X();
    139     X(const X&);
    140     X &operator=(const X&);
    141     ~X();
    142   };
    143 
    144   struct P {
    145     P();
    146     P(const P&);
    147     ~P();
    148     X first;
    149     X second;
    150   };
    151 
    152   P getP();
    153 
    154   struct Base1 {
    155     int i;
    156 
    157     virtual X f() { return X(); }
    158   };
    159 
    160   struct Base2 {
    161     float real;
    162 
    163     virtual X f() { return X(); }
    164   };
    165 
    166   struct Thunks : Base1, Base2 {
    167     long l;
    168 
    169     virtual X f();
    170   };
    171 
    172   // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
    173   // CHECK-NOT: memcpy
    174   // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
    175   // CHECK: ret void
    176   X Thunks::f() { return X(); }
    177 }
    178 
    179 namespace Test7 {
    180   // PR7188
    181   struct X {
    182     X();
    183     X(const X&);
    184     X &operator=(const X&);
    185     ~X();
    186   };
    187 
    188   struct Small { short s; };
    189   struct Large {
    190     char array[1024];
    191   };
    192 
    193   class A {
    194   protected:
    195     virtual void foo() = 0;
    196   };
    197 
    198   class B : public A {
    199   protected:
    200     virtual void bar() = 0;
    201   };
    202 
    203   class C : public A  {
    204   protected:
    205     virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
    206   };
    207 
    208   class D : public B,
    209             public C {
    210 
    211     void foo() {}
    212     void bar() {}
    213     void baz(X, X&, _Complex float, Small, Small&, Large);
    214   };
    215 
    216   void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
    217 
    218   // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
    219   // CHECK-NOT: memcpy
    220   // CHECK: ret void
    221   void testD() { D d; }
    222 }
    223 
    224 namespace Test8 {
    225   struct NonPOD { ~NonPOD(); int x, y, z; };
    226   struct A { virtual void foo(); };
    227   struct B { virtual void bar(NonPOD); };
    228   struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
    229 
    230   // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
    231   void C::helper(NonPOD var) {}
    232 
    233   // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
    234   // CHECK-NOT: load [[NONPODTYPE]], [[NONPODTYPE]]*
    235   // CHECK-NOT: memcpy
    236   // CHECK: ret void
    237   void C::bar(NonPOD var) {}
    238 }
    239 
    240 // PR7241: Emitting thunks for a method shouldn't require the vtable for
    241 // that class to be emitted.
    242 namespace Test9 {
    243   struct A { virtual ~A() { } };
    244   struct B : A { virtual void test() const {} };
    245   struct C : B { C(); ~C(); };
    246   struct D : C { D() {} };
    247   void test() {
    248     D d;
    249   }
    250 }
    251 
    252 namespace Test10 {
    253   struct A { virtual void foo(); };
    254   struct B { virtual void foo(); };
    255   struct C : A, B { void foo() {} };
    256 
    257   // Test later.
    258   void test() {
    259     C c;
    260   }
    261 }
    262 
    263 // PR7611
    264 namespace Test11 {
    265   struct A {             virtual A* f(); };
    266   struct B : virtual A { virtual A* f(); };
    267   struct C : B         { virtual C* f(); };
    268   C* C::f() { return 0; }
    269 
    270   //  C::f itself.
    271   // CHECK: define {{.*}} @_ZN6Test111C1fEv(
    272 
    273   //  The this-adjustment and return-adjustment thunk required when
    274   //  C::f appears in a vtable where A is at a nonzero offset from C.
    275   // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv(
    276 
    277   //  The return-adjustment thunk required when C::f appears in a vtable
    278   //  where A is at a zero offset from C.
    279   // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv(
    280 }
    281 
    282 // Varargs thunk test.
    283 namespace Test12 {
    284   struct A {
    285     virtual A* f(int x, ...);
    286   };
    287   struct B {
    288     virtual B* f(int x, ...);
    289   };
    290   struct C : A, B {
    291     virtual void c();
    292     virtual C* f(int x, ...);
    293   };
    294   C* C::f(int x, ...) { return this; }
    295 
    296   // C::f
    297   // CHECK: define {{.*}} @_ZN6Test121C1fEiz
    298 
    299   // Varargs thunk; check that both the this and covariant adjustments
    300   // are generated.
    301   // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz
    302   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
    303   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
    304 }
    305 
    306 // PR13832
    307 namespace Test13 {
    308   struct B1 {
    309     virtual B1 &foo1();
    310   };
    311   struct Pad1 {
    312     virtual ~Pad1();
    313   };
    314   struct Proxy1 : Pad1, B1 {
    315     virtual ~Proxy1();
    316   };
    317   struct D : virtual Proxy1 {
    318     virtual ~D();
    319     virtual D &foo1();
    320   };
    321   D& D::foo1() {
    322     return *this;
    323   }
    324   // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
    325   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
    326   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
    327   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
    328   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
    329   // CHECK: ret %"struct.Test13::D"*
    330 }
    331 
    332 namespace Test14 {
    333   class A {
    334     virtual void f();
    335   };
    336   class B {
    337     virtual void f();
    338   };
    339   class C : public A, public B  {
    340     virtual void f();
    341   };
    342   void C::f() {
    343   }
    344   // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
    345 }
    346 
    347 // Varargs non-covariant thunk test.
    348 // PR18098
    349 namespace Test15 {
    350   struct A {
    351     virtual ~A();
    352   };
    353   struct B {
    354     virtual void f(int x, ...);
    355   };
    356   struct C : A, B {
    357     virtual void c();
    358     virtual void f(int x, ...);
    359   };
    360   void C::c() {}
    361 
    362   // C::c
    363   // CHECK: declare void @_ZN6Test151C1fEiz
    364   // non-virtual thunk to C::f
    365   // CHECK: declare void @_ZThn8_N6Test151C1fEiz
    366 }
    367 
    368 namespace Test16 {
    369 struct A {
    370   virtual ~A();
    371 };
    372 struct B {
    373   virtual void foo();
    374 };
    375 struct C : public A, public B {
    376   void foo() {}
    377 };
    378 struct D : public C {
    379   ~D();
    380 };
    381 D::~D() {}
    382 // CHECK: define linkonce_odr void @_ZThn8_N6Test161C3fooEv({{.*}}) {{.*}} comdat
    383 }
    384 
    385 /**** The following has to go at the end of the file ****/
    386 
    387 // checking without opt
    388 // CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
    389 // CHECK-NONOPT-NOT: comdat
    390 
    391 // This is from Test5:
    392 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
    393 
    394 // This is from Test10:
    395 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
    396 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
    397 
    398 // Checking with opt
    399 // CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2
    400 
    401 // This is from Test5:
    402 // CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
    403 
    404 // This is from Test10:
    405 // CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
    406 // CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
    407 
    408 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
    409