Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -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:   invoke 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:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     25 // WIN32:   call void @llvm.stackrestore(i8* %[[base]])
     26 // WIN32:   ret void
     27 //
     28 //    There should be one dtor call for unwinding from the second getA.
     29 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     30 // WIN32-NOT: @"\01??1A@@QAE@XZ"
     31 // WIN32:   call void @llvm.stackrestore
     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:   invoke 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 // WIN32:   call void @llvm.stackrestore
     58 //        Destroy the two const ref temporaries.
     59 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     60 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     61 // WIN32:   ret i32
     62 //
     63 //        Conditionally destroy arg1.
     64 // WIN32:   %[[cond:.*]] = load i1, i1* %[[isactive]]
     65 // WIN32:   br i1 %[[cond]]
     66 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
     67 // WIN32: }
     68 
     69 // Test putting the cleanups inside a conditional.
     70 int CouldThrow();
     71 int HasConditionalCleanup(bool cond) {
     72   return (cond ? TakesTwo(A(), A()) : CouldThrow());
     73 }
     74 
     75 // WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
     76 // WIN32:   store i1 false
     77 // WIN32:   br i1
     78 // WIN32:   call i8* @llvm.stacksave()
     79 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
     80 // WIN32:   store i1 true
     81 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
     82 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     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:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
     89 // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     90 // WIN32:   call void @llvm.stackrestore
     91 // WIN32: }
     92 
     93 // Now test both.
     94 int HasConditionalDeactivatedCleanups(bool cond) {
     95   return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
     96 }
     97 
     98 // WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
     99 // WIN32:   alloca i1
    100 // WIN32:   %[[arg1_cond:.*]] = alloca i1
    101 //        Start all four cleanups as deactivated.
    102 // WIN32:   store i1 false
    103 // WIN32:   store i1 false
    104 // WIN32:   store i1 false
    105 // WIN32:   store i1 false
    106 // WIN32:   br i1
    107 //        True condition.
    108 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    109 // WIN32:   store i1 true
    110 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
    111 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    112 // WIN32:   store i1 true, i1* %[[arg1_cond]]
    113 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    114 // WIN32:   store i1 true
    115 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
    116 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    117 // WIN32:   store i1 true
    118 // WIN32:   store i1 false, i1* %[[arg1_cond]]
    119 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
    120 //        False condition.
    121 // WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
    122 //        Two normal cleanups for TakeRef args.
    123 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
    124 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
    125 // WIN32:   ret i32
    126 //
    127 //        Somewhere in the landing pad soup, we conditionally destroy arg1.
    128 // WIN32:   %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
    129 // WIN32:   br i1 %[[isactive]]
    130 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
    131 // WIN32: }
    132 
    133 namespace crash_on_partial_destroy {
    134 struct A {
    135   virtual ~A();
    136 };
    137 
    138 struct B : virtual A {
    139   // Has an implicit destructor.
    140 };
    141 
    142 struct C : B {
    143   C();
    144 };
    145 
    146 void foo();
    147 // We used to crash when emitting this.
    148 C::C() { foo(); }
    149 
    150 // Verify that we don't bother with a vbtable lookup when adjusting the this
    151 // pointer to call a base destructor from a constructor while unwinding.
    152 // WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
    153 // WIN32:      landingpad
    154 //
    155 //        We shouldn't do any vbptr loads, just constant GEPs.
    156 // WIN32-NOT:  load
    157 // WIN32:      getelementptr i8, i8* %{{.*}}, i32 4
    158 // WIN32-NOT:  load
    159 // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
    160 // WIN32:      invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
    161 //
    162 // WIN32-NOT:  load
    163 // WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
    164 // WIN32-NOT:  load
    165 // WIN32:      getelementptr inbounds i8, i8* %{{.*}}, i64 4
    166 // WIN32-NOT:  load
    167 // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
    168 // WIN32:      call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"
    169 // WIN32: }
    170 }
    171 
    172 namespace dont_call_terminate {
    173 struct C {
    174   ~C();
    175 };
    176 void g();
    177 void f() {
    178   C c;
    179   g();
    180 }
    181 
    182 // WIN32-LABEL: define void @"\01?f@dont_call_terminate@@YAXXZ"()
    183 // WIN32: invoke void @"\01?g@dont_call_terminate@@YAXXZ"()
    184 // WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
    185 //
    186 // WIN32: [[cont]]
    187 // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
    188 //
    189 // WIN32: [[lpad]]
    190 // WIN32-NEXT: landingpad
    191 // WIN32-NEXT: cleanup
    192 // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
    193 }
    194