[clang] [clang][seh]: Fix c++ destructors when c++ exceptions are disabled (PR #151836)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 3 06:20:21 PDT 2025
https://github.com/Qwinci updated https://github.com/llvm/llvm-project/pull/151836
>From 858ae7ed08a52cc8e4a295df7ca3b536df88a7b7 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 +++++++++++++++++++
2 files changed, 47 insertions(+)
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..dd177628e10d6 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");
+}
+
+static void checkSehTryNeedsUnwind(Sema &S, const FunctionDecl *FD,
+ AnalysisDeclContext &AC) {
+ CFG *BodyCFG = AC.getCFG();
+ if (!BodyCFG)
+ return;
+ if (BodyCFG->getExit().pred_empty())
+ return;
+ if (!FD->usesSEHTry())
+ 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())) {
More information about the cfe-commits
mailing list