1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s 2 3 void abort(void) __attribute__((noreturn)); 4 void might_crash(void); 5 void cleanup(void); 6 int check_condition(void); 7 void basic_finally(void) { 8 __try { 9 might_crash(); 10 } __finally { 11 cleanup(); 12 } 13 } 14 15 // CHECK-LABEL: define void @basic_finally() 16 // CHECK: invoke void @might_crash() 17 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 18 // 19 // CHECK: [[invoke_cont]] 20 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 21 // CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]]) 22 // CHECK-NEXT: ret void 23 // 24 // CHECK: [[lpad]] 25 // CHECK-NEXT: landingpad 26 // CHECK-NEXT: cleanup 27 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 28 // CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]]) 29 // CHECK: resume { i8*, i32 } 30 31 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 32 // CHECK: call void @cleanup() 33 34 // Mostly check that we don't double emit 'r' which would crash. 35 void decl_in_finally(void) { 36 __try { 37 might_crash(); 38 } __finally { 39 int r; 40 } 41 } 42 43 // Ditto, don't crash double emitting 'l'. 44 void label_in_finally(void) { 45 __try { 46 might_crash(); 47 } __finally { 48 l: 49 cleanup(); 50 if (check_condition()) 51 goto l; 52 } 53 } 54 55 // CHECK-LABEL: define void @label_in_finally() 56 // CHECK: invoke void @might_crash() 57 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 58 // 59 // CHECK: [[invoke_cont]] 60 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 61 // CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext false, i8* %[[fp]]) 62 // CHECK: ret void 63 64 // CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 65 // CHECK: br label %[[l:[^ ]*]] 66 // 67 // CHECK: [[l]] 68 // CHECK: call void @cleanup() 69 // CHECK: call i32 @check_condition() 70 // CHECK: br i1 {{.*}}, label 71 // CHECK: br label %[[l]] 72 73 int crashed; 74 void use_abnormal_termination(void) { 75 __try { 76 might_crash(); 77 } __finally { 78 crashed = __abnormal_termination(); 79 } 80 } 81 82 // CHECK-LABEL: define void @use_abnormal_termination() 83 // CHECK: invoke void @might_crash() 84 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 85 // 86 // CHECK: [[invoke_cont]] 87 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 88 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext false, i8* %[[fp]]) 89 // CHECK: ret void 90 // 91 // CHECK: [[lpad]] 92 // CHECK-NEXT: landingpad 93 // CHECK-NEXT: cleanup 94 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 95 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]]) 96 // CHECK: resume { i8*, i32 } 97 98 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 99 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i1 %abnormal_termination to i32 100 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed 101 // CHECK-NEXT: ret void 102 103 void noreturn_noop_finally() { 104 __try { 105 __noop(); 106 } __finally { 107 abort(); 108 } 109 } 110 111 // CHECK-LABEL: define void @noreturn_noop_finally() 112 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 113 // CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext false, i8* %[[fp]]) 114 // CHECK: ret void 115 116 // CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 117 // CHECK: call void @abort() 118 // CHECK: unreachable 119 120 void noreturn_finally() { 121 __try { 122 might_crash(); 123 } __finally { 124 abort(); 125 } 126 } 127 128 // CHECK-LABEL: define void @noreturn_finally() 129 // CHECK: invoke void @might_crash() 130 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 131 // 132 // CHECK: [[cont]] 133 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 134 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext false, i8* %[[fp]]) 135 // CHECK: ret void 136 // 137 // CHECK: [[lpad]] 138 // CHECK: landingpad 139 // CHECK-NEXT: cleanup 140 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 141 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext true, i8* %[[fp]]) 142 // CHECK: resume { i8*, i32 } 143 144 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 145 // CHECK: call void @abort() 146 // CHECK: unreachable 147 148 int finally_with_return() { 149 __try { 150 return 42; 151 } __finally { 152 } 153 } 154 // CHECK-LABEL: define i32 @finally_with_return() 155 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 156 // CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]]) 157 // CHECK-NEXT: ret i32 42 158 159 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 160 // CHECK-NOT: br i1 161 // CHECK-NOT: br label 162 // CHECK: ret void 163 164 int nested___finally___finally() { 165 __try { 166 __try { 167 } __finally { 168 return 1; 169 } 170 } __finally { 171 // Intentionally no return here. 172 } 173 return 0; 174 } 175 176 // CHECK-LABEL: define i32 @nested___finally___finally 177 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 178 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) 179 // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 180 // 181 // CHECK: [[outercont]] 182 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 183 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) 184 // CHECK-NEXT: ret i32 0 185 // 186 // CHECK: [[lpad]] 187 // CHECK-NEXT: landingpad 188 // CHECK-NEXT: cleanup 189 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 190 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) 191 192 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 193 // CHECK: ret void 194 195 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 196 // CHECK: unreachable 197 198 int nested___finally___finally_with_eh_edge() { 199 __try { 200 __try { 201 might_crash(); 202 } __finally { 203 return 899; 204 } 205 } __finally { 206 // Intentionally no return here. 207 } 208 return 912; 209 } 210 // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge 211 // CHECK: invoke void @might_crash() 212 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]] 213 // 214 // [[invokecont]] 215 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 216 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) 217 // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]] 218 // 219 // CHECK: [[outercont]] 220 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 221 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) 222 // CHECK-NEXT: ret i32 912 223 // 224 // CHECK: [[lpad1]] 225 // CHECK-NEXT: landingpad 226 // CHECK-NEXT: cleanup 227 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 228 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) 229 // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]] 230 // 231 // CHECK: [[lpad2]] 232 // CHECK-NEXT: landingpad 233 // CHECK-NEXT: cleanup 234 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 235 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) 236 // CHECK: resume 237 238 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 239 // CHECK: ret void 240 241 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 242 // CHECK: unreachable 243