aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp124
1 files changed, 76 insertions, 48 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
index 8816c9c1fea0..75730ea888af 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -21,6 +21,7 @@
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include <optional>
namespace clang {
@@ -78,14 +79,21 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
.Default(false);
}
-ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc,
- Expr *NoexceptExpr,
+ExprResult Sema::ActOnNoexceptSpec(Expr *NoexceptExpr,
ExceptionSpecificationType &EST) {
- // FIXME: This is bogus, a noexcept expression is not a condition.
- ExprResult Converted = CheckBooleanCondition(NoexceptLoc, NoexceptExpr);
+
+ if (NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->containsUnexpandedParameterPack()) {
+ EST = EST_DependentNoexcept;
+ return NoexceptExpr;
+ }
+
+ llvm::APSInt Result;
+ ExprResult Converted = CheckConvertedConstantExpression(
+ NoexceptExpr, Context.BoolTy, Result, CCEK_Noexcept);
+
if (Converted.isInvalid()) {
EST = EST_NoexceptFalse;
-
// Fill in an expression of 'false' as a fixup.
auto *BoolExpr = new (Context)
CXXBoolLiteralExpr(false, Context.BoolTy, NoexceptExpr->getBeginLoc());
@@ -99,9 +107,6 @@ ExprResult Sema::ActOnNoexceptSpec(SourceLocation NoexceptLoc,
return Converted;
}
- llvm::APSInt Result;
- Converted = VerifyIntegerConstantExpression(
- Converted.get(), &Result, diag::err_noexcept_needs_constant_expression);
if (!Converted.isInvalid())
EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
return Converted;
@@ -167,6 +172,12 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range))
return ReturnValueOnError;
+ // WebAssembly reference types can't be used in exception specifications.
+ if (PointeeT.isWebAssemblyReferenceType()) {
+ Diag(Range.getBegin(), diag::err_wasm_reftype_exception_spec);
+ return true;
+ }
+
// The MSVC compatibility mode doesn't extend to sizeless types,
// so diagnose them separately.
if (PointeeT->isSizelessType() && Kind != 1) {
@@ -338,8 +349,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
if (!MissingExceptionSpecification)
return ReturnValueOnError;
- const FunctionProtoType *NewProto =
- New->getType()->castAs<FunctionProtoType>();
+ const auto *NewProto = New->getType()->castAs<FunctionProtoType>();
// The new function declaration is only missing an empty exception
// specification "throw()". If the throw() specification came from a
@@ -349,7 +359,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// specifications.
//
// Likewise if the old function is a builtin.
- if (MissingEmptyExceptionSpecification && NewProto &&
+ if (MissingEmptyExceptionSpecification &&
(Old->getLocation().isInvalid() ||
Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
Old->getBuiltinID()) &&
@@ -360,8 +370,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
return false;
}
- const FunctionProtoType *OldProto =
- Old->getType()->castAs<FunctionProtoType>();
+ const auto *OldProto = Old->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
if (ESI.Type == EST_Dynamic) {
@@ -387,9 +396,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
}
- if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) {
- // Allow missing exception specifications in redeclarations as an extension.
- DiagID = diag::ext_ms_missing_exception_specification;
+ if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
+ DiagID = diag::ext_missing_exception_specification;
ReturnValueOnError = false;
} else if (New->isReplaceableGlobalAllocationFunction() &&
ESI.Type != EST_DependentNoexcept) {
@@ -398,6 +406,10 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
DiagID = diag::ext_missing_exception_specification;
ReturnValueOnError = false;
} else if (ESI.Type == EST_NoThrow) {
+ // Don't emit any warning for missing 'nothrow' in MSVC.
+ if (getLangOpts().MSVCCompat) {
+ return false;
+ }
// Allow missing attribute 'nothrow' in redeclarations, since this is a very
// common omission.
DiagID = diag::ext_missing_exception_specification;
@@ -757,14 +769,12 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
/// CheckExceptionSpecSubset - Check whether the second function type's
/// exception specification is a subset (or equivalent) of the first function
/// type. This is used by override and pointer assignment checks.
-bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
- const PartialDiagnostic &NestedDiagID,
- const PartialDiagnostic &NoteID,
- const PartialDiagnostic &NoThrowDiagID,
- const FunctionProtoType *Superset,
- SourceLocation SuperLoc,
- const FunctionProtoType *Subset,
- SourceLocation SubLoc) {
+bool Sema::CheckExceptionSpecSubset(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID,
+ const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID,
+ const FunctionProtoType *Superset, bool SkipSupersetFirstParameter,
+ SourceLocation SuperLoc, const FunctionProtoType *Subset,
+ bool SkipSubsetFirstParameter, SourceLocation SubLoc) {
// Just auto-succeed under -fno-exceptions.
if (!getLangOpts().CXXExceptions)
@@ -804,8 +814,9 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
// done.
if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) ||
SubCanThrow == CT_Cannot)
- return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
- Subset, SubLoc);
+ return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset,
+ SkipSupersetFirstParameter, SuperLoc, Subset,
+ SkipSubsetFirstParameter, SubLoc);
// Allow __declspec(nothrow) to be missing on redeclaration as an extension in
// some cases.
@@ -857,8 +868,9 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
}
}
// We've run half the gauntlet.
- return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
- Subset, SubLoc);
+ return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset,
+ SkipSupersetFirstParameter, SuperLoc, Subset,
+ SkipSupersetFirstParameter, SubLoc);
}
static bool
@@ -882,12 +894,11 @@ CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID,
/// assignment and override compatibility check. We do not check the parameters
/// of parameter function pointers recursively, as no sane programmer would
/// even be able to write such a function type.
-bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &DiagID,
- const PartialDiagnostic &NoteID,
- const FunctionProtoType *Target,
- SourceLocation TargetLoc,
- const FunctionProtoType *Source,
- SourceLocation SourceLoc) {
+bool Sema::CheckParamExceptionSpec(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Target, bool SkipTargetFirstParameter,
+ SourceLocation TargetLoc, const FunctionProtoType *Source,
+ bool SkipSourceFirstParameter, SourceLocation SourceLoc) {
auto RetDiag = DiagID;
RetDiag << 0;
if (CheckSpecForTypesEquivalent(
@@ -898,14 +909,16 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &DiagID,
// We shouldn't even be testing this unless the arguments are otherwise
// compatible.
- assert(Target->getNumParams() == Source->getNumParams() &&
+ assert((Target->getNumParams() - (unsigned)SkipTargetFirstParameter) ==
+ (Source->getNumParams() - (unsigned)SkipSourceFirstParameter) &&
"Functions have different argument counts.");
for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) {
auto ParamDiag = DiagID;
ParamDiag << 1;
if (CheckSpecForTypesEquivalent(
*this, ParamDiag, PDiag(),
- Target->getParamType(i), TargetLoc, Source->getParamType(i),
+ Target->getParamType(i + (SkipTargetFirstParameter ? 1 : 0)),
+ TargetLoc, Source->getParamType(SkipSourceFirstParameter ? 1 : 0),
SourceLoc))
return true;
}
@@ -946,9 +959,10 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
// void (*q)(void (*) throw(int)) = p;
// }
// ... because it might be instantiated with T=int.
- return CheckExceptionSpecSubset(
- PDiag(DiagID), PDiag(NestedDiagID), PDiag(), PDiag(), ToFunc,
- From->getSourceRange().getBegin(), FromFunc, SourceLocation()) &&
+ return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(),
+ PDiag(), ToFunc, 0,
+ From->getSourceRange().getBegin(), FromFunc,
+ 0, SourceLocation()) &&
!getLangOpts().CPlusPlus17;
}
@@ -977,14 +991,14 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
unsigned DiagID = diag::err_override_exception_spec;
if (getLangOpts().MSVCCompat)
DiagID = diag::ext_override_exception_spec;
- return CheckExceptionSpecSubset(PDiag(DiagID),
- PDiag(diag::err_deep_exception_specs_differ),
- PDiag(diag::note_overridden_virtual_function),
- PDiag(diag::ext_override_exception_spec),
- Old->getType()->castAs<FunctionProtoType>(),
- Old->getLocation(),
- New->getType()->castAs<FunctionProtoType>(),
- New->getLocation());
+ return CheckExceptionSpecSubset(
+ PDiag(DiagID), PDiag(diag::err_deep_exception_specs_differ),
+ PDiag(diag::note_overridden_virtual_function),
+ PDiag(diag::ext_override_exception_spec),
+ Old->getType()->castAs<FunctionProtoType>(),
+ Old->hasCXXExplicitFunctionObjectParameter(), Old->getLocation(),
+ New->getType()->castAs<FunctionProtoType>(),
+ New->hasCXXExplicitFunctionObjectParameter(), New->getLocation());
}
static CanThrowResult canSubStmtsThrow(Sema &Self, const Stmt *S) {
@@ -1284,6 +1298,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Expr::StmtExprClass:
case Expr::ConvertVectorExprClass:
case Expr::VAArgExprClass:
+ case Expr::CXXParenListInitExprClass:
return canSubStmtsThrow(*this, S);
case Expr::CompoundLiteralExprClass:
@@ -1448,15 +1463,20 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OMPForSimdDirectiveClass:
case Stmt::OMPMasterDirectiveClass:
case Stmt::OMPMasterTaskLoopDirectiveClass:
+ case Stmt::OMPMaskedTaskLoopDirectiveClass:
case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
+ case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
case Stmt::OMPOrderedDirectiveClass:
case Stmt::OMPCanonicalLoopClass:
case Stmt::OMPParallelDirectiveClass:
case Stmt::OMPParallelForDirectiveClass:
case Stmt::OMPParallelForSimdDirectiveClass:
case Stmt::OMPParallelMasterDirectiveClass:
+ case Stmt::OMPParallelMaskedDirectiveClass:
case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
+ case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
+ case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
case Stmt::OMPParallelSectionsDirectiveClass:
case Stmt::OMPSectionDirectiveClass:
case Stmt::OMPSectionsDirectiveClass:
@@ -1478,12 +1498,14 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
case Stmt::OMPTargetUpdateDirectiveClass:
+ case Stmt::OMPScopeDirectiveClass:
case Stmt::OMPTaskDirectiveClass:
case Stmt::OMPTaskgroupDirectiveClass:
case Stmt::OMPTaskLoopDirectiveClass:
case Stmt::OMPTaskLoopSimdDirectiveClass:
case Stmt::OMPTaskwaitDirectiveClass:
case Stmt::OMPTaskyieldDirectiveClass:
+ case Stmt::OMPErrorDirectiveClass:
case Stmt::OMPTeamsDirectiveClass:
case Stmt::OMPTeamsDistributeDirectiveClass:
case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
@@ -1492,6 +1514,12 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OMPInteropDirectiveClass:
case Stmt::OMPDispatchDirectiveClass:
case Stmt::OMPMaskedDirectiveClass:
+ case Stmt::OMPMetaDirectiveClass:
+ case Stmt::OMPGenericLoopDirectiveClass:
+ case Stmt::OMPTeamsGenericLoopDirectiveClass:
+ case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
+ case Stmt::OMPParallelGenericLoopDirectiveClass:
+ case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
case Stmt::ReturnStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
@@ -1529,7 +1557,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
// For 'if constexpr', consider only the non-discarded case.
// FIXME: We should add a DiscardedStmt marker to the AST.
- if (Optional<const Stmt *> Case = IS->getNondiscardedCase(Context))
+ if (std::optional<const Stmt *> Case = IS->getNondiscardedCase(Context))
return *Case ? mergeCanThrow(CT, canThrow(*Case)) : CT;
CanThrowResult Then = canThrow(IS->getThen());