19b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft -fexceptions | FileCheck -check-prefix WIN32 %s
29b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
39b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknerstruct A {
49b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  A();
59b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  ~A();
69b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  int a;
79b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner};
89b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
99b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid KlecknerA getA();
109b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
119b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknerint TakesTwo(A a, A b);
129b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknervoid HasEHCleanup() {
139b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  TakesTwo(getA(), getA());
149b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner}
159b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
169b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// With exceptions, we need to clean up at least one of these temporaries.
179b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
189b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//    First one doesn't have any cleanups, no need for invoke.
199b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
209b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//    If this call throws, we have to cleanup the first temporary.
219b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
229b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//    If this call throws, we already popped our cleanups
239b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
249b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   ret void
259b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//
269b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//    There should be one dtor call for unwinding from the second getA.
279b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
289b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: }
299b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
309b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknervoid TakeRef(const A &a);
319b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknerint HasDeactivatedCleanups() {
329b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
339b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner}
349b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
359b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
369b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   %[[isactive:.*]] = alloca i1
379b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
389b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
399b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
409b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 true, i1* %[[isactive]]
419b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
429b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
439b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
449b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false, i1* %[[isactive]]
459b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
469b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Destroy the two const ref temporaries.
479b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
489b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
499b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   ret i32
509b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//
519b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Conditionally destroy arg1.
529b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   %[[cond:.*]] = load i1* %[[isactive]]
539b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   br i1 %[[cond]]
549b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
559b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: }
569b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
579b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// Test putting the cleanups inside a conditional.
589b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknerint CouldThrow();
599b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknerint HasConditionalCleanup(bool cond) {
609b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  return (cond ? TakesTwo(A(), A()) : CouldThrow());
619b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner}
629b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
639b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
649b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false
659b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   br i1
669b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        No cleanups, so we call and then activate a cleanup if it succeeds.
679b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
689b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 true
699b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Now we have a cleanup for the first aggregate, so we invoke.
709b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
719b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Now we have no cleanups because TakeTwo will destruct both args.
729b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
739b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Still no cleanups, so call.
749b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
759b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Somewhere in the landing pad for our single invoke, call the dtor.
769b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
779b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: }
789b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
799b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// Now test both.
809b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Klecknerint HasConditionalDeactivatedCleanups(bool cond) {
819b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner  return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
829b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner}
839b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner
849b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
859b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   %[[arg1:.*]] = alloca %struct.A, align 4
869b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   alloca i1
879b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   %[[arg1_cond:.*]] = alloca i1
889b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Start all four cleanups as deactivated.
899b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false
909b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false
919b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false
929b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false
939b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   br i1
949b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        True condition.
959b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
969b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 true
979b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
989b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
999b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 true, i1* %[[arg1_cond]]
1009b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
1019b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 true
1029b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
1039b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
1049b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 true
1059b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   store i1 false, i1* %[[arg1_cond]]
1069b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
1079b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        False condition.
1089b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
1099b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Two normal cleanups for TakeRef args.
1109b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
1119b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
1129b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   ret i32
1139b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//
1149b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner//        Somewhere in the landing pad soup, we conditionally destroy arg1.
1159b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
1169b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   br i1 %[[isactive]]
1179b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
1189b60195ad4843c9e2e231673a0dbc0d5c8c6eb2bReid Kleckner// WIN32: }
119