@@ -262,6 +262,28 @@ static bool shouldWalkIntoUnhandledDecl(const Decl *D) {
262262 return isa<PatternBindingDecl>(D);
263263}
264264
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+
265287// / An ASTWalker that maps ASTNodes to profiling counters.
266288struct MapRegionCounters : public ASTWalker {
267289 // / The SIL function being profiled.
@@ -355,7 +377,26 @@ struct MapRegionCounters : public ASTWalker {
355377 if (isa<LazyInitializerExpr>(E))
356378 mapRegion (E);
357379
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);
359400 }
360401};
361402
@@ -809,7 +850,26 @@ struct PGOMapping : public ASTWalker {
809850 if (isa<LazyInitializerExpr>(E))
810851 setKnownExecutionCount (E);
811852
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);
813873 }
814874};
815875
@@ -1379,11 +1439,10 @@ struct CoverageMapping : public ASTWalker {
13791439 }
13801440 auto WalkResult = shouldWalkIntoExpr (E, Parent, Constant);
13811441 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 .
13841444 // FIXME: The ASTWalker should do a post-visit.
1385- if (hasCounter (E))
1386- popRegions (E);
1445+ walkToExprPost (E);
13871446 }
13881447 return WalkResult;
13891448 }
@@ -1395,6 +1454,15 @@ struct CoverageMapping : public ASTWalker {
13951454 if (hasCounter (E))
13961455 popRegions (E);
13971456
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+
13981466 return Action::Continue (E);
13991467 }
14001468};
0 commit comments