https://github.com/GkvJwa updated 
https://github.com/llvm/llvm-project/pull/172287

>From 2e34318cd3fbffedbd231239d9f99a0907442970 Mon Sep 17 00:00:00 2001
From: GkvJwa <[email protected]>
Date: Thu, 18 Dec 2025 00:30:02 +0800
Subject: [PATCH] Add test and skip Borland

---
 clang/lib/Sema/SemaStmt.cpp           | 70 +++++++++++++++++++++++++++
 clang/test/SemaCXX/exceptions-seh.cpp | 30 ++++++++++++
 2 files changed, 100 insertions(+)

diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 1b1643250d05e..c562d15b0338c 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -4515,6 +4515,57 @@ 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(Sema &S, const Stmt *Node) {
+  (void)S;
+  if (!Node)
+    return nullptr;
+
+  // Check for declarations of local variables with non-trivial destructors.
+  if (const DeclStmt *DS = dyn_cast<DeclStmt>(Node)) {
+    for (const Decl *D : DS->decls()) {
+      if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+        QualType T = VD->getType();
+        if (const RecordType *RT = T->getAs<RecordType>()) {
+          if (const CXXRecordDecl *RD = RT->getAsCXXRecordDecl()) {
+            if (RD->hasDefinition() && !RD->hasTrivialDestructor())
+              return DS;
+          }
+        }
+      }
+    }
+  }
+
+  // Check for expressions that materialize temporaries or otherwise
+  // produce prvalue/xvalue C++ objects that will require destruction.
+  if (const Expr *E = dyn_cast<Expr>(Node)) {
+    // A throw-expression creates an exception object as part of throwing and
+    // doesn't create a temporary that lives until the end of the handler
+    // scope; ignore it when checking for non-trivial temporaries.
+    if (isa<CXXThrowExpr>(E))
+      return nullptr;
+
+    QualType T = E->getType();
+    if (T->isRecordType() && E->getValueKind() != VK_LValue) {
+      if (const RecordType *RT = T->getAs<RecordType>()) {
+        if (const CXXRecordDecl *RD = RT->getAsCXXRecordDecl()) {
+          if (RD->hasDefinition() && !RD->hasTrivialDestructor())
+            return E;
+        }
+      }
+    }
+  }
+
+  // Recurse into children.
+  for (const Stmt *Child : Node->children())
+    if (const Stmt *SWith = findNonTrivialObject(S, Child))
+      return SWith;
+
+  return nullptr;
+}
+
 StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
                                   Stmt *TryBlock, Stmt *Handler) {
   assert(TryBlock && Handler);
@@ -4535,6 +4586,17 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, 
SourceLocation TryLoc,
 
   FSI->setHasSEHTry(TryLoc);
 
+  // Disallow non-trivial C++ objects in an SEH __try block as well. If the
+  // try block contains temporaries or local objects with non-trivial
+  // destructors, emit the same diagnostic and fail parsing the try. Skip
+  // this diagnostic when Borland extensions are enabled.
+  if (!getLangOpts().Borland) {
+    if (const Stmt *Offending = findNonTrivialObject(*this, TryBlock)) {
+      return StmtError(
+          Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions));
+    }
+  }
+
   // Reject __try in Obj-C methods, blocks, and captured decls, since we don't
   // track if they use SEH.
   DeclContext *DC = CurContext;
@@ -4562,6 +4624,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(*this, 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..0a008aeb5721e 100644
--- a/clang/test/SemaCXX/exceptions-seh.cpp
+++ b/clang/test/SemaCXX/exceptions-seh.cpp
@@ -126,3 +126,33 @@ 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;
+}
\ No newline at end of file

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to