Skip to content

Commit 59a5c1f

Browse files
authored
[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.
1 parent d58e00d commit 59a5c1f

File tree

5 files changed

+51
-15
lines changed

5 files changed

+51
-15
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11170,6 +11170,8 @@ class Sema final : public SemaBase {
1117011170
StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
1117111171
ArrayRef<Stmt *> Handlers);
1117211172

11173+
void DiagnoseExceptionUse(SourceLocation Loc, bool IsTry);
11174+
1117311175
StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
1117411176
SourceLocation TryLoc, Stmt *TryBlock,
1117511177
Stmt *Handler);

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -848,13 +848,8 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
848848
const llvm::Triple &T = Context.getTargetInfo().getTriple();
849849
const bool IsOpenMPGPUTarget =
850850
getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());
851-
// Don't report an error if 'throw' is used in system headers or in an OpenMP
852-
// target region compiled for a GPU architecture.
853-
if (!IsOpenMPGPUTarget && !getLangOpts().CXXExceptions &&
854-
!getSourceManager().isInSystemHeader(OpLoc) && !getLangOpts().CUDA) {
855-
// Delay error emission for the OpenMP device code.
856-
targetDiag(OpLoc, diag::err_exceptions_disabled) << "throw";
857-
}
851+
852+
DiagnoseExceptionUse(OpLoc, /* IsTry= */ false);
858853

859854
// In OpenMP target regions, we replace 'throw' with a trap on GPU targets.
860855
if (IsOpenMPGPUTarget)

clang/lib/Sema/SemaStmt.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4311,13 +4311,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
43114311
const llvm::Triple &T = Context.getTargetInfo().getTriple();
43124312
const bool IsOpenMPGPUTarget =
43134313
getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());
4314-
// Don't report an error if 'try' is used in system headers or in an OpenMP
4315-
// target region compiled for a GPU architecture.
4316-
if (!IsOpenMPGPUTarget && !getLangOpts().CXXExceptions &&
4317-
!getSourceManager().isInSystemHeader(TryLoc) && !getLangOpts().CUDA) {
4318-
// Delay error emission for the OpenMP device code.
4319-
targetDiag(TryLoc, diag::err_exceptions_disabled) << "try";
4320-
}
4314+
4315+
DiagnoseExceptionUse(TryLoc, /* IsTry= */ true);
43214316

43224317
// In OpenMP target regions, we assume that catch is never reached on GPU
43234318
// targets.
@@ -4419,6 +4414,23 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
44194414
Handlers);
44204415
}
44214416

4417+
void Sema::DiagnoseExceptionUse(SourceLocation Loc, bool IsTry) {
4418+
const llvm::Triple &T = Context.getTargetInfo().getTriple();
4419+
const bool IsOpenMPGPUTarget =
4420+
getLangOpts().OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN());
4421+
4422+
// Don't report an error if 'try' is used in system headers or in an OpenMP
4423+
// target region compiled for a GPU architecture.
4424+
if (IsOpenMPGPUTarget || getLangOpts().CUDA)
4425+
// Delay error emission for the OpenMP device code.
4426+
return;
4427+
4428+
if (!getLangOpts().CXXExceptions &&
4429+
!getSourceManager().isInSystemHeader(Loc) &&
4430+
!CurContext->isDependentContext())
4431+
targetDiag(Loc, diag::err_exceptions_disabled) << (IsTry ? "try" : "throw");
4432+
}
4433+
44224434
StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
44234435
Stmt *TryBlock, Stmt *Handler) {
44244436
assert(TryBlock && Handler);

clang/lib/Sema/TreeTransform.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9169,6 +9169,8 @@ StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
91699169
Handlers.push_back(Handler.getAs<Stmt>());
91709170
}
91719171

9172+
getSema().DiagnoseExceptionUse(S->getTryLoc(), /* IsTry= */ true);
9173+
91729174
if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() &&
91739175
!HandlerChanged)
91749176
return S;
@@ -14391,6 +14393,8 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
1439114393
if (SubExpr.isInvalid())
1439214394
return ExprError();
1439314395

14396+
getSema().DiagnoseExceptionUse(E->getThrowLoc(), /* IsTry= */ false);
14397+
1439414398
if (!getDerived().AlwaysRebuild() &&
1439514399
SubExpr.get() == E->getSubExpr())
1439614400
return E;

clang/test/SemaCXX/no-exceptions.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
22

33
// Various tests for -fno-exceptions
44

@@ -30,5 +30,28 @@ void g() {
3030
} catch (...) {
3131
}
3232
}
33+
}
34+
35+
namespace test2 {
36+
template <auto enable> void foo(auto &&Fnc) {
37+
if constexpr (enable)
38+
try {
39+
Fnc();
40+
} catch (...) {
41+
}
42+
else
43+
Fnc();
44+
}
45+
46+
void bar1() {
47+
foo<false>([] {});
48+
}
3349

50+
template <typename T> void foo() {
51+
try { // expected-error {{cannot use 'try' with exceptions disabled}}
52+
} catch (...) {
53+
}
54+
throw 1; // expected-error {{cannot use 'throw' with exceptions disabled}}
55+
}
56+
void bar2() { foo<int>(); } // expected-note {{in instantiation of function template specialization 'test2::foo<int>' requested here}}
3457
}

0 commit comments

Comments
 (0)