mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 21:53:12 +08:00
[Coverage] Report errors when reading malformed source regions
Each source region has a start and end location. Report an error when the end location does not precede the begin location. The old lineExecutionCounts.covmapping test actually had a buggy source region in it. This commit introduces a regenerated copy of the coverage and moves the old copy to malformedRegions.covmapping, for a test. Differential Revision: https://reviews.llvm.org/D37387 llvm-svn: 312814
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Binary file not shown.
@@ -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: }]}
|
||||
|
||||
BIN
llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping
Normal file
BIN
llvm/test/tools/llvm-cov/Inputs/malformedRegions.covmapping
Normal file
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user