diff options
-rw-r--r-- | llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h | 32 | ||||
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp | 7 | ||||
-rw-r--r-- | llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping | bin | 168 -> 180 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.json | 4 | ||||
-rw-r--r-- | llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping | bin | 0 -> 168 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp | 6 | ||||
-rw-r--r-- | llvm/test/tools/llvm-cov/warnings.h | 3 |
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 Binary files differindex 20d6abfffa7..f5ef388a733 100644 --- a/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping +++ b/llvm/test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping 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 Binary files differnew file mode 100644 index 00000000000..20d6abfffa7 --- /dev/null +++ b/llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping 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 < 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 > 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 |