https://github.com/Qwinci updated https://github.com/llvm/llvm-project/pull/151836
>From 472cdf4a8433c776a3d955a2b8a7dbe71d85f763 Mon Sep 17 00:00:00 2001 From: Qwinci <qwinci...@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..2e1ec446ed7e1 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) { + 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())) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits