Coverage Report

Created: 2024-01-17 10:31

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