@@ -876,22 +876,28 @@ struct CoverageMapping : public ASTWalker {
876
876
// / Adjust the count for control flow when exiting a scope.
877
877
void adjustForNonLocalExits (ASTNode Scope,
878
878
llvm::Optional<CounterExpr> ControlFlowAdjust) {
879
- if (Parent.getAsDecl ())
879
+ // If there are no regions left, there's nothing to adjust.
880
+ if (RegionStack.empty ())
880
881
return ;
881
882
883
+ // If the region is for a brace, check to see if we have a parent labeled
884
+ // statement, in which case the exit count needs to account for any direct
885
+ // jumps to it though e.g break statements.
882
886
llvm::Optional<CounterExpr> JumpsToLabel;
883
- if (auto *ParentStmt = Parent.getAsStmt ()) {
884
- if (auto *DCS = dyn_cast<DoCatchStmt>(ParentStmt)) {
885
- // We need to handle the brace of a DoCatchStmt here specially,
886
- // applying the same logic we apply to the catch clauses (handled by
887
- // the CaseStmt logic), we add on the exit count of the branch to the
888
- // statement's exit count.
889
- addToCounter (DCS, getExitCounter ());
890
- return ;
891
- }
887
+ if (Scope.isStmt (StmtKind::Brace)) {
888
+ if (auto *ParentStmt = Parent.getAsStmt ()) {
889
+ if (auto *DCS = dyn_cast<DoCatchStmt>(ParentStmt)) {
890
+ // We need to handle the brace of a DoCatchStmt here specially,
891
+ // applying the same logic we apply to the catch clauses (handled by
892
+ // the CaseStmt logic), we add on the exit count of the branch to the
893
+ // statement's exit count.
894
+ addToCounter (DCS, getExitCounter ());
895
+ return ;
896
+ }
892
897
893
- if (auto *LS = dyn_cast<LabeledStmt>(ParentStmt))
894
- JumpsToLabel = getCounter (LS);
898
+ if (auto *LS = dyn_cast<LabeledStmt>(ParentStmt))
899
+ JumpsToLabel = getCounter (LS);
900
+ }
895
901
}
896
902
897
903
if (!ControlFlowAdjust && !JumpsToLabel)
@@ -942,46 +948,55 @@ struct CoverageMapping : public ASTWalker {
942
948
return Lexer::getLocForEndOfToken (SM, Node.getEndLoc ());
943
949
}
944
950
951
+ // / Record a popped region in the resulting list of regions.
952
+ void takePoppedRegion (SourceMappingRegion &&Region, SourceLoc ParentEndLoc) {
953
+ LLVM_DEBUG ({
954
+ llvm::dbgs () << " Popped region: " ;
955
+ Region.print (llvm::dbgs (), SM);
956
+ llvm::dbgs () << " \n " ;
957
+ });
958
+
959
+ // Don't record incomplete regions.
960
+ if (!Region.hasStartLoc ())
961
+ return ;
962
+
963
+ // Set the region end location to the end location of the parent.
964
+ if (!Region.hasEndLoc ())
965
+ Region.setEndLoc (ParentEndLoc);
966
+
967
+ // If the range ended up being empty, ignore it (this can happen when we
968
+ // replace the counter, and don't extend the region any further).
969
+ if (!Region.hasNonEmptyRange ())
970
+ return ;
971
+
972
+ SourceRegions.push_back (std::move (Region));
973
+ }
974
+
945
975
// / Pop regions from the stack into the function's list of regions.
946
976
// /
947
977
// / Adds all regions from \c ParentNode to the top of the stack to the
948
978
// / function's \c SourceRegions.
949
979
void popRegions (ASTNode ParentNode) {
950
- auto I = RegionStack. begin (), E = RegionStack. end ();
951
- while (I != E &&
952
- I-> getNode (). getOpaqueValue () != ParentNode. getOpaqueValue ())
953
- ++I ;
980
+ auto I = llvm::find_if (RegionStack, [&]( const SourceMappingRegion &Region) {
981
+ return Region. getNode (). getOpaqueValue () == ParentNode. getOpaqueValue ();
982
+ });
983
+ auto E = RegionStack. end () ;
954
984
assert (I != E && " parent not in stack" );
955
- auto ParentIt = I;
956
- SourceLoc EndLoc = ParentIt->getEndLoc ();
957
- assert (ParentIt->hasNonEmptyRange () && " Pushed node with empty range?" );
958
-
959
- unsigned FirstPoppedIndex = SourceRegions.size ();
960
- (void )FirstPoppedIndex;
961
- SourceRegions.push_back (std::move (*I++));
962
- for (; I != E; ++I) {
963
- if (!I->hasStartLoc ())
964
- continue ;
965
- if (!I->hasEndLoc ())
966
- I->setEndLoc (EndLoc);
967
-
968
- // If the range ended up being empty, ignore it (this can happen when we
969
- // replace the counter, and don't extend the region any further).
970
- if (!I->hasNonEmptyRange ())
971
- continue ;
972
-
973
- SourceRegions.push_back (std::move (*I));
974
- }
985
+ assert (I->hasNonEmptyRange () && " Pushed node with empty range?" );
975
986
976
- LLVM_DEBUG ({
977
- for (unsigned Idx = FirstPoppedIndex; Idx < SourceRegions.size (); ++Idx) {
978
- llvm::dbgs () << " Popped region: " ;
979
- SourceRegions[Idx].print (llvm::dbgs (), SM);
980
- llvm::dbgs () << " \n " ;
981
- }
982
- });
987
+ auto EndLoc = I->getEndLoc ();
988
+ for (auto &Region : llvm::make_range (I, E))
989
+ takePoppedRegion (std::move (Region), EndLoc);
983
990
984
- RegionStack.erase (ParentIt, E);
991
+ RegionStack.erase (I, E);
992
+ }
993
+
994
+ // / Exit the given region, popping it and its children from the region stack,
995
+ // / and adjusting the following counter if needed.
996
+ void exitRegion (ASTNode Node) {
997
+ auto Adjust = setExitCount (Node);
998
+ popRegions (Node);
999
+ adjustForNonLocalExits (Node, Adjust);
985
1000
}
986
1001
987
1002
// / Return the currently active region.
@@ -1217,11 +1232,8 @@ struct CoverageMapping : public ASTWalker {
1217
1232
return Action::Continue (S);
1218
1233
1219
1234
if (isa<BraceStmt>(S)) {
1220
- if (hasCounter (S)) {
1221
- auto Adjust = setExitCount (S);
1222
- popRegions (S);
1223
- adjustForNonLocalExits (S, Adjust);
1224
- }
1235
+ if (hasCounter (S))
1236
+ exitRegion (S);
1225
1237
1226
1238
} else if (auto *WS = dyn_cast<WhileStmt>(S)) {
1227
1239
// Update the condition with the backedge count.
@@ -1339,18 +1351,18 @@ struct CoverageMapping : public ASTWalker {
1339
1351
if (shouldSkipExpr (E))
1340
1352
return Action::Continue (E);
1341
1353
1342
- if (hasCounter (E))
1343
- popRegions (E);
1344
-
1345
- // The region following the expression gets current counter minus the
1346
- // error branch counter, i.e the number of times we didn't throw an error.
1347
- if (!RegionStack.empty () && mayExpressionThrow (E)) {
1354
+ // The region following the expression gets current counter minus the error
1355
+ // branch counter, i.e the number of times we didn't throw an error.
1356
+ if (mayExpressionThrow (E)) {
1348
1357
auto ThrowCount = assignKnownCounter (ProfileCounterRef::errorBranchOf (E));
1349
1358
replaceCount (
1350
1359
CounterExpr::Sub (getCurrentCounter (), ThrowCount, CounterBuilder),
1351
1360
Lexer::getLocForEndOfToken (SM, E->getEndLoc ()));
1352
1361
}
1353
1362
1363
+ if (hasCounter (E))
1364
+ exitRegion (E);
1365
+
1354
1366
return Action::Continue (E);
1355
1367
}
1356
1368
};
0 commit comments