https://github.com/MuellerMP updated 
https://github.com/llvm/llvm-project/pull/167176

>From 7e7812d663b2d914d9d6962c3c03f0f66e2c522f Mon Sep 17 00:00:00 2001
From: MuellerMP <[email protected]>
Date: Wed, 26 Nov 2025 16:20:12 +0100
Subject: [PATCH] [WinEH] Fix try scopes leaking to caller on inline

This fixes issue #164169

When inlining functions compiled with -EHa, try scope terminators might need to 
be inserted before inlined returns.
This prevents leaking try scopes over to the caller.
Try scopes can be ended before a ret due to the unwinder forwarding exceptions 
in the seh epilog to the caller.
---
 clang/lib/CodeGen/CGException.cpp             |  26 +++-
 .../windows-seh-EHa-TryScopeTermination1.cpp  |  57 ++++++++
 .../windows-seh-EHa-TryScopeTermination2.cpp  | 132 ++++++++++++++++++
 .../windows-seh-EHa-TryScopeTermination3.cpp  |  92 ++++++++++++
 4 files changed, 303 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGen/windows-seh-EHa-TryScopeTermination1.cpp
 create mode 100644 clang/test/CodeGen/windows-seh-EHa-TryScopeTermination2.cpp
 create mode 100644 clang/test/CodeGen/windows-seh-EHa-TryScopeTermination3.cpp

diff --git a/clang/lib/CodeGen/CGException.cpp 
b/clang/lib/CodeGen/CGException.cpp
index e9d20672ce185..cbbb0b03909be 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -635,6 +635,13 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
     ExitCXXTryStmt(S);
 }
 
+struct TerminateTryScope final : EHScopeStack::Cleanup {
+  TerminateTryScope() {}
+
+  // this is a noop scope that triggers the scope end emission in CGCleanup
+  void Emit(CodeGenFunction &CGF, Flags flags) override {}
+};
+
 void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
   unsigned NumHandlers = S.getNumHandlers();
   EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);
@@ -666,8 +673,11 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, 
bool IsFnTryBlock) {
       CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), 
Handler);
       // Under async exceptions, catch(...) need to catch HW exception too
       // Mark scope with SehTryBegin as a SEH __try scope
-      if (getLangOpts().EHAsynch)
+      if (getLangOpts().EHAsynch) {
         EmitSehTryScopeBegin();
+        // Push cleanup to emit the end of the scope
+        EHStack.pushCleanup<TerminateTryScope>(NormalCleanup);
+      }
     }
   }
 }
@@ -1211,6 +1221,10 @@ void CodeGenFunction::popCatchScope() {
 }
 
 void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
+  // For EHa we might have a cleanup block for the try end
+  if (EHStack.begin()->getKind() == EHScope::Cleanup)
+    PopCleanupBlock();
+
   unsigned NumHandlers = S.getNumHandlers();
   EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin());
   assert(CatchScope.getNumHandlers() == NumHandlers);
@@ -2187,6 +2201,11 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt 
&S) {
   const SEHExceptStmt *Except = S.getExceptHandler();
   assert(Except);
   EHCatchScope *CatchScope = EHStack.pushCatch(1);
+
+  if (getLangOpts().EHAsynch) {
+    EHStack.pushCleanup<TerminateTryScope>(NormalCleanup);
+  }
+
   SEHCodeSlotStack.push_back(
       CreateMemTemp(getContext().IntTy, "__exception_code"));
 
@@ -2217,9 +2236,8 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) 
{
   }
 
   // IsEHa: emit an invoke _seh_try_end() to mark end of FT flow
-  if (getLangOpts().EHAsynch && Builder.GetInsertBlock()) {
-    llvm::FunctionCallee SehTryEnd = getSehTryEndFn(CGM);
-    EmitRuntimeCallOrInvoke(SehTryEnd);
+  if (getLangOpts().EHAsynch) {
+    PopCleanupBlock();
   }
 
   // Otherwise, we must have an __except block.
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination1.cpp 
b/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination1.cpp
new file mode 100644
index 0000000000000..a648362b3a04f
--- /dev/null
+++ b/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination1.cpp
@@ -0,0 +1,57 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions 
-fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration 
-emit-llvm %s -o - | FileCheck %s
+// Check that the try scope of main is properly terminated.
+[[noreturn]] void Exit();
+
+// CHECK-LABEL: define dso_local noundef i32 @main(
+// CHECK-SAME: i32 noundef [[ARGC:%.*]], ptr noundef [[TMP0:%.*]]) 
#[[ATTR0:[0-9]+]] personality ptr @__CxxFrameHandler3 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[ARGC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[TMP:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK-NEXT:    store i32 [[ARGC]], ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label 
%[[CATCH_DISPATCH:.*]]
+// CHECK:       [[INVOKE_CONT]]:
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 0
+// CHECK-NEXT:    br i1 [[TOBOOL]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
+// CHECK:       [[IF_THEN]]:
+// CHECK-NEXT:    store i32 -1, ptr [[TMP]], align 4
+// CHECK-NEXT:    invoke void @_CxxThrowException(ptr [[TMP]], ptr @_TI1H) 
#[[ATTR4:[0-9]+]]
+// CHECK-NEXT:            to label %[[UNREACHABLE:.*]] unwind label 
%[[CATCH_DISPATCH]]
+// CHECK:       [[IF_END]]:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[RETVAL]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT1:.*]] unwind label 
%[[CATCH_DISPATCH]]
+// CHECK:       [[CATCH_DISPATCH]]:
+// CHECK-NEXT:    [[TMP3:%.*]] = catchswitch within none [label %[[CATCH:.*]]] 
unwind to caller
+// CHECK:       [[CATCH]]:
+// CHECK-NEXT:    [[TMP4:%.*]] = catchpad within [[TMP3]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    catchret from [[TMP4]] to label %[[CATCHRET_DEST:.*]]
+// CHECK:       [[CATCHRET_DEST]]:
+// CHECK-NEXT:    br label %[[TRY_CONT:.*]]
+// CHECK:       [[TRY_CONT]]:
+// CHECK-NEXT:    call void @"?Exit@@YAXXZ"() #[[ATTR4]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[INVOKE_CONT1]]:
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    ret i32 [[TMP5]]
+// CHECK:       [[UNREACHABLE]]:
+// CHECK-NEXT:    unreachable
+//
+int main(int argc, char**) noexcept
+{
+  try {
+    if (!argc) { throw -1; }
+    return argc;
+  } catch (...) {
+  }
+
+  Exit();
+  return 0;
+}
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination2.cpp 
b/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination2.cpp
new file mode 100644
index 0000000000000..c479686e8dced
--- /dev/null
+++ b/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination2.cpp
@@ -0,0 +1,132 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions 
-fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration 
-emit-llvm %s -o - | FileCheck %s
+// Check that both try scopes containing a return statement are properly 
terminated.
+void DoSth();
+[[noreturn]] void Exit();
+
+// CHECK-LABEL: define dso_local noundef i32 @main(
+// CHECK-SAME: i32 noundef [[ARGC:%.*]], ptr noundef [[TMP0:%.*]]) 
#[[ATTR0:[0-9]+]] personality ptr @__CxxFrameHandler3 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[ARGC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[TMP:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK-NEXT:    store i32 [[ARGC]], ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label 
%[[CATCH_DISPATCH6:.*]]
+// CHECK:       [[INVOKE_CONT]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT1:.*]] unwind label 
%[[CATCH_DISPATCH:.*]]
+// CHECK:       [[INVOKE_CONT1]]:
+// CHECK-NEXT:    invoke void @"?DoSth@@YAXXZ"()
+// CHECK-NEXT:            to label %[[INVOKE_CONT2:.*]] unwind label 
%[[CATCH_DISPATCH]]
+// CHECK:       [[INVOKE_CONT2]]:
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT3:.*]] unwind label 
%[[CATCH_DISPATCH]]
+// CHECK:       [[CATCH_DISPATCH]]:
+// CHECK-NEXT:    [[TMP1:%.*]] = catchswitch within none [label %[[CATCH:.*]]] 
unwind label %[[CATCH_DISPATCH6]]
+// CHECK:       [[CATCH]]:
+// CHECK-NEXT:    [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end() [ "funclet"(token 
[[TMP2]]) ]
+// CHECK-NEXT:            to label %[[INVOKE_CONT4:.*]] unwind label 
%[[CATCH_DISPATCH6]]
+// CHECK:       [[INVOKE_CONT4]]:
+// CHECK-NEXT:    catchret from [[TMP2]] to label %[[CATCHRET_DEST:.*]]
+// CHECK:       [[CATCHRET_DEST]]:
+// CHECK-NEXT:    br label %[[TRY_CONT:.*]]
+// CHECK:       [[TRY_CONT]]:
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT5:.*]] unwind label 
%[[CATCH_DISPATCH6]]
+// CHECK:       [[CATCH_DISPATCH6]]:
+// CHECK-NEXT:    [[TMP3:%.*]] = catchswitch within none [label 
%[[CATCH7:.*]]] unwind to caller
+// CHECK:       [[CATCH7]]:
+// CHECK-NEXT:    [[TMP4:%.*]] = catchpad within [[TMP3]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    catchret from [[TMP4]] to label %[[CATCHRET_DEST8:.*]]
+// CHECK:       [[CATCHRET_DEST8]]:
+// CHECK-NEXT:    br label %[[TRY_CONT9:.*]]
+// CHECK:       [[TRY_CONT9]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT10:.*]] unwind label 
%[[CATCH_DISPATCH19:.*]]
+// CHECK:       [[INVOKE_CONT10]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT11:.*]] unwind label 
%[[CATCH_DISPATCH13:.*]]
+// CHECK:       [[INVOKE_CONT11]]:
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP5]], 0
+// CHECK-NEXT:    br i1 [[TOBOOL]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
+// CHECK:       [[IF_THEN]]:
+// CHECK-NEXT:    store i32 -1, ptr [[TMP]], align 4
+// CHECK-NEXT:    invoke void @_CxxThrowException(ptr [[TMP]], ptr @_TI1H) 
#[[ATTR5:[0-9]+]]
+// CHECK-NEXT:            to label %[[UNREACHABLE:.*]] unwind label 
%[[CATCH_DISPATCH13]]
+// CHECK:       [[INVOKE_CONT5]]:
+// CHECK-NEXT:    br label %[[TRY_CONT9]]
+// CHECK:       [[INVOKE_CONT3]]:
+// CHECK-NEXT:    br label %[[TRY_CONT]]
+// CHECK:       [[IF_END]]:
+// CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP6]], ptr [[RETVAL]], align 4
+// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT12:.*]] unwind label 
%[[CATCH_DISPATCH13]]
+// CHECK:       [[CATCH_DISPATCH13]]:
+// CHECK-NEXT:    [[TMP7:%.*]] = catchswitch within none [label 
%[[CATCH14:.*]]] unwind label %[[CATCH_DISPATCH19]]
+// CHECK:       [[CATCH14]]:
+// CHECK-NEXT:    [[TMP8:%.*]] = catchpad within [[TMP7]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end() [ "funclet"(token 
[[TMP8]]) ]
+// CHECK-NEXT:            to label %[[INVOKE_CONT15:.*]] unwind label 
%[[CATCH_DISPATCH19]]
+// CHECK:       [[INVOKE_CONT15]]:
+// CHECK-NEXT:    catchret from [[TMP8]] to label %[[CATCHRET_DEST16:.*]]
+// CHECK:       [[CATCHRET_DEST16]]:
+// CHECK-NEXT:    br label %[[TRY_CONT17:.*]]
+// CHECK:       [[TRY_CONT17]]:
+// CHECK-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
+// CHECK-NEXT:    br label %[[CLEANUP:.*]]
+// CHECK:       [[CLEANUP]]:
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT18:.*]] unwind label 
%[[CATCH_DISPATCH19]]
+// CHECK:       [[CATCH_DISPATCH19]]:
+// CHECK-NEXT:    [[TMP9:%.*]] = catchswitch within none [label 
%[[CATCH20:.*]]] unwind to caller
+// CHECK:       [[CATCH20]]:
+// CHECK-NEXT:    [[TMP10:%.*]] = catchpad within [[TMP9]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    catchret from [[TMP10]] to label %[[CATCHRET_DEST21:.*]]
+// CHECK:       [[CATCHRET_DEST21]]:
+// CHECK-NEXT:    br label %[[TRY_CONT22:.*]]
+// CHECK:       [[TRY_CONT22]]:
+// CHECK-NEXT:    call void @"?Exit@@YAXXZ"() #[[ATTR5]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[INVOKE_CONT18]]:
+// CHECK-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], 
align 4
+// CHECK-NEXT:    switch i32 [[CLEANUP_DEST]], label %[[UNREACHABLE]] [
+// CHECK-NEXT:      i32 0, label %[[CLEANUP_CONT:.*]]
+// CHECK-NEXT:      i32 1, label %[[RETURN:.*]]
+// CHECK-NEXT:    ]
+// CHECK:       [[CLEANUP_CONT]]:
+// CHECK-NEXT:    br label %[[TRY_CONT22]]
+// CHECK:       [[INVOKE_CONT12]]:
+// CHECK-NEXT:    br label %[[CLEANUP]]
+// CHECK:       [[RETURN]]:
+// CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    ret i32 [[TMP11]]
+// CHECK:       [[UNREACHABLE]]:
+// CHECK-NEXT:    unreachable
+//
+int main(int argc, char**) noexcept
+{
+  try {
+    try {
+      DoSth();
+    } catch(...) {}
+  } catch(...) {}
+
+  try {
+    try {
+      if (!argc) { throw -1; }
+      return argc;
+    } catch (...) {}
+  } catch (...) {}
+
+  Exit();
+  return 0;
+}
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination3.cpp 
b/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination3.cpp
new file mode 100644
index 0000000000000..6438a600695ec
--- /dev/null
+++ b/clang/test/CodeGen/windows-seh-EHa-TryScopeTermination3.cpp
@@ -0,0 +1,92 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions 
-fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration 
-emit-llvm %s -o - | FileCheck %s
+// Check that the both __try scopes containing a return statement are properly 
terminated.
+[[noreturn]] void Exit();
+volatile int *p{nullptr};
+
+// CHECK-LABEL: define dso_local noundef i32 @main(
+// CHECK-SAME: i32 noundef [[ARGC:%.*]], ptr noundef [[TMP0:%.*]]) 
#[[ATTR0:[0-9]+]] personality ptr @__C_specific_handler {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[ARGC_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[__EXCEPTION_CODE:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[__EXCEPTION_CODE1:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK-NEXT:    store i32 [[ARGC]], ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label 
%[[CATCH_DISPATCH6:.*]]
+// CHECK:       [[INVOKE_CONT]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT2:.*]] unwind label 
%[[CATCH_DISPATCH:.*]]
+// CHECK:       [[INVOKE_CONT2]]:
+// CHECK-NEXT:    [[TMP1:%.*]] = load volatile i32, ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 0
+// CHECK-NEXT:    br i1 [[TOBOOL]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
+// CHECK:       [[IF_THEN]]:
+// CHECK-NEXT:    [[TMP2:%.*]] = load volatile ptr, ptr @"?p@@3PECHEC", align 8
+// CHECK-NEXT:    store volatile i32 0, ptr [[TMP2]], align 4
+// CHECK-NEXT:    br label %[[IF_END]]
+// CHECK:       [[IF_END]]:
+// CHECK-NEXT:    [[TMP3:%.*]] = load volatile i32, ptr [[ARGC_ADDR]], align 4
+// CHECK-NEXT:    store volatile i32 [[TMP3]], ptr [[RETVAL]], align 4
+// CHECK-NEXT:    store volatile i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.try.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT3:.*]] unwind label 
%[[CATCH_DISPATCH]]
+// CHECK:       [[CATCH_DISPATCH]]:
+// CHECK-NEXT:    [[TMP4:%.*]] = catchswitch within none [label 
%[[__EXCEPT:.*]]] unwind label %[[CATCH_DISPATCH6]]
+// CHECK:       [[__EXCEPT]]:
+// CHECK-NEXT:    [[TMP5:%.*]] = catchpad within [[TMP4]] [ptr null]
+// CHECK-NEXT:    catchret from [[TMP5]] to label %[[__EXCEPT4:.*]]
+// CHECK:       [[__EXCEPT4]]:
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.eh.exceptioncode(token 
[[TMP5]])
+// CHECK-NEXT:    store volatile i32 [[TMP6]], ptr [[__EXCEPTION_CODE1]], 
align 4
+// CHECK-NEXT:    br label %[[__TRY_CONT:.*]]
+// CHECK:       [[__TRY_CONT]]:
+// CHECK-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
+// CHECK-NEXT:    br label %[[CLEANUP:.*]]
+// CHECK:       [[CLEANUP]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.end()
+// CHECK-NEXT:            to label %[[INVOKE_CONT5:.*]] unwind label 
%[[CATCH_DISPATCH6]]
+// CHECK:       [[CATCH_DISPATCH6]]:
+// CHECK-NEXT:    [[TMP7:%.*]] = catchswitch within none [label 
%[[__EXCEPT7:.*]]] unwind to caller
+// CHECK:       [[__EXCEPT7]]:
+// CHECK-NEXT:    [[TMP8:%.*]] = catchpad within [[TMP7]] [ptr null]
+// CHECK-NEXT:    catchret from [[TMP8]] to label %[[__EXCEPT8:.*]]
+// CHECK:       [[__EXCEPT8]]:
+// CHECK-NEXT:    [[TMP9:%.*]] = call i32 @llvm.eh.exceptioncode(token 
[[TMP8]])
+// CHECK-NEXT:    store i32 [[TMP9]], ptr [[__EXCEPTION_CODE]], align 4
+// CHECK-NEXT:    br label %[[__TRY_CONT9:.*]]
+// CHECK:       [[__TRY_CONT9]]:
+// CHECK-NEXT:    call void @"?Exit@@YAXXZ"() #[[ATTR4:[0-9]+]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[INVOKE_CONT5]]:
+// CHECK-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], 
align 4
+// CHECK-NEXT:    switch i32 [[CLEANUP_DEST]], label %[[UNREACHABLE:.*]] [
+// CHECK-NEXT:      i32 0, label %[[CLEANUP_CONT:.*]]
+// CHECK-NEXT:      i32 1, label %[[RETURN:.*]]
+// CHECK-NEXT:    ]
+// CHECK:       [[CLEANUP_CONT]]:
+// CHECK-NEXT:    br label %[[__TRY_CONT9]]
+// CHECK:       [[INVOKE_CONT3]]:
+// CHECK-NEXT:    br label %[[CLEANUP]]
+// CHECK:       [[RETURN]]:
+// CHECK-NEXT:    [[TMP10:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    ret i32 [[TMP10]]
+// CHECK:       [[UNREACHABLE]]:
+// CHECK-NEXT:    unreachable
+//
+int main(int argc, char**) noexcept
+{
+  __try {
+    __try {
+      if (!argc) { *p = 0; }
+      return argc;
+    } __except(1) {}
+  } __except(1) {}
+
+  Exit();
+  return 0;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to