summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h32
-rw-r--r--llvm/lib/ProfileData/Coverage/CoverageMapping.cpp9
-rw-r--r--llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp17
-rw-r--r--llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp7
-rw-r--r--llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmappingbin168 -> 180 bytes
-rw-r--r--llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.json4
-rw-r--r--llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmappingbin0 -> 168 bytes
-rw-r--r--llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp6
-rw-r--r--llvm/test/tools/llvm-cov/warnings.h3
9 files changed, 60 insertions, 18 deletions
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index 5b372252a9a..633e51565cd 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -44,18 +44,26 @@ struct CoverageMappingRecord {
/// \brief A file format agnostic iterator over coverage mapping data.
class CoverageMappingIterator
: public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
- CoverageMappingReader *Reader = nullptr;
+ CoverageMappingReader *Reader;
CoverageMappingRecord Record;
+ coveragemap_error ReadErr;
void increment();
public:
- CoverageMappingIterator() = default;
+ CoverageMappingIterator()
+ : Reader(nullptr), Record(), ReadErr(coveragemap_error::success) {}
- CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) {
+ CoverageMappingIterator(CoverageMappingReader *Reader)
+ : Reader(Reader), Record(), ReadErr(coveragemap_error::success) {
increment();
}
+ ~CoverageMappingIterator() {
+ if (ReadErr != coveragemap_error::success)
+ llvm_unreachable("Unexpected error in coverage mapping iterator");
+ }
+
CoverageMappingIterator &operator++() {
increment();
return *this;
@@ -66,8 +74,22 @@ public:
bool operator!=(const CoverageMappingIterator &RHS) {
return Reader != RHS.Reader;
}
- CoverageMappingRecord &operator*() { return Record; }
- CoverageMappingRecord *operator->() { return &Record; }
+ Expected<CoverageMappingRecord &> operator*() {
+ if (ReadErr != coveragemap_error::success) {
+ auto E = make_error<CoverageMapError>(ReadErr);
+ ReadErr = coveragemap_error::success;
+ return std::move(E);
+ }
+ return Record;
+ }
+ Expected<CoverageMappingRecord *> operator->() {
+ if (ReadErr != coveragemap_error::success) {
+ auto E = make_error<CoverageMapError>(ReadErr);
+ ReadErr = coveragemap_error::success;
+ return std::move(E);
+ }
+ return &Record;
+ }
};
class CoverageMappingReader {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 346ac76a6f7..d2878d3283a 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -250,10 +250,15 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
IndexedInstrProfReader &ProfileReader) {
auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
- for (const auto &CoverageReader : CoverageReaders)
- for (const auto &Record : *CoverageReader)
+ for (const auto &CoverageReader : CoverageReaders) {
+ for (auto RecordOrErr : *CoverageReader) {
+ if (Error E = RecordOrErr.takeError())
+ return std::move(E);
+ const auto &Record = *RecordOrErr;
if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
return std::move(E);
+ }
+ }
return std::move(Coverage);
}
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index fff0a03ccbe..9bf70c2e3aa 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -49,16 +49,18 @@ using namespace object;
#define DEBUG_TYPE "coverage-mapping"
void CoverageMappingIterator::increment() {
+ if (ReadErr != coveragemap_error::success)
+ return;
+
// Check if all the records were read or if an error occurred while reading
// the next record.
- if (auto E = Reader->readNextRecord(Record)) {
+ if (auto E = Reader->readNextRecord(Record))
handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
if (CME.get() == coveragemap_error::eof)
*this = CoverageMappingIterator();
else
- llvm_unreachable("Unexpected error in coverage mapping iterator");
+ ReadErr = CME.get();
});
- }
}
Error RawCoverageReader::readULEB128(uint64_t &Result) {
@@ -238,9 +240,12 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
dbgs() << "\n";
});
- MappingRegions.push_back(CounterMappingRegion(
- C, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
- LineStart + NumLines, ColumnEnd, Kind));
+ auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID,
+ LineStart, ColumnStart,
+ LineStart + NumLines, ColumnEnd, Kind);
+ if (CMR.startLoc() > CMR.endLoc())
+ return make_error<CoverageMapError>(coveragemap_error::malformed);
+ MappingRegions.push_back(CMR);
}
return Error::success();
}
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
index 6fe93530da2..4a1ce16c486 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
@@ -116,6 +116,13 @@ static void writeCounter(ArrayRef<CounterExpression> Expressions, Counter C,
}
void CoverageMappingWriter::write(raw_ostream &OS) {
+ // Check that we don't have any bogus regions.
+ assert(all_of(MappingRegions,
+ [](const CounterMappingRegion &CMR) {
+ return CMR.startLoc() <= CMR.endLoc();
+ }) &&
+ "Source region does not begin before it ends");
+
// Sort the regions in an ascending order by the file id and the starting
// location. Sort by region kinds to ensure stable order for tests.
std::stable_sort(
diff --git a/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping b/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping
index 20d6abfffa7..f5ef388a733 100644
--- a/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping
+++ b/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping
Binary files differ
diff --git a/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.json b/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.json
index 7185d3fbf00..aaf1d9aa4e1 100644
--- a/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.json
+++ b/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.json
@@ -14,7 +14,7 @@
// CHECK-SAME: "summary":{
// CHECK-SAME: "lines":{"count":20,"covered":16,"percent":80},
// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
-// CHECK-SAME: "regions":{"count":10,"covered":7,"notcovered":3,"percent":70}}}
+// CHECK-SAME: "regions":{"count":11,"covered":8,"notcovered":3,"percent":72}}}
// Close Files Array
// CHECK-SAME: ],
@@ -33,7 +33,7 @@
// CHECK-SAME: "lines":{"count":20,"covered":16,"percent":80},
// CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
// CHECK-SAME: "instantiations":{"count":1,"covered":1,"percent":100},
-// CHECK-SAME: "regions":{"count":10,"covered":7,"notcovered":3,"percent":70}}
+// CHECK-SAME: "regions":{"count":11,"covered":8,"notcovered":3,"percent":72}}
// Close the export object, data array, and root object
// CHECK-SAME: }]}
diff --git a/llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping b/llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping
new file mode 100644
index 00000000000..20d6abfffa7
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping
Binary files differ
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
index 48460b3d2fd..ab0987ee756 100644
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
@@ -50,7 +50,7 @@ int main() { // TEXT: [[@LINE]]| 161|int main(
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> int x = 0
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
-// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> if (x) {
+// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> if (x)
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre><span class='red'> }</span>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = 1;
@@ -62,7 +62,7 @@ int main() { // TEXT: [[@LINE]]| 161|int main(
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &lt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &gt; 10
-// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre> x - 1:
+// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre> <span class='red'>x - 1</span>:
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x + 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> return 0;
@@ -91,5 +91,5 @@ int main() { // TEXT: [[@LINE]]| 161|int main(
// HTML-INDEX: <td class='column-entry-yellow'>
// HTML-INDEX: 80.00% (16/20)
// HTML-INDEX: <td class='column-entry-red'>
-// HTML-INDEX: 70.00% (7/10)
+// HTML-INDEX: 72.73% (8/11)
// HTML-INDEX: TOTALS
diff --git a/llvm/test/tools/llvm-cov/warnings.h b/llvm/test/tools/llvm-cov/warnings.h
index a7826e8bcc8..5bd62be6d04 100644
--- a/llvm/test/tools/llvm-cov/warnings.h
+++ b/llvm/test/tools/llvm-cov/warnings.h
@@ -11,3 +11,6 @@
// FAKE-FUNC-STDOUT-NOT: warning: Could not read coverage for '{{.*}}'.
// FAKE-FUNC-STDERR: Could not read coverage for '{{.*}}'.
+
+// RUN: not llvm-cov report %S/Inputs/malformedRegions.covmapping -instr-profile %S/Inputs/elf_binary_comdat.profdata 2>&1 | FileCheck %s -check-prefix=MALFORMED-REGION
+// MALFORMED-REGION: malformedRegions.covmapping: Failed to load coverage: Malformed coverage data
OpenPOWER on IntegriCloud