diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -873,8 +873,13 @@ // If there's exactly one branch-after and no other threads, // we can route it without a switch. + // Skip for SEH, since ExitSwitch is used to generate code to indicate + // abnormal termination. (SEH: Except _leave and fall-through at + // the end, all other exits in a _try (return/goto/continue/break) + // are considered as abnormal terminations, using NormalCleanupDestSlot + // to indicate abnormal termination) if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough && - Scope.getNumBranchAfters() == 1) { + !currentFunctionUsesSEHTry() && Scope.getNumBranchAfters() == 1) { assert(!BranchThroughDest || !IsActive); // Clean up the possibly dead store to the cleanup dest slot. diff --git a/clang/test/CodeGen/exceptions-seh-finally.c b/clang/test/CodeGen/exceptions-seh-finally.c --- a/clang/test/CodeGen/exceptions-seh-finally.c +++ b/clang/test/CodeGen/exceptions-seh-finally.c @@ -154,8 +154,11 @@ } } // CHECK-LABEL: define dso_local i32 @finally_with_return() +// CHECK: store i32 1, ptr %cleanup.dest.slot +// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot +// CHECK: icmp ne i32 %cleanup.dest // CHECK: call void @"?fin$0@0@finally_with_return@@"({{.*}}) -// CHECK-NEXT: ret i32 42 +// CHECK: ret i32 42 // CHECK: define internal void @"?fin$0@0@finally_with_return@@"({{.*}}) // CHECK-SAME: [[finally_attrs]] diff --git a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp --- a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp +++ b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s +// CHECK-LABEL: @main() // CHECK: invoke void @llvm.seh.try.begin() // CHECK: invoke void @llvm.seh.try.begin() // CHECK: %[[src:[0-9-]+]] = load volatile i32, ptr %i @@ -40,3 +41,29 @@ } return 0; } + +// CHECK-LABEL:@"?foo@@YAXXZ"() +// CHECK: invoke.cont: +// CHECK: invoke void @llvm.seh.try.begin() +// CHECK: store volatile i32 1, ptr %cleanup.dest.slot +// CHECK: invoke void @llvm.seh.try.end() +// CHECK: invoke.cont2: +// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot +// CHECK: %1 = icmp ne i32 %cleanup.dest, 0 +// CHECK: %2 = zext i1 %1 to i8 +// CHECK: call void @"?fin$0@0@foo@@"(i8 noundef %2, ptr noundef %0) +// CHECK: ehcleanup: +// CHECK: call void @"?fin$0@0@foo@@"(i8 noundef 1, ptr noundef %4) +void foo() +{ + __try { + return; + } + __finally { + if (_abnormal_termination()) { + printf("Passed\n"); + } else { + printf("Failed\n"); + } + } +}