namespace GCOV {
-enum GCOVVersion { V304, V407, V408, V800, V900 };
+enum GCOVVersion { V304, V407, V408, V800, V900, V1200 };
/// A struct for passing gcov options between functions.
struct Options {
}
/// readGCOVVersion - Read GCOV version.
- bool readGCOVVersion(GCOV::GCOVVersion &Version) {
+ bool readGCOVVersion(GCOV::GCOVVersion &version) {
std::string str(de.getBytes(cursor, 4));
if (str.size() != 4)
return false;
int ver = str[0] >= 'A'
? (str[0] - 'A') * 100 + (str[1] - '0') * 10 + str[2] - '0'
: (str[0] - '0') * 10 + str[2] - '0';
- if (ver >= 90) {
+ if (ver >= 120) {
+ this->version = version = GCOV::V1200;
+ return true;
+ } else if (ver >= 90) {
// PR gcov-profile/84846, r269678
- Version = GCOV::V900;
+ this->version = version = GCOV::V900;
return true;
} else if (ver >= 80) {
// PR gcov-profile/48463
- Version = GCOV::V800;
+ this->version = version = GCOV::V800;
return true;
} else if (ver >= 48) {
// r189778: the exit block moved from the last to the second.
- Version = GCOV::V408;
+ this->version = version = GCOV::V408;
return true;
} else if (ver >= 47) {
// r173147: split checksum into cfg checksum and line checksum.
- Version = GCOV::V407;
+ this->version = version = GCOV::V407;
return true;
} else if (ver >= 34) {
- Version = GCOV::V304;
+ this->version = version = GCOV::V304;
return true;
}
errs() << "unexpected version: " << str << "\n";
return true;
}
- bool readString(StringRef &Str) {
+ bool readString(StringRef &str) {
uint32_t len;
if (!readInt(len) || len == 0)
return false;
- Str = de.getBytes(cursor, len * 4).split('\0').first;
+ if (version >= GCOV::V1200)
+ str = de.getBytes(cursor, len).drop_back();
+ else
+ str = de.getBytes(cursor, len * 4).split('\0').first;
return bool(cursor);
}
private:
MemoryBuffer *Buffer;
+ GCOV::GCOVVersion version{};
};
/// GCOVFile - Collects coverage information for one pair of coverage file
public:
bool GCNOInitialized = false;
- GCOV::GCOVVersion version;
+ GCOV::GCOVVersion version{};
uint32_t checksum = 0;
StringRef cwd;
SmallVector<std::unique_ptr<GCOVFunction>, 16> functions;
while ((tag = buf.getWord())) {
if (!buf.readInt(length))
return false;
+ uint32_t pos = buf.cursor.tell();
if (tag == GCOV_TAG_FUNCTION) {
functions.push_back(std::make_unique<GCOVFunction>(*this));
fn = functions.back().get();
return false;
}
GCOVBlock *src = fn->blocks[srcNo].get();
- for (uint32_t i = 0, e = (length - 1) / 2; i != e; ++i) {
+ const uint32_t e =
+ version >= GCOV::V1200 ? (length / 4 - 1) / 2 : (length - 1) / 2;
+ for (uint32_t i = 0; 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);
}
}
}
+ pos += version >= GCOV::V1200 ? length : 4 * length;
+ if (pos < buf.cursor.tell())
+ return false;
+ buf.de.skip(buf.cursor, pos - buf.cursor.tell());
}
GCNOInitialized = true;
}
}
} else if (tag == GCOV_TAG_COUNTER_ARCS && fn) {
- if (length != 2 * fn->arcs.size()) {
+ uint32_t expected = 2 * fn->arcs.size();
+ if (version >= GCOV::V1200)
+ expected *= 4;
+ if (length != expected) {
errs() << fn->Name
<< format(
": GCOV_TAG_COUNTER_ARCS mismatch, got %u, expected %u\n",
- length, unsigned(2 * fn->arcs.size()));
+ length, expected);
return false;
}
for (std::unique_ptr<GCOVArc> &arc : fn->arcs) {
fn->treeArcs[i - 1]->src.count += fn->treeArcs[i - 1]->count;
}
}
- pos += 4 * length;
+ pos += version >= GCOV::V1200 ? length : 4 * length;
if (pos < buf.cursor.tell())
return false;
buf.de.skip(buf.cursor, pos - buf.cursor.tell());
--- /dev/null
+/// Test that llvm-cov supports gcov 12 compatible format.
+#include <math.h>
+#include <stdio.h>
+int main() { // GCOV: 1: [[@LINE]]:int main
+ double a[11], result; // GCOV-NEXT: -: [[@LINE]]:
+ for (int i = 0; i < 11; i++) // GCOV-NEXT: 12: [[@LINE]]:
+ scanf("%lf", &a[i]); // GCOV-NEXT: 11: [[@LINE]]:
+ for (int i = 10; i >= 0; i--) { // GCOV-NEXT: 12: [[@LINE]]:
+ result = sqrt(fabs(a[i])) + 5 * pow(a[i], 3); // GCOV-NEXT: 11: [[@LINE]]:
+ printf("\nf(%d) = ", i); // GCOV-NEXT: 11: [[@LINE]]:
+ if (result > 400) printf("Overflow!"); // GCOV-NEXT: 11: [[@LINE]]:
+ else printf("%lf", result); // GCOV-NEXT: 4: [[@LINE]]:
+ } // GCOV-NEXT: -: [[@LINE]]:
+ return 0; // GCOV-NEXT: 1: [[@LINE]]:
+} // GCOV-NEXT: -: [[@LINE]]:
+
+// RUN: rm -rf %t && mkdir %t && cd %t
+// RUN: cp %s %p/Inputs/gcov-12.gc* .
+
+// RUN: llvm-cov gcov gcov-12.c | FileCheck %s
+// CHECK: File 'gcov-12.c'
+// CHECK-NEXT: Lines executed:100.00% of 9
+// CHECK-NEXT: Creating 'gcov-12.c.gcov'
+
+// RUN: FileCheck --input-file=%t/gcov-12.c.gcov --check-prefix=HEADER %s
+// RUN: FileCheck --input-file=%t/gcov-12.c.gcov --check-prefix=GCOV %s
+
+// HEADER: {{^}} -: 0:Source:gcov-12.c
+// HEADER-NEXT: -: 0:Graph:gcov-12.gcno
+// HEADER-NEXT: -: 0:Data:gcov-12.gcda
+// HEADER-NEXT: -: 0:Runs:1{{$}}
+// HEADER-NEXT: -: 1:/// Test that llvm-cov