summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExceptionSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp42
1 files changed, 33 insertions, 9 deletions
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index e0850feaffc6..9fd924a8cad0 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -1,9 +1,8 @@
//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -382,6 +381,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// when declaring a replaceable global allocation function.
DiagID = diag::ext_missing_exception_specification;
ReturnValueOnError = false;
+ } else if (ESI.Type == EST_NoThrow) {
+ // Allow missing attribute 'nothrow' in redeclarations, since this is a very
+ // common omission.
+ DiagID = diag::ext_missing_exception_specification;
+ ReturnValueOnError = false;
} else {
DiagID = diag::err_missing_exception_specification;
ReturnValueOnError = true;
@@ -422,8 +426,14 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
break;
-
- default:
+ case EST_NoThrow:
+ OS <<"__attribute__((nothrow))";
+ break;
+ case EST_None:
+ case EST_MSAny:
+ case EST_Unevaluated:
+ case EST_Uninstantiated:
+ case EST_Unparsed:
llvm_unreachable("This spec type is compatible with none.");
}
@@ -734,6 +744,7 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
const PartialDiagnostic &NestedDiagID,
const PartialDiagnostic &NoteID,
+ const PartialDiagnostic &NoThrowDiagID,
const FunctionProtoType *Superset,
SourceLocation SuperLoc,
const FunctionProtoType *Subset,
@@ -780,6 +791,16 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
Subset, SubLoc);
+ // Allow __declspec(nothrow) to be missing on redeclaration as an extension in
+ // some cases.
+ if (NoThrowDiagID.getDiagID() != 0 && SubCanThrow == CT_Can &&
+ SuperCanThrow == CT_Cannot && SuperEST == EST_NoThrow) {
+ Diag(SubLoc, NoThrowDiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+
// If the subset contains everything or the superset contains nothing, we've
// failed.
if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) ||
@@ -909,9 +930,9 @@ 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(),
- ToFunc, From->getSourceRange().getBegin(),
- FromFunc, SourceLocation()) &&
+ return CheckExceptionSpecSubset(
+ PDiag(DiagID), PDiag(NestedDiagID), PDiag(), PDiag(), ToFunc,
+ From->getSourceRange().getBegin(), FromFunc, SourceLocation()) &&
!getLangOpts().CPlusPlus17;
}
@@ -943,6 +964,7 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
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()->getAs<FunctionProtoType>(),
Old->getLocation(),
New->getType()->getAs<FunctionProtoType>(),
@@ -1179,6 +1201,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::CoyieldExprClass:
case Expr::CXXConstCastExprClass:
case Expr::CXXReinterpretCastExprClass:
+ case Expr::BuiltinBitCastExprClass:
case Expr::CXXStdInitializerListExprClass:
case Expr::DesignatedInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
@@ -1290,6 +1313,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::PredefinedExprClass:
case Expr::SizeOfPackExprClass:
case Expr::StringLiteralClass:
+ case Expr::SourceLocExprClass:
// These expressions can never throw.
return CT_Cannot;