[clang] [clang][sema]: Error when SEH __try is used in a function with C++ dtors (PR #151836)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 3 06:47:41 PDT 2025
https://github.com/Qwinci updated https://github.com/llvm/llvm-project/pull/151836
>From 5d6cdacb04b9bdb6cc4bad1539901b442ae613d5 Mon Sep 17 00:00:00 2001
From: Qwinci <qwinci222 at gmail.com>
Date: Sun, 3 Aug 2025 16:18:37 +0300
Subject: [PATCH] [clang][sema]: Error when SEH __try is used in a function
with C++ dtors
SEH __try is not allowed in a function with C++ objects that have non-trivial
destructors.
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +
clang/lib/Sema/AnalysisBasedWarnings.cpp | 45 +++++++++++++++++++
clang/test/Sema/seh-cxx-dtors.cpp | 18 ++++++++
3 files changed, 65 insertions(+)
create mode 100644 clang/test/Sema/seh-cxx-dtors.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f4f1bc67724a1..f25584cb89bcf 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8264,6 +8264,8 @@ def err_mixing_cxx_try_seh_try : Error<
"in the same function as SEH '__try'">;
def err_seh_try_unsupported : Error<
"SEH '__try' is not supported on this target">;
+def err_seh_try_dtor : Error<"cannot use C++ object with a destructor "
+ "in the same function as SEH '__try'">;
def note_conflicting_try_here : Note<
"conflicting %0 here">;
def warn_jump_out_of_seh_finally : Warning<
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index f21e571e6e0ce..589a921b23a6d 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -399,6 +399,47 @@ static bool isNoexcept(const FunctionDecl *FD) {
return false;
}
+//===----------------------------------------------------------------------===//
+// Check for SEH __try in a function with C++ objects that have destructors.
+//===----------------------------------------------------------------------===//
+
+static void emitDiagForSehTryUnwind(Sema &S, CFGElement &E) {
+ if (auto AD = E.getAs<CFGAutomaticObjDtor>()) {
+ const auto *VD = AD->getVarDecl();
+ S.Diag(VD->getLocation(), diag::err_seh_try_dtor);
+ } else if (auto TD = E.getAs<CFGTemporaryDtor>()) {
+ const auto *E = TD->getBindTemporaryExpr();
+ S.Diag(E->getBeginLoc(), diag::err_seh_try_dtor);
+ } else
+ llvm_unreachable("emitDiagForSehTryUnwind should only be used with "
+ "AutomaticObjectDtor or TemporaryDtor");
+}
+
+static void checkSehTryNeedsUnwind(Sema &S, const FunctionDecl *FD,
+ AnalysisDeclContext &AC) {
+ if (!FD->usesSEHTry())
+ return;
+ CFG *BodyCFG = AC.getCFG();
+ if (!BodyCFG)
+ return;
+ if (BodyCFG->getExit().pred_empty())
+ return;
+
+ llvm::BitVector Reachable(BodyCFG->getNumBlockIDs());
+ clang::reachable_code::ScanReachableFromBlock(&BodyCFG->getEntry(),
+ Reachable);
+ for (CFGBlock *B : *BodyCFG) {
+ if (!Reachable[B->getBlockID()])
+ continue;
+ for (CFGElement &E : *B) {
+ auto Kind = E.getKind();
+ if (Kind == CFGElement::AutomaticObjectDtor ||
+ Kind == CFGElement::TemporaryDtor)
+ emitDiagForSehTryUnwind(S, E);
+ }
+ }
+}
+
//===----------------------------------------------------------------------===//
// Check for missing return value.
//===----------------------------------------------------------------------===//
@@ -2821,6 +2862,10 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
if (S.getLangOpts().CPlusPlus && !fscope->isCoroutine() && isNoexcept(FD))
checkThrowInNonThrowingFunc(S, FD, AC);
+ if (S.getLangOpts().CPlusPlus)
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ checkSehTryNeedsUnwind(S, FD, AC);
+
// If none of the previous checks caused a CFG build, trigger one here
// for the logical error handler.
if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
diff --git a/clang/test/Sema/seh-cxx-dtors.cpp b/clang/test/Sema/seh-cxx-dtors.cpp
new file mode 100644
index 0000000000000..6e00fe8bd89a8
--- /dev/null
+++ b/clang/test/Sema/seh-cxx-dtors.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -fms-extensions -verify %s
+
+struct Foo {
+ ~Foo() {}
+};
+
+// These need '-fms-extensions'
+void f1() {
+ Foo foo {}; // expected-error {{destructor}}
+ __try {} __except (1) {}
+}
+
+void bar(Foo foo);
+
+void f2() {
+ bar(Foo {}); // expected-error {{destructor}}
+ __try {} __except (1) {}
+}
More information about the cfe-commits
mailing list