Index: tools/llvm-cov/CMakeLists.txt =================================================================== --- tools/llvm-cov/CMakeLists.txt +++ tools/llvm-cov/CMakeLists.txt @@ -11,5 +11,6 @@ SourceCoverageView.cpp SourceCoverageViewHTML.cpp SourceCoverageViewText.cpp + SourceFilters.cpp TestingSupport.cpp ) Index: tools/llvm-cov/CodeCoverage.cpp =================================================================== --- tools/llvm-cov/CodeCoverage.cpp +++ tools/llvm-cov/CodeCoverage.cpp @@ -20,6 +20,7 @@ #include "CoverageViewOptions.h" #include "RenderingSupport.h" #include "SourceCoverageView.h" +#include "SourceFilters.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -126,6 +127,7 @@ std::vector ObjectFilenames; CoverageViewOptions ViewOpts; CoverageFiltersMatchAll Filters; + SourceFiltersMatchAll IgnoreSourceFilters; /// The path to the indexed profile. std::string PGOFilename; @@ -189,7 +191,8 @@ return; } sys::path::remove_dots(EffectivePath, /*remove_dot_dots=*/true); - SourceFiles.emplace_back(EffectivePath.str()); + if (!IgnoreSourceRegexFilters.match(EffectivePath)) + SourceFiles.emplace_back(EffectivePath.str()); } void CodeCoverageTool::collectPaths(const std::string &Path) { @@ -593,6 +596,12 @@ "regular expression"), cl::ZeroOrMore, cl::cat(FilteringCategory)); + cl::list IgnoreSourceRegexFilters( + "ignore-source-regex", cl::Optional, + cl::desc("Skip source code files that match the given regular " + "expression"), + cl::ZeroOrMore, cl::cat(FilteringCategory)); + cl::opt RegionCoverageLtFilter( "region-coverage-lt", cl::Optional, cl::desc("Show code coverage only for functions with region coverage " @@ -697,7 +706,7 @@ error(SpecialCaseListErr); } - // Create the function filters + // Create the function filters. if (!NameFilters.empty() || NameWhitelist || !NameRegexFilters.empty()) { auto NameFilterer = llvm::make_unique(); for (const auto &Name : NameFilters) @@ -710,6 +719,15 @@ llvm::make_unique(Regex)); Filters.push_back(std::move(NameFilterer)); } + + // Create the source files filters. + if (!IgnoreSourceRegexFilters.empty()) { + auto SourceFilterer = llvm::make_unique(); + for (const auto &Regex : IgnoreSourceRegexFilters) + SourceFilterer->push_back(llvm::make_unique(Regex)); + IgnoreSourceFilters.push_back(std::move(SourceFilterer)); + } + if (RegionCoverageLtFilter.getNumOccurrences() || RegionCoverageGtFilter.getNumOccurrences() || LineCoverageLtFilter.getNumOccurrences() || @@ -858,8 +876,11 @@ if (SourceFiles.empty()) // Get the source files from the function coverage mapping. - for (StringRef Filename : Coverage->getUniqueSourceFiles()) - SourceFiles.push_back(Filename); + for (StringRef Filename : Coverage->getUniqueSourceFiles()) { + // Apply ignore source files filters. + if (!IgnoreSourceRegexFilters.match(Filename)) + SourceFiles.push_back(Filename); + } // Create an index out of the source files. if (ViewOpts.hasOutputDirectory()) { @@ -958,7 +979,7 @@ CoverageReport Report(ViewOpts, *Coverage.get()); if (!ShowFunctionSummaries) { if (SourceFiles.empty()) - Report.renderFileReports(llvm::outs()); + Report.renderFileReports(llvm::outs(), IgnoreSourceFilters); else Report.renderFileReports(llvm::outs(), SourceFiles); } else { Index: tools/llvm-cov/CoverageExporterJson.cpp =================================================================== --- tools/llvm-cov/CoverageExporterJson.cpp +++ tools/llvm-cov/CoverageExporterJson.cpp @@ -119,8 +119,10 @@ void CoverageExporterJson::renderRoot() { std::vector SourceFiles; - for (StringRef SF : Coverage.getUniqueSourceFiles()) - SourceFiles.emplace_back(SF); + for (StringRef SF : Coverage.getUniqueSourceFiles()) { + if (!IgnoreSourceRegexFilters.match(Filename)) + SourceFiles.emplace_back(SF); + } renderRoot(SourceFiles); } Index: tools/llvm-cov/CoverageReport.h =================================================================== --- tools/llvm-cov/CoverageReport.h +++ tools/llvm-cov/CoverageReport.h @@ -53,7 +53,8 @@ const CoverageFilter *Filters); /// Render file reports for every unique file in the coverage mapping. - void renderFileReports(raw_ostream &OS) const; + void renderFileReports(raw_ostream &OS, + const SourceFiltersMatchAll &IgnoreFilters) const; /// Render file reports for the files specified in \p Files. void renderFileReports(raw_ostream &OS, ArrayRef Files) const; Index: tools/llvm-cov/CoverageReport.cpp =================================================================== --- tools/llvm-cov/CoverageReport.cpp +++ tools/llvm-cov/CoverageReport.cpp @@ -379,10 +379,14 @@ return FileReports; } -void CoverageReport::renderFileReports(raw_ostream &OS) const { +void CoverageReport::renderFileReports( + raw_ostream &OS, const SourceFiltersMatchAll &IgnoreFilters) const { std::vector UniqueSourceFiles; - for (StringRef SF : Coverage.getUniqueSourceFiles()) - UniqueSourceFiles.emplace_back(SF.str()); + for (StringRef SF : Coverage.getUniqueSourceFiles()) { + // Apply ignore source files filters. + if (!IgnoreFilters.match(Filename)) + UniqueSourceFiles.emplace_back(SF.str()); + } renderFileReports(OS, UniqueSourceFiles); } Index: tools/llvm-cov/SourceFilters.h =================================================================== --- /dev/null +++ tools/llvm-cov/SourceFilters.h @@ -0,0 +1,69 @@ +//===- SourceFilters.h - Source file names filters ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes provide filtering for source file names. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_COV_SOURCEFILTERS_H +#define LLVM_COV_SOURCEFILTERS_H + +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + +/// \brief Matches specific filename that pass the requirement of this filter. +class SourceFilter { +public: + virtual ~SourceFilter() {} + + /// \brief Return true if the filename passes the requirements of this filter. + virtual bool matches(StringRef Filename) const { + return true; + } +}; + +/// \brief Matches source files whose name matches a certain regular expression. +class SourceRegexFilter : public SourceFilter { + StringRef Regex; + +public: + SourceRegexFilter(StringRef Regex) : Regex(Regex) {} + + bool matches(StringRef Filename) const override; +}; + +/// \brief A collection of filters. +/// Matches source files that match any filters contained +/// in an instance of this class. +class SourceFilters : public SourceFilter { +protected: + std::vector> Filters; + +public: + /// \brief Append a filter to this collection. + void push_back(std::unique_ptr Filter); + + bool empty() const { return Filters.empty(); } + + bool matches(StringRef Filename) const override; +}; + +/// \brief A collection of filters. +/// Matches source files that match all of the filters contained +/// in an instance of this class. +class SourceFiltersMatchAll : public SourceFilters { +public: + bool matches(StringRef Filename) const override; +}; + +} // namespace llvm + +#endif // LLVM_COV_SOURCEFILTERS_H Index: tools/llvm-cov/SourceFilters.cpp =================================================================== --- /dev/null +++ tools/llvm-cov/SourceFilters.cpp @@ -0,0 +1,41 @@ +//===- SourceFilters.cpp - Source file names filters ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes provide filtering for source file names. +// +//===----------------------------------------------------------------------===// + +#include "SourceFilters.h" +#include "llvm/Support/Regex.h" + +using namespace llvm; + +bool SourceRegexFilter::matches(StringRef Filename) const { + return llvm::Regex(Regex).match(Filename); +} + +void SourceFilters::push_back(std::unique_ptr Filter) { + Filters.push_back(std::move(Filter)); +} + +bool SourceFilters::matches(StringRef Filename) const { + for (const auto &Filter : Filters) { + if (Filter->matches(Filename)) + return true; + } + return false; +} + +bool SourceFiltersMatchAll::matches(StringRef Filename) const { + for (const auto &Filter : Filters) { + if (!Filter->matches(Filename)) + return false; + } + return true; +}