[llvm] Add executed MC/DC TestVectors to `llvm-cov export` (PR #159119)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 23 03:50:29 PDT 2025
https://github.com/kuzmich321 updated https://github.com/llvm/llvm-project/pull/159119
>From 21f94135a5138516f4daa48b499bcf8c040e37b4 Mon Sep 17 00:00:00 2001
From: Arpad Borsos <swatinem at swatinem.de>
Date: Wed, 21 Aug 2024 14:29:47 +0200
Subject: [PATCH 1/3] Add executed MC/DC TestVectors to `llvm-cov export`
---
.../Inputs/binary-formats.canonical.json | 2 +-
llvm/tools/llvm-cov/CoverageExporterJson.cpp | 54 +++++++++++++------
2 files changed, 40 insertions(+), 16 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json b/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
index 5f9122d01da9a..f219ca6c7e179 100644
--- a/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
+++ b/llvm/test/tools/llvm-cov/Inputs/binary-formats.canonical.json
@@ -33,4 +33,4 @@ CHECK-SAME: "mcdc":{"count":0,"covered":0,"notcovered":0,"percent":0},
CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}}
CHECK-SAME: ],
CHECK-SAME: "type":"llvm.coverage.json.export"
-CHECK-SAME: "version":"3.0.1"
+CHECK-SAME: "version":"3.1.0"
diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 06de33dc070e0..5319286addf54 100644
--- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -62,7 +62,7 @@
#include <utility>
/// The semantic version combined as a string.
-#define LLVM_COVERAGE_EXPORT_JSON_STR "3.0.1"
+#define LLVM_COVERAGE_EXPORT_JSON_STR "3.1.0"
/// Unique type identifier for JSON coverage export.
#define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export"
@@ -108,13 +108,42 @@ json::Array gatherConditions(const coverage::MCDCRecord &Record) {
return Conditions;
}
+json::Value renderCondState(const coverage::MCDCRecord::CondState CondState) {
+ switch (CondState) {
+ case coverage::MCDCRecord::MCDC_DontCare:
+ return json::Value(nullptr);
+ case coverage::MCDCRecord::MCDC_True:
+ return json::Value(true);
+ case coverage::MCDCRecord::MCDC_False:
+ return json::Value(false);
+ }
+}
+
+json::Array gatherTestVectors(coverage::MCDCRecord &Record) {
+ json::Array TestVectors;
+ unsigned NumConditions = Record.getNumConditions();
+ for (unsigned tv = 0; tv < Record.getNumTestVectors(); tv++) {
+
+ json::Array TVConditions;
+ for (unsigned c = 0; c < NumConditions; c++)
+ TVConditions.push_back(renderCondState(Record.getTVCondition(tv, c)));
+
+ TestVectors.push_back(
+ json::Object({{"executed", json::Value(true)},
+ {"result", renderCondState(Record.getTVResult(tv))},
+ {"conditions", std::move(TVConditions)}}));
+ }
+ return TestVectors;
+}
+
json::Array renderMCDCRecord(const coverage::MCDCRecord &Record) {
const llvm::coverage::CounterMappingRegion &CMR = Record.getDecisionRegion();
const auto [TrueDecisions, FalseDecisions] = Record.getDecisions();
return json::Array({CMR.LineStart, CMR.ColumnStart, CMR.LineEnd,
CMR.ColumnEnd, TrueDecisions, FalseDecisions,
CMR.FileID, CMR.ExpandedFileID, int64_t(CMR.Kind),
- gatherConditions(Record)});
+ gatherConditions(Record),
+ gatherTestVectors(const_cast<coverage::MCDCRecord &>(Record))});
}
json::Array renderRegions(ArrayRef<coverage::CountedRegion> Regions) {
@@ -216,32 +245,28 @@ json::Object renderSummary(const FileCoverageSummary &Summary) {
}
json::Array renderFileExpansions(const coverage::CoverageMapping &Coverage,
- const coverage::CoverageData &FileCoverage,
- const FileCoverageSummary &FileReport) {
+ const coverage::CoverageData &FileCoverage) {
json::Array ExpansionArray;
for (const auto &Expansion : FileCoverage.getExpansions())
ExpansionArray.push_back(renderExpansion(Coverage, Expansion));
return ExpansionArray;
}
-json::Array renderFileSegments(const coverage::CoverageData &FileCoverage,
- const FileCoverageSummary &FileReport) {
+json::Array renderFileSegments(const coverage::CoverageData &FileCoverage) {
json::Array SegmentArray;
for (const auto &Segment : FileCoverage)
SegmentArray.push_back(renderSegment(Segment));
return SegmentArray;
}
-json::Array renderFileBranches(const coverage::CoverageData &FileCoverage,
- const FileCoverageSummary &FileReport) {
+json::Array renderFileBranches(const coverage::CoverageData &FileCoverage) {
json::Array BranchArray;
for (const auto &Branch : FileCoverage.getBranches())
BranchArray.push_back(renderBranch(Branch));
return BranchArray;
}
-json::Array renderFileMCDC(const coverage::CoverageData &FileCoverage,
- const FileCoverageSummary &FileReport) {
+json::Array renderFileMCDC(const coverage::CoverageData &FileCoverage) {
json::Array MCDCRecordArray;
for (const auto &Record : FileCoverage.getMCDCRecords())
MCDCRecordArray.push_back(renderMCDCRecord(Record));
@@ -256,12 +281,11 @@ json::Object renderFile(const coverage::CoverageMapping &Coverage,
if (!Options.ExportSummaryOnly) {
// Calculate and render detailed coverage information for given file.
auto FileCoverage = Coverage.getCoverageForFile(Filename);
- File["segments"] = renderFileSegments(FileCoverage, FileReport);
- File["branches"] = renderFileBranches(FileCoverage, FileReport);
- File["mcdc_records"] = renderFileMCDC(FileCoverage, FileReport);
+ File["segments"] = renderFileSegments(FileCoverage);
+ File["branches"] = renderFileBranches(FileCoverage);
+ File["mcdc_records"] = renderFileMCDC(FileCoverage);
if (!Options.SkipExpansions) {
- File["expansions"] =
- renderFileExpansions(Coverage, FileCoverage, FileReport);
+ File["expansions"] = renderFileExpansions(Coverage, FileCoverage);
}
}
File["summary"] = renderSummary(FileReport);
>From a9e1ad2ffdc820a8cd99adb1e958ad90f208ed47 Mon Sep 17 00:00:00 2001
From: Andrew Ignatov <dota2drot at gmail.com>
Date: Tue, 16 Sep 2025 17:58:18 +0200
Subject: [PATCH 2/3] add doc and tests for executed test vectors in llvm-cov
export
---
llvm/test/tools/llvm-cov/mcdc-export-json.test | 8 ++++----
llvm/tools/llvm-cov/CoverageExporterJson.cpp | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/mcdc-export-json.test b/llvm/test/tools/llvm-cov/mcdc-export-json.test
index e6dbd17bee5b2..30055bef415b8 100644
--- a/llvm/test/tools/llvm-cov/mcdc-export-json.test
+++ b/llvm/test/tools/llvm-cov/mcdc-export-json.test
@@ -1,10 +1,10 @@
// RUN: llvm-profdata merge %S/Inputs/mcdc-general.proftext -o %t.profdata
// RUN: llvm-cov export --format=text %S/Inputs/mcdc-general.o -instr-profile %t.profdata | FileCheck %s
-// CHECK: 12,7,12,27,2,4,0,0,5,[true,true,true,true]
-// CHECK: 15,7,15,13,1,2,0,0,5,[true,true]
-// CHECK: 15,19,15,25,1,1,0,0,5,[true,false]
-// CHECK: 18,7,19,15,1,3,0,0,5,[true,true,false,true]
+// CHECK: 12,7,12,27,2,4,0,0,5,[true,true,true,true],[{"conditions":[false,null,false,null],"executed":true,"result":false},{"conditions":[false,null,true,false],"executed":true,"result":false},{"conditions":[true,false,false,null],"executed":true,"result":false},{"conditions":[true,false,true,false],"executed":true,"result":false},{"conditions":[true,false,true,true],"executed":true,"result":true},{"conditions":[true,true,null,null],"executed":true,"result":true}]],[15,7,15,13,1,2,0,0,5,[true,true],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,false],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]],[15,19,15,25,1,1,0,0,5,[true,false],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]],[18,7,19,15,1,3,0,0,5,[true,true,false,true],[{"conditions":[false,null,null,null],"executed":true,"result":false},{"conditions":[true,false,null,null],"executed":true,"result":false},{"conditions":[true,true,true,false],"executed":true,"result":false},{"conditions":[true,true,true,true],"executed":true,"result":true}]]
+// CHECK: 15,7,15,13,1,2,0,0,5,[true,true],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,false],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]
+// CHECK: 15,19,15,25,1,1,0,0,5,[true,false],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]
+// CHECK: 18,7,19,15,1,3,0,0,5,[true,true,false,true],[{"conditions":[false,null,null,null],"executed":true,"result":false},{"conditions":[true,false,null,null],"executed":true,"result":false},{"conditions":[true,true,true,false],"executed":true,"result":false},{"conditions":[true,true,true,true],"executed":true,"result":true}]
// CHECK: "mcdc":{"count":12,"covered":10,"notcovered":2,"percent":83.333333333333343}
Instructions for regenerating the test:
diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 5319286addf54..2abaaaf8d2012 100644
--- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -21,7 +21,7 @@
// -- Branches: array => List of Branches in the file
// -- Branch: dict => Describes a branch of the file with counters
// -- MCDC Records: array => List of MCDC records in the file
-// -- MCDC Values: array => List of T/F covered condition values
+// -- MCDC Values: array => List of T/F covered condition values and list of executed test vectors
// -- Segments: array => List of Segments contained in the file
// -- Segment: dict => Describes a segment of the file with a counter
// -- Expansions: array => List of expansion records
>From 67ccd34564b715e7203823a571cbef8ac232510d Mon Sep 17 00:00:00 2001
From: Andrew Ignatov <dota2drot at gmail.com>
Date: Tue, 16 Sep 2025 20:30:31 +0200
Subject: [PATCH 3/3] cleanup
---
llvm/test/tools/llvm-cov/mcdc-export-json.test | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/tools/llvm-cov/mcdc-export-json.test b/llvm/test/tools/llvm-cov/mcdc-export-json.test
index 30055bef415b8..4b6f3b011451a 100644
--- a/llvm/test/tools/llvm-cov/mcdc-export-json.test
+++ b/llvm/test/tools/llvm-cov/mcdc-export-json.test
@@ -1,7 +1,7 @@
// RUN: llvm-profdata merge %S/Inputs/mcdc-general.proftext -o %t.profdata
// RUN: llvm-cov export --format=text %S/Inputs/mcdc-general.o -instr-profile %t.profdata | FileCheck %s
-// CHECK: 12,7,12,27,2,4,0,0,5,[true,true,true,true],[{"conditions":[false,null,false,null],"executed":true,"result":false},{"conditions":[false,null,true,false],"executed":true,"result":false},{"conditions":[true,false,false,null],"executed":true,"result":false},{"conditions":[true,false,true,false],"executed":true,"result":false},{"conditions":[true,false,true,true],"executed":true,"result":true},{"conditions":[true,true,null,null],"executed":true,"result":true}]],[15,7,15,13,1,2,0,0,5,[true,true],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,false],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]],[15,19,15,25,1,1,0,0,5,[true,false],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]],[18,7,19,15,1,3,0,0,5,[true,true,false,true],[{"conditions":[false,null,null,null],"executed":true,"result":false},{"conditions":[true,false,null,null],"executed":true,"result":false},{"conditions":[true,true,true,false],"executed":true,"result":false},{"conditions":[true,true,true,true],"executed":true,"result":true}]]
+// CHECK: 12,7,12,27,2,4,0,0,5,[true,true,true,true],[{"conditions":[false,null,false,null],"executed":true,"result":false},{"conditions":[false,null,true,false],"executed":true,"result":false},{"conditions":[true,false,false,null],"executed":true,"result":false},{"conditions":[true,false,true,false],"executed":true,"result":false},{"conditions":[true,false,true,true],"executed":true,"result":true},{"conditions":[true,true,null,null],"executed":true,"result":true}]
// CHECK: 15,7,15,13,1,2,0,0,5,[true,true],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,false],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]
// CHECK: 15,19,15,25,1,1,0,0,5,[true,false],[{"conditions":[false,null],"executed":true,"result":false},{"conditions":[true,true],"executed":true,"result":true}]
// CHECK: 18,7,19,15,1,3,0,0,5,[true,true,false,true],[{"conditions":[false,null,null,null],"executed":true,"result":false},{"conditions":[true,false,null,null],"executed":true,"result":false},{"conditions":[true,true,true,false],"executed":true,"result":false},{"conditions":[true,true,true,true],"executed":true,"result":true}]
More information about the llvm-commits
mailing list