1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -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]], 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]], 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* %[[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* %[[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* %{{.*}}, 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* %{{.*}}, i64 4 166 // WIN32-NOT: load 167 // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* 168 // WIN32: invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ" 169 // WIN32: } 170 } 171