1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s 2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s 3 // RUN: %clang_cc1 %s -triple aarch64-windows -fms-extensions -emit-llvm -o - | FileCheck %s 4 5 void abort(void) __attribute__((noreturn)); 6 void might_crash(void); 7 void cleanup(void); 8 int check_condition(void); 9 void basic_finally(void) { 10 __try { 11 might_crash(); 12 } __finally { 13 cleanup(); 14 } 15 } 16 17 // CHECK-LABEL: define dso_local void @basic_finally() 18 // CHECK: invoke void @might_crash() 19 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 20 // 21 // CHECK: [[invoke_cont]] 22 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 23 // CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) 24 // CHECK-NEXT: ret void 25 // 26 // CHECK: [[lpad]] 27 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad 28 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 29 // CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) 30 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller 31 32 // CHECK: define internal void @"?fin$0@0@basic_finally@@"({{.*}}) 33 // CHECK-SAME: [[finally_attrs:#[0-9]+]] 34 // CHECK: call void @cleanup() 35 36 // Mostly check that we don't double emit 'r' which would crash. 37 void decl_in_finally(void) { 38 __try { 39 might_crash(); 40 } __finally { 41 int r; 42 } 43 } 44 45 // Ditto, don't crash double emitting 'l'. 46 void label_in_finally(void) { 47 __try { 48 might_crash(); 49 } __finally { 50 l: 51 cleanup(); 52 if (check_condition()) 53 goto l; 54 } 55 } 56 57 // CHECK-LABEL: define dso_local void @label_in_finally() 58 // CHECK: invoke void @might_crash() 59 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 60 // 61 // CHECK: [[invoke_cont]] 62 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 63 // CHECK: call void @"?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) 64 // CHECK: ret void 65 66 // CHECK: define internal void @"?fin$0@0@label_in_finally@@"({{.*}}) 67 // CHECK-SAME: [[finally_attrs]] 68 // CHECK: br label %[[l:[^ ]*]] 69 // 70 // CHECK: [[l]] 71 // CHECK: call void @cleanup() 72 // CHECK: call i32 @check_condition() 73 // CHECK: br i1 {{.*}}, label 74 // CHECK: br label %[[l]] 75 76 int crashed; 77 void use_abnormal_termination(void) { 78 __try { 79 might_crash(); 80 } __finally { 81 crashed = __abnormal_termination(); 82 } 83 } 84 85 // CHECK-LABEL: define dso_local void @use_abnormal_termination() 86 // CHECK: invoke void @might_crash() 87 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 88 // 89 // CHECK: [[invoke_cont]] 90 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 91 // CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) 92 // CHECK: ret void 93 // 94 // CHECK: [[lpad]] 95 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad 96 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 97 // CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) 98 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller 99 100 // CHECK: define internal void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer) 101 // CHECK-SAME: [[finally_attrs]] 102 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32 103 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed 104 // CHECK-NEXT: ret void 105 106 void noreturn_noop_finally() { 107 __try { 108 __noop(); 109 } __finally { 110 abort(); 111 } 112 } 113 114 // CHECK-LABEL: define dso_local void @noreturn_noop_finally() 115 // CHECK: call void @"?fin$0@0@noreturn_noop_finally@@"({{.*}}) 116 // CHECK: ret void 117 118 // CHECK: define internal void @"?fin$0@0@noreturn_noop_finally@@"({{.*}}) 119 // CHECK-SAME: [[finally_attrs]] 120 // CHECK: call void @abort() 121 // CHECK: unreachable 122 123 void noreturn_finally() { 124 __try { 125 might_crash(); 126 } __finally { 127 abort(); 128 } 129 } 130 131 // CHECK-LABEL: define dso_local void @noreturn_finally() 132 // CHECK: invoke void @might_crash() 133 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 134 // 135 // CHECK: [[cont]] 136 // CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}}) 137 // CHECK: ret void 138 // 139 // CHECK: [[lpad]] 140 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad 141 // CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}}) 142 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller 143 144 // CHECK: define internal void @"?fin$0@0@noreturn_finally@@"({{.*}}) 145 // CHECK-SAME: [[finally_attrs]] 146 // CHECK: call void @abort() 147 // CHECK: unreachable 148 149 int finally_with_return() { 150 __try { 151 return 42; 152 } __finally { 153 } 154 } 155 // CHECK-LABEL: define dso_local i32 @finally_with_return() 156 // CHECK: call void @"?fin$0@0@finally_with_return@@"({{.*}}) 157 // CHECK-NEXT: ret i32 42 158 159 // CHECK: define internal void @"?fin$0@0@finally_with_return@@"({{.*}}) 160 // CHECK-SAME: [[finally_attrs]] 161 // CHECK-NOT: br i1 162 // CHECK-NOT: br label 163 // CHECK: ret void 164 165 int nested___finally___finally() { 166 __try { 167 __try { 168 } __finally { 169 return 1; 170 } 171 } __finally { 172 // Intentionally no return here. 173 } 174 return 0; 175 } 176 177 // CHECK-LABEL: define dso_local i32 @nested___finally___finally 178 // CHECK: invoke void @"?fin$1@0@nested___finally___finally@@"({{.*}}) 179 // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 180 // 181 // CHECK: [[outercont]] 182 // CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}}) 183 // CHECK-NEXT: ret i32 0 184 // 185 // CHECK: [[lpad]] 186 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad 187 // CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}}) 188 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller 189 190 // CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally@@"({{.*}}) 191 // CHECK-SAME: [[finally_attrs]] 192 // CHECK: ret void 193 194 // CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally@@"({{.*}}) 195 // CHECK-SAME: [[finally_attrs]] 196 // CHECK: unreachable 197 198 // FIXME: Our behavior seems suspiciously different. 199 200 int nested___finally___finally_with_eh_edge() { 201 __try { 202 __try { 203 might_crash(); 204 } __finally { 205 return 899; 206 } 207 } __finally { 208 // Intentionally no return here. 209 } 210 return 912; 211 } 212 // CHECK-LABEL: define dso_local i32 @nested___finally___finally_with_eh_edge 213 // CHECK: invoke void @might_crash() 214 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]] 215 // 216 // [[invokecont]] 217 // CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) 218 // CHECK-NEXT: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]] 219 // 220 // CHECK: [[outercont]] 221 // CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) 222 // CHECK-NEXT: ret i32 912 223 // 224 // CHECK: [[lpad1]] 225 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad 226 // CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) 227 // CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]] 228 // 229 // CHECK: [[innercleanupretbb]] 230 // CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]] 231 // 232 // CHECK: [[lpad2]] 233 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad 234 // CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) 235 // CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller 236 237 // CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) 238 // CHECK-SAME: [[finally_attrs]] 239 // CHECK: ret void 240 241 // CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) 242 // CHECK-SAME: [[finally_attrs]] 243 // CHECK: unreachable 244 245 void finally_within_finally() { 246 __try { 247 might_crash(); 248 } __finally { 249 __try { 250 might_crash(); 251 } __finally { 252 } 253 } 254 } 255 256 // CHECK-LABEL: define dso_local void @finally_within_finally( 257 // CHECK: invoke void @might_crash( 258 259 // CHECK: call void @"?fin$0@0@finally_within_finally@@"( 260 // CHECK: call void @"?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"( 261 262 // CHECK-LABEL: define internal void @"?fin$0@0@finally_within_finally@@"({{[^)]*}}) 263 // CHECK-SAME: [[finally_attrs]] 264 // CHECK: invoke void @might_crash( 265 266 // CHECK: call void @"?fin$1@0@finally_within_finally@@"( 267 // CHECK: call void @"?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"( 268 269 // CHECK-LABEL: define internal void @"?fin$1@0@finally_within_finally@@"({{[^)]*}}) 270 // CHECK-SAME: [[finally_attrs]] 271 272 void cleanup_with_func(const char *); 273 void finally_with_func() { 274 __try { 275 might_crash(); 276 } __finally { 277 cleanup_with_func(__func__); 278 } 279 } 280 281 // CHECK-LABEL: define internal void @"?fin$0@0@finally_with_func@@"({{[^)]*}}) 282 // CHECK: call void @cleanup_with_func(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@COAGBPGM@finally_with_func?$AA@", i{{32|64}} 0, i{{32|64}} 0)) 283 284 // Look for the absence of noinline. Enum attributes come first, so check that 285 // a string attribute is the first to verify that no enum attributes are 286 // present. 287 // CHECK: attributes [[finally_attrs]] = { "{{.*}}" } 288