[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