xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides Sema routines for C++ exception specification testing.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Sema/SemaInternal.h"
14 #include "clang/AST/ASTMutationListener.h"
15 #include "clang/AST/CXXInheritance.h"
16 #include "clang/AST/Expr.h"
17 #include "clang/AST/ExprCXX.h"
18 #include "clang/AST/StmtObjC.h"
19 #include "clang/AST/TypeLoc.h"
20 #include "clang/Basic/Diagnostic.h"
21 #include "clang/Basic/SourceManager.h"
22 #include "llvm/ADT/SmallPtrSet.h"
23 #include "llvm/ADT/SmallString.h"
24 #include <optional>
25 
26 namespace clang {
27 
GetUnderlyingFunction(QualType T)28 static const FunctionProtoType *GetUnderlyingFunction(QualType T)
29 {
30   if (const PointerType *PtrTy = T->getAs<PointerType>())
31     T = PtrTy->getPointeeType();
32   else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
33     T = RefTy->getPointeeType();
34   else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
35     T = MPTy->getPointeeType();
36   return T->getAs<FunctionProtoType>();
37 }
38 
39 /// HACK: 2014-11-14 libstdc++ had a bug where it shadows std::swap with a
40 /// member swap function then tries to call std::swap unqualified from the
41 /// exception specification of that function. This function detects whether
42 /// we're in such a case and turns off delay-parsing of exception
43 /// specifications. Libstdc++ 6.1 (released 2016-04-27) appears to have
44 /// resolved it as side-effect of commit ddb63209a8d (2015-06-05).
isLibstdcxxEagerExceptionSpecHack(const Declarator & D)45 bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
46   auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
47 
48   // All the problem cases are member functions named "swap" within class
49   // templates declared directly within namespace std or std::__debug or
50   // std::__profile.
51   if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() ||
52       !D.getIdentifier() || !D.getIdentifier()->isStr("swap"))
53     return false;
54 
55   auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext());
56   if (!ND)
57     return false;
58 
59   bool IsInStd = ND->isStdNamespace();
60   if (!IsInStd) {
61     // This isn't a direct member of namespace std, but it might still be
62     // libstdc++'s std::__debug::array or std::__profile::array.
63     IdentifierInfo *II = ND->getIdentifier();
64     if (!II || !(II->isStr("__debug") || II->isStr("__profile")) ||
65         !ND->isInStdNamespace())
66       return false;
67   }
68 
69   // Only apply this hack within a system header.
70   if (!Context.getSourceManager().isInSystemHeader(D.getBeginLoc()))
71     return false;
72 
73   return llvm::StringSwitch<bool>(RD->getIdentifier()->getName())
74       .Case("array", true)
75       .Case("pair", IsInStd)
76       .Case("priority_queue", IsInStd)
77       .Case("stack", IsInStd)
78       .Case("queue", IsInStd)
79       .Default(false);
80 }
81 
ActOnNoexceptSpec(Expr * NoexceptExpr,ExceptionSpecificationType & EST)82 ExprResult Sema::ActOnNoexceptSpec(Expr *NoexceptExpr,
83                                    ExceptionSpecificationType &EST) {
84 
85   if (NoexceptExpr->isTypeDependent() ||
86       NoexceptExpr->containsUnexpandedParameterPack()) {
87     EST = EST_DependentNoexcept;
88     return NoexceptExpr;
89   }
90 
91   llvm::APSInt Result;
92   ExprResult Converted = CheckConvertedConstantExpression(
93       NoexceptExpr, Context.BoolTy, Result, CCEK_Noexcept);
94 
95   if (Converted.isInvalid()) {
96     EST = EST_NoexceptFalse;
97     // Fill in an expression of 'false' as a fixup.
98     auto *BoolExpr = new (Context)
99         CXXBoolLiteralExpr(false, Context.BoolTy, NoexceptExpr->getBeginLoc());
100     llvm::APSInt Value{1};
101     Value = 0;
102     return ConstantExpr::Create(Context, BoolExpr, APValue{Value});
103   }
104 
105   if (Converted.get()->isValueDependent()) {
106     EST = EST_DependentNoexcept;
107     return Converted;
108   }
109 
110   if (!Converted.isInvalid())
111     EST = !Result ? EST_NoexceptFalse : EST_NoexceptTrue;
112   return Converted;
113 }
114 
CheckSpecifiedExceptionType(QualType & T,SourceRange Range)115 bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
116   // C++11 [except.spec]p2:
117   //   A type cv T, "array of T", or "function returning T" denoted
118   //   in an exception-specification is adjusted to type T, "pointer to T", or
119   //   "pointer to function returning T", respectively.
120   //
121   // We also apply this rule in C++98.
122   if (T->isArrayType())
123     T = Context.getArrayDecayedType(T);
124   else if (T->isFunctionType())
125     T = Context.getPointerType(T);
126 
127   int Kind = 0;
128   QualType PointeeT = T;
129   if (const PointerType *PT = T->getAs<PointerType>()) {
130     PointeeT = PT->getPointeeType();
131     Kind = 1;
132 
133     // cv void* is explicitly permitted, despite being a pointer to an
134     // incomplete type.
135     if (PointeeT->isVoidType())
136       return false;
137   } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
138     PointeeT = RT->getPointeeType();
139     Kind = 2;
140 
141     if (RT->isRValueReferenceType()) {
142       // C++11 [except.spec]p2:
143       //   A type denoted in an exception-specification shall not denote [...]
144       //   an rvalue reference type.
145       Diag(Range.getBegin(), diag::err_rref_in_exception_spec)
146         << T << Range;
147       return true;
148     }
149   }
150 
151   // C++11 [except.spec]p2:
152   //   A type denoted in an exception-specification shall not denote an
153   //   incomplete type other than a class currently being defined [...].
154   //   A type denoted in an exception-specification shall not denote a
155   //   pointer or reference to an incomplete type, other than (cv) void* or a
156   //   pointer or reference to a class currently being defined.
157   // In Microsoft mode, downgrade this to a warning.
158   unsigned DiagID = diag::err_incomplete_in_exception_spec;
159   bool ReturnValueOnError = true;
160   if (getLangOpts().MSVCCompat) {
161     DiagID = diag::ext_incomplete_in_exception_spec;
162     ReturnValueOnError = false;
163   }
164   if (!(PointeeT->isRecordType() &&
165         PointeeT->castAs<RecordType>()->isBeingDefined()) &&
166       RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range))
167     return ReturnValueOnError;
168 
169   // WebAssembly reference types can't be used in exception specifications.
170   if (PointeeT.isWebAssemblyReferenceType()) {
171     Diag(Range.getBegin(), diag::err_wasm_reftype_exception_spec);
172     return true;
173   }
174 
175   // The MSVC compatibility mode doesn't extend to sizeless types,
176   // so diagnose them separately.
177   if (PointeeT->isSizelessType() && Kind != 1) {
178     Diag(Range.getBegin(), diag::err_sizeless_in_exception_spec)
179         << (Kind == 2 ? 1 : 0) << PointeeT << Range;
180     return true;
181   }
182 
183   return false;
184 }
185 
CheckDistantExceptionSpec(QualType T)186 bool Sema::CheckDistantExceptionSpec(QualType T) {
187   // C++17 removes this rule in favor of putting exception specifications into
188   // the type system.
189   if (getLangOpts().CPlusPlus17)
190     return false;
191 
192   if (const PointerType *PT = T->getAs<PointerType>())
193     T = PT->getPointeeType();
194   else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
195     T = PT->getPointeeType();
196   else
197     return false;
198 
199   const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
200   if (!FnT)
201     return false;
202 
203   return FnT->hasExceptionSpec();
204 }
205 
206 const FunctionProtoType *
ResolveExceptionSpec(SourceLocation Loc,const FunctionProtoType * FPT)207 Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
208   if (FPT->getExceptionSpecType() == EST_Unparsed) {
209     Diag(Loc, diag::err_exception_spec_not_parsed);
210     return nullptr;
211   }
212 
213   if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
214     return FPT;
215 
216   FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
217   const FunctionProtoType *SourceFPT =
218       SourceDecl->getType()->castAs<FunctionProtoType>();
219 
220   // If the exception specification has already been resolved, just return it.
221   if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType()))
222     return SourceFPT;
223 
224   // Compute or instantiate the exception specification now.
225   if (SourceFPT->getExceptionSpecType() == EST_Unevaluated)
226     EvaluateImplicitExceptionSpec(Loc, SourceDecl);
227   else
228     InstantiateExceptionSpec(Loc, SourceDecl);
229 
230   const FunctionProtoType *Proto =
231     SourceDecl->getType()->castAs<FunctionProtoType>();
232   if (Proto->getExceptionSpecType() == clang::EST_Unparsed) {
233     Diag(Loc, diag::err_exception_spec_not_parsed);
234     Proto = nullptr;
235   }
236   return Proto;
237 }
238 
239 void
UpdateExceptionSpec(FunctionDecl * FD,const FunctionProtoType::ExceptionSpecInfo & ESI)240 Sema::UpdateExceptionSpec(FunctionDecl *FD,
241                           const FunctionProtoType::ExceptionSpecInfo &ESI) {
242   // If we've fully resolved the exception specification, notify listeners.
243   if (!isUnresolvedExceptionSpec(ESI.Type))
244     if (auto *Listener = getASTMutationListener())
245       Listener->ResolvedExceptionSpec(FD);
246 
247   for (FunctionDecl *Redecl : FD->redecls())
248     Context.adjustExceptionSpec(Redecl, ESI);
249 }
250 
exceptionSpecNotKnownYet(const FunctionDecl * FD)251 static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) {
252   ExceptionSpecificationType EST =
253       FD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType();
254   if (EST == EST_Unparsed)
255     return true;
256   else if (EST != EST_Unevaluated)
257     return false;
258   const DeclContext *DC = FD->getLexicalDeclContext();
259   return DC->isRecord() && cast<RecordDecl>(DC)->isBeingDefined();
260 }
261 
262 static bool CheckEquivalentExceptionSpecImpl(
263     Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
264     const FunctionProtoType *Old, SourceLocation OldLoc,
265     const FunctionProtoType *New, SourceLocation NewLoc,
266     bool *MissingExceptionSpecification = nullptr,
267     bool *MissingEmptyExceptionSpecification = nullptr,
268     bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false);
269 
270 /// Determine whether a function has an implicitly-generated exception
271 /// specification.
hasImplicitExceptionSpec(FunctionDecl * Decl)272 static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
273   if (!isa<CXXDestructorDecl>(Decl) &&
274       Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete &&
275       Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
276     return false;
277 
278   // For a function that the user didn't declare:
279   //  - if this is a destructor, its exception specification is implicit.
280   //  - if this is 'operator delete' or 'operator delete[]', the exception
281   //    specification is as-if an explicit exception specification was given
282   //    (per [basic.stc.dynamic]p2).
283   if (!Decl->getTypeSourceInfo())
284     return isa<CXXDestructorDecl>(Decl);
285 
286   auto *Ty = Decl->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
287   return !Ty->hasExceptionSpec();
288 }
289 
CheckEquivalentExceptionSpec(FunctionDecl * Old,FunctionDecl * New)290 bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
291   // Just completely ignore this under -fno-exceptions prior to C++17.
292   // In C++17 onwards, the exception specification is part of the type and
293   // we will diagnose mismatches anyway, so it's better to check for them here.
294   if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus17)
295     return false;
296 
297   OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
298   bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
299   bool MissingExceptionSpecification = false;
300   bool MissingEmptyExceptionSpecification = false;
301 
302   unsigned DiagID = diag::err_mismatched_exception_spec;
303   bool ReturnValueOnError = true;
304   if (getLangOpts().MSVCCompat) {
305     DiagID = diag::ext_mismatched_exception_spec;
306     ReturnValueOnError = false;
307   }
308 
309   // If we're befriending a member function of a class that's currently being
310   // defined, we might not be able to work out its exception specification yet.
311   // If not, defer the check until later.
312   if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) {
313     DelayedEquivalentExceptionSpecChecks.push_back({New, Old});
314     return false;
315   }
316 
317   // Check the types as written: they must match before any exception
318   // specification adjustment is applied.
319   if (!CheckEquivalentExceptionSpecImpl(
320         *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
321         Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
322         New->getType()->getAs<FunctionProtoType>(), New->getLocation(),
323         &MissingExceptionSpecification, &MissingEmptyExceptionSpecification,
324         /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) {
325     // C++11 [except.spec]p4 [DR1492]:
326     //   If a declaration of a function has an implicit
327     //   exception-specification, other declarations of the function shall
328     //   not specify an exception-specification.
329     if (getLangOpts().CPlusPlus11 && getLangOpts().CXXExceptions &&
330         hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
331       Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
332         << hasImplicitExceptionSpec(Old);
333       if (Old->getLocation().isValid())
334         Diag(Old->getLocation(), diag::note_previous_declaration);
335     }
336     return false;
337   }
338 
339   // The failure was something other than an missing exception
340   // specification; return an error, except in MS mode where this is a warning.
341   if (!MissingExceptionSpecification)
342     return ReturnValueOnError;
343 
344   const auto *NewProto = New->getType()->castAs<FunctionProtoType>();
345 
346   // The new function declaration is only missing an empty exception
347   // specification "throw()". If the throw() specification came from a
348   // function in a system header that has C linkage, just add an empty
349   // exception specification to the "new" declaration. Note that C library
350   // implementations are permitted to add these nothrow exception
351   // specifications.
352   //
353   // Likewise if the old function is a builtin.
354   if (MissingEmptyExceptionSpecification &&
355       (Old->getLocation().isInvalid() ||
356        Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
357        Old->getBuiltinID()) &&
358       Old->isExternC()) {
359     New->setType(Context.getFunctionType(
360         NewProto->getReturnType(), NewProto->getParamTypes(),
361         NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone)));
362     return false;
363   }
364 
365   const auto *OldProto = Old->getType()->castAs<FunctionProtoType>();
366 
367   FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
368   if (ESI.Type == EST_Dynamic) {
369     // FIXME: What if the exceptions are described in terms of the old
370     // prototype's parameters?
371     ESI.Exceptions = OldProto->exceptions();
372   }
373 
374   if (ESI.Type == EST_NoexceptFalse)
375     ESI.Type = EST_None;
376   if (ESI.Type == EST_NoexceptTrue)
377     ESI.Type = EST_BasicNoexcept;
378 
379   // For dependent noexcept, we can't just take the expression from the old
380   // prototype. It likely contains references to the old prototype's parameters.
381   if (ESI.Type == EST_DependentNoexcept) {
382     New->setInvalidDecl();
383   } else {
384     // Update the type of the function with the appropriate exception
385     // specification.
386     New->setType(Context.getFunctionType(
387         NewProto->getReturnType(), NewProto->getParamTypes(),
388         NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
389   }
390 
391   if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) {
392     DiagID = diag::ext_missing_exception_specification;
393     ReturnValueOnError = false;
394   } else if (New->isReplaceableGlobalAllocationFunction() &&
395              ESI.Type != EST_DependentNoexcept) {
396     // Allow missing exception specifications in redeclarations as an extension,
397     // when declaring a replaceable global allocation function.
398     DiagID = diag::ext_missing_exception_specification;
399     ReturnValueOnError = false;
400   } else if (ESI.Type == EST_NoThrow) {
401     // Don't emit any warning for missing 'nothrow' in MSVC.
402     if (getLangOpts().MSVCCompat) {
403       return false;
404     }
405     // Allow missing attribute 'nothrow' in redeclarations, since this is a very
406     // common omission.
407     DiagID = diag::ext_missing_exception_specification;
408     ReturnValueOnError = false;
409   } else {
410     DiagID = diag::err_missing_exception_specification;
411     ReturnValueOnError = true;
412   }
413 
414   // Warn about the lack of exception specification.
415   SmallString<128> ExceptionSpecString;
416   llvm::raw_svector_ostream OS(ExceptionSpecString);
417   switch (OldProto->getExceptionSpecType()) {
418   case EST_DynamicNone:
419     OS << "throw()";
420     break;
421 
422   case EST_Dynamic: {
423     OS << "throw(";
424     bool OnFirstException = true;
425     for (const auto &E : OldProto->exceptions()) {
426       if (OnFirstException)
427         OnFirstException = false;
428       else
429         OS << ", ";
430 
431       OS << E.getAsString(getPrintingPolicy());
432     }
433     OS << ")";
434     break;
435   }
436 
437   case EST_BasicNoexcept:
438     OS << "noexcept";
439     break;
440 
441   case EST_DependentNoexcept:
442   case EST_NoexceptFalse:
443   case EST_NoexceptTrue:
444     OS << "noexcept(";
445     assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr");
446     OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy());
447     OS << ")";
448     break;
449   case EST_NoThrow:
450     OS <<"__attribute__((nothrow))";
451     break;
452   case EST_None:
453   case EST_MSAny:
454   case EST_Unevaluated:
455   case EST_Uninstantiated:
456   case EST_Unparsed:
457     llvm_unreachable("This spec type is compatible with none.");
458   }
459 
460   SourceLocation FixItLoc;
461   if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
462     TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
463     // FIXME: Preserve enough information so that we can produce a correct fixit
464     // location when there is a trailing return type.
465     if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>())
466       if (!FTLoc.getTypePtr()->hasTrailingReturn())
467         FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
468   }
469 
470   if (FixItLoc.isInvalid())
471     Diag(New->getLocation(), DiagID)
472       << New << OS.str();
473   else {
474     Diag(New->getLocation(), DiagID)
475       << New << OS.str()
476       << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
477   }
478 
479   if (Old->getLocation().isValid())
480     Diag(Old->getLocation(), diag::note_previous_declaration);
481 
482   return ReturnValueOnError;
483 }
484 
CheckEquivalentExceptionSpec(const FunctionProtoType * Old,SourceLocation OldLoc,const FunctionProtoType * New,SourceLocation NewLoc)485 bool Sema::CheckEquivalentExceptionSpec(
486     const FunctionProtoType *Old, SourceLocation OldLoc,
487     const FunctionProtoType *New, SourceLocation NewLoc) {
488   if (!getLangOpts().CXXExceptions)
489     return false;
490 
491   unsigned DiagID = diag::err_mismatched_exception_spec;
492   if (getLangOpts().MSVCCompat)
493     DiagID = diag::ext_mismatched_exception_spec;
494   bool Result = CheckEquivalentExceptionSpecImpl(
495       *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
496       Old, OldLoc, New, NewLoc);
497 
498   // In Microsoft mode, mismatching exception specifications just cause a warning.
499   if (getLangOpts().MSVCCompat)
500     return false;
501   return Result;
502 }
503 
504 /// CheckEquivalentExceptionSpec - Check if the two types have compatible
505 /// exception specifications. See C++ [except.spec]p3.
506 ///
507 /// \return \c false if the exception specifications match, \c true if there is
508 /// a problem. If \c true is returned, either a diagnostic has already been
509 /// produced or \c *MissingExceptionSpecification is set to \c true.
CheckEquivalentExceptionSpecImpl(Sema & S,const PartialDiagnostic & DiagID,const PartialDiagnostic & NoteID,const FunctionProtoType * Old,SourceLocation OldLoc,const FunctionProtoType * New,SourceLocation NewLoc,bool * MissingExceptionSpecification,bool * MissingEmptyExceptionSpecification,bool AllowNoexceptAllMatchWithNoSpec,bool IsOperatorNew)510 static bool CheckEquivalentExceptionSpecImpl(
511     Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
512     const FunctionProtoType *Old, SourceLocation OldLoc,
513     const FunctionProtoType *New, SourceLocation NewLoc,
514     bool *MissingExceptionSpecification,
515     bool *MissingEmptyExceptionSpecification,
516     bool AllowNoexceptAllMatchWithNoSpec, bool IsOperatorNew) {
517   if (MissingExceptionSpecification)
518     *MissingExceptionSpecification = false;
519 
520   if (MissingEmptyExceptionSpecification)
521     *MissingEmptyExceptionSpecification = false;
522 
523   Old = S.ResolveExceptionSpec(NewLoc, Old);
524   if (!Old)
525     return false;
526   New = S.ResolveExceptionSpec(NewLoc, New);
527   if (!New)
528     return false;
529 
530   // C++0x [except.spec]p3: Two exception-specifications are compatible if:
531   //   - both are non-throwing, regardless of their form,
532   //   - both have the form noexcept(constant-expression) and the constant-
533   //     expressions are equivalent,
534   //   - both are dynamic-exception-specifications that have the same set of
535   //     adjusted types.
536   //
537   // C++0x [except.spec]p12: An exception-specification is non-throwing if it is
538   //   of the form throw(), noexcept, or noexcept(constant-expression) where the
539   //   constant-expression yields true.
540   //
541   // C++0x [except.spec]p4: If any declaration of a function has an exception-
542   //   specifier that is not a noexcept-specification allowing all exceptions,
543   //   all declarations [...] of that function shall have a compatible
544   //   exception-specification.
545   //
546   // That last point basically means that noexcept(false) matches no spec.
547   // It's considered when AllowNoexceptAllMatchWithNoSpec is true.
548 
549   ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
550   ExceptionSpecificationType NewEST = New->getExceptionSpecType();
551 
552   assert(!isUnresolvedExceptionSpec(OldEST) &&
553          !isUnresolvedExceptionSpec(NewEST) &&
554          "Shouldn't see unknown exception specifications here");
555 
556   CanThrowResult OldCanThrow = Old->canThrow();
557   CanThrowResult NewCanThrow = New->canThrow();
558 
559   // Any non-throwing specifications are compatible.
560   if (OldCanThrow == CT_Cannot && NewCanThrow == CT_Cannot)
561     return false;
562 
563   // Any throws-anything specifications are usually compatible.
564   if (OldCanThrow == CT_Can && OldEST != EST_Dynamic &&
565       NewCanThrow == CT_Can && NewEST != EST_Dynamic) {
566     // The exception is that the absence of an exception specification only
567     // matches noexcept(false) for functions, as described above.
568     if (!AllowNoexceptAllMatchWithNoSpec &&
569         ((OldEST == EST_None && NewEST == EST_NoexceptFalse) ||
570          (OldEST == EST_NoexceptFalse && NewEST == EST_None))) {
571       // This is the disallowed case.
572     } else {
573       return false;
574     }
575   }
576 
577   // C++14 [except.spec]p3:
578   //   Two exception-specifications are compatible if [...] both have the form
579   //   noexcept(constant-expression) and the constant-expressions are equivalent
580   if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) {
581     llvm::FoldingSetNodeID OldFSN, NewFSN;
582     Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true);
583     New->getNoexceptExpr()->Profile(NewFSN, S.Context, true);
584     if (OldFSN == NewFSN)
585       return false;
586   }
587 
588   // Dynamic exception specifications with the same set of adjusted types
589   // are compatible.
590   if (OldEST == EST_Dynamic && NewEST == EST_Dynamic) {
591     bool Success = true;
592     // Both have a dynamic exception spec. Collect the first set, then compare
593     // to the second.
594     llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
595     for (const auto &I : Old->exceptions())
596       OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
597 
598     for (const auto &I : New->exceptions()) {
599       CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
600       if (OldTypes.count(TypePtr))
601         NewTypes.insert(TypePtr);
602       else {
603         Success = false;
604         break;
605       }
606     }
607 
608     if (Success && OldTypes.size() == NewTypes.size())
609       return false;
610   }
611 
612   // As a special compatibility feature, under C++0x we accept no spec and
613   // throw(std::bad_alloc) as equivalent for operator new and operator new[].
614   // This is because the implicit declaration changed, but old code would break.
615   if (S.getLangOpts().CPlusPlus11 && IsOperatorNew) {
616     const FunctionProtoType *WithExceptions = nullptr;
617     if (OldEST == EST_None && NewEST == EST_Dynamic)
618       WithExceptions = New;
619     else if (OldEST == EST_Dynamic && NewEST == EST_None)
620       WithExceptions = Old;
621     if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
622       // One has no spec, the other throw(something). If that something is
623       // std::bad_alloc, all conditions are met.
624       QualType Exception = *WithExceptions->exception_begin();
625       if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
626         IdentifierInfo* Name = ExRecord->getIdentifier();
627         if (Name && Name->getName() == "bad_alloc") {
628           // It's called bad_alloc, but is it in std?
629           if (ExRecord->isInStdNamespace()) {
630             return false;
631           }
632         }
633       }
634     }
635   }
636 
637   // If the caller wants to handle the case that the new function is
638   // incompatible due to a missing exception specification, let it.
639   if (MissingExceptionSpecification && OldEST != EST_None &&
640       NewEST == EST_None) {
641     // The old type has an exception specification of some sort, but
642     // the new type does not.
643     *MissingExceptionSpecification = true;
644 
645     if (MissingEmptyExceptionSpecification && OldCanThrow == CT_Cannot) {
646       // The old type has a throw() or noexcept(true) exception specification
647       // and the new type has no exception specification, and the caller asked
648       // to handle this itself.
649       *MissingEmptyExceptionSpecification = true;
650     }
651 
652     return true;
653   }
654 
655   S.Diag(NewLoc, DiagID);
656   if (NoteID.getDiagID() != 0 && OldLoc.isValid())
657     S.Diag(OldLoc, NoteID);
658   return true;
659 }
660 
CheckEquivalentExceptionSpec(const PartialDiagnostic & DiagID,const PartialDiagnostic & NoteID,const FunctionProtoType * Old,SourceLocation OldLoc,const FunctionProtoType * New,SourceLocation NewLoc)661 bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
662                                         const PartialDiagnostic &NoteID,
663                                         const FunctionProtoType *Old,
664                                         SourceLocation OldLoc,
665                                         const FunctionProtoType *New,
666                                         SourceLocation NewLoc) {
667   if (!getLangOpts().CXXExceptions)
668     return false;
669   return CheckEquivalentExceptionSpecImpl(*this, DiagID, NoteID, Old, OldLoc,
670                                           New, NewLoc);
671 }
672 
handlerCanCatch(QualType HandlerType,QualType ExceptionType)673 bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
674   // [except.handle]p3:
675   //   A handler is a match for an exception object of type E if:
676 
677   // HandlerType must be ExceptionType or derived from it, or pointer or
678   // reference to such types.
679   const ReferenceType *RefTy = HandlerType->getAs<ReferenceType>();
680   if (RefTy)
681     HandlerType = RefTy->getPointeeType();
682 
683   //   -- the handler is of type cv T or cv T& and E and T are the same type
684   if (Context.hasSameUnqualifiedType(ExceptionType, HandlerType))
685     return true;
686 
687   // FIXME: ObjC pointer types?
688   if (HandlerType->isPointerType() || HandlerType->isMemberPointerType()) {
689     if (RefTy && (!HandlerType.isConstQualified() ||
690                   HandlerType.isVolatileQualified()))
691       return false;
692 
693     // -- the handler is of type cv T or const T& where T is a pointer or
694     //    pointer to member type and E is std::nullptr_t
695     if (ExceptionType->isNullPtrType())
696       return true;
697 
698     // -- the handler is of type cv T or const T& where T is a pointer or
699     //    pointer to member type and E is a pointer or pointer to member type
700     //    that can be converted to T by one or more of
701     //    -- a qualification conversion
702     //    -- a function pointer conversion
703     bool LifetimeConv;
704     QualType Result;
705     // FIXME: Should we treat the exception as catchable if a lifetime
706     // conversion is required?
707     if (IsQualificationConversion(ExceptionType, HandlerType, false,
708                                   LifetimeConv) ||
709         IsFunctionConversion(ExceptionType, HandlerType, Result))
710       return true;
711 
712     //    -- a standard pointer conversion [...]
713     if (!ExceptionType->isPointerType() || !HandlerType->isPointerType())
714       return false;
715 
716     // Handle the "qualification conversion" portion.
717     Qualifiers EQuals, HQuals;
718     ExceptionType = Context.getUnqualifiedArrayType(
719         ExceptionType->getPointeeType(), EQuals);
720     HandlerType = Context.getUnqualifiedArrayType(
721         HandlerType->getPointeeType(), HQuals);
722     if (!HQuals.compatiblyIncludes(EQuals))
723       return false;
724 
725     if (HandlerType->isVoidType() && ExceptionType->isObjectType())
726       return true;
727 
728     // The only remaining case is a derived-to-base conversion.
729   }
730 
731   //   -- the handler is of type cg T or cv T& and T is an unambiguous public
732   //      base class of E
733   if (!ExceptionType->isRecordType() || !HandlerType->isRecordType())
734     return false;
735   CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
736                      /*DetectVirtual=*/false);
737   if (!IsDerivedFrom(SourceLocation(), ExceptionType, HandlerType, Paths) ||
738       Paths.isAmbiguous(Context.getCanonicalType(HandlerType)))
739     return false;
740 
741   // Do this check from a context without privileges.
742   switch (CheckBaseClassAccess(SourceLocation(), HandlerType, ExceptionType,
743                                Paths.front(),
744                                /*Diagnostic*/ 0,
745                                /*ForceCheck*/ true,
746                                /*ForceUnprivileged*/ true)) {
747   case AR_accessible: return true;
748   case AR_inaccessible: return false;
749   case AR_dependent:
750     llvm_unreachable("access check dependent for unprivileged context");
751   case AR_delayed:
752     llvm_unreachable("access check delayed in non-declaration");
753   }
754   llvm_unreachable("unexpected access check result");
755 }
756 
CheckExceptionSpecSubset(const PartialDiagnostic & DiagID,const PartialDiagnostic & NestedDiagID,const PartialDiagnostic & NoteID,const PartialDiagnostic & NoThrowDiagID,const FunctionProtoType * Superset,bool SkipSupersetFirstParameter,SourceLocation SuperLoc,const FunctionProtoType * Subset,bool SkipSubsetFirstParameter,SourceLocation SubLoc)757 bool Sema::CheckExceptionSpecSubset(
758     const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID,
759     const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID,
760     const FunctionProtoType *Superset, bool SkipSupersetFirstParameter,
761     SourceLocation SuperLoc, const FunctionProtoType *Subset,
762     bool SkipSubsetFirstParameter, SourceLocation SubLoc) {
763 
764   // Just auto-succeed under -fno-exceptions.
765   if (!getLangOpts().CXXExceptions)
766     return false;
767 
768   // FIXME: As usual, we could be more specific in our error messages, but
769   // that better waits until we've got types with source locations.
770 
771   if (!SubLoc.isValid())
772     SubLoc = SuperLoc;
773 
774   // Resolve the exception specifications, if needed.
775   Superset = ResolveExceptionSpec(SuperLoc, Superset);
776   if (!Superset)
777     return false;
778   Subset = ResolveExceptionSpec(SubLoc, Subset);
779   if (!Subset)
780     return false;
781 
782   ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
783   ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
784   assert(!isUnresolvedExceptionSpec(SuperEST) &&
785          !isUnresolvedExceptionSpec(SubEST) &&
786          "Shouldn't see unknown exception specifications here");
787 
788   // If there are dependent noexcept specs, assume everything is fine. Unlike
789   // with the equivalency check, this is safe in this case, because we don't
790   // want to merge declarations. Checks after instantiation will catch any
791   // omissions we make here.
792   if (SuperEST == EST_DependentNoexcept || SubEST == EST_DependentNoexcept)
793     return false;
794 
795   CanThrowResult SuperCanThrow = Superset->canThrow();
796   CanThrowResult SubCanThrow = Subset->canThrow();
797 
798   // If the superset contains everything or the subset contains nothing, we're
799   // done.
800   if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) ||
801       SubCanThrow == CT_Cannot)
802     return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset,
803                                    SkipSupersetFirstParameter, SuperLoc, Subset,
804                                    SkipSubsetFirstParameter, SubLoc);
805 
806   // Allow __declspec(nothrow) to be missing on redeclaration as an extension in
807   // some cases.
808   if (NoThrowDiagID.getDiagID() != 0 && SubCanThrow == CT_Can &&
809       SuperCanThrow == CT_Cannot && SuperEST == EST_NoThrow) {
810     Diag(SubLoc, NoThrowDiagID);
811     if (NoteID.getDiagID() != 0)
812       Diag(SuperLoc, NoteID);
813     return true;
814   }
815 
816   // If the subset contains everything or the superset contains nothing, we've
817   // failed.
818   if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) ||
819       SuperCanThrow == CT_Cannot) {
820     Diag(SubLoc, DiagID);
821     if (NoteID.getDiagID() != 0)
822       Diag(SuperLoc, NoteID);
823     return true;
824   }
825 
826   assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic &&
827          "Exception spec subset: non-dynamic case slipped through.");
828 
829   // Neither contains everything or nothing. Do a proper comparison.
830   for (QualType SubI : Subset->exceptions()) {
831     if (const ReferenceType *RefTy = SubI->getAs<ReferenceType>())
832       SubI = RefTy->getPointeeType();
833 
834     // Make sure it's in the superset.
835     bool Contained = false;
836     for (QualType SuperI : Superset->exceptions()) {
837       // [except.spec]p5:
838       //   the target entity shall allow at least the exceptions allowed by the
839       //   source
840       //
841       // We interpret this as meaning that a handler for some target type would
842       // catch an exception of each source type.
843       if (handlerCanCatch(SuperI, SubI)) {
844         Contained = true;
845         break;
846       }
847     }
848     if (!Contained) {
849       Diag(SubLoc, DiagID);
850       if (NoteID.getDiagID() != 0)
851         Diag(SuperLoc, NoteID);
852       return true;
853     }
854   }
855   // We've run half the gauntlet.
856   return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset,
857                                  SkipSupersetFirstParameter, SuperLoc, Subset,
858                                  SkipSupersetFirstParameter, SubLoc);
859 }
860 
861 static bool
CheckSpecForTypesEquivalent(Sema & S,const PartialDiagnostic & DiagID,const PartialDiagnostic & NoteID,QualType Target,SourceLocation TargetLoc,QualType Source,SourceLocation SourceLoc)862 CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID,
863                             const PartialDiagnostic &NoteID, QualType Target,
864                             SourceLocation TargetLoc, QualType Source,
865                             SourceLocation SourceLoc) {
866   const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
867   if (!TFunc)
868     return false;
869   const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
870   if (!SFunc)
871     return false;
872 
873   return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
874                                         SFunc, SourceLoc);
875 }
876 
CheckParamExceptionSpec(const PartialDiagnostic & DiagID,const PartialDiagnostic & NoteID,const FunctionProtoType * Target,bool SkipTargetFirstParameter,SourceLocation TargetLoc,const FunctionProtoType * Source,bool SkipSourceFirstParameter,SourceLocation SourceLoc)877 bool Sema::CheckParamExceptionSpec(
878     const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
879     const FunctionProtoType *Target, bool SkipTargetFirstParameter,
880     SourceLocation TargetLoc, const FunctionProtoType *Source,
881     bool SkipSourceFirstParameter, SourceLocation SourceLoc) {
882   auto RetDiag = DiagID;
883   RetDiag << 0;
884   if (CheckSpecForTypesEquivalent(
885           *this, RetDiag, PDiag(),
886           Target->getReturnType(), TargetLoc, Source->getReturnType(),
887           SourceLoc))
888     return true;
889 
890   // We shouldn't even be testing this unless the arguments are otherwise
891   // compatible.
892   assert((Target->getNumParams() - (unsigned)SkipTargetFirstParameter) ==
893              (Source->getNumParams() - (unsigned)SkipSourceFirstParameter) &&
894          "Functions have different argument counts.");
895   for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) {
896     auto ParamDiag = DiagID;
897     ParamDiag << 1;
898     if (CheckSpecForTypesEquivalent(
899             *this, ParamDiag, PDiag(),
900             Target->getParamType(i + (SkipTargetFirstParameter ? 1 : 0)),
901             TargetLoc, Source->getParamType(SkipSourceFirstParameter ? 1 : 0),
902             SourceLoc))
903       return true;
904   }
905   return false;
906 }
907 
CheckExceptionSpecCompatibility(Expr * From,QualType ToType)908 bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
909   // First we check for applicability.
910   // Target type must be a function, function pointer or function reference.
911   const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
912   if (!ToFunc || ToFunc->hasDependentExceptionSpec())
913     return false;
914 
915   // SourceType must be a function or function pointer.
916   const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
917   if (!FromFunc || FromFunc->hasDependentExceptionSpec())
918     return false;
919 
920   unsigned DiagID = diag::err_incompatible_exception_specs;
921   unsigned NestedDiagID = diag::err_deep_exception_specs_differ;
922   // This is not an error in C++17 onwards, unless the noexceptness doesn't
923   // match, but in that case we have a full-on type mismatch, not just a
924   // type sugar mismatch.
925   if (getLangOpts().CPlusPlus17) {
926     DiagID = diag::warn_incompatible_exception_specs;
927     NestedDiagID = diag::warn_deep_exception_specs_differ;
928   }
929 
930   // Now we've got the correct types on both sides, check their compatibility.
931   // This means that the source of the conversion can only throw a subset of
932   // the exceptions of the target, and any exception specs on arguments or
933   // return types must be equivalent.
934   //
935   // FIXME: If there is a nested dependent exception specification, we should
936   // not be checking it here. This is fine:
937   //   template<typename T> void f() {
938   //     void (*p)(void (*) throw(T));
939   //     void (*q)(void (*) throw(int)) = p;
940   //   }
941   // ... because it might be instantiated with T=int.
942   return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(),
943                                   PDiag(), ToFunc, 0,
944                                   From->getSourceRange().getBegin(), FromFunc,
945                                   0, SourceLocation()) &&
946          !getLangOpts().CPlusPlus17;
947 }
948 
CheckOverridingFunctionExceptionSpec(const CXXMethodDecl * New,const CXXMethodDecl * Old)949 bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
950                                                 const CXXMethodDecl *Old) {
951   // If the new exception specification hasn't been parsed yet, skip the check.
952   // We'll get called again once it's been parsed.
953   if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
954       EST_Unparsed)
955     return false;
956 
957   // Don't check uninstantiated template destructors at all. We can only
958   // synthesize correct specs after the template is instantiated.
959   if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType())
960     return false;
961 
962   // If the old exception specification hasn't been parsed yet, or the new
963   // exception specification can't be computed yet, remember that we need to
964   // perform this check when we get to the end of the outermost
965   // lexically-surrounding class.
966   if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) {
967     DelayedOverridingExceptionSpecChecks.push_back({New, Old});
968     return false;
969   }
970 
971   unsigned DiagID = diag::err_override_exception_spec;
972   if (getLangOpts().MSVCCompat)
973     DiagID = diag::ext_override_exception_spec;
974   return CheckExceptionSpecSubset(
975       PDiag(DiagID), PDiag(diag::err_deep_exception_specs_differ),
976       PDiag(diag::note_overridden_virtual_function),
977       PDiag(diag::ext_override_exception_spec),
978       Old->getType()->castAs<FunctionProtoType>(),
979       Old->hasCXXExplicitFunctionObjectParameter(), Old->getLocation(),
980       New->getType()->castAs<FunctionProtoType>(),
981       New->hasCXXExplicitFunctionObjectParameter(), New->getLocation());
982 }
983 
canSubStmtsThrow(Sema & Self,const Stmt * S)984 static CanThrowResult canSubStmtsThrow(Sema &Self, const Stmt *S) {
985   CanThrowResult R = CT_Cannot;
986   for (const Stmt *SubStmt : S->children()) {
987     if (!SubStmt)
988       continue;
989     R = mergeCanThrow(R, Self.canThrow(SubStmt));
990     if (R == CT_Can)
991       break;
992   }
993   return R;
994 }
995 
canCalleeThrow(Sema & S,const Expr * E,const Decl * D,SourceLocation Loc)996 CanThrowResult Sema::canCalleeThrow(Sema &S, const Expr *E, const Decl *D,
997                                     SourceLocation Loc) {
998   // As an extension, we assume that __attribute__((nothrow)) functions don't
999   // throw.
1000   if (isa_and_nonnull<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
1001     return CT_Cannot;
1002 
1003   QualType T;
1004 
1005   // In C++1z, just look at the function type of the callee.
1006   if (S.getLangOpts().CPlusPlus17 && isa_and_nonnull<CallExpr>(E)) {
1007     E = cast<CallExpr>(E)->getCallee();
1008     T = E->getType();
1009     if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
1010       // Sadly we don't preserve the actual type as part of the "bound member"
1011       // placeholder, so we need to reconstruct it.
1012       E = E->IgnoreParenImpCasts();
1013 
1014       // Could be a call to a pointer-to-member or a plain member access.
1015       if (auto *Op = dyn_cast<BinaryOperator>(E)) {
1016         assert(Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI);
1017         T = Op->getRHS()->getType()
1018               ->castAs<MemberPointerType>()->getPointeeType();
1019       } else {
1020         T = cast<MemberExpr>(E)->getMemberDecl()->getType();
1021       }
1022     }
1023   } else if (const ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D))
1024     T = VD->getType();
1025   else
1026     // If we have no clue what we're calling, assume the worst.
1027     return CT_Can;
1028 
1029   const FunctionProtoType *FT;
1030   if ((FT = T->getAs<FunctionProtoType>())) {
1031   } else if (const PointerType *PT = T->getAs<PointerType>())
1032     FT = PT->getPointeeType()->getAs<FunctionProtoType>();
1033   else if (const ReferenceType *RT = T->getAs<ReferenceType>())
1034     FT = RT->getPointeeType()->getAs<FunctionProtoType>();
1035   else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
1036     FT = MT->getPointeeType()->getAs<FunctionProtoType>();
1037   else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
1038     FT = BT->getPointeeType()->getAs<FunctionProtoType>();
1039 
1040   if (!FT)
1041     return CT_Can;
1042 
1043   if (Loc.isValid() || (Loc.isInvalid() && E))
1044     FT = S.ResolveExceptionSpec(Loc.isInvalid() ? E->getBeginLoc() : Loc, FT);
1045   if (!FT)
1046     return CT_Can;
1047 
1048   return FT->canThrow();
1049 }
1050 
canVarDeclThrow(Sema & Self,const VarDecl * VD)1051 static CanThrowResult canVarDeclThrow(Sema &Self, const VarDecl *VD) {
1052   CanThrowResult CT = CT_Cannot;
1053 
1054   // Initialization might throw.
1055   if (!VD->isUsableInConstantExpressions(Self.Context))
1056     if (const Expr *Init = VD->getInit())
1057       CT = mergeCanThrow(CT, Self.canThrow(Init));
1058 
1059   // Destructor might throw.
1060   if (VD->needsDestruction(Self.Context) == QualType::DK_cxx_destructor) {
1061     if (auto *RD =
1062             VD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
1063       if (auto *Dtor = RD->getDestructor()) {
1064         CT = mergeCanThrow(
1065             CT, Sema::canCalleeThrow(Self, nullptr, Dtor, VD->getLocation()));
1066       }
1067     }
1068   }
1069 
1070   // If this is a decomposition declaration, bindings might throw.
1071   if (auto *DD = dyn_cast<DecompositionDecl>(VD))
1072     for (auto *B : DD->bindings())
1073       if (auto *HD = B->getHoldingVar())
1074         CT = mergeCanThrow(CT, canVarDeclThrow(Self, HD));
1075 
1076   return CT;
1077 }
1078 
canDynamicCastThrow(const CXXDynamicCastExpr * DC)1079 static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
1080   if (DC->isTypeDependent())
1081     return CT_Dependent;
1082 
1083   if (!DC->getTypeAsWritten()->isReferenceType())
1084     return CT_Cannot;
1085 
1086   if (DC->getSubExpr()->isTypeDependent())
1087     return CT_Dependent;
1088 
1089   return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
1090 }
1091 
canTypeidThrow(Sema & S,const CXXTypeidExpr * DC)1092 static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
1093   // A typeid of a type is a constant and does not throw.
1094   if (DC->isTypeOperand())
1095     return CT_Cannot;
1096 
1097   if (DC->isValueDependent())
1098     return CT_Dependent;
1099 
1100   // If this operand is not evaluated it cannot possibly throw.
1101   if (!DC->isPotentiallyEvaluated())
1102     return CT_Cannot;
1103 
1104   // Can throw std::bad_typeid if a nullptr is dereferenced.
1105   if (DC->hasNullCheck())
1106     return CT_Can;
1107 
1108   return S.canThrow(DC->getExprOperand());
1109 }
1110 
canThrow(const Stmt * S)1111 CanThrowResult Sema::canThrow(const Stmt *S) {
1112   // C++ [expr.unary.noexcept]p3:
1113   //   [Can throw] if in a potentially-evaluated context the expression would
1114   //   contain:
1115   switch (S->getStmtClass()) {
1116   case Expr::ConstantExprClass:
1117     return canThrow(cast<ConstantExpr>(S)->getSubExpr());
1118 
1119   case Expr::CXXThrowExprClass:
1120     //   - a potentially evaluated throw-expression
1121     return CT_Can;
1122 
1123   case Expr::CXXDynamicCastExprClass: {
1124     //   - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
1125     //     where T is a reference type, that requires a run-time check
1126     auto *CE = cast<CXXDynamicCastExpr>(S);
1127     // FIXME: Properly determine whether a variably-modified type can throw.
1128     if (CE->getType()->isVariablyModifiedType())
1129       return CT_Can;
1130     CanThrowResult CT = canDynamicCastThrow(CE);
1131     if (CT == CT_Can)
1132       return CT;
1133     return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
1134   }
1135 
1136   case Expr::CXXTypeidExprClass:
1137     //   - a potentially evaluated typeid expression applied to a (possibly
1138     //     parenthesized) built-in unary * operator applied to a pointer to a
1139     //     polymorphic class type
1140     return canTypeidThrow(*this, cast<CXXTypeidExpr>(S));
1141 
1142     //   - a potentially evaluated call to a function, member function, function
1143     //     pointer, or member function pointer that does not have a non-throwing
1144     //     exception-specification
1145   case Expr::CallExprClass:
1146   case Expr::CXXMemberCallExprClass:
1147   case Expr::CXXOperatorCallExprClass:
1148   case Expr::UserDefinedLiteralClass: {
1149     const CallExpr *CE = cast<CallExpr>(S);
1150     CanThrowResult CT;
1151     if (CE->isTypeDependent())
1152       CT = CT_Dependent;
1153     else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
1154       CT = CT_Cannot;
1155     else
1156       CT = canCalleeThrow(*this, CE, CE->getCalleeDecl());
1157     if (CT == CT_Can)
1158       return CT;
1159     return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
1160   }
1161 
1162   case Expr::CXXConstructExprClass:
1163   case Expr::CXXTemporaryObjectExprClass: {
1164     auto *CE = cast<CXXConstructExpr>(S);
1165     // FIXME: Properly determine whether a variably-modified type can throw.
1166     if (CE->getType()->isVariablyModifiedType())
1167       return CT_Can;
1168     CanThrowResult CT = canCalleeThrow(*this, CE, CE->getConstructor());
1169     if (CT == CT_Can)
1170       return CT;
1171     return mergeCanThrow(CT, canSubStmtsThrow(*this, CE));
1172   }
1173 
1174   case Expr::CXXInheritedCtorInitExprClass: {
1175     auto *ICIE = cast<CXXInheritedCtorInitExpr>(S);
1176     return canCalleeThrow(*this, ICIE, ICIE->getConstructor());
1177   }
1178 
1179   case Expr::LambdaExprClass: {
1180     const LambdaExpr *Lambda = cast<LambdaExpr>(S);
1181     CanThrowResult CT = CT_Cannot;
1182     for (LambdaExpr::const_capture_init_iterator
1183              Cap = Lambda->capture_init_begin(),
1184              CapEnd = Lambda->capture_init_end();
1185          Cap != CapEnd; ++Cap)
1186       CT = mergeCanThrow(CT, canThrow(*Cap));
1187     return CT;
1188   }
1189 
1190   case Expr::CXXNewExprClass: {
1191     auto *NE = cast<CXXNewExpr>(S);
1192     CanThrowResult CT;
1193     if (NE->isTypeDependent())
1194       CT = CT_Dependent;
1195     else
1196       CT = canCalleeThrow(*this, NE, NE->getOperatorNew());
1197     if (CT == CT_Can)
1198       return CT;
1199     return mergeCanThrow(CT, canSubStmtsThrow(*this, NE));
1200   }
1201 
1202   case Expr::CXXDeleteExprClass: {
1203     auto *DE = cast<CXXDeleteExpr>(S);
1204     CanThrowResult CT;
1205     QualType DTy = DE->getDestroyedType();
1206     if (DTy.isNull() || DTy->isDependentType()) {
1207       CT = CT_Dependent;
1208     } else {
1209       CT = canCalleeThrow(*this, DE, DE->getOperatorDelete());
1210       if (const RecordType *RT = DTy->getAs<RecordType>()) {
1211         const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
1212         const CXXDestructorDecl *DD = RD->getDestructor();
1213         if (DD)
1214           CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD));
1215       }
1216       if (CT == CT_Can)
1217         return CT;
1218     }
1219     return mergeCanThrow(CT, canSubStmtsThrow(*this, DE));
1220   }
1221 
1222   case Expr::CXXBindTemporaryExprClass: {
1223     auto *BTE = cast<CXXBindTemporaryExpr>(S);
1224     // The bound temporary has to be destroyed again, which might throw.
1225     CanThrowResult CT =
1226         canCalleeThrow(*this, BTE, BTE->getTemporary()->getDestructor());
1227     if (CT == CT_Can)
1228       return CT;
1229     return mergeCanThrow(CT, canSubStmtsThrow(*this, BTE));
1230   }
1231 
1232   case Expr::PseudoObjectExprClass: {
1233     auto *POE = cast<PseudoObjectExpr>(S);
1234     CanThrowResult CT = CT_Cannot;
1235     for (const Expr *E : POE->semantics()) {
1236       CT = mergeCanThrow(CT, canThrow(E));
1237       if (CT == CT_Can)
1238         break;
1239     }
1240     return CT;
1241   }
1242 
1243     // ObjC message sends are like function calls, but never have exception
1244     // specs.
1245   case Expr::ObjCMessageExprClass:
1246   case Expr::ObjCPropertyRefExprClass:
1247   case Expr::ObjCSubscriptRefExprClass:
1248     return CT_Can;
1249 
1250     // All the ObjC literals that are implemented as calls are
1251     // potentially throwing unless we decide to close off that
1252     // possibility.
1253   case Expr::ObjCArrayLiteralClass:
1254   case Expr::ObjCDictionaryLiteralClass:
1255   case Expr::ObjCBoxedExprClass:
1256     return CT_Can;
1257 
1258     // Many other things have subexpressions, so we have to test those.
1259     // Some are simple:
1260   case Expr::CoawaitExprClass:
1261   case Expr::ConditionalOperatorClass:
1262   case Expr::CoyieldExprClass:
1263   case Expr::CXXRewrittenBinaryOperatorClass:
1264   case Expr::CXXStdInitializerListExprClass:
1265   case Expr::DesignatedInitExprClass:
1266   case Expr::DesignatedInitUpdateExprClass:
1267   case Expr::ExprWithCleanupsClass:
1268   case Expr::ExtVectorElementExprClass:
1269   case Expr::InitListExprClass:
1270   case Expr::ArrayInitLoopExprClass:
1271   case Expr::MemberExprClass:
1272   case Expr::ObjCIsaExprClass:
1273   case Expr::ObjCIvarRefExprClass:
1274   case Expr::ParenExprClass:
1275   case Expr::ParenListExprClass:
1276   case Expr::ShuffleVectorExprClass:
1277   case Expr::StmtExprClass:
1278   case Expr::ConvertVectorExprClass:
1279   case Expr::VAArgExprClass:
1280   case Expr::CXXParenListInitExprClass:
1281     return canSubStmtsThrow(*this, S);
1282 
1283   case Expr::CompoundLiteralExprClass:
1284   case Expr::CXXConstCastExprClass:
1285   case Expr::CXXAddrspaceCastExprClass:
1286   case Expr::CXXReinterpretCastExprClass:
1287   case Expr::BuiltinBitCastExprClass:
1288       // FIXME: Properly determine whether a variably-modified type can throw.
1289     if (cast<Expr>(S)->getType()->isVariablyModifiedType())
1290       return CT_Can;
1291     return canSubStmtsThrow(*this, S);
1292 
1293     // Some might be dependent for other reasons.
1294   case Expr::ArraySubscriptExprClass:
1295   case Expr::MatrixSubscriptExprClass:
1296   case Expr::ArraySectionExprClass:
1297   case Expr::OMPArrayShapingExprClass:
1298   case Expr::OMPIteratorExprClass:
1299   case Expr::BinaryOperatorClass:
1300   case Expr::DependentCoawaitExprClass:
1301   case Expr::CompoundAssignOperatorClass:
1302   case Expr::CStyleCastExprClass:
1303   case Expr::CXXStaticCastExprClass:
1304   case Expr::CXXFunctionalCastExprClass:
1305   case Expr::ImplicitCastExprClass:
1306   case Expr::MaterializeTemporaryExprClass:
1307   case Expr::UnaryOperatorClass: {
1308     // FIXME: Properly determine whether a variably-modified type can throw.
1309     if (auto *CE = dyn_cast<CastExpr>(S))
1310       if (CE->getType()->isVariablyModifiedType())
1311         return CT_Can;
1312     CanThrowResult CT =
1313         cast<Expr>(S)->isTypeDependent() ? CT_Dependent : CT_Cannot;
1314     return mergeCanThrow(CT, canSubStmtsThrow(*this, S));
1315   }
1316 
1317   case Expr::CXXDefaultArgExprClass:
1318     return canThrow(cast<CXXDefaultArgExpr>(S)->getExpr());
1319 
1320   case Expr::CXXDefaultInitExprClass:
1321     return canThrow(cast<CXXDefaultInitExpr>(S)->getExpr());
1322 
1323   case Expr::ChooseExprClass: {
1324     auto *CE = cast<ChooseExpr>(S);
1325     if (CE->isTypeDependent() || CE->isValueDependent())
1326       return CT_Dependent;
1327     return canThrow(CE->getChosenSubExpr());
1328   }
1329 
1330   case Expr::GenericSelectionExprClass:
1331     if (cast<GenericSelectionExpr>(S)->isResultDependent())
1332       return CT_Dependent;
1333     return canThrow(cast<GenericSelectionExpr>(S)->getResultExpr());
1334 
1335     // Some expressions are always dependent.
1336   case Expr::CXXDependentScopeMemberExprClass:
1337   case Expr::CXXUnresolvedConstructExprClass:
1338   case Expr::DependentScopeDeclRefExprClass:
1339   case Expr::CXXFoldExprClass:
1340   case Expr::RecoveryExprClass:
1341     return CT_Dependent;
1342 
1343   case Expr::AsTypeExprClass:
1344   case Expr::BinaryConditionalOperatorClass:
1345   case Expr::BlockExprClass:
1346   case Expr::CUDAKernelCallExprClass:
1347   case Expr::DeclRefExprClass:
1348   case Expr::ObjCBridgedCastExprClass:
1349   case Expr::ObjCIndirectCopyRestoreExprClass:
1350   case Expr::ObjCProtocolExprClass:
1351   case Expr::ObjCSelectorExprClass:
1352   case Expr::ObjCAvailabilityCheckExprClass:
1353   case Expr::OffsetOfExprClass:
1354   case Expr::PackExpansionExprClass:
1355   case Expr::SubstNonTypeTemplateParmExprClass:
1356   case Expr::SubstNonTypeTemplateParmPackExprClass:
1357   case Expr::FunctionParmPackExprClass:
1358   case Expr::UnaryExprOrTypeTraitExprClass:
1359   case Expr::UnresolvedLookupExprClass:
1360   case Expr::UnresolvedMemberExprClass:
1361   case Expr::TypoExprClass:
1362     // FIXME: Many of the above can throw.
1363     return CT_Cannot;
1364 
1365   case Expr::AddrLabelExprClass:
1366   case Expr::ArrayTypeTraitExprClass:
1367   case Expr::AtomicExprClass:
1368   case Expr::TypeTraitExprClass:
1369   case Expr::CXXBoolLiteralExprClass:
1370   case Expr::CXXNoexceptExprClass:
1371   case Expr::CXXNullPtrLiteralExprClass:
1372   case Expr::CXXPseudoDestructorExprClass:
1373   case Expr::CXXScalarValueInitExprClass:
1374   case Expr::CXXThisExprClass:
1375   case Expr::CXXUuidofExprClass:
1376   case Expr::CharacterLiteralClass:
1377   case Expr::ExpressionTraitExprClass:
1378   case Expr::FloatingLiteralClass:
1379   case Expr::GNUNullExprClass:
1380   case Expr::ImaginaryLiteralClass:
1381   case Expr::ImplicitValueInitExprClass:
1382   case Expr::IntegerLiteralClass:
1383   case Expr::FixedPointLiteralClass:
1384   case Expr::ArrayInitIndexExprClass:
1385   case Expr::NoInitExprClass:
1386   case Expr::ObjCEncodeExprClass:
1387   case Expr::ObjCStringLiteralClass:
1388   case Expr::ObjCBoolLiteralExprClass:
1389   case Expr::OpaqueValueExprClass:
1390   case Expr::PredefinedExprClass:
1391   case Expr::SizeOfPackExprClass:
1392   case Expr::PackIndexingExprClass:
1393   case Expr::StringLiteralClass:
1394   case Expr::SourceLocExprClass:
1395   case Expr::EmbedExprClass:
1396   case Expr::ConceptSpecializationExprClass:
1397   case Expr::RequiresExprClass:
1398     // These expressions can never throw.
1399     return CT_Cannot;
1400 
1401   case Expr::MSPropertyRefExprClass:
1402   case Expr::MSPropertySubscriptExprClass:
1403     llvm_unreachable("Invalid class for expression");
1404 
1405     // Most statements can throw if any substatement can throw.
1406   case Stmt::OpenACCComputeConstructClass:
1407   case Stmt::OpenACCLoopConstructClass:
1408   case Stmt::AttributedStmtClass:
1409   case Stmt::BreakStmtClass:
1410   case Stmt::CapturedStmtClass:
1411   case Stmt::CaseStmtClass:
1412   case Stmt::CompoundStmtClass:
1413   case Stmt::ContinueStmtClass:
1414   case Stmt::CoreturnStmtClass:
1415   case Stmt::CoroutineBodyStmtClass:
1416   case Stmt::CXXCatchStmtClass:
1417   case Stmt::CXXForRangeStmtClass:
1418   case Stmt::DefaultStmtClass:
1419   case Stmt::DoStmtClass:
1420   case Stmt::ForStmtClass:
1421   case Stmt::GCCAsmStmtClass:
1422   case Stmt::GotoStmtClass:
1423   case Stmt::IndirectGotoStmtClass:
1424   case Stmt::LabelStmtClass:
1425   case Stmt::MSAsmStmtClass:
1426   case Stmt::MSDependentExistsStmtClass:
1427   case Stmt::NullStmtClass:
1428   case Stmt::ObjCAtCatchStmtClass:
1429   case Stmt::ObjCAtFinallyStmtClass:
1430   case Stmt::ObjCAtSynchronizedStmtClass:
1431   case Stmt::ObjCAutoreleasePoolStmtClass:
1432   case Stmt::ObjCForCollectionStmtClass:
1433   case Stmt::OMPAtomicDirectiveClass:
1434   case Stmt::OMPBarrierDirectiveClass:
1435   case Stmt::OMPCancelDirectiveClass:
1436   case Stmt::OMPCancellationPointDirectiveClass:
1437   case Stmt::OMPCriticalDirectiveClass:
1438   case Stmt::OMPDistributeDirectiveClass:
1439   case Stmt::OMPDistributeParallelForDirectiveClass:
1440   case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1441   case Stmt::OMPDistributeSimdDirectiveClass:
1442   case Stmt::OMPFlushDirectiveClass:
1443   case Stmt::OMPDepobjDirectiveClass:
1444   case Stmt::OMPScanDirectiveClass:
1445   case Stmt::OMPForDirectiveClass:
1446   case Stmt::OMPForSimdDirectiveClass:
1447   case Stmt::OMPMasterDirectiveClass:
1448   case Stmt::OMPMasterTaskLoopDirectiveClass:
1449   case Stmt::OMPMaskedTaskLoopDirectiveClass:
1450   case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1451   case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1452   case Stmt::OMPOrderedDirectiveClass:
1453   case Stmt::OMPCanonicalLoopClass:
1454   case Stmt::OMPParallelDirectiveClass:
1455   case Stmt::OMPParallelForDirectiveClass:
1456   case Stmt::OMPParallelForSimdDirectiveClass:
1457   case Stmt::OMPParallelMasterDirectiveClass:
1458   case Stmt::OMPParallelMaskedDirectiveClass:
1459   case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1460   case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1461   case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1462   case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1463   case Stmt::OMPParallelSectionsDirectiveClass:
1464   case Stmt::OMPSectionDirectiveClass:
1465   case Stmt::OMPSectionsDirectiveClass:
1466   case Stmt::OMPSimdDirectiveClass:
1467   case Stmt::OMPTileDirectiveClass:
1468   case Stmt::OMPUnrollDirectiveClass:
1469   case Stmt::OMPReverseDirectiveClass:
1470   case Stmt::OMPInterchangeDirectiveClass:
1471   case Stmt::OMPSingleDirectiveClass:
1472   case Stmt::OMPTargetDataDirectiveClass:
1473   case Stmt::OMPTargetDirectiveClass:
1474   case Stmt::OMPTargetEnterDataDirectiveClass:
1475   case Stmt::OMPTargetExitDataDirectiveClass:
1476   case Stmt::OMPTargetParallelDirectiveClass:
1477   case Stmt::OMPTargetParallelForDirectiveClass:
1478   case Stmt::OMPTargetParallelForSimdDirectiveClass:
1479   case Stmt::OMPTargetSimdDirectiveClass:
1480   case Stmt::OMPTargetTeamsDirectiveClass:
1481   case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1482   case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1483   case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1484   case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1485   case Stmt::OMPTargetUpdateDirectiveClass:
1486   case Stmt::OMPScopeDirectiveClass:
1487   case Stmt::OMPTaskDirectiveClass:
1488   case Stmt::OMPTaskgroupDirectiveClass:
1489   case Stmt::OMPTaskLoopDirectiveClass:
1490   case Stmt::OMPTaskLoopSimdDirectiveClass:
1491   case Stmt::OMPTaskwaitDirectiveClass:
1492   case Stmt::OMPTaskyieldDirectiveClass:
1493   case Stmt::OMPErrorDirectiveClass:
1494   case Stmt::OMPTeamsDirectiveClass:
1495   case Stmt::OMPTeamsDistributeDirectiveClass:
1496   case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1497   case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1498   case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1499   case Stmt::OMPInteropDirectiveClass:
1500   case Stmt::OMPDispatchDirectiveClass:
1501   case Stmt::OMPMaskedDirectiveClass:
1502   case Stmt::OMPMetaDirectiveClass:
1503   case Stmt::OMPGenericLoopDirectiveClass:
1504   case Stmt::OMPTeamsGenericLoopDirectiveClass:
1505   case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1506   case Stmt::OMPParallelGenericLoopDirectiveClass:
1507   case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1508   case Stmt::ReturnStmtClass:
1509   case Stmt::SEHExceptStmtClass:
1510   case Stmt::SEHFinallyStmtClass:
1511   case Stmt::SEHLeaveStmtClass:
1512   case Stmt::SEHTryStmtClass:
1513   case Stmt::SwitchStmtClass:
1514   case Stmt::WhileStmtClass:
1515     return canSubStmtsThrow(*this, S);
1516 
1517   case Stmt::DeclStmtClass: {
1518     CanThrowResult CT = CT_Cannot;
1519     for (const Decl *D : cast<DeclStmt>(S)->decls()) {
1520       if (auto *VD = dyn_cast<VarDecl>(D))
1521         CT = mergeCanThrow(CT, canVarDeclThrow(*this, VD));
1522 
1523       // FIXME: Properly determine whether a variably-modified type can throw.
1524       if (auto *TND = dyn_cast<TypedefNameDecl>(D))
1525         if (TND->getUnderlyingType()->isVariablyModifiedType())
1526           return CT_Can;
1527       if (auto *VD = dyn_cast<ValueDecl>(D))
1528         if (VD->getType()->isVariablyModifiedType())
1529           return CT_Can;
1530     }
1531     return CT;
1532   }
1533 
1534   case Stmt::IfStmtClass: {
1535     auto *IS = cast<IfStmt>(S);
1536     CanThrowResult CT = CT_Cannot;
1537     if (const Stmt *Init = IS->getInit())
1538       CT = mergeCanThrow(CT, canThrow(Init));
1539     if (const Stmt *CondDS = IS->getConditionVariableDeclStmt())
1540       CT = mergeCanThrow(CT, canThrow(CondDS));
1541     CT = mergeCanThrow(CT, canThrow(IS->getCond()));
1542 
1543     // For 'if constexpr', consider only the non-discarded case.
1544     // FIXME: We should add a DiscardedStmt marker to the AST.
1545     if (std::optional<const Stmt *> Case = IS->getNondiscardedCase(Context))
1546       return *Case ? mergeCanThrow(CT, canThrow(*Case)) : CT;
1547 
1548     CanThrowResult Then = canThrow(IS->getThen());
1549     CanThrowResult Else = IS->getElse() ? canThrow(IS->getElse()) : CT_Cannot;
1550     if (Then == Else)
1551       return mergeCanThrow(CT, Then);
1552 
1553     // For a dependent 'if constexpr', the result is dependent if it depends on
1554     // the value of the condition.
1555     return mergeCanThrow(CT, IS->isConstexpr() ? CT_Dependent
1556                                                : mergeCanThrow(Then, Else));
1557   }
1558 
1559   case Stmt::CXXTryStmtClass: {
1560     auto *TS = cast<CXXTryStmt>(S);
1561     // try /*...*/ catch (...) { H } can throw only if H can throw.
1562     // Any other try-catch can throw if any substatement can throw.
1563     const CXXCatchStmt *FinalHandler = TS->getHandler(TS->getNumHandlers() - 1);
1564     if (!FinalHandler->getExceptionDecl())
1565       return canThrow(FinalHandler->getHandlerBlock());
1566     return canSubStmtsThrow(*this, S);
1567   }
1568 
1569   case Stmt::ObjCAtThrowStmtClass:
1570     return CT_Can;
1571 
1572   case Stmt::ObjCAtTryStmtClass: {
1573     auto *TS = cast<ObjCAtTryStmt>(S);
1574 
1575     // @catch(...) need not be last in Objective-C. Walk backwards until we
1576     // see one or hit the @try.
1577     CanThrowResult CT = CT_Cannot;
1578     if (const Stmt *Finally = TS->getFinallyStmt())
1579       CT = mergeCanThrow(CT, canThrow(Finally));
1580     for (unsigned I = TS->getNumCatchStmts(); I != 0; --I) {
1581       const ObjCAtCatchStmt *Catch = TS->getCatchStmt(I - 1);
1582       CT = mergeCanThrow(CT, canThrow(Catch));
1583       // If we reach a @catch(...), no earlier exceptions can escape.
1584       if (Catch->hasEllipsis())
1585         return CT;
1586     }
1587 
1588     // Didn't find an @catch(...). Exceptions from the @try body can escape.
1589     return mergeCanThrow(CT, canThrow(TS->getTryBody()));
1590   }
1591 
1592   case Stmt::SYCLUniqueStableNameExprClass:
1593     return CT_Cannot;
1594   case Stmt::NoStmtClass:
1595     llvm_unreachable("Invalid class for statement");
1596   }
1597   llvm_unreachable("Bogus StmtClass");
1598 }
1599 
1600 } // end namespace clang
1601