[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