@@ -399,6 +399,47 @@ static bool isNoexcept(const FunctionDecl *FD) {
399399 return false ;
400400}
401401
402+ // ===----------------------------------------------------------------------===//
403+ // Check for SEH __try in a function with C++ objects that have destructors.
404+ // ===----------------------------------------------------------------------===//
405+
406+ static void emitDiagForSehTryUnwind (Sema &S, CFGElement &E) {
407+ if (auto AD = E.getAs <CFGAutomaticObjDtor>()) {
408+ const auto *VD = AD->getVarDecl ();
409+ S.Diag (VD->getLocation (), diag::err_seh_try_dtor);
410+ } else if (auto TD = E.getAs <CFGTemporaryDtor>()) {
411+ const auto *E = TD->getBindTemporaryExpr ();
412+ S.Diag (E->getBeginLoc (), diag::err_seh_try_dtor);
413+ } else
414+ llvm_unreachable (" emitDiagForSehTryUnwind should only be used with "
415+ " AutomaticObjectDtor or TemporaryDtor" );
416+ }
417+
418+ static void checkSehTryNeedsUnwind (Sema &S, const FunctionDecl *FD,
419+ AnalysisDeclContext &AC) {
420+ if (!FD->usesSEHTry ())
421+ return ;
422+ CFG *BodyCFG = AC.getCFG ();
423+ if (!BodyCFG)
424+ return ;
425+ if (BodyCFG->getExit ().pred_empty ())
426+ return ;
427+
428+ llvm::BitVector Reachable (BodyCFG->getNumBlockIDs ());
429+ clang::reachable_code::ScanReachableFromBlock (&BodyCFG->getEntry (),
430+ Reachable);
431+ for (CFGBlock *B : *BodyCFG) {
432+ if (!Reachable[B->getBlockID ()])
433+ continue ;
434+ for (CFGElement &E : *B) {
435+ auto Kind = E.getKind ();
436+ if (Kind == CFGElement::AutomaticObjectDtor ||
437+ Kind == CFGElement::TemporaryDtor)
438+ emitDiagForSehTryUnwind (S, E);
439+ }
440+ }
441+ }
442+
402443// ===----------------------------------------------------------------------===//
403444// Check for missing return value.
404445// ===----------------------------------------------------------------------===//
@@ -2821,6 +2862,10 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
28212862 if (S.getLangOpts ().CPlusPlus && !fscope->isCoroutine () && isNoexcept (FD))
28222863 checkThrowInNonThrowingFunc (S, FD, AC);
28232864
2865+ if (S.getLangOpts ().CPlusPlus )
2866+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2867+ checkSehTryNeedsUnwind (S, FD, AC);
2868+
28242869 // If none of the previous checks caused a CFG build, trigger one here
28252870 // for the logical error handler.
28262871 if (LogicalErrorHandler::hasActiveDiagnostics (Diags, D->getBeginLoc ())) {
0 commit comments