@@ -259,8 +259,6 @@ struct MapRegionCounters : public ASTWalker {
259
259
mapRegion (RWS->getBody ());
260
260
} else if (auto *FES = dyn_cast<ForEachStmt>(S)) {
261
261
mapRegion (FES->getBody ());
262
- } else if (auto *SS = dyn_cast<SwitchStmt>(S)) {
263
- mapRegion (SS);
264
262
} else if (auto *CS = dyn_cast<CaseStmt>(S)) {
265
263
mapRegion (getProfilerStmtForCase (CS));
266
264
}
@@ -647,8 +645,6 @@ struct PGOMapping : public ASTWalker {
647
645
} else if (auto *FES = dyn_cast<ForEachStmt>(S)) {
648
646
setKnownExecutionCount (FES->getBody ());
649
647
setExecutionCount (FES, parentCount);
650
- } else if (auto *SS = dyn_cast<SwitchStmt>(S)) {
651
- setKnownExecutionCount (SS);
652
648
} else if (auto *CS = dyn_cast<CaseStmt>(S)) {
653
649
setKnownExecutionCount (getProfilerStmtForCase (CS));
654
650
}
@@ -695,6 +691,9 @@ struct PGOMapping : public ASTWalker {
695
691
}
696
692
};
697
693
694
+ // / Produce coverage mapping information for a function. This involves taking
695
+ // / the counters computed by MapRegionCounters, and annotating the source with
696
+ // / regions that are defined in terms of those counters.
698
697
struct CoverageMapping : public ASTWalker {
699
698
private:
700
699
const SourceManager &SM;
@@ -820,17 +819,7 @@ struct CoverageMapping : public ASTWalker {
820
819
if (ControlFlowAdjust)
821
820
Count = &createCounter (CounterExpr::Sub (*Count, *ControlFlowAdjust));
822
821
823
- if (Count->isSemanticallyZero ()) {
824
- // If the counter is semantically zero, form an 'incomplete' region with
825
- // no starting location. This prevents forming unreachable regions unless
826
- // there is a following statement or expression to extend the region.
827
- RegionStack.emplace_back (ASTNode (), *Count, None, None);
828
- } else {
829
- // Otherwise, we have a non-zero counter, so form a new region starting
830
- // at the end of the previous scope. This ensures the user covers both
831
- // branches of a condition.
832
- RegionStack.emplace_back (ASTNode (), *Count, getEndLoc (Scope), None);
833
- }
822
+ replaceCount (Count, getEndLoc (Scope));
834
823
}
835
824
836
825
// / Push a region covering \c Node onto the stack.
@@ -844,10 +833,24 @@ struct CoverageMapping : public ASTWalker {
844
833
});
845
834
}
846
835
847
- // / Replace the current region's count by pushing an incomplete region.
848
- void replaceCount (CounterExpr &&Expr, Optional<SourceLoc> Start = None) {
849
- CounterExpr &Counter = createCounter (std::move (Expr));
850
- RegionStack.emplace_back (ASTNode (), Counter, Start, None);
836
+ // / Replace the current region at \p Start with a new counter. If \p Start is
837
+ // / \c None, or the counter is semantically zero, an 'incomplete' region is
838
+ // / formed, which is not recorded unless followed by additional AST nodes.
839
+ void replaceCount (CounterExpr *Counter, Optional<SourceLoc> Start) {
840
+ // If the counter is semantically zero, form an 'incomplete' region with
841
+ // no starting location. This prevents forming unreachable regions unless
842
+ // there is a following statement or expression to extend the region.
843
+ if (Start && Counter->isSemanticallyZero ())
844
+ Start = None;
845
+
846
+ RegionStack.emplace_back (ASTNode (), *Counter, Start, None);
847
+ }
848
+
849
+ // / Replace the current region at \p Start with a new counter. If \p Start is
850
+ // / \c None, or the counter is semantically zero, an 'incomplete' region is
851
+ // / formed, which is not recorded unless followed by additional AST nodes.
852
+ void replaceCount (CounterExpr &&Expr, Optional<SourceLoc> Start) {
853
+ replaceCount (&createCounter (std::move (Expr)), Start);
851
854
}
852
855
853
856
// / Get the location for the end of the last token in \c Node.
@@ -909,7 +912,7 @@ struct CoverageMapping : public ASTWalker {
909
912
SourceMappingRegion &Region = getRegion ();
910
913
if (!Region.hasEndLoc ())
911
914
Region.setEndLoc (getEndLoc (S));
912
- replaceCount (CounterExpr::Zero ());
915
+ replaceCount (CounterExpr::Zero (), /* Start */ None );
913
916
}
914
917
915
918
Expr *getConditionNode (StmtCondition SC) {
@@ -976,6 +979,8 @@ struct CoverageMapping : public ASTWalker {
976
979
if (S->isImplicit () && S != ImplicitTopLevelBody)
977
980
return {true , S};
978
981
982
+ // If we're in an 'incomplete' region, update it to include this node. This
983
+ // ensures we only create the region if needed.
979
984
if (!RegionStack.empty ())
980
985
extendRegion (S);
981
986
@@ -986,7 +991,13 @@ struct CoverageMapping : public ASTWalker {
986
991
} else if (auto *IS = dyn_cast<IfStmt>(S)) {
987
992
if (auto *Cond = getConditionNode (IS->getCond ()))
988
993
assignCounter (Cond, CounterExpr::Ref (getCurrentCounter ()));
994
+
995
+ // The counter for the if statement itself tracks the number of jumps to
996
+ // it by break statements.
989
997
assignCounter (IS, CounterExpr::Zero ());
998
+
999
+ // We emit a counter for the then block, and define the else block in
1000
+ // terms of it.
990
1001
CounterExpr &ThenCounter = assignCounter (IS->getThenStmt ());
991
1002
if (IS->getElseStmt ())
992
1003
assignCounter (IS->getElseStmt (),
@@ -996,23 +1007,38 @@ struct CoverageMapping : public ASTWalker {
996
1007
assignCounter (GS->getBody ());
997
1008
998
1009
} else if (auto *WS = dyn_cast<WhileStmt>(S)) {
1010
+ // The counter for the while statement itself tracks the number of jumps
1011
+ // to it by break and continue statements.
999
1012
assignCounter (WS, CounterExpr::Zero ());
1013
+
1000
1014
if (auto *E = getConditionNode (WS->getCond ()))
1001
1015
assignCounter (E, CounterExpr::Ref (getCurrentCounter ()));
1002
1016
assignCounter (WS->getBody ());
1003
1017
1004
1018
} else if (auto *RWS = dyn_cast<RepeatWhileStmt>(S)) {
1019
+ // The counter for the while statement itself tracks the number of jumps
1020
+ // to it by break and continue statements.
1005
1021
assignCounter (RWS, CounterExpr::Zero ());
1022
+
1006
1023
CounterExpr &BodyCounter = assignCounter (RWS->getBody ());
1007
1024
assignCounter (RWS->getCond (), CounterExpr::Ref (BodyCounter));
1008
1025
RepeatWhileStack.push_back (RWS);
1009
1026
1010
1027
} else if (auto *FES = dyn_cast<ForEachStmt>(S)) {
1028
+ // The counter for the for statement itself tracks the number of jumps
1029
+ // to it by break and continue statements.
1011
1030
assignCounter (FES, CounterExpr::Zero ());
1012
1031
assignCounter (FES->getBody ());
1013
1032
1014
1033
} else if (auto *SS = dyn_cast<SwitchStmt>(S)) {
1015
- assignCounter (SS);
1034
+ // The counter for the switch statement itself tracks the number of jumps
1035
+ // to it by break statements, including the implicit breaks at the end of
1036
+ // cases.
1037
+ assignCounter (SS, CounterExpr::Zero ());
1038
+
1039
+ assignCounter (SS->getSubjectExpr (),
1040
+ CounterExpr::Ref (getCurrentCounter ()));
1041
+
1016
1042
// Assign counters for cases so they're available for fallthrough.
1017
1043
for (CaseStmt *Case : SS->getCases ())
1018
1044
assignCounter (Case);
@@ -1021,7 +1047,10 @@ struct CoverageMapping : public ASTWalker {
1021
1047
if (caseStmt->getParentKind () == CaseParentKind::Switch)
1022
1048
pushRegion (S);
1023
1049
} else if (auto *DS = dyn_cast<DoStmt>(S)) {
1050
+ // The counter for the do statement itself tracks the number of jumps
1051
+ // to it by break statements.
1024
1052
assignCounter (DS, CounterExpr::Zero ());
1053
+
1025
1054
assignCounter (DS->getBody (), CounterExpr::Ref (getCurrentCounter ()));
1026
1055
1027
1056
} else if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
@@ -1075,7 +1104,8 @@ struct CoverageMapping : public ASTWalker {
1075
1104
Stmt *BreakTarget = BS->getTarget ();
1076
1105
if (auto *RWS = dyn_cast<RepeatWhileStmt>(BreakTarget)) {
1077
1106
subtractFromCounter (RWS->getCond (), getCurrentCounter ());
1078
- } else if (!isa<SwitchStmt>(BreakTarget)) {
1107
+ } else {
1108
+ // Update the exit counter for the target.
1079
1109
addToCounter (BS->getTarget (), getCurrentCounter ());
1080
1110
}
1081
1111
@@ -1093,9 +1123,12 @@ struct CoverageMapping : public ASTWalker {
1093
1123
replaceCount (CounterExpr::Ref (getCounter (S)), getEndLoc (S));
1094
1124
1095
1125
} else if (auto caseStmt = dyn_cast<CaseStmt>(S)) {
1096
- if (caseStmt->getParentKind () == CaseParentKind::Switch)
1126
+ if (caseStmt->getParentKind () == CaseParentKind::Switch) {
1127
+ // The end of a case block is an implicit break, update the exit
1128
+ // counter to reflect this.
1129
+ addToCounter (caseStmt->getParentStmt (), getCurrentCounter ());
1097
1130
popRegions (S);
1098
-
1131
+ }
1099
1132
} else if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
1100
1133
assert (DoCatchStack.back () == DCS && " Malformed do-catch stack" );
1101
1134
DoCatchStack.pop_back ();
@@ -1125,6 +1158,8 @@ struct CoverageMapping : public ASTWalker {
1125
1158
if (isa<AbstractClosureExpr>(E) && !Parent.isNull ())
1126
1159
return {false , E};
1127
1160
1161
+ // If we're in an 'incomplete' region, update it to include this node. This
1162
+ // ensures we only create the region if needed.
1128
1163
if (!RegionStack.empty ())
1129
1164
extendRegion (E);
1130
1165
0 commit comments