@@ -468,6 +468,10 @@ class SourceMappingRegion {
468468 // / The region's ending location.
469469 std::optional<SourceLoc> EndLoc;
470470
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+
471475 SourceMappingRegion (Kind RegionKind, std::optional<CounterExpr> Counter,
472476 std::optional<SourceLoc> StartLoc)
473477 : RegionKind(RegionKind), Counter(Counter), StartLoc(StartLoc) {
@@ -516,6 +520,14 @@ class SourceMappingRegion {
516520 SourceMappingRegion (SourceMappingRegion &&Region) = default ;
517521 SourceMappingRegion &operator =(SourceMappingRegion &&RHS) = default ;
518522
523+ bool isInMacroExpansion () const {
524+ return IsInMacroExpansion;
525+ }
526+
527+ void setIsInMacroExpansion () {
528+ IsInMacroExpansion = true ;
529+ }
530+
519531 // / Whether this region is for scoping only.
520532 bool isForScopingOnly () const { return RegionKind == Kind::ScopingOnly; }
521533
@@ -837,6 +849,12 @@ struct CoverageMapping : public ASTWalker {
837849
838850 Stmt *ImplicitTopLevelBody = nullptr ;
839851
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+
840858 // / Return true if \c Ref has an associated counter.
841859 bool hasCounter (ProfileCounterRef Ref) { return CounterExprs.count (Ref); }
842860
@@ -993,6 +1011,10 @@ struct CoverageMapping : public ASTWalker {
9931011
9941012 // / Push a region onto the stack.
9951013 void pushRegion (SourceMappingRegion Region) {
1014+ // Note on the region whether we're currently in a macro expansion.
1015+ if (isInMacroExpansion ())
1016+ Region.setIsInMacroExpansion ();
1017+
9961018 LLVM_DEBUG ({
9971019 llvm::dbgs () << " Pushed region: " ;
9981020 Region.print (llvm::dbgs (), SM);
@@ -1027,6 +1049,11 @@ struct CoverageMapping : public ASTWalker {
10271049 llvm::dbgs () << " \n " ;
10281050 });
10291051
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+
10301057 // Don't bother recording regions that are only present for scoping.
10311058 if (Region.isForScopingOnly ())
10321059 return ;
@@ -1141,16 +1168,29 @@ struct CoverageMapping : public ASTWalker {
11411168 if (SourceRegions.empty ())
11421169 return nullptr ;
11431170
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+ };
11451175
1176+ using MappedRegion = SILCoverageMap::MappedRegion;
11461177 std::vector<MappedRegion> Regions;
11471178 SourceRange OuterRange;
11481179 for (const auto &Region : SourceRegions) {
11491180 assert (Region.hasStartLoc () && " invalid region" );
11501181 assert (Region.hasEndLoc () && " incomplete region" );
11511182
1152- // Build up the outer range from the union of all coverage regions.
11531183 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.
11541194 if (!OuterRange) {
11551195 OuterRange = Range;
11561196 } else {
@@ -1522,10 +1562,14 @@ struct CoverageMapping : public ASTWalker {
15221562
15231563 if (hasCounter (E)) {
15241564 pushRegion (SourceMappingRegion::forNode (E, SM));
1525- } else if (isa<OptionalTryExpr>(E)) {
1565+ } else if (isa<OptionalTryExpr>(E) || isa<MacroExpansionExpr>(E) ) {
15261566 // If we have a `try?`, that doesn't already have a counter, record it
15271567 // as a scoping-only region. We need it to scope child error branches,
15281568 // 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.
15291573 assignCounter (E, getCurrentCounter ());
15301574 pushRegion (SourceMappingRegion::scopingOnly (E, SM));
15311575 }
@@ -1560,6 +1604,10 @@ struct CoverageMapping : public ASTWalker {
15601604 // Already visited the children.
15611605 return Action::SkipChildren (TE);
15621606 }
1607+
1608+ if (isa<MacroExpansionExpr>(E))
1609+ MacroDepth += 1 ;
1610+
15631611 return shouldWalkIntoExpr (E, Parent, Constant);
15641612 }
15651613
@@ -1576,6 +1624,11 @@ struct CoverageMapping : public ASTWalker {
15761624 Lexer::getLocForEndOfToken (SM, E->getEndLoc ()));
15771625 }
15781626
1627+ if (isa<MacroExpansionExpr>(E)) {
1628+ assert (isInMacroExpansion ());
1629+ MacroDepth -= 1 ;
1630+ }
1631+
15791632 if (hasCounter (E))
15801633 exitRegion (E);
15811634
0 commit comments