xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file provides Sema routines for C++ exception specification testing.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTMutationListener.h"
150b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h"
160b57cec5SDimitry Andric #include "clang/AST/Expr.h"
170b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
18480093f4SDimitry Andric #include "clang/AST/StmtObjC.h"
190b57cec5SDimitry Andric #include "clang/AST/TypeLoc.h"
200b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
210b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
220b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
230b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
24bdd1243dSDimitry Andric #include <optional>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace clang {
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric static const FunctionProtoType *GetUnderlyingFunction(QualType T)
290b57cec5SDimitry Andric {
300b57cec5SDimitry Andric   if (const PointerType *PtrTy = T->getAs<PointerType>())
310b57cec5SDimitry Andric     T = PtrTy->getPointeeType();
320b57cec5SDimitry Andric   else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
330b57cec5SDimitry Andric     T = RefTy->getPointeeType();
340b57cec5SDimitry Andric   else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
350b57cec5SDimitry Andric     T = MPTy->getPointeeType();
360b57cec5SDimitry Andric   return T->getAs<FunctionProtoType>();
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
39fe6060f1SDimitry Andric /// HACK: 2014-11-14 libstdc++ had a bug where it shadows std::swap with a
40fe6060f1SDimitry Andric /// member swap function then tries to call std::swap unqualified from the
41fe6060f1SDimitry Andric /// exception specification of that function. This function detects whether
42fe6060f1SDimitry Andric /// we're in such a case and turns off delay-parsing of exception
43fe6060f1SDimitry Andric /// specifications. Libstdc++ 6.1 (released 2016-04-27) appears to have
44fe6060f1SDimitry Andric /// resolved it as side-effect of commit ddb63209a8d (2015-06-05).
450b57cec5SDimitry Andric bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
460b57cec5SDimitry Andric   auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   // All the problem cases are member functions named "swap" within class
490b57cec5SDimitry Andric   // templates declared directly within namespace std or std::__debug or
500b57cec5SDimitry Andric   // std::__profile.
510b57cec5SDimitry Andric   if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() ||
520b57cec5SDimitry Andric       !D.getIdentifier() || !D.getIdentifier()->isStr("swap"))
530b57cec5SDimitry Andric     return false;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext());
560b57cec5SDimitry Andric   if (!ND)
570b57cec5SDimitry Andric     return false;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   bool IsInStd = ND->isStdNamespace();
600b57cec5SDimitry Andric   if (!IsInStd) {
610b57cec5SDimitry Andric     // This isn't a direct member of namespace std, but it might still be
620b57cec5SDimitry Andric     // libstdc++'s std::__debug::array or std::__profile::array.
630b57cec5SDimitry Andric     IdentifierInfo *II = ND->getIdentifier();
640b57cec5SDimitry Andric     if (!II || !(II->isStr("__debug") || II->isStr("__profile")) ||
650b57cec5SDimitry Andric         !ND->isInStdNamespace())
660b57cec5SDimitry Andric       return false;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   // Only apply this hack within a system header.
700b57cec5SDimitry Andric   if (!Context.getSourceManager().isInSystemHeader(D.getBeginLoc()))
710b57cec5SDimitry Andric     return false;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(RD->getIdentifier()->getName())
740b57cec5SDimitry Andric       .Case("array", true)
750b57cec5SDimitry Andric       .Case("pair", IsInStd)
760b57cec5SDimitry Andric       .Case("priority_queue", IsInStd)
770b57cec5SDimitry Andric       .Case("stack", IsInStd)
780b57cec5SDimitry Andric       .Case("queue", IsInStd)
790b57cec5SDimitry Andric       .Default(false);
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
82349cc55cSDimitry Andric ExprResult Sema::ActOnNoexceptSpec(Expr *NoexceptExpr,
830b57cec5SDimitry Andric                                    ExceptionSpecificationType &EST) {
84349cc55cSDimitry Andric 
85349cc55cSDimitry Andric   if (NoexceptExpr->isTypeDependent() ||
86349cc55cSDimitry Andric       NoexceptExpr->containsUnexpandedParameterPack()) {
87349cc55cSDimitry Andric     EST = EST_DependentNoexcept;
88349cc55cSDimitry Andric     return NoexceptExpr;
89349cc55cSDimitry Andric   }
90349cc55cSDimitry Andric 
91349cc55cSDimitry Andric   llvm::APSInt Result;
92349cc55cSDimitry Andric   ExprResult Converted = CheckConvertedConstantExpression(
93349cc55cSDimitry Andric       NoexceptExpr, Context.BoolTy, Result, CCEK_Noexcept);
94349cc55cSDimitry Andric 
95480093f4SDimitry Andric   if (Converted.isInvalid()) {
96480093f4SDimitry Andric     EST = EST_NoexceptFalse;
97480093f4SDimitry Andric     // Fill in an expression of 'false' as a fixup.
98480093f4SDimitry Andric     auto *BoolExpr = new (Context)
99480093f4SDimitry Andric         CXXBoolLiteralExpr(false, Context.BoolTy, NoexceptExpr->getBeginLoc());
100480093f4SDimitry Andric     llvm::APSInt Value{1};
101480093f4SDimitry Andric     Value = 0;
102480093f4SDimitry Andric     return ConstantExpr::Create(Context, BoolExpr, APValue{Value});
103480093f4SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   if (Converted.get()->isValueDependent()) {
1060b57cec5SDimitry Andric     EST = EST_DependentNoexcept;
1070b57cec5SDimitry Andric     return Converted;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   if (!Converted.isInvalid())
1110b57cec5SDimitry Andric     EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
1120b57cec5SDimitry Andric   return Converted;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
1160b57cec5SDimitry Andric   // C++11 [except.spec]p2:
1170b57cec5SDimitry Andric   //   A type cv T, "array of T", or "function returning T" denoted
1180b57cec5SDimitry Andric   //   in an exception-specification is adjusted to type T, "pointer to T", or
1190b57cec5SDimitry Andric   //   "pointer to function returning T", respectively.
1200b57cec5SDimitry Andric   //
1210b57cec5SDimitry Andric   // We also apply this rule in C++98.
1220b57cec5SDimitry Andric   if (T->isArrayType())
1230b57cec5SDimitry Andric     T = Context.getArrayDecayedType(T);
1240b57cec5SDimitry Andric   else if (T->isFunctionType())
1250b57cec5SDimitry Andric     T = Context.getPointerType(T);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   int Kind = 0;
1280b57cec5SDimitry Andric   QualType PointeeT = T;
1290b57cec5SDimitry Andric   if (const PointerType *PT = T->getAs<PointerType>()) {
1300b57cec5SDimitry Andric     PointeeT = PT->getPointeeType();
1310b57cec5SDimitry Andric     Kind = 1;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric     // cv void* is explicitly permitted, despite being a pointer to an
1340b57cec5SDimitry Andric     // incomplete type.
1350b57cec5SDimitry Andric     if (PointeeT->isVoidType())
1360b57cec5SDimitry Andric       return false;
1370b57cec5SDimitry Andric   } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
1380b57cec5SDimitry Andric     PointeeT = RT->getPointeeType();
1390b57cec5SDimitry Andric     Kind = 2;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric     if (RT->isRValueReferenceType()) {
1420b57cec5SDimitry Andric       // C++11 [except.spec]p2:
1430b57cec5SDimitry Andric       //   A type denoted in an exception-specification shall not denote [...]
1440b57cec5SDimitry Andric       //   an rvalue reference type.
1450b57cec5SDimitry Andric       Diag(Range.getBegin(), diag::err_rref_in_exception_spec)
1460b57cec5SDimitry Andric         << T << Range;
1470b57cec5SDimitry Andric       return true;
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // C++11 [except.spec]p2:
1520b57cec5SDimitry Andric   //   A type denoted in an exception-specification shall not denote an
1530b57cec5SDimitry Andric   //   incomplete type other than a class currently being defined [...].
1540b57cec5SDimitry Andric   //   A type denoted in an exception-specification shall not denote a
1550b57cec5SDimitry Andric   //   pointer or reference to an incomplete type, other than (cv) void* or a
1560b57cec5SDimitry Andric   //   pointer or reference to a class currently being defined.
1570b57cec5SDimitry Andric   // In Microsoft mode, downgrade this to a warning.
1580b57cec5SDimitry Andric   unsigned DiagID = diag::err_incomplete_in_exception_spec;
1590b57cec5SDimitry Andric   bool ReturnValueOnError = true;
160a7dea167SDimitry Andric   if (getLangOpts().MSVCCompat) {
1610b57cec5SDimitry Andric     DiagID = diag::ext_incomplete_in_exception_spec;
1620b57cec5SDimitry Andric     ReturnValueOnError = false;
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric   if (!(PointeeT->isRecordType() &&
165a7dea167SDimitry Andric         PointeeT->castAs<RecordType>()->isBeingDefined()) &&
1660b57cec5SDimitry Andric       RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range))
1670b57cec5SDimitry Andric     return ReturnValueOnError;
1680b57cec5SDimitry Andric 
16906c3fb27SDimitry Andric   // WebAssembly reference types can't be used in exception specifications.
17006c3fb27SDimitry Andric   if (PointeeT.isWebAssemblyReferenceType()) {
17106c3fb27SDimitry Andric     Diag(Range.getBegin(), diag::err_wasm_reftype_exception_spec);
17206c3fb27SDimitry Andric     return true;
17306c3fb27SDimitry Andric   }
17406c3fb27SDimitry Andric 
1755ffd83dbSDimitry Andric   // The MSVC compatibility mode doesn't extend to sizeless types,
1765ffd83dbSDimitry Andric   // so diagnose them separately.
1775ffd83dbSDimitry Andric   if (PointeeT->isSizelessType() && Kind != 1) {
1785ffd83dbSDimitry Andric     Diag(Range.getBegin(), diag::err_sizeless_in_exception_spec)
1795ffd83dbSDimitry Andric         << (Kind == 2 ? 1 : 0) << PointeeT << Range;
1805ffd83dbSDimitry Andric     return true;
1815ffd83dbSDimitry Andric   }
1825ffd83dbSDimitry Andric 
1830b57cec5SDimitry Andric   return false;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric bool Sema::CheckDistantExceptionSpec(QualType T) {
1870b57cec5SDimitry Andric   // C++17 removes this rule in favor of putting exception specifications into
1880b57cec5SDimitry Andric   // the type system.
1890b57cec5SDimitry Andric   if (getLangOpts().CPlusPlus17)
1900b57cec5SDimitry Andric     return false;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   if (const PointerType *PT = T->getAs<PointerType>())
1930b57cec5SDimitry Andric     T = PT->getPointeeType();
1940b57cec5SDimitry Andric   else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
1950b57cec5SDimitry Andric     T = PT->getPointeeType();
1960b57cec5SDimitry Andric   else
1970b57cec5SDimitry Andric     return false;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
2000b57cec5SDimitry Andric   if (!FnT)
2010b57cec5SDimitry Andric     return false;
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   return FnT->hasExceptionSpec();
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric const FunctionProtoType *
2070b57cec5SDimitry Andric Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
2080b57cec5SDimitry Andric   if (FPT->getExceptionSpecType() == EST_Unparsed) {
2090b57cec5SDimitry Andric     Diag(Loc, diag::err_exception_spec_not_parsed);
2100b57cec5SDimitry Andric     return nullptr;
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
2140b57cec5SDimitry Andric     return FPT;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
2170b57cec5SDimitry Andric   const FunctionProtoType *SourceFPT =
2180b57cec5SDimitry Andric       SourceDecl->getType()->castAs<FunctionProtoType>();
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   // If the exception specification has already been resolved, just return it.
2210b57cec5SDimitry Andric   if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType()))
2220b57cec5SDimitry Andric     return SourceFPT;
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   // Compute or instantiate the exception specification now.
2250b57cec5SDimitry Andric   if (SourceFPT->getExceptionSpecType() == EST_Unevaluated)
226480093f4SDimitry Andric     EvaluateImplicitExceptionSpec(Loc, SourceDecl);
2270b57cec5SDimitry Andric   else
2280b57cec5SDimitry Andric     InstantiateExceptionSpec(Loc, SourceDecl);
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   const FunctionProtoType *Proto =
2310b57cec5SDimitry Andric     SourceDecl->getType()->castAs<FunctionProtoType>();
2320b57cec5SDimitry Andric   if (Proto->getExceptionSpecType() == clang::EST_Unparsed) {
2330b57cec5SDimitry Andric     Diag(Loc, diag::err_exception_spec_not_parsed);
2340b57cec5SDimitry Andric     Proto = nullptr;
2350b57cec5SDimitry Andric   }
2360b57cec5SDimitry Andric   return Proto;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric void
2400b57cec5SDimitry Andric Sema::UpdateExceptionSpec(FunctionDecl *FD,
2410b57cec5SDimitry Andric                           const FunctionProtoType::ExceptionSpecInfo &ESI) {
2420b57cec5SDimitry Andric   // If we've fully resolved the exception specification, notify listeners.
2430b57cec5SDimitry Andric   if (!isUnresolvedExceptionSpec(ESI.Type))
2440b57cec5SDimitry Andric     if (auto *Listener = getASTMutationListener())
2450b57cec5SDimitry Andric       Listener->ResolvedExceptionSpec(FD);
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   for (FunctionDecl *Redecl : FD->redecls())
2480b57cec5SDimitry Andric     Context.adjustExceptionSpec(Redecl, ESI);
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) {
252*0fca6ea1SDimitry Andric   ExceptionSpecificationType EST =
253*0fca6ea1SDimitry Andric       FD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType();
254*0fca6ea1SDimitry Andric   if (EST == EST_Unparsed)
255*0fca6ea1SDimitry Andric     return true;
256*0fca6ea1SDimitry Andric   else if (EST != EST_Unevaluated)
2570b57cec5SDimitry Andric     return false;
258*0fca6ea1SDimitry Andric   const DeclContext *DC = FD->getLexicalDeclContext();
259*0fca6ea1SDimitry Andric   return DC->isRecord() && cast<RecordDecl>(DC)->isBeingDefined();
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric static bool CheckEquivalentExceptionSpecImpl(
2630b57cec5SDimitry Andric     Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
2640b57cec5SDimitry Andric     const FunctionProtoType *Old, SourceLocation OldLoc,
2650b57cec5SDimitry Andric     const FunctionProtoType *New, SourceLocation NewLoc,
2660b57cec5SDimitry Andric     bool *MissingExceptionSpecification = nullptr,
2670b57cec5SDimitry Andric     bool *MissingEmptyExceptionSpecification = nullptr,
2680b57cec5SDimitry Andric     bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric /// Determine whether a function has an implicitly-generated exception
2710b57cec5SDimitry Andric /// specification.
2720b57cec5SDimitry Andric static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
2730b57cec5SDimitry Andric   if (!isa<CXXDestructorDecl>(Decl) &&
2740b57cec5SDimitry Andric       Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete &&
2750b57cec5SDimitry Andric       Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
2760b57cec5SDimitry Andric     return false;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   // For a function that the user didn't declare:
2790b57cec5SDimitry Andric   //  - if this is a destructor, its exception specification is implicit.
2800b57cec5SDimitry Andric   //  - if this is 'operator delete' or 'operator delete[]', the exception
2810b57cec5SDimitry Andric   //    specification is as-if an explicit exception specification was given
2820b57cec5SDimitry Andric   //    (per [basic.stc.dynamic]p2).
2830b57cec5SDimitry Andric   if (!Decl->getTypeSourceInfo())
2840b57cec5SDimitry Andric     return isa<CXXDestructorDecl>(Decl);
2850b57cec5SDimitry Andric 
286a7dea167SDimitry Andric   auto *Ty = Decl->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
2870b57cec5SDimitry Andric   return !Ty->hasExceptionSpec();
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
2910b57cec5SDimitry Andric   // Just completely ignore this under -fno-exceptions prior to C++17.
2920b57cec5SDimitry Andric   // In C++17 onwards, the exception specification is part of the type and
2930b57cec5SDimitry Andric   // we will diagnose mismatches anyway, so it's better to check for them here.
2940b57cec5SDimitry Andric   if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus17)
2950b57cec5SDimitry Andric     return false;
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
2980b57cec5SDimitry Andric   bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
2990b57cec5SDimitry Andric   bool MissingExceptionSpecification = false;
3000b57cec5SDimitry Andric   bool MissingEmptyExceptionSpecification = false;
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   unsigned DiagID = diag::err_mismatched_exception_spec;
3030b57cec5SDimitry Andric   bool ReturnValueOnError = true;
304a7dea167SDimitry Andric   if (getLangOpts().MSVCCompat) {
3050b57cec5SDimitry Andric     DiagID = diag::ext_mismatched_exception_spec;
3060b57cec5SDimitry Andric     ReturnValueOnError = false;
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   // If we're befriending a member function of a class that's currently being
3100b57cec5SDimitry Andric   // defined, we might not be able to work out its exception specification yet.
3110b57cec5SDimitry Andric   // If not, defer the check until later.
3120b57cec5SDimitry Andric   if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) {
3130b57cec5SDimitry Andric     DelayedEquivalentExceptionSpecChecks.push_back({New, Old});
3140b57cec5SDimitry Andric     return false;
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   // Check the types as written: they must match before any exception
3180b57cec5SDimitry Andric   // specification adjustment is applied.
3190b57cec5SDimitry Andric   if (!CheckEquivalentExceptionSpecImpl(
3200b57cec5SDimitry Andric         *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
3210b57cec5SDimitry Andric         Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
3220b57cec5SDimitry Andric         New->getType()->getAs<FunctionProtoType>(), New->getLocation(),
3230b57cec5SDimitry Andric         &MissingExceptionSpecification, &MissingEmptyExceptionSpecification,
3240b57cec5SDimitry Andric         /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) {
3250b57cec5SDimitry Andric     // C++11 [except.spec]p4 [DR1492]:
3260b57cec5SDimitry Andric     //   If a declaration of a function has an implicit
3270b57cec5SDimitry Andric     //   exception-specification, other declarations of the function shall
3280b57cec5SDimitry Andric     //   not specify an exception-specification.
3290b57cec5SDimitry Andric     if (getLangOpts().CPlusPlus11 && getLangOpts().CXXExceptions &&
3300b57cec5SDimitry Andric         hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
3310b57cec5SDimitry Andric       Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
3320b57cec5SDimitry Andric         << hasImplicitExceptionSpec(Old);
3330b57cec5SDimitry Andric       if (Old->getLocation().isValid())
3340b57cec5SDimitry Andric         Diag(Old->getLocation(), diag::note_previous_declaration);
3350b57cec5SDimitry Andric     }
3360b57cec5SDimitry Andric     return false;
3370b57cec5SDimitry Andric   }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   // The failure was something other than an missing exception
3400b57cec5SDimitry Andric   // specification; return an error, except in MS mode where this is a warning.
3410b57cec5SDimitry Andric   if (!MissingExceptionSpecification)
3420b57cec5SDimitry Andric     return ReturnValueOnError;
3430b57cec5SDimitry Andric 
34481ad6265SDimitry Andric   const auto *NewProto = New->getType()->castAs<FunctionProtoType>();
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   // The new function declaration is only missing an empty exception
3470b57cec5SDimitry Andric   // specification "throw()". If the throw() specification came from a
3480b57cec5SDimitry Andric   // function in a system header that has C linkage, just add an empty
3490b57cec5SDimitry Andric   // exception specification to the "new" declaration. Note that C library
3500b57cec5SDimitry Andric   // implementations are permitted to add these nothrow exception
3510b57cec5SDimitry Andric   // specifications.
3520b57cec5SDimitry Andric   //
3530b57cec5SDimitry Andric   // Likewise if the old function is a builtin.
35481ad6265SDimitry Andric   if (MissingEmptyExceptionSpecification &&
3550b57cec5SDimitry Andric       (Old->getLocation().isInvalid() ||
3560b57cec5SDimitry Andric        Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
3570b57cec5SDimitry Andric        Old->getBuiltinID()) &&
3580b57cec5SDimitry Andric       Old->isExternC()) {
3590b57cec5SDimitry Andric     New->setType(Context.getFunctionType(
3600b57cec5SDimitry Andric         NewProto->getReturnType(), NewProto->getParamTypes(),
3610b57cec5SDimitry Andric         NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone)));
3620b57cec5SDimitry Andric     return false;
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric 
36581ad6265SDimitry Andric   const auto *OldProto = Old->getType()->castAs<FunctionProtoType>();
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
3680b57cec5SDimitry Andric   if (ESI.Type == EST_Dynamic) {
3690b57cec5SDimitry Andric     // FIXME: What if the exceptions are described in terms of the old
3700b57cec5SDimitry Andric     // prototype's parameters?
3710b57cec5SDimitry Andric     ESI.Exceptions = OldProto->exceptions();
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   if (ESI.Type == EST_NoexceptFalse)
3750b57cec5SDimitry Andric     ESI.Type = EST_None;
3760b57cec5SDimitry Andric   if (ESI.Type == EST_NoexceptTrue)
3770b57cec5SDimitry Andric     ESI.Type = EST_BasicNoexcept;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   // For dependent noexcept, we can't just take the expression from the old
3800b57cec5SDimitry Andric   // prototype. It likely contains references to the old prototype's parameters.
3810b57cec5SDimitry Andric   if (ESI.Type == EST_DependentNoexcept) {
3820b57cec5SDimitry Andric     New->setInvalidDecl();
3830b57cec5SDimitry Andric   } else {
3840b57cec5SDimitry Andric     // Update the type of the function with the appropriate exception
3850b57cec5SDimitry Andric     // specification.
3860b57cec5SDimitry Andric     New->setType(Context.getFunctionType(
3870b57cec5SDimitry Andric         NewProto->getReturnType(), NewProto->getParamTypes(),
3880b57cec5SDimitry Andric         NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
39104eeddc0SDimitry Andric   if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
39204eeddc0SDimitry Andric     DiagID = diag::ext_missing_exception_specification;
3930b57cec5SDimitry Andric     ReturnValueOnError = false;
3940b57cec5SDimitry Andric   } else if (New->isReplaceableGlobalAllocationFunction() &&
3950b57cec5SDimitry Andric              ESI.Type != EST_DependentNoexcept) {
3960b57cec5SDimitry Andric     // Allow missing exception specifications in redeclarations as an extension,
3970b57cec5SDimitry Andric     // when declaring a replaceable global allocation function.
3980b57cec5SDimitry Andric     DiagID = diag::ext_missing_exception_specification;
3990b57cec5SDimitry Andric     ReturnValueOnError = false;
4000b57cec5SDimitry Andric   } else if (ESI.Type == EST_NoThrow) {
40104eeddc0SDimitry Andric     // Don't emit any warning for missing 'nothrow' in MSVC.
40204eeddc0SDimitry Andric     if (getLangOpts().MSVCCompat) {
40304eeddc0SDimitry Andric       return false;
40404eeddc0SDimitry Andric     }
4050b57cec5SDimitry Andric     // Allow missing attribute 'nothrow' in redeclarations, since this is a very
4060b57cec5SDimitry Andric     // common omission.
4070b57cec5SDimitry Andric     DiagID = diag::ext_missing_exception_specification;
4080b57cec5SDimitry Andric     ReturnValueOnError = false;
4090b57cec5SDimitry Andric   } else {
4100b57cec5SDimitry Andric     DiagID = diag::err_missing_exception_specification;
4110b57cec5SDimitry Andric     ReturnValueOnError = true;
4120b57cec5SDimitry Andric   }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   // Warn about the lack of exception specification.
4150b57cec5SDimitry Andric   SmallString<128> ExceptionSpecString;
4160b57cec5SDimitry Andric   llvm::raw_svector_ostream OS(ExceptionSpecString);
4170b57cec5SDimitry Andric   switch (OldProto->getExceptionSpecType()) {
4180b57cec5SDimitry Andric   case EST_DynamicNone:
4190b57cec5SDimitry Andric     OS << "throw()";
4200b57cec5SDimitry Andric     break;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   case EST_Dynamic: {
4230b57cec5SDimitry Andric     OS << "throw(";
4240b57cec5SDimitry Andric     bool OnFirstException = true;
4250b57cec5SDimitry Andric     for (const auto &E : OldProto->exceptions()) {
4260b57cec5SDimitry Andric       if (OnFirstException)
4270b57cec5SDimitry Andric         OnFirstException = false;
4280b57cec5SDimitry Andric       else
4290b57cec5SDimitry Andric         OS << ", ";
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric       OS << E.getAsString(getPrintingPolicy());
4320b57cec5SDimitry Andric     }
4330b57cec5SDimitry Andric     OS << ")";
4340b57cec5SDimitry Andric     break;
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   case EST_BasicNoexcept:
4380b57cec5SDimitry Andric     OS << "noexcept";
4390b57cec5SDimitry Andric     break;
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   case EST_DependentNoexcept:
4420b57cec5SDimitry Andric   case EST_NoexceptFalse:
4430b57cec5SDimitry Andric   case EST_NoexceptTrue:
4440b57cec5SDimitry Andric     OS << "noexcept(";
4450b57cec5SDimitry Andric     assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr");
4460b57cec5SDimitry Andric     OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
4470b57cec5SDimitry Andric     OS << ")";
4480b57cec5SDimitry Andric     break;
4490b57cec5SDimitry Andric   case EST_NoThrow:
4500b57cec5SDimitry Andric     OS <<"__attribute__((nothrow))";
4510b57cec5SDimitry Andric     break;
4520b57cec5SDimitry Andric   case EST_None:
4530b57cec5SDimitry Andric   case EST_MSAny:
4540b57cec5SDimitry Andric   case EST_Unevaluated:
4550b57cec5SDimitry Andric   case EST_Uninstantiated:
4560b57cec5SDimitry Andric   case EST_Unparsed:
4570b57cec5SDimitry Andric     llvm_unreachable("This spec type is compatible with none.");
4580b57cec5SDimitry Andric   }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   SourceLocation FixItLoc;
4610b57cec5SDimitry Andric   if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
4620b57cec5SDimitry Andric     TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
4630b57cec5SDimitry Andric     // FIXME: Preserve enough information so that we can produce a correct fixit
4640b57cec5SDimitry Andric     // location when there is a trailing return type.
4650b57cec5SDimitry Andric     if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>())
4660b57cec5SDimitry Andric       if (!FTLoc.getTypePtr()->hasTrailingReturn())
4670b57cec5SDimitry Andric         FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   if (FixItLoc.isInvalid())
4710b57cec5SDimitry Andric     Diag(New->getLocation(), DiagID)
4720b57cec5SDimitry Andric       << New << OS.str();
4730b57cec5SDimitry Andric   else {
4740b57cec5SDimitry Andric     Diag(New->getLocation(), DiagID)
4750b57cec5SDimitry Andric       << New << OS.str()
4760b57cec5SDimitry Andric       << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
4770b57cec5SDimitry Andric   }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   if (Old->getLocation().isValid())
4800b57cec5SDimitry Andric     Diag(Old->getLocation(), diag::note_previous_declaration);
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   return ReturnValueOnError;
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric bool Sema::CheckEquivalentExceptionSpec(
4860b57cec5SDimitry Andric     const FunctionProtoType *Old, SourceLocation OldLoc,
4870b57cec5SDimitry Andric     const FunctionProtoType *New, SourceLocation NewLoc) {
4880b57cec5SDimitry Andric   if (!getLangOpts().CXXExceptions)
4890b57cec5SDimitry Andric     return false;
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   unsigned DiagID = diag::err_mismatched_exception_spec;
492a7dea167SDimitry Andric   if (getLangOpts().MSVCCompat)
4930b57cec5SDimitry Andric     DiagID = diag::ext_mismatched_exception_spec;
4940b57cec5SDimitry Andric   bool Result = CheckEquivalentExceptionSpecImpl(
4950b57cec5SDimitry Andric       *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
4960b57cec5SDimitry Andric       Old, OldLoc, New, NewLoc);
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   // In Microsoft mode, mismatching exception specifications just cause a warning.
499a7dea167SDimitry Andric   if (getLangOpts().MSVCCompat)
5000b57cec5SDimitry Andric     return false;
5010b57cec5SDimitry Andric   return Result;
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric /// CheckEquivalentExceptionSpec - Check if the two types have compatible
5050b57cec5SDimitry Andric /// exception specifications. See C++ [except.spec]p3.
5060b57cec5SDimitry Andric ///
5070b57cec5SDimitry Andric /// \return \c false if the exception specifications match, \c true if there is
5080b57cec5SDimitry Andric /// a problem. If \c true is returned, either a diagnostic has already been
5090b57cec5SDimitry Andric /// produced or \c *MissingExceptionSpecification is set to \c true.
5100b57cec5SDimitry Andric static bool CheckEquivalentExceptionSpecImpl(
5110b57cec5SDimitry Andric     Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
5120b57cec5SDimitry Andric     const FunctionProtoType *Old, SourceLocation OldLoc,
5130b57cec5SDimitry Andric     const FunctionProtoType *New, SourceLocation NewLoc,
5140b57cec5SDimitry Andric     bool *MissingExceptionSpecification,
5150b57cec5SDimitry Andric     bool *MissingEmptyExceptionSpecification,
5160b57cec5SDimitry Andric     bool AllowNoexceptAllMatchWithNoSpec, bool IsOperatorNew) {
5170b57cec5SDimitry Andric   if (MissingExceptionSpecification)
5180b57cec5SDimitry Andric     *MissingExceptionSpecification = false;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   if (MissingEmptyExceptionSpecification)
5210b57cec5SDimitry Andric     *MissingEmptyExceptionSpecification = false;
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   Old = S.ResolveExceptionSpec(NewLoc, Old);
5240b57cec5SDimitry Andric   if (!Old)
5250b57cec5SDimitry Andric     return false;
5260b57cec5SDimitry Andric   New = S.ResolveExceptionSpec(NewLoc, New);
5270b57cec5SDimitry Andric   if (!New)
5280b57cec5SDimitry Andric     return false;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   // C++0x [except.spec]p3: Two exception-specifications are compatible if:
5310b57cec5SDimitry Andric   //   - both are non-throwing, regardless of their form,
5320b57cec5SDimitry Andric   //   - both have the form noexcept(constant-expression) and the constant-
5330b57cec5SDimitry Andric   //     expressions are equivalent,
5340b57cec5SDimitry Andric   //   - both are dynamic-exception-specifications that have the same set of
5350b57cec5SDimitry Andric   //     adjusted types.
5360b57cec5SDimitry Andric   //
5370b57cec5SDimitry Andric   // C++0x [except.spec]p12: An exception-specification is non-throwing if it is
5380b57cec5SDimitry Andric   //   of the form throw(), noexcept, or noexcept(constant-expression) where the
5390b57cec5SDimitry Andric   //   constant-expression yields true.
5400b57cec5SDimitry Andric   //
5410b57cec5SDimitry Andric   // C++0x [except.spec]p4: If any declaration of a function has an exception-
5420b57cec5SDimitry Andric   //   specifier that is not a noexcept-specification allowing all exceptions,
5430b57cec5SDimitry Andric   //   all declarations [...] of that function shall have a compatible
5440b57cec5SDimitry Andric   //   exception-specification.
5450b57cec5SDimitry Andric   //
5460b57cec5SDimitry Andric   // That last point basically means that noexcept(false) matches no spec.
5470b57cec5SDimitry Andric   // It's considered when AllowNoexceptAllMatchWithNoSpec is true.
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
5500b57cec5SDimitry Andric   ExceptionSpecificationType NewEST = New->getExceptionSpecType();
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   assert(!isUnresolvedExceptionSpec(OldEST) &&
5530b57cec5SDimitry Andric          !isUnresolvedExceptionSpec(NewEST) &&
5540b57cec5SDimitry Andric          "Shouldn't see unknown exception specifications here");
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   CanThrowResult OldCanThrow = Old->canThrow();
5570b57cec5SDimitry Andric   CanThrowResult NewCanThrow = New->canThrow();
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   // Any non-throwing specifications are compatible.
5600b57cec5SDimitry Andric   if (OldCanThrow == CT_Cannot && NewCanThrow == CT_Cannot)
5610b57cec5SDimitry Andric     return false;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   // Any throws-anything specifications are usually compatible.
5640b57cec5SDimitry Andric   if (OldCanThrow == CT_Can && OldEST != EST_Dynamic &&
5650b57cec5SDimitry Andric       NewCanThrow == CT_Can && NewEST != EST_Dynamic) {
5660b57cec5SDimitry Andric     // The exception is that the absence of an exception specification only
5670b57cec5SDimitry Andric     // matches noexcept(false) for functions, as described above.
5680b57cec5SDimitry Andric     if (!AllowNoexceptAllMatchWithNoSpec &&
5690b57cec5SDimitry Andric         ((OldEST == EST_None && NewEST == EST_NoexceptFalse) ||
5700b57cec5SDimitry Andric          (OldEST == EST_NoexceptFalse && NewEST == EST_None))) {
5710b57cec5SDimitry Andric       // This is the disallowed case.
5720b57cec5SDimitry Andric     } else {
5730b57cec5SDimitry Andric       return false;
5740b57cec5SDimitry Andric     }
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   // C++14 [except.spec]p3:
5780b57cec5SDimitry Andric   //   Two exception-specifications are compatible if [...] both have the form
5790b57cec5SDimitry Andric   //   noexcept(constant-expression) and the constant-expressions are equivalent
5800b57cec5SDimitry Andric   if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) {
5810b57cec5SDimitry Andric     llvm::FoldingSetNodeID OldFSN, NewFSN;
5820b57cec5SDimitry Andric     Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true);
5830b57cec5SDimitry Andric     New->getNoexceptExpr()->Profile(NewFSN, S.Context, true);
5840b57cec5SDimitry Andric     if (OldFSN == NewFSN)
5850b57cec5SDimitry Andric       return false;
5860b57cec5SDimitry Andric   }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   // Dynamic exception specifications with the same set of adjusted types
5890b57cec5SDimitry Andric   // are compatible.
5900b57cec5SDimitry Andric   if (OldEST == EST_Dynamic && NewEST == EST_Dynamic) {
5910b57cec5SDimitry Andric     bool Success = true;
5920b57cec5SDimitry Andric     // Both have a dynamic exception spec. Collect the first set, then compare
5930b57cec5SDimitry Andric     // to the second.
5940b57cec5SDimitry Andric     llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
5950b57cec5SDimitry Andric     for (const auto &I : Old->exceptions())
5960b57cec5SDimitry Andric       OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric     for (const auto &I : New->exceptions()) {
5990b57cec5SDimitry Andric       CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
6000b57cec5SDimitry Andric       if (OldTypes.count(TypePtr))
6010b57cec5SDimitry Andric         NewTypes.insert(TypePtr);
6020b57cec5SDimitry Andric       else {
6030b57cec5SDimitry Andric         Success = false;
6040b57cec5SDimitry Andric         break;
6050b57cec5SDimitry Andric       }
6060b57cec5SDimitry Andric     }
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric     if (Success && OldTypes.size() == NewTypes.size())
6090b57cec5SDimitry Andric       return false;
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   // As a special compatibility feature, under C++0x we accept no spec and
6130b57cec5SDimitry Andric   // throw(std::bad_alloc) as equivalent for operator new and operator new[].
6140b57cec5SDimitry Andric   // This is because the implicit declaration changed, but old code would break.
6150b57cec5SDimitry Andric   if (S.getLangOpts().CPlusPlus11 && IsOperatorNew) {
6160b57cec5SDimitry Andric     const FunctionProtoType *WithExceptions = nullptr;
6170b57cec5SDimitry Andric     if (OldEST == EST_None && NewEST == EST_Dynamic)
6180b57cec5SDimitry Andric       WithExceptions = New;
6190b57cec5SDimitry Andric     else if (OldEST == EST_Dynamic && NewEST == EST_None)
6200b57cec5SDimitry Andric       WithExceptions = Old;
6210b57cec5SDimitry Andric     if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
6220b57cec5SDimitry Andric       // One has no spec, the other throw(something). If that something is
6230b57cec5SDimitry Andric       // std::bad_alloc, all conditions are met.
6240b57cec5SDimitry Andric       QualType Exception = *WithExceptions->exception_begin();
6250b57cec5SDimitry Andric       if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
6260b57cec5SDimitry Andric         IdentifierInfo* Name = ExRecord->getIdentifier();
6270b57cec5SDimitry Andric         if (Name && Name->getName() == "bad_alloc") {
6280b57cec5SDimitry Andric           // It's called bad_alloc, but is it in std?
6290b57cec5SDimitry Andric           if (ExRecord->isInStdNamespace()) {
6300b57cec5SDimitry Andric             return false;
6310b57cec5SDimitry Andric           }
6320b57cec5SDimitry Andric         }
6330b57cec5SDimitry Andric       }
6340b57cec5SDimitry Andric     }
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric   // If the caller wants to handle the case that the new function is
6380b57cec5SDimitry Andric   // incompatible due to a missing exception specification, let it.
6390b57cec5SDimitry Andric   if (MissingExceptionSpecification && OldEST != EST_None &&
6400b57cec5SDimitry Andric       NewEST == EST_None) {
6410b57cec5SDimitry Andric     // The old type has an exception specification of some sort, but
6420b57cec5SDimitry Andric     // the new type does not.
6430b57cec5SDimitry Andric     *MissingExceptionSpecification = true;
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric     if (MissingEmptyExceptionSpecification && OldCanThrow == CT_Cannot) {
6460b57cec5SDimitry Andric       // The old type has a throw() or noexcept(true) exception specification
6470b57cec5SDimitry Andric       // and the new type has no exception specification, and the caller asked
6480b57cec5SDimitry Andric       // to handle this itself.
6490b57cec5SDimitry Andric       *MissingEmptyExceptionSpecification = true;
6500b57cec5SDimitry Andric     }
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric     return true;
6530b57cec5SDimitry Andric   }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   S.Diag(NewLoc, DiagID);
6560b57cec5SDimitry Andric   if (NoteID.getDiagID() != 0 && OldLoc.isValid())
6570b57cec5SDimitry Andric     S.Diag(OldLoc, NoteID);
6580b57cec5SDimitry Andric   return true;
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
6620b57cec5SDimitry Andric                                         const PartialDiagnostic &NoteID,
6630b57cec5SDimitry Andric                                         const FunctionProtoType *Old,
6640b57cec5SDimitry Andric                                         SourceLocation OldLoc,
6650b57cec5SDimitry Andric                                         const FunctionProtoType *New,
6660b57cec5SDimitry Andric                                         SourceLocation NewLoc) {
6670b57cec5SDimitry Andric   if (!getLangOpts().CXXExceptions)
6680b57cec5SDimitry Andric     return false;
6690b57cec5SDimitry Andric   return CheckEquivalentExceptionSpecImpl(*this, DiagID, NoteID, Old, OldLoc,
6700b57cec5SDimitry Andric                                           New, NewLoc);
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
6740b57cec5SDimitry Andric   // [except.handle]p3:
6750b57cec5SDimitry Andric   //   A handler is a match for an exception object of type E if:
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   // HandlerType must be ExceptionType or derived from it, or pointer or
6780b57cec5SDimitry Andric   // reference to such types.
6790b57cec5SDimitry Andric   const ReferenceType *RefTy = HandlerType->getAs<ReferenceType>();
6800b57cec5SDimitry Andric   if (RefTy)
6810b57cec5SDimitry Andric     HandlerType = RefTy->getPointeeType();
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   //   -- the handler is of type cv T or cv T& and E and T are the same type
6840b57cec5SDimitry Andric   if (Context.hasSameUnqualifiedType(ExceptionType, HandlerType))
6850b57cec5SDimitry Andric     return true;
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   // FIXME: ObjC pointer types?
6880b57cec5SDimitry Andric   if (HandlerType->isPointerType() || HandlerType->isMemberPointerType()) {
6890b57cec5SDimitry Andric     if (RefTy && (!HandlerType.isConstQualified() ||
6900b57cec5SDimitry Andric                   HandlerType.isVolatileQualified()))
6910b57cec5SDimitry Andric       return false;
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric     // -- the handler is of type cv T or const T& where T is a pointer or
6940b57cec5SDimitry Andric     //    pointer to member type and E is std::nullptr_t
6950b57cec5SDimitry Andric     if (ExceptionType->isNullPtrType())
6960b57cec5SDimitry Andric       return true;
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     // -- the handler is of type cv T or const T& where T is a pointer or
6990b57cec5SDimitry Andric     //    pointer to member type and E is a pointer or pointer to member type
7000b57cec5SDimitry Andric     //    that can be converted to T by one or more of
7010b57cec5SDimitry Andric     //    -- a qualification conversion
7020b57cec5SDimitry Andric     //    -- a function pointer conversion
7030b57cec5SDimitry Andric     bool LifetimeConv;
7040b57cec5SDimitry Andric     QualType Result;
7050b57cec5SDimitry Andric     // FIXME: Should we treat the exception as catchable if a lifetime
7060b57cec5SDimitry Andric     // conversion is required?
7070b57cec5SDimitry Andric     if (IsQualificationConversion(ExceptionType, HandlerType, false,
7080b57cec5SDimitry Andric                                   LifetimeConv) ||
7090b57cec5SDimitry Andric         IsFunctionConversion(ExceptionType, HandlerType, Result))
7100b57cec5SDimitry Andric       return true;
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric     //    -- a standard pointer conversion [...]
7130b57cec5SDimitry Andric     if (!ExceptionType->isPointerType() || !HandlerType->isPointerType())
7140b57cec5SDimitry Andric       return false;
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric     // Handle the "qualification conversion" portion.
7170b57cec5SDimitry Andric     Qualifiers EQuals, HQuals;
7180b57cec5SDimitry Andric     ExceptionType = Context.getUnqualifiedArrayType(
7190b57cec5SDimitry Andric         ExceptionType->getPointeeType(), EQuals);
7200b57cec5SDimitry Andric     HandlerType = Context.getUnqualifiedArrayType(
7210b57cec5SDimitry Andric         HandlerType->getPointeeType(), HQuals);
7220b57cec5SDimitry Andric     if (!HQuals.compatiblyIncludes(EQuals))
7230b57cec5SDimitry Andric       return false;
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric     if (HandlerType->isVoidType() && ExceptionType->isObjectType())
7260b57cec5SDimitry Andric       return true;
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric     // The only remaining case is a derived-to-base conversion.
7290b57cec5SDimitry Andric   }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   //   -- the handler is of type cg T or cv T& and T is an unambiguous public
7320b57cec5SDimitry Andric   //      base class of E
7330b57cec5SDimitry Andric   if (!ExceptionType->isRecordType() || !HandlerType->isRecordType())
7340b57cec5SDimitry Andric     return false;
7350b57cec5SDimitry Andric   CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
7360b57cec5SDimitry Andric                      /*DetectVirtual=*/false);
7370b57cec5SDimitry Andric   if (!IsDerivedFrom(SourceLocation(), ExceptionType, HandlerType, Paths) ||
7380b57cec5SDimitry Andric       Paths.isAmbiguous(Context.getCanonicalType(HandlerType)))
7390b57cec5SDimitry Andric     return false;
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   // Do this check from a context without privileges.
7420b57cec5SDimitry Andric   switch (CheckBaseClassAccess(SourceLocation(), HandlerType, ExceptionType,
7430b57cec5SDimitry Andric                                Paths.front(),
7440b57cec5SDimitry Andric                                /*Diagnostic*/ 0,
7450b57cec5SDimitry Andric                                /*ForceCheck*/ true,
7460b57cec5SDimitry Andric                                /*ForceUnprivileged*/ true)) {
7470b57cec5SDimitry Andric   case AR_accessible: return true;
7480b57cec5SDimitry Andric   case AR_inaccessible: return false;
7490b57cec5SDimitry Andric   case AR_dependent:
7500b57cec5SDimitry Andric     llvm_unreachable("access check dependent for unprivileged context");
7510b57cec5SDimitry Andric   case AR_delayed:
7520b57cec5SDimitry Andric     llvm_unreachable("access check delayed in non-declaration");
7530b57cec5SDimitry Andric   }
7540b57cec5SDimitry Andric   llvm_unreachable("unexpected access check result");
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric 
7575f757f3fSDimitry Andric bool Sema::CheckExceptionSpecSubset(
7585f757f3fSDimitry Andric     const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID,
7595f757f3fSDimitry Andric     const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID,
7605f757f3fSDimitry Andric     const FunctionProtoType *Superset, bool SkipSupersetFirstParameter,
7615f757f3fSDimitry Andric     SourceLocation SuperLoc, const FunctionProtoType *Subset,
7625f757f3fSDimitry Andric     bool SkipSubsetFirstParameter, SourceLocation SubLoc) {
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   // Just auto-succeed under -fno-exceptions.
7650b57cec5SDimitry Andric   if (!getLangOpts().CXXExceptions)
7660b57cec5SDimitry Andric     return false;
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   // FIXME: As usual, we could be more specific in our error messages, but
7690b57cec5SDimitry Andric   // that better waits until we've got types with source locations.
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric   if (!SubLoc.isValid())
7720b57cec5SDimitry Andric     SubLoc = SuperLoc;
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric   // Resolve the exception specifications, if needed.
7750b57cec5SDimitry Andric   Superset = ResolveExceptionSpec(SuperLoc, Superset);
7760b57cec5SDimitry Andric   if (!Superset)
7770b57cec5SDimitry Andric     return false;
7780b57cec5SDimitry Andric   Subset = ResolveExceptionSpec(SubLoc, Subset);
7790b57cec5SDimitry Andric   if (!Subset)
7800b57cec5SDimitry Andric     return false;
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
7830b57cec5SDimitry Andric   ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
7840b57cec5SDimitry Andric   assert(!isUnresolvedExceptionSpec(SuperEST) &&
7850b57cec5SDimitry Andric          !isUnresolvedExceptionSpec(SubEST) &&
7860b57cec5SDimitry Andric          "Shouldn't see unknown exception specifications here");
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   // If there are dependent noexcept specs, assume everything is fine. Unlike
7890b57cec5SDimitry Andric   // with the equivalency check, this is safe in this case, because we don't
7900b57cec5SDimitry Andric   // want to merge declarations. Checks after instantiation will catch any
7910b57cec5SDimitry Andric   // omissions we make here.
7920b57cec5SDimitry Andric   if (SuperEST == EST_DependentNoexcept || SubEST == EST_DependentNoexcept)
7930b57cec5SDimitry Andric     return false;
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   CanThrowResult SuperCanThrow = Superset->canThrow();
7960b57cec5SDimitry Andric   CanThrowResult SubCanThrow = Subset->canThrow();
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric   // If the superset contains everything or the subset contains nothing, we're
7990b57cec5SDimitry Andric   // done.
8000b57cec5SDimitry Andric   if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) ||
8010b57cec5SDimitry Andric       SubCanThrow == CT_Cannot)
8025f757f3fSDimitry Andric     return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset,
8035f757f3fSDimitry Andric                                    SkipSupersetFirstParameter, SuperLoc, Subset,
8045f757f3fSDimitry Andric                                    SkipSubsetFirstParameter, SubLoc);
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   // Allow __declspec(nothrow) to be missing on redeclaration as an extension in
8070b57cec5SDimitry Andric   // some cases.
8080b57cec5SDimitry Andric   if (NoThrowDiagID.getDiagID() != 0 && SubCanThrow == CT_Can &&
8090b57cec5SDimitry Andric       SuperCanThrow == CT_Cannot && SuperEST == EST_NoThrow) {
8100b57cec5SDimitry Andric     Diag(SubLoc, NoThrowDiagID);
8110b57cec5SDimitry Andric     if (NoteID.getDiagID() != 0)
8120b57cec5SDimitry Andric       Diag(SuperLoc, NoteID);
8130b57cec5SDimitry Andric     return true;
8140b57cec5SDimitry Andric   }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric   // If the subset contains everything or the superset contains nothing, we've
8170b57cec5SDimitry Andric   // failed.
8180b57cec5SDimitry Andric   if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) ||
8190b57cec5SDimitry Andric       SuperCanThrow == CT_Cannot) {
8200b57cec5SDimitry Andric     Diag(SubLoc, DiagID);
8210b57cec5SDimitry Andric     if (NoteID.getDiagID() != 0)
8220b57cec5SDimitry Andric       Diag(SuperLoc, NoteID);
8230b57cec5SDimitry Andric     return true;
8240b57cec5SDimitry Andric   }
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic &&
8270b57cec5SDimitry Andric          "Exception spec subset: non-dynamic case slipped through.");
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric   // Neither contains everything or nothing. Do a proper comparison.
8300b57cec5SDimitry Andric   for (QualType SubI : Subset->exceptions()) {
8310b57cec5SDimitry Andric     if (const ReferenceType *RefTy = SubI->getAs<ReferenceType>())
8320b57cec5SDimitry Andric       SubI = RefTy->getPointeeType();
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric     // Make sure it's in the superset.
8350b57cec5SDimitry Andric     bool Contained = false;
8360b57cec5SDimitry Andric     for (QualType SuperI : Superset->exceptions()) {
8370b57cec5SDimitry Andric       // [except.spec]p5:
8380b57cec5SDimitry Andric       //   the target entity shall allow at least the exceptions allowed by the
8390b57cec5SDimitry Andric       //   source
8400b57cec5SDimitry Andric       //
8410b57cec5SDimitry Andric       // We interpret this as meaning that a handler for some target type would
8420b57cec5SDimitry Andric       // catch an exception of each source type.
8430b57cec5SDimitry Andric       if (handlerCanCatch(SuperI, SubI)) {
8440b57cec5SDimitry Andric         Contained = true;
8450b57cec5SDimitry Andric         break;
8460b57cec5SDimitry Andric       }
8470b57cec5SDimitry Andric     }
8480b57cec5SDimitry Andric     if (!Contained) {
8490b57cec5SDimitry Andric       Diag(SubLoc, DiagID);
8500b57cec5SDimitry Andric       if (NoteID.getDiagID() != 0)
8510b57cec5SDimitry Andric         Diag(SuperLoc, NoteID);
8520b57cec5SDimitry Andric       return true;
8530b57cec5SDimitry Andric     }
8540b57cec5SDimitry Andric   }
8550b57cec5SDimitry Andric   // We've run half the gauntlet.
8565f757f3fSDimitry Andric   return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset,
8575f757f3fSDimitry Andric                                  SkipSupersetFirstParameter, SuperLoc, Subset,
8585f757f3fSDimitry Andric                                  SkipSupersetFirstParameter, SubLoc);
8590b57cec5SDimitry Andric }
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric static bool
8620b57cec5SDimitry Andric CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID,
8630b57cec5SDimitry Andric                             const PartialDiagnostic &NoteID, QualType Target,
8640b57cec5SDimitry Andric                             SourceLocation TargetLoc, QualType Source,
8650b57cec5SDimitry Andric                             SourceLocation SourceLoc) {
8660b57cec5SDimitry Andric   const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
8670b57cec5SDimitry Andric   if (!TFunc)
8680b57cec5SDimitry Andric     return false;
8690b57cec5SDimitry Andric   const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
8700b57cec5SDimitry Andric   if (!SFunc)
8710b57cec5SDimitry Andric     return false;
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
8740b57cec5SDimitry Andric                                         SFunc, SourceLoc);
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
8775f757f3fSDimitry Andric bool Sema::CheckParamExceptionSpec(
8785f757f3fSDimitry Andric     const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
8795f757f3fSDimitry Andric     const FunctionProtoType *Target, bool SkipTargetFirstParameter,
8805f757f3fSDimitry Andric     SourceLocation TargetLoc, const FunctionProtoType *Source,
8815f757f3fSDimitry Andric     bool SkipSourceFirstParameter, SourceLocation SourceLoc) {
8820b57cec5SDimitry Andric   auto RetDiag = DiagID;
8830b57cec5SDimitry Andric   RetDiag << 0;
8840b57cec5SDimitry Andric   if (CheckSpecForTypesEquivalent(
8850b57cec5SDimitry Andric           *this, RetDiag, PDiag(),
8860b57cec5SDimitry Andric           Target->getReturnType(), TargetLoc, Source->getReturnType(),
8870b57cec5SDimitry Andric           SourceLoc))
8880b57cec5SDimitry Andric     return true;
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   // We shouldn't even be testing this unless the arguments are otherwise
8910b57cec5SDimitry Andric   // compatible.
8925f757f3fSDimitry Andric   assert((Target->getNumParams() - (unsigned)SkipTargetFirstParameter) ==
8935f757f3fSDimitry Andric              (Source->getNumParams() - (unsigned)SkipSourceFirstParameter) &&
8940b57cec5SDimitry Andric          "Functions have different argument counts.");
8950b57cec5SDimitry Andric   for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) {
8960b57cec5SDimitry Andric     auto ParamDiag = DiagID;
8970b57cec5SDimitry Andric     ParamDiag << 1;
8980b57cec5SDimitry Andric     if (CheckSpecForTypesEquivalent(
8990b57cec5SDimitry Andric             *this, ParamDiag, PDiag(),
9005f757f3fSDimitry Andric             Target->getParamType(i + (SkipTargetFirstParameter ? 1 : 0)),
9015f757f3fSDimitry Andric             TargetLoc, Source->getParamType(SkipSourceFirstParameter ? 1 : 0),
9020b57cec5SDimitry Andric             SourceLoc))
9030b57cec5SDimitry Andric       return true;
9040b57cec5SDimitry Andric   }
9050b57cec5SDimitry Andric   return false;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
9090b57cec5SDimitry Andric   // First we check for applicability.
9100b57cec5SDimitry Andric   // Target type must be a function, function pointer or function reference.
9110b57cec5SDimitry Andric   const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
9120b57cec5SDimitry Andric   if (!ToFunc || ToFunc->hasDependentExceptionSpec())
9130b57cec5SDimitry Andric     return false;
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   // SourceType must be a function or function pointer.
9160b57cec5SDimitry Andric   const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
9170b57cec5SDimitry Andric   if (!FromFunc || FromFunc->hasDependentExceptionSpec())
9180b57cec5SDimitry Andric     return false;
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   unsigned DiagID = diag::err_incompatible_exception_specs;
9210b57cec5SDimitry Andric   unsigned NestedDiagID = diag::err_deep_exception_specs_differ;
9220b57cec5SDimitry Andric   // This is not an error in C++17 onwards, unless the noexceptness doesn't
9230b57cec5SDimitry Andric   // match, but in that case we have a full-on type mismatch, not just a
9240b57cec5SDimitry Andric   // type sugar mismatch.
9250b57cec5SDimitry Andric   if (getLangOpts().CPlusPlus17) {
9260b57cec5SDimitry Andric     DiagID = diag::warn_incompatible_exception_specs;
9270b57cec5SDimitry Andric     NestedDiagID = diag::warn_deep_exception_specs_differ;
9280b57cec5SDimitry Andric   }
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   // Now we've got the correct types on both sides, check their compatibility.
9310b57cec5SDimitry Andric   // This means that the source of the conversion can only throw a subset of
9320b57cec5SDimitry Andric   // the exceptions of the target, and any exception specs on arguments or
9330b57cec5SDimitry Andric   // return types must be equivalent.
9340b57cec5SDimitry Andric   //
9350b57cec5SDimitry Andric   // FIXME: If there is a nested dependent exception specification, we should
9360b57cec5SDimitry Andric   // not be checking it here. This is fine:
9370b57cec5SDimitry Andric   //   template<typename T> void f() {
9380b57cec5SDimitry Andric   //     void (*p)(void (*) throw(T));
9390b57cec5SDimitry Andric   //     void (*q)(void (*) throw(int)) = p;
9400b57cec5SDimitry Andric   //   }
9410b57cec5SDimitry Andric   // ... because it might be instantiated with T=int.
9425f757f3fSDimitry Andric   return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(),
9435f757f3fSDimitry Andric                                   PDiag(), ToFunc, 0,
9445f757f3fSDimitry Andric                                   From->getSourceRange().getBegin(), FromFunc,
9455f757f3fSDimitry Andric                                   0, SourceLocation()) &&
9460b57cec5SDimitry Andric          !getLangOpts().CPlusPlus17;
9470b57cec5SDimitry Andric }
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
9500b57cec5SDimitry Andric                                                 const CXXMethodDecl *Old) {
9510b57cec5SDimitry Andric   // If the new exception specification hasn't been parsed yet, skip the check.
9520b57cec5SDimitry Andric   // We'll get called again once it's been parsed.
9530b57cec5SDimitry Andric   if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
9540b57cec5SDimitry Andric       EST_Unparsed)
9550b57cec5SDimitry Andric     return false;
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   // Don't check uninstantiated template destructors at all. We can only
9580b57cec5SDimitry Andric   // synthesize correct specs after the template is instantiated.
9590b57cec5SDimitry Andric   if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType())
9600b57cec5SDimitry Andric     return false;
9610b57cec5SDimitry Andric 
9620b57cec5SDimitry Andric   // If the old exception specification hasn't been parsed yet, or the new
9630b57cec5SDimitry Andric   // exception specification can't be computed yet, remember that we need to
9640b57cec5SDimitry Andric   // perform this check when we get to the end of the outermost
9650b57cec5SDimitry Andric   // lexically-surrounding class.
9660b57cec5SDimitry Andric   if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) {
9670b57cec5SDimitry Andric     DelayedOverridingExceptionSpecChecks.push_back({New, Old});
9680b57cec5SDimitry Andric     return false;
9690b57cec5SDimitry Andric   }
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   unsigned DiagID = diag::err_override_exception_spec;
972a7dea167SDimitry Andric   if (getLangOpts().MSVCCompat)
9730b57cec5SDimitry Andric     DiagID = diag::ext_override_exception_spec;
9745f757f3fSDimitry Andric   return CheckExceptionSpecSubset(
9755f757f3fSDimitry Andric       PDiag(DiagID), PDiag(diag::err_deep_exception_specs_differ),
9760b57cec5SDimitry Andric       PDiag(diag::note_overridden_virtual_function),
9770b57cec5SDimitry Andric       PDiag(diag::ext_override_exception_spec),
978a7dea167SDimitry Andric       Old->getType()->castAs<FunctionProtoType>(),
9795f757f3fSDimitry Andric       Old->hasCXXExplicitFunctionObjectParameter(), Old->getLocation(),
980a7dea167SDimitry Andric       New->getType()->castAs<FunctionProtoType>(),
9815f757f3fSDimitry Andric       New->hasCXXExplicitFunctionObjectParameter(), New->getLocation());
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
984480093f4SDimitry Andric static CanThrowResult canSubStmtsThrow(Sema &Self, const Stmt *S) {
9850b57cec5SDimitry Andric   CanThrowResult R = CT_Cannot;
986480093f4SDimitry Andric   for (const Stmt *SubStmt : S->children()) {
987480093f4SDimitry Andric     if (!SubStmt)
988480093f4SDimitry Andric       continue;
989480093f4SDimitry Andric     R = mergeCanThrow(R, Self.canThrow(SubStmt));
9900b57cec5SDimitry Andric     if (R == CT_Can)
9910b57cec5SDimitry Andric       break;
9920b57cec5SDimitry Andric   }
9930b57cec5SDimitry Andric   return R;
9940b57cec5SDimitry Andric }
9950b57cec5SDimitry Andric 
9965ffd83dbSDimitry Andric CanThrowResult Sema::canCalleeThrow(Sema &S, const Expr *E, const Decl *D,
9975ffd83dbSDimitry Andric                                     SourceLocation Loc) {
9980b57cec5SDimitry Andric   // As an extension, we assume that __attribute__((nothrow)) functions don't
9990b57cec5SDimitry Andric   // throw.
1000*0fca6ea1SDimitry Andric   if (isa_and_nonnull<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
10010b57cec5SDimitry Andric     return CT_Cannot;
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   QualType T;
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   // In C++1z, just look at the function type of the callee.
1006*0fca6ea1SDimitry Andric   if (S.getLangOpts().CPlusPlus17 && isa_and_nonnull<CallExpr>(E)) {
10070b57cec5SDimitry Andric     E = cast<CallExpr>(E)->getCallee();
10080b57cec5SDimitry Andric     T = E->getType();
10090b57cec5SDimitry Andric     if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
10100b57cec5SDimitry Andric       // Sadly we don't preserve the actual type as part of the "bound member"
10110b57cec5SDimitry Andric       // placeholder, so we need to reconstruct it.
10120b57cec5SDimitry Andric       E = E->IgnoreParenImpCasts();
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric       // Could be a call to a pointer-to-member or a plain member access.
10150b57cec5SDimitry Andric       if (auto *Op = dyn_cast<BinaryOperator>(E)) {
10160b57cec5SDimitry Andric         assert(Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI);
10170b57cec5SDimitry Andric         T = Op->getRHS()->getType()
10180b57cec5SDimitry Andric               ->castAs<MemberPointerType>()->getPointeeType();
10190b57cec5SDimitry Andric       } else {
10200b57cec5SDimitry Andric         T = cast<MemberExpr>(E)->getMemberDecl()->getType();
10210b57cec5SDimitry Andric       }
10220b57cec5SDimitry Andric     }
10230b57cec5SDimitry Andric   } else if (const ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D))
10240b57cec5SDimitry Andric     T = VD->getType();
10250b57cec5SDimitry Andric   else
10260b57cec5SDimitry Andric     // If we have no clue what we're calling, assume the worst.
10270b57cec5SDimitry Andric     return CT_Can;
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   const FunctionProtoType *FT;
10300b57cec5SDimitry Andric   if ((FT = T->getAs<FunctionProtoType>())) {
10310b57cec5SDimitry Andric   } else if (const PointerType *PT = T->getAs<PointerType>())
10320b57cec5SDimitry Andric     FT = PT->getPointeeType()->getAs<FunctionProtoType>();
10330b57cec5SDimitry Andric   else if (const ReferenceType *RT = T->getAs<ReferenceType>())
10340b57cec5SDimitry Andric     FT = RT->getPointeeType()->getAs<FunctionProtoType>();
10350b57cec5SDimitry Andric   else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
10360b57cec5SDimitry Andric     FT = MT->getPointeeType()->getAs<FunctionProtoType>();
10370b57cec5SDimitry Andric   else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
10380b57cec5SDimitry Andric     FT = BT->getPointeeType()->getAs<FunctionProtoType>();
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   if (!FT)
10410b57cec5SDimitry Andric     return CT_Can;
10420b57cec5SDimitry Andric 
10435ffd83dbSDimitry Andric   if (Loc.isValid() || (Loc.isInvalid() && E))
1044480093f4SDimitry Andric     FT = S.ResolveExceptionSpec(Loc.isInvalid() ? E->getBeginLoc() : Loc, FT);
10450b57cec5SDimitry Andric   if (!FT)
10460b57cec5SDimitry Andric     return CT_Can;
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric   return FT->canThrow();
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric 
1051480093f4SDimitry Andric static CanThrowResult canVarDeclThrow(Sema &Self, const VarDecl *VD) {
1052480093f4SDimitry Andric   CanThrowResult CT = CT_Cannot;
1053480093f4SDimitry Andric 
1054480093f4SDimitry Andric   // Initialization might throw.
1055480093f4SDimitry Andric   if (!VD->isUsableInConstantExpressions(Self.Context))
1056480093f4SDimitry Andric     if (const Expr *Init = VD->getInit())
1057480093f4SDimitry Andric       CT = mergeCanThrow(CT, Self.canThrow(Init));
1058480093f4SDimitry Andric 
1059480093f4SDimitry Andric   // Destructor might throw.
1060480093f4SDimitry Andric   if (VD->needsDestruction(Self.Context) == QualType::DK_cxx_destructor) {
1061480093f4SDimitry Andric     if (auto *RD =
1062480093f4SDimitry Andric             VD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
1063480093f4SDimitry Andric       if (auto *Dtor = RD->getDestructor()) {
1064480093f4SDimitry Andric         CT = mergeCanThrow(
10655ffd83dbSDimitry Andric             CT, Sema::canCalleeThrow(Self, nullptr, Dtor, VD->getLocation()));
1066480093f4SDimitry Andric       }
1067480093f4SDimitry Andric     }
1068480093f4SDimitry Andric   }
1069480093f4SDimitry Andric 
1070480093f4SDimitry Andric   // If this is a decomposition declaration, bindings might throw.
1071480093f4SDimitry Andric   if (auto *DD = dyn_cast<DecompositionDecl>(VD))
1072480093f4SDimitry Andric     for (auto *B : DD->bindings())
1073480093f4SDimitry Andric       if (auto *HD = B->getHoldingVar())
1074480093f4SDimitry Andric         CT = mergeCanThrow(CT, canVarDeclThrow(Self, HD));
1075480093f4SDimitry Andric 
1076480093f4SDimitry Andric   return CT;
1077480093f4SDimitry Andric }
1078480093f4SDimitry Andric 
10790b57cec5SDimitry Andric static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
10800b57cec5SDimitry Andric   if (DC->isTypeDependent())
10810b57cec5SDimitry Andric     return CT_Dependent;
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   if (!DC->getTypeAsWritten()->isReferenceType())
10840b57cec5SDimitry Andric     return CT_Cannot;
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   if (DC->getSubExpr()->isTypeDependent())
10870b57cec5SDimitry Andric     return CT_Dependent;
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric   return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
1093*0fca6ea1SDimitry Andric   // A typeid of a type is a constant and does not throw.
10940b57cec5SDimitry Andric   if (DC->isTypeOperand())
10950b57cec5SDimitry Andric     return CT_Cannot;
10960b57cec5SDimitry Andric 
1097*0fca6ea1SDimitry Andric   if (DC->isValueDependent())
10980b57cec5SDimitry Andric     return CT_Dependent;
10990b57cec5SDimitry Andric 
1100*0fca6ea1SDimitry Andric   // If this operand is not evaluated it cannot possibly throw.
1101*0fca6ea1SDimitry Andric   if (!DC->isPotentiallyEvaluated())
11020b57cec5SDimitry Andric     return CT_Cannot;
11030b57cec5SDimitry Andric 
1104*0fca6ea1SDimitry Andric   // Can throw std::bad_typeid if a nullptr is dereferenced.
1105*0fca6ea1SDimitry Andric   if (DC->hasNullCheck())
11060b57cec5SDimitry Andric     return CT_Can;
1107*0fca6ea1SDimitry Andric 
1108*0fca6ea1SDimitry Andric   return S.canThrow(DC->getExprOperand());
11090b57cec5SDimitry Andric }
11100b57cec5SDimitry Andric 
1111480093f4SDimitry Andric CanThrowResult Sema::canThrow(const Stmt *S) {
11120b57cec5SDimitry Andric   // C++ [expr.unary.noexcept]p3:
11130b57cec5SDimitry Andric   //   [Can throw] if in a potentially-evaluated context the expression would
11140b57cec5SDimitry Andric   //   contain:
1115480093f4SDimitry Andric   switch (S->getStmtClass()) {
11160b57cec5SDimitry Andric   case Expr::ConstantExprClass:
1117480093f4SDimitry Andric     return canThrow(cast<ConstantExpr>(S)->getSubExpr());
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   case Expr::CXXThrowExprClass:
11200b57cec5SDimitry Andric     //   - a potentially evaluated throw-expression
11210b57cec5SDimitry Andric     return CT_Can;
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   case Expr::CXXDynamicCastExprClass: {
11240b57cec5SDimitry Andric     //   - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
11250b57cec5SDimitry Andric     //     where T is a reference type, that requires a run-time check
1126480093f4SDimitry Andric     auto *CE = cast<CXXDynamicCastExpr>(S);
1127480093f4SDimitry Andric     // FIXME: Properly determine whether a variably-modified type can throw.
1128480093f4SDimitry Andric     if (CE->getType()->isVariablyModifiedType())
1129480093f4SDimitry Andric       return CT_Can;
1130480093f4SDimitry Andric     CanThrowResult CT = canDynamicCastThrow(CE);
11310b57cec5SDimitry Andric     if (CT == CT_Can)
11320b57cec5SDimitry Andric       return CT;
1133480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
11340b57cec5SDimitry Andric   }
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   case Expr::CXXTypeidExprClass:
1137*0fca6ea1SDimitry Andric     //   - a potentially evaluated typeid expression applied to a (possibly
1138*0fca6ea1SDimitry Andric     //     parenthesized) built-in unary * operator applied to a pointer to a
1139*0fca6ea1SDimitry Andric     //     polymorphic class type
1140480093f4SDimitry Andric     return canTypeidThrow(*this, cast<CXXTypeidExpr>(S));
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric     //   - a potentially evaluated call to a function, member function, function
11430b57cec5SDimitry Andric     //     pointer, or member function pointer that does not have a non-throwing
11440b57cec5SDimitry Andric     //     exception-specification
11450b57cec5SDimitry Andric   case Expr::CallExprClass:
11460b57cec5SDimitry Andric   case Expr::CXXMemberCallExprClass:
11470b57cec5SDimitry Andric   case Expr::CXXOperatorCallExprClass:
11480b57cec5SDimitry Andric   case Expr::UserDefinedLiteralClass: {
1149480093f4SDimitry Andric     const CallExpr *CE = cast<CallExpr>(S);
11500b57cec5SDimitry Andric     CanThrowResult CT;
1151480093f4SDimitry Andric     if (CE->isTypeDependent())
11520b57cec5SDimitry Andric       CT = CT_Dependent;
11530b57cec5SDimitry Andric     else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
11540b57cec5SDimitry Andric       CT = CT_Cannot;
11550b57cec5SDimitry Andric     else
1156480093f4SDimitry Andric       CT = canCalleeThrow(*this, CE, CE->getCalleeDecl());
11570b57cec5SDimitry Andric     if (CT == CT_Can)
11580b57cec5SDimitry Andric       return CT;
1159480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
11600b57cec5SDimitry Andric   }
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric   case Expr::CXXConstructExprClass:
11630b57cec5SDimitry Andric   case Expr::CXXTemporaryObjectExprClass: {
1164480093f4SDimitry Andric     auto *CE = cast<CXXConstructExpr>(S);
1165480093f4SDimitry Andric     // FIXME: Properly determine whether a variably-modified type can throw.
1166480093f4SDimitry Andric     if (CE->getType()->isVariablyModifiedType())
1167480093f4SDimitry Andric       return CT_Can;
1168480093f4SDimitry Andric     CanThrowResult CT = canCalleeThrow(*this, CE, CE->getConstructor());
11690b57cec5SDimitry Andric     if (CT == CT_Can)
11700b57cec5SDimitry Andric       return CT;
1171480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
11720b57cec5SDimitry Andric   }
11730b57cec5SDimitry Andric 
1174480093f4SDimitry Andric   case Expr::CXXInheritedCtorInitExprClass: {
1175480093f4SDimitry Andric     auto *ICIE = cast<CXXInheritedCtorInitExpr>(S);
1176480093f4SDimitry Andric     return canCalleeThrow(*this, ICIE, ICIE->getConstructor());
1177480093f4SDimitry Andric   }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric   case Expr::LambdaExprClass: {
1180480093f4SDimitry Andric     const LambdaExpr *Lambda = cast<LambdaExpr>(S);
11810b57cec5SDimitry Andric     CanThrowResult CT = CT_Cannot;
11820b57cec5SDimitry Andric     for (LambdaExpr::const_capture_init_iterator
11830b57cec5SDimitry Andric              Cap = Lambda->capture_init_begin(),
11840b57cec5SDimitry Andric              CapEnd = Lambda->capture_init_end();
11850b57cec5SDimitry Andric          Cap != CapEnd; ++Cap)
11860b57cec5SDimitry Andric       CT = mergeCanThrow(CT, canThrow(*Cap));
11870b57cec5SDimitry Andric     return CT;
11880b57cec5SDimitry Andric   }
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric   case Expr::CXXNewExprClass: {
1191480093f4SDimitry Andric     auto *NE = cast<CXXNewExpr>(S);
11920b57cec5SDimitry Andric     CanThrowResult CT;
1193480093f4SDimitry Andric     if (NE->isTypeDependent())
11940b57cec5SDimitry Andric       CT = CT_Dependent;
11950b57cec5SDimitry Andric     else
1196480093f4SDimitry Andric       CT = canCalleeThrow(*this, NE, NE->getOperatorNew());
11970b57cec5SDimitry Andric     if (CT == CT_Can)
11980b57cec5SDimitry Andric       return CT;
1199480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, NE));
12000b57cec5SDimitry Andric   }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   case Expr::CXXDeleteExprClass: {
1203480093f4SDimitry Andric     auto *DE = cast<CXXDeleteExpr>(S);
12040b57cec5SDimitry Andric     CanThrowResult CT;
1205480093f4SDimitry Andric     QualType DTy = DE->getDestroyedType();
12060b57cec5SDimitry Andric     if (DTy.isNull() || DTy->isDependentType()) {
12070b57cec5SDimitry Andric       CT = CT_Dependent;
12080b57cec5SDimitry Andric     } else {
1209480093f4SDimitry Andric       CT = canCalleeThrow(*this, DE, DE->getOperatorDelete());
12100b57cec5SDimitry Andric       if (const RecordType *RT = DTy->getAs<RecordType>()) {
12110b57cec5SDimitry Andric         const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
12120b57cec5SDimitry Andric         const CXXDestructorDecl *DD = RD->getDestructor();
12130b57cec5SDimitry Andric         if (DD)
1214480093f4SDimitry Andric           CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD));
12150b57cec5SDimitry Andric       }
12160b57cec5SDimitry Andric       if (CT == CT_Can)
12170b57cec5SDimitry Andric         return CT;
12180b57cec5SDimitry Andric     }
1219480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, DE));
12200b57cec5SDimitry Andric   }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   case Expr::CXXBindTemporaryExprClass: {
1223480093f4SDimitry Andric     auto *BTE = cast<CXXBindTemporaryExpr>(S);
12240b57cec5SDimitry Andric     // The bound temporary has to be destroyed again, which might throw.
1225480093f4SDimitry Andric     CanThrowResult CT =
1226480093f4SDimitry Andric         canCalleeThrow(*this, BTE, BTE->getTemporary()->getDestructor());
12270b57cec5SDimitry Andric     if (CT == CT_Can)
12280b57cec5SDimitry Andric       return CT;
1229480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, BTE));
1230480093f4SDimitry Andric   }
1231480093f4SDimitry Andric 
1232480093f4SDimitry Andric   case Expr::PseudoObjectExprClass: {
1233480093f4SDimitry Andric     auto *POE = cast<PseudoObjectExpr>(S);
1234480093f4SDimitry Andric     CanThrowResult CT = CT_Cannot;
1235480093f4SDimitry Andric     for (const Expr *E : POE->semantics()) {
1236480093f4SDimitry Andric       CT = mergeCanThrow(CT, canThrow(E));
1237480093f4SDimitry Andric       if (CT == CT_Can)
1238480093f4SDimitry Andric         break;
1239480093f4SDimitry Andric     }
1240480093f4SDimitry Andric     return CT;
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric     // ObjC message sends are like function calls, but never have exception
12440b57cec5SDimitry Andric     // specs.
12450b57cec5SDimitry Andric   case Expr::ObjCMessageExprClass:
12460b57cec5SDimitry Andric   case Expr::ObjCPropertyRefExprClass:
12470b57cec5SDimitry Andric   case Expr::ObjCSubscriptRefExprClass:
12480b57cec5SDimitry Andric     return CT_Can;
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric     // All the ObjC literals that are implemented as calls are
12510b57cec5SDimitry Andric     // potentially throwing unless we decide to close off that
12520b57cec5SDimitry Andric     // possibility.
12530b57cec5SDimitry Andric   case Expr::ObjCArrayLiteralClass:
12540b57cec5SDimitry Andric   case Expr::ObjCDictionaryLiteralClass:
12550b57cec5SDimitry Andric   case Expr::ObjCBoxedExprClass:
12560b57cec5SDimitry Andric     return CT_Can;
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric     // Many other things have subexpressions, so we have to test those.
12590b57cec5SDimitry Andric     // Some are simple:
12600b57cec5SDimitry Andric   case Expr::CoawaitExprClass:
12610b57cec5SDimitry Andric   case Expr::ConditionalOperatorClass:
12620b57cec5SDimitry Andric   case Expr::CoyieldExprClass:
1263a7dea167SDimitry Andric   case Expr::CXXRewrittenBinaryOperatorClass:
12640b57cec5SDimitry Andric   case Expr::CXXStdInitializerListExprClass:
12650b57cec5SDimitry Andric   case Expr::DesignatedInitExprClass:
12660b57cec5SDimitry Andric   case Expr::DesignatedInitUpdateExprClass:
12670b57cec5SDimitry Andric   case Expr::ExprWithCleanupsClass:
12680b57cec5SDimitry Andric   case Expr::ExtVectorElementExprClass:
12690b57cec5SDimitry Andric   case Expr::InitListExprClass:
12700b57cec5SDimitry Andric   case Expr::ArrayInitLoopExprClass:
12710b57cec5SDimitry Andric   case Expr::MemberExprClass:
12720b57cec5SDimitry Andric   case Expr::ObjCIsaExprClass:
12730b57cec5SDimitry Andric   case Expr::ObjCIvarRefExprClass:
12740b57cec5SDimitry Andric   case Expr::ParenExprClass:
12750b57cec5SDimitry Andric   case Expr::ParenListExprClass:
12760b57cec5SDimitry Andric   case Expr::ShuffleVectorExprClass:
1277480093f4SDimitry Andric   case Expr::StmtExprClass:
12780b57cec5SDimitry Andric   case Expr::ConvertVectorExprClass:
12790b57cec5SDimitry Andric   case Expr::VAArgExprClass:
1280bdd1243dSDimitry Andric   case Expr::CXXParenListInitExprClass:
1281480093f4SDimitry Andric     return canSubStmtsThrow(*this, S);
1282480093f4SDimitry Andric 
1283480093f4SDimitry Andric   case Expr::CompoundLiteralExprClass:
1284480093f4SDimitry Andric   case Expr::CXXConstCastExprClass:
12855ffd83dbSDimitry Andric   case Expr::CXXAddrspaceCastExprClass:
1286480093f4SDimitry Andric   case Expr::CXXReinterpretCastExprClass:
1287480093f4SDimitry Andric   case Expr::BuiltinBitCastExprClass:
1288480093f4SDimitry Andric       // FIXME: Properly determine whether a variably-modified type can throw.
1289480093f4SDimitry Andric     if (cast<Expr>(S)->getType()->isVariablyModifiedType())
1290480093f4SDimitry Andric       return CT_Can;
1291480093f4SDimitry Andric     return canSubStmtsThrow(*this, S);
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric     // Some might be dependent for other reasons.
12940b57cec5SDimitry Andric   case Expr::ArraySubscriptExprClass:
12955ffd83dbSDimitry Andric   case Expr::MatrixSubscriptExprClass:
1296*0fca6ea1SDimitry Andric   case Expr::ArraySectionExprClass:
12975ffd83dbSDimitry Andric   case Expr::OMPArrayShapingExprClass:
12985ffd83dbSDimitry Andric   case Expr::OMPIteratorExprClass:
12990b57cec5SDimitry Andric   case Expr::BinaryOperatorClass:
13000b57cec5SDimitry Andric   case Expr::DependentCoawaitExprClass:
13010b57cec5SDimitry Andric   case Expr::CompoundAssignOperatorClass:
13020b57cec5SDimitry Andric   case Expr::CStyleCastExprClass:
13030b57cec5SDimitry Andric   case Expr::CXXStaticCastExprClass:
13040b57cec5SDimitry Andric   case Expr::CXXFunctionalCastExprClass:
13050b57cec5SDimitry Andric   case Expr::ImplicitCastExprClass:
13060b57cec5SDimitry Andric   case Expr::MaterializeTemporaryExprClass:
13070b57cec5SDimitry Andric   case Expr::UnaryOperatorClass: {
1308480093f4SDimitry Andric     // FIXME: Properly determine whether a variably-modified type can throw.
1309480093f4SDimitry Andric     if (auto *CE = dyn_cast<CastExpr>(S))
1310480093f4SDimitry Andric       if (CE->getType()->isVariablyModifiedType())
1311480093f4SDimitry Andric         return CT_Can;
1312480093f4SDimitry Andric     CanThrowResult CT =
1313480093f4SDimitry Andric         cast<Expr>(S)->isTypeDependent() ? CT_Dependent : CT_Cannot;
1314480093f4SDimitry Andric     return mergeCanThrow(CT, canSubStmtsThrow(*this, S));
13150b57cec5SDimitry Andric   }
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric   case Expr::CXXDefaultArgExprClass:
1318480093f4SDimitry Andric     return canThrow(cast<CXXDefaultArgExpr>(S)->getExpr());
13190b57cec5SDimitry Andric 
13200b57cec5SDimitry Andric   case Expr::CXXDefaultInitExprClass:
1321480093f4SDimitry Andric     return canThrow(cast<CXXDefaultInitExpr>(S)->getExpr());
13220b57cec5SDimitry Andric 
1323480093f4SDimitry Andric   case Expr::ChooseExprClass: {
1324480093f4SDimitry Andric     auto *CE = cast<ChooseExpr>(S);
1325480093f4SDimitry Andric     if (CE->isTypeDependent() || CE->isValueDependent())
13260b57cec5SDimitry Andric       return CT_Dependent;
1327480093f4SDimitry Andric     return canThrow(CE->getChosenSubExpr());
1328480093f4SDimitry Andric   }
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric   case Expr::GenericSelectionExprClass:
1331480093f4SDimitry Andric     if (cast<GenericSelectionExpr>(S)->isResultDependent())
13320b57cec5SDimitry Andric       return CT_Dependent;
1333480093f4SDimitry Andric     return canThrow(cast<GenericSelectionExpr>(S)->getResultExpr());
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric     // Some expressions are always dependent.
13360b57cec5SDimitry Andric   case Expr::CXXDependentScopeMemberExprClass:
13370b57cec5SDimitry Andric   case Expr::CXXUnresolvedConstructExprClass:
13380b57cec5SDimitry Andric   case Expr::DependentScopeDeclRefExprClass:
13390b57cec5SDimitry Andric   case Expr::CXXFoldExprClass:
13405ffd83dbSDimitry Andric   case Expr::RecoveryExprClass:
13410b57cec5SDimitry Andric     return CT_Dependent;
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric   case Expr::AsTypeExprClass:
13440b57cec5SDimitry Andric   case Expr::BinaryConditionalOperatorClass:
13450b57cec5SDimitry Andric   case Expr::BlockExprClass:
13460b57cec5SDimitry Andric   case Expr::CUDAKernelCallExprClass:
13470b57cec5SDimitry Andric   case Expr::DeclRefExprClass:
13480b57cec5SDimitry Andric   case Expr::ObjCBridgedCastExprClass:
13490b57cec5SDimitry Andric   case Expr::ObjCIndirectCopyRestoreExprClass:
13500b57cec5SDimitry Andric   case Expr::ObjCProtocolExprClass:
13510b57cec5SDimitry Andric   case Expr::ObjCSelectorExprClass:
13520b57cec5SDimitry Andric   case Expr::ObjCAvailabilityCheckExprClass:
13530b57cec5SDimitry Andric   case Expr::OffsetOfExprClass:
13540b57cec5SDimitry Andric   case Expr::PackExpansionExprClass:
13550b57cec5SDimitry Andric   case Expr::SubstNonTypeTemplateParmExprClass:
13560b57cec5SDimitry Andric   case Expr::SubstNonTypeTemplateParmPackExprClass:
13570b57cec5SDimitry Andric   case Expr::FunctionParmPackExprClass:
13580b57cec5SDimitry Andric   case Expr::UnaryExprOrTypeTraitExprClass:
13590b57cec5SDimitry Andric   case Expr::UnresolvedLookupExprClass:
13600b57cec5SDimitry Andric   case Expr::UnresolvedMemberExprClass:
13610b57cec5SDimitry Andric   case Expr::TypoExprClass:
1362480093f4SDimitry Andric     // FIXME: Many of the above can throw.
13630b57cec5SDimitry Andric     return CT_Cannot;
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric   case Expr::AddrLabelExprClass:
13660b57cec5SDimitry Andric   case Expr::ArrayTypeTraitExprClass:
13670b57cec5SDimitry Andric   case Expr::AtomicExprClass:
13680b57cec5SDimitry Andric   case Expr::TypeTraitExprClass:
13690b57cec5SDimitry Andric   case Expr::CXXBoolLiteralExprClass:
13700b57cec5SDimitry Andric   case Expr::CXXNoexceptExprClass:
13710b57cec5SDimitry Andric   case Expr::CXXNullPtrLiteralExprClass:
13720b57cec5SDimitry Andric   case Expr::CXXPseudoDestructorExprClass:
13730b57cec5SDimitry Andric   case Expr::CXXScalarValueInitExprClass:
13740b57cec5SDimitry Andric   case Expr::CXXThisExprClass:
13750b57cec5SDimitry Andric   case Expr::CXXUuidofExprClass:
13760b57cec5SDimitry Andric   case Expr::CharacterLiteralClass:
13770b57cec5SDimitry Andric   case Expr::ExpressionTraitExprClass:
13780b57cec5SDimitry Andric   case Expr::FloatingLiteralClass:
13790b57cec5SDimitry Andric   case Expr::GNUNullExprClass:
13800b57cec5SDimitry Andric   case Expr::ImaginaryLiteralClass:
13810b57cec5SDimitry Andric   case Expr::ImplicitValueInitExprClass:
13820b57cec5SDimitry Andric   case Expr::IntegerLiteralClass:
13830b57cec5SDimitry Andric   case Expr::FixedPointLiteralClass:
13840b57cec5SDimitry Andric   case Expr::ArrayInitIndexExprClass:
13850b57cec5SDimitry Andric   case Expr::NoInitExprClass:
13860b57cec5SDimitry Andric   case Expr::ObjCEncodeExprClass:
13870b57cec5SDimitry Andric   case Expr::ObjCStringLiteralClass:
13880b57cec5SDimitry Andric   case Expr::ObjCBoolLiteralExprClass:
13890b57cec5SDimitry Andric   case Expr::OpaqueValueExprClass:
13900b57cec5SDimitry Andric   case Expr::PredefinedExprClass:
13910b57cec5SDimitry Andric   case Expr::SizeOfPackExprClass:
1392*0fca6ea1SDimitry Andric   case Expr::PackIndexingExprClass:
13930b57cec5SDimitry Andric   case Expr::StringLiteralClass:
13940b57cec5SDimitry Andric   case Expr::SourceLocExprClass:
1395*0fca6ea1SDimitry Andric   case Expr::EmbedExprClass:
1396a7dea167SDimitry Andric   case Expr::ConceptSpecializationExprClass:
139755e4f9d5SDimitry Andric   case Expr::RequiresExprClass:
13980b57cec5SDimitry Andric     // These expressions can never throw.
13990b57cec5SDimitry Andric     return CT_Cannot;
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric   case Expr::MSPropertyRefExprClass:
14020b57cec5SDimitry Andric   case Expr::MSPropertySubscriptExprClass:
14030b57cec5SDimitry Andric     llvm_unreachable("Invalid class for expression");
14040b57cec5SDimitry Andric 
1405480093f4SDimitry Andric     // Most statements can throw if any substatement can throw.
1406*0fca6ea1SDimitry Andric   case Stmt::OpenACCComputeConstructClass:
1407*0fca6ea1SDimitry Andric   case Stmt::OpenACCLoopConstructClass:
1408480093f4SDimitry Andric   case Stmt::AttributedStmtClass:
1409480093f4SDimitry Andric   case Stmt::BreakStmtClass:
1410480093f4SDimitry Andric   case Stmt::CapturedStmtClass:
1411480093f4SDimitry Andric   case Stmt::CaseStmtClass:
1412480093f4SDimitry Andric   case Stmt::CompoundStmtClass:
1413480093f4SDimitry Andric   case Stmt::ContinueStmtClass:
1414480093f4SDimitry Andric   case Stmt::CoreturnStmtClass:
1415480093f4SDimitry Andric   case Stmt::CoroutineBodyStmtClass:
1416480093f4SDimitry Andric   case Stmt::CXXCatchStmtClass:
1417480093f4SDimitry Andric   case Stmt::CXXForRangeStmtClass:
1418480093f4SDimitry Andric   case Stmt::DefaultStmtClass:
1419480093f4SDimitry Andric   case Stmt::DoStmtClass:
1420480093f4SDimitry Andric   case Stmt::ForStmtClass:
1421480093f4SDimitry Andric   case Stmt::GCCAsmStmtClass:
1422480093f4SDimitry Andric   case Stmt::GotoStmtClass:
1423480093f4SDimitry Andric   case Stmt::IndirectGotoStmtClass:
1424480093f4SDimitry Andric   case Stmt::LabelStmtClass:
1425480093f4SDimitry Andric   case Stmt::MSAsmStmtClass:
1426480093f4SDimitry Andric   case Stmt::MSDependentExistsStmtClass:
1427480093f4SDimitry Andric   case Stmt::NullStmtClass:
1428480093f4SDimitry Andric   case Stmt::ObjCAtCatchStmtClass:
1429480093f4SDimitry Andric   case Stmt::ObjCAtFinallyStmtClass:
1430480093f4SDimitry Andric   case Stmt::ObjCAtSynchronizedStmtClass:
1431480093f4SDimitry Andric   case Stmt::ObjCAutoreleasePoolStmtClass:
1432480093f4SDimitry Andric   case Stmt::ObjCForCollectionStmtClass:
1433480093f4SDimitry Andric   case Stmt::OMPAtomicDirectiveClass:
1434480093f4SDimitry Andric   case Stmt::OMPBarrierDirectiveClass:
1435480093f4SDimitry Andric   case Stmt::OMPCancelDirectiveClass:
1436480093f4SDimitry Andric   case Stmt::OMPCancellationPointDirectiveClass:
1437480093f4SDimitry Andric   case Stmt::OMPCriticalDirectiveClass:
1438480093f4SDimitry Andric   case Stmt::OMPDistributeDirectiveClass:
1439480093f4SDimitry Andric   case Stmt::OMPDistributeParallelForDirectiveClass:
1440480093f4SDimitry Andric   case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1441480093f4SDimitry Andric   case Stmt::OMPDistributeSimdDirectiveClass:
1442480093f4SDimitry Andric   case Stmt::OMPFlushDirectiveClass:
14435ffd83dbSDimitry Andric   case Stmt::OMPDepobjDirectiveClass:
14445ffd83dbSDimitry Andric   case Stmt::OMPScanDirectiveClass:
1445480093f4SDimitry Andric   case Stmt::OMPForDirectiveClass:
1446480093f4SDimitry Andric   case Stmt::OMPForSimdDirectiveClass:
1447480093f4SDimitry Andric   case Stmt::OMPMasterDirectiveClass:
1448480093f4SDimitry Andric   case Stmt::OMPMasterTaskLoopDirectiveClass:
144981ad6265SDimitry Andric   case Stmt::OMPMaskedTaskLoopDirectiveClass:
1450480093f4SDimitry Andric   case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
145181ad6265SDimitry Andric   case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1452480093f4SDimitry Andric   case Stmt::OMPOrderedDirectiveClass:
1453fe6060f1SDimitry Andric   case Stmt::OMPCanonicalLoopClass:
1454480093f4SDimitry Andric   case Stmt::OMPParallelDirectiveClass:
1455480093f4SDimitry Andric   case Stmt::OMPParallelForDirectiveClass:
1456480093f4SDimitry Andric   case Stmt::OMPParallelForSimdDirectiveClass:
1457480093f4SDimitry Andric   case Stmt::OMPParallelMasterDirectiveClass:
145881ad6265SDimitry Andric   case Stmt::OMPParallelMaskedDirectiveClass:
1459480093f4SDimitry Andric   case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
146081ad6265SDimitry Andric   case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1461480093f4SDimitry Andric   case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
146281ad6265SDimitry Andric   case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1463480093f4SDimitry Andric   case Stmt::OMPParallelSectionsDirectiveClass:
1464480093f4SDimitry Andric   case Stmt::OMPSectionDirectiveClass:
1465480093f4SDimitry Andric   case Stmt::OMPSectionsDirectiveClass:
1466480093f4SDimitry Andric   case Stmt::OMPSimdDirectiveClass:
1467fe6060f1SDimitry Andric   case Stmt::OMPTileDirectiveClass:
1468fe6060f1SDimitry Andric   case Stmt::OMPUnrollDirectiveClass:
1469*0fca6ea1SDimitry Andric   case Stmt::OMPReverseDirectiveClass:
1470*0fca6ea1SDimitry Andric   case Stmt::OMPInterchangeDirectiveClass:
1471480093f4SDimitry Andric   case Stmt::OMPSingleDirectiveClass:
1472480093f4SDimitry Andric   case Stmt::OMPTargetDataDirectiveClass:
1473480093f4SDimitry Andric   case Stmt::OMPTargetDirectiveClass:
1474480093f4SDimitry Andric   case Stmt::OMPTargetEnterDataDirectiveClass:
1475480093f4SDimitry Andric   case Stmt::OMPTargetExitDataDirectiveClass:
1476480093f4SDimitry Andric   case Stmt::OMPTargetParallelDirectiveClass:
1477480093f4SDimitry Andric   case Stmt::OMPTargetParallelForDirectiveClass:
1478480093f4SDimitry Andric   case Stmt::OMPTargetParallelForSimdDirectiveClass:
1479480093f4SDimitry Andric   case Stmt::OMPTargetSimdDirectiveClass:
1480480093f4SDimitry Andric   case Stmt::OMPTargetTeamsDirectiveClass:
1481480093f4SDimitry Andric   case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1482480093f4SDimitry Andric   case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1483480093f4SDimitry Andric   case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1484480093f4SDimitry Andric   case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1485480093f4SDimitry Andric   case Stmt::OMPTargetUpdateDirectiveClass:
14865f757f3fSDimitry Andric   case Stmt::OMPScopeDirectiveClass:
1487480093f4SDimitry Andric   case Stmt::OMPTaskDirectiveClass:
1488480093f4SDimitry Andric   case Stmt::OMPTaskgroupDirectiveClass:
1489480093f4SDimitry Andric   case Stmt::OMPTaskLoopDirectiveClass:
1490480093f4SDimitry Andric   case Stmt::OMPTaskLoopSimdDirectiveClass:
1491480093f4SDimitry Andric   case Stmt::OMPTaskwaitDirectiveClass:
1492480093f4SDimitry Andric   case Stmt::OMPTaskyieldDirectiveClass:
1493bdd1243dSDimitry Andric   case Stmt::OMPErrorDirectiveClass:
1494480093f4SDimitry Andric   case Stmt::OMPTeamsDirectiveClass:
1495480093f4SDimitry Andric   case Stmt::OMPTeamsDistributeDirectiveClass:
1496480093f4SDimitry Andric   case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1497480093f4SDimitry Andric   case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1498480093f4SDimitry Andric   case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1499fe6060f1SDimitry Andric   case Stmt::OMPInteropDirectiveClass:
1500fe6060f1SDimitry Andric   case Stmt::OMPDispatchDirectiveClass:
1501fe6060f1SDimitry Andric   case Stmt::OMPMaskedDirectiveClass:
1502349cc55cSDimitry Andric   case Stmt::OMPMetaDirectiveClass:
1503349cc55cSDimitry Andric   case Stmt::OMPGenericLoopDirectiveClass:
150481ad6265SDimitry Andric   case Stmt::OMPTeamsGenericLoopDirectiveClass:
150581ad6265SDimitry Andric   case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
150681ad6265SDimitry Andric   case Stmt::OMPParallelGenericLoopDirectiveClass:
150781ad6265SDimitry Andric   case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1508480093f4SDimitry Andric   case Stmt::ReturnStmtClass:
1509480093f4SDimitry Andric   case Stmt::SEHExceptStmtClass:
1510480093f4SDimitry Andric   case Stmt::SEHFinallyStmtClass:
1511480093f4SDimitry Andric   case Stmt::SEHLeaveStmtClass:
1512480093f4SDimitry Andric   case Stmt::SEHTryStmtClass:
1513480093f4SDimitry Andric   case Stmt::SwitchStmtClass:
1514480093f4SDimitry Andric   case Stmt::WhileStmtClass:
1515480093f4SDimitry Andric     return canSubStmtsThrow(*this, S);
1516480093f4SDimitry Andric 
1517480093f4SDimitry Andric   case Stmt::DeclStmtClass: {
1518480093f4SDimitry Andric     CanThrowResult CT = CT_Cannot;
1519480093f4SDimitry Andric     for (const Decl *D : cast<DeclStmt>(S)->decls()) {
1520480093f4SDimitry Andric       if (auto *VD = dyn_cast<VarDecl>(D))
1521480093f4SDimitry Andric         CT = mergeCanThrow(CT, canVarDeclThrow(*this, VD));
1522480093f4SDimitry Andric 
1523480093f4SDimitry Andric       // FIXME: Properly determine whether a variably-modified type can throw.
1524480093f4SDimitry Andric       if (auto *TND = dyn_cast<TypedefNameDecl>(D))
1525480093f4SDimitry Andric         if (TND->getUnderlyingType()->isVariablyModifiedType())
1526480093f4SDimitry Andric           return CT_Can;
1527480093f4SDimitry Andric       if (auto *VD = dyn_cast<ValueDecl>(D))
1528480093f4SDimitry Andric         if (VD->getType()->isVariablyModifiedType())
1529480093f4SDimitry Andric           return CT_Can;
1530480093f4SDimitry Andric     }
1531480093f4SDimitry Andric     return CT;
1532480093f4SDimitry Andric   }
1533480093f4SDimitry Andric 
1534480093f4SDimitry Andric   case Stmt::IfStmtClass: {
1535480093f4SDimitry Andric     auto *IS = cast<IfStmt>(S);
1536480093f4SDimitry Andric     CanThrowResult CT = CT_Cannot;
1537480093f4SDimitry Andric     if (const Stmt *Init = IS->getInit())
1538480093f4SDimitry Andric       CT = mergeCanThrow(CT, canThrow(Init));
1539480093f4SDimitry Andric     if (const Stmt *CondDS = IS->getConditionVariableDeclStmt())
1540480093f4SDimitry Andric       CT = mergeCanThrow(CT, canThrow(CondDS));
1541480093f4SDimitry Andric     CT = mergeCanThrow(CT, canThrow(IS->getCond()));
1542480093f4SDimitry Andric 
1543480093f4SDimitry Andric     // For 'if constexpr', consider only the non-discarded case.
1544480093f4SDimitry Andric     // FIXME: We should add a DiscardedStmt marker to the AST.
1545bdd1243dSDimitry Andric     if (std::optional<const Stmt *> Case = IS->getNondiscardedCase(Context))
1546480093f4SDimitry Andric       return *Case ? mergeCanThrow(CT, canThrow(*Case)) : CT;
1547480093f4SDimitry Andric 
1548480093f4SDimitry Andric     CanThrowResult Then = canThrow(IS->getThen());
1549480093f4SDimitry Andric     CanThrowResult Else = IS->getElse() ? canThrow(IS->getElse()) : CT_Cannot;
1550480093f4SDimitry Andric     if (Then == Else)
1551480093f4SDimitry Andric       return mergeCanThrow(CT, Then);
1552480093f4SDimitry Andric 
1553480093f4SDimitry Andric     // For a dependent 'if constexpr', the result is dependent if it depends on
1554480093f4SDimitry Andric     // the value of the condition.
1555480093f4SDimitry Andric     return mergeCanThrow(CT, IS->isConstexpr() ? CT_Dependent
1556480093f4SDimitry Andric                                                : mergeCanThrow(Then, Else));
1557480093f4SDimitry Andric   }
1558480093f4SDimitry Andric 
1559480093f4SDimitry Andric   case Stmt::CXXTryStmtClass: {
1560480093f4SDimitry Andric     auto *TS = cast<CXXTryStmt>(S);
1561480093f4SDimitry Andric     // try /*...*/ catch (...) { H } can throw only if H can throw.
1562480093f4SDimitry Andric     // Any other try-catch can throw if any substatement can throw.
1563480093f4SDimitry Andric     const CXXCatchStmt *FinalHandler = TS->getHandler(TS->getNumHandlers() - 1);
1564480093f4SDimitry Andric     if (!FinalHandler->getExceptionDecl())
1565480093f4SDimitry Andric       return canThrow(FinalHandler->getHandlerBlock());
1566480093f4SDimitry Andric     return canSubStmtsThrow(*this, S);
1567480093f4SDimitry Andric   }
1568480093f4SDimitry Andric 
1569480093f4SDimitry Andric   case Stmt::ObjCAtThrowStmtClass:
1570480093f4SDimitry Andric     return CT_Can;
1571480093f4SDimitry Andric 
1572480093f4SDimitry Andric   case Stmt::ObjCAtTryStmtClass: {
1573480093f4SDimitry Andric     auto *TS = cast<ObjCAtTryStmt>(S);
1574480093f4SDimitry Andric 
1575480093f4SDimitry Andric     // @catch(...) need not be last in Objective-C. Walk backwards until we
1576480093f4SDimitry Andric     // see one or hit the @try.
1577480093f4SDimitry Andric     CanThrowResult CT = CT_Cannot;
1578480093f4SDimitry Andric     if (const Stmt *Finally = TS->getFinallyStmt())
1579480093f4SDimitry Andric       CT = mergeCanThrow(CT, canThrow(Finally));
1580480093f4SDimitry Andric     for (unsigned I = TS->getNumCatchStmts(); I != 0; --I) {
1581480093f4SDimitry Andric       const ObjCAtCatchStmt *Catch = TS->getCatchStmt(I - 1);
1582480093f4SDimitry Andric       CT = mergeCanThrow(CT, canThrow(Catch));
1583480093f4SDimitry Andric       // If we reach a @catch(...), no earlier exceptions can escape.
1584480093f4SDimitry Andric       if (Catch->hasEllipsis())
1585480093f4SDimitry Andric         return CT;
1586480093f4SDimitry Andric     }
1587480093f4SDimitry Andric 
1588480093f4SDimitry Andric     // Didn't find an @catch(...). Exceptions from the @try body can escape.
1589480093f4SDimitry Andric     return mergeCanThrow(CT, canThrow(TS->getTryBody()));
1590480093f4SDimitry Andric   }
1591480093f4SDimitry Andric 
1592fe6060f1SDimitry Andric   case Stmt::SYCLUniqueStableNameExprClass:
1593fe6060f1SDimitry Andric     return CT_Cannot;
1594480093f4SDimitry Andric   case Stmt::NoStmtClass:
1595480093f4SDimitry Andric     llvm_unreachable("Invalid class for statement");
15960b57cec5SDimitry Andric   }
15970b57cec5SDimitry Andric   llvm_unreachable("Bogus StmtClass");
15980b57cec5SDimitry Andric }
15990b57cec5SDimitry Andric 
16000b57cec5SDimitry Andric } // end namespace clang
1601