@@ -262,6 +262,28 @@ static bool shouldWalkIntoUnhandledDecl(const Decl *D) {
262
262
return isa<PatternBindingDecl>(D);
263
263
}
264
264
265
+ // / Whether the expression \c E could potentially throw an error.
266
+ static bool mayExpressionThrow (const Expr *E) {
267
+ if (auto *AE = dyn_cast<ApplyExpr>(E)) {
268
+ // Throws if the function throws.
269
+ return bool (AE->throws ());
270
+ }
271
+ if (auto *S = dyn_cast<SubscriptExpr>(E)) {
272
+ // Throws if subscript has a throwing getter.
273
+ auto *SD = cast<SubscriptDecl>(S->getDecl ().getDecl ());
274
+ if (auto *accessor = SD->getEffectfulGetAccessor ())
275
+ return accessor->hasThrows ();
276
+ }
277
+ if (auto *DE = dyn_cast<DeclRefExpr>(E)) {
278
+ if (auto *VD = dyn_cast<VarDecl>(DE->getDecl ())) {
279
+ // Throws if the getter throws.
280
+ if (auto *accessor = VD->getEffectfulGetAccessor ())
281
+ return accessor->hasThrows ();
282
+ }
283
+ }
284
+ return false ;
285
+ }
286
+
265
287
// / An ASTWalker that maps ASTNodes to profiling counters.
266
288
struct MapRegionCounters : public ASTWalker {
267
289
// / The SIL function being profiled.
@@ -355,7 +377,26 @@ struct MapRegionCounters : public ASTWalker {
355
377
if (isa<LazyInitializerExpr>(E))
356
378
mapRegion (E);
357
379
358
- return shouldWalkIntoExpr (E, Parent, Constant);
380
+ auto WalkResult = shouldWalkIntoExpr (E, Parent, Constant);
381
+ if (WalkResult.Action .Action == PreWalkAction::SkipChildren) {
382
+ // We need to manually do the post-visit here since the ASTWalker will
383
+ // skip it.
384
+ // FIXME: The ASTWalker should do a post-visit.
385
+ walkToExprPost (E);
386
+ }
387
+ return WalkResult;
388
+ }
389
+
390
+ PostWalkResult<Expr *> walkToExprPost (Expr *E) override {
391
+ if (shouldSkipExpr (E))
392
+ return Action::Continue (E);
393
+
394
+ // If we have an expr that may throw an error, give it a counter for the
395
+ // error branch.
396
+ if (mayExpressionThrow (E))
397
+ mapRegion (ProfileCounterRef::errorBranchOf (E));
398
+
399
+ return Action::Continue (E);
359
400
}
360
401
};
361
402
@@ -809,7 +850,26 @@ struct PGOMapping : public ASTWalker {
809
850
if (isa<LazyInitializerExpr>(E))
810
851
setKnownExecutionCount (E);
811
852
812
- return shouldWalkIntoExpr (E, Parent, Constant);
853
+ auto WalkResult = shouldWalkIntoExpr (E, Parent, Constant);
854
+ if (WalkResult.Action .Action == PreWalkAction::SkipChildren) {
855
+ // We need to manually do the post-visit here since the ASTWalker will
856
+ // skip it.
857
+ // FIXME: The ASTWalker should do a post-visit.
858
+ walkToExprPost (E);
859
+ }
860
+ return WalkResult;
861
+ }
862
+
863
+ PostWalkResult<Expr *> walkToExprPost (Expr *E) override {
864
+ if (shouldSkipExpr (E))
865
+ return Action::Continue (E);
866
+
867
+ // If we have an expr that may throw an error, give it a counter for the
868
+ // error branch.
869
+ if (mayExpressionThrow (E))
870
+ setKnownExecutionCount (ProfileCounterRef::errorBranchOf (E));
871
+
872
+ return Action::Continue (E);
813
873
}
814
874
};
815
875
@@ -1379,11 +1439,10 @@ struct CoverageMapping : public ASTWalker {
1379
1439
}
1380
1440
auto WalkResult = shouldWalkIntoExpr (E, Parent, Constant);
1381
1441
if (WalkResult.Action .Action == PreWalkAction::SkipChildren) {
1382
- // We need to manually pop the region here as the ASTWalker won't call
1383
- // the post-visitation .
1442
+ // We need to manually do the post-visit here since the ASTWalker will
1443
+ // skip it .
1384
1444
// FIXME: The ASTWalker should do a post-visit.
1385
- if (hasCounter (E))
1386
- popRegions (E);
1445
+ walkToExprPost (E);
1387
1446
}
1388
1447
return WalkResult;
1389
1448
}
@@ -1395,6 +1454,15 @@ struct CoverageMapping : public ASTWalker {
1395
1454
if (hasCounter (E))
1396
1455
popRegions (E);
1397
1456
1457
+ // The region following the expression gets current counter minus the
1458
+ // error branch counter, i.e the number of times we didn't throw an error.
1459
+ if (!RegionStack.empty () && mayExpressionThrow (E)) {
1460
+ auto ThrowCount = assignKnownCounter (ProfileCounterRef::errorBranchOf (E));
1461
+ replaceCount (
1462
+ CounterExpr::Sub (getCurrentCounter (), ThrowCount, CounterAlloc),
1463
+ Lexer::getLocForEndOfToken (SM, E->getEndLoc ()));
1464
+ }
1465
+
1398
1466
return Action::Continue (E);
1399
1467
}
1400
1468
};
0 commit comments