[clang] 59a5c1f - [clang][Sema] Diagnose exceptions only in non-dependent context in discarded `try/catch/throw` blocks (#139859)

via cfe-commits cfe-commits at lists.llvm.org
Wed May 28 07:10:58 PDT 2025


Author: Rajveer Singh Bharadwaj
Date: 2025-05-28T07:10:55-07:00
New Revision: 59a5c1f25f578bb1a4951a4610b4e683ee94a870

URL: https://github.com/llvm/llvm-project/commit/59a5c1f25f578bb1a4951a4610b4e683ee94a870
DIFF: https://github.com/llvm/llvm-project/commit/59a5c1f25f578bb1a4951a4610b4e683ee94a870.diff

LOG: [clang][Sema] Diagnose exceptions only in non-dependent context in discarded `try/catch/throw` blocks (#139859)

Resolves #138939

When enabling `--fno-exceptions` flag, discarded statements containing
`try/catch/throw` in an independent context can be avoided from being
rejected.

Added: 
    

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaExprCXX.cpp
    clang/lib/Sema/SemaStmt.cpp
    clang/lib/Sema/TreeTransform.h
    clang/test/SemaCXX/no-exceptions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b423e2a61fef9..6ce9ae588b637 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11170,6 +11170,8 @@ class Sema final : public SemaBase {
   StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
                               ArrayRef<Stmt *> Handlers);
 
+  void DiagnoseExceptionUse(SourceLocation Loc, bool IsTry);
+
   StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
                               SourceLocation TryLoc, Stmt *TryBlock,
                               Stmt *Handler);

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d8338e08dd0f7..7b08fb869ccca 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -848,13 +848,8 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
   const llvm::Triple &T = Context.getTargetInfo().getTriple();
   const bool IsOpenMPGPUTarget =
       getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());
-  // Don't report an error if 'throw' is used in system headers or in an OpenMP
-  // target region compiled for a GPU architecture.
-  if (!IsOpenMPGPUTarget && !getLangOpts().CXXExceptions &&
-      !getSourceManager().isInSystemHeader(OpLoc) && !getLangOpts().CUDA) {
-    // Delay error emission for the OpenMP device code.
-    targetDiag(OpLoc, diag::err_exceptions_disabled) << "throw";
-  }
+
+  DiagnoseExceptionUse(OpLoc, /* IsTry= */ false);
 
   // In OpenMP target regions, we replace 'throw' with a trap on GPU targets.
   if (IsOpenMPGPUTarget)

diff  --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 1fc96664dd87c..bc873937f6dc5 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -4311,13 +4311,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
   const llvm::Triple &T = Context.getTargetInfo().getTriple();
   const bool IsOpenMPGPUTarget =
       getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());
-  // Don't report an error if 'try' is used in system headers or in an OpenMP
-  // target region compiled for a GPU architecture.
-  if (!IsOpenMPGPUTarget && !getLangOpts().CXXExceptions &&
-      !getSourceManager().isInSystemHeader(TryLoc) && !getLangOpts().CUDA) {
-    // Delay error emission for the OpenMP device code.
-    targetDiag(TryLoc, diag::err_exceptions_disabled) << "try";
-  }
+
+  DiagnoseExceptionUse(TryLoc, /* IsTry= */ true);
 
   // In OpenMP target regions, we assume that catch is never reached on GPU
   // targets.
@@ -4419,6 +4414,23 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
                             Handlers);
 }
 
+void Sema::DiagnoseExceptionUse(SourceLocation Loc, bool IsTry) {
+  const llvm::Triple &T = Context.getTargetInfo().getTriple();
+  const bool IsOpenMPGPUTarget =
+      getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());
+
+  // Don't report an error if 'try' is used in system headers or in an OpenMP
+  // target region compiled for a GPU architecture.
+  if (IsOpenMPGPUTarget || getLangOpts().CUDA)
+    // Delay error emission for the OpenMP device code.
+    return;
+
+  if (!getLangOpts().CXXExceptions &&
+      !getSourceManager().isInSystemHeader(Loc) &&
+      !CurContext->isDependentContext())
+    targetDiag(Loc, diag::err_exceptions_disabled) << (IsTry ? "try" : "throw");
+}
+
 StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
                                   Stmt *TryBlock, Stmt *Handler) {
   assert(TryBlock && Handler);

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7629e84f5b848..bd839087c66ed 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -9169,6 +9169,8 @@ StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
     Handlers.push_back(Handler.getAs<Stmt>());
   }
 
+  getSema().DiagnoseExceptionUse(S->getTryLoc(), /* IsTry= */ true);
+
   if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() &&
       !HandlerChanged)
     return S;
@@ -14391,6 +14393,8 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
   if (SubExpr.isInvalid())
     return ExprError();
 
+  getSema().DiagnoseExceptionUse(E->getThrowLoc(), /* IsTry= */ false);
+
   if (!getDerived().AlwaysRebuild() &&
       SubExpr.get() == E->getSubExpr())
     return E;

diff  --git a/clang/test/SemaCXX/no-exceptions.cpp b/clang/test/SemaCXX/no-exceptions.cpp
index 097123d3fe523..e8ac8a657ab84 100644
--- a/clang/test/SemaCXX/no-exceptions.cpp
+++ b/clang/test/SemaCXX/no-exceptions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
 
 // Various tests for -fno-exceptions
 
@@ -30,5 +30,28 @@ void g() {
   } catch (...) {
   }
 }
+}
+
+namespace test2 {
+template <auto enable> void foo(auto &&Fnc) {
+  if constexpr (enable)
+    try {
+      Fnc();
+    } catch (...) {
+    }
+  else
+    Fnc();
+}
+
+void bar1() {
+  foo<false>([] {});
+}
 
+template <typename T> void foo() {
+  try { // expected-error {{cannot use 'try' with exceptions disabled}}
+  } catch (...) {
+  }
+  throw 1; // expected-error {{cannot use 'throw' with exceptions disabled}}
+}
+void bar2() { foo<int>(); } // expected-note {{in instantiation of function template specialization 'test2::foo<int>' requested here}}
 }


        


More information about the cfe-commits mailing list