diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 1b1643250d05e..c64029f269c2b 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -4553,6 +4553,45 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler); } +static bool containsNonTrivialObject(Sema &S, const Stmt *Node) { + (void)S; + if (!Node) + return false; + + if (const DeclStmt *DS = dyn_cast(Node)) { + for (const Decl *D : DS->decls()) { + if (const VarDecl *VD = dyn_cast(D)) { + QualType T = VD->getType(); + if (const RecordType *RT = T->getAs()) { + if (const CXXRecordDecl *RD = RT->getAsCXXRecordDecl()) { + if (RD->hasDefinition() && !RD->hasTrivialDestructor()) + return true; + } + } + } + } + } + + if (const Expr *E = dyn_cast(Node)) { + QualType T = E->getType(); + if (T->isRecordType() && E->getValueKind() != VK_LValue) { + if (const RecordType *RT = T->getAs()) { + if (const CXXRecordDecl *RD = RT->getAsCXXRecordDecl()) { + if (RD->hasDefinition() && !RD->hasTrivialDestructor()) + return true; + } + } + } + } + + // children. + for (const Stmt *Child : Node->children()) + if (containsNonTrivialObject(S, Child)) + return true; + + return false; +} + StmtResult Sema::ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) { assert(FilterExpr && Block); @@ -4562,6 +4601,10 @@ StmtResult Sema::ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FTy); } + if (containsNonTrivialObject(*this, Block)) { + Diag(Loc, diag::err_seh_try_outside_functions); + return StmtError(); + } return SEHExceptStmt::Create(Context, Loc, FilterExpr, Block); }