Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft -fexceptions | 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: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
     18 //    First one doesn't have any cleanups, no need for invoke.
     19 // WIN32:   call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
     20 //    If this call throws, we have to cleanup the first temporary.
     21 // WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
     22 //    If this call throws, we already popped our cleanups
     23 // WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     24 // WIN32:   ret void
     25 //
     26 //    There should be one dtor call for unwinding from the second getA.
     27 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     28 // WIN32: }
     29 
     30 void TakeRef(const A &a);
     31 int HasDeactivatedCleanups() {
     32   return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
     33 }
     34 
     35 // WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
     36 // WIN32:   %[[isactive:.*]] = alloca i1
     37 // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     38 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
     39 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
     40 // WIN32:   store i1 true, i1* %[[isactive]]
     41 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     42 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
     43 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     44 // WIN32:   store i1 false, i1* %[[isactive]]
     45 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     46 //        Destroy the two const ref temporaries.
     47 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
     48 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
     49 // WIN32:   ret i32
     50 //
     51 //        Conditionally destroy arg1.
     52 // WIN32:   %[[cond:.*]] = load i1* %[[isactive]]
     53 // WIN32:   br i1 %[[cond]]
     54 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
     55 // WIN32: }
     56 
     57 // Test putting the cleanups inside a conditional.
     58 int CouldThrow();
     59 int HasConditionalCleanup(bool cond) {
     60   return (cond ? TakesTwo(A(), A()) : CouldThrow());
     61 }
     62 
     63 // WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
     64 // WIN32:   store i1 false
     65 // WIN32:   br i1
     66 //        No cleanups, so we call and then activate a cleanup if it succeeds.
     67 // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
     68 // WIN32:   store i1 true
     69 //        Now we have a cleanup for the first aggregate, so we invoke.
     70 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
     71 //        Now we have no cleanups because TakeTwo will destruct both args.
     72 // WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
     73 //        Still no cleanups, so call.
     74 // WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
     75 //        Somewhere in the landing pad for our single invoke, call the dtor.
     76 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
     77 // WIN32: }
     78 
     79 // Now test both.
     80 int HasConditionalDeactivatedCleanups(bool cond) {
     81   return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
     82 }
     83 
     84 // WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
     85 // WIN32:   %[[arg1:.*]] = alloca %struct.A, align 4
     86 // WIN32:   alloca i1
     87 // WIN32:   %[[arg1_cond:.*]] = alloca i1
     88 //        Start all four cleanups as deactivated.
     89 // WIN32:   store i1 false
     90 // WIN32:   store i1 false
     91 // WIN32:   store i1 false
     92 // WIN32:   store i1 false
     93 // WIN32:   br i1
     94 //        True condition.
     95 // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
     96 // WIN32:   store i1 true
     97 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
     98 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
     99 // WIN32:   store i1 true, i1* %[[arg1_cond]]
    100 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    101 // WIN32:   store i1 true
    102 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
    103 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
    104 // WIN32:   store i1 true
    105 // WIN32:   store i1 false, i1* %[[arg1_cond]]
    106 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
    107 //        False condition.
    108 // WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
    109 //        Two normal cleanups for TakeRef args.
    110 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
    111 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
    112 // WIN32:   ret i32
    113 //
    114 //        Somewhere in the landing pad soup, we conditionally destroy arg1.
    115 // WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
    116 // WIN32:   br i1 %[[isactive]]
    117 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
    118 // WIN32: }
    119