diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGen/exceptions-seh-finally.c | 227 | ||||
-rw-r--r-- | clang/test/CodeGen/exceptions-seh-leave.c | 149 | ||||
-rw-r--r-- | clang/test/CodeGen/exceptions-seh.c | 23 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/exceptions-seh.cpp | 44 | ||||
-rw-r--r-- | clang/test/SemaCXX/switch-implicit-fallthrough.cpp | 6 |
5 files changed, 241 insertions, 208 deletions
diff --git a/clang/test/CodeGen/exceptions-seh-finally.c b/clang/test/CodeGen/exceptions-seh-finally.c index a594aaac051..eeadf0d5ec5 100644 --- a/clang/test/CodeGen/exceptions-seh-finally.c +++ b/clang/test/CodeGen/exceptions-seh-finally.c @@ -17,20 +17,30 @@ void basic_finally(void) { // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[invoke_cont]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] +// CHECK: br label %[[finally:[^ ]*]] +// +// CHECK: [[finally]] +// CHECK: call void @cleanup() +// CHECK: load i8, i8* %[[abnormal]] +// CHECK: icmp eq +// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]] +// +// CHECK: [[finallycont]] // CHECK-NEXT: ret void // // CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: store i8 1, i8* %[[abnormal]] +// CHECK: br label %[[finally]] +// +// CHECK: [[resumecont]] +// CHECK: br label %[[ehresume:[^ ]*]] +// +// CHECK: [[ehresume]] // CHECK: resume { i8*, i32 } -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: call void @cleanup() - // Mostly check that we don't double emit 'r' which would crash. void decl_in_finally(void) { __try { @@ -57,11 +67,10 @@ l: // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[invoke_cont]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: ret void - -// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] +// CHECK: br label %[[finally:[^ ]*]] +// +// CHECK: [[finally]] // CHECK: br label %[[l:[^ ]*]] // // CHECK: [[l]] @@ -84,22 +93,32 @@ void use_abnormal_termination(void) { // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[invoke_cont]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: ret void +// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] +// CHECK: br label %[[finally:[^ ]*]] +// +// CHECK: [[finally]] +// CHECK: load i8, i8* %[[abnormal]] +// CHECK: zext i8 %{{.*}} to i32 +// CHECK: store i32 %{{.*}}, i32* @crashed +// CHECK: load i8, i8* %[[abnormal]] +// CHECK: icmp eq +// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]] +// +// CHECK: [[finallycont]] +// CHECK-NEXT: ret void // // CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: store i8 1, i8* %[[abnormal]] +// CHECK: br label %[[finally]] +// +// CHECK: [[resumecont]] +// CHECK: br label %[[ehresume:[^ ]*]] +// +// CHECK: [[ehresume]] // CHECK: resume { i8*, i32 } -// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: %[[abnormal_zext:[^ ]*]] = zext i1 %abnormal_termination to i32 -// CHECK: store i32 %[[abnormal_zext]], i32* @crashed -// CHECK-NEXT: ret void - void noreturn_noop_finally() { __try { __noop(); @@ -109,13 +128,12 @@ void noreturn_noop_finally() { } // CHECK-LABEL: define void @noreturn_noop_finally() -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: ret void - -// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) +// CHECK: store i8 0, i8* % +// CHECK: br label %[[finally:[^ ]*]] +// CHECK: [[finally]] // CHECK: call void @abort() -// CHECK: unreachable +// CHECK-NEXT: unreachable +// CHECK-NOT: load void noreturn_finally() { __try { @@ -130,20 +148,18 @@ void noreturn_finally() { // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: ret void +// CHECK: store i8 0, i8* % +// CHECK: br label %[[finally:[^ ]*]] +// +// CHECK: [[finally]] +// CHECK: call void @abort() +// CHECK-NEXT: unreachable // // CHECK: [[lpad]] // CHECK: landingpad // CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext true, i8* %[[fp]]) -// CHECK: resume { i8*, i32 } - -// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: call void @abort() -// CHECK: unreachable +// CHECK: store i8 1, i8* % +// CHECK: br label %[[finally]] int finally_with_return() { __try { @@ -152,15 +168,15 @@ int finally_with_return() { } } // CHECK-LABEL: define i32 @finally_with_return() -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: store i8 0, i8* % +// CHECK-NEXT: br label %[[finally:[^ ]*]] +// +// CHECK: [[finally]] +// CHECK-NEXT: br label %[[finallycont:[^ ]*]] +// +// CHECK: [[finallycont]] // CHECK-NEXT: ret i32 42 -// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK-NOT: br i1 -// CHECK-NOT: br label -// CHECK: ret void - int nested___finally___finally() { __try { __try { @@ -172,28 +188,38 @@ int nested___finally___finally() { } return 0; } - // CHECK-LABEL: define i32 @nested___finally___finally -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]] +// CHECK: store i8 0, i8* % +// CHECK-NEXT: br label %[[finally:[^ ]*]] // -// CHECK: [[outercont]] -// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK-NEXT: ret i32 0 +// CHECK: [[finally]] +// CHECK-NEXT: store i32 1, i32* % +// CHECK-NEXT: store i32 1, i32* % +// CHECK-NEXT: br label %[[cleanup:[^ ]*]] // -// CHECK: [[lpad]] -// CHECK-NEXT: landingpad -// CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) - -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: ret void - -// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: unreachable +// The finally's unreachable continuation block: +// CHECK: store i32 0, i32* % +// CHECK-NEXT: br label %[[cleanup]] +// +// CHECK: [[cleanup]] +// CHECK-NEXT: store i8 0, i8* % +// CHECK-NEXT: br label %[[outerfinally:[^ ]*]] +// +// CHECK: [[outerfinally]] +// CHECK-NEXT: br label %[[finallycont:[^ ]*]] +// +// CHECK: [[finallycont]] +// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* % +// CHECK-NEXT: switch i32 %[[dest]] +// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]] +// +// CHECK: [[cleanupcont]] +// CHECK-NEXT: store i32 0, i32* % +// CHECK-NEXT: br label %[[return:[^ ]*]] +// +// CHECK: [[return]] +// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* % +// CHECK-NEXT: ret i32 %[[reg]] int nested___finally___finally_with_eh_edge() { __try { @@ -208,35 +234,58 @@ int nested___finally___finally_with_eh_edge() { return 912; } // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge -// CHECK: invoke void @might_crash() -// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]] +// CHECK: invoke void @might_crash() #3 +// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // -// [[invokecont]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]] +// CHECK: [[invokecont]] +// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]] +// CHECK-NEXT: br label %[[finally:[^ ]*]] + +// CHECK: [[finally]] +// CHECK-NEXT: store i32 899, i32* % +// CHECK-NEXT: store i32 1, i32* % +// CHECK-NEXT: br label %[[cleanup:[^ ]*]] // -// CHECK: [[outercont]] -// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK-NEXT: ret i32 912 +// The inner finally's unreachable continuation block: +// CHECK: store i32 0, i32* % +// CHECK-NEXT: br label %[[cleanup]] // -// CHECK: [[lpad1]] -// CHECK-NEXT: landingpad -// CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) -// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]] +// CHECK: [[cleanup]] +// CHECK-NEXT: store i8 0, i8* % +// CHECK-NEXT: br label %[[outerfinally:[^ ]*]] +// +// CHECK: [[outerfinally]] +// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]] +// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0 +// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]] +// +// CHECK: [[finallycont]] +// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* % +// CHECK-NEXT: switch i32 %[[dest]] +// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]] // -// CHECK: [[lpad2]] +// CHECK: [[cleanupcont]] +// CHECK-NEXT: store i32 912, i32* % +// CHECK-NEXT: br label %[[return:[^ ]*]] +// +// +// CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: store i8 1, i8* %[[abnormal]] +// CHECK: br label %[[finally]] +// +// The inner finally's unreachable resume block: +// CHECK: store i8 1, i8* %[[abnormal]] +// CHECK-NEXT: br label %[[outerfinally]] +// +// CHECK: [[finallyresume]] +// CHECK-NEXT: br label %[[ehresume:[^ ]*]] +// +// CHECK: [[return]] +// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* % +// CHECK-NEXT: ret i32 %[[reg]] +// +// The ehresume block, not reachable either. +// CHECK: [[ehresume]] // CHECK: resume - -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: ret void - -// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: unreachable diff --git a/clang/test/CodeGen/exceptions-seh-leave.c b/clang/test/CodeGen/exceptions-seh-leave.c index 793501a9fe5..0d38439c9b0 100644 --- a/clang/test/CodeGen/exceptions-seh-leave.c +++ b/clang/test/CodeGen/exceptions-seh-leave.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s -void g(void); +void g(); ////////////////////////////////////////////////////////////////////////////// // __leave with __except @@ -38,7 +38,7 @@ int __leave_with___except() { return 1; } // CHECK-LABEL: define i32 @__leave_with___except() -// CHECK: invoke void @g() +// CHECK: invoke void bitcast (void (...)* @g to void ()*)() // CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}} // For __excepts, instead of an explicit __try.__leave label, we could use // use invoke.cont as __leave jump target instead. However, not doing this @@ -74,8 +74,8 @@ int __leave_with___finally_simple() { // CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: store i32 23 // CHECK: [[tryleave]] -// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: store i8 0, i8* % +// CHECK-NEXT: br label % // __finally block doesn't return, __finally.cont doesn't exist. int __leave_with___finally_noreturn() { @@ -94,8 +94,8 @@ int __leave_with___finally_noreturn() { // CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: store i32 23 // CHECK: [[tryleave]] -// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: store i8 0, i8* % +// CHECK-NEXT: br label % // The "normal" case. int __leave_with___finally() { @@ -110,7 +110,7 @@ int __leave_with___finally() { return 1; } // CHECK-LABEL: define i32 @__leave_with___finally() -// CHECK: invoke void @g() +// CHECK: invoke void bitcast (void (...)* @g to void ()*)() // CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}} // For __finally, there needs to be an explicit __try.__leave, because // abnormal.termination.slot needs to be set there. @@ -118,8 +118,8 @@ int __leave_with___finally() { // CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: store i32 23 // CHECK: [[tryleave]] -// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: store i8 0, i8* % +// CHECK-NEXT: br label % ////////////////////////////////////////////////////////////////////////////// @@ -142,37 +142,45 @@ int nested___except___finally() { } return 1; } +// The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___except___finally() -// CHECK-LABEL: invoke void @g() -// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label %[[g1_lpad:.*]] +// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] + +// CHECK: [[g1_cont]] +// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]] +// CHECK-NEXT: br label %[[finally:[^ ]*]] -// CHECK: [[g1_cont1]] -// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]] +// CHECK: [[finally]] +// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() +// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] + +// CHECK: [[g2_cont]] +// CHECK-NEXT: br label %[[tryleave:[^ ]*]] +// CHECK-NOT: store i32 23 -// CHECK: [[fin_cont]] +// Unused __finally continuation block // CHECK: store i32 51, i32* % +// CHECK-NEXT: br label %[[tryleave]] + +// CHECK: [[tryleave]] // CHECK-NEXT: br label %[[trycont:[^ ]*]] // CHECK: [[g1_lpad]] -// CHECK-NEXT: landingpad -// CHECK-NEXT: catch i8* null -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext true, i8* %[[fp]]) -// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]] +// CHECK: store i8 1, i8* % +// CHECK-NEXT: br label %[[finally]] // CHECK: [[g2_lpad]] -// CHECK: br label %[[trycont]] +// CHECK-NOT: %[[abnormal]] +// CHECK: br label %[[except:[^ ]*]] + +// CHECK: [[except]] +// CHECK-NEXT: br label %[[trycont]] // CHECK: [[trycont]] // CHECK-NEXT: ret i32 1 -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: call void @g() -// CHECK: unreachable - int nested___except___except() { int myres = 0; __try { @@ -194,7 +202,7 @@ int nested___except___except() { // The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___except___except() -// CHECK-LABEL: invoke void @g() +// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_cont]] @@ -205,7 +213,7 @@ int nested___except___except() { // CHECK: br label %[[except:[^ ]*]] // CHECK: [[except]] -// CHECK-NEXT: invoke void @g() +// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3 // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_cont]] @@ -248,7 +256,7 @@ int nested___finally___except() { // The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___finally___except() -// CHECK-LABEL: invoke void @g() +// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_cont]] @@ -258,7 +266,7 @@ int nested___finally___except() { // CHECK: br label %[[except:[^ ]*]] // CHECK: [[except]] -// CHECK-NEXT: invoke void @g() +// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_cont]] @@ -266,25 +274,31 @@ int nested___finally___except() { // CHECK-NOT: 23 // CHECK: [[g2_lpad]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext true, i8* %[[fp]]) -// CHECK-NEXT: br label %[[ehresume:[^ ]*]] +// CHECK: store i8 1, i8* %[[abnormal:[^ ]*]] +// CHECK-NEXT: br label %[[finally:[^ ]*]] // CHECK: [[trycont]] // CHECK: store i32 51, i32* % // CHECK-NEXT: br label %[[tryleave]] // CHECK: [[tryleave]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: store i8 0, i8* %[[abnormal]] +// CHECK-NEXT: br label %[[finally:[^ ]*]] + +// CHECK: [[finally]] +// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]] +// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0 +// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]] + +// CHECK: [[finallycont]] // CHECK-NEXT: ret i32 1 +// CHECK: [[finallyresume]] +// CHECK-NEXT: br label %[[ehresume:[^ ]*]] + // CHECK: [[ehresume]] // CHECK: resume -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: ret void - int nested___finally___finally() { int myres = 0; __try { @@ -306,44 +320,51 @@ int nested___finally___finally() { // The order of basic blocks in the below doesn't matter. // CHECK-LABEL: define i32 @nested___finally___finally() -// CHECK-LABEL: invoke void @g() +// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)() // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_cont]] // CHECK: store i32 16, i32* %[[myres:[^ ]*]], -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]] +// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] +// CHECK-NEXT: br label %[[finally:[^ ]*]] + +// CHECK: [[finally]] +// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3 +// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] + +// CHECK: [[g2_cont]] +// CHECK-NEXT: br label %[[tryleave:[^ ]*]] +// CHECK-NOT: store i32 23 -// CHECK: [[finally_cont]] +// There's an unreachable block for the skipped `myres = 51`. // CHECK: store i32 51, i32* %[[myres]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK-NEXT: br label %[[tryleave]] + +// CHECK: [[tryleave]] +// CHECK-NEXT: store i8 0, i8* %[[abnormal]] +// CHECK-NEXT: br label %[[outerfinally:[^ ]*]] + +// CHECK: [[outerfinally]] +// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]] +// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0 +// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]] + +// CHECK: [[finallycont]] // CHECK-NEXT: ret i32 1 // CHECK: [[g1_lpad]] -// CHECK-NEXT: landingpad -// CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) -// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]] +// CHECK: store i8 1, i8* %[[abnormal]] +// CHECK-NEXT: br label %[[finally:[^ ]*]] // CHECK: [[g2_lpad]] -// CHECK-NEXT: landingpad -// CHECK-NEXT: cleanup -// CHECK: br label %[[ehcleanup:.*]] - -// CHECK: [[finally_cont2]] -// CHECK: br label %[[ehcleanup]] +// CHECK: br label %[[ehcleanup:[^ ]*]] // CHECK: [[ehcleanup]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) -// CHECK: resume +// CHECK-NEXT: store i8 1, i8* %[[abnormal]] +// CHECK-NEXT: br label %[[outerfinally]] -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: ret void +// CHECK: [[finallyresume]] +// CHECK-NEXT: br label %[[ehresume:[^ ]*]] -// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: call void @g() -// CHECK: unreachable +// CHECK: [[ehresume]] +// CHECK: resume diff --git a/clang/test/CodeGen/exceptions-seh.c b/clang/test/CodeGen/exceptions-seh.c index 9a273ced567..2d9d4b1f018 100644 --- a/clang/test/CodeGen/exceptions-seh.c +++ b/clang/test/CodeGen/exceptions-seh.c @@ -118,6 +118,8 @@ int nested_try(void) { // CHECK: [[inner_try_cont]] // CHECK: br label %[[outer_try_cont]] +// FIXME: This lowering of __finally can't actually work, it will have to +// change. static unsigned g = 0; void basic_finally(void) { ++g; @@ -136,23 +138,24 @@ void basic_finally(void) { // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]]) +// CHECK: br label %[[finally:[^ ]*]] +// +// CHECK: [[finally]] +// CHECK: load i32, i32* @g +// CHECK: add i32 %{{.*}}, -1 +// CHECK: store i32 %{{.*}}, i32* @g +// CHECK: icmp eq +// CHECK: br i1 %{{.*}}, label +// // CHECK: ret void // // CHECK: [[lpad]] // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]]) +// CHECK: br label %[[finally]] +// // CHECK: resume -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -// CHECK: load i32, i32* @g, align 4 -// CHECK: add i32 %{{.*}}, -1 -// CHECK: store i32 %{{.*}}, i32* @g, align 4 -// CHECK: ret void - int returns_int(void); int except_return(void) { __try { diff --git a/clang/test/CodeGenCXX/exceptions-seh.cpp b/clang/test/CodeGenCXX/exceptions-seh.cpp index cb5f6dfad90..5f93cb1be3f 100644 --- a/clang/test/CodeGenCXX/exceptions-seh.cpp +++ b/clang/test/CodeGenCXX/exceptions-seh.cpp @@ -5,7 +5,6 @@ // RUN: -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX -extern "C" unsigned long _exception_code(); extern "C" void might_throw(); struct HasCleanup { @@ -96,47 +95,4 @@ void use_seh_in_lambda() { // CHECK: invoke void @might_throw() #[[NOINLINE]] // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -static int my_unique_global; - -extern "C" inline void use_seh_in_inline_func() { - __try { - might_throw(); - } __except(_exception_code() == 424242) { - } - __try { - might_throw(); - } __finally { - my_unique_global = 1234; - } -} - -void use_inline() { - use_seh_in_inline_func(); -} - -// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat { -// CHECK: invoke void @might_throw() -// -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*) -// -// CHECK: invoke void @might_throw() -// -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i1 zeroext false, i8* %[[fp]]) -// CHECK: ret void -// -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -// CHECK-NEXT: cleanup -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i1 zeroext true, i8* %[[fp]]) - -// CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) -// CHECK: icmp eq i32 %{{.*}}, 424242 -// CHECK: zext i1 %{{.*}} to i32 -// CHECK: ret i32 - -// CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) -// CHECK: store i32 1234, i32* @my_unique_global - // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp index 0bc43cdbd45..a547dc6d9f8 100644 --- a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp +++ b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -1,6 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough %s - int fallthrough(int n) { switch (n / 10) { if (n - 1) { @@ -300,3 +299,8 @@ int fallthrough_targets(int n) { } return n; } + +[[clang::fallthrough]] int a; // expected-error {{'fallthrough' attribute only applies to empty statements}} +[[clang::fallthrough]] int f(); // expected-error {{'fallthrough' attribute only applies to empty statements}} +void g([[clang::fallthrough]] int p); // expected-error {{'fallthrough' attribute only applies to empty statements}} +struct [[clang::fallthrough]] S; // expected-error {{'fallthrough' attribute only applies to empty statements}} |