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

>From 1dc5b737beeb3062bafc6e8221aeb9cef9b1b77b Mon Sep 17 00:00:00 2001
From: GkvJwa <[email protected]>
Date: Wed, 17 Dec 2025 01:02:42 +0800
Subject: [PATCH 1/3] Add check object

---
 clang/lib/Sema/SemaStmt.cpp | 43 +++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

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<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 true;
+          }
+        }
+      }
+    }
+  }
+
+  if (const Expr *E = dyn_cast<Expr>(Node)) {
+    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 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);
 }
 

>From adfa51086425c0f9400342f04746428851b217b8 Mon Sep 17 00:00:00 2001
From: GkvJwa <[email protected]>
Date: Wed, 17 Dec 2025 23:02:49 +0800
Subject: [PATCH 2/3] Check try block and CXXThrow

---
 clang/lib/Sema/SemaStmt.cpp | 106 ++++++++++++++++++++++--------------
 1 file changed, 65 insertions(+), 41 deletions(-)

diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index c64029f269c2b..c312c445b1fb3 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -4515,6 +4515,58 @@ 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 +4587,15 @@ 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.
+  if (const Stmt *Offending = findNonTrivialObject(*this, TryBlock)) {
+    Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions);
+    Diag(TryLoc, diag::note_conflicting_try_here) << "'__try'";
+    return StmtError();
+  }
+
   // Reject __try in Obj-C methods, blocks, and captured decls, since we don't
   // track if they use SEH.
   DeclContext *DC = CurContext;
@@ -4553,45 +4614,6 @@ 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<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 true;
-          }
-        }
-      }
-    }
-  }
-
-  if (const Expr *E = dyn_cast<Expr>(Node)) {
-    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 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);
@@ -4601,8 +4623,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);
+  // Disallow non-trivial C++ objects in an SEH __except handler.
+  if (const Stmt *Offending = findNonTrivialObject(*this, Block)) {
+    Diag(Offending->getBeginLoc(), diag::err_seh_try_outside_functions);
+    Diag(Loc, diag::note_conflicting_try_here) << "'__except'";
     return StmtError();
   }
   return SEHExceptStmt::Create(Context, Loc, FilterExpr, Block);

>From da427e01da966fd2a3b083e6a9137366457d1978 Mon Sep 17 00:00:00 2001
From: GkvJwa <[email protected]>
Date: Wed, 17 Dec 2025 23:24:22 +0800
Subject: [PATCH 3/3] Align with mscv

---
 clang/test/SemaCXX/__try.cpp | 33 ++++++++++-----------------------
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/clang/test/SemaCXX/__try.cpp b/clang/test/SemaCXX/__try.cpp
index eb4612f508d37..035fbc26dcefd 100644
--- a/clang/test/SemaCXX/__try.cpp
+++ b/clang/test/SemaCXX/__try.cpp
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify 
-fborland-extensions -fcxx-exceptions %s
+// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions 
-fexceptions -fms-extensions -x c++ %s -verify
 
 // This test is from http://docwiki.embarcadero.com/RADStudio/en/Try
+// We are considering aligning with MSVC.
 
 int puts(const char *);
 
@@ -27,32 +28,18 @@ class Exception
 int main()
 {
   float e, f, g;
-  try
+  f = 1.0;
+  g = 0.0;
+  __try
   {
-    try
-    {
-      f = 1.0;
-      g = 0.0;
-      try
-      {
-        puts("Another exception:");
+    puts("Another exception:");
 
-        e = f / g;
-      }
-      __except(EXCEPTION_EXECUTE_HANDLER)
-      {
-        puts("Caught a C-based exception.");
-        throw(Exception("Hardware error: Divide by 0"));
-      }
-    }
-    catch(const Exception& e)
-    {
-      printf("Caught C++ Exception: %s :\n", e.msg());
-    }
+    e = f / g;
   }
-  __finally
+  __except(EXCEPTION_EXECUTE_HANDLER)
   {
-    puts("C++ allows __finally too!");
+    puts("Caught a C-based exception.");
+    throw(Exception("Hardware error: Divide by 0"));
   }
   return e;
 }

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

Reply via email to