[llvm] [llvm-cov] add ability to show non executed test vectors for mc/dc coverage (PR #187517)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 6 07:01:32 PDT 2026
https://github.com/kuzmich321 updated https://github.com/llvm/llvm-project/pull/187517
>From ea610e97d9a12276344986675a87acdbc06e660b Mon Sep 17 00:00:00 2001
From: Andrew Ignatov <dota2drot at gmail.com>
Date: Thu, 19 Mar 2026 15:55:59 +0100
Subject: [PATCH] add ability to show non executed test vectors for mc/dc
coverage
---
.../ProfileData/Coverage/CoverageMapping.h | 99 +++++++-----
.../ProfileData/Coverage/CoverageMapping.cpp | 60 ++++---
llvm/test/tools/llvm-cov/mcdc-const.test | 147 +++++++++++++++++-
.../test/tools/llvm-cov/mcdc-export-json.test | 22 ++-
.../tools/llvm-cov/mcdc-general-none.test | 124 ++++++++++++++-
llvm/test/tools/llvm-cov/mcdc-general.test | 136 +++++++++++++++-
llvm/test/tools/llvm-cov/mcdc-macro.test | 136 +++++++++++++++-
llvm/tools/llvm-cov/CodeCoverage.cpp | 13 ++
llvm/tools/llvm-cov/CoverageExporterJson.cpp | 58 ++++---
llvm/tools/llvm-cov/CoverageViewOptions.h | 1 +
.../tools/llvm-cov/SourceCoverageViewHTML.cpp | 34 +++-
.../tools/llvm-cov/SourceCoverageViewText.cpp | 50 +++++-
12 files changed, 776 insertions(+), 104 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 8ab036195160e..96fb5f337b075 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -459,15 +459,56 @@ struct MCDCRecord {
private:
CounterMappingRegion Region;
TestVectors TV;
+ TestVectors NotExecutedTV;
std::optional<TVPairMap> IndependencePairs;
BoolVector Folded;
CondIDMap PosToID;
LineColPairMap CondLoc;
+ std::string formatTestVectorRow(const TestVector &Vec, CondState Result,
+ unsigned DisplayRowNumber) const {
+ std::ostringstream OS;
+ const auto NumConditions = getNumConditions();
+ // Add individual condition values to the string.
+ OS << " " << DisplayRowNumber << " { ";
+ for (unsigned Condition = 0; Condition < NumConditions; Condition++) {
+ if (isCondFolded(Condition))
+ OS << "C";
+ else {
+ auto It = PosToID.find(Condition);
+ assert(It != PosToID.end() && "Ordinal without CondID mapping");
+ switch (Vec[It->second]) {
+ case MCDC_DontCare:
+ OS << "-";
+ break;
+ case MCDC_True:
+ OS << "T";
+ break;
+ case MCDC_False:
+ OS << "F";
+ break;
+ }
+ }
+ if (Condition != NumConditions - 1)
+ OS << ", ";
+ }
+
+ // Add result value to the string.
+ OS << " = ";
+ if (Result == MCDC_True)
+ OS << "T";
+ else
+ OS << "F";
+ OS << " }\n";
+ return OS.str();
+ }
+
public:
MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV,
- BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
- : Region(Region), TV(std::move(TV)), Folded(std::move(Folded)),
+ TestVectors &&NotExecutedTV, BoolVector &&Folded,
+ CondIDMap &&PosToID, LineColPairMap &&CondLoc)
+ : Region(Region), TV(std::move(TV)),
+ NotExecutedTV(std::move(NotExecutedTV)), Folded(std::move(Folded)),
PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) {
findIndependencePairs();
}
@@ -481,6 +522,8 @@ struct MCDCRecord {
return Region.getDecisionParams().NumConditions;
}
unsigned getNumTestVectors() const { return TV.size(); }
+ unsigned getNumNotExecutedTestVectors() const { return NotExecutedTV.size(); }
+
bool isCondFolded(unsigned Condition) const {
return Folded[false][Condition] || Folded[true][Condition];
}
@@ -495,6 +538,11 @@ struct MCDCRecord {
return TV[TestVectorIndex].first[PosToID[Condition]];
}
+ CondState getNotExecutedTVCondition(unsigned NotExecutedIndex,
+ unsigned Condition) {
+ return NotExecutedTV[NotExecutedIndex].first[PosToID[Condition]];
+ }
+
/// Return the number of True and False decisions for all executed test
/// vectors.
std::pair<unsigned, unsigned> getDecisions() const {
@@ -510,6 +558,10 @@ struct MCDCRecord {
return TV[TestVectorIndex].second;
}
+ CondState getNotExecutedTVResult(unsigned NotExecutedIndex) {
+ return NotExecutedTV[NotExecutedIndex].second;
+ }
+
/// Determine whether a given condition (indicated by Condition) is covered
/// by an Independence Pair. Because condition IDs are not associated based
/// on their position in the expression, accessing conditions in the
@@ -559,7 +611,7 @@ struct MCDCRecord {
std::string getTestVectorHeaderString() const {
std::ostringstream OS;
- if (getNumTestVectors() == 0) {
+ if (getNumTestVectors() == 0 && getNumNotExecutedTestVectors() == 0) {
OS << "None.\n";
return OS.str();
}
@@ -576,39 +628,16 @@ struct MCDCRecord {
std::string getTestVectorString(unsigned TestVectorIndex) {
assert(TestVectorIndex < getNumTestVectors() &&
"TestVector index out of bounds!");
- std::ostringstream OS;
- const auto NumConditions = getNumConditions();
- // Add individual condition values to the string.
- OS << " " << TestVectorIndex + 1 << " { ";
- for (unsigned Condition = 0; Condition < NumConditions; Condition++) {
- if (isCondFolded(Condition))
- OS << "C";
- else {
- switch (getTVCondition(TestVectorIndex, Condition)) {
- case MCDCRecord::MCDC_DontCare:
- OS << "-";
- break;
- case MCDCRecord::MCDC_True:
- OS << "T";
- break;
- case MCDCRecord::MCDC_False:
- OS << "F";
- break;
- }
- }
- if (Condition != NumConditions - 1)
- OS << ", ";
- }
-
- // Add result value to the string.
- OS << " = ";
- if (getTVResult(TestVectorIndex) == MCDC_True)
- OS << "T";
- else
- OS << "F";
- OS << " }\n";
+ const auto &[Vec, Res] = TV[TestVectorIndex];
+ return formatTestVectorRow(Vec, Res, TestVectorIndex + 1);
+ }
- return OS.str();
+ std::string getNotExecutedTestVectorString(unsigned NotExecutedIndex) {
+ assert(NotExecutedIndex < getNumNotExecutedTestVectors() &&
+ "Not-executed test vector index out of bounds!");
+ const auto &[Vec, Res] = NotExecutedTV[NotExecutedIndex];
+ return formatTestVectorRow(Vec, Res,
+ getNumTestVectors() + NotExecutedIndex + 1);
}
std::string getConditionCoverageString(unsigned Condition) {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 4ce78fe6e3182..ebed42a402de2 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -426,11 +426,11 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
/// Mapping of calculated MC/DC Independence Pairs for each condition.
MCDCRecord::TVPairMap IndependencePairs;
- /// Helper for sorting ExecVectors.
+ /// Helper for sorting ExecVectors / NotExecVectors.
struct TVIdxTuple {
MCDCRecord::CondState MCDCCond; /// True/False
unsigned BIdx; /// Bitmap Index
- unsigned Ord; /// Last position on ExecVectors
+ unsigned Ord; /// Last position in exec / not-exec TVs
TVIdxTuple(MCDCRecord::CondState MCDCCond, unsigned BIdx, unsigned Ord)
: MCDCCond(MCDCCond), BIdx(BIdx), Ord(Ord) {}
@@ -441,12 +441,14 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
}
};
- // Indices for sorted TestVectors;
std::vector<TVIdxTuple> ExecVectorIdxs;
+ std::vector<TVIdxTuple> NotExecVectorIdxs;
/// Actual executed Test Vectors for the boolean expression, based on
/// ExecutedTestVectorBitmap.
MCDCRecord::TestVectors ExecVectors;
+ /// Never-executed test vectors
+ MCDCRecord::TestVectors NotExecVectors;
#ifndef NDEBUG
DenseSet<unsigned> TVIdxs;
@@ -486,17 +488,21 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
assert(TVIdx < SavedNodes[ID].Width);
assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");
- if (!Bitmap[IsVersion11
- ? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()
- : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
- continue;
-
- ExecVectorIdxs.emplace_back(MCDCCond, NextTVIdx, ExecVectors.size());
-
- // Copy the completed test vector to the vector of testvectors.
- // The final value (T,F) is equal to the last non-dontcare state on the
- // path (in a short-circuiting system).
- ExecVectors.push_back({TV, MCDCCond});
+ bool Executed =
+ Bitmap[IsVersion11
+ ? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()
+ : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx];
+ if (Executed) {
+ ExecVectorIdxs.emplace_back(MCDCCond, NextTVIdx, ExecVectors.size());
+ // Copy the completed test vector to the vector of testvectors.
+ // The final value (T,F) is equal to the last non-dontcare state on the
+ // path (in a short-circuiting system).
+ ExecVectors.push_back({TV, MCDCCond});
+ } else {
+ NotExecVectorIdxs.emplace_back(MCDCCond, NextTVIdx,
+ NotExecVectors.size());
+ NotExecVectors.push_back({TV, MCDCCond});
+ }
}
// Reset back to DontCare.
@@ -505,7 +511,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
/// Walk the bits in the bitmap. A bit set to '1' indicates that the test
/// vector at the corresponding index was executed during a test run.
- void findExecutedTestVectors() {
+ /// Vectors with '0' bit are collected separately for UI.
+ void findTestVectors() {
// Walk the binary decision diagram to enumerate all possible test vectors.
// We start at the root node (ID == 0) with all values being DontCare.
// `TVIdx` starts with 0 and is in the traversal.
@@ -516,10 +523,16 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
"TVIdxs wasn't fulfilled");
llvm::sort(ExecVectorIdxs);
- MCDCRecord::TestVectors NewTestVectors;
+ MCDCRecord::TestVectors NewExec;
for (const auto &IdxTuple : ExecVectorIdxs)
- NewTestVectors.push_back(std::move(ExecVectors[IdxTuple.Ord]));
- ExecVectors = std::move(NewTestVectors);
+ NewExec.push_back(std::move(ExecVectors[IdxTuple.Ord]));
+ ExecVectors = std::move(NewExec);
+
+ llvm::sort(NotExecVectorIdxs);
+ MCDCRecord::TestVectors NewNotExec;
+ for (const auto &IdxTuple : NotExecVectorIdxs)
+ NewNotExec.push_back(std::move(NotExecVectors[IdxTuple.Ord]));
+ NotExecVectors = std::move(NewNotExec);
}
public:
@@ -554,12 +567,13 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
Folded[true][I] = B->Count.isZero();
}
- // Using Profile Bitmap from runtime, mark the executed test vectors.
- findExecutedTestVectors();
+ // Using Profile Bitmap from runtime, mark the test vectors.
+ findTestVectors();
- // Record Test vectors, executed vectors, and independence pairs.
- return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded),
- std::move(PosToID), std::move(CondLoc));
+ // Record executed vectors, not-executed vectors, and independence pairs.
+ return MCDCRecord(Region, std::move(ExecVectors), std::move(NotExecVectors),
+ std::move(Folded), std::move(PosToID),
+ std::move(CondLoc));
}
};
diff --git a/llvm/test/tools/llvm-cov/mcdc-const.test b/llvm/test/tools/llvm-cov/mcdc-const.test
index 76eb7cf706d73..1358725dce60e 100644
--- a/llvm/test/tools/llvm-cov/mcdc-const.test
+++ b/llvm/test/tools/llvm-cov/mcdc-const.test
@@ -19,7 +19,9 @@
// CHECKGENERALCASE-NEXT: | Condition C4 --> (12:25)
// CHECKGENERALCASE-NEXT: | Condition C5 --> (12:31)
// CHECKGENERALCASE-NEXT: |
-// CHECKGENERALCASE-NEXT: | Executed MC/DC Test Vectors:
+// CHECKGENERALCASE-NEXT: | MC/DC Test Vectors:
+// CHECKGENERALCASE-NEXT: |
+// CHECKGENERALCASE-NEXT: | Executed:
// CHECKGENERALCASE-NEXT: |
// CHECKGENERALCASE-NEXT: | C1, C2, C3, C4, C5 Result
// CHECKGENERALCASE-NEXT: | 1 { F, C, C, -, C = F }
@@ -36,7 +38,6 @@
// RUN: llvm-profdata merge %S/Inputs/mcdc-const-folding.proftext -o %t.profdata
// RUN: llvm-cov show --show-mcdc %S/Inputs/mcdc-const-folding.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=CHECKFULLCASE
-// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-const-folding.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-const-folding.cpp | FileCheck %s -check-prefix=REPORT
// CHECKFULLCASE: | 1 { C, - = F }
// CHECKFULLCASE: | C1-Pair: constant folded
@@ -176,6 +177,148 @@
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// RUN: llvm-cov show --show-mcdc --show-mcdc-non-executed-vectors %S/Inputs/mcdc-const-folding.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=ALLFULLCASE
+
+// ALLFULLCASE: | 1 { C, - = F }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { F, C = F }
+// ALLFULLCASE-NEXT: | 2 { T, C = F }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { C, F = F }
+// ALLFULLCASE-NEXT: | 2 { C, T = T }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: covered: (1,2)
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { F, C = F }
+// ALLFULLCASE-NEXT: | 2 { T, C = T }
+// ALLFULLCASE: | C1-Pair: covered: (1,2)
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { C, - = T }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { T, C = T }
+// ALLFULLCASE-NEXT: | 2 { F, C = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { C, F = F }
+// ALLFULLCASE-NEXT: | 2 { C, T = T }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: covered: (1,2)
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { F, C = F }
+// ALLFULLCASE-NEXT: | 2 { T, C = T }
+// ALLFULLCASE: | C1-Pair: covered: (1,2)
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { C, -, - = F }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { F, C, - = F }
+// ALLFULLCASE-NEXT: | 2 { T, C, - = F }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { C, F, - = F }
+// ALLFULLCASE-NEXT: | 2 { C, T, F = F }
+// ALLFULLCASE-NEXT: | 3 { C, T, T = T }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: covered: (1,3)
+// ALLFULLCASE-NEXT: | C3-Pair: covered: (2,3)
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { F, C, - = F }
+// ALLFULLCASE-NEXT: | 2 { T, C, F = F }
+// ALLFULLCASE-NEXT: | 3 { T, C, T = T }
+// ALLFULLCASE: | C1-Pair: covered: (1,3)
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: covered: (2,3)
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { C, -, - = T }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { T, C, - = T }
+// ALLFULLCASE-NEXT: | 2 { F, C, - = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { C, T, - = T }
+// ALLFULLCASE-NEXT: | 2 { C, F, T = T }
+// ALLFULLCASE: | C1-Pair: constant folded
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { T, C, - = T }
+// ALLFULLCASE-NEXT: | 2 { F, C, T = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { F, -, C = F }
+// ALLFULLCASE-NEXT: | 2 { T, F, C = F }
+// ALLFULLCASE-NEXT: | 3 { T, T, C = F }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE-NEXT: | C3-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { F, C, - = F }
+// ALLFULLCASE-NEXT: | 2 { T, C, - = F }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { F, -, C = F }
+// ALLFULLCASE-NEXT: | 2 { T, F, C = F }
+// ALLFULLCASE-NEXT: | 3 { T, T, C = T }
+// ALLFULLCASE: | C1-Pair: covered: (1,3)
+// ALLFULLCASE-NEXT: | C2-Pair: covered: (2,3)
+// ALLFULLCASE-NEXT: | C3-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { F, C, - = F }
+// ALLFULLCASE-NEXT: | 2 { T, C, F = F }
+// ALLFULLCASE-NEXT: | 3 { T, C, T = T }
+// ALLFULLCASE: | C1-Pair: covered: (1,3)
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: covered: (2,3)
+// ALLFULLCASE: | MC/DC Coverage for Decision: 100.00%
+// ALLFULLCASE: | 1 { T, -, C = T }
+// ALLFULLCASE-NEXT: | 2 { F, T, C = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE-NEXT: | C3-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { T, C, - = T }
+// ALLFULLCASE-NEXT: | 2 { F, C, - = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { T, -, C = T }
+// ALLFULLCASE-NEXT: | 2 { F, T, C = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: not covered
+// ALLFULLCASE-NEXT: | C3-Pair: constant folded
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+// ALLFULLCASE: | 1 { T, C, - = T }
+// ALLFULLCASE-NEXT: | 2 { F, C, T = T }
+// ALLFULLCASE: | C1-Pair: not covered
+// ALLFULLCASE-NEXT: | C2-Pair: constant folded
+// ALLFULLCASE-NEXT: | C3-Pair: not covered
+// ALLFULLCASE: | MC/DC Coverage for Decision: 0.00%
+
+// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-const-folding.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-const-folding.cpp | FileCheck %s -check-prefix=REPORT
+
// REPORT: _Z5case0b {{.*}} 1 1 0.00%
// REPORT-NEXT: _Z5case1b {{.*}} 1 1 0.00%
// REPORT-NEXT: _Z5case2b {{.*}} 1 0 100.00%
diff --git a/llvm/test/tools/llvm-cov/mcdc-export-json.test b/llvm/test/tools/llvm-cov/mcdc-export-json.test
index 3ff563955c996..e1d0601ba6ab9 100644
--- a/llvm/test/tools/llvm-cov/mcdc-export-json.test
+++ b/llvm/test/tools/llvm-cov/mcdc-export-json.test
@@ -1,11 +1,19 @@
// 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
+// RUN: llvm-cov export --format=text %S/Inputs/mcdc-general.o -instr-profile %t.profdata | FileCheck %s --check-prefix=DEFAULT
-// CHECK: 12,7,12,27,2,4,0,0,5,[true,true,true,true],[{"conditions":[false,null,false,null],"executed":true,"result":false},{"conditions":[true,false,false,null],"executed":true,"result":false},{"conditions":[false,null,true,false],"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}]
-// CHECK: "mcdc":{"count":12,"covered":10,"notcovered":2,"percent":83.333333333333343}
+// DEFAULT: 12,7,12,27,2,4,0,0,5,[true,true,true,true],[{"conditions":[false,null,false,null],"executed":true,"result":false},{"conditions":[true,false,false,null],"executed":true,"result":false},{"conditions":[false,null,true,false],"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}]
+// DEFAULT: 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}]
+// DEFAULT: 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}]
+// DEFAULT: 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}]
+// DEFAULT: "mcdc":{"count":12,"covered":10,"notcovered":2,"percent":83.333333333333343}
+
+// RUN: llvm-cov export --format=text --show-mcdc-non-executed-vectors %S/Inputs/mcdc-general.o -instr-profile %t.profdata | FileCheck %s --check-prefix=ALL
+
+// ALL: 12,7,12,27,2,4,0,0,5,[true,true,true,true],[{"conditions":[false,null,false,null],"executed":true,"result":false},{"conditions":[true,false,false,null],"executed":true,"result":false},{"conditions":[false,null,true,false],"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},{"conditions":[false,null,true,true],"executed":false,"result":true}]
+// ALL: 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}]
+// ALL: 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},{"conditions":[true,false],"executed":false,"result":false}]
+// ALL: 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},{"conditions":[true,true,false,null],"executed":false,"result":false}]
+// ALL: "mcdc":{"count":12,"covered":10,"notcovered":2,"percent":83.333333333333343}
Instructions for regenerating the test:
@@ -13,6 +21,6 @@ Instructions for regenerating the test:
cp mcdc-general.cpp /tmp
clang -fcoverage-mcdc -fprofile-instr-generate -fcoverage-compilation-dir=. \
- -fcoverage-mapping /tmp/mcdc-general.cpp -o /tmp/mcdc-const.o
+ -fcoverage-mapping /tmp/mcdc-general.cpp -o /tmp/mcdc-general.o
mv /tmp/mcdc-general.o %S/Inputs
diff --git a/llvm/test/tools/llvm-cov/mcdc-general-none.test b/llvm/test/tools/llvm-cov/mcdc-general-none.test
index b57b35d49c8c1..f2013a17964d1 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general-none.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general-none.test
@@ -15,9 +15,11 @@
// CHECK-NEXT: | Condition C3 --> (12:20)
// CHECK-NEXT: | Condition C4 --> (12:25)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
// CHECK-NEXT: |
-// CHECK-NEXT: | None.
+// CHECK-NEXT: | Executed:
+// CHECK-NEXT: |
+// CHECK-NEXT: | None.
// CHECK-NEXT: |
// CHECK-NEXT: | C1-Pair: not covered
// CHECK-NEXT: | C2-Pair: not covered
@@ -27,6 +29,124 @@
// CHECK-NEXT: |
// CHECK-NEXT: ------------------
+// RUN: llvm-cov show --show-mcdc --show-mcdc-non-executed-vectors %S/Inputs/mcdc-general.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=ALL
+
+// ALL: test(bool
+
+// ALL: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (12:7) to (12:27)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 4
+// ALL-NEXT: | Condition C1 --> (12:8)
+// ALL-NEXT: | Condition C2 --> (12:13)
+// ALL-NEXT: | Condition C3 --> (12:20)
+// ALL-NEXT: | Condition C4 --> (12:25)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | None.
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4 Result
+// ALL-NEXT: | 1 { F, -, F, - = F }
+// ALL-NEXT: | 2 { T, F, F, - = F }
+// ALL-NEXT: | 3 { F, -, T, F = F }
+// ALL-NEXT: | 4 { T, F, T, F = F }
+// ALL-NEXT: | 5 { F, -, T, T = T }
+// ALL-NEXT: | 6 { T, F, T, T = T }
+// ALL-NEXT: | 7 { T, T, -, - = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: not covered
+// ALL-NEXT: | C3-Pair: not covered
+// ALL-NEXT: | C4-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
+// ALL: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (15:7) to (15:13)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 2
+// ALL-NEXT: | Condition C1 --> (15:7)
+// ALL-NEXT: | Condition C2 --> (15:12)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | None.
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 1 { F, - = F }
+// ALL-NEXT: | 2 { T, F = F }
+// ALL-NEXT: | 3 { T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: |---> MC/DC Decision Region (15:19) to (15:25)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 2
+// ALL-NEXT: | Condition C1 --> (15:19)
+// ALL-NEXT: | Condition C2 --> (15:24)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | None.
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 1 { F, - = F }
+// ALL-NEXT: | 2 { T, F = F }
+// ALL-NEXT: | 3 { T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
+// ALL: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (18:7) to (19:15)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 4
+// ALL-NEXT: | Condition C1 --> (18:8)
+// ALL-NEXT: | Condition C2 --> (18:13)
+// ALL-NEXT: | Condition C3 --> (19:8)
+// ALL-NEXT: | Condition C4 --> (19:13)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | None.
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4 Result
+// ALL-NEXT: | 1 { F, -, -, - = F }
+// ALL-NEXT: | 2 { T, F, -, - = F }
+// ALL-NEXT: | 3 { T, T, F, - = F }
+// ALL-NEXT: | 4 { T, T, T, F = F }
+// ALL-NEXT: | 5 { T, T, T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: not covered
+// ALL-NEXT: | C3-Pair: not covered
+// ALL-NEXT: | C4-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
// Turn off MC/DC visualization.
// RUN: llvm-cov show %S/Inputs/mcdc-general.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=NOMCDC
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index 1835af9a4c6b5..7f2f449c197bb 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -2,6 +2,7 @@
// RUN: llvm-profdata merge %S/Inputs/mcdc-general.proftext -o %t.profdata
// RUN: llvm-cov show --show-mcdc %S/Inputs/mcdc-general.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s
+// RUN: llvm-cov show --show-mcdc --show-mcdc-non-executed-vectors %S/Inputs/mcdc-general.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=ALL
// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-general.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %s -check-prefix=REPORT
// CHECK: test(bool
@@ -15,7 +16,9 @@
// CHECK-NEXT: | Condition C3 --> (12:20)
// CHECK-NEXT: | Condition C4 --> (12:25)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2, C3, C4 Result
// CHECK-NEXT: | 1 { F, -, F, - = F }
@@ -40,7 +43,9 @@
// CHECK-NEXT: | Condition C1 --> (15:7)
// CHECK-NEXT: | Condition C2 --> (15:12)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2 Result
// CHECK-NEXT: | 1 { F, - = F }
@@ -57,7 +62,9 @@
// CHECK-NEXT: | Condition C1 --> (15:19)
// CHECK-NEXT: | Condition C2 --> (15:24)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2 Result
// CHECK-NEXT: | 1 { F, - = F }
@@ -78,7 +85,9 @@
// CHECK-NEXT: | Condition C3 --> (19:8)
// CHECK-NEXT: | Condition C4 --> (19:13)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2, C3, C4 Result
// CHECK-NEXT: | 1 { F, -, -, - = F }
@@ -94,6 +103,125 @@
// CHECK-NEXT: |
// CHECK-NEXT: ------------------
+// Same as CHECK above, but with --show-mcdc-non-executed-vectors (Not executed section after each decision).
+
+// ALL: test(bool
+
+// ALL: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (12:7) to (12:27)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 4
+// ALL-NEXT: | Condition C1 --> (12:8)
+// ALL-NEXT: | Condition C2 --> (12:13)
+// ALL-NEXT: | Condition C3 --> (12:20)
+// ALL-NEXT: | Condition C4 --> (12:25)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4 Result
+// ALL-NEXT: | 1 { F, -, F, - = F }
+// ALL-NEXT: | 2 { T, F, F, - = F }
+// ALL-NEXT: | 3 { F, -, T, F = F }
+// ALL-NEXT: | 4 { T, F, T, F = F }
+// ALL-NEXT: | 5 { T, F, T, T = T }
+// ALL-NEXT: | 6 { T, T, -, - = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4 Result
+// ALL-NEXT: | 7 { F, -, T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: covered: (1,6)
+// ALL-NEXT: | C2-Pair: covered: (2,6)
+// ALL-NEXT: | C3-Pair: covered: (2,5)
+// ALL-NEXT: | C4-Pair: covered: (4,5)
+// ALL-NEXT: | MC/DC Coverage for Decision: 100.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
+// ALL: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (15:7) to (15:13)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 2
+// ALL-NEXT: | Condition C1 --> (15:7)
+// ALL-NEXT: | Condition C2 --> (15:12)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 1 { F, - = F }
+// ALL-NEXT: | 2 { T, F = F }
+// ALL-NEXT: | 3 { T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | None.
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: covered: (1,3)
+// ALL-NEXT: | C2-Pair: covered: (2,3)
+// ALL-NEXT: | MC/DC Coverage for Decision: 100.00%
+// ALL-NEXT: |
+// ALL-NEXT: |---> MC/DC Decision Region (15:19) to (15:25)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 2
+// ALL-NEXT: | Condition C1 --> (15:19)
+// ALL-NEXT: | Condition C2 --> (15:24)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 1 { F, - = F }
+// ALL-NEXT: | 2 { T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 3 { T, F = F }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: covered: (1,2)
+// ALL-NEXT: | C2-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 50.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
+// ALL: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (18:7) to (19:15)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 4
+// ALL-NEXT: | Condition C1 --> (18:8)
+// ALL-NEXT: | Condition C2 --> (18:13)
+// ALL-NEXT: | Condition C3 --> (19:8)
+// ALL-NEXT: | Condition C4 --> (19:13)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4 Result
+// ALL-NEXT: | 1 { F, -, -, - = F }
+// ALL-NEXT: | 2 { T, F, -, - = F }
+// ALL-NEXT: | 3 { T, T, T, F = F }
+// ALL-NEXT: | 4 { T, T, T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4 Result
+// ALL-NEXT: | 5 { T, T, F, - = F }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: covered: (1,4)
+// ALL-NEXT: | C2-Pair: covered: (2,4)
+// ALL-NEXT: | C3-Pair: not covered
+// ALL-NEXT: | C4-Pair: covered: (3,4)
+// ALL-NEXT: | MC/DC Coverage for Decision: 75.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
// Turn off MC/DC visualization.
// RUN: llvm-cov show %S/Inputs/mcdc-general.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=NOMCDC
// NOMCDC-NOT: MC/DC Decision Region
diff --git a/llvm/test/tools/llvm-cov/mcdc-macro.test b/llvm/test/tools/llvm-cov/mcdc-macro.test
index d68f4aeb67bcb..e55d7e56c3f04 100644
--- a/llvm/test/tools/llvm-cov/mcdc-macro.test
+++ b/llvm/test/tools/llvm-cov/mcdc-macro.test
@@ -2,6 +2,7 @@
// RUN: llvm-profdata merge %S/Inputs/mcdc-macro.proftext -o %t.profdata
// RUN: llvm-cov show --show-expansions --show-branches=count --show-mcdc %S/Inputs/mcdc-macro.o -instr-profile %t.profdata --compilation-dir=%S/Inputs | FileCheck %s
+// RUN: llvm-cov show --show-expansions --show-branches=count --show-mcdc --show-mcdc-non-executed-vectors %S/Inputs/mcdc-macro.o -instr-profile %t.profdata --compilation-dir=%S/Inputs | FileCheck %s -check-prefix=ALL
// CHECK: | | | Branch (2:11): [Folded - Ignored]
// CHECK: | | | Branch (3:11): [True: 1, False: 0]
@@ -18,7 +19,9 @@
// CHECK-NEXT: | Condition C4 --> (3:23)
// CHECK-NEXT: | Condition C5 --> (9:22)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2, C3, C4, C5 Result
// CHECK-NEXT: | 1 { T, C, T, T, - = T }
@@ -41,7 +44,9 @@
// CHECK-NEXT: | Condition C1 --> (11:7)
// CHECK-NEXT: | Condition C2 --> (2:11)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2 Result
// CHECK-NEXT: | 1 { T, C = T }
@@ -69,7 +74,9 @@
// CHECK-NEXT: | Condition C5 --> (3:11)
// CHECK-NEXT: | Condition C6 --> (3:23)
// CHECK-NEXT: |
-// CHECK-NEXT: | Executed MC/DC Test Vectors:
+// CHECK-NEXT: | MC/DC Test Vectors:
+// CHECK-NEXT: |
+// CHECK-NEXT: | Executed:
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2, C3, C4, C5, C6 Result
// CHECK-NEXT: | 1 { T, T, T, C, -, - = T }
@@ -84,6 +91,129 @@
// CHECK-NEXT: |
// CHECK-NEXT: ------------------
+// Same as CHECK above, but with --show-mcdc-non-executed-vectors (Not executed section after each decision).
+
+// ALL: | | | Branch (2:11): [Folded - Ignored]
+// ALL: | | | Branch (3:11): [True: 1, False: 0]
+// ALL: | | | Branch (3:23): [True: 1, False: 0]
+// ALL: | Branch (9:7): [True: 1, False: 0]
+// ALL-NEXT: | Branch (9:22): [True: 0, False: 0]
+// ALL-NEXT: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (9:7) to (9:23)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 5
+// ALL-NEXT: | Condition C1 --> (9:7)
+// ALL-NEXT: | Condition C2 --> (2:11)
+// ALL-NEXT: | Condition C3 --> (3:11)
+// ALL-NEXT: | Condition C4 --> (3:23)
+// ALL-NEXT: | Condition C5 --> (9:22)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4, C5 Result
+// ALL-NEXT: | 1 { T, C, T, T, - = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4, C5 Result
+// ALL-NEXT: | 2 { F, C, -, -, F = F }
+// ALL-NEXT: | 3 { T, C, -, -, F = F }
+// ALL-NEXT: | 4 { T, C, F, -, F = F }
+// ALL-NEXT: | 5 { T, C, T, F, F = F }
+// ALL-NEXT: | 6 { F, C, -, -, T = T }
+// ALL-NEXT: | 7 { T, C, -, -, T = T }
+// ALL-NEXT: | 8 { T, C, F, -, T = T }
+// ALL-NEXT: | 9 { T, C, T, F, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: constant folded
+// ALL-NEXT: | C3-Pair: not covered
+// ALL-NEXT: | C4-Pair: not covered
+// ALL-NEXT: | C5-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
+// ALL: | | | Branch (2:11): [Folded - Ignored]
+// ALL: | Branch (11:7): [True: 1, False: 0]
+// ALL-NEXT: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (11:7) to (11:13)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 2
+// ALL-NEXT: | Condition C1 --> (11:7)
+// ALL-NEXT: | Condition C2 --> (2:11)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 1 { T, C = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2 Result
+// ALL-NEXT: | 2 { F, C = F }
+// ALL-NEXT: | 3 { T, C = F }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: constant folded
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
+// ALL: | | | Branch (1:11): [True: 1, False: 0]
+// ALL: | | | Branch (2:11): [Folded - Ignored]
+// ALL: | | | | | Branch (3:11): [True: 0, False: 0]
+// ALL: | | | | | Branch (3:23): [True: 0, False: 0]
+// ALL: | Branch (13:7): [True: 1, False: 0]
+// ALL-NEXT: | Branch (13:13): [True: 1, False: 0]
+// ALL-NEXT: ------------------
+// ALL-NEXT: |---> MC/DC Decision Region (13:7) to (13:32)
+// ALL-NEXT: |
+// ALL-NEXT: | Number of Conditions: 6
+// ALL-NEXT: | Condition C1 --> (13:7)
+// ALL-NEXT: | Condition C2 --> (13:13)
+// ALL-NEXT: | Condition C3 --> (1:11)
+// ALL-NEXT: | Condition C4 --> (2:11)
+// ALL-NEXT: | Condition C5 --> (3:11)
+// ALL-NEXT: | Condition C6 --> (3:23)
+// ALL-NEXT: |
+// ALL-NEXT: | MC/DC Test Vectors:
+// ALL-NEXT: |
+// ALL-NEXT: | Executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4, C5, C6 Result
+// ALL-NEXT: | 1 { T, T, T, C, -, - = T }
+// ALL-NEXT: |
+// ALL-NEXT: | Not executed:
+// ALL-NEXT: |
+// ALL-NEXT: | C1, C2, C3, C4, C5, C6 Result
+// ALL-NEXT: | 2 { F, -, -, C, -, - = F }
+// ALL-NEXT: | 3 { T, F, -, C, -, - = F }
+// ALL-NEXT: | 4 { T, T, F, C, -, - = F }
+// ALL-NEXT: | 5 { F, -, -, C, F, - = F }
+// ALL-NEXT: | 6 { T, F, -, C, F, - = F }
+// ALL-NEXT: | 7 { T, T, F, C, F, - = F }
+// ALL-NEXT: | 8 { F, -, -, C, T, F = F }
+// ALL-NEXT: | 9 { T, F, -, C, T, F = F }
+// ALL-NEXT: | 10 { T, T, F, C, T, F = F }
+// ALL-NEXT: | 11 { F, -, -, C, T, T = T }
+// ALL-NEXT: | 12 { T, F, -, C, T, T = T }
+// ALL-NEXT: | 13 { T, T, F, C, T, T = T }
+// ALL-NEXT: |
+// ALL-NEXT: | C1-Pair: not covered
+// ALL-NEXT: | C2-Pair: not covered
+// ALL-NEXT: | C3-Pair: not covered
+// ALL-NEXT: | C4-Pair: constant folded
+// ALL-NEXT: | C5-Pair: not covered
+// ALL-NEXT: | C6-Pair: not covered
+// ALL-NEXT: | MC/DC Coverage for Decision: 0.00%
+// ALL-NEXT: |
+// ALL-NEXT: ------------------
+
Instructions for regenerating the test:
cd %S/Inputs # Or copy mcdc-macro.c into the working directory
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 4be6d8d9cdaf7..1196faa1acef9 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -1024,6 +1024,11 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
cl::desc("Show the MCDC Coverage for each applicable boolean expression"),
cl::cat(ViewCategory));
+ cl::opt<bool> ShowMCDCNonExecutedVectors(
+ "show-mcdc-non-executed-vectors", cl::Optional,
+ cl::desc("Show MC/DC test vectors that were not executed"),
+ cl::cat(ViewCategory));
+
cl::opt<bool> ShowBestLineRegionsCounts(
"show-line-counts-or-regions", cl::Optional,
cl::desc("Show the execution counts for each line, or the execution "
@@ -1130,6 +1135,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
ViewOpts.ShowBranchCounts =
ShowBranches == CoverageViewOptions::BranchOutputType::Count;
ViewOpts.ShowMCDC = ShowMCDC;
+ ViewOpts.ShowMCDCNonExecutedVectors = ShowMCDCNonExecutedVectors;
ViewOpts.ShowBranchPercents =
ShowBranches == CoverageViewOptions::BranchOutputType::Percent;
ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
@@ -1321,6 +1327,12 @@ int CodeCoverageTool::doExport(int argc, const char **argv,
cl::desc("Unify function instantiations"),
cl::init(true), cl::cat(ExportCategory));
+ cl::opt<bool> ShowMCDCNonExecutedVectors(
+ "show-mcdc-non-executed-vectors", cl::Optional,
+ cl::desc("Include MC/DC test vectors that were not executed in the "
+ "export"),
+ cl::cat(ExportCategory));
+
auto Err = commandLineParser(argc, argv);
if (Err)
return Err;
@@ -1329,6 +1341,7 @@ int CodeCoverageTool::doExport(int argc, const char **argv,
ViewOpts.SkipFunctions = SkipFunctions;
ViewOpts.SkipBranches = SkipBranches;
ViewOpts.UnifyFunctionInstantiations = UnifyInstantiations;
+ ViewOpts.ShowMCDCNonExecutedVectors = ShowMCDCNonExecutedVectors;
if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text &&
ViewOpts.Format != CoverageViewOptions::OutputFormat::Lcov) {
diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 4c07c05396732..d8c01db6906fb 100644
--- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -22,7 +22,7 @@
// -- 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 and
-// list of executed test vectors
+// list of test vectors with execution status
// -- 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
@@ -121,11 +121,13 @@ json::Value renderCondState(const coverage::MCDCRecord::CondState CondState) {
llvm_unreachable("Unknown llvm::coverage::MCDCRecord::CondState enum");
}
-json::Array gatherTestVectors(coverage::MCDCRecord &Record) {
+json::Array gatherTestVectors(coverage::MCDCRecord &Record,
+ const CoverageViewOptions &Options) {
json::Array TestVectors;
unsigned NumConditions = Record.getNumConditions();
- for (unsigned tv = 0; tv < Record.getNumTestVectors(); tv++) {
+ const bool ShowNonExecutedVectors = Options.ShowMCDCNonExecutedVectors;
+ 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)));
@@ -134,18 +136,32 @@ json::Array gatherTestVectors(coverage::MCDCRecord &Record) {
json::Object({{"executed", json::Value(true)},
{"result", renderCondState(Record.getTVResult(tv))},
{"conditions", std::move(TVConditions)}}));
+ }
+ if (ShowNonExecutedVectors) {
+ for (unsigned tv = 0; tv < Record.getNumNotExecutedTestVectors(); tv++) {
+ json::Array TVConditions;
+ for (unsigned c = 0; c < NumConditions; c++)
+ TVConditions.push_back(
+ renderCondState(Record.getNotExecutedTVCondition(tv, c)));
+
+ TestVectors.push_back(json::Object(
+ {{"executed", json::Value(false)},
+ {"result", renderCondState(Record.getNotExecutedTVResult(tv))},
+ {"conditions", std::move(TVConditions)}}));
+ }
}
return TestVectors;
}
-json::Array renderMCDCRecord(const coverage::MCDCRecord &Record) {
+json::Array renderMCDCRecord(const coverage::MCDCRecord &Record,
+ const CoverageViewOptions &Options) {
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),
- gatherTestVectors(const_cast<coverage::MCDCRecord &>(Record))});
+ gatherTestVectors(const_cast<coverage::MCDCRecord &>(Record), Options)});
}
json::Array renderRegions(ArrayRef<coverage::CountedRegion> Regions) {
@@ -163,10 +179,11 @@ json::Array renderBranchRegions(ArrayRef<coverage::CountedRegion> Regions) {
return RegionArray;
}
-json::Array renderMCDCRecords(ArrayRef<coverage::MCDCRecord> Records) {
+json::Array renderMCDCRecords(ArrayRef<coverage::MCDCRecord> Records,
+ const CoverageViewOptions &Options) {
json::Array RecordArray;
for (auto &Record : Records)
- RecordArray.push_back(renderMCDCRecord(Record));
+ RecordArray.push_back(renderMCDCRecord(Record, Options));
return RecordArray;
}
@@ -268,10 +285,11 @@ json::Array renderFileBranches(const coverage::CoverageData &FileCoverage) {
return BranchArray;
}
-json::Array renderFileMCDC(const coverage::CoverageData &FileCoverage) {
+json::Array renderFileMCDC(const coverage::CoverageData &FileCoverage,
+ const CoverageViewOptions &Options) {
json::Array MCDCRecordArray;
for (const auto &Record : FileCoverage.getMCDCRecords())
- MCDCRecordArray.push_back(renderMCDCRecord(Record));
+ MCDCRecordArray.push_back(renderMCDCRecord(Record, Options));
return MCDCRecordArray;
}
@@ -285,7 +303,7 @@ json::Object renderFile(const coverage::CoverageMapping &Coverage,
auto FileCoverage = Coverage.getCoverageForFile(Filename);
File["segments"] = renderFileSegments(FileCoverage);
File["branches"] = renderFileBranches(FileCoverage);
- File["mcdc_records"] = renderFileMCDC(FileCoverage);
+ File["mcdc_records"] = renderFileMCDC(FileCoverage, Options);
if (!Options.SkipExpansions) {
File["expansions"] = renderFileExpansions(Coverage, FileCoverage);
}
@@ -325,16 +343,17 @@ json::Array renderFiles(const coverage::CoverageMapping &Coverage,
}
json::Array renderFunctions(
- const iterator_range<coverage::FunctionRecordIterator> &Functions) {
+ const iterator_range<coverage::FunctionRecordIterator> &Functions,
+ const CoverageViewOptions &Options) {
json::Array FunctionArray;
for (const auto &F : Functions)
- FunctionArray.push_back(
- json::Object({{"name", F.Name},
- {"count", clamp_uint64_to_int64(F.ExecutionCount)},
- {"regions", renderRegions(F.CountedRegions)},
- {"branches", renderBranchRegions(F.CountedBranchRegions)},
- {"mcdc_records", renderMCDCRecords(F.MCDCRecords)},
- {"filenames", json::Array(F.Filenames)}}));
+ FunctionArray.push_back(json::Object(
+ {{"name", F.Name},
+ {"count", clamp_uint64_to_int64(F.ExecutionCount)},
+ {"regions", renderRegions(F.CountedRegions)},
+ {"branches", renderBranchRegions(F.CountedBranchRegions)},
+ {"mcdc_records", renderMCDCRecords(F.MCDCRecords, Options)},
+ {"filenames", json::Array(F.Filenames)}}));
return FunctionArray;
}
@@ -368,7 +387,8 @@ void CoverageExporterJson::renderRoot(ArrayRef<std::string> SourceFiles) {
{{"files", std::move(Files)}, {"totals", renderSummary(Totals)}});
// Skip functions-level information if necessary.
if (!Options.ExportSummaryOnly && !Options.SkipFunctions)
- Export["functions"] = renderFunctions(Coverage.getCoveredFunctions());
+ Export["functions"] =
+ renderFunctions(Coverage.getCoveredFunctions(), Options);
auto ExportArray = json::Array({std::move(Export)});
diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index 7ac38d76a7e41..4826d4adb53bf 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -31,6 +31,7 @@ struct CoverageViewOptions {
bool ShowLineStats;
bool ShowRegionMarkers;
bool ShowMCDC;
+ bool ShowMCDCNonExecutedVectors = false;
bool ShowBranchCounts;
bool ShowBranchPercents;
bool ShowExpandedRegions;
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index bdef0994d1841..1cc8f1ba92bd2 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -1152,6 +1152,9 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV,
void SourceCoverageViewHTML::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
unsigned ViewDepth) {
+ const bool ShowNonExecutedVectors =
+ getOptions().ShowMCDCNonExecutedVectors;
+
for (auto &Record : MRV.Records) {
OS << BeginExpansionDiv;
OS << BeginPre;
@@ -1179,10 +1182,33 @@ void SourceCoverageViewHTML::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
OS << " " << Record.getConditionHeaderString(i);
}
OS << "\n";
- OS << " Executed MC/DC Test Vectors:\n\n ";
- OS << Record.getTestVectorHeaderString();
- for (unsigned i = 0; i < Record.getNumTestVectors(); i++)
- OS << Record.getTestVectorString(i);
+ OS << " MC/DC Test Vectors\n\n";
+
+ const unsigned NumExecuted = Record.getNumTestVectors();
+ const unsigned NumNotExecuted = Record.getNumNotExecutedTestVectors();
+
+ const std::string HeaderStr = Record.getTestVectorHeaderString();
+
+ OS << " Executed:\n\n ";
+ if (NumExecuted == 0) {
+ OS << "None.\n";
+ } else {
+ OS << HeaderStr;
+ for (unsigned k = 0; k < NumExecuted; k++)
+ OS << Record.getTestVectorString(k);
+ }
+
+ if (ShowNonExecutedVectors) {
+ OS << "\n Not executed:\n\n ";
+ if (NumNotExecuted == 0) {
+ OS << "None.\n";
+ } else {
+ OS << HeaderStr;
+ for (unsigned k = 0; k < NumNotExecuted; k++)
+ OS << Record.getNotExecutedTestVectorString(k);
+ }
+ }
+
OS << "\n";
for (unsigned i = 0; i < Record.getNumConditions(); i++)
OS << Record.getConditionCoverageString(i);
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index df8eb1d871878..dbe8fb7f91e01 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -337,6 +337,9 @@ void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV,
void SourceCoverageViewText::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
unsigned ViewDepth) {
+ const bool ShowNonExecutedVectors =
+ getOptions().ShowMCDCNonExecutedVectors;
+
for (auto &Record : MRV.Records) {
renderLinePrefix(OS, ViewDepth);
OS << "---> MC/DC Decision Region (";
@@ -359,16 +362,53 @@ void SourceCoverageViewText::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
renderLinePrefix(OS, ViewDepth);
OS << "\n";
renderLinePrefix(OS, ViewDepth);
- OS << " Executed MC/DC Test Vectors:\n";
+ OS << " MC/DC Test Vectors:\n";
renderLinePrefix(OS, ViewDepth);
OS << "\n";
+
+ const unsigned NumExecuted = Record.getNumTestVectors();
+ const unsigned NumNotExecuted = Record.getNumNotExecutedTestVectors();
+
+ const std::string HeaderStr = Record.getTestVectorHeaderString();
+
renderLinePrefix(OS, ViewDepth);
- OS << " ";
- OS << Record.getTestVectorHeaderString();
- for (unsigned i = 0; i < Record.getNumTestVectors(); i++) {
+ OS << " Executed:\n";
+ renderLinePrefix(OS, ViewDepth);
+ OS << "\n";
+ if (NumExecuted == 0) {
+ renderLinePrefix(OS, ViewDepth);
+ OS << " None.\n";
+ } else {
renderLinePrefix(OS, ViewDepth);
- OS << Record.getTestVectorString(i);
+ OS << " ";
+ OS << HeaderStr;
+ for (unsigned k = 0; k < NumExecuted; k++) {
+ renderLinePrefix(OS, ViewDepth);
+ OS << Record.getTestVectorString(k);
+ }
}
+
+ if (ShowNonExecutedVectors) {
+ renderLinePrefix(OS, ViewDepth);
+ OS << "\n";
+ renderLinePrefix(OS, ViewDepth);
+ OS << " Not executed:\n";
+ renderLinePrefix(OS, ViewDepth);
+ OS << "\n";
+ if (NumNotExecuted == 0) {
+ renderLinePrefix(OS, ViewDepth);
+ OS << " None.\n";
+ } else {
+ renderLinePrefix(OS, ViewDepth);
+ OS << " ";
+ OS << HeaderStr;
+ for (unsigned k = 0; k < NumNotExecuted; k++) {
+ renderLinePrefix(OS, ViewDepth);
+ OS << Record.getNotExecutedTestVectorString(k);
+ }
+ }
+ }
+
renderLinePrefix(OS, ViewDepth);
OS << "\n";
for (unsigned i = 0; i < Record.getNumConditions(); i++) {
More information about the llvm-commits
mailing list