@@ -399,6 +399,47 @@ static bool isNoexcept(const FunctionDecl *FD) {
399
399
return false ;
400
400
}
401
401
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
+
402
443
// ===----------------------------------------------------------------------===//
403
444
// Check for missing return value.
404
445
// ===----------------------------------------------------------------------===//
@@ -2821,6 +2862,10 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
2821
2862
if (S.getLangOpts ().CPlusPlus && !fscope->isCoroutine () && isNoexcept (FD))
2822
2863
checkThrowInNonThrowingFunc (S, FD, AC);
2823
2864
2865
+ if (S.getLangOpts ().CPlusPlus )
2866
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
2867
+ checkSehTryNeedsUnwind (S, FD, AC);
2868
+
2824
2869
// If none of the previous checks caused a CFG build, trigger one here
2825
2870
// for the logical error handler.
2826
2871
if (LogicalErrorHandler::hasActiveDiagnostics (Diags, D->getBeginLoc ())) {
0 commit comments