From b8e01630df22fd1e7a6646e1739a2c2a63bd79bb Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Wed, 7 May 2014 02:11:18 +0000 Subject: [PATCH] llvm-cov: Implement --no-output In gcov, there's a -n/--no-output option, which disables the writing of any .gcov files, so that it emits only the summary info on stdout. This implements the same behaviour in llvm-cov. llvm-svn: 208148 --- include/llvm/Support/GCOV.h | 15 +++-- lib/IR/GCOV.cpp | 58 ++++++++++++++----- .../llvm-cov/Inputs/test_no_output.output | 6 ++ test/tools/llvm-cov/llvm-cov.test | 3 + tools/llvm-cov/llvm-cov.cpp | 6 +- 5 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 test/tools/llvm-cov/Inputs/test_no_output.output diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index 923affcd0b8..267693fa492 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -37,9 +37,9 @@ namespace GCOV { /// GCOVOptions - A struct for passing gcov options between functions. struct GCOVOptions { - GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L) + GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), - PreservePaths(P), UncondBranch(U), LongFileNames(L) {} + PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} bool AllBlocks; bool BranchInfo; @@ -48,6 +48,7 @@ struct GCOVOptions { bool PreservePaths; bool UncondBranch; bool LongFileNames; + bool NoOutput; }; /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific @@ -389,13 +390,15 @@ public: void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); private: - void printFunctionSummary(raw_fd_ostream &OS, + std::string getCoveragePath(StringRef Filename, StringRef MainFilename); + std::unique_ptr openCoveragePath(StringRef CoveragePath); + void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const; - void printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block, + void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, uint32_t LineIndex, uint32_t &BlockNo) const; - void printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block, + void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, GCOVCoverage &Coverage, uint32_t &EdgeNo); - void printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo, + void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, uint64_t Count) const; void printCoverage(const GCOVCoverage &Coverage) const; diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp index 522716309a9..05fe1e07dfd 100644 --- a/lib/IR/GCOV.cpp +++ b/lib/IR/GCOV.cpp @@ -467,6 +467,38 @@ static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) { return Result.str(); } +std::string FileInfo::getCoveragePath(StringRef Filename, + StringRef MainFilename) { + if (Options.NoOutput) + // This is probably a bug in gcov, but when -n is specified, paths aren't + // mangled at all, and the -l and -p options are ignored. Here, we do the + // same. + return Filename; + + std::string CoveragePath; + if (Options.LongFileNames && !Filename.equals(MainFilename)) + CoveragePath = + mangleCoveragePath(MainFilename, Options.PreservePaths) + "##"; + CoveragePath += + mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov"; + return CoveragePath; +} + +std::unique_ptr +FileInfo::openCoveragePath(StringRef CoveragePath) { + if (Options.NoOutput) + return make_unique(); + + std::string ErrorInfo; + auto OS = make_unique(CoveragePath.str().c_str(), ErrorInfo, + sys::fs::F_Text); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << "\n"; + return make_unique(); + } + return std::move(OS); +} + /// print - Print source files with collected line count information. void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile) { @@ -480,16 +512,9 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, } StringRef AllLines = Buff->getBuffer(); - std::string CoveragePath; - if (Options.LongFileNames && !Filename.equals(MainFilename)) - CoveragePath = - mangleCoveragePath(MainFilename, Options.PreservePaths) + "##"; - CoveragePath += - mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov"; - std::string ErrorInfo; - raw_fd_ostream OS(CoveragePath.c_str(), ErrorInfo, sys::fs::F_Text); - if (!ErrorInfo.empty()) - errs() << ErrorInfo << "\n"; + std::string CoveragePath = getCoveragePath(Filename, MainFilename); + std::unique_ptr S = openCoveragePath(CoveragePath); + raw_ostream &OS = *S; OS << " -: 0:Source:" << Filename << "\n"; OS << " -: 0:Graph:" << GCNOFile << "\n"; @@ -606,10 +631,11 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, if (Options.FuncCoverage) printFuncCoverage(); printFileCoverage(); + return; } /// printFunctionSummary - Print function and block summary. -void FileInfo::printFunctionSummary(raw_fd_ostream &OS, +void FileInfo::printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const { for (FunctionVector::const_iterator I = Funcs.begin(), E = Funcs.end(); I != E; ++I) { @@ -631,7 +657,7 @@ void FileInfo::printFunctionSummary(raw_fd_ostream &OS, } /// printBlockInfo - Output counts for each block. -void FileInfo::printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block, +void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, uint32_t LineIndex, uint32_t &BlockNo) const { if (Block.getCount() == 0) OS << " $$$$$:"; @@ -641,7 +667,7 @@ void FileInfo::printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block, } /// printBranchInfo - Print conditional branch probabilities. -void FileInfo::printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block, +void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, GCOVCoverage &Coverage, uint32_t &EdgeNo) { SmallVector BranchCounts; uint64_t TotalCounts = 0; @@ -671,7 +697,7 @@ void FileInfo::printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block, } /// printUncondBranchInfo - Print unconditional branch probabilities. -void FileInfo::printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo, +void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, uint64_t Count) const { OS << format("unconditional %2u ", EdgeNo++) << formatBranchInfo(Options, Count, Count) << "\n"; @@ -717,6 +743,8 @@ void FileInfo::printFileCoverage() const { const GCOVCoverage &Coverage = I->second; outs() << "File '" << Coverage.Name << "'\n"; printCoverage(Coverage); - outs() << Coverage.Name << ":creating '" << Filename << "'\n\n"; + if (!Options.NoOutput) + outs() << Coverage.Name << ":creating '" << Filename << "'\n"; + outs() << "\n"; } } diff --git a/test/tools/llvm-cov/Inputs/test_no_output.output b/test/tools/llvm-cov/Inputs/test_no_output.output new file mode 100644 index 00000000000..74286b9a2fc --- /dev/null +++ b/test/tools/llvm-cov/Inputs/test_no_output.output @@ -0,0 +1,6 @@ +File 'test.cpp' +Lines executed:84.21% of 38 + +File './test.h' +Lines executed:100.00% of 1 + diff --git a/test/tools/llvm-cov/llvm-cov.test b/test/tools/llvm-cov/llvm-cov.test index 8457aef292f..8f57d9a1893 100644 --- a/test/tools/llvm-cov/llvm-cov.test +++ b/test/tools/llvm-cov/llvm-cov.test @@ -31,6 +31,9 @@ RUN: llvm-cov -o objdir/test test.c | diff -u test_no_options.output - RUN: diff -aub test_objdir.cpp.gcov test.cpp.gcov RUN: diff -aub test_objdir.h.gcov test.h.gcov +# With gcov output disabled +RUN: llvm-cov -n test.c | diff -u test_no_output.output - + # Preserve paths. This mangles the output filenames. RUN: mkdir -p %t/srcdir/nested_dir RUN: cp test.cpp test.h %t/srcdir diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp index 02f4b722169..9463609ae3d 100644 --- a/tools/llvm-cov/llvm-cov.cpp +++ b/tools/llvm-cov/llvm-cov.cpp @@ -47,6 +47,10 @@ static cl::opt FuncSummary("f", cl::Grouping, cl::init(false), cl::desc("Show coverage for each function")); static cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary)); +static cl::opt NoOutput("n", cl::Grouping, cl::init(false), + cl::desc("Do not output any .gcov files")); +static cl::alias NoOutputA("no-output", cl::aliasopt(NoOutput)); + static cl::opt ObjectDir("o", cl::value_desc("DIR|FILE"), cl::init(""), cl::desc("Find objects in DIR or based on FILE's path")); @@ -130,7 +134,7 @@ int main(int argc, char **argv) { GF.dump(); GCOVOptions Options(AllBlocks, BranchProb, BranchCount, FuncSummary, - PreservePaths, UncondBranch, LongNames); + PreservePaths, UncondBranch, LongNames, NoOutput); FileInfo FI(Options); GF.collectLineCounts(FI); FI.print(SourceFile, InputGCNO, InputGCDA);