https://github.com/GkvJwa updated https://github.com/llvm/llvm-project/pull/172287
>From e1a11aa30ccf63162de6f7d9507460db9614362b Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Thu, 18 Dec 2025 00:30:02 +0800 Subject: [PATCH 1/3] Use sema --- clang/lib/Sema/SemaStmt.cpp | 61 +++++++++++++++++++++++++++ clang/test/SemaCXX/exceptions-seh.cpp | 42 ++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 1b1643250d05e..a32d5c37b4605 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -4515,6 +4515,55 @@ void Sema::DiagnoseExceptionUse(SourceLocation Loc, bool IsTry) { targetDiag(Loc, diag::err_exceptions_disabled) << (IsTry ? "try" : "throw"); } +// Walk the statement subtree and return the first statement that +// contains a non-trivial C++ object that would require destruction at +// scope exit, or nullptr if none was found. +static const Stmt *findNonTrivialObject(const Stmt *S) { + if (!S) + return nullptr; + + llvm::SmallVector<const Stmt *, 32> Worklist; + Worklist.push_back(S); + + while (!Worklist.empty()) { + const Stmt *Cur = Worklist.pop_back_val(); + if (!Cur) + continue; + + if (isa<CXXThrowExpr>(Cur)) + return nullptr; + + if (isa<CXXConstructExpr>(Cur) || isa<CXXTemporaryObjectExpr>(Cur) || + isa<CXXNewExpr>(Cur)) { + return Cur; + } + + if (isa<CXXBindTemporaryExpr>(Cur) || isa<CXXDeleteExpr>(Cur)) { + return Cur; + } + + if (const auto *DS = dyn_cast<DeclStmt>(Cur)) { + for (const Decl *D : DS->decls()) { + if (const auto *VD = dyn_cast<VarDecl>(D)) { + QualType QT = VD->getType(); + if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl()) { + if (const CXXDestructorDecl *DD = RD->getDestructor()) { + if (!DD->isTrivial()) + return DS; + } + } + } + } + } + + for (const Stmt *Child : Cur->children()) + if (Child) + Worklist.push_back(Child); + } + + return nullptr; +} + StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler) { assert(TryBlock && Handler); @@ -4531,6 +4580,10 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, ? "'try'" : "'@try'"); } + if (const Stmt *Offending = findNonTrivialObject(TryBlock)) { + return StmtError( + Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions)); + } } FSI->setHasSEHTry(TryLoc); @@ -4562,6 +4615,14 @@ StmtResult Sema::ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FTy); } + // Disallow non-trivial C++ objects in an SEH __except handler. Skip + // this diagnostic when Borland extensions are enabled. + if (!getLangOpts().Borland) { + if (const Stmt *Offending = findNonTrivialObject(Block)) { + return StmtError( + Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions)); + } + } return SEHExceptStmt::Create(Context, Loc, FilterExpr, Block); } diff --git a/clang/test/SemaCXX/exceptions-seh.cpp b/clang/test/SemaCXX/exceptions-seh.cpp index 02bb786160dcf..bdc369ff767da 100644 --- a/clang/test/SemaCXX/exceptions-seh.cpp +++ b/clang/test/SemaCXX/exceptions-seh.cpp @@ -126,3 +126,45 @@ void instantiate_dependent_filter() { dependent_filter<int>(); dependent_filter<NotInteger>(); // expected-note {{requested here}} } + +int puts(const char *); +class CheckError { +public: + static CheckError Check(const char* msg); + + ~CheckError(); +}; + +int foo__try(const int* f) { + int e; + __try { + CheckError::Check("null pointer"); // expected-error{{cannot use SEH '__try' in blocks}} + e = *f; + } __except (1) { + puts("Caught a C-based exception."); + } + return e; +} + +int foo__except(const int* f) { + int e; + __try { + puts("null pointer"); + e = *f; + } __except (1) { + CheckError::Check("Caught a C-based exception."); // expected-error{{cannot use SEH '__try' in blocks}} + } + return e; +} + +// has throw should work +int foo__except_with_throw(const int* f) { + int e; + __try { + puts("null pointer"); + e = *f; + } __except (1) { + throw(CheckError::Check("Caught a C-based exception.")); + } + return e; +} >From 86db2c253868a1fb867497c88ee06a2d938696c1 Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Sun, 21 Dec 2025 16:24:55 +0800 Subject: [PATCH 2/3] Revert "Use sema" This reverts commit e1a11aa30ccf63162de6f7d9507460db9614362b. --- clang/lib/Sema/SemaStmt.cpp | 61 --------------------------- clang/test/SemaCXX/exceptions-seh.cpp | 42 ------------------ 2 files changed, 103 deletions(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a32d5c37b4605..1b1643250d05e 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -4515,55 +4515,6 @@ void Sema::DiagnoseExceptionUse(SourceLocation Loc, bool IsTry) { targetDiag(Loc, diag::err_exceptions_disabled) << (IsTry ? "try" : "throw"); } -// Walk the statement subtree and return the first statement that -// contains a non-trivial C++ object that would require destruction at -// scope exit, or nullptr if none was found. -static const Stmt *findNonTrivialObject(const Stmt *S) { - if (!S) - return nullptr; - - llvm::SmallVector<const Stmt *, 32> Worklist; - Worklist.push_back(S); - - while (!Worklist.empty()) { - const Stmt *Cur = Worklist.pop_back_val(); - if (!Cur) - continue; - - if (isa<CXXThrowExpr>(Cur)) - return nullptr; - - if (isa<CXXConstructExpr>(Cur) || isa<CXXTemporaryObjectExpr>(Cur) || - isa<CXXNewExpr>(Cur)) { - return Cur; - } - - if (isa<CXXBindTemporaryExpr>(Cur) || isa<CXXDeleteExpr>(Cur)) { - return Cur; - } - - if (const auto *DS = dyn_cast<DeclStmt>(Cur)) { - for (const Decl *D : DS->decls()) { - if (const auto *VD = dyn_cast<VarDecl>(D)) { - QualType QT = VD->getType(); - if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl()) { - if (const CXXDestructorDecl *DD = RD->getDestructor()) { - if (!DD->isTrivial()) - return DS; - } - } - } - } - } - - for (const Stmt *Child : Cur->children()) - if (Child) - Worklist.push_back(Child); - } - - return nullptr; -} - StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler) { assert(TryBlock && Handler); @@ -4580,10 +4531,6 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, ? "'try'" : "'@try'"); } - if (const Stmt *Offending = findNonTrivialObject(TryBlock)) { - return StmtError( - Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions)); - } } FSI->setHasSEHTry(TryLoc); @@ -4615,14 +4562,6 @@ StmtResult Sema::ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FTy); } - // Disallow non-trivial C++ objects in an SEH __except handler. Skip - // this diagnostic when Borland extensions are enabled. - if (!getLangOpts().Borland) { - if (const Stmt *Offending = findNonTrivialObject(Block)) { - return StmtError( - Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions)); - } - } return SEHExceptStmt::Create(Context, Loc, FilterExpr, Block); } diff --git a/clang/test/SemaCXX/exceptions-seh.cpp b/clang/test/SemaCXX/exceptions-seh.cpp index bdc369ff767da..02bb786160dcf 100644 --- a/clang/test/SemaCXX/exceptions-seh.cpp +++ b/clang/test/SemaCXX/exceptions-seh.cpp @@ -126,45 +126,3 @@ void instantiate_dependent_filter() { dependent_filter<int>(); dependent_filter<NotInteger>(); // expected-note {{requested here}} } - -int puts(const char *); -class CheckError { -public: - static CheckError Check(const char* msg); - - ~CheckError(); -}; - -int foo__try(const int* f) { - int e; - __try { - CheckError::Check("null pointer"); // expected-error{{cannot use SEH '__try' in blocks}} - e = *f; - } __except (1) { - puts("Caught a C-based exception."); - } - return e; -} - -int foo__except(const int* f) { - int e; - __try { - puts("null pointer"); - e = *f; - } __except (1) { - CheckError::Check("Caught a C-based exception."); // expected-error{{cannot use SEH '__try' in blocks}} - } - return e; -} - -// has throw should work -int foo__except_with_throw(const int* f) { - int e; - __try { - puts("null pointer"); - e = *f; - } __except (1) { - throw(CheckError::Check("Caught a C-based exception.")); - } - return e; -} >From d56028a47bcdf940f3d73154a043240ec3db7777 Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Sun, 21 Dec 2025 16:32:27 +0800 Subject: [PATCH 3/3] Move to CodeGen --- clang/lib/CodeGen/CGException.cpp | 24 ++++++++++++++++++++++++ clang/test/CodeGenCXX/exceptions-seh.cpp | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index e9d20672ce185..3fc87e0e2456b 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -2170,6 +2170,26 @@ void CodeGenFunction::pushSEHCleanup(CleanupKind Kind, EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc); } +static bool StmtCanNotSEH(const Stmt *S) { + if (!S) + return false; + + if (isa<CXXThrowExpr>(S)) + return false; + + if (isa<CXXBindTemporaryExpr>(S)) + return true; + + if (isa<CXXConstructExpr>(S)) + return true; + + for (const auto *child : S->children()) + if (StmtCanNotSEH(child)) + return true; + + return false; +} + void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); HelperCGF.ParentCGF = this; @@ -2186,6 +2206,10 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { // Otherwise, we must have an __except block. const SEHExceptStmt *Except = S.getExceptHandler(); assert(Except); + if (!CGM.getLangOpts().Borland && + (StmtCanNotSEH(&S) || StmtCanNotSEH(Except))) + CGM.getDiags().Report(CurFuncDecl->getLocation(), + diag::err_seh_try_outside_functions); EHCatchScope *CatchScope = EHStack.pushCatch(1); SEHCodeSlotStack.push_back( CreateMemTemp(getContext().IntTy, "__exception_code")); diff --git a/clang/test/CodeGenCXX/exceptions-seh.cpp b/clang/test/CodeGenCXX/exceptions-seh.cpp index bb374dd1f5bd5..39c39b179983d 100644 --- a/clang/test/CodeGenCXX/exceptions-seh.cpp +++ b/clang/test/CodeGenCXX/exceptions-seh.cpp @@ -4,6 +4,10 @@ // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \ // RUN: -o - -mconstructor-aliases -O1 -disable-llvm-passes | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX +// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \ +// RUN: -x c++ -emit-llvm -verify %s -DERR1 +// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions \ +// RUN: -x c++ -emit-llvm -verify %s -DERR2 extern "C" unsigned long _exception_code(); extern "C" void might_throw(); @@ -175,3 +179,19 @@ void use_inline() { // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } void seh_in_noexcept() noexcept { __try {} __finally {} } + +#if defined(ERR1) +void seh_unwinding() { // expected-error{{cannot use SEH '__try' in blocks}} + __try { + HasCleanup x; + } __except (1) { + } +} +#elif defined(ERR2) +void seh_unwinding() { // expected-error{{cannot use SEH '__try' in blocks}} + __try { + } __except (1) { + HasCleanup x; + } +} +#endif _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
