llvm-cov: Handle missing source files as GCOV does

If the source files referenced by a gcno file are missing, gcov
outputs a coverage file where every line is simply /*EOF*/.  This also
occurs for lines in the coverage that are past the end of a file that
is found.

This change mimics gcov.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208149 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Justin Bogner 2014-05-07 02:11:23 +00:00
parent 56d05e468c
commit c92330c18c
6 changed files with 133 additions and 14 deletions

View File

@ -356,8 +356,10 @@ class FileInfo {
typedef DenseMap<uint32_t, BlockVector> BlockLines;
struct LineData {
LineData() : LastLine(0) {}
BlockLines Blocks;
FunctionLines Functions;
uint32_t LastLine;
};
struct GCOVCoverage {
@ -379,11 +381,15 @@ public:
Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
if (Line > LineInfo[Filename].LastLine)
LineInfo[Filename].LastLine = Line;
LineInfo[Filename].Blocks[Line-1].push_back(Block);
}
void addFunctionLine(StringRef Filename, uint32_t Line,
const GCOVFunction *Function) {
LineInfo[Filename].Functions[Line-1].push_back(Function);
if (Line > LineInfo[Filename].LastLine)
LineInfo[Filename].LastLine = Line;
LineInfo[Filename].Functions[Line-1].push_back(Function);
}
void setRunCount(uint32_t Runs) { RunCount = Runs; }
void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }

View File

@ -432,6 +432,30 @@ static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
return OS;
}
namespace {
class LineConsumer {
std::unique_ptr<MemoryBuffer> Buffer;
StringRef Remaining;
public:
LineConsumer(StringRef Filename) {
if (error_code EC = MemoryBuffer::getFileOrSTDIN(Filename, Buffer)) {
errs() << Filename << ": " << EC.message() << "\n";
Remaining = "";
} else
Remaining = Buffer->getBuffer();
}
bool empty() { return Remaining.empty(); }
void printNext(raw_ostream &OS, uint32_t LineNum) {
StringRef Line;
if (empty())
Line = "/*EOF*/";
else
std::tie(Line, Remaining) = Remaining.split("\n");
OS << format("%5u:", LineNum) << Line << "\n";
}
};
}
/// Convert a path to a gcov filename. If PreservePaths is true, this
/// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
@ -505,12 +529,7 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile,
for (StringMap<LineData>::const_iterator I = LineInfo.begin(),
E = LineInfo.end(); I != E; ++I) {
StringRef Filename = I->first();
std::unique_ptr<MemoryBuffer> Buff;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
errs() << Filename << ": " << ec.message() << "\n";
return;
}
StringRef AllLines = Buff->getBuffer();
auto AllLines = LineConsumer(Filename);
std::string CoveragePath = getCoveragePath(Filename, MainFilename);
std::unique_ptr<raw_ostream> S = openCoveragePath(CoveragePath);
@ -524,7 +543,8 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile,
const LineData &Line = I->second;
GCOVCoverage FileCoverage(Filename);
for (uint32_t LineIndex = 0; !AllLines.empty(); ++LineIndex) {
for (uint32_t LineIndex = 0;
LineIndex < Line.LastLine || !AllLines.empty(); ++LineIndex) {
if (Options.BranchInfo) {
FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
if (FuncsIt != Line.Functions.end())
@ -535,9 +555,7 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile,
if (BlocksIt == Line.Blocks.end()) {
// No basic blocks are on this line. Not an executable line of code.
OS << " -:";
std::pair<StringRef, StringRef> P = AllLines.split('\n');
OS << format("%5u:", LineIndex+1) << P.first << "\n";
AllLines = P.second;
AllLines.printNext(OS, LineIndex + 1);
} else {
const BlockVector &Blocks = BlocksIt->second;
@ -599,9 +617,7 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile,
}
++FileCoverage.LogicalLines;
std::pair<StringRef, StringRef> P = AllLines.split('\n');
OS << format("%5u:", LineIndex+1) << P.first << "\n";
AllLines = P.second;
AllLines.printNext(OS, LineIndex + 1);
uint32_t BlockNo = 0;
uint32_t EdgeNo = 0;

View File

@ -0,0 +1,77 @@
-: 0:Source:srcdir/./nested_dir/../test.cpp
-: 0:Graph:test_paths.gcno
-: 0:Data:test_paths.gcda
-: 0:Runs:3
-: 0:Programs:1
-: 1:/*EOF*/
-: 2:/*EOF*/
-: 3:/*EOF*/
-: 4:/*EOF*/
-: 5:/*EOF*/
-: 6:/*EOF*/
-: 7:/*EOF*/
-: 8:/*EOF*/
-: 9:/*EOF*/
12884901888: 10:/*EOF*/
-: 11:/*EOF*/
#####: 12:/*EOF*/
-: 13:/*EOF*/
-: 14:/*EOF*/
#####: 15:/*EOF*/
-: 16:/*EOF*/
-: 17:/*EOF*/
-: 18:/*EOF*/
3: 19:/*EOF*/
3: 20:/*EOF*/
-: 21:/*EOF*/
-: 22:/*EOF*/
-: 23:/*EOF*/
#####: 24:/*EOF*/
#####: 25:/*EOF*/
-: 26:/*EOF*/
-: 27:/*EOF*/
12: 28:/*EOF*/
12: 29:/*EOF*/
12: 30:/*EOF*/
-: 31:/*EOF*/
-: 32:/*EOF*/
21: 33:/*EOF*/
36: 34:/*EOF*/
18: 35:/*EOF*/
3: 36:/*EOF*/
-: 37:/*EOF*/
-: 38:/*EOF*/
3: 39:/*EOF*/
-: 40:/*EOF*/
3: 41:/*EOF*/
3: 42:/*EOF*/
3: 43:/*EOF*/
3: 44:/*EOF*/
3: 45:/*EOF*/
3: 46:/*EOF*/
#####: 47:/*EOF*/
#####: 48:/*EOF*/
-: 49:/*EOF*/
-: 50:/*EOF*/
66: 51:/*EOF*/
30: 52:/*EOF*/
-: 53:/*EOF*/
6: 54:/*EOF*/
6: 55:/*EOF*/
-: 56:/*EOF*/
-: 57:/*EOF*/
3: 58:/*EOF*/
3: 59:/*EOF*/
-: 60:/*EOF*/
9: 61:/*EOF*/
9: 62:/*EOF*/
-: 63:/*EOF*/
12: 64:/*EOF*/
12: 65:/*EOF*/
30: 66:/*EOF*/
-: 67:/*EOF*/
3: 68:/*EOF*/
25769803782: 69:/*EOF*/
12884901888: 70:/*EOF*/
-: 71:/*EOF*/
3: 72:/*EOF*/

View File

@ -0,0 +1,6 @@
-: 0:Source:srcdir/./nested_dir/../test.h
-: 0:Graph:test_paths.gcno
-: 0:Data:test_paths.gcda
-: 0:Runs:3
-: 0:Programs:1
6: 1:/*EOF*/

View File

@ -0,0 +1,8 @@
File 'srcdir/./nested_dir/../test.h'
Lines executed:100.00% of 1
srcdir/./nested_dir/../test.h:creating 'test.h.gcov'
File 'srcdir/./nested_dir/../test.cpp'
Lines executed:84.21% of 38
srcdir/./nested_dir/../test.cpp:creating 'test.cpp.gcov'

View File

@ -34,6 +34,12 @@ 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 -
# Missing source files. This test is fragile, as it depends on being
# run before we copy some sources into place in the next test.
RUN: llvm-cov test_paths.cpp 2>/dev/null | diff -u test_missing.output -
RUN: diff -aub test_missing.cpp.gcov test.cpp.gcov
RUN: diff -aub test_missing.h.gcov test.h.gcov
# Preserve paths. This mangles the output filenames.
RUN: mkdir -p %t/srcdir/nested_dir
RUN: cp test.cpp test.h %t/srcdir