[gcov] Improve .gcno compatibility with gcov and use DataExtractor

llvm-cov.test and many Inputs/test* files contain wrong tests.
This patch rewrites a large portion of these files.
The pre-canned .gcno & .gcda are replaced by binaries produced by
clang --coverage (compatible with gcov 4.8~7)
(after some GCDAProfiling.c bugs were fixed by my previous commits).

Also make llvm-cov gcov on a little-endian host capable to parse big-endian .gcno and .gcda,
and make llvm-cov gcov on big-endian host capable to parse little-endian .gcno and .gcda
This commit is contained in:
Fangrui Song 2020-06-03 19:29:21 -07:00
parent 049d860707
commit 01899bb4e4
37 changed files with 426 additions and 1224 deletions

View File

@ -21,6 +21,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@ -70,36 +71,51 @@ struct Options {
class GCOVBuffer {
public:
GCOVBuffer(MemoryBuffer *B) : Buffer(B) {}
~GCOVBuffer() { consumeError(cursor.takeError()); }
/// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
bool readGCNOFormat() {
StringRef File = Buffer->getBuffer().slice(0, 4);
if (File != "oncg") {
errs() << "Unexpected file type: " << File << ".\n";
StringRef buf = Buffer->getBuffer();
StringRef magic = buf.substr(0, 4);
if (magic == "gcno") {
de = DataExtractor(buf.substr(4), false, 0);
} else if (magic == "oncg") {
de = DataExtractor(buf.substr(4), true, 0);
} else {
errs() << "unexpected magic: " << magic << "\n";
return false;
}
Cursor = 4;
return true;
}
/// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
bool readGCDAFormat() {
StringRef File = Buffer->getBuffer().slice(0, 4);
if (File != "adcg") {
errs() << "Unexpected file type: " << File << ".\n";
StringRef buf = Buffer->getBuffer();
StringRef magic = buf.substr(0, 4);
if (magic == "gcda") {
de = DataExtractor(buf.substr(4), false, 0);
} else if (magic == "adcg") {
de = DataExtractor(buf.substr(4), true, 0);
} else {
errs() << "unexpected file type: " << magic << "\n";
return false;
}
Cursor = 4;
return true;
}
/// readGCOVVersion - Read GCOV version.
bool readGCOVVersion(GCOV::GCOVVersion &Version) {
StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
Cursor += 4;
int Major =
Str[3] >= 'A' ? (Str[3] - 'A') * 10 + Str[2] - '0' : Str[3] - '0';
int Minor = Str[1] - '0';
StringRef str = de.getBytes(cursor, 4);
int Major, Minor;
if (str.size() != 4)
return false;
if (de.isLittleEndian()) {
Major = str[3] >= 'A' ? (str[3] - 'A') * 10 + str[2] - '0' : str[3] - '0';
Minor = str[1] - '0';
} else {
Major = str[0] >= 'A' ? (str[0] - 'A') * 10 + str[1] - '0' : str[0] - '0';
Minor = str[3] - '0';
}
if (Major >= 9) {
// PR gcov-profile/84846, r269678
Version = GCOV::V900;
@ -120,67 +136,25 @@ public:
Version = GCOV::V402;
return true;
}
Cursor -= 4;
errs() << "unexpected version: " << Str << "\n";
errs() << "unexpected version: " << str << "\n";
return false;
}
/// readFunctionTag - If cursor points to a function tag then increment the
/// cursor and return true otherwise return false.
bool readFunctionTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
Tag[3] != '\1') {
return false;
}
Cursor += 4;
return true;
}
/// readBlockTag - If cursor points to a block tag then increment the
/// cursor and return true otherwise return false.
bool readBlockTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
Tag[3] != '\x01') {
return false;
}
Cursor += 4;
return true;
}
/// readEdgeTag - If cursor points to an edge tag then increment the
/// cursor and return true otherwise return false.
bool readEdgeTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
Tag[3] != '\x01') {
return false;
}
Cursor += 4;
return true;
}
/// readLineTag - If cursor points to a line tag then increment the
/// cursor and return true otherwise return false.
bool readLineTag() {
StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
Tag[3] != '\x01') {
return false;
}
Cursor += 4;
return true;
uint32_t getWord() { return de.getU32(cursor); }
StringRef getString() {
uint32_t len;
if (!readInt(len) || len == 0)
return {};
return de.getBytes(cursor, len * 4).split('\0').first;
}
bool readInt(uint32_t &Val) {
if (Buffer->getBuffer().size() < Cursor + 4) {
errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
if (cursor.tell() + 4 > de.size()) {
Val = 0;
errs() << "unexpected end of memory buffer: " << cursor.tell() << "\n";
return false;
}
StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
Cursor += 4;
Val = *(const uint32_t *)(Str.data());
Val = de.getU32(cursor);
return true;
}
@ -193,26 +167,18 @@ public:
}
bool readString(StringRef &Str) {
uint32_t Len;
if (!readInt(Len) || Len == 0)
uint32_t len;
if (!readInt(len) || len == 0)
return false;
Len *= 4;
if (Buffer->getBuffer().size() < Cursor + Len) {
errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
return false;
}
Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
Cursor += Len;
return true;
Str = de.getBytes(cursor, len * 4).split('\0').first;
return bool(cursor);
}
uint64_t getCursor() const { return Cursor; }
void advanceCursor(uint32_t n) { Cursor += n * 4; }
void setCursor(uint64_t c) { Cursor = c; }
DataExtractor de{ArrayRef<uint8_t>{}, false, 0};
DataExtractor::Cursor cursor{0};
private:
MemoryBuffer *Buffer;
uint64_t Cursor = 0;
};
/// GCOVFile - Collects coverage information for one pair of coverage file
@ -259,7 +225,6 @@ public:
GCOVFunction(GCOVFile &P) {}
bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
StringRef getName() const { return Name; }
StringRef getFilename() const { return Filename; }
size_t getNumBlocks() const { return Blocks.size(); }

View File

@ -30,6 +30,9 @@ enum : uint32_t {
GCOV_ARC_FALLTHROUGH = 1 << 2,
GCOV_TAG_FUNCTION = 0x01000000,
GCOV_TAG_BLOCKS = 0x01410000,
GCOV_TAG_ARCS = 0x01430000,
GCOV_TAG_LINES = 0x01450000,
GCOV_TAG_COUNTER_ARCS = 0x01a10000,
// GCOV_TAG_OBJECT_SUMMARY superseded GCOV_TAG_PROGRAM_SUMMARY in GCC 9.
GCOV_TAG_OBJECT_SUMMARY = 0xa1000000,
@ -46,21 +49,89 @@ bool GCOVFile::readGCNO(GCOVBuffer &buf) {
if (!buf.readGCOVVersion(Version))
return false;
if (!buf.readInt(Checksum))
return false;
if (Version >= GCOV::V900 && !buf.readString(cwd))
return false;
uint32_t hasUnexecutedBlocks;
if (Version >= GCOV::V800 && !buf.readInt(hasUnexecutedBlocks))
return false;
while (true) {
if (!buf.readFunctionTag())
break;
auto GFun = std::make_unique<GCOVFunction>(*this);
if (!GFun->readGCNO(buf, Version))
Checksum = buf.getWord();
if (Version >= GCOV::V900)
cwd = buf.getString();
if (Version >= GCOV::V800)
buf.getWord(); // hasUnexecutedBlocks
uint32_t tag, length;
GCOVFunction *fn;
while (buf.readInt(tag) && tag) {
if (!buf.readInt(length))
return false;
IdentToFunction[GFun->ident] = GFun.get();
Functions.push_back(std::move(GFun));
if (tag == GCOV_TAG_FUNCTION) {
Functions.push_back(std::make_unique<GCOVFunction>(*this));
fn = Functions.back().get();
fn->ident = buf.getWord();
fn->linenoChecksum = buf.getWord();
if (Version >= GCOV::V407)
fn->cfgChecksum = buf.getWord();
buf.readString(fn->Name);
if (Version < GCOV::V800) {
buf.readString(fn->Filename);
fn->startLine = buf.getWord();
} else {
fn->artificial = buf.getWord();
fn->Filename = buf.getString();
fn->startLine = buf.getWord();
fn->startColumn = buf.getWord();
fn->endLine = buf.getWord();
if (Version >= GCOV::V900)
fn->endColumn = buf.getWord();
}
IdentToFunction[fn->ident] = fn;
} else if (tag == GCOV_TAG_BLOCKS && fn) {
if (Version < GCOV::V800) {
for (uint32_t i = 0; i != length; ++i) {
buf.getWord(); // Ignored block flags
fn->Blocks.push_back(std::make_unique<GCOVBlock>(*fn, i));
}
} else {
uint32_t num = buf.getWord();
for (uint32_t i = 0; i != num; ++i)
fn->Blocks.push_back(std::make_unique<GCOVBlock>(*fn, i));
}
} else if (tag == GCOV_TAG_ARCS && fn) {
uint32_t srcNo = buf.getWord();
if (srcNo >= fn->Blocks.size()) {
errs() << "unexpected block number: " << srcNo << " (in "
<< fn->Blocks.size() << ")\n";
return false;
}
GCOVBlock *src = fn->Blocks[srcNo].get();
for (uint32_t i = 0, e = (length - 1) / 2; i != e; ++i) {
uint32_t dstNo = buf.getWord(), flags = buf.getWord();
GCOVBlock *dst = fn->Blocks[dstNo].get();
auto arc =
std::make_unique<GCOVArc>(*src, *dst, flags & GCOV_ARC_FALLTHROUGH);
src->addDstEdge(arc.get());
dst->addSrcEdge(arc.get());
if (flags & GCOV_ARC_ON_TREE)
fn->treeArcs.push_back(std::move(arc));
else
fn->arcs.push_back(std::move(arc));
}
} else if (tag == GCOV_TAG_LINES && fn) {
uint32_t srcNo = buf.getWord();
if (srcNo >= fn->Blocks.size()) {
errs() << "unexpected block number: " << srcNo << " (in "
<< fn->Blocks.size() << ")\n";
return false;
}
GCOVBlock &Block = *fn->Blocks[srcNo];
for (;;) {
uint32_t line = buf.getWord();
if (line)
Block.addLine(line);
else {
StringRef filename = buf.getString();
if (filename.empty())
break;
// TODO Unhandled
}
}
}
}
GCNOInitialized = true;
@ -95,7 +166,7 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) {
while (buf.readInt(tag) && tag) {
if (!buf.readInt(length))
return false;
uint32_t cursor = buf.getCursor();
uint32_t pos = buf.cursor.tell();
if (tag == GCOV_TAG_OBJECT_SUMMARY) {
buf.readInt(RunCount);
buf.readInt(dummy);
@ -107,10 +178,8 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) {
} else if (tag == GCOV_TAG_FUNCTION) {
if (length == 0) // Placeholder
continue;
// length>3 is to be compatible with some clang --coverage generated
// tests. As of GCC 10, GCOV_TAG_FUNCTION_LENGTH has never been larger
// than 3.
if (length < 3 || !buf.readInt(ident))
// As of GCC 10, GCOV_TAG_FUNCTION_LENGTH has never been larger than 3.
if (length != 3 || !buf.readInt(ident))
return false;
auto It = IdentToFunction.find(ident);
uint32_t linenoChecksum, cfgChecksum;
@ -146,7 +215,10 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) {
arc->dst.Counter += arc->Count;
}
}
buf.setCursor(cursor + 4 * length);
pos += 4 * length;
if (pos < buf.cursor.tell())
return false;
buf.de.skip(buf.cursor, pos - buf.cursor.tell());
}
return true;
@ -174,145 +246,6 @@ void GCOVFile::collectLineCounts(FileInfo &FI) {
//===----------------------------------------------------------------------===//
// GCOVFunction implementation.
/// readGCNO - Read a function from the GCNO buffer. Return false if an error
/// occurs.
bool GCOVFunction::readGCNO(GCOVBuffer &buf, GCOV::GCOVVersion Version) {
uint32_t Dummy;
if (!buf.readInt(Dummy))
return false; // Function header length
if (!buf.readInt(ident))
return false;
if (!buf.readInt(linenoChecksum))
return false;
if (Version >= GCOV::V407 && !buf.readInt(cfgChecksum))
return false;
if (!buf.readString(Name))
return false;
if (Version < GCOV::V800) {
if (!buf.readString(Filename))
return false;
if (!buf.readInt(startLine))
return false;
} else {
if (!buf.readInt(Dummy))
return false;
artificial = Dummy;
if (!buf.readString(Filename))
return false;
if (!buf.readInt(startLine))
return false;
if (!buf.readInt(startColumn))
return false;
if (!buf.readInt(endLine))
return false;
if (Version >= GCOV::V900 && !buf.readInt(endColumn))
return false;
}
// read blocks.
if (!buf.readBlockTag()) {
errs() << "Block tag not found.\n";
return false;
}
if (Version >= GCOV::V800 && !buf.readInt(Dummy))
return false;
uint32_t BlockCount;
if (!buf.readInt(BlockCount))
return false;
for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
if (Version < GCOV::V800 && !buf.readInt(Dummy))
return false; // Block flags;
Blocks.push_back(std::make_unique<GCOVBlock>(*this, i));
}
// read edges.
while (buf.readEdgeTag()) {
uint32_t EdgeCount;
if (!buf.readInt(EdgeCount))
return false;
EdgeCount = (EdgeCount - 1) / 2;
uint32_t BlockNo;
if (!buf.readInt(BlockNo))
return false;
if (BlockNo >= BlockCount) {
errs() << "Unexpected block number: " << BlockNo << " (in " << Name
<< ").\n";
return false;
}
GCOVBlock *src = Blocks[BlockNo].get();
for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
uint32_t dstNo, flags;
if (!buf.readInt(dstNo))
return false;
if (!buf.readInt(flags))
return false;
GCOVBlock *dst = Blocks[dstNo].get();
auto arc =
std::make_unique<GCOVArc>(*src, *dst, flags & GCOV_ARC_FALLTHROUGH);
src->addDstEdge(arc.get());
dst->addSrcEdge(arc.get());
if (flags & GCOV_ARC_ON_TREE)
treeArcs.push_back(std::move(arc));
else
arcs.push_back(std::move(arc));
}
}
// read line table.
while (buf.readLineTag()) {
uint32_t LineTableLength;
// Read the length of this line table.
if (!buf.readInt(LineTableLength))
return false;
uint32_t EndPos = buf.getCursor() + LineTableLength * 4;
uint32_t BlockNo;
// Read the block number this table is associated with.
if (!buf.readInt(BlockNo))
return false;
if (BlockNo >= BlockCount) {
errs() << "Unexpected block number: " << BlockNo << " (in " << Name
<< ").\n";
return false;
}
GCOVBlock &Block = *Blocks[BlockNo];
// Read the word that pads the beginning of the line table. This may be a
// flag of some sort, but seems to always be zero.
if (!buf.readInt(Dummy))
return false;
// Line information starts here and continues up until the last word.
if (buf.getCursor() != (EndPos - sizeof(uint32_t))) {
StringRef F;
// Read the source file name.
if (!buf.readString(F))
return false;
if (Filename != F) {
// FIXME
errs() << "Multiple sources for a single basic block: " << Filename
<< " != " << F << " (in " << Name << ").\n";
}
// Read lines up to, but not including, the null terminator.
while (buf.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
uint32_t Line;
if (!buf.readInt(Line))
return false;
// Line 0 means this instruction was injected by the compiler. Skip it.
if (!Line)
continue;
Block.addLine(Line);
}
// Read the null terminator.
if (!buf.readInt(Dummy))
return false;
}
// The last word is either a flag or padding, it isn't clear which. Skip
// over it.
if (!buf.readInt(Dummy))
return false;
}
return true;
}
/// getEntryCount - Get the number of times the function was called by
/// retrieving the entry block's count.
uint64_t GCOVFunction::getEntryCount() const {

View File

@ -1,3 +1,4 @@
#include <stdint.h>
struct A {
virtual void B();
};

View File

@ -1,111 +0,0 @@
-: 0:Source:test.cpp
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
-: 1:#include "test.h"
-: 2:#include <cstdlib>
-: 3:
-: 4:bool on = false;
-: 5:int len = 42;
-: 6:double grid[10][10] = {0};
-: 7:const char * hello = "world";
-: 8:const char * world = "hello";
-: 9:
8589934592: 10:void A::B() {}
8589934592: 10-block 0
-: 11:
#####: 12:void useless() {}
$$$$$: 12-block 0
-: 13:
-: 14:double more_useless() {
#####: 15: return 0;
$$$$$: 15-block 0
-: 16:}
-: 17:
-: 18:int foo() {
2: 19: on = true;
2: 20: return 3;
2: 20-block 0
-: 21:}
-: 22:
-: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
$$$$$: 25-block 0
-: 26:}
-: 27:
8: 28:void assign(int ii, int jj) {
8: 29: grid[ii][jj] = (ii+1) * (jj+1);
8: 30:}
8: 30-block 0
-: 31:
-: 32:void initialize_grid() {
6: 33: for (int ii = 0; ii < 2; ii++)
2: 33-block 0
6: 33-block 1
4: 33-block 2
12: 34: for (int jj = 0; jj < 2; jj++)
4: 34-block 0
12: 34-block 1
8: 34-block 2
12: 35: assign(ii, jj);
8: 35-block 0
4: 35-block 1
2: 36:}
2: 36-block 0
-: 37:
-: 38:int main() {
2: 39: initialize_grid();
-: 40:
2: 41: int a = 2;
2: 42: on = rand() % 2;
2: 43: if (on) {
2: 43-block 0
2: 44: foo();
2: 45: ++a;
2: 46: } else {
2: 46-block 0
#####: 47: bar();
#####: 48: a += rand();
$$$$$: 48-block 0
-: 49: }
-: 50:
22: 51: for (int ii = 0; ii < 10; ++ii) {
2: 51-block 0
22: 51-block 1
20: 51-block 2
20: 52: switch (rand() % 5) {
20: 52-block 0
-: 53: case 0:
4: 54: a += rand();
4: 55: break;
4: 55-block 0
-: 56: case 1:
-: 57: case 2:
2: 58: a += rand() / rand();
2: 59: break;
2: 59-block 0
-: 60: case 3:
6: 61: a -= rand();
6: 62: break;
6: 62-block 0
-: 63: default:
8: 64: a = -1;
8: 65: }
8: 65-block 0
20: 66: }
20: 66-block 0
-: 67:
2: 68: A thing;
8589934594: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
2: 69-block 0
8589934594: 69-block 1
8589934592: 69-block 2
8589934592: 70: thing.B();
8589934592: 70-block 0
-: 71:
2: 72: return a + 8 + grid[2][3] + len;
2: 72-block 0
-: 73: return more_useless();
-: 74:}

View File

@ -1,10 +0,0 @@
-: 0:Source:./test.h
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
4: 1:struct A {
2: 1-block 0
2: 1-block 1
-: 2: virtual void B();
-: 3:};

View File

@ -1,134 +0,0 @@
-: 0:Source:test.cpp
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
-: 1:#include "test.h"
-: 2:#include <cstdlib>
-: 3:
-: 4:bool on = false;
-: 5:int len = 42;
-: 6:double grid[10][10] = {0};
-: 7:const char * hello = "world";
-: 8:const char * world = "hello";
-: 9:
function _ZN1A1BEv called 8589934592 returned 100% blocks executed 100%
8589934592: 10:void A::B() {}
8589934592: 10-block 0
-: 11:
function _Z7uselessv called 0 returned 0% blocks executed 0%
#####: 12:void useless() {}
$$$$$: 12-block 0
-: 13:
function _Z12more_uselessv called 0 returned 0% blocks executed 0%
-: 14:double more_useless() {
#####: 15: return 0;
$$$$$: 15-block 0
-: 16:}
-: 17:
function _Z3foov called 2 returned 100% blocks executed 100%
-: 18:int foo() {
2: 19: on = true;
2: 20: return 3;
2: 20-block 0
-: 21:}
-: 22:
function _Z3barv called 0 returned 0% blocks executed 0%
-: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
$$$$$: 25-block 0
-: 26:}
-: 27:
function _Z6assignii called 8 returned 100% blocks executed 100%
8: 28:void assign(int ii, int jj) {
8: 29: grid[ii][jj] = (ii+1) * (jj+1);
8: 30:}
8: 30-block 0
-: 31:
function _Z15initialize_gridv called 2 returned 100% blocks executed 100%
-: 32:void initialize_grid() {
6: 33: for (int ii = 0; ii < 2; ii++)
2: 33-block 0
6: 33-block 1
branch 0 taken 67%
branch 1 taken 33%
4: 33-block 2
12: 34: for (int jj = 0; jj < 2; jj++)
4: 34-block 0
12: 34-block 1
branch 0 taken 67%
branch 1 taken 33%
8: 34-block 2
12: 35: assign(ii, jj);
8: 35-block 0
4: 35-block 1
2: 36:}
2: 36-block 0
-: 37:
function main called 2 returned 100% blocks executed 94%
-: 38:int main() {
2: 39: initialize_grid();
-: 40:
2: 41: int a = 2;
2: 42: on = rand() % 2;
2: 43: if (on) {
2: 43-block 0
branch 0 taken 100%
branch 1 taken 0%
2: 44: foo();
2: 45: ++a;
2: 46: } else {
2: 46-block 0
#####: 47: bar();
#####: 48: a += rand();
$$$$$: 48-block 0
-: 49: }
-: 50:
22: 51: for (int ii = 0; ii < 10; ++ii) {
2: 51-block 0
22: 51-block 1
branch 0 taken 91%
branch 1 taken 9%
20: 51-block 2
20: 52: switch (rand() % 5) {
20: 52-block 0
branch 0 taken 20%
branch 1 taken 0%
branch 2 taken 10%
branch 3 taken 30%
branch 4 taken 40%
-: 53: case 0:
4: 54: a += rand();
4: 55: break;
4: 55-block 0
-: 56: case 1:
-: 57: case 2:
2: 58: a += rand() / rand();
2: 59: break;
2: 59-block 0
-: 60: case 3:
6: 61: a -= rand();
6: 62: break;
6: 62-block 0
-: 63: default:
8: 64: a = -1;
8: 65: }
8: 65-block 0
20: 66: }
20: 66-block 0
-: 67:
2: 68: A thing;
8589934594: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
2: 69-block 0
8589934594: 69-block 1
branch 0 taken 99%
branch 1 taken 1%
8589934592: 69-block 2
8589934592: 70: thing.B();
8589934592: 70-block 0
-: 71:
2: 72: return a + 8 + grid[2][3] + len;
2: 72-block 0
-: 73: return more_useless();
-: 74:}

View File

@ -1,12 +0,0 @@
-: 0:Source:./test.h
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
function _ZN1AC1Ev called 2 returned 100% blocks executed 100%
function _ZN1AC2Ev called 2 returned 100% blocks executed 100%
4: 1:struct A {
2: 1-block 0
2: 1-block 1
-: 2: virtual void B();
-: 3:};

View File

@ -1,160 +0,0 @@
-: 0:Source:test.cpp
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
-: 1:#include "test.h"
-: 2:#include <cstdlib>
-: 3:
-: 4:bool on = false;
-: 5:int len = 42;
-: 6:double grid[10][10] = {0};
-: 7:const char * hello = "world";
-: 8:const char * world = "hello";
-: 9:
function _ZN1A1BEv called 8589934592 returned 100% blocks executed 100%
8589934592: 10:void A::B() {}
8589934592: 10-block 0
unconditional 0 taken 8589934592
-: 11:
function _Z7uselessv called 0 returned 0% blocks executed 0%
#####: 12:void useless() {}
$$$$$: 12-block 0
unconditional 0 never executed
-: 13:
function _Z12more_uselessv called 0 returned 0% blocks executed 0%
-: 14:double more_useless() {
#####: 15: return 0;
$$$$$: 15-block 0
unconditional 0 never executed
-: 16:}
-: 17:
function _Z3foov called 2 returned 100% blocks executed 100%
-: 18:int foo() {
2: 19: on = true;
2: 20: return 3;
2: 20-block 0
unconditional 0 taken 2
-: 21:}
-: 22:
function _Z3barv called 0 returned 0% blocks executed 0%
-: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
$$$$$: 25-block 0
unconditional 0 never executed
-: 26:}
-: 27:
function _Z6assignii called 8 returned 100% blocks executed 100%
8: 28:void assign(int ii, int jj) {
8: 29: grid[ii][jj] = (ii+1) * (jj+1);
8: 30:}
8: 30-block 0
unconditional 0 taken 8
-: 31:
function _Z15initialize_gridv called 2 returned 100% blocks executed 100%
-: 32:void initialize_grid() {
6: 33: for (int ii = 0; ii < 2; ii++)
2: 33-block 0
unconditional 0 taken 2
6: 33-block 1
branch 1 taken 4
branch 2 taken 2
4: 33-block 2
unconditional 3 taken 4
12: 34: for (int jj = 0; jj < 2; jj++)
4: 34-block 0
unconditional 0 taken 4
12: 34-block 1
branch 1 taken 8
branch 2 taken 4
8: 34-block 2
unconditional 3 taken 8
12: 35: assign(ii, jj);
8: 35-block 0
unconditional 0 taken 8
4: 35-block 1
unconditional 1 taken 4
2: 36:}
2: 36-block 0
unconditional 0 taken 2
-: 37:
function main called 2 returned 100% blocks executed 94%
-: 38:int main() {
2: 39: initialize_grid();
-: 40:
2: 41: int a = 2;
2: 42: on = rand() % 2;
2: 43: if (on) {
2: 43-block 0
branch 0 taken 2
branch 1 taken 0
2: 44: foo();
2: 45: ++a;
2: 46: } else {
2: 46-block 0
unconditional 0 taken 2
#####: 47: bar();
#####: 48: a += rand();
$$$$$: 48-block 0
unconditional 0 never executed
-: 49: }
-: 50:
22: 51: for (int ii = 0; ii < 10; ++ii) {
2: 51-block 0
unconditional 0 taken 2
22: 51-block 1
branch 1 taken 20
branch 2 taken 2
20: 51-block 2
unconditional 3 taken 20
20: 52: switch (rand() % 5) {
20: 52-block 0
branch 0 taken 4
branch 1 taken 0
branch 2 taken 2
branch 3 taken 6
branch 4 taken 8
-: 53: case 0:
4: 54: a += rand();
4: 55: break;
4: 55-block 0
unconditional 0 taken 4
-: 56: case 1:
-: 57: case 2:
2: 58: a += rand() / rand();
2: 59: break;
2: 59-block 0
unconditional 0 taken 2
-: 60: case 3:
6: 61: a -= rand();
6: 62: break;
6: 62-block 0
unconditional 0 taken 6
-: 63: default:
8: 64: a = -1;
8: 65: }
8: 65-block 0
unconditional 0 taken 8
20: 66: }
20: 66-block 0
unconditional 0 taken 20
-: 67:
2: 68: A thing;
8589934594: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
2: 69-block 0
unconditional 0 taken 2
8589934594: 69-block 1
branch 1 taken 8589934592
branch 2 taken 2
8589934592: 69-block 2
unconditional 3 taken 8589934592
8589934592: 70: thing.B();
8589934592: 70-block 0
unconditional 0 taken 8589934592
-: 71:
2: 72: return a + 8 + grid[2][3] + len;
2: 72-block 0
unconditional 0 taken 2
-: 73: return more_useless();
-: 74:}

View File

@ -1,14 +0,0 @@
-: 0:Source:./test.h
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
function _ZN1AC1Ev called 2 returned 100% blocks executed 100%
function _ZN1AC2Ev called 2 returned 100% blocks executed 100%
4: 1:struct A {
2: 1-block 0
unconditional 0 taken 2
2: 1-block 1
unconditional 1 taken 2
-: 2: virtual void B();
-: 3:};

View File

@ -1,160 +0,0 @@
-: 0:Source:test.cpp
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
-: 1:#include "test.h"
-: 2:#include <cstdlib>
-: 3:
-: 4:bool on = false;
-: 5:int len = 42;
-: 6:double grid[10][10] = {0};
-: 7:const char * hello = "world";
-: 8:const char * world = "hello";
-: 9:
function _ZN1A1BEv called 8589934592 returned 100% blocks executed 100%
8589934592: 10:void A::B() {}
8589934592: 10-block 0
unconditional 0 taken 100%
-: 11:
function _Z7uselessv called 0 returned 0% blocks executed 0%
#####: 12:void useless() {}
$$$$$: 12-block 0
unconditional 0 never executed
-: 13:
function _Z12more_uselessv called 0 returned 0% blocks executed 0%
-: 14:double more_useless() {
#####: 15: return 0;
$$$$$: 15-block 0
unconditional 0 never executed
-: 16:}
-: 17:
function _Z3foov called 2 returned 100% blocks executed 100%
-: 18:int foo() {
2: 19: on = true;
2: 20: return 3;
2: 20-block 0
unconditional 0 taken 100%
-: 21:}
-: 22:
function _Z3barv called 0 returned 0% blocks executed 0%
-: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
$$$$$: 25-block 0
unconditional 0 never executed
-: 26:}
-: 27:
function _Z6assignii called 8 returned 100% blocks executed 100%
8: 28:void assign(int ii, int jj) {
8: 29: grid[ii][jj] = (ii+1) * (jj+1);
8: 30:}
8: 30-block 0
unconditional 0 taken 100%
-: 31:
function _Z15initialize_gridv called 2 returned 100% blocks executed 100%
-: 32:void initialize_grid() {
6: 33: for (int ii = 0; ii < 2; ii++)
2: 33-block 0
unconditional 0 taken 100%
6: 33-block 1
branch 1 taken 67%
branch 2 taken 33%
4: 33-block 2
unconditional 3 taken 100%
12: 34: for (int jj = 0; jj < 2; jj++)
4: 34-block 0
unconditional 0 taken 100%
12: 34-block 1
branch 1 taken 67%
branch 2 taken 33%
8: 34-block 2
unconditional 3 taken 100%
12: 35: assign(ii, jj);
8: 35-block 0
unconditional 0 taken 100%
4: 35-block 1
unconditional 1 taken 100%
2: 36:}
2: 36-block 0
unconditional 0 taken 100%
-: 37:
function main called 2 returned 100% blocks executed 94%
-: 38:int main() {
2: 39: initialize_grid();
-: 40:
2: 41: int a = 2;
2: 42: on = rand() % 2;
2: 43: if (on) {
2: 43-block 0
branch 0 taken 100%
branch 1 taken 0%
2: 44: foo();
2: 45: ++a;
2: 46: } else {
2: 46-block 0
unconditional 0 taken 100%
#####: 47: bar();
#####: 48: a += rand();
$$$$$: 48-block 0
unconditional 0 never executed
-: 49: }
-: 50:
22: 51: for (int ii = 0; ii < 10; ++ii) {
2: 51-block 0
unconditional 0 taken 100%
22: 51-block 1
branch 1 taken 91%
branch 2 taken 9%
20: 51-block 2
unconditional 3 taken 100%
20: 52: switch (rand() % 5) {
20: 52-block 0
branch 0 taken 20%
branch 1 taken 0%
branch 2 taken 10%
branch 3 taken 30%
branch 4 taken 40%
-: 53: case 0:
4: 54: a += rand();
4: 55: break;
4: 55-block 0
unconditional 0 taken 100%
-: 56: case 1:
-: 57: case 2:
2: 58: a += rand() / rand();
2: 59: break;
2: 59-block 0
unconditional 0 taken 100%
-: 60: case 3:
6: 61: a -= rand();
6: 62: break;
6: 62-block 0
unconditional 0 taken 100%
-: 63: default:
8: 64: a = -1;
8: 65: }
8: 65-block 0
unconditional 0 taken 100%
20: 66: }
20: 66-block 0
unconditional 0 taken 100%
-: 67:
2: 68: A thing;
8589934594: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
2: 69-block 0
unconditional 0 taken 100%
8589934594: 69-block 1
branch 1 taken 99%
branch 2 taken 1%
8589934592: 69-block 2
unconditional 3 taken 100%
8589934592: 70: thing.B();
8589934592: 70-block 0
unconditional 0 taken 100%
-: 71:
2: 72: return a + 8 + grid[2][3] + len;
2: 72-block 0
unconditional 0 taken 100%
-: 73: return more_useless();
-: 74:}

View File

@ -1,14 +0,0 @@
-: 0:Source:./test.h
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Programs:1
function _ZN1AC1Ev called 2 returned 100% blocks executed 100%
function _ZN1AC2Ev called 2 returned 100% blocks executed 100%
4: 1:struct A {
2: 1-block 0
unconditional 0 taken 100%
2: 1-block 1
unconditional 1 taken 100%
-: 2: virtual void B();
-: 3:};

View File

@ -5,7 +5,7 @@ No calls
./test.h:creating 'test.h.gcov'
File 'test.cpp'
Lines executed:84.21% of 38
Lines executed:81.40% of 43
Branches executed:100.00% of 15
Taken at least once:86.67% of 15
No calls

View File

@ -1,6 +1,3 @@
Function '_ZN1AC1Ev'
Lines executed:100.00% of 1
Function '_ZN1AC2Ev'
Lines executed:100.00% of 1
@ -11,28 +8,28 @@ Function '_Z7uselessv'
Lines executed:0.00% of 1
Function '_Z12more_uselessv'
Lines executed:0.00% of 1
Lines executed:0.00% of 2
Function '_Z3foov'
Lines executed:100.00% of 2
Lines executed:100.00% of 3
Function '_Z3barv'
Lines executed:0.00% of 2
Lines executed:0.00% of 3
Function '_Z6assignii'
Lines executed:100.00% of 3
Function '_Z15initialize_gridv'
Lines executed:100.00% of 4
Lines executed:100.00% of 5
Function 'main'
Lines executed:91.67% of 24
Lines executed:92.00% of 25
File './test.h'
Lines executed:100.00% of 1
./test.h:creating 'test.h.gcov'
File 'test.cpp'
Lines executed:84.21% of 38
Lines executed:81.40% of 43
test.cpp:creating 'test.cpp.gcov'

View File

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

View File

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

View File

@ -1,77 +0,0 @@
-: 0:Source:srcdir/./nested_dir/../test.cpp
-: 0:Graph:test_paths.gcno
-: 0:Data:test_paths.gcda
-: 0:Runs:0
-: 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*/
9: 33:/*EOF*/
18: 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*/
33: 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*/
12884901891: 69:/*EOF*/
12884901888: 70:/*EOF*/
-: 71:/*EOF*/
3: 72:/*EOF*/

View File

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

View File

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

View File

@ -16,16 +16,16 @@
-: 11:
#####: 12:void useless() {}
-: 13:
-: 14:double more_useless() {
#####: 14:double more_useless() {
#####: 15: return 0;
-: 16:}
-: 17:
-: 18:int foo() {
#####: 18:int foo() {
#####: 19: on = true;
#####: 20: return 3;
-: 21:}
-: 22:
-: 23:int bar() {
#####: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
-: 26:}
@ -34,13 +34,13 @@
#####: 29: grid[ii][jj] = (ii+1) * (jj+1);
#####: 30:}
-: 31:
-: 32:void initialize_grid() {
#####: 32:void initialize_grid() {
#####: 33: for (int ii = 0; ii < 2; ii++)
#####: 34: for (int jj = 0; jj < 2; jj++)
#####: 35: assign(ii, jj);
#####: 36:}
-: 37:
-: 38:int main() {
#####: 38:int main() {
#####: 39: initialize_grid();
-: 40:
#####: 41: int a = 2;

View File

@ -3,6 +3,7 @@
-: 0:Data:-
-: 0:Runs:0
-: 0:Programs:0
#####: 1:struct A {
-: 2: virtual void B();
-: 3:};
-: 1:#include <stdint.h>
#####: 2:struct A {
-: 3: virtual void B();
-: 4:};

View File

@ -3,6 +3,6 @@ Lines executed:0.00% of 1
./test.h:creating 'test.h.gcov'
File 'test.cpp'
Lines executed:0.00% of 38
Lines executed:0.00% of 43
test.cpp:creating 'test.cpp.gcov'

View File

@ -1,7 +1,7 @@
-: 0:Source:test.cpp
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include "test.h"
-: 2:#include <cstdlib>
@ -12,68 +12,68 @@
-: 7:const char * hello = "world";
-: 8:const char * world = "hello";
-: 9:
8589934592: 10:void A::B() {}
4294967296: 10:void A::B() {}
-: 11:
#####: 12:void useless() {}
-: 13:
-: 14:double more_useless() {
#####: 14:double more_useless() {
#####: 15: return 0;
-: 16:}
-: 17:
-: 18:int foo() {
2: 19: on = true;
2: 20: return 3;
1: 18:int foo() {
1: 19: on = true;
1: 20: return 3;
-: 21:}
-: 22:
-: 23:int bar() {
#####: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
-: 26:}
-: 27:
8: 28:void assign(int ii, int jj) {
8: 29: grid[ii][jj] = (ii+1) * (jj+1);
8: 30:}
4: 28:void assign(int ii, int jj) {
4: 29: grid[ii][jj] = (ii+1) * (jj+1);
4: 30:}
-: 31:
-: 32:void initialize_grid() {
6: 33: for (int ii = 0; ii < 2; ii++)
12: 34: for (int jj = 0; jj < 2; jj++)
12: 35: assign(ii, jj);
2: 36:}
1: 32:void initialize_grid() {
3: 33: for (int ii = 0; ii < 2; ii++)
6: 34: for (int jj = 0; jj < 2; jj++)
6: 35: assign(ii, jj);
1: 36:}
-: 37:
-: 38:int main() {
2: 39: initialize_grid();
1: 38:int main() {
1: 39: initialize_grid();
-: 40:
2: 41: int a = 2;
2: 42: on = rand() % 2;
2: 43: if (on) {
2: 44: foo();
2: 45: ++a;
2: 46: } else {
1: 41: int a = 2;
1: 42: on = rand() % 2;
1: 43: if (on) {
1: 44: foo();
1: 45: ++a;
1: 46: } else {
#####: 47: bar();
#####: 48: a += rand();
-: 49: }
-: 50:
22: 51: for (int ii = 0; ii < 10; ++ii) {
20: 52: switch (rand() % 5) {
11: 51: for (int ii = 0; ii < 10; ++ii) {
10: 52: switch (rand() % 5) {
-: 53: case 0:
4: 54: a += rand();
4: 55: break;
2: 54: a += rand();
2: 55: break;
-: 56: case 1:
-: 57: case 2:
2: 58: a += rand() / rand();
2: 59: break;
4: 58: a += rand() / rand();
4: 59: break;
-: 60: case 3:
6: 61: a -= rand();
6: 62: break;
3: 61: a -= rand();
3: 62: break;
-: 63: default:
8: 64: a = -1;
8: 65: }
20: 66: }
1: 64: a = -1;
1: 65: }
10: 66: }
-: 67:
2: 68: A thing;
8589934594: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
8589934592: 70: thing.B();
1: 68: A thing;
4294967297: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
4294967296: 70: thing.B();
-: 71:
2: 72: return a + 8 + grid[2][3] + len;
1: 72: return a + 8 + grid[2][3] + len;
-: 73: return more_useless();
-: 74:}

View File

@ -1,8 +1,9 @@
-: 0:Source:./test.h
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 0:Runs:0
-: 0:Runs:1
-: 0:Programs:1
4: 1:struct A {
-: 2: virtual void B();
-: 3:};
-: 1:#include <stdint.h>
1: 2:struct A {
-: 3: virtual void B();
-: 4:};

View File

@ -3,6 +3,6 @@ Lines executed:100.00% of 1
./test.h:creating 'test.h.gcov'
File 'test.cpp'
Lines executed:84.21% of 38
Lines executed:81.40% of 43
test.cpp:creating 'test.cpp.gcov'

View File

@ -2,5 +2,5 @@ File './test.h'
Lines executed:100.00% of 1
File 'test.cpp'
Lines executed:84.21% of 38
Lines executed:81.40% of 43

View File

@ -1,79 +0,0 @@
-: 0:Source:test.cpp
-: 0:Graph:objdir/test.gcno
-: 0:Data:objdir/test.gcda
-: 0:Runs:0
-: 0:Programs:1
-: 1:#include "test.h"
-: 2:#include <cstdlib>
-: 3:
-: 4:bool on = false;
-: 5:int len = 42;
-: 6:double grid[10][10] = {0};
-: 7:const char * hello = "world";
-: 8:const char * world = "hello";
-: 9:
8589934592: 10:void A::B() {}
-: 11:
#####: 12:void useless() {}
-: 13:
-: 14:double more_useless() {
#####: 15: return 0;
-: 16:}
-: 17:
-: 18:int foo() {
2: 19: on = true;
2: 20: return 3;
-: 21:}
-: 22:
-: 23:int bar() {
#####: 24: len--;
#####: 25: return foo() + 45;
-: 26:}
-: 27:
8: 28:void assign(int ii, int jj) {
8: 29: grid[ii][jj] = (ii+1) * (jj+1);
8: 30:}
-: 31:
-: 32:void initialize_grid() {
6: 33: for (int ii = 0; ii < 2; ii++)
12: 34: for (int jj = 0; jj < 2; jj++)
12: 35: assign(ii, jj);
2: 36:}
-: 37:
-: 38:int main() {
2: 39: initialize_grid();
-: 40:
2: 41: int a = 2;
2: 42: on = rand() % 2;
2: 43: if (on) {
2: 44: foo();
2: 45: ++a;
2: 46: } else {
#####: 47: bar();
#####: 48: a += rand();
-: 49: }
-: 50:
22: 51: for (int ii = 0; ii < 10; ++ii) {
20: 52: switch (rand() % 5) {
-: 53: case 0:
4: 54: a += rand();
4: 55: break;
-: 56: case 1:
-: 57: case 2:
2: 58: a += rand() / rand();
2: 59: break;
-: 60: case 3:
6: 61: a -= rand();
6: 62: break;
-: 63: default:
8: 64: a = -1;
8: 65: }
20: 66: }
-: 67:
2: 68: A thing;
8589934594: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
8589934592: 70: thing.B();
-: 71:
2: 72: return a + 8 + grid[2][3] + len;
-: 73: return more_useless();
-: 74:}

View File

@ -1,8 +0,0 @@
-: 0:Source:./test.h
-: 0:Graph:objdir/test.gcno
-: 0:Data:objdir/test.gcda
-: 0:Runs:0
-: 0:Programs:1
4: 1:struct A {
-: 2: virtual void B();
-: 3:};

View File

@ -1,5 +1,5 @@
File 'srcdir/./nested_dir/../test.cpp'
Lines executed:84.21% of 38
File 'src/./n/../a.c'
Lines executed:100.00% of 1
srcdir/./nested_dir/../test.cpp:creating 'srcdir#nested_dir#^#test.cpp.gcov'
File 'srcdir/./nested_dir/../test.h'

View File

@ -1,32 +0,0 @@
// Make sure that compiler-added functions (whose line number is zero) don't
// crash llvm-cov.
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: cd %t
// RUN: cp %s %p/Inputs/copy_block_helper.gc* .
// RUN: llvm-cov gcov copy_block_helper.m | FileCheck %s --check-prefix=STDOUT
// STDOUT: File 'copy_block_helper.m'
// STDOUT: Lines executed:100.00% of 5
// STDOUT: copy_block_helper.m:creating 'copy_block_helper.m.gcov'
// RUN: FileCheck %s --check-prefix=GCOV < %t/copy_block_helper.m.gcov
// GCOV: -: 0:Runs:1
// GCOV: -: 0:Programs:1
id test_helper(id (^foo)(void)) { return foo(); } // GCOV: 1: [[@LINE]]:id
void test(id x) { // GCOV: -: [[@LINE]]:void test
test_helper(^{ // GCOV: 2: [[@LINE]]: test_helper
return x; // GCOV: 1: [[@LINE]]: return
}); // GCOV: -: [[@LINE]]:
} // GCOV: 1: [[@LINE]]:}
// GCOV: 1: [[@LINE+1]]:int main
int main(int argc, const char *argv[]) { test(0); }
// llvm-cov doesn't work on big endian yet
// XFAIL: host-byteorder-big-endian

View File

@ -12,25 +12,24 @@ RUN: cp %p/Inputs/test* .
# Basic behaviour with no flags
RUN: llvm-cov gcov test.c | diff -u test_no_options.output -
RUN: diff -aub test_no_options.cpp.gcov test.cpp.gcov
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefix=C
RUN: diff -aub test_no_options.h.gcov test.h.gcov
# Same, but specifying the object directory
RUN: mkdir -p %t/objdir
RUN: cp test.gcno test.gcda %t/objdir
RUN: llvm-cov gcov -o objdir 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
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefix=OBJDIR
OBJDIR: 0:Graph:objdir/test.gcno
OBJDIR-NEXT: 0:Data:objdir/test.gcda
# Specifying an object file
RUN: llvm-cov gcov -o objdir/test.o 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
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefix=OBJDIR
# Specifying an object file that could be ambiguous with a directory
RUN: llvm-cov gcov -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
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefix=OBJDIR
# With gcov output disabled
RUN: llvm-cov gcov -n test.c | diff -u test_no_output.output -
@ -41,72 +40,58 @@ RUN: llvm-cov gcov --stdout test.c | cmp stdout -
RUN: cat test_no_options.h.gcov test_no_options.cpp.gcov | diff -u - stdout
RUN: llvm-cov gcov -n -t test.c | count 0
# 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 gcov 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
RUN: llvm-cov gcov test_paths.cpp 2>/dev/null | FileCheck %s --check-prefix=MISSING
RUN: ls a.c.gcov
MISSING: File 'src/./n/../a.c'
MISSING: src/./n/../a.c:creating 'a.c.gcov'
# Preserve paths. This mangles the output filenames.
RUN: mkdir -p %t/srcdir/nested_dir
RUN: cp test.cpp test.h %t/srcdir
RUN: llvm-cov gcov -p test_paths.cpp | diff -u test_preserve_paths.output -
RUN: diff -aub test_paths.cpp.gcov srcdir#nested_dir#^#test.cpp.gcov
RUN: diff -aub test_paths.h.gcov srcdir#nested_dir#^#test.h.gcov
# Don't preserve paths. Same results as preserve paths, but no mangling.
RUN: llvm-cov gcov test_paths.cpp | diff -u test_no_preserve_paths.output -
RUN: diff -aub test_paths.cpp.gcov test.cpp.gcov
RUN: diff -aub test_paths.h.gcov test.h.gcov
RUN: llvm-cov gcov -p test_paths.cpp 2>/dev/null | FileCheck %s --check-prefix=PRESERVE
RUN: ls src#n#^#a.c.gcov
PRESERVE: File 'src/./n/../a.c'
PRESERVE: src/./n/../a.c:creating 'src#n#^#a.c.gcov'
# Long file names.
RUN: llvm-cov gcov -l test_paths.cpp | diff -u test_long_file_names.output -
RUN: diff -aub test_paths.cpp.gcov test_paths.cpp##test.cpp.gcov
RUN: diff -aub test_paths.h.gcov test_paths.cpp##test.h.gcov
RUN: llvm-cov gcov -l test_paths.cpp
RUN: ls test_paths.cpp##a.c.gcov
# Long file names and preserve paths.
RUN: llvm-cov gcov -lp -gcno test_paths.gcno -gcda test_paths.gcda srcdir/../test_paths.cpp | diff -u test_long_paths.output -
RUN: diff -aub test_paths.cpp.gcov srcdir#^#test_paths.cpp##srcdir#nested_dir#^#test.cpp.gcov
RUN: diff -aub test_paths.h.gcov srcdir#^#test_paths.cpp##srcdir#nested_dir#^#test.h.gcov
RUN: mkdir -p src && llvm-cov gcov -lp -gcno test_paths.gcno -gcda test_paths.gcda src/../test_paths.cpp
RUN: ls src#^#test_paths.cpp##src#n#^#a.c.gcov
# Hash pathnames.
RUN: llvm-cov gcov -x -gcno test_paths.gcno -gcda test_paths.gcda srcdir/../test_paths.cpp | diff -u test_hash.output -
RUN: diff -aub test_paths.cpp.gcov test.cpp##a806e5b3093cd6f683da88c0da150daf.gcov
RUN: diff -aub test_paths.h.gcov test.h##0cbee7e2421fa4517420ac4f935620ca.gcov
RUN: llvm-cov gcov -x -gcno test_paths.gcno -gcda test_paths.gcda src/../test_paths.cpp
RUN: ls a.c##4784150e272908907eaa7380ca3eced8.gcov
# Function summaries. This changes stdout, but not the gcov files.
RUN: llvm-cov gcov test.c -f | diff -u test_-f.output -
RUN: diff -aub test_no_options.cpp.gcov test.cpp.gcov
RUN: diff -aub test_no_options.h.gcov test.h.gcov
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefix=C
RUN: FileCheck --input-file=test.h.gcov %s --check-prefix=H
# All blocks. This doesn't affect stdout, only the gcov files.
RUN: llvm-cov gcov test.c -a | diff -u test_no_options.output -
RUN: diff -aub test_-a.cpp.gcov test.cpp.gcov
RUN: diff -aub test_-a.h.gcov test.h.gcov
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefixes=C,C-A
RUN: FileCheck --input-file=test.h.gcov %s --check-prefixes=H,H-A
# Branch probabilities.
RUN: llvm-cov gcov test.c -a -b | diff -u test_-b.output -
RUN-DIABLED: diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
RUN: diff -aub test_-a_-b.h.gcov test.h.gcov
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefixes=C,C-A,C-B
RUN: FileCheck --input-file=test.h.gcov %s --check-prefixes=H,H-A,H-B
# Function summaries including branch probabilities.
# FIXME: We don't correctly handle calls when -b and -f are used
# together, so our output differs from gcov. Remove the 'not' from
# this test once this is fixed.
RUN: llvm-cov gcov test.c -a -b -f | not diff -u test_-b_-f.output - >/dev/null
RUN-DISABLED: diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
RUN: diff -aub test_-a_-b.h.gcov test.h.gcov
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefixes=C,C-A,C-B
RUN: FileCheck --input-file=test.h.gcov %s --check-prefixes=H,H-A,H-B
# Summarize unconditional branches too.
RUN: llvm-cov gcov test.c -a -b -u | diff -u test_-b.output -
RUN-DIABLED: diff -aub test_-a_-b_-u.cpp.gcov test.cpp.gcov
RUN: diff -aub test_-a_-b_-u.h.gcov test.h.gcov
RUN: FileCheck --input-file=test.cpp.gcov %s --check-prefixes=C,C-A,C-B,C-U
RUN: FileCheck --input-file=test.h.gcov %s --check-prefixes=H,H-A,H-B,H-U
# Absolute counts for branches.
RUN: llvm-cov gcov test.c -a -b -c -u | diff -u test_-b.output -
RUN-DISABLED: diff -aub test_-a_-b_-c_-u.cpp.gcov test.cpp.gcov
RUN: diff -aub test_-a_-b_-c_-u.h.gcov test.h.gcov
RUN: llvm-cov gcov test.c -a -b -c -u
RUN: FileCheck --input-file=test.h.gcov %s --check-prefix=H-C
H-C: unconditional 0 taken 1
# Missing gcda file just gives 0 counts.
RUN: llvm-cov gcov test.c -gcda=no_such_gcda_file | diff -u test_no_gcda.output -
@ -126,4 +111,193 @@ RUN: llvm-cov gcov test.c -gcda=test_func_checksum_fail.gcda
RUN-DISABLED: llvm-cov gcov test_exit_block_arcs.c 2>&1 | FileCheck %s -check-prefix=EXIT_BLOCK_ARCS
EXIT_BLOCK_ARCS: (main) has arcs from exit block.
XFAIL: host-byteorder-big-endian
C: -: 0:Source:test.cpp
C-NEXT: -: 0:Graph:test.gcno
C-NEXT: -: 0:Data:test.gcda
C-NEXT: -: 0:Runs:1
C-NEXT: -: 0:Programs:1
C-NEXT: -: 1:#include "test.h"
C-NEXT: -: 2:#include <cstdlib>
C-NEXT: -: 3:
C-NEXT: -: 4:bool on = false;
C-NEXT: -: 5:int len = 42;
C-NEXT: -: 6:double grid[10][10] = {0};
C-NEXT: -: 7:const char * hello = "world";
C-NEXT: -: 8:const char * world = "hello";
C-NEXT: -: 9:
C-B:function _ZN1A1BEv called 4294967296 returned 100% blocks executed 100%
C-NEXT:4294967296: 10:void A::B() {}
C-A:4294967296: 10-block 0
C-U:unconditional 0 taken 100%
C-A:4294967296: 10-block 1
C-U:unconditional 1 taken 100%
C-NEXT: -: 11:
C-B:function _Z7uselessv called 0 returned 0% blocks executed 0%
C-NEXT: #####: 12:void useless() {}
C-A: $$$$$: 12-block 0
C-U:unconditional 0 never executed
C-A: $$$$$: 12-block 1
C-U:unconditional 1 never executed
C-NEXT: -: 13:
C-B:function _Z12more_uselessv called 0 returned 0% blocks executed 0%
C-NEXT: #####: 14:double more_useless() {
C-NEXT: #####: 15: return 0;
C-A: $$$$$: 15-block 0
C-U:unconditional 0 never executed
C-A: $$$$$: 15-block 1
C-U:unconditional 1 never executed
C-NEXT: -: 16:}
C-NEXT: -: 17:
C-B:function _Z3foov called 1 returned 100% blocks executed 100%
C-NEXT: 1: 18:int foo() {
C-NEXT: 1: 19: on = true;
C-A: 1: 19-block 0
C-U:unconditional 0 taken 100%
C-NEXT: 1: 20: return 3;
C-A: 1: 20-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 21:}
C-NEXT: -: 22:
C-B:function _Z3barv called 0 returned 0% blocks executed 0%
C-NEXT: #####: 23:int bar() {
C-NEXT: #####: 24: len--;
C-A: $$$$$: 24-block 0
C-U:unconditional 0 never executed
C-NEXT: #####: 25: return foo() + 45;
C-A: $$$$$: 25-block 0
C-U:unconditional 0 never executed
C-NEXT: -: 26:}
C-NEXT: -: 27:
C-B:function _Z6assignii called 4 returned 100% blocks executed 100%
C-NEXT: 4: 28:void assign(int ii, int jj) {
C-A: 4: 28-block 0
C-U:unconditional 0 taken 100%
C-NEXT: 4: 29: grid[ii][jj] = (ii+1) * (jj+1);
C-NEXT: 4: 30:}
C-A: 4: 30-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 31:
C-B:function _Z15initialize_gridv called 1 returned 100% blocks executed 100%
C-NEXT: 1: 32:void initialize_grid() {
C-NEXT: 3: 33: for (int ii = 0; ii < 2; ii++)
C-A: 1: 33-block 0
C-U:unconditional 0 taken 100%
C-A: 1: 33-block 1
C-U:unconditional 1 taken 100%
C-A: 3: 33-block 2
C-B:branch {{[02]}} taken 67%
C-B:branch {{[13]}} taken 33%
C-A: 2: 33-block 3
C-U:unconditional 4 taken 100%
C-NEXT: 6: 34: for (int jj = 0; jj < 2; jj++)
C-A: 2: 34-block 0
C-U:unconditional 0 taken 100%
C-A: 6: 34-block 1
C-B:branch {{[01]}} taken 67%
C-B:branch {{[12]}} taken 33%
C-A: 4: 34-block 2
C-U:unconditional 3 taken 100%
C-NEXT: 6: 35: assign(ii, jj);
C-A: 4: 35-block 0
C-U:unconditional 0 taken 100%
C-A: 2: 35-block 1
C-U:unconditional 1 taken 100%
C-NEXT: 1: 36:}
C-A: 1: 36-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 37:
C-B:function main called 1 returned 100% blocks executed 94%
C-NEXT: 1: 38:int main() {
C-A: 1: 38-block 0
C-U:unconditional 0 taken 100%
C-NEXT: 1: 39: initialize_grid();
C-NEXT: -: 40:
C-NEXT: 1: 41: int a = 2;
C-NEXT: 1: 42: on = rand() % 2;
C-NEXT: 1: 43: if (on) {
C-A: 1: 43-block 0
C-B:branch 0 taken 100%
C-B:branch 1 taken 0%
C-NEXT: 1: 44: foo();
C-NEXT: 1: 45: ++a;
C-NEXT: 1: 46: } else {
C-A: 1: 46-block 0
C-U:unconditional 0 taken 100%
C-NEXT: #####: 47: bar();
C-NEXT: #####: 48: a += rand();
C-A: $$$$$: 48-block 0
C-U:unconditional 0 never executed
C-NEXT: -: 49: }
C-NEXT: -: 50:
C-NEXT: 11: 51: for (int ii = 0; ii < 10; ++ii) {
C-A: 1: 51-block 0
C-U:unconditional 0 taken 100%
C-A: 11: 51-block 1
C-B:branch {{[01]}} taken 91%
C-B:branch {{[12]}} taken 9%
C-A: 10: 51-block 2
C-U:unconditional 3 taken 100%
C-NEXT: 10: 52: switch (rand() % 5) {
C-A: 10: 52-block 0
C-B:branch 0 taken 10%
C-B:branch 1 taken 20%
C-B:branch 2 taken 0%
C-B:branch 3 taken 40%
C-B:branch 4 taken 30%
C-NEXT: -: 53: case 0:
C-NEXT: 2: 54: a += rand();
C-NEXT: 2: 55: break;
C-A: 2: 55-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 56: case 1:
C-NEXT: -: 57: case 2:
C-NEXT: 4: 58: a += rand() / rand();
C-NEXT: 4: 59: break;
C-A: 4: 59-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 60: case 3:
C-NEXT: 3: 61: a -= rand();
C-NEXT: 3: 62: break;
C-A: 3: 62-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 63: default:
C-NEXT: 1: 64: a = -1;
C-NEXT: 1: 65: }
C-A: 1: 65-block 0
C-U:unconditional 0 taken 100%
C-NEXT: 10: 66: }
C-A: 10: 66-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 67:
C-NEXT: 1: 68: A thing;
C-NEXT:4294967297: 69: for (uint64_t ii = 0; ii < 4294967296; ++ii)
C-A: 1: 69-block 0
C-U:unconditional 0 taken 100%
C-A:4294967297: 69-block 1
C-B:branch {{[01]}} taken 99%
C-B:branch {{[12]}} taken 1%
C-A:4294967296: 69-block 2
C-U:unconditional 3 taken 100%
C-NEXT:4294967296: 70: thing.B();
C-A:4294967296: 70-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 71:
C-NEXT: 1: 72: return a + 8 + grid[2][3] + len;
C-A: 1: 72-block 0
C-U:unconditional 0 taken 100%
C-NEXT: -: 73: return more_useless();
C-NEXT: -: 74:}
H: -: 0:Source:./test.h
H-NEXT: -: 0:Graph:test.gcno
H-NEXT: -: 0:Data:test.gcda
H-NEXT: -: 0:Runs:1
H-NEXT: -: 0:Programs:1
H-NEXT: -: 1:#include <stdint.h>
H-B:function _ZN1AC2Ev called 1 returned 100% blocks executed 100%
H-NEXT: 1: 2:struct A {
H-A: 1: 2-block 0
H-U:unconditional 0 taken 100%
H-NEXT: -: 3: virtual void B();
H-NEXT: -: 4:};

View File

@ -1,29 +0,0 @@
// Make sure that compiler-added local variables (whose line number is zero)
// don't crash llvm-cov.
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: cd %t
// RUN: cp %s %p/Inputs/range_based_for.gc* .
// RUN: llvm-cov gcov range_based_for.cpp | FileCheck %s --check-prefix=STDOUT
// STDOUT: File 'range_based_for.cpp'
// STDOUT: Lines executed:100.00% of 5
// STDOUT: range_based_for.cpp:creating 'range_based_for.cpp.gcov'
// RUN: FileCheck %s --check-prefix=GCOV < %t/range_based_for.cpp.gcov
// GCOV: -: 0:Runs:1
// GCOV: -: 0:Programs:1
int main(int argc, const char *argv[]) { // GCOV: 1: [[@LINE]]:int main(
int V[] = {1, 2}; // GCOV: 1: [[@LINE]]: int V[]
for (int &I : V) { // GCOV: 5: [[@LINE]]: for (
} // GCOV: 2: [[@LINE]]: }
return 0; // GCOV: 1: [[@LINE]]: return
} // GCOV: -: [[@LINE]]:}
// llvm-cov doesn't work on big endian yet
// XFAIL: host-byteorder-big-endian