summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CoverageMappingGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp107
1 files changed, 76 insertions, 31 deletions
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 2d84464635942..35962c73d9a82 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -67,7 +67,7 @@ public:
void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
- SourceLocation getStartLoc() const {
+ SourceLocation getBeginLoc() const {
assert(LocStart && "Region has no start location");
return *LocStart;
}
@@ -116,7 +116,7 @@ struct SpellingRegion {
}
SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
- : SpellingRegion(SM, R.getStartLoc(), R.getEndLoc()) {}
+ : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
/// Check if the start and end locations appear in source order, i.e
/// top->bottom, left->right.
@@ -204,7 +204,7 @@ public:
/// Get the start of \c S ignoring macro arguments and builtin macros.
SourceLocation getStart(const Stmt *S) {
- SourceLocation Loc = S->getLocStart();
+ SourceLocation Loc = S->getBeginLoc();
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
return Loc;
@@ -212,7 +212,7 @@ public:
/// Get the end of \c S ignoring macro arguments and builtin macros.
SourceLocation getEnd(const Stmt *S) {
- SourceLocation Loc = S->getLocEnd();
+ SourceLocation Loc = S->getEndLoc();
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
return getPreciseTokenLocEnd(Loc);
@@ -229,7 +229,7 @@ public:
llvm::SmallSet<FileID, 8> Visited;
SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
for (const auto &Region : SourceRegions) {
- SourceLocation Loc = Region.getStartLoc();
+ SourceLocation Loc = Region.getBeginLoc();
FileID File = SM.getFileID(Loc);
if (!Visited.insert(File).second)
continue;
@@ -311,7 +311,7 @@ public:
for (const auto &Region : SourceRegions) {
assert(Region.hasEndLoc() && "incomplete region");
- SourceLocation LocStart = Region.getStartLoc();
+ SourceLocation LocStart = Region.getBeginLoc();
assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
// Ignore regions from system headers.
@@ -502,7 +502,7 @@ struct CounterCoverageMappingBuilder
DeferredRegion = None;
// If the region ends in an expansion, find the expansion site.
- FileID StartFile = SM.getFileID(DR.getStartLoc());
+ FileID StartFile = SM.getFileID(DR.getBeginLoc());
if (SM.getFileID(DeferredEndLoc) != StartFile) {
if (isNestedIn(DeferredEndLoc, StartFile)) {
do {
@@ -515,12 +515,12 @@ struct CounterCoverageMappingBuilder
// The parent of this deferred region ends where the containing decl ends,
// so the region isn't useful.
- if (DR.getStartLoc() == DeferredEndLoc)
+ if (DR.getBeginLoc() == DeferredEndLoc)
return Index;
// If we're visiting statements in non-source order (e.g switch cases or
// a loop condition) we can't construct a sensible deferred region.
- if (!SpellingRegion(SM, DR.getStartLoc(), DeferredEndLoc).isInSourceOrder())
+ if (!SpellingRegion(SM, DR.getBeginLoc(), DeferredEndLoc).isInSourceOrder())
return Index;
DR.setGap(true);
@@ -552,6 +552,15 @@ struct CounterCoverageMappingBuilder
completeDeferred(Count, DeferredEndLoc);
}
+ size_t locationDepth(SourceLocation Loc) {
+ size_t Depth = 0;
+ while (Loc.isValid()) {
+ Loc = getIncludeOrExpansionLoc(Loc);
+ Depth++;
+ }
+ return Depth;
+ }
+
/// Pop regions from the stack into the function's list of regions.
///
/// Adds all regions from \c ParentIndex to the top of the stack to the
@@ -562,23 +571,45 @@ struct CounterCoverageMappingBuilder
while (RegionStack.size() > ParentIndex) {
SourceMappingRegion &Region = RegionStack.back();
if (Region.hasStartLoc()) {
- SourceLocation StartLoc = Region.getStartLoc();
+ SourceLocation StartLoc = Region.getBeginLoc();
SourceLocation EndLoc = Region.hasEndLoc()
? Region.getEndLoc()
: RegionStack[ParentIndex].getEndLoc();
+ size_t StartDepth = locationDepth(StartLoc);
+ size_t EndDepth = locationDepth(EndLoc);
while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
- // The region ends in a nested file or macro expansion. Create a
- // separate region for each expansion.
- SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
- assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
-
- if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
- SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
-
- EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
- if (EndLoc.isInvalid())
- llvm::report_fatal_error("File exit not handled before popRegions");
+ bool UnnestStart = StartDepth >= EndDepth;
+ bool UnnestEnd = EndDepth >= StartDepth;
+ if (UnnestEnd) {
+ // The region ends in a nested file or macro expansion. Create a
+ // separate region for each expansion.
+ SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
+ assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
+
+ if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
+ SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
+
+ EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
+ if (EndLoc.isInvalid())
+ llvm::report_fatal_error("File exit not handled before popRegions");
+ EndDepth--;
+ }
+ if (UnnestStart) {
+ // The region begins in a nested file or macro expansion. Create a
+ // separate region for each expansion.
+ SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
+ assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
+
+ if (!isRegionAlreadyAdded(StartLoc, NestedLoc))
+ SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc);
+
+ StartLoc = getIncludeOrExpansionLoc(StartLoc);
+ if (StartLoc.isInvalid())
+ llvm::report_fatal_error("File exit not handled before popRegions");
+ StartDepth--;
+ }
}
+ Region.setStartLoc(StartLoc);
Region.setEndLoc(EndLoc);
MostRecentLocation = EndLoc;
@@ -588,7 +619,7 @@ struct CounterCoverageMappingBuilder
EndLoc == getEndOfFileOrMacro(EndLoc))
MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
- assert(SM.isWrittenInSameFile(Region.getStartLoc(), EndLoc));
+ assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
assert(SpellingRegion(SM, Region).isInSourceOrder());
SourceRegions.push_back(Region);
@@ -625,18 +656,21 @@ struct CounterCoverageMappingBuilder
return RegionStack.back();
}
- /// Propagate counts through the children of \c S.
- Counter propagateCounts(Counter TopCount, const Stmt *S) {
+ /// Propagate counts through the children of \p S if \p VisitChildren is true.
+ /// Otherwise, only emit a count for \p S itself.
+ Counter propagateCounts(Counter TopCount, const Stmt *S,
+ bool VisitChildren = true) {
SourceLocation StartLoc = getStart(S);
SourceLocation EndLoc = getEnd(S);
size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
- Visit(S);
+ if (VisitChildren)
+ Visit(S);
Counter ExitCount = getRegion().getCounter();
popRegions(Index);
// The statement may be spanned by an expansion. Make sure we handle a file
// exit out of this expansion before moving to the next statement.
- if (SM.isBeforeInTranslationUnit(StartLoc, S->getLocStart()))
+ if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
MostRecentLocation = EndLoc;
return ExitCount;
@@ -648,7 +682,7 @@ struct CounterCoverageMappingBuilder
return SourceRegions.rend() !=
std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
[&](const SourceMappingRegion &Region) {
- return Region.getStartLoc() == StartLoc &&
+ return Region.getBeginLoc() == StartLoc &&
Region.getEndLoc() == EndLoc;
});
}
@@ -700,7 +734,7 @@ struct CounterCoverageMappingBuilder
for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
if (!I.hasStartLoc())
continue;
- SourceLocation Loc = I.getStartLoc();
+ SourceLocation Loc = I.getBeginLoc();
if (!isNestedIn(Loc, ParentFile)) {
ParentCounter = I.getCounter();
break;
@@ -826,7 +860,7 @@ struct CounterCoverageMappingBuilder
}
void VisitStmt(const Stmt *S) {
- if (S->getLocStart().isValid())
+ if (S->getBeginLoc().isValid())
extendRegion(S);
for (const Stmt *Child : S->children())
if (Child)
@@ -843,7 +877,16 @@ struct CounterCoverageMappingBuilder
if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
return;
- propagateCounts(getRegionCounter(Body), Body);
+ // Do not visit the artificial children nodes of defaulted methods. The
+ // lexer may not be able to report back precise token end locations for
+ // these children nodes (llvm.org/PR39822), and moreover users will not be
+ // able to see coverage for them.
+ bool Defaulted = false;
+ if (auto *Method = dyn_cast<CXXMethodDecl>(D))
+ Defaulted = Method->isDefaulted();
+
+ propagateCounts(getRegionCounter(Body), Body,
+ /*VisitChildren=*/!Defaulted);
assert(RegionStack.empty() && "Regions entered but never exited");
// Discard the last uncompleted deferred region in a decl, if one exists.
@@ -1004,6 +1047,8 @@ struct CounterCoverageMappingBuilder
void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
extendRegion(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getLoopVarStmt());
Visit(S->getRangeStmt());
@@ -1109,7 +1154,7 @@ struct CounterCoverageMappingBuilder
Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
// Reuse the existing region if it starts at our label. This is typical of
// the first case in a switch.
- if (Parent.hasStartLoc() && Parent.getStartLoc() == getStart(S))
+ if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
Parent.setCounter(Count);
else
pushRegion(Count, getStart(S));