aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp')
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp96
1 files changed, 85 insertions, 11 deletions
diff --git a/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp b/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
index b3c895b44a6d..baa968820b63 100644
--- a/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -88,6 +88,12 @@ private:
ArrayRef<ExpansionRecord> Expansions,
const CoverageMapping &Coverage);
+ /// Create source views for the branches of the view.
+ void attachBranchSubViews(SourceCoverageView &View, StringRef SourceName,
+ ArrayRef<CountedRegion> Branches,
+ const MemoryBuffer &File,
+ CoverageData &CoverageInfo);
+
/// Create the source view of a particular function.
std::unique_ptr<SourceCoverageView>
createFunctionView(const FunctionRecord &Function,
@@ -130,6 +136,9 @@ private:
CoverageFiltersMatchAll Filters;
CoverageFilters IgnoreFilenameFilters;
+ /// True if InputSourceFiles are provided.
+ bool HadSourceFiles = false;
+
/// The path to the indexed profile.
std::string PGOFilename;
@@ -194,6 +203,7 @@ void CodeCoverageTool::addCollectedPath(const std::string &Path) {
sys::path::remove_dots(EffectivePath, /*remove_dot_dots=*/true);
if (!IgnoreFilenameFilters.matchesFilename(EffectivePath))
SourceFiles.emplace_back(EffectivePath.str());
+ HadSourceFiles = !SourceFiles.empty();
}
void CodeCoverageTool::collectPaths(const std::string &Path) {
@@ -264,15 +274,45 @@ void CodeCoverageTool::attachExpansionSubViews(
if (!SourceBuffer)
continue;
+ auto SubViewBranches = ExpansionCoverage.getBranches();
auto SubViewExpansions = ExpansionCoverage.getExpansions();
auto SubView =
SourceCoverageView::create(Expansion.Function.Name, SourceBuffer.get(),
ViewOpts, std::move(ExpansionCoverage));
attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
+ attachBranchSubViews(*SubView, Expansion.Function.Name, SubViewBranches,
+ SourceBuffer.get(), ExpansionCoverage);
View.addExpansion(Expansion.Region, std::move(SubView));
}
}
+void CodeCoverageTool::attachBranchSubViews(SourceCoverageView &View,
+ StringRef SourceName,
+ ArrayRef<CountedRegion> Branches,
+ const MemoryBuffer &File,
+ CoverageData &CoverageInfo) {
+ if (!ViewOpts.ShowBranchCounts && !ViewOpts.ShowBranchPercents)
+ return;
+
+ const auto *NextBranch = Branches.begin();
+ const auto *EndBranch = Branches.end();
+
+ // Group branches that have the same line number into the same subview.
+ while (NextBranch != EndBranch) {
+ std::vector<CountedRegion> ViewBranches;
+ unsigned CurrentLine = NextBranch->LineStart;
+
+ while (NextBranch != EndBranch && CurrentLine == NextBranch->LineStart)
+ ViewBranches.push_back(*NextBranch++);
+
+ if (!ViewBranches.empty()) {
+ auto SubView = SourceCoverageView::create(SourceName, File, ViewOpts,
+ std::move(CoverageInfo));
+ View.addBranch(CurrentLine, ViewBranches, std::move(SubView));
+ }
+ }
+}
+
std::unique_ptr<SourceCoverageView>
CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
const CoverageMapping &Coverage) {
@@ -283,11 +323,14 @@ CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
if (!SourceBuffer)
return nullptr;
+ auto Branches = FunctionCoverage.getBranches();
auto Expansions = FunctionCoverage.getExpansions();
auto View = SourceCoverageView::create(DC.demangle(Function.Name),
SourceBuffer.get(), ViewOpts,
std::move(FunctionCoverage));
attachExpansionSubViews(*View, Expansions, Coverage);
+ attachBranchSubViews(*View, DC.demangle(Function.Name), Branches,
+ SourceBuffer.get(), FunctionCoverage);
return View;
}
@@ -302,10 +345,13 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
if (FileCoverage.empty())
return nullptr;
+ auto Branches = FileCoverage.getBranches();
auto Expansions = FileCoverage.getExpansions();
auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
ViewOpts, std::move(FileCoverage));
attachExpansionSubViews(*View, Expansions, Coverage);
+ attachBranchSubViews(*View, SourceFile, Branches, SourceBuffer.get(),
+ FileCoverage);
if (!ViewOpts.ShowFunctionInstantiations)
return View;
@@ -322,9 +368,12 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
if (Function->ExecutionCount > 0) {
auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
auto SubViewExpansions = SubViewCoverage.getExpansions();
+ auto SubViewBranches = SubViewCoverage.getBranches();
SubView = SourceCoverageView::create(
Funcname, SourceBuffer.get(), ViewOpts, std::move(SubViewCoverage));
attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
+ attachBranchSubViews(*SubView, SourceFile, SubViewBranches,
+ SourceBuffer.get(), SubViewCoverage);
}
unsigned FileID = Function->CountedRegions.front().FileID;
@@ -395,6 +444,7 @@ void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
return "";
SmallString<128> NativePath;
sys::path::native(Path, NativePath);
+ sys::path::remove_dots(NativePath, true);
if (!sys::path::is_separator(NativePath.back()))
NativePath += sys::path::get_separator();
return NativePath.c_str();
@@ -406,6 +456,7 @@ void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
SmallString<128> NativeFilename;
sys::path::native(Filename, NativeFilename);
+ sys::path::remove_dots(NativeFilename, true);
if (NativeFilename.startswith(RemapFrom)) {
RemappedFilenames[Filename] =
RemapTo + NativeFilename.substr(RemapFrom.size()).str();
@@ -430,16 +481,11 @@ void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
void CodeCoverageTool::removeUnmappedInputs(const CoverageMapping &Coverage) {
std::vector<StringRef> CoveredFiles = Coverage.getUniqueSourceFiles();
- auto UncoveredFilesIt = SourceFiles.end();
// The user may have specified source files which aren't in the coverage
// mapping. Filter these files away.
- UncoveredFilesIt = std::remove_if(
- SourceFiles.begin(), SourceFiles.end(), [&](const std::string &SF) {
- return !std::binary_search(CoveredFiles.begin(), CoveredFiles.end(),
- SF);
- });
-
- SourceFiles.erase(UncoveredFilesIt, SourceFiles.end());
+ llvm::erase_if(SourceFiles, [&](const std::string &SF) {
+ return !std::binary_search(CoveredFiles.begin(), CoveredFiles.end(), SF);
+ });
}
void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {
@@ -544,8 +590,11 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
cl::Positional, cl::desc("Covered executable or object file."));
cl::list<std::string> CovFilenames(
- "object", cl::desc("Coverage executable or object file"), cl::ZeroOrMore,
- cl::CommaSeparated);
+ "object", cl::desc("Coverage executable or object file"), cl::ZeroOrMore);
+
+ cl::opt<bool> DebugDumpCollectedObjects(
+ "dump-collected-objects", cl::Optional, cl::Hidden,
+ cl::desc("Show the collected coverage object files"));
cl::list<std::string> InputSourceFiles(
cl::Positional, cl::desc("<Source files>"), cl::ZeroOrMore);
@@ -641,6 +690,11 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
cl::desc("Show region statistics in summary table"),
cl::init(true));
+ cl::opt<bool> BranchSummary(
+ "show-branch-summary", cl::Optional,
+ cl::desc("Show branch condition statistics in summary table"),
+ cl::init(true));
+
cl::opt<bool> InstantiationSummary(
"show-instantiation-summary", cl::Optional,
cl::desc("Show instantiation statistics in summary table"));
@@ -668,6 +722,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
::exit(1);
}
+ if (DebugDumpCollectedObjects) {
+ for (StringRef OF : ObjectFilenames)
+ outs() << OF << '\n';
+ ::exit(0);
+ }
+
ViewOpts.Format = Format;
switch (ViewOpts.Format) {
case CoverageViewOptions::OutputFormat::Text:
@@ -778,6 +838,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
::exit(0);
}
+ ViewOpts.ShowBranchSummary = BranchSummary;
ViewOpts.ShowRegionSummary = RegionSummary;
ViewOpts.ShowInstantiationSummary = InstantiationSummary;
ViewOpts.ExportSummaryOnly = SummaryOnly;
@@ -812,6 +873,15 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
cl::desc("Show the execution counts for each region"),
cl::cat(ViewCategory));
+ cl::opt<CoverageViewOptions::BranchOutputType> ShowBranches(
+ "show-branches", cl::Optional,
+ cl::desc("Show coverage for branch conditions"), cl::cat(ViewCategory),
+ cl::values(clEnumValN(CoverageViewOptions::BranchOutputType::Count,
+ "count", "Show True/False counts"),
+ clEnumValN(CoverageViewOptions::BranchOutputType::Percent,
+ "percent", "Show True/False percent")),
+ cl::init(CoverageViewOptions::BranchOutputType::Off));
+
cl::opt<bool> ShowBestLineRegionsCounts(
"show-line-counts-or-regions", cl::Optional,
cl::desc("Show the execution counts for each line, or the execution "
@@ -855,6 +925,10 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
!ShowRegions || ShowBestLineRegionsCounts;
ViewOpts.ShowRegionMarkers = ShowRegions || ShowBestLineRegionsCounts;
ViewOpts.ShowExpandedRegions = ShowExpansions;
+ ViewOpts.ShowBranchCounts =
+ ShowBranches == CoverageViewOptions::BranchOutputType::Count;
+ ViewOpts.ShowBranchPercents =
+ ShowBranches == CoverageViewOptions::BranchOutputType::Percent;
ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
ViewOpts.TabSize = TabSize;
@@ -886,7 +960,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
auto Printer = CoveragePrinter::create(ViewOpts);
- if (SourceFiles.empty())
+ if (SourceFiles.empty() && !HadSourceFiles)
// Get the source files from the function coverage mapping.
for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
if (!IgnoreFilenameFilters.matchesFilename(Filename))