summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2015-02-26 22:34:33 +0000
committerNico Weber <nicolasweber@gmx.de>2015-02-26 22:34:33 +0000
commitff62a6a0b79da24fe6336fe1dfbe1bc11d0a563a (patch)
tree89207f1f0497d60acc34f2ad6825ec63583d6c54 /clang/test/CodeGen
parent653773d0048de921fbd5cf6a4aa2767a7cd9158a (diff)
downloadbcm5719-llvm-ff62a6a0b79da24fe6336fe1dfbe1bc11d0a563a.tar.gz
bcm5719-llvm-ff62a6a0b79da24fe6336fe1dfbe1bc11d0a563a.zip
Don't crash on leaving nested __finally blocks through an EH edge.
The __finally emission block tries to be clever by removing unused continuation edges if there's an unconditional jump out of the __finally block. With exception edges, the EH continuation edge isn't always unused though and we'd crash in a few places. Just don't be clever. That makes the IR for __finally blocks a bit longer in some cases (hence small and behavior-preserving changes to existing tests), but it makes no difference in general and it fixes the last crash from PR22553. http://reviews.llvm.org/D7918 llvm-svn: 230697
Diffstat (limited to 'clang/test/CodeGen')
-rw-r--r--clang/test/CodeGen/exceptions-seh-finally.c93
-rw-r--r--clang/test/CodeGen/exceptions-seh-leave.c12
2 files changed, 98 insertions, 7 deletions
diff --git a/clang/test/CodeGen/exceptions-seh-finally.c b/clang/test/CodeGen/exceptions-seh-finally.c
index 64b3ffdf187..1bb60d820a9 100644
--- a/clang/test/CodeGen/exceptions-seh-finally.c
+++ b/clang/test/CodeGen/exceptions-seh-finally.c
@@ -193,12 +193,99 @@ int nested___finally___finally() {
// CHECK-NEXT: br label %[[finally:[^ ]*]]
//
// CHECK: [[finally]]
-// CHECK-NEXT: store i32 1, i32* %
-// CHECK-NEXT: store i8 0, i8* %
+// CHECK-NEXT: store i32 1, i32* %
+// CHECK-NEXT: store i32 1, i32* %
+// CHECK-NEXT: br label %[[cleanup:[^ ]*]]
+//
+// 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: ret i32 1
+// CHECK-NEXT: %[[dest:[^ ]*]] = load 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* %
+// CHECK-NEXT: ret i32 %[[reg]]
+
+int nested___finally___finally_with_eh_edge() {
+ __try {
+ __try {
+ might_crash();
+ } __finally {
+ return 899;
+ }
+ } __finally {
+ // Intentionally no return here.
+ }
+ return 912;
+}
+// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
+// CHECK: invoke void @might_crash() #3
+// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+//
+// 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:[^ ]*]]
+//
+// The inner 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: %[[abnormallocal:[^ ]*]] = load 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* %
+// CHECK-NEXT: switch i32 %[[dest]]
+// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]]
+//
+// CHECK: [[cleanupcont]]
+// CHECK-NEXT: store i32 912, i32* %
+// CHECK-NEXT: br label %[[return:[^ ]*]]
+//
+//
+// CHECK: [[lpad]]
+// CHECK-NEXT: landingpad
+// CHECK-NEXT: cleanup
+// 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* %
+// CHECK-NEXT: ret i32 %[[reg]]
+//
+// The ehresume block, not reachable either.
+// CHECK: [[ehresume]]
+// CHECK: resume
diff --git a/clang/test/CodeGen/exceptions-seh-leave.c b/clang/test/CodeGen/exceptions-seh-leave.c
index c590bd87033..7901c8c2fbd 100644
--- a/clang/test/CodeGen/exceptions-seh-leave.c
+++ b/clang/test/CodeGen/exceptions-seh-leave.c
@@ -162,6 +162,13 @@ int nested___except___finally() {
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
+// 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: store i8 1, i8* %
// CHECK-NEXT: br label %[[finally]]
@@ -171,14 +178,11 @@ int nested___except___finally() {
// CHECK: br label %[[except:[^ ]*]]
// CHECK: [[except]]
-// CHECK-NEXT: br label %[[trycont:[^ ]*]]
+// CHECK-NEXT: br label %[[trycont]]
// CHECK: [[trycont]]
// CHECK-NEXT: ret i32 1
-// CHECK: [[tryleave]]
-// CHECK-NEXT: br label %[[trycont]]
-
int nested___except___except() {
int myres = 0;
__try {
OpenPOWER on IntegriCloud