diff options
Diffstat (limited to 'lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 42 |
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; |