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

>From 1ef74fa56ae9b362ccd76ad940363764d36ad97c 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/CGCleanup.cpp               |  14 ++-
 clang/lib/CodeGen/CGException.cpp             |  47 ++++++--
 clang/lib/CodeGen/CodeGenFunction.h           |   5 +-
 .../test/CodeGen/windows-seh-EHa-Inline1.cpp  |  62 +++++++++++
 .../test/CodeGen/windows-seh-EHa-Inline2.cpp  | 103 ++++++++++++++++++
 .../test/CodeGen/windows-seh-EHa-Inline3.cpp  |  91 ++++++++++++++++
 llvm/lib/CodeGen/WinEHPrepare.cpp             |   4 +-
 7 files changed, 312 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/CodeGen/windows-seh-EHa-Inline1.cpp
 create mode 100644 clang/test/CodeGen/windows-seh-EHa-Inline2.cpp
 create mode 100644 clang/test/CodeGen/windows-seh-EHa-Inline3.cpp

diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 28ac9bf396356..3beaa95f0b8e0 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -1329,8 +1329,11 @@ void CodeGenFunction::EmitCXXTemporary(const 
CXXTemporary *Temporary,
 // Need to set "funclet" in OperandBundle properly for noThrow
 //       intrinsic (see CGCall.cpp)
 static void EmitSehScope(CodeGenFunction &CGF,
-                         llvm::FunctionCallee &SehCppScope) {
-  llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
+                         llvm::FunctionCallee &SehCppScope,
+                         llvm::BasicBlock *InvokeDest = nullptr) {
+  if (!InvokeDest)
+    InvokeDest = CGF.getInvokeDest();
+
   assert(CGF.Builder.GetInsertBlock() && InvokeDest);
   llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
   SmallVector<llvm::OperandBundleDef, 1> BundleList =
@@ -1373,11 +1376,14 @@ void CodeGenFunction::EmitSehTryScopeBegin() {
 }
 
 // Invoke a llvm.seh.try.end at the end of a SEH scope for -EHa
-void CodeGenFunction::EmitSehTryScopeEnd() {
+void CodeGenFunction::EmitSehTryScopeEnd(bool ReuseCachedInvokeDest) {
   assert(getLangOpts().EHAsynch);
   llvm::FunctionType *FTy =
       llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
   llvm::FunctionCallee SehCppScope =
       CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
-  EmitSehScope(*this, SehCppScope);
+  if (ReuseCachedInvokeDest)
+    EmitSehScope(*this, SehCppScope, SehTryEndInvokeDest);
+  else
+    EmitSehScope(*this, SehCppScope);
 }
diff --git a/clang/lib/CodeGen/CGException.cpp 
b/clang/lib/CodeGen/CGException.cpp
index e9d20672ce185..19ae0cb46ec70 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -635,14 +635,23 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) 
{
     ExitCXXTryStmt(S);
 }
 
+struct TerminateTryScope final : EHScopeStack::Cleanup {
+  void Emit(CodeGenFunction &CGF, Flags flags) override {
+    CGF.EmitSehTryScopeEnd(true);
+  }
+};
+
+struct HandlerInfo {
+  CatchTypeInfo TypeInfo;
+  bool RequiresSehScope;
+};
+
 void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
   unsigned NumHandlers = S.getNumHandlers();
-  EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);
-
+  unsigned NumHandlerInfos = NumHandlers > 0 ? NumHandlers - 1 : 0;
+  llvm::SmallVector<HandlerInfo> HandlerInfos{NumHandlerInfos};
   for (unsigned I = 0; I != NumHandlers; ++I) {
     const CXXCatchStmt *C = S.getHandler(I);
-
-    llvm::BasicBlock *Handler = createBasicBlock("catch");
     if (C->getExceptionDecl()) {
       // FIXME: Dropping the reference type on the type into makes it
       // impossible to correctly implement catch-by-reference
@@ -660,14 +669,30 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt 
&S, bool IsFnTryBlock) {
       else
         TypeInfo = CGM.getCXXABI().getAddrOfCXXCatchHandlerType(
             CaughtType, C->getCaughtType());
-      CatchScope->setHandler(I, TypeInfo, Handler);
+      HandlerInfos.push_back({TypeInfo, false});
     } else {
+      bool HasEHa = getLangOpts().EHAsynch;
       // No exception decl indicates '...', a catch-all.
-      CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), 
Handler);
+      HandlerInfos.push_back({CGM.getCXXABI().getCatchAllTypeInfo(), HasEHa});
+      // Push, if needed, a terminator for the created SEH __try scope
+      if (HasEHa && !SehTryEndInvokeDest) {
+        EHStack.pushCleanup<TerminateTryScope>(NormalCleanup);
+      }
+    }
+  }
+
+  EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);
+
+  for (unsigned I = 0; I < HandlerInfos.size(); ++I) {
+    llvm::BasicBlock *Handler = createBasicBlock("catch");
+    auto HandlerInfo = HandlerInfos[I];
+    CatchScope->setHandler(I, HandlerInfo.TypeInfo, Handler);
+    if (HandlerInfo.RequiresSehScope) {
       // Under async exceptions, catch(...) need to catch HW exception too
       // Mark scope with SehTryBegin as a SEH __try scope
-      if (getLangOpts().EHAsynch)
-        EmitSehTryScopeBegin();
+      EmitSehTryScopeBegin();
+      if (!SehTryEndInvokeDest)
+        SehTryEndInvokeDest = getInvokeDest();
     }
   }
 }
@@ -1675,6 +1700,8 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) 
{
       EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
       if (SEHTryEpilogueStack.size() == 1) // outermost only
         TryBB = Builder.GetInsertBlock();
+      if (!SehTryEndInvokeDest)
+        SehTryEndInvokeDest = getInvokeDest();
     }
 
     EmitStmt(S.getTryBlock());
@@ -2186,6 +2213,10 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt 
&S) {
   // Otherwise, we must have an __except block.
   const SEHExceptStmt *Except = S.getExceptHandler();
   assert(Except);
+
+  if (getLangOpts().EHAsynch && !SehTryEndInvokeDest)
+    EHStack.pushCleanup<TerminateTryScope>(NormalCleanup);
+
   EHCatchScope *CatchScope = EHStack.pushCatch(1);
   SEHCodeSlotStack.push_back(
       CreateMemTemp(getContext().IntTy, "__exception_code"));
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 8c4c1c8c2dc95..8930d784da5e4 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2129,6 +2129,9 @@ class CodeGenFunction : public CodeGenTypeCache {
   /// Terminate funclets keyed by parent funclet pad.
   llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets;
 
+  /// Unwind destination for try scope end.
+  llvm::BasicBlock *SehTryEndInvokeDest = nullptr;
+
   /// Largest vector width used in ths function. Will be used to create a
   /// function attribute.
   unsigned LargestVectorWidth = 0;
@@ -3241,7 +3244,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   void EmitSehCppScopeBegin();
   void EmitSehCppScopeEnd();
   void EmitSehTryScopeBegin();
-  void EmitSehTryScopeEnd();
+  void EmitSehTryScopeEnd(bool ReuseCachedInvokeDest = false);
 
   bool EmitLifetimeStart(llvm::Value *Addr);
   void EmitLifetimeEnd(llvm::Value *Addr);
diff --git a/clang/test/CodeGen/windows-seh-EHa-Inline1.cpp 
b/clang/test/CodeGen/windows-seh-EHa-Inline1.cpp
new file mode 100644
index 0000000000000..26d8cc204274e
--- /dev/null
+++ b/clang/test/CodeGen/windows-seh-EHa-Inline1.cpp
@@ -0,0 +1,62 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -O3 -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 ExitOnThrow is terminated upon inlining into 
main.
+int AlwaysThrows(int);
+[[noreturn]] void Exit();
+
+int ExitOnThrow(int argc) noexcept
+{
+  try {
+    if (!argc) { throw -1; }
+    return argc;
+  } catch (...) {
+  }
+
+  Exit();
+  return 0;
+}
+
+// CHECK-LABEL: define dso_local noundef i32 @main(
+// CHECK-SAME: i32 noundef [[ARGC:%.*]], ptr noundef readnone captures(none) 
[[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] personality ptr 
@__CxxFrameHandler3 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[TMP_I]])
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT_I:.*]] unwind label 
%[[CATCH_DISPATCH_I:.*]]
+// CHECK:       [[INVOKE_CONT_I]]:
+// CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[ARGC]], 0
+// CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_THEN_I:.*]], label 
%[[IF_END_I:.*]]
+// CHECK:       [[IF_THEN_I]]:
+// CHECK-NEXT:    store i32 -1, ptr [[TMP_I]], align 4, !tbaa 
[[INT_TBAA7:![0-9]+]]
+// CHECK-NEXT:    invoke void @_CxxThrowException(ptr nonnull [[TMP_I]], ptr 
nonnull @_TI1H) #[[ATTR6:[0-9]+]]
+// CHECK-NEXT:            to label %[[UNREACHABLE_I:.*]] unwind label 
%[[CATCH_DISPATCH_I]]
+// CHECK:       [[CATCH_DISPATCH_I]]:
+// CHECK-NEXT:    [[TMP1:%.*]] = catchswitch within none [label 
%[[CATCH_I:.*]]] unwind to caller
+// CHECK:       [[CATCH_I]]:
+// CHECK-NEXT:    [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    catchret from [[TMP2]] to label %[[TRY_CONT_I:.*]]
+// CHECK:       [[TRY_CONT_I]]:
+// CHECK-NEXT:    call void @"?Exit@@YAXXZ"() #[[ATTR7:[0-9]+]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[IF_END_I]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.end()
+// CHECK-NEXT:            to label %"?ExitOnThrow@@[email protected]" unwind label 
%[[CATCH_DISPATCH_I]]
+// CHECK:       [[UNREACHABLE_I]]:
+// CHECK-NEXT:    unreachable
+// CHECK:       "?ExitOnThrow@@[email protected]":
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP_I]])
+// CHECK-NEXT:    [[CALL1:%.*]] = tail call noundef i32 
@"?AlwaysThrows@@YAHH@Z"(i32 noundef [[ARGC]])
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL1]], [[ARGC]]
+// CHECK-NEXT:    ret i32 [[ADD]]
+//
+int main(int argc, char**)
+{
+  auto data = ExitOnThrow(argc);
+  return data + AlwaysThrows(data);
+}
+//.
+// CHECK: [[INT_TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0}
+// CHECK: [[META8]] = !{!"int", [[META9:![0-9]+]], i64 0}
+// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0}
+// CHECK: [[META10]] = !{!"Simple C++ TBAA"}
+//.
diff --git a/clang/test/CodeGen/windows-seh-EHa-Inline2.cpp 
b/clang/test/CodeGen/windows-seh-EHa-Inline2.cpp
new file mode 100644
index 0000000000000..b7edcf00ecb7e
--- /dev/null
+++ b/clang/test/CodeGen/windows-seh-EHa-Inline2.cpp
@@ -0,0 +1,103 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -O3 -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 only the outermost try scope containing a return statement is 
terminated upon inlining into main.
+void DoSth();
+int AlwaysThrows(int);
+[[noreturn]] void Exit();
+
+int ExitOnThrow(int argc) noexcept
+{
+  try {
+    try {
+      DoSth();
+    } catch(...) {}
+  } catch(...) {}
+
+  try {
+    try {
+      if (!argc) { throw -1; }
+      return argc;
+    } catch (...) {}
+  } catch (...) {}
+
+  Exit();
+  return 0;
+}
+
+// CHECK-LABEL: define dso_local noundef i32 @main(
+// CHECK-SAME: i32 noundef [[ARGC:%.*]], ptr noundef readnone captures(none) 
[[TMP0:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] personality ptr 
@__CxxFrameHandler3 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[TMP_I]])
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT_I:.*]] unwind label 
%[[CATCH_DISPATCH4_I:.*]]
+// CHECK:       [[INVOKE_CONT_I]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT1_I:.*]] unwind label 
%[[CATCH_DISPATCH_I:.*]]
+// CHECK:       [[INVOKE_CONT1_I]]:
+// CHECK-NEXT:    invoke void @"?DoSth@@YAXXZ"()
+// CHECK-NEXT:            to label %[[TRY_CONT7_I:.*]] unwind label 
%[[CATCH_DISPATCH_I]]
+// CHECK:       [[CATCH_DISPATCH_I]]:
+// CHECK-NEXT:    [[TMP1:%.*]] = catchswitch within none [label 
%[[CATCH_I:.*]]] unwind label %[[CATCH_DISPATCH4_I]]
+// CHECK:       [[CATCH_I]]:
+// 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_CONT3_I:.*]] unwind label 
%[[CATCH_DISPATCH4_I]]
+// CHECK:       [[CATCH_DISPATCH4_I]]:
+// CHECK-NEXT:    [[TMP3:%.*]] = catchswitch within none [label 
%[[CATCH5_I:.*]]] unwind to caller
+// CHECK:       [[CATCH5_I]]:
+// CHECK-NEXT:    [[TMP4:%.*]] = catchpad within [[TMP3]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    catchret from [[TMP4]] to label %[[TRY_CONT7_I]]
+// CHECK:       [[TRY_CONT7_I]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT8_I:.*]] unwind label 
%[[CATCH_DISPATCH15_I:.*]]
+// CHECK:       [[INVOKE_CONT8_I]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT9_I:.*]] unwind label 
%[[CATCH_DISPATCH10_I:.*]]
+// CHECK:       [[INVOKE_CONT9_I]]:
+// CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[ARGC]], 0
+// CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_THEN_I:.*]], label 
%[[IF_END_I:.*]]
+// CHECK:       [[IF_THEN_I]]:
+// CHECK-NEXT:    store i32 -1, ptr [[TMP_I]], align 4, !tbaa 
[[INT_TBAA7:![0-9]+]]
+// CHECK-NEXT:    invoke void @_CxxThrowException(ptr nonnull [[TMP_I]], ptr 
nonnull @_TI1H) #[[ATTR7:[0-9]+]]
+// CHECK-NEXT:            to label %[[UNREACHABLE_I:.*]] unwind label 
%[[CATCH_DISPATCH10_I]]
+// CHECK:       [[CATCH_DISPATCH10_I]]:
+// CHECK-NEXT:    [[TMP5:%.*]] = catchswitch within none [label 
%[[CATCH11_I:.*]]] unwind label %[[CATCH_DISPATCH15_I]]
+// CHECK:       [[CATCH11_I]]:
+// CHECK-NEXT:    [[TMP6:%.*]] = catchpad within [[TMP5]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    invoke void @llvm.seh.scope.end() [ "funclet"(token 
[[TMP6]]) ]
+// CHECK-NEXT:            to label %[[INVOKE_CONT12_I:.*]] unwind label 
%[[CATCH_DISPATCH15_I]]
+// CHECK:       [[CATCH_DISPATCH15_I]]:
+// CHECK-NEXT:    [[TMP7:%.*]] = catchswitch within none [label 
%[[CATCH16_I:.*]]] unwind to caller
+// CHECK:       [[CATCH16_I]]:
+// CHECK-NEXT:    [[TMP8:%.*]] = catchpad within [[TMP7]] [ptr null, i32 0, 
ptr null]
+// CHECK-NEXT:    catchret from [[TMP8]] to label %[[TRY_CONT18_I:.*]]
+// CHECK:       [[TRY_CONT18_I]]:
+// CHECK-NEXT:    call void @"?Exit@@YAXXZ"() #[[ATTR8:[0-9]+]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[INVOKE_CONT12_I]]:
+// CHECK-NEXT:    catchret from [[TMP6]] to label %[[TRY_CONT18_I]]
+// CHECK:       [[INVOKE_CONT3_I]]:
+// CHECK-NEXT:    catchret from [[TMP2]] to label %[[TRY_CONT7_I]]
+// CHECK:       [[IF_END_I]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.end()
+// CHECK-NEXT:            to label %"?ExitOnThrow@@[email protected]" unwind label 
%[[CATCH_DISPATCH4_I]]
+// CHECK:       [[UNREACHABLE_I]]:
+// CHECK-NEXT:    unreachable
+// CHECK:       "?ExitOnThrow@@[email protected]":
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP_I]])
+// CHECK-NEXT:    [[CALL1:%.*]] = tail call noundef i32 
@"?AlwaysThrows@@YAHH@Z"(i32 noundef [[ARGC]])
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL1]], [[ARGC]]
+// CHECK-NEXT:    ret i32 [[ADD]]
+//
+int main(int argc, char**)
+{
+  auto data = ExitOnThrow(argc);
+  return data + AlwaysThrows(data);
+}
+//.
+// CHECK: [[INT_TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0}
+// CHECK: [[META8]] = !{!"int", [[META9:![0-9]+]], i64 0}
+// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0}
+// CHECK: [[META10]] = !{!"Simple C++ TBAA"}
+//.
diff --git a/clang/test/CodeGen/windows-seh-EHa-Inline3.cpp 
b/clang/test/CodeGen/windows-seh-EHa-Inline3.cpp
new file mode 100644
index 0000000000000..0ab117b6d2bf8
--- /dev/null
+++ b/clang/test/CodeGen/windows-seh-EHa-Inline3.cpp
@@ -0,0 +1,91 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -O3 -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 outermost __try scope containing a return statement is 
terminated upon inlining into main.
+int AlwaysThrows(int);
+[[noreturn]] void Exit();
+volatile int *p{nullptr};
+
+int ExitOnThrow(int argc) noexcept
+{
+  __try {
+    __try {
+      if (!argc) { *p = 0; }
+      return argc;
+    } __except(1) {}
+  } __except(1) {}
+
+  Exit();
+  return 0;
+}
+
+// CHECK-LABEL: define dso_local noundef i32 @main(
+// CHECK-SAME: i32 noundef [[ARGC:%.*]], ptr noundef readnone captures(none) 
[[TMP0:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] personality ptr 
@__C_specific_handler {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[ARGC_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[__EXCEPTION_CODE1_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[CLEANUP_DEST_SLOT_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull 
[[ARGC_ADDR_I]])
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull 
[[__EXCEPTION_CODE1_I]])
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull 
[[CLEANUP_DEST_SLOT_I]])
+// CHECK-NEXT:    store i32 [[ARGC]], ptr [[ARGC_ADDR_I]], align 4, !tbaa 
[[INT_TBAA7:![0-9]+]]
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT_I:.*]] unwind label 
%[[CATCH_DISPATCH5_I:.*]]
+// CHECK:       [[INVOKE_CONT_I]]:
+// CHECK-NEXT:    invoke void @llvm.seh.try.begin()
+// CHECK-NEXT:            to label %[[INVOKE_CONT2_I:.*]] unwind label 
%[[CATCH_DISPATCH_I:.*]]
+// CHECK:       [[CATCH_DISPATCH_I]]:
+// CHECK-NEXT:    [[TMP1:%.*]] = catchswitch within none [label 
%[[__EXCEPT_I:.*]]] unwind label %[[CATCH_DISPATCH5_I]]
+// CHECK:       [[__EXCEPT_I]]:
+// CHECK-NEXT:    [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null]
+// CHECK-NEXT:    catchret from [[TMP2]] to label %[[__EXCEPT3_I:.*]]
+// CHECK:       [[__EXCEPT3_I]]:
+// CHECK-NEXT:    [[TMP3:%.*]] = tail call i32 @llvm.eh.exceptioncode(token 
[[TMP2]])
+// CHECK-NEXT:    store volatile i32 [[TMP3]], ptr [[__EXCEPTION_CODE1_I]], 
align 4
+// CHECK-NEXT:    invoke void @llvm.seh.try.end()
+// CHECK-NEXT:            to label %[[__TRY_CONT8_I:.*]] unwind label 
%[[CATCH_DISPATCH5_I]]
+// CHECK:       [[CATCH_DISPATCH5_I]]:
+// CHECK-NEXT:    [[TMP4:%.*]] = catchswitch within none [label 
%[[__EXCEPT6_I:.*]]] unwind to caller
+// CHECK:       [[__EXCEPT6_I]]:
+// CHECK-NEXT:    [[TMP5:%.*]] = catchpad within [[TMP4]] [ptr null]
+// CHECK-NEXT:    catchret from [[TMP5]] to label %[[__EXCEPT7_I:.*]]
+// CHECK:       [[__EXCEPT7_I]]:
+// CHECK-NEXT:    [[TMP6:%.*]] = tail call i32 @llvm.eh.exceptioncode(token 
[[TMP5]])
+// CHECK-NEXT:    br label %[[__TRY_CONT8_I]]
+// CHECK:       [[__TRY_CONT8_I]]:
+// CHECK-NEXT:    tail call void @"?Exit@@YAXXZ"() #[[ATTR7:[0-9]+]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[INVOKE_CONT2_I]]:
+// CHECK-NEXT:    
[[ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_0_ARGC_ADDR_0_ARGC_ADDR_0__I:%.*]]
 = load volatile i32, ptr [[ARGC_ADDR_I]], align 4, !tbaa [[INT_TBAA7]]
+// CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 
[[ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_0_ARGC_ADDR_0_ARGC_ADDR_0__I]],
 0
+// CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_THEN_I:.*]], label 
%[[IF_END_I:.*]]
+// CHECK:       [[IF_THEN_I]]:
+// CHECK-NEXT:    [[TMP7:%.*]] = load volatile ptr, ptr @"?p@@3PECHEC", align 
8, !tbaa [[INTPTR_TBAA11:![0-9]+]]
+// CHECK-NEXT:    store volatile i32 0, ptr [[TMP7]], align 4, !tbaa 
[[INT_TBAA7]]
+// CHECK-NEXT:    br label %[[IF_END_I]]
+// CHECK:       [[IF_END_I]]:
+// CHECK-NEXT:    
[[ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_0_ARGC_ADDR_0_ARGC_ADDR_0_10_I:%.*]]
 = load volatile i32, ptr [[ARGC_ADDR_I]], align 4, !tbaa [[INT_TBAA7]]
+// CHECK-NEXT:    store volatile i32 1, ptr [[CLEANUP_DEST_SLOT_I]], align 4
+// CHECK-NEXT:    invoke void @llvm.seh.try.end()
+// CHECK-NEXT:            to label %"?ExitOnThrow@@[email protected]" unwind label 
%[[CATCH_DISPATCH5_I]]
+// CHECK:       "?ExitOnThrow@@[email protected]":
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[ARGC_ADDR_I]])
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull 
[[__EXCEPTION_CODE1_I]])
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull 
[[CLEANUP_DEST_SLOT_I]])
+// CHECK-NEXT:    [[CALL1:%.*]] = tail call noundef i32 
@"?AlwaysThrows@@YAHH@Z"(i32 noundef 
[[ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_0_ARGC_ADDR_0_ARGC_ADDR_0_10_I]])
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL1]], 
[[ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_I_0_ARGC_ADDR_0_ARGC_ADDR_0_ARGC_ADDR_0_10_I]]
+// CHECK-NEXT:    ret i32 [[ADD]]
+//
+int main(int argc, char**)
+{
+  auto data = ExitOnThrow(argc);
+  return data + AlwaysThrows(data);
+}
+//.
+// CHECK: [[INT_TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0}
+// CHECK: [[META8]] = !{!"int", [[META9:![0-9]+]], i64 0}
+// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0}
+// CHECK: [[META10]] = !{!"Simple C++ TBAA"}
+// CHECK: [[INTPTR_TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0}
+// CHECK: [[META12]] = !{!"p1 int", [[META13:![0-9]+]], i64 0}
+// CHECK: [[META13]] = !{!"any pointer", [[META9]], i64 0}
+//.
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp 
b/llvm/lib/CodeGen/WinEHPrepare.cpp
index 66d29cb5d65e4..93eeec584d522 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -341,9 +341,11 @@ void llvm::calculateSEHStateForAsynchEH(const BasicBlock 
*BB, int State,
         // Retrive the new State from seh_try_begin
         State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
       else if (Fn && Fn->isIntrinsic() &&
-               Fn->getIntrinsicID() == Intrinsic::seh_try_end)
+               Fn->getIntrinsicID() == Intrinsic::seh_try_end) {
         // end of current state, retrive new state from UnwindMap
+        State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
         State = EHInfo.SEHUnwindMap[State].ToState;
+      }
     }
     // Continue push successors into worklist
     for (auto *SuccBB : successors(BB)) {

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

Reply via email to