// Test visualization of MC/DC constructs for constant-folded condition masking.
// RUN: llvm-profdata merge %S/Inputs/mcdc-const.proftext -o %t.profdata
// RUN: llvm-cov show --show-branches=count --show-mcdc %S/Inputs/mcdc-const.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefix=CHECKGENERALCASE
// CHECKGENERALCASE: ------------------
// CHECKGENERALCASE-NEXT: | Branch (12:8): [True: 4, False: 1]
// CHECKGENERALCASE-NEXT: | Branch (12:13): [Folded - Ignored]
// CHECKGENERALCASE-NEXT: | Branch (12:20): [Folded - Ignored]
// CHECKGENERALCASE-NEXT: | Branch (12:25): [True: 0, False: 0]
// CHECKGENERALCASE-NEXT: | Branch (12:31): [Folded - Ignored]
// CHECKGENERALCASE-NEXT: ------------------
// CHECKGENERALCASE-NEXT: |---> MC/DC Decision Region (12:7) to (12:32)
// CHECKGENERALCASE-NEXT: |
// CHECKGENERALCASE-NEXT: | Number of Conditions: 5
// CHECKGENERALCASE-NEXT: | Condition C1 --> (12:8)
// CHECKGENERALCASE-NEXT: | Condition C2 --> (12:13)
// CHECKGENERALCASE-NEXT: | Condition C3 --> (12:20)
// CHECKGENERALCASE-NEXT: | Condition C4 --> (12:25)
// CHECKGENERALCASE-NEXT: | Condition C5 --> (12:31)
// CHECKGENERALCASE-NEXT: |
// CHECKGENERALCASE-NEXT: | Executed MC/DC Test Vectors:
// CHECKGENERALCASE-NEXT: |
// CHECKGENERALCASE-NEXT: | C1, C2, C3, C4, C5 Result
// CHECKGENERALCASE-NEXT: | 1 { F, C, C, -, C = F }
// CHECKGENERALCASE-NEXT: | 2 { T, C, C, -, C = T }
// CHECKGENERALCASE-NEXT: |
// CHECKGENERALCASE-NEXT: | C1-Pair: covered: (1,2)
// CHECKGENERALCASE-NEXT: | C2-Pair: constant folded
// CHECKGENERALCASE-NEXT: | C3-Pair: constant folded
// CHECKGENERALCASE-NEXT: | C4-Pair: not covered
// CHECKGENERALCASE-NEXT: | C5-Pair: constant folded
// CHECKGENERALCASE-NEXT: | MC/DC Coverage for Decision: 50.00%
// CHECKGENERALCASE-NEXT: |
// CHECKGENERALCASE-NEXT: ------------------
// 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
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C = F }
// CHECKFULLCASE-NEXT: | 2 { T, C = F }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { C, F = F }
// CHECKFULLCASE-NEXT: | 2 { C, T = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: covered: (1,2)
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { F, C = F }
// CHECKFULLCASE-NEXT: | 2 { T, C = T }
// CHECKFULLCASE: | C1-Pair: covered: (1,2)
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { C, - = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C = T }
// CHECKFULLCASE-NEXT: | 2 { T, C = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { C, F = F }
// CHECKFULLCASE-NEXT: | 2 { C, T = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: covered: (1,2)
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { F, C = F }
// CHECKFULLCASE-NEXT: | 2 { T, C = T }
// CHECKFULLCASE: | C1-Pair: covered: (1,2)
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { C, -, - = F }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C, - = F }
// CHECKFULLCASE-NEXT: | 2 { T, C, - = F }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { C, F, - = F }
// CHECKFULLCASE-NEXT: | 2 { C, T, F = F }
// CHECKFULLCASE-NEXT: | 3 { C, T, T = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: covered: (1,3)
// CHECKFULLCASE-NEXT: | C3-Pair: covered: (2,3)
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { F, C, - = F }
// CHECKFULLCASE-NEXT: | 2 { T, C, F = F }
// CHECKFULLCASE-NEXT: | 3 { T, C, T = T }
// CHECKFULLCASE: | C1-Pair: covered: (1,3)
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: covered: (2,3)
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { C, -, - = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C, - = T }
// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { C, F, T = T }
// CHECKFULLCASE-NEXT: | 2 { C, T, - = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C, T = T }
// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, -, C = F }
// CHECKFULLCASE-NEXT: | 2 { T, F, C = F }
// CHECKFULLCASE-NEXT: | 3 { T, T, C = F }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C, - = F }
// CHECKFULLCASE-NEXT: | 2 { T, C, - = F }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, -, C = F }
// CHECKFULLCASE-NEXT: | 2 { T, F, C = F }
// CHECKFULLCASE-NEXT: | 3 { T, T, C = T }
// CHECKFULLCASE: | C1-Pair: covered: (1,3)
// CHECKFULLCASE-NEXT: | C2-Pair: covered: (2,3)
// CHECKFULLCASE-NEXT: | C3-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { F, C, - = F }
// CHECKFULLCASE-NEXT: | 2 { T, C, F = F }
// CHECKFULLCASE-NEXT: | 3 { T, C, T = T }
// CHECKFULLCASE: | C1-Pair: covered: (1,3)
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: covered: (2,3)
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
// CHECKFULLCASE: | 1 { F, T, C = T }
// CHECKFULLCASE-NEXT: | 2 { T, -, C = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C, - = T }
// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, T, C = T }
// CHECKFULLCASE-NEXT: | 2 { T, -, C = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// CHECKFULLCASE: | 1 { F, C, T = T }
// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
// REPORT: _Z5case0b {{.*}} 1 1 0.00%
// REPORT-NEXT: _Z5case1b {{.*}} 1 1 0.00%
// REPORT-NEXT: _Z5case2b {{.*}} 1 0 100.00%
// REPORT-NEXT: _Z5case3b {{.*}} 1 0 100.00%
// REPORT-NEXT: _Z5case4b {{.*}} 1 1 0.00%
// REPORT-NEXT: _Z5case5b {{.*}} 1 1 0.00%
// REPORT-NEXT: _Z5case6b {{.*}} 1 0 100.00%
// REPORT-NEXT: _Z5case7b {{.*}} 1 0 100.00%
// REPORT-NEXT: _Z5case8bb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5case9bb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5caseabb {{.*}} 2 0 100.00%
// REPORT-NEXT: _Z5casebbb {{.*}} 2 0 100.00%
// REPORT-NEXT: _Z5casecbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5casedbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5caseebb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5casefbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5casegbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5casehbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5caseibb {{.*}} 2 0 100.00%
// REPORT-NEXT: _Z5casejbb {{.*}} 2 0 100.00%
// REPORT-NEXT: _Z5casekbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5caselbb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5casembb {{.*}} 2 2 0.00%
// REPORT-NEXT: _Z5casenbb {{.*}} 2 2 0.00%
// REPORT: TOTAL {{.*}} 40 28 30.00%
Instructions for regenerating the test:
cd %S/Inputs # Or copy files into the working directory
clang++ -c -Os \
-fcoverage-compilation-dir=. -mllvm -enable-name-compression=false \
-fcoverage-mcdc -fprofile-instr-generate -fcoverage-mapping \
mcdc-const.cpp mcdc-const-folding.cpp
# Instructions for regenerating proftext
for x in mcdc-const mcdc-const-folding; do (
clang++ -fprofile-instr-generate $x.o -o $x
find -name '*.profraw' | xargs rm -f
export LLVM_PROFILE_FILE=$x-%p.profraw
./$x 0 1
if [ "$x" = "mcdc-const-folding" ]; then
./$x 1 0
./$x 1 1
./$x 1 1 # Redundant
fi
llvm-profdata merge --sparse -o $x.profdata $(find -name '*.profraw')
llvm-profdata merge --text -o $x.proftext $x.profdata
); done