Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
      2 
      3 struct A {
      4   A();
      5   ~A();
      6   int a;
      7 };
      8 
      9 A getA();
     10 
     11 int TakesTwo(A a, A b);
     12 void HasEHCleanup() {
     13   TakesTwo(getA(), getA());
     14 }
     15 
     16 // With exceptions, we need to clean up at least one of these temporaries.
     17 // WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
     18 // WIN32:   %[[base:.*]] = call i8* @llvm.stacksave()
     19 //    If this call throws, we have to restore the stack.
     20 // WIN32:   call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
     21 //    If this call throws, we have to cleanup the first temporary.
     22 // WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
     23 //    If this call throws, we have to cleanup the stacksave.
     24 // WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     25 // WIN32:   call void @llvm.stackrestore
     26 // WIN32:   ret void
     27 //
     28 //    There should be one dtor call for unwinding from the second getA.
     29 // WIN32:   cleanuppad
     30 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
     31 // WIN32-NOT: @"\01??1A@@QAE@XZ"
     32 // WIN32: }
     33 
     34 void TakeRef(const A &a);
     35 int HasDeactivatedCleanups() {
     36   return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
     37 }
     38 
     39 // WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
     40 // WIN32:   %[[isactive:.*]] = alloca i1
     41 // WIN32:   call i8* @llvm.stacksave()
     42 // WIN32:   %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
     43 // WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
     44 // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     45 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
     46 //
     47 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
     48 // WIN32:   store i1 true, i1* %[[isactive]]
     49 //
     50 // WIN32:   %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
     51 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     52 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
     53 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     54 // WIN32:   store i1 false, i1* %[[isactive]]
     55 //
     56 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
     57 //        Destroy the two const ref temporaries.
     58 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
     59 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
     60 // WIN32:   ret i32
     61 //
     62 //        Conditionally destroy arg1.
     63 // WIN32:   %[[cond:.*]] = load i1, i1* %[[isactive]]
     64 // WIN32:   br i1 %[[cond]]
     65 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
     66 // WIN32: }
     67 
     68 // Test putting the cleanups inside a conditional.
     69 int CouldThrow();
     70 int HasConditionalCleanup(bool cond) {
     71   return (cond ? TakesTwo(A(), A()) : CouldThrow());
     72 }
     73 
     74 // WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
     75 // WIN32:   store i1 false
     76 // WIN32:   br i1
     77 // WIN32:   call i8* @llvm.stacksave()
     78 // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
     79 // WIN32:   store i1 true
     80 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
     81 // WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     82 //
     83 // WIN32:   call void @llvm.stackrestore
     84 //
     85 // WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
     86 //
     87 //        Only one dtor in the invoke for arg1
     88 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
     89 // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     90 // WIN32: }
     91 
     92 // Now test both.
     93 int HasConditionalDeactivatedCleanups(bool cond) {
     94   return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
     95 }
     96 
     97 // WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
     98 // WIN32:   alloca i1
     99 // WIN32:   %[[arg1_cond:.*]] = alloca i1
    100 //        Start all four cleanups as deactivated.
    101 // WIN32:   store i1 false
    102 // WIN32:   store i1 false
    103 // WIN32:   store i1 false
    104 // WIN32:   store i1 false
    105 // WIN32:   br i1
    106 //        True condition.
    107 // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    108 // WIN32:   store i1 true
    109 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
    110 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    111 // WIN32:   store i1 true, i1* %[[arg1_cond]]
    112 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    113 // WIN32:   store i1 true
    114 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
    115 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    116 // WIN32:   store i1 true
    117 // WIN32:   store i1 false, i1* %[[arg1_cond]]
    118 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
    119 //        False condition.
    120 // WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
    121 //        Two normal cleanups for TakeRef args.
    122 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
    123 // WIN32-NOT:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
    124 // WIN32:   ret i32
    125 //
    126 //        Somewhere in the landing pad soup, we conditionally destroy arg1.
    127 // WIN32:   %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
    128 // WIN32:   br i1 %[[isactive]]
    129 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
    130 // WIN32: }
    131 
    132 namespace crash_on_partial_destroy {
    133 struct A {
    134   virtual ~A();
    135 };
    136 
    137 struct B : virtual A {
    138   // Has an implicit destructor.
    139 };
    140 
    141 struct C : B {
    142   C();
    143 };
    144 
    145 void foo();
    146 // We used to crash when emitting this.
    147 C::C() { foo(); }
    148 
    149 // Verify that we don't bother with a vbtable lookup when adjusting the this
    150 // pointer to call a base destructor from a constructor while unwinding.
    151 // WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
    152 // WIN32:      cleanuppad
    153 //
    154 //        We shouldn't do any vbptr loads, just constant GEPs.
    155 // WIN32-NOT:  load
    156 // WIN32:      getelementptr i8, i8* %{{.*}}, i32 4
    157 // WIN32-NOT:  load
    158 // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
    159 // WIN32:      call x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
    160 //
    161 // WIN32-NOT:  load
    162 // WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
    163 // WIN32-NOT:  load
    164 // WIN32:      getelementptr inbounds i8, i8* %{{.*}}, i32 4
    165 // WIN32-NOT:  load
    166 // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
    167 // WIN32:      call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
    168 // WIN32: }
    169 }
    170 
    171 namespace dont_call_terminate {
    172 struct C {
    173   ~C();
    174 };
    175 void g();
    176 void f() {
    177   C c;
    178   g();
    179 }
    180 
    181 // WIN32-LABEL: define void @"\01?f@dont_call_terminate@@YAXXZ"()
    182 // WIN32: invoke void @"\01?g@dont_call_terminate@@YAXXZ"()
    183 // WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
    184 //
    185 // WIN32: [[cont]]
    186 // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
    187 //
    188 // WIN32: [[lpad]]
    189 // WIN32-NEXT: cleanuppad
    190 // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
    191 }
    192 
    193 namespace noexcept_false_dtor {
    194 struct D {
    195   ~D() noexcept(false);
    196 };
    197 void f() {
    198   D d;
    199   CouldThrow();
    200 }
    201 }
    202 
    203 // WIN32-LABEL: define void @"\01?f@noexcept_false_dtor@@YAXXZ"()
    204 // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
    205 // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
    206 // WIN32: cleanuppad
    207 // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
    208 // WIN32: cleanupret
    209