Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
      2 // RUN: not %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft | FileCheck -check-prefix WIN32 %s
      3 // RUN: not %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -cxx-abi microsoft | FileCheck -check-prefix WIN64 %s
      4 
      5 struct Empty {};
      6 
      7 struct EmptyWithCtor {
      8   EmptyWithCtor() {}
      9 };
     10 
     11 struct Small {
     12   int x;
     13 };
     14 
     15 // This is a C++11 trivial and standard-layout struct but not a C++03 POD.
     16 struct SmallCpp11NotCpp03Pod : Empty {
     17   int x;
     18 };
     19 
     20 struct SmallWithCtor {
     21   SmallWithCtor() {}
     22   int x;
     23 };
     24 
     25 struct SmallWithDtor {
     26   SmallWithDtor();
     27   ~SmallWithDtor();
     28   int x;
     29 };
     30 
     31 struct SmallWithVftable {
     32   int x;
     33   virtual void foo();
     34 };
     35 
     36 struct Medium {
     37   int x, y;
     38 };
     39 
     40 struct MediumWithCopyCtor {
     41   MediumWithCopyCtor();
     42   MediumWithCopyCtor(const struct MediumWithCopyCtor &);
     43   int x, y;
     44 };
     45 
     46 struct Big {
     47   int a, b, c, d, e, f;
     48 };
     49 
     50 // Returning structs that fit into a register.
     51 Small small_return() { return Small(); }
     52 // LINUX: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
     53 // WIN32: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
     54 // WIN64: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
     55 
     56 Medium medium_return() { return Medium(); }
     57 // LINUX: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
     58 // WIN32: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
     59 // WIN64: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
     60 
     61 // Returning structs that fit into a register but are not POD.
     62 SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
     63 // LINUX: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
     64 // WIN32: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
     65 // WIN64: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
     66 
     67 SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
     68 // LINUX: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
     69 // WIN32: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
     70 // WIN64: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
     71 
     72 SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
     73 // LINUX: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
     74 // WIN32: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
     75 // WIN64: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
     76 
     77 MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
     78 // LINUX: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
     79 // WIN32: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
     80 // WIN64: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
     81 
     82 // Returning a large struct that doesn't fit into a register.
     83 Big big_return() { return Big(); }
     84 // LINUX: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
     85 // WIN32: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
     86 // WIN64: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
     87 
     88 
     89 void small_arg(Small s) {}
     90 // LINUX: define void @_Z9small_arg5Small(%struct.Small* byval align 4 %s)
     91 // WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(%struct.Small* byval align 4 %s)
     92 // WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
     93 
     94 void medium_arg(Medium s) {}
     95 // LINUX: define void @_Z10medium_arg6Medium(%struct.Medium* byval align 4 %s)
     96 // WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(%struct.Medium* byval align 4 %s)
     97 // WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
     98 
     99 void small_arg_with_ctor(SmallWithCtor s) {}
    100 // LINUX: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
    101 // WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(%struct.SmallWithCtor* byval align 4 %s)
    102 // WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
    103 
    104 // Test that dtors are invoked in the callee.
    105 void small_arg_with_dtor(SmallWithDtor s) {}
    106 // WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval align 4 %s) {{.*}} {
    107 // WIN32:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"(%struct.SmallWithDtor* %s)
    108 // WIN32: }
    109 // WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval %s) {{.*}} {
    110 // WIN64:   call void @"\01??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
    111 // WIN64: }
    112 
    113 // Test that references aren't destroyed in the callee.
    114 void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
    115 // WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
    116 // WIN32-NOT:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
    117 // WIN32: }
    118 
    119 // Test that temporaries passed by reference are destroyed in the caller.
    120 void temporary_ref_with_dtor() {
    121   ref_small_arg_with_dtor(SmallWithDtor());
    122 }
    123 // WIN32: define void @"\01?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
    124 // WIN32:   call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
    125 // WIN32:   call void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
    126 // WIN32:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
    127 // WIN32: }
    128 
    129 void takes_two_by_val_with_dtor(SmallWithDtor a, SmallWithDtor b);
    130 void eh_cleanup_arg_with_dtor() {
    131   takes_two_by_val_with_dtor(SmallWithDtor(), SmallWithDtor());
    132 }
    133 //   When exceptions are off, we don't have any cleanups.  See
    134 //   microsoft-abi-exceptions.cpp for these cleanups.
    135 // WIN32: define void @"\01?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
    136 // WIN32:   call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
    137 // WIN32:   call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
    138 // WIN32:   call void @"\01?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
    139 // WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
    140 // WIN32: }
    141 
    142 void small_arg_with_vftable(SmallWithVftable s) {}
    143 // LINUX: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
    144 // WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval align 4 %s)
    145 // WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval %s)
    146 
    147 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
    148 // LINUX: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
    149 // WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval align 4 %s)
    150 // WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval %s)
    151 
    152 void big_arg(Big s) {}
    153 // LINUX: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
    154 // WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
    155 // WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
    156 
    157 // FIXME: Add WIN64 tests. Currently, even the method manglings are wrong (sic!).
    158 class Class {
    159  public:
    160   Small thiscall_method_small() { return Small(); }
    161   // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
    162   // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
    163 
    164   SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
    165   // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
    166   // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
    167 
    168   Small __cdecl cdecl_method_small() { return Small(); }
    169   // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
    170   // FIXME: Interesting, cdecl returns structures differently for instance
    171   // methods and global functions. This is not supported by Clang yet...
    172   // FIXME: Replace WIN32-NOT with WIN32 when this is fixed.
    173   // WIN32-NOT: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
    174 
    175   Big __cdecl cdecl_method_big() { return Big(); }
    176   // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
    177   // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result, %class.Class* %this)
    178 
    179   void thiscall_method_arg(Empty s) {}
    180   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
    181   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
    182 
    183   void thiscall_method_arg(EmptyWithCtor s) {}
    184   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
    185   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
    186 
    187   void thiscall_method_arg(Small s) {}
    188   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, %struct.Small* byval align 4 %s)
    189   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, %struct.Small* byval align 4 %s)
    190 
    191   void thiscall_method_arg(SmallWithCtor s) {}
    192   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
    193   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
    194 
    195   void thiscall_method_arg(Big s) {}
    196   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
    197   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
    198 };
    199 
    200 void use_class() {
    201   Class c;
    202   c.thiscall_method_small();
    203   c.thiscall_method_small_with_ctor();
    204 
    205   c.cdecl_method_small();
    206   c.cdecl_method_big();
    207 
    208   c.thiscall_method_arg(Empty());
    209   c.thiscall_method_arg(EmptyWithCtor());
    210   c.thiscall_method_arg(Small());
    211   c.thiscall_method_arg(SmallWithCtor());
    212   c.thiscall_method_arg(Big());
    213 }
    214 
    215 struct X {
    216   X();
    217   ~X();
    218 };
    219 void g(X) {
    220 }
    221 // WIN32: define void @"\01?g@@YAXUX@@@Z"(%struct.X* byval align 4) {{.*}} {
    222 // WIN32:   call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* %0)
    223 // WIN32: }
    224 void f() {
    225   g(X());
    226 }
    227 // WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
    228 // WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
    229 // WIN32: }
    230