From 10edef110eb78f7b4b302ed2c2138dbeeb3d3685 Mon Sep 17 00:00:00 2001 From: Sean Eveson Date: Thu, 31 Aug 2017 09:11:31 +0000 Subject: [PATCH] [llvm-cov] Read in function names for filtering from a text file. Summary: Add a -name-whitelist option, which behaves in the same way as -name, but it reads in multiple function names from the given input file(s). Reviewers: vsk Reviewed By: vsk Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D37111 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312227 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandGuide/llvm-cov.rst | 6 ++ .../llvm-cov/Inputs/name_whitelist.covmapping | Bin 0 -> 384 bytes test/tools/llvm-cov/Inputs/name_whitelist.cpp | 18 ++++++ .../llvm-cov/Inputs/name_whitelist.proftext | 56 ++++++++++++++++++ test/tools/llvm-cov/Inputs/whitelist1.txt | 4 ++ test/tools/llvm-cov/Inputs/whitelist2.txt | 2 + test/tools/llvm-cov/name_whitelist.test | 21 +++++++ tools/llvm-cov/CodeCoverage.cpp | 23 ++++++- tools/llvm-cov/CoverageFilters.cpp | 5 ++ tools/llvm-cov/CoverageFilters.h | 13 ++++ 10 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 test/tools/llvm-cov/Inputs/name_whitelist.covmapping create mode 100644 test/tools/llvm-cov/Inputs/name_whitelist.cpp create mode 100644 test/tools/llvm-cov/Inputs/name_whitelist.proftext create mode 100644 test/tools/llvm-cov/Inputs/whitelist1.txt create mode 100644 test/tools/llvm-cov/Inputs/whitelist2.txt create mode 100644 test/tools/llvm-cov/name_whitelist.test diff --git a/docs/CommandGuide/llvm-cov.rst b/docs/CommandGuide/llvm-cov.rst index 082f5103751..4b5860a4e6a 100644 --- a/docs/CommandGuide/llvm-cov.rst +++ b/docs/CommandGuide/llvm-cov.rst @@ -235,6 +235,12 @@ OPTIONS Show code coverage only for functions with the given name. +.. option:: -name-whitelist= + + Show code coverage only for functions listed in the given file. Each line in + the file should start with `whitelist_fun:`, immediately followed by the name + of the function to accept. This name can be a wildcard expression. + .. option:: -name-regex= Show code coverage only for functions that match the given regular expression. diff --git a/test/tools/llvm-cov/Inputs/name_whitelist.covmapping b/test/tools/llvm-cov/Inputs/name_whitelist.covmapping new file mode 100644 index 0000000000000000000000000000000000000000..6c067abd02799732414e4bfe442f4a41090a4e79 GIT binary patch literal 384 zcmd1FDa%dHFUu`SEiOq(EJ^geaIBG;g&{XFGmildtQq2?Ow&s9k`2okp)4af%NWiw zfwN5EEVD9*DU3jhABZ`D7{vZ{wfDJM%GBE+J`6DO>X+me=!5LmOD-q?Dr011_G9g{R13m+qa(-rZLli7fW*@u?qAo!2TM zi=AA2!mz^R)=FeCsZg8HcPtsA$YPA*U^nI^=BCD%XJnS7=42L^AY9AK!~}LW3yi@I PV{pM3yfB6Ukih@|-1trg literal 0 HcmV?d00001 diff --git a/test/tools/llvm-cov/Inputs/name_whitelist.cpp b/test/tools/llvm-cov/Inputs/name_whitelist.cpp new file mode 100644 index 00000000000..dec10ea1fb6 --- /dev/null +++ b/test/tools/llvm-cov/Inputs/name_whitelist.cpp @@ -0,0 +1,18 @@ +int func1() { + return 1; +} +int func2() { + return 1; +} +int func3() { + return 1; +} +int func4() { + return 1; +} +int func5() { + return 1; +} +int func6() { + return 1; +} diff --git a/test/tools/llvm-cov/Inputs/name_whitelist.proftext b/test/tools/llvm-cov/Inputs/name_whitelist.proftext new file mode 100644 index 00000000000..c806d1565fb --- /dev/null +++ b/test/tools/llvm-cov/Inputs/name_whitelist.proftext @@ -0,0 +1,56 @@ +_Z5func1v +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +0 + +_Z5func2v +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +0 + +_Z5func3v +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +0 + +_Z5func4v +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +0 + +main +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +1 + +_Z5func5v +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +0 + +_Z5func6v +# Func Hash: +0 +# Num Counters: +1 +# Counter Values: +0 + diff --git a/test/tools/llvm-cov/Inputs/whitelist1.txt b/test/tools/llvm-cov/Inputs/whitelist1.txt new file mode 100644 index 00000000000..26463237ae9 --- /dev/null +++ b/test/tools/llvm-cov/Inputs/whitelist1.txt @@ -0,0 +1,4 @@ +# Comment + +whitelist_fun:*func1* +whitelist_fun:*func2* diff --git a/test/tools/llvm-cov/Inputs/whitelist2.txt b/test/tools/llvm-cov/Inputs/whitelist2.txt new file mode 100644 index 00000000000..58098203503 --- /dev/null +++ b/test/tools/llvm-cov/Inputs/whitelist2.txt @@ -0,0 +1,2 @@ +whitelist_fun:*func3* +whitelist_fun:*func4* diff --git a/test/tools/llvm-cov/name_whitelist.test b/test/tools/llvm-cov/name_whitelist.test new file mode 100644 index 00000000000..3eb21e5d332 --- /dev/null +++ b/test/tools/llvm-cov/name_whitelist.test @@ -0,0 +1,21 @@ +RUN: llvm-profdata merge %S/Inputs/name_whitelist.proftext -o %t.profdata + +RUN: llvm-cov show %S/Inputs/name_whitelist.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp,%S/Inputs -name-whitelist=%S/Inputs/whitelist1.txt %S/Inputs/name_whitelist.cpp > %t.one_list +RUN: FileCheck -input-file=%t.one_list -check-prefix=ONE_WHITELIST %s +RUN: FileCheck -input-file=%t.one_list -check-prefix=ONE_WHITELIST_NEG %s +ONE_WHITELIST: _Z5func1v: +ONE_WHITELIST: _Z5func2v: +ONE_WHITELIST_NEG-NOT: _Z5func3v: +ONE_WHITELIST_NEG-NOT: _Z5func4v: +ONE_WHITELIST_NEG-NOT: _Z5func5v: +ONE_WHITELIST_NEG-NOT: _Z5func6v: + +RUN: llvm-cov show %S/Inputs/name_whitelist.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp,%S/Inputs -name-whitelist=%S/Inputs/whitelist1.txt -name-whitelist=%S/Inputs/whitelist2.txt %S/Inputs/name_whitelist.cpp > %t.two_list +RUN: FileCheck -input-file=%t.two_list -check-prefix=TWO_WHITELIST %s +RUN: FileCheck -input-file=%t.two_list -check-prefix=TWO_WHITELIST_NEG %s +TWO_WHITELIST: _Z5func1v: +TWO_WHITELIST: _Z5func2v: +TWO_WHITELIST: _Z5func3v: +TWO_WHITELIST: _Z5func4v: +TWO_WHITELIST_NEG-NOT: _Z5func5v: +TWO_WHITELIST_NEG-NOT: _Z5func6v: diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp index e5878df6c15..f75fcb8884c 100644 --- a/tools/llvm-cov/CodeCoverage.cpp +++ b/tools/llvm-cov/CodeCoverage.cpp @@ -150,6 +150,9 @@ private: std::mutex LoadedSourceFilesLock; std::vector>> LoadedSourceFiles; + + /// Whitelist from -name-whitelist to be used for filtering. + std::unique_ptr NameWhitelist; }; } @@ -561,6 +564,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { cl::desc("Show code coverage only for functions with the given name"), cl::ZeroOrMore, cl::cat(FilteringCategory)); + cl::list NameFilterFiles( + "name-whitelist", cl::Optional, + cl::desc("Show code coverage only for functions listed in the given " + "file"), + cl::ZeroOrMore, cl::cat(FilteringCategory)); + cl::list NameRegexFilters( "name-regex", cl::Optional, cl::desc("Show code coverage only for functions that match the given " @@ -643,11 +652,23 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { ViewOpts.DemanglerOpts.swap(DemanglerOpts); } + // Read in -name-whitelist files. + if (!NameFilterFiles.empty()) { + std::string SpecialCaseListErr; + NameWhitelist = + SpecialCaseList::create(NameFilterFiles, SpecialCaseListErr); + if (!NameWhitelist) + error(SpecialCaseListErr); + } + // Create the function filters - if (!NameFilters.empty() || !NameRegexFilters.empty()) { + if (!NameFilters.empty() || NameWhitelist || !NameRegexFilters.empty()) { auto NameFilterer = llvm::make_unique(); for (const auto &Name : NameFilters) NameFilterer->push_back(llvm::make_unique(Name)); + if (NameWhitelist) + NameFilterer->push_back( + llvm::make_unique(*NameWhitelist)); for (const auto &Regex : NameRegexFilters) NameFilterer->push_back( llvm::make_unique(Regex)); diff --git a/tools/llvm-cov/CoverageFilters.cpp b/tools/llvm-cov/CoverageFilters.cpp index 325dd723578..606d4af1687 100644 --- a/tools/llvm-cov/CoverageFilters.cpp +++ b/tools/llvm-cov/CoverageFilters.cpp @@ -27,6 +27,11 @@ NameRegexCoverageFilter::matches(const coverage::FunctionRecord &Function) { return llvm::Regex(Regex).match(Function.Name); } +bool NameWhitelistCoverageFilter::matches( + const coverage::FunctionRecord &Function) { + return Whitelist.inSection("whitelist_fun", Function.Name); +} + bool RegionCoverageFilter::matches(const coverage::FunctionRecord &Function) { return PassesThreshold(FunctionCoverageSummary::get(Function) .RegionCoverage.getPercentCovered()); diff --git a/tools/llvm-cov/CoverageFilters.h b/tools/llvm-cov/CoverageFilters.h index 756c4b47872..e5c52fe877a 100644 --- a/tools/llvm-cov/CoverageFilters.h +++ b/tools/llvm-cov/CoverageFilters.h @@ -15,6 +15,7 @@ #define LLVM_COV_COVERAGEFILTERS_H #include "llvm/ProfileData/Coverage/CoverageMapping.h" +#include "llvm/Support/SpecialCaseList.h" #include #include @@ -51,6 +52,18 @@ public: bool matches(const coverage::FunctionRecord &Function) override; }; +/// \brief Matches functions whose name appears in a SpecialCaseList in the +/// whitelist_fun section. +class NameWhitelistCoverageFilter : public CoverageFilter { + const SpecialCaseList &Whitelist; + +public: + NameWhitelistCoverageFilter(const SpecialCaseList &Whitelist) + : Whitelist(Whitelist) {} + + bool matches(const coverage::FunctionRecord &Function) override; +}; + /// \brief Matches numbers that pass a certain threshold. template class StatisticThresholdFilter { public: