[clang] [WinEH] Fix object delete crash (PR #180144)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 1 07:42:45 PDT 2026
https://github.com/GkvJwa updated https://github.com/llvm/llvm-project/pull/180144
>From 9d1f31eb3a551d1f718557ac83a87e19450db331 Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 24 Mar 2026 22:04:17 +0800
Subject: [PATCH 1/8] Add test
---
clang/lib/CodeGen/CGCleanup.cpp | 23 ++++++----
clang/lib/CodeGen/CGCleanup.h | 7 ++++
clang/lib/CodeGen/CGException.cpp | 6 ++-
clang/lib/CodeGen/EHScopeStack.h | 3 ++
.../CodeGen/windows-seh-EHa-TryInFinally.cpp | 42 ++++++++++++++++---
5 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 3d242bec73126..c33f057688b1a 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -159,6 +159,7 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
bool IsEHCleanup = Kind & EHCleanup;
bool IsLifetimeMarker = Kind & LifetimeMarker;
bool IsFakeUse = Kind & FakeUse;
+ bool IsSEHFinallyCleanup = Kind & SEHFinallyCleanup;
// Per C++ [except.terminate], it is implementation-defined whether none,
// some, or all cleanups are called before std::terminate. Thus, when
@@ -183,6 +184,8 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
Scope->setLifetimeMarker();
if (IsFakeUse)
Scope->setFakeUse();
+ if (IsSEHFinallyCleanup)
+ Scope->setSEHFinallyCleanup();
// With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup
// If exceptions are disabled/ignored and SEH is not in use, then there is no
@@ -191,7 +194,8 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
// consistent with MSVC's behavior, except in the presence of -EHa.
// Check getInvokeDest() to generate llvm.seh.scope.begin() as needed.
if (CGF->getLangOpts().EHAsynch && IsEHCleanup && !IsLifetimeMarker &&
- CGF->getTarget().getCXXABI().isMicrosoft() && CGF->getInvokeDest())
+ !IsSEHFinallyCleanup && CGF->getTarget().getCXXABI().isMicrosoft() &&
+ CGF->getInvokeDest())
CGF->EmitSehCppScopeBegin();
return Scope->getCleanupBuffer();
@@ -785,6 +789,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// Under -EHa, invoke seh.scope.end() to mark scope end before dtor
bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
+ // Save IsSEHFinallyCleanup before any popCleanup() invalidates Scope.
+ bool IsSEHFinallyCleanup = Scope.isSEHFinallyCleanup();
const EHPersonality &Personality = EHPersonality::get(*this);
if (!RequiresNormalCleanup) {
// Mark CPP scope end for passed-by-value Arg temp
@@ -811,10 +817,10 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// mark SEH scope end for fall-through flow
if (IsEHa && getInvokeDest()) {
- if (Personality.isMSVCXXPersonality())
- EmitSehCppScopeEnd();
- else
+ if (Scope.isSEHFinallyCleanup())
EmitSehTryScopeEnd();
+ else if (Personality.isMSVCPersonality())
+ EmitSehCppScopeEnd();
}
destroyOptimisticNormalEntry(*this, Scope);
@@ -853,10 +859,10 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// intercept normal cleanup to mark SEH scope end
if (IsEHa && getInvokeDest()) {
- if (Personality.isMSVCXXPersonality())
- EmitSehCppScopeEnd();
- else
+ if (Scope.isSEHFinallyCleanup())
EmitSehTryScopeEnd();
+ else if (Personality.isMSVCPersonality())
+ EmitSehCppScopeEnd();
}
// III. Figure out where we're going and build the cleanup
@@ -1056,7 +1062,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
EHStack.pushTerminate();
PushedTerminate = true;
} else if (IsEHa && getInvokeDest()) {
- EmitSehCppScopeEnd();
+ if (!IsSEHFinallyCleanup)
+ EmitSehCppScopeEnd();
}
// We only actually emit the cleanup code if the cleanup is either
diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h
index ba78e5478ac37..ded8be13c5fae 100644
--- a/clang/lib/CodeGen/CGCleanup.h
+++ b/clang/lib/CodeGen/CGCleanup.h
@@ -99,6 +99,9 @@ class EHScope {
LLVM_PREFERRED_TYPE(bool)
unsigned TestFlagInEHCleanup : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned IsSEHFinallyCleanup : 1;
+
/// The amount of extra storage needed by the Cleanup.
/// Always a multiple of the scope-stack alignment.
unsigned CleanupSize : 12;
@@ -357,6 +360,7 @@ class alignas(8) EHCleanupScope : public EHScope {
CleanupBits.IsActive = true;
CleanupBits.IsLifetimeMarker = false;
CleanupBits.IsFakeUse = false;
+ CleanupBits.IsSEHFinallyCleanup = false;
CleanupBits.TestFlagInNormalCleanup = false;
CleanupBits.TestFlagInEHCleanup = false;
CleanupBits.CleanupSize = cleanupSize;
@@ -392,6 +396,9 @@ class alignas(8) EHCleanupScope : public EHScope {
bool isFakeUse() const { return CleanupBits.IsFakeUse; }
void setFakeUse() { CleanupBits.IsFakeUse = true; }
+ bool isSEHFinallyCleanup() const { return CleanupBits.IsSEHFinallyCleanup; }
+ void setSEHFinallyCleanup() { CleanupBits.IsSEHFinallyCleanup = true; }
+
bool hasActiveFlag() const { return ActiveFlag.isValid(); }
Address getActiveFlag() const {
return ActiveFlag;
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 7559727721496..fcbb473228c01 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -2182,7 +2182,8 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
void CodeGenFunction::pushSEHCleanup(CleanupKind Kind,
llvm::Function *FinallyFunc) {
- EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc);
+ EHStack.pushCleanup<PerformSEHFinally>(
+ static_cast<CleanupKind>(Kind | SEHFinallyCleanup), FinallyFunc);
}
void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
@@ -2194,7 +2195,8 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
// Push a cleanup for __finally blocks.
- EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
+ EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHSEHFinallyCleanup,
+ FinallyFunc);
return;
}
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index b9b8021191d62..2f5e056e7db3b 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -92,6 +92,9 @@ enum CleanupKind : unsigned {
// markers chiefly to be ignored in most contexts.
FakeUse = 0x10,
NormalFakeUse = FakeUse | NormalCleanup,
+
+ SEHFinallyCleanup = 0x20,
+ NormalAndEHSEHFinallyCleanup = SEHFinallyCleanup | NormalAndEHCleanup,
};
/// A stack of scopes which respond to exceptions, including cleanups
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
index 462ba9afb5b30..3301178f32b49 100644
--- a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
+++ b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -43,11 +43,11 @@ int main() {
}
// CHECK-LABEL:@"?foo@@YAXXZ"()
-// CHECK: invoke.cont:
// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: invoke.cont:
// CHECK: store volatile i32 1, ptr %cleanup.dest.slot
// CHECK: invoke void @llvm.seh.try.end()
-// CHECK: invoke.cont2:
+// CHECK: invoke.cont1:
// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot
// CHECK: %1 = icmp ne i32 %cleanup.dest, 0
// CHECK: %2 = zext i1 %1 to i8
@@ -69,14 +69,13 @@ void foo()
}
// CHECK-LABEL:@"?bar@@YAHXZ"()
-// CHECK: invoke.cont:
// CHECK: invoke void @llvm.seh.try.begin()
-// CHECK: invoke.cont1:
+// CHECK: invoke.cont:
// CHECK: store volatile i32 1, ptr %cleanup.dest.slot
// CHECK: invoke void @llvm.seh.try.end()
-// CHECK: invoke.cont2:
+// CHECK: invoke.cont1:
// CHECK: call void @"?fin$0 at 0@bar@@"
-// CHECK: %cleanup.dest3 = load i32, ptr %cleanup.dest.slot
+// CHECK: %cleanup.dest2 = load i32, ptr %cleanup.dest.slot
// CHECK: return:
// CHECK: ret i32 11
int bar()
@@ -90,3 +89,34 @@ int bar()
}
}
}
+
+// CHECK-LABEL: @"?foo1@@YAXXZ"()
+// CHECK-NOT: invoke void @llvm.seh.scope.begin()
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: invoke.cont:
+// CHECK: invoke void @llvm.seh.scope.begin()
+// CHECK: store volatile ptr %call, ptr %a, align 8
+// CHECK: invoke void @llvm.seh.scope.begin()
+// CHECK: invoke void @"??1A@@QEAA at XZ"
+// CHECK: invoke void @llvm.seh.scope.end()
+// CHECK-NOT: invoke void @llvm.seh.try.end()
+// CHECK: br label %delete.end
+// CHECK: invoke void @llvm.seh.try.end()
+// CHECK: call void @"?fin$0 at 0@foo1@@"(i8 noundef 0
+// CHECK: cleanupret
+// CHECK: call void @"?fin$0 at 0@foo1@@"(i8 noundef 1
+// CHECK-NOT: @llvm.seh.scope.end
+// CHECK: cleanupret
+struct A {
+ A();
+ ~A();
+};
+
+void foo1() {
+ __try {
+ A* a = new A;
+ delete a;
+ }
+ __finally {
+ }
+}
>From aae06618f6d222beb492016e71c34c405b9dd296 Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 24 Mar 2026 22:26:16 +0800
Subject: [PATCH 2/8] 2
---
clang/lib/CodeGen/CGCleanup.cpp | 4 ++--
clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index c33f057688b1a..b7130ff8578e1 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -789,7 +789,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// Under -EHa, invoke seh.scope.end() to mark scope end before dtor
bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
- // Save IsSEHFinallyCleanup before any popCleanup() invalidates Scope.
bool IsSEHFinallyCleanup = Scope.isSEHFinallyCleanup();
const EHPersonality &Personality = EHPersonality::get(*this);
if (!RequiresNormalCleanup) {
@@ -801,7 +800,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// block.
if (NormalDeactivateOrigIP.isSet())
Builder.restoreIP(NormalDeactivateOrigIP);
- if (Personality.isMSVCXXPersonality() && Builder.GetInsertBlock())
+ if (Personality.isMSVCPersonality() && Builder.GetInsertBlock() &&
+ !IsSEHFinallyCleanup)
EmitSehCppScopeEnd();
if (NormalDeactivateOrigIP.isSet())
NormalDeactivateOrigIP = Builder.saveAndClearIP();
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
index 3301178f32b49..cd9e823113967 100644
--- a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
+++ b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -95,7 +95,8 @@ int bar()
// CHECK: invoke void @llvm.seh.try.begin()
// CHECK: invoke.cont:
// CHECK: invoke void @llvm.seh.scope.begin()
-// CHECK: store volatile ptr %call, ptr %a, align 8
+// CHECK: invoke noundef ptr @"??0A@@QEAA at XZ"
+// CHECK: invoke void @llvm.seh.scope.end()
// CHECK: invoke void @llvm.seh.scope.begin()
// CHECK: invoke void @"??1A@@QEAA at XZ"
// CHECK: invoke void @llvm.seh.scope.end()
>From 2b4e6f97230096dd1d2607f4b9f7e4b84451da5d Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 31 Mar 2026 21:38:40 +0800
Subject: [PATCH 3/8] 3
---
.../CodeGen/windows-seh-EHa-TryInFinally.cpp | 23 +++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
index cd9e823113967..e561c223919ed 100644
--- a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
+++ b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -91,25 +91,40 @@ int bar()
}
// CHECK-LABEL: @"?foo1@@YAXXZ"()
+
// CHECK-NOT: invoke void @llvm.seh.scope.begin()
// CHECK: invoke void @llvm.seh.try.begin()
-// CHECK: invoke.cont:
+// CHECK: invoke.cont1:
+
// CHECK: invoke void @llvm.seh.scope.begin()
// CHECK: invoke noundef ptr @"??0A@@QEAA at XZ"
+
// CHECK: invoke void @llvm.seh.scope.end()
+
// CHECK: invoke void @llvm.seh.scope.begin()
// CHECK: invoke void @"??1A@@QEAA at XZ"
+
// CHECK: invoke void @llvm.seh.scope.end()
-// CHECK-NOT: invoke void @llvm.seh.try.end()
+// CHECK-NOT: @llvm.seh
// CHECK: br label %delete.end
+
// CHECK: invoke void @llvm.seh.try.end()
+// CHECK: invoke.cont15:
+
// CHECK: call void @"?fin$0 at 0@foo1@@"(i8 noundef 0
+// CHECK-NOT: @llvm.seh
+// CHECK: ehcleanup:
+// CHECK: invoke.cont7:
// CHECK: cleanupret
+// CHECK: invoke.cont14:
+// CHECK: cleanupret
+
+// CHECK: ehcleanup16:
// CHECK: call void @"?fin$0 at 0@foo1@@"(i8 noundef 1
-// CHECK-NOT: @llvm.seh.scope.end
+// CHECK-NOT: @llvm.seh
// CHECK: cleanupret
struct A {
- A();
+ A() noexcept;
~A();
};
>From 68d73acd2346c9fc20fc1efaaca033938a2bc94b Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 31 Mar 2026 21:40:32 +0800
Subject: [PATCH 4/8] 4
---
clang/lib/CodeGen/CGExprCXX.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 82300c3ede183..296c0f838e88a 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1720,6 +1720,18 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::Instruction *cleanupDominator = nullptr;
if (E->getOperatorDelete() &&
!E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
+ // A potentially-throwing constructor inside __try requires C++ object
+ // unwinding, which is incompatible with SEH.
+ if (getLangOpts().CXXExceptions && currentFunctionUsesSEHTry()) {
+ if (const auto *ConstructExpr = E->getConstructExpr()) {
+ const auto *FPT = ConstructExpr->getConstructor()
+ ->getType()
+ ->castAs<FunctionProtoType>();
+ if (!FPT->isNothrow())
+ getContext().getDiagnostics().Report(E->getBeginLoc(),
+ diag::err_seh_object_unwinding);
+ }
+ }
EnterNewDeleteCleanup(*this, E, TypeIdentityArg, allocation, allocSize,
allocAlign, allocatorArgs);
operatorDeleteCleanup = EHStack.stable_begin();
>From 9cbf298830cd6a8e700447bd3daa7880e7505b3e Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 31 Mar 2026 21:43:55 +0800
Subject: [PATCH 5/8] 5
---
clang/test/CodeGenCXX/exceptions-seh.cpp | 25 ++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/clang/test/CodeGenCXX/exceptions-seh.cpp b/clang/test/CodeGenCXX/exceptions-seh.cpp
index 270b249f700fa..d385ed1e86728 100644
--- a/clang/test/CodeGenCXX/exceptions-seh.cpp
+++ b/clang/test/CodeGenCXX/exceptions-seh.cpp
@@ -12,6 +12,10 @@
// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR3
// RUN: %clang_cc1 -triple x86_64-windows -fcxx-exceptions -fexceptions \
// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR4
+// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_NEW_THROWING_CTOR
+// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DNOERR_NEW_NOEXCEPT_CTOR
// RUN: %clang_cc1 -triple x86_64-windows \
// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DNOERR
@@ -214,6 +218,27 @@ void seh_unwinding() {
} __except (1) {
}
}
+#elif defined(ERR_NEW_THROWING_CTOR)
+void seh_unwinding() {
+ __try {
+ HasCleanup *p = new HasCleanup; // expected-error{{'__try' is not permitted in functions that require object unwinding}}
+ delete p;
+ } __except (1) {
+ }
+}
+#elif defined(NOERR_NEW_NOEXCEPT_CTOR)
+// new-expression with a noexcept constructor should be fine.
+struct NoThrowCtor {
+ NoThrowCtor() noexcept;
+ ~NoThrowCtor();
+};
+void seh_unwinding() {
+ __try {
+ NoThrowCtor *p = new NoThrowCtor; // expected-no-diagnostics
+ delete p;
+ } __except (1) {
+ }
+}
#elif defined(NOERR)
void seh_unwinding() {
__try {
>From 25c7bf3313fb8982ca25ef546cc4acad8887e0c2 Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 31 Mar 2026 21:53:27 +0800
Subject: [PATCH 6/8] 6
---
clang/lib/CodeGen/CGCleanup.cpp | 7 +++----
clang/lib/CodeGen/CGExprCXX.cpp | 2 +-
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index b7130ff8578e1..0157ef4bdd5af 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -800,8 +800,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// block.
if (NormalDeactivateOrigIP.isSet())
Builder.restoreIP(NormalDeactivateOrigIP);
- if (Personality.isMSVCPersonality() && Builder.GetInsertBlock() &&
- !IsSEHFinallyCleanup)
+ if (Builder.GetInsertBlock() && !IsSEHFinallyCleanup)
EmitSehCppScopeEnd();
if (NormalDeactivateOrigIP.isSet())
NormalDeactivateOrigIP = Builder.saveAndClearIP();
@@ -819,7 +818,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
if (IsEHa && getInvokeDest()) {
if (Scope.isSEHFinallyCleanup())
EmitSehTryScopeEnd();
- else if (Personality.isMSVCPersonality())
+ else
EmitSehCppScopeEnd();
}
@@ -861,7 +860,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
if (IsEHa && getInvokeDest()) {
if (Scope.isSEHFinallyCleanup())
EmitSehTryScopeEnd();
- else if (Personality.isMSVCPersonality())
+ else
EmitSehCppScopeEnd();
}
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 296c0f838e88a..c585523f2718f 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1729,7 +1729,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
->castAs<FunctionProtoType>();
if (!FPT->isNothrow())
getContext().getDiagnostics().Report(E->getBeginLoc(),
- diag::err_seh_object_unwinding);
+ diag::err_seh_object_unwinding);
}
}
EnterNewDeleteCleanup(*this, E, TypeIdentityArg, allocation, allocSize,
>From 431154a15da1a4929d306b083eaaec117faaf1e8 Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Tue, 31 Mar 2026 22:08:22 +0800
Subject: [PATCH 7/8] 7
---
clang/lib/CodeGen/CGCleanup.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 0157ef4bdd5af..c33cdfb67db68 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -790,7 +790,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// Under -EHa, invoke seh.scope.end() to mark scope end before dtor
bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
bool IsSEHFinallyCleanup = Scope.isSEHFinallyCleanup();
- const EHPersonality &Personality = EHPersonality::get(*this);
if (!RequiresNormalCleanup) {
// Mark CPP scope end for passed-by-value Arg temp
// per Windows ABI which is "normally" Cleanup in callee
>From a533337284fedc3d29b427e770484fdb757d87af Mon Sep 17 00:00:00 2001
From: GkvJwa <gkvjwa at gmail.com>
Date: Wed, 1 Apr 2026 22:42:16 +0800
Subject: [PATCH 8/8] 8
---
.../CodeGen/windows-seh-EHa-TryInFinally.cpp | 46 +++++++++++++++----
1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
index e561c223919ed..b5f1d750b0dfb 100644
--- a/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
+++ b/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -91,34 +91,64 @@ int bar()
}
// CHECK-LABEL: @"?foo1@@YAXXZ"()
-
+//
+// NORMAL PATH
+//
+// no spurious seh.scope.begin from PerformSEHFinally push
// CHECK-NOT: invoke void @llvm.seh.scope.begin()
// CHECK: invoke void @llvm.seh.try.begin()
+//
+// only one seh.try.begin (from EmitSEHTryStmt):
+// CHECK-NOT: invoke void @llvm.seh.try.begin()
// CHECK: invoke.cont1:
-
+//
+// operator-delete EH cleanup push emits seh.scope.begin[1]
// CHECK: invoke void @llvm.seh.scope.begin()
// CHECK: invoke noundef ptr @"??0A@@QEAA at XZ"
-
+//
+// deactivation emits seh.scope.end[1]
// CHECK: invoke void @llvm.seh.scope.end()
-
+//
+// no stray seh markers between the two scope pairs:
+// CHECK-NOT: @llvm.seh
+//
+// delete-dtor cleanup push emits seh.scope.begin[2]
// CHECK: invoke void @llvm.seh.scope.begin()
+//
+// no extra scope markers before dtor call:
+// CHECK-NOT: @llvm.seh.scope
// CHECK: invoke void @"??1A@@QEAA at XZ"
-
+//
+// dtor cleanup pop emits seh.scope.end[2], not seh.try.end
// CHECK: invoke void @llvm.seh.scope.end()
// CHECK-NOT: @llvm.seh
// CHECK: br label %delete.end
-
+//
+// pop emits seh.try.end (correct pairing)
// CHECK: invoke void @llvm.seh.try.end()
+//
+// only one seh.try.end (paired with the single seh.try.begin):
+// CHECK-NOT: invoke void @llvm.seh.try.end()
// CHECK: invoke.cont15:
-
+//
+// normal __finally call path
// CHECK: call void @"?fin$0 at 0@foo1@@"(i8 noundef 0
// CHECK-NOT: @llvm.seh
+//
+// EH PATH
+//
+// dtor EH cleanup correctly emits seh.scope.end
// CHECK: ehcleanup:
+// CHECK: invoke void @llvm.seh.scope.end()
// CHECK: invoke.cont7:
// CHECK: cleanupret
+//
+// operator-delete EH cleanup correctly emits seh.scope.end
+// CHECK: invoke void @llvm.seh.scope.end()
// CHECK: invoke.cont14:
// CHECK: cleanupret
-
+//
+// EH __finally path must NOT emit seh.scope.end
// CHECK: ehcleanup16:
// CHECK: call void @"?fin$0 at 0@foo1@@"(i8 noundef 1
// CHECK-NOT: @llvm.seh
More information about the cfe-commits
mailing list