Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 >%t 2>&1
      2 // RUN: FileCheck --check-prefix=MANGLING %s < %t
      3 // RUN: FileCheck --check-prefix=XMANGLING %s < %t
      4 // RUN: FileCheck --check-prefix=CODEGEN %s < %t
      5 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
      6 
      7 void foo(void *);
      8 
      9 struct A {
     10   virtual ~A();
     11   virtual void public_f();
     12   // Make sure we don't emit unneeded thunks:
     13   // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
     14  protected:
     15   virtual void protected_f();
     16  private:
     17   virtual void private_f();
     18 };
     19 
     20 struct B {
     21   virtual ~B();
     22   virtual void public_f();
     23  protected:
     24   virtual void protected_f();
     25  private:
     26   virtual void private_f();
     27 };
     28 
     29 
     30 struct C : A, B {
     31   C();
     32 
     33   virtual ~C();
     34   // MANGLING-DAG: declare {{.*}} @"\01??1C@@UAE@XZ"({{.*}})
     35   // MANGLING-DAG: define {{.*}} @"\01??_GC@@UAEPAXI@Z"({{.*}})
     36   // MANGLING-DAG: define {{.*}} @"\01??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
     37   // MANGLING-X64-DAG: declare {{.*}} @"\01??1C@@UEAA@XZ"({{.*}})
     38   // MANGLING-X64-DAG: define {{.*}} @"\01??_GC@@UEAAPEAXI@Z"({{.*}})
     39   // MANGLING-X64-DAG: define {{.*}} @"\01??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
     40 
     41   // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
     42   virtual void public_f();
     43   // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
     44   // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
     45   // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
     46   // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
     47  protected:
     48   virtual void protected_f();
     49   // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
     50   // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
     51   // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
     52   // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
     53 
     54  private:
     55   virtual void private_f();
     56   // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
     57   // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
     58   // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
     59   // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
     60 };
     61 
     62 C::C() {}  // Emits vftable and forces thunk generation.
     63 
     64 // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
     65 // CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
     66 // FIXME: should actually call _EC, not _GC.
     67 // CODEGEN:   call x86_thiscallcc i8* @"\01??_GC@@UAEPAXI@Z"
     68 // CODEGEN: ret
     69 
     70 // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
     71 // CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
     72 // CODEGEN:   call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
     73 // CODEGEN: ret
     74 
     75 void zoo(C* obj) {
     76   delete obj;
     77 }
     78 
     79 struct D {
     80   virtual B* goo();
     81 };
     82 
     83 struct E : D {
     84   E();
     85   virtual C* goo();
     86   // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
     87   // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
     88   // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
     89   // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
     90 };
     91 
     92 E::E() {}  // Emits vftable and forces thunk generation.
     93 
     94 // CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
     95 // CODEGEN:   call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
     96 // CODEGEN:   getelementptr inbounds i8, i8* {{.*}}, i32 4
     97 // CODEGEN: ret
     98 
     99 struct F : virtual A, virtual B {
    100   virtual void own_method();
    101   virtual ~F();
    102 };
    103 
    104 F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.
    105 
    106 struct G : C { };
    107 
    108 struct H : E {
    109   virtual G* goo();
    110   // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
    111   // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
    112   // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
    113   // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
    114   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
    115   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
    116 };
    117 
    118 H h;
    119 
    120 struct I : D {
    121   I();
    122   virtual F* goo();
    123 };
    124 
    125 I::I() {}  // Emits vftable and forces thunk generation.
    126 
    127 // CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
    128 // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ"
    129 // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
    130 // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ORIG_RET_i8]], i32 4
    131 // CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
    132 // CODEGEN: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]]
    133 // CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 2
    134 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBASE_OFFSET_PTR]]
    135 // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
    136 // CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F*
    137 // CODEGEN: phi %struct.F* {{.*}} %[[RES]]
    138 // CODEGEN: ret %struct.{{[BF]}}*
    139 
    140 namespace CrashOnThunksForAttributedType {
    141 // We used to crash on this because the type of foo is an AttributedType, not
    142 // FunctionType, and we had to look through the sugar.
    143 struct A {
    144   virtual void __stdcall foo();
    145 };
    146 struct B {
    147   virtual void __stdcall foo();
    148 };
    149 struct C : A, B {
    150   virtual void __stdcall foo();
    151 };
    152 C c;
    153 }
    154 
    155 namespace {
    156 struct E : D {
    157   E();
    158   virtual C* goo();
    159 };
    160 E::E() {}
    161 E e;
    162 // Class with internal linkage has internal linkage thunks.
    163 // CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ"
    164 }
    165