[clang] 8da581d - [WinEH] Diagnose SEH object unwinding in skipped __except bodies (#187718)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 18:48:40 PDT 2026
Author: GkvJwa
Date: 2026-04-29T09:48:35+08:00
New Revision: 8da581d58abd5b1921d3959b04dcf9e1c1feeb34
URL: https://github.com/llvm/llvm-project/commit/8da581d58abd5b1921d3959b04dcf9e1c1feeb34
DIFF: https://github.com/llvm/llvm-project/commit/8da581d58abd5b1921d3959b04dcf9e1c1feeb34.diff
LOG: [WinEH] Diagnose SEH object unwinding in skipped __except bodies (#187718)
When an SEH __except block has no EH branches, CodeGen skips emitting the handler
body. This also skipped the existing diagnostic for local variables that require destruction
under C++ exceptions
Diagnose those variables before dropping the skipped handler body, and add coverage
for both sync and async exception modes
Added:
Modified:
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CGException.cpp
clang/test/CodeGenCXX/exceptions-seh.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 419b3c477e7b2..a7479809d219e 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -2230,8 +2230,6 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
// Check the type for a cleanup.
if (QualType::DestructionKind dtorKind = D.needsDestruction(getContext())) {
// Check if we're in a SEH block with /EH, prevent it
- // TODO: /EHs*
diff ers from /EHa, the former may not be executed to this
- // point.
if (getLangOpts().CXXExceptions && currentFunctionUsesSEHTry())
getContext().getDiagnostics().Report(D.getLocation(),
diag::err_seh_object_unwinding);
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index a83a05d01121f..f7c6f7521c98e 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -2245,6 +2245,17 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
// TODO: Model unwind edges from instructions, either with iload / istore or
// a try body function.
if (!CatchScope.hasEHBranches()) {
+ // Even though we skip emitting the __except body, diagnose variables
+ // with non-trivial destructors that would normally be caught by
+ // EmitAutoVarCleanups.
+ if (getLangOpts().CXXExceptions && currentFunctionUsesSEHTry())
+ for (const Stmt *S : Except->getBlock()->body())
+ if (const auto *DS = dyn_cast<DeclStmt>(S))
+ for (const Decl *D : DS->decls())
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (VD->needsDestruction(getContext()))
+ getContext().getDiagnostics().Report(
+ VD->getLocation(), diag::err_seh_object_unwinding);
CatchScope.clearHandlerBlocks();
EHStack.popCatch();
SEHCodeSlotStack.pop_back();
diff --git a/clang/test/CodeGenCXX/exceptions-seh.cpp b/clang/test/CodeGenCXX/exceptions-seh.cpp
index 270b249f700fa..c4b191377b844 100644
--- a/clang/test/CodeGenCXX/exceptions-seh.cpp
+++ b/clang/test/CodeGenCXX/exceptions-seh.cpp
@@ -5,13 +5,17 @@
// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-passes | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \
-// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR1
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_ASYNC1
// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \
-// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR2
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_ASYNC2
// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \
-// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR3
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_ASYNC3
// RUN: %clang_cc1 -triple x86_64-windows -fcxx-exceptions -fexceptions \
-// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR4
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_SYNC1
+// RUN: %clang_cc1 -triple x86_64-windows -fcxx-exceptions -fexceptions \
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_SYNC2
+// RUN: %clang_cc1 -triple x86_64-windows -fcxx-exceptions -fexceptions \
+// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DERR_SYNC3
// RUN: %clang_cc1 -triple x86_64-windows \
// RUN: -fms-extensions -x c++ -emit-llvm-only -verify %s -DNOERR
@@ -186,34 +190,27 @@ void use_inline() {
void seh_in_noexcept() noexcept { __try {} __finally {} }
-#if defined(ERR1)
+#if defined(ERR_ASYNC1) || defined(ERR_SYNC1)
void seh_unwinding() {
__try {
HasCleanup x; // expected-error{{'__try' is not permitted in functions that require object unwinding}}
} __except (1) {
}
}
-#elif defined(ERR2)
+#elif defined(ERR_ASYNC2) || defined(ERR_SYNC2)
void seh_unwinding() {
__try {
} __except (1) {
HasCleanup x; // expected-error{{'__try' is not permitted in functions that require object unwinding}}
}
}
-#elif defined(ERR3)
+#elif defined(ERR_ASYNC3) || defined(ERR_SYNC3)
void seh_unwinding() {
HasCleanup x; // expected-error{{'__try' is not permitted in functions that require object unwinding}}
__try {
} __except (1) {
}
}
-#elif defined(ERR4)
-void seh_unwinding() {
- __try {
- HasCleanup x; // expected-error{{'__try' is not permitted in functions that require object unwinding}}
- } __except (1) {
- }
-}
#elif defined(NOERR)
void seh_unwinding() {
__try {
More information about the cfe-commits
mailing list