@@ -468,6 +468,10 @@ class SourceMappingRegion {
468
468
// / The region's ending location.
469
469
std::optional<SourceLoc> EndLoc;
470
470
471
+ // / Whether the region is within a macro expansion. Such regions do not
472
+ // / get recorded, but are needed to track the counters within the expansion.
473
+ bool IsInMacroExpansion = false ;
474
+
471
475
SourceMappingRegion (Kind RegionKind, std::optional<CounterExpr> Counter,
472
476
std::optional<SourceLoc> StartLoc)
473
477
: RegionKind(RegionKind), Counter(Counter), StartLoc(StartLoc) {
@@ -516,6 +520,14 @@ class SourceMappingRegion {
516
520
SourceMappingRegion (SourceMappingRegion &&Region) = default ;
517
521
SourceMappingRegion &operator =(SourceMappingRegion &&RHS) = default ;
518
522
523
+ bool isInMacroExpansion () const {
524
+ return IsInMacroExpansion;
525
+ }
526
+
527
+ void setIsInMacroExpansion () {
528
+ IsInMacroExpansion = true ;
529
+ }
530
+
519
531
// / Whether this region is for scoping only.
520
532
bool isForScopingOnly () const { return RegionKind == Kind::ScopingOnly; }
521
533
@@ -837,6 +849,12 @@ struct CoverageMapping : public ASTWalker {
837
849
838
850
Stmt *ImplicitTopLevelBody = nullptr ;
839
851
852
+ // / The number of parent MacroExpansionExprs.
853
+ unsigned MacroDepth = 0 ;
854
+
855
+ // / Whether the current walk is within a macro expansion.
856
+ bool isInMacroExpansion () const { return MacroDepth > 0 ; }
857
+
840
858
// / Return true if \c Ref has an associated counter.
841
859
bool hasCounter (ProfileCounterRef Ref) { return CounterExprs.count (Ref); }
842
860
@@ -993,6 +1011,10 @@ struct CoverageMapping : public ASTWalker {
993
1011
994
1012
// / Push a region onto the stack.
995
1013
void pushRegion (SourceMappingRegion Region) {
1014
+ // Note on the region whether we're currently in a macro expansion.
1015
+ if (isInMacroExpansion ())
1016
+ Region.setIsInMacroExpansion ();
1017
+
996
1018
LLVM_DEBUG ({
997
1019
llvm::dbgs () << " Pushed region: " ;
998
1020
Region.print (llvm::dbgs (), SM);
@@ -1027,6 +1049,11 @@ struct CoverageMapping : public ASTWalker {
1027
1049
llvm::dbgs () << " \n " ;
1028
1050
});
1029
1051
1052
+ // Don't record regions in macro expansions, they don't have source
1053
+ // locations that can be meaningfully mapped to source code.
1054
+ if (Region.isInMacroExpansion ())
1055
+ return ;
1056
+
1030
1057
// Don't bother recording regions that are only present for scoping.
1031
1058
if (Region.isForScopingOnly ())
1032
1059
return ;
@@ -1141,16 +1168,29 @@ struct CoverageMapping : public ASTWalker {
1141
1168
if (SourceRegions.empty ())
1142
1169
return nullptr ;
1143
1170
1144
- using MappedRegion = SILCoverageMap::MappedRegion;
1171
+ auto FileSourceRange = SM.getRangeForBuffer (*SF->getBufferID ());
1172
+ auto isLocInFile = [&](SourceLoc Loc) {
1173
+ return FileSourceRange.contains (Loc) || FileSourceRange.getEnd () == Loc;
1174
+ };
1145
1175
1176
+ using MappedRegion = SILCoverageMap::MappedRegion;
1146
1177
std::vector<MappedRegion> Regions;
1147
1178
SourceRange OuterRange;
1148
1179
for (const auto &Region : SourceRegions) {
1149
1180
assert (Region.hasStartLoc () && " invalid region" );
1150
1181
assert (Region.hasEndLoc () && " incomplete region" );
1151
1182
1152
- // Build up the outer range from the union of all coverage regions.
1153
1183
SourceRange Range (Region.getStartLoc (), Region.getEndLoc ());
1184
+
1185
+ // Make sure we haven't ended up with any source locations outside the
1186
+ // SourceFile (e.g for generated code such as macros), asserting in an
1187
+ // asserts build, dropping in a non-asserts build.
1188
+ if (!isLocInFile (Range.Start ) || !isLocInFile (Range.End )) {
1189
+ assert (false && " range outside of file" );
1190
+ continue ;
1191
+ }
1192
+
1193
+ // Build up the outer range from the union of all coverage regions.
1154
1194
if (!OuterRange) {
1155
1195
OuterRange = Range;
1156
1196
} else {
@@ -1522,10 +1562,14 @@ struct CoverageMapping : public ASTWalker {
1522
1562
1523
1563
if (hasCounter (E)) {
1524
1564
pushRegion (SourceMappingRegion::forNode (E, SM));
1525
- } else if (isa<OptionalTryExpr>(E)) {
1565
+ } else if (isa<OptionalTryExpr>(E) || isa<MacroExpansionExpr>(E) ) {
1526
1566
// If we have a `try?`, that doesn't already have a counter, record it
1527
1567
// as a scoping-only region. We need it to scope child error branches,
1528
1568
// but don't need it in the resulting set of regions.
1569
+ //
1570
+ // If we have a macro expansion, also push a scoping-only region. We'll
1571
+ // discard any regions recorded within the macro, but will adjust for any
1572
+ // control flow that may have happened within the macro.
1529
1573
assignCounter (E, getCurrentCounter ());
1530
1574
pushRegion (SourceMappingRegion::scopingOnly (E, SM));
1531
1575
}
@@ -1560,6 +1604,10 @@ struct CoverageMapping : public ASTWalker {
1560
1604
// Already visited the children.
1561
1605
return Action::SkipChildren (TE);
1562
1606
}
1607
+
1608
+ if (isa<MacroExpansionExpr>(E))
1609
+ MacroDepth += 1 ;
1610
+
1563
1611
return shouldWalkIntoExpr (E, Parent, Constant);
1564
1612
}
1565
1613
@@ -1576,6 +1624,11 @@ struct CoverageMapping : public ASTWalker {
1576
1624
Lexer::getLocForEndOfToken (SM, E->getEndLoc ()));
1577
1625
}
1578
1626
1627
+ if (isa<MacroExpansionExpr>(E)) {
1628
+ assert (isInMacroExpansion ());
1629
+ MacroDepth -= 1 ;
1630
+ }
1631
+
1579
1632
if (hasCounter (E))
1580
1633
exitRegion (E);
1581
1634
0 commit comments