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