@@ -217,6 +217,10 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
217
217
OS << " <Entry>Multi</Entry>\n " ;
218
218
}
219
219
220
+ if (ThrowingUnhandledError) {
221
+ OS << " <Error>Throwing</Error>\n " ;
222
+ }
223
+
220
224
if (Orphan != OrphanKind::None) {
221
225
OS << " <Orphan>" ;
222
226
switch (Orphan) {
@@ -260,6 +264,43 @@ bool ReferencedDecl::operator==(const ReferencedDecl& Other) {
260
264
return VD == Other.VD && Ty.getPointer () == Other.Ty .getPointer ();
261
265
}
262
266
267
+ static bool hasUnhandledError (ArrayRef<ASTNode> Nodes) {
268
+ class ThrowingEntityAnalyzer : public SourceEntityWalker {
269
+ bool Throwing;
270
+ public:
271
+ ThrowingEntityAnalyzer (): Throwing(false ) {}
272
+ bool walkToStmtPre (Stmt *S) override {
273
+ if (auto DCS = dyn_cast<DoCatchStmt>(S)) {
274
+ if (DCS->isSyntacticallyExhaustive ())
275
+ return false ;
276
+ Throwing = true ;
277
+ } else if (auto TS = dyn_cast<ThrowStmt>(S)) {
278
+ Throwing = true ;
279
+ }
280
+ return !Throwing;
281
+ }
282
+ bool walkToExprPre (Expr *E) override {
283
+ if (auto TE = dyn_cast<TryExpr>(E)) {
284
+ Throwing = true ;
285
+ }
286
+ return !Throwing;
287
+ }
288
+ bool walkToDeclPre (Decl *D, CharSourceRange Range) override {
289
+ return false ;
290
+ }
291
+ bool walkToDeclPost (Decl *D) override { return !Throwing; }
292
+ bool walkToStmtPost (Stmt *S) override { return !Throwing; }
293
+ bool walkToExprPost (Expr *E) override { return !Throwing; }
294
+ bool isThrowing () { return Throwing; }
295
+ };
296
+
297
+ return Nodes.end () != std::find_if (Nodes.begin (), Nodes.end (), [](ASTNode N) {
298
+ ThrowingEntityAnalyzer Analyzer;
299
+ N.walk (Analyzer);
300
+ return Analyzer.isThrowing ();
301
+ });
302
+ }
303
+
263
304
struct RangeResolver ::Implementation {
264
305
SourceFile &File;
265
306
ASTContext &Ctx;
@@ -319,24 +360,28 @@ struct RangeResolver::Implementation {
319
360
assert (ContainedASTNodes.size () == 1 );
320
361
// Single node implies single entry point, or is it?
321
362
bool SingleEntry = true ;
363
+ bool UnhandledError = hasUnhandledError ({Node});
322
364
OrphanKind Kind = getOrphanKind (ContainedASTNodes);
323
365
if (Node.is <Expr*>())
324
366
return ResolvedRangeInfo (RangeKind::SingleExpression,
325
367
resolveNodeType (Node), Content,
326
- getImmediateContext (), SingleEntry, Kind,
368
+ getImmediateContext (), SingleEntry,
369
+ UnhandledError, Kind,
327
370
llvm::makeArrayRef (ContainedASTNodes),
328
371
llvm::makeArrayRef (DeclaredDecls),
329
372
llvm::makeArrayRef (ReferencedDecls));
330
373
else if (Node.is <Stmt*>())
331
374
return ResolvedRangeInfo (RangeKind::SingleStatement, resolveNodeType (Node),
332
- Content, getImmediateContext (), SingleEntry, Kind,
375
+ Content, getImmediateContext (), SingleEntry,
376
+ UnhandledError, Kind,
333
377
llvm::makeArrayRef (ContainedASTNodes),
334
378
llvm::makeArrayRef (DeclaredDecls),
335
379
llvm::makeArrayRef (ReferencedDecls));
336
380
else {
337
381
assert (Node.is <Decl*>());
338
382
return ResolvedRangeInfo (RangeKind::SingleDecl, Type (), Content,
339
- getImmediateContext (), SingleEntry, Kind,
383
+ getImmediateContext (), SingleEntry,
384
+ UnhandledError, Kind,
340
385
llvm::makeArrayRef (ContainedASTNodes),
341
386
llvm::makeArrayRef (DeclaredDecls),
342
387
llvm::makeArrayRef (ReferencedDecls));
@@ -606,6 +651,7 @@ struct RangeResolver::Implementation {
606
651
/* Last node has the type */
607
652
resolveNodeType (DCInfo.EndMatches .back ()), Content,
608
653
getImmediateContext (), hasSingleEntryPoint (ContainedASTNodes),
654
+ hasUnhandledError (ContainedASTNodes),
609
655
getOrphanKind (ContainedASTNodes),
610
656
llvm::makeArrayRef (ContainedASTNodes),
611
657
llvm::makeArrayRef (DeclaredDecls),
0 commit comments