Skip to content

Commit

Permalink
feat: Verification coverage analysis for axioms (#948)
Browse files Browse the repository at this point in the history
This PR enables verification coverage analysis for axioms.
  • Loading branch information
fabiomadge authored Oct 7, 2024
1 parent 2ea9a43 commit 475faa0
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Source/Core/Monomorphization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ public override Axiom VisitAxiom(Axiom node)
}
else
{
var newAxiom = new Axiom(axiom.tok, expr);
var newAxiom = new Axiom(axiom.tok, expr, axiom.Comment, axiom.Attributes);
if (monomorphizationVisitor.originalAxiomToSplitAxioms.ContainsKey(axiom)) {
monomorphizationVisitor.originalAxiomToSplitAxioms[axiom].Add(newAxiom);
}
Expand Down
10 changes: 9 additions & 1 deletion Source/Provers/SMTLib/ProverContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,15 @@ public override void AddAxiom(Axiom ax, string attributes)
//Contract.Requires(ax != null);
base.AddAxiom(ax, attributes);

axiomConjuncts.Add(translator.Translate(ax.Expr));
var expr = translator.Translate(ax.Expr);
var assumeId = QKeyValue.FindStringAttribute(ax.Attributes, "id");
if (assumeId != null && options.TrackVerificationCoverage)
{
var v = gen.Variable(assumeId, Microsoft.Boogie.Type.Bool, VCExprVarKind.Assume);
expr = gen.Function(VCExpressionGenerator.NamedAssumeOp, v, gen.ImpliesSimp(v, expr));
}

axiomConjuncts.Add(expr);
}

public override void AddAxiom(VCExpr vc)
Expand Down
5 changes: 1 addition & 4 deletions Source/VCGeneration/BlockTransformations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,8 @@ private static bool ContainsAssert(Block b)
public static bool IsNonTrivialAssert (Cmd c) { return c is AssertCmd { Expr: not LiteralExpr { asBool: true } }; }

private static void DeleteUselessBlocks(List<Block> blocks) {
var toVisit = new HashSet<Block>();
var toVisit = new HashSet<Block>(blocks);
var removed = new HashSet<Block>();
foreach (var block in blocks) {
toVisit.Add(block);
}
while(toVisit.Count > 0) {
var block = toVisit.First();
toVisit.Remove(block);
Expand Down
4 changes: 3 additions & 1 deletion Source/VCGeneration/Splits/Split.cs
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,9 @@ public VerificationRunResult ReadOutcome(int iteration, Checker checker, Verifie
Asserts: Asserts,
CoveredElements: CoveredElements,
ResourceCount: resourceCount,
SolverUsed: (Options as SMTLibSolverOptions)?.Solver);
SolverUsed: (Options as SMTLibSolverOptions)?.Solver,
DeclarationsAfterPruning: PrunedDeclarations
);
callback.OnVCResult(result);

if (Options.VcsDumpSplits)
Expand Down
3 changes: 2 additions & 1 deletion Source/VCGeneration/VerificationRunResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public record VerificationRunResult
List<AssertCmd> Asserts,
IEnumerable<TrackedNodeComponent> CoveredElements,
int ResourceCount,
SolverKind? SolverUsed
SolverKind? SolverUsed,
IReadOnlyList<Declaration> DeclarationsAfterPruning
) {
public void ComputePerAssertOutcomes(out Dictionary<AssertCmd, SolverOutcome> perAssertOutcome,
out Dictionary<AssertCmd, Counterexample> perAssertCounterExamples) {
Expand Down
15 changes: 15 additions & 0 deletions Test/coverage/verificationCoverage.bpl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
// CHECK: ensures clause cont_ens_abs from call call_cont
// CHECK: requires clause xpos_abs proved for call call_cont
// CHECK: xpos_caller
// CHECK: Proof dependencies:
// CHECK: someInteger_value_axiom
// CHECK: Proof dependencies of whole program:
// CHECK: a_gt_10
// CHECK: a0
Expand Down Expand Up @@ -79,6 +81,7 @@
// CHECK: requires clause ter0 proved for call call1
// CHECK: requires clause ter0 proved for call call2
// CHECK: requires clause xpos_abs proved for call call_cont
// CHECK: someInteger_value_axiom
// CHECK: spost
// CHECK: spre1
// CHECK: tee_not_1
Expand Down Expand Up @@ -202,3 +205,15 @@ procedure callContradictoryFunction(x: int) returns (r: int)
call {:id "call_cont"} r := contradictoryEnsuresClause(x); // requires and ensures covered
r := {:id "unreachable_assignment"} r - 1; // not covered
}

function someInteger(i: int) : int uses {
axiom {:id "someInteger_value_axiom"} (forall i: int :: someInteger(i) == 3);

axiom {:id "uselessAxiom"} (3 == 3);
}

procedure usesSomeInteger() returns (r: bool)
ensures r;
{
r := someInteger(7) == 3;
}
2 changes: 1 addition & 1 deletion Test/coverage/verificationCoverage.bpl.expect
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

Boogie program verifier finished with 10 verified, 0 errors
Boogie program verifier finished with 11 verified, 0 errors

0 comments on commit 475faa0

Please sign in to comment.