Skip to content

Commit 1c749a6

Browse files
committed
Add /warnVacuousProofs option
This option enables `/trackVerificationCoverage` and automatically warns if it detects vacuous proofs. This is intended for the less-common case where a front end doesn't add IDs to program elements and then post- process the results.
1 parent 7f9f784 commit 1c749a6

File tree

4 files changed

+198
-2
lines changed

4 files changed

+198
-2
lines changed

Source/ExecutionEngine/CommandLineOptions.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,15 @@ public bool TrackVerificationCoverage {
322322
set => trackVerificationCoverage = value;
323323
}
324324

325+
public bool WarnVacuousProofs
326+
{
327+
get => warnVacuousProofs;
328+
set {
329+
warnVacuousProofs = value;
330+
if (warnVacuousProofs) { trackVerificationCoverage = true; }
331+
}
332+
}
333+
325334
public int InlineDepth { get; set; } = -1;
326335

327336
public bool UseProverEvaluate {
@@ -605,6 +614,7 @@ void ObjectInvariant5()
605614
private bool normalizeNames;
606615
private bool normalizeDeclarationOrder = true;
607616
private bool keepQuantifier = false;
617+
private bool warnVacuousProofs;
608618

609619
public List<CoreOptions.ConcurrentHoudiniOptions> Cho { get; set; } = new();
610620

@@ -1373,6 +1383,7 @@ protected override bool ParseOption(string name, CommandLineParseState ps)
13731383
ps.CheckBooleanFlag("useUnsatCoreForContractInfer", x => useUnsatCoreForContractInfer = x) ||
13741384
ps.CheckBooleanFlag("printAssignment", x => PrintAssignment = x) ||
13751385
ps.CheckBooleanFlag("trackVerificationCoverage", x => trackVerificationCoverage = x) ||
1386+
ps.CheckBooleanFlag("warnVacuousProofs", x => WarnVacuousProofs = x) ||
13761387
ps.CheckBooleanFlag("useProverEvaluate", x => useProverEvaluate = x) ||
13771388
ps.CheckBooleanFlag("deterministicExtractLoops", x => DeterministicExtractLoops = x) ||
13781389
ps.CheckBooleanFlag("verifySeparately", x => VerifySeparately = x) ||
@@ -2005,7 +2016,11 @@ Track and report which program elements labeled with an
20052016
assignments, and calls can be labeled for inclusion in this
20062017
report. This generalizes and replaces the previous
20072018
(undocumented) `/printNecessaryAssertions` option.
2008-
2019+
/warnVacuousProofs
2020+
Automatically add `{:id ...}` attributes to assumptions, assertions,
2021+
requires clauses, ensures clauses, and calls; enable the
2022+
`/trackVerificationCoverage` option; and warn when proof goals are
2023+
not covered by a proof.
20092024
/keepQuantifier
20102025
If pool-based quantifier instantiation creates instances of a quantifier
20112026
then keep the quantifier along with the instances. By default, the quantifier

Source/ExecutionEngine/ExecutionEngine.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,9 @@ private Task<ProcessedProgram> PreProcessProgramVerification(Program program, Ca
611611
}
612612

613613
var processedProgram = Options.ExtractLoops ? ExtractLoops(program) : new ProcessedProgram(program);
614+
if (Options.WarnVacuousProofs) {
615+
processedProgram = AddVacuityChecking(processedProgram);
616+
}
614617

615618
if (Options.PrintInstrumented)
616619
{
@@ -635,6 +638,55 @@ private ProcessedProgram ExtractLoops(Program program)
635638
});
636639
}
637640

641+
private ProcessedProgram AddVacuityChecking(ProcessedProgram processedProgram)
642+
{
643+
Program program = processedProgram.Program;
644+
CoverageAnnotator annotator = new CoverageAnnotator();
645+
foreach (var impl in program.Implementations) {
646+
annotator.VisitImplementation(impl);
647+
}
648+
return new ProcessedProgram(program, (vcgen, impl, result) =>
649+
{
650+
CheckVacuity(annotator, impl, result);
651+
processedProgram.PostProcessResult(vcgen, impl, result);
652+
}
653+
);
654+
}
655+
656+
private void CheckVacuity(CoverageAnnotator annotator, Implementation impl, ImplementationRunResult verificationResult)
657+
{
658+
var covered = verificationResult
659+
.RunResults
660+
.SelectMany(r => r.CoveredElements)
661+
.ToHashSet();
662+
foreach (var goalId in annotator.GetImplementationGoalIds(impl.Name)) {
663+
if (!CoveredId(goalId, covered)) {
664+
var node = annotator.GetIdNode(goalId);
665+
Options.Printer.AdvisoryWriteLine(Options.OutputWriter,
666+
$"{node.tok.filename}({node.tok.line},{node.tok.col - 1}): Warning: Proved vacuously");
667+
}
668+
}
669+
}
670+
671+
private static bool CoveredId(string goalId, HashSet<TrackedNodeComponent> covered)
672+
{
673+
foreach (var component in covered) {
674+
if (component is LabeledNodeComponent { id: var id } && id == goalId) {
675+
return true;
676+
}
677+
678+
if (component is TrackedInvariantEstablished { invariantId: var eid } && eid == goalId) {
679+
return true;
680+
}
681+
682+
if (component is TrackedInvariantMaintained { invariantId: var mid } && mid == goalId) {
683+
return true;
684+
}
685+
}
686+
687+
return false;
688+
}
689+
638690
private Implementation[] GetPrioritizedImplementations(Program program)
639691
{
640692
var impls = program.Implementations.Where(
@@ -964,7 +1016,6 @@ private Task<ImplementationRunResult> VerifyImplementationWithLargeThread(Proces
9641016
return resultTask;
9651017
}
9661018

967-
9681019
#region Houdini
9691020

9701021
private async Task<PipelineOutcome> RunHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er,

Source/Provers/SMTLib/SMTLibOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public interface SMTLibOptions : CoreOptions
1414
bool ImmediatelyAcceptCommands { get; }
1515
bool RunningBoogieFromCommandLine { get; }
1616
bool TrackVerificationCoverage { get; }
17+
bool WarnVacuousProofs { get; }
1718
string ProverPreamble { get; }
1819
bool TraceDiagnosticsOnTimeout { get; }
1920
uint TimeLimitPerAssertionInPercent { get; }
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
Parsing verificationCoverage.bpl
2+
Coalescing blocks...
3+
Inlining...
4+
5+
Verifying testRequiresAssign ...
6+
[TRACE] Using prover: z3
7+
Proof dependencies:
8+
a0
9+
id0
10+
id1
11+
id2
12+
13+
Verifying sum ...
14+
Proof dependencies:
15+
id10
16+
id7
17+
id8
18+
id9
19+
invariant id4 assumed in body
20+
invariant id4 established
21+
invariant id4 maintained
22+
invariant id5 assumed in body
23+
invariant id5 established
24+
invariant id5 maintained
25+
invariant id6 established
26+
invariant id6 maintained
27+
28+
Verifying contradictoryAssume ...
29+
Proof dependencies:
30+
id11
31+
id12
32+
verificationCoverage.bpl(143,4): Warning: Proved vacuously
33+
34+
Verifying falseRequires ...
35+
Proof dependencies:
36+
id16
37+
verificationCoverage.bpl(150,4): Warning: Proved vacuously
38+
39+
Verifying contradictoryRequires ...
40+
Proof dependencies:
41+
id19
42+
id20
43+
verificationCoverage.bpl(158,4): Warning: Proved vacuously
44+
45+
Verifying assumeFalse ...
46+
Proof dependencies:
47+
id21
48+
verificationCoverage.bpl(163,2): Warning: Proved vacuously
49+
50+
Verifying testEnsuresCallee ...
51+
Proof dependencies:
52+
id23
53+
id24
54+
id25
55+
56+
Verifying testEnsuresCaller ...
57+
Proof dependencies:
58+
ensures clause id23 from call id26
59+
ensures clause id23 from call id27
60+
ensures clause id24 from call id27
61+
id28
62+
id29
63+
id30
64+
requires clause id25 proved for call id26
65+
requires clause id25 proved for call id27
66+
xy_sum
67+
68+
Verifying obviouslyUnconstrainedCode ...
69+
Proof dependencies:
70+
constrained
71+
id31
72+
id32
73+
74+
Verifying callContradictoryFunction ...
75+
Proof dependencies:
76+
ensures clause cont_ens_abs from call id34
77+
id36
78+
requires clause xpos_abs proved for call id34
79+
verificationCoverage.bpl(203,2): Warning: Proved vacuously
80+
81+
Verifying usesSomeInteger ...
82+
Proof dependencies:
83+
id37
84+
someInteger_value_axiom
85+
Proof dependencies of whole program:
86+
a0
87+
constrained
88+
ensures clause cont_ens_abs from call id34
89+
ensures clause id23 from call id26
90+
ensures clause id23 from call id27
91+
ensures clause id24 from call id27
92+
id0
93+
id1
94+
id10
95+
id11
96+
id12
97+
id16
98+
id19
99+
id2
100+
id20
101+
id21
102+
id23
103+
id24
104+
id25
105+
id28
106+
id29
107+
id30
108+
id31
109+
id32
110+
id36
111+
id37
112+
id7
113+
id8
114+
id9
115+
invariant id4 assumed in body
116+
invariant id4 established
117+
invariant id4 maintained
118+
invariant id5 assumed in body
119+
invariant id5 established
120+
invariant id5 maintained
121+
invariant id6 established
122+
invariant id6 maintained
123+
requires clause id25 proved for call id26
124+
requires clause id25 proved for call id27
125+
requires clause xpos_abs proved for call id34
126+
someInteger_value_axiom
127+
xy_sum
128+
129+
Boogie program verifier finished with 11 verified, 0 errors

0 commit comments

Comments
 (0)