@@ -196,6 +196,13 @@ static bool skipExpr(Expr *E) {
196196 return !E->getStartLoc ().isValid () || !E->getEndLoc ().isValid ();
197197}
198198
199+ // / Whether the children of an unmapped decl should still be walked.
200+ static bool shouldWalkUnmappedDecl (const Decl *D) {
201+ // We want to walk into the initializer for a pattern binding decl. This
202+ // allows us to map LazyInitializerExprs.
203+ return isa<PatternBindingDecl>(D);
204+ }
205+
199206// / An ASTWalker that maps ASTNodes to profiling counters.
200207struct MapRegionCounters : public ASTWalker {
201208 // / The next counter value to assign.
@@ -207,6 +214,12 @@ struct MapRegionCounters : public ASTWalker {
207214 MapRegionCounters (llvm::DenseMap<ASTNode, unsigned > &CounterMap)
208215 : CounterMap(CounterMap) {}
209216
217+ LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
218+ // We want to walk lazy initializers present in the synthesized getter for
219+ // a lazy variable.
220+ return LazyInitializerWalking::InAccessor;
221+ }
222+
210223 void mapRegion (ASTNode N) {
211224 CounterMap[N] = NextCounter;
212225
@@ -225,7 +238,7 @@ struct MapRegionCounters : public ASTWalker {
225238
226239 bool walkToDeclPre (Decl *D) override {
227240 if (isUnmapped (D))
228- return false ;
241+ return shouldWalkUnmappedDecl (D) ;
229242
230243 if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
231244 return visitFunctionDecl (*this , AFD, [&] { mapRegion (AFD->getBody ()); });
@@ -274,14 +287,8 @@ struct MapRegionCounters : public ASTWalker {
274287 mapRegion (IE->getThenExpr ());
275288 }
276289
277- // rdar://42792053
278- // TODO: There's an outstanding issue here with LazyInitializerExpr. A LIE
279- // is copied into the body of a property getter after type-checking (before
280- // coverage). ASTWalker only visits this expression once via the property's
281- // VarDecl, and does not visit it again within the getter. This results in
282- // missing coverage. SILGen treats the init expr as part of the getter, but
283- // its SILProfiler has no information about the init because the LIE isn't
284- // visited here.
290+ if (isa<LazyInitializerExpr>(E))
291+ mapRegion (E);
285292
286293 return {true , E};
287294 }
@@ -579,7 +586,7 @@ struct PGOMapping : public ASTWalker {
579586
580587 bool walkToDeclPre (Decl *D) override {
581588 if (isUnmapped (D))
582- return false ;
589+ return shouldWalkUnmappedDecl (D) ;
583590 if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
584591 return visitFunctionDecl (*this , AFD, [&] {
585592 setKnownExecutionCount (AFD->getBody ());
@@ -591,6 +598,12 @@ struct PGOMapping : public ASTWalker {
591598 return true ;
592599 }
593600
601+ LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
602+ // We want to walk lazy initializers present in the synthesized getter for
603+ // a lazy variable.
604+ return LazyInitializerWalking::InAccessor;
605+ }
606+
594607 std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
595608 unsigned parent = getParentCounter ();
596609 auto parentCount = LoadedCounts.Counts [parent];
@@ -674,6 +687,9 @@ struct PGOMapping : public ASTWalker {
674687 }
675688 setExecutionCount (elseExpr, subtract (count, thenCount));
676689 }
690+ if (isa<LazyInitializerExpr>(E))
691+ setKnownExecutionCount (E);
692+
677693 return {true , E};
678694 }
679695};
@@ -903,6 +919,12 @@ struct CoverageMapping : public ASTWalker {
903919public:
904920 CoverageMapping (const SourceManager &SM) : SM(SM) {}
905921
922+ LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
923+ // We want to walk lazy initializers present in the synthesized getter for
924+ // a lazy variable.
925+ return LazyInitializerWalking::InAccessor;
926+ }
927+
906928 // / Generate the coverage counter mapping regions from collected
907929 // / source regions.
908930 SILCoverageMap *emitSourceRegions (
@@ -930,7 +952,7 @@ struct CoverageMapping : public ASTWalker {
930952
931953 bool walkToDeclPre (Decl *D) override {
932954 if (isUnmapped (D))
933- return false ;
955+ return shouldWalkUnmappedDecl (D) ;
934956
935957 if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
936958 return visitFunctionDecl (*this , AFD, [&] {
@@ -1124,6 +1146,9 @@ struct CoverageMapping : public ASTWalker {
11241146 }
11251147 }
11261148
1149+ if (isa<LazyInitializerExpr>(E))
1150+ assignCounter (E);
1151+
11271152 if (hasCounter (E) && !Parent.isNull ())
11281153 pushRegion (E);
11291154 return {true , E};
0 commit comments