Skip to content

Commit 9dc8089

Browse files
authored
Merge pull request #469 from viperproject/meilers_unfold_none_2
Unfold, fold, and unfolding must have a strictly positive permission amount
2 parents 06755cf + 1a90800 commit 9dc8089

4 files changed

Lines changed: 32 additions & 13 deletions

File tree

src/main/scala/viper/carbon/modules/PermModule.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ trait PermModule extends Module with CarbonStateComponent {
4545

4646
def conservativeIsPositivePerm(e: sil.Exp): Boolean
4747

48+
/**
49+
* Returns an expression representing that a permission amount is positive.
50+
* Similar to [[permissionPositive]], but works directly on Viper expressions, *including* ones containing
51+
* wildcards, and performs more aggressive simplifications.
52+
*
53+
* @param e the permission amount to be checked
54+
* @return the expression representing the fact that the permission is positive
55+
*/
56+
def isStrictlyPositivePerm(e: sil.Exp): Exp
57+
4858
/**
4959
* The current mask.
5060
*/

src/main/scala/viper/carbon/modules/impls/DefaultFuncPredModule.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import viper.silver.verifier.{NullPartialVerificationError, PartialVerificationE
2020

2121
import scala.collection.mutable.ListBuffer
2222
import viper.silver.ast.utility.QuantifiedPermissions.QuantifiedPermissionAssertion
23+
import viper.silver.verifier.reasons.NonPositivePermission
2324

2425
import scala.collection.mutable
2526

@@ -927,7 +928,8 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
927928
, statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false): (Stmt,Stmt) = {
928929
duringFold = true
929930
foldInfo = acc
930-
val stmt = exhaleSingleWithoutDefinedness(Permissions.multiplyExpByPerm(acc.loc.predicateBody(verifier.program, env.allDefinedNames(program)).get,acc.perm), error, havocHeap = false,
931+
val stmt = Assert(permModule.isStrictlyPositivePerm(acc.perm), error.dueTo(NonPositivePermission(acc.perm))) ++
932+
exhaleSingleWithoutDefinedness(Permissions.multiplyExpByPerm(acc.loc.predicateBody(verifier.program, env.allDefinedNames(program)).get,acc.perm), error, havocHeap = false,
931933
statesStackForPackageStmt = statesStackForPackageStmt, insidePackageStmt = insidePackageStmt) ++
932934
inhale(Seq((acc, error)), addDefinednessChecks = false, statesStackForPackageStmt, insidePackageStmt)
933935
val stmtLast = Assume(predicateTrigger(heapModule.currentStateExps, acc.loc)) ++ {
@@ -965,7 +967,8 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
965967
duringUnfold = true
966968
duringUnfolding = isUnfolding
967969
unfoldInfo = acc
968-
val stmt = Assume(predicateTrigger(heapModule.currentStateExps, acc.loc)) ++
970+
val stmt = Assert(permModule.isStrictlyPositivePerm(acc.perm), error.dueTo(NonPositivePermission(acc.perm))) ++
971+
Assume(predicateTrigger(heapModule.currentStateExps, acc.loc)) ++
969972
{
970973
val location = acc.loc
971974
val predicate = verifier.program.findPredicate(location.predicateName)

src/main/scala/viper/carbon/modules/impls/QuantifiedPermModule.scala

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,26 +1601,30 @@ class QuantifiedPermModule(val verifier: Verifier)
16011601

16021602
override def conservativeIsPositivePerm(e: sil.Exp): Boolean = PermissionHelper.conservativeStaticIsStrictlyPositivePerm(e)
16031603

1604+
override def isStrictlyPositivePerm(e: sil.Exp): Exp = PermissionHelper.isStrictlyPositivePerm(e)
1605+
16041606
object PermissionHelper {
16051607

16061608
def isStrictlyPositivePerm(e: sil.Exp): Exp = {
16071609
require(e isSubtype sil.Perm, s"found ${e.typ} ($e), but required Perm")
1608-
val backup = permissionPositiveInternal(translatePerm(e), Some(e))
1610+
// Use backup lazily when needed only. This allows the function to work on WildcardPerms for which
1611+
// translatePerm would throw an exception.
1612+
val backup = () => permissionPositiveInternal(translatePerm(e), Some(e))
16091613
e match {
16101614
case sil.NoPerm() => FalseLit()
16111615
case sil.FullPerm() => TrueLit()
16121616
case sil.WildcardPerm() => TrueLit()
16131617
case sil.EpsilonPerm() => sys.error("epsilon permissions are not supported by this permission module")
16141618
case x: sil.LocalVar if isAbstractRead(x) => TrueLit()
1615-
case sil.CurrentPerm(loc) => backup
1619+
case sil.CurrentPerm(loc) => backup()
16161620
case sil.FractionalPerm(left, right) =>
16171621
val (l, r) = (translateExp(left), translateExp(right))
16181622
((l > IntLit(0)) && (r > IntLit(0))) || ((l < IntLit(0)) && (r < IntLit(0)))
16191623
case sil.PermMinus(a) =>
16201624
isStrictlyNegativePerm(a)
16211625
case sil.PermAdd(left, right) =>
1622-
(isStrictlyPositivePerm(left) && isStrictlyPositivePerm(right)) || backup
1623-
case sil.PermSub(left, right) => backup
1626+
(isStrictlyPositivePerm(left) && isStrictlyPositivePerm(right)) || backup()
1627+
case sil.PermSub(left, right) => backup()
16241628
case sil.PermMul(a, b) =>
16251629
(isStrictlyPositivePerm(a) && isStrictlyPositivePerm(b)) || (isStrictlyNegativePerm(a) && isStrictlyNegativePerm(b))
16261630
case sil.PermDiv(a, b) =>
@@ -1633,7 +1637,7 @@ class QuantifiedPermModule(val verifier: Verifier)
16331637
((n > IntLit(0)) && isStrictlyPositivePerm(b)) || ((n < IntLit(0)) && isStrictlyNegativePerm(b))
16341638
case sil.CondExp(cond, thn, els) =>
16351639
CondExp(translateExp(cond), isStrictlyPositivePerm(thn), isStrictlyPositivePerm(els))
1636-
case _ => backup
1640+
case _ => backup()
16371641
}
16381642
}
16391643

@@ -1705,22 +1709,24 @@ class QuantifiedPermModule(val verifier: Verifier)
17051709

17061710
def isStrictlyNegativePerm(e: sil.Exp): Exp = {
17071711
require(e isSubtype sil.Perm)
1708-
val backup = UnExp(Not,permissionPositiveInternal(translatePerm(e), Some(e), true))
1712+
// Use backup lazily when needed only. This allows the function to work on WildcardPerms for which
1713+
// translatePerm would throw an exception.
1714+
val backup = () => UnExp(Not,permissionPositiveInternal(translatePerm(e), Some(e), true))
17091715
e match {
17101716
case sil.NoPerm() => FalseLit() // strictly negative
17111717
case sil.FullPerm() => FalseLit()
17121718
case sil.WildcardPerm() => FalseLit()
17131719
case sil.EpsilonPerm() => sys.error("epsilon permissions are not supported by this permission module")
17141720
case x: sil.LocalVar if isAbstractRead(x) => FalseLit()
1715-
case sil.CurrentPerm(loc) => backup
1721+
case sil.CurrentPerm(loc) => backup()
17161722
case sil.FractionalPerm(left, right) =>
17171723
val (l, r) = (translateExp(left), translateExp(right))
17181724
((l < IntLit(0)) && (r > IntLit(0))) || ((l > IntLit(0)) && (r < IntLit(0)))
17191725
case sil.PermMinus(a) =>
17201726
isStrictlyPositivePerm(a)
17211727
case sil.PermAdd(left, right) =>
1722-
(isStrictlyNegativePerm(left) && isStrictlyNegativePerm(right)) || backup
1723-
case sil.PermSub(left, right) => backup
1728+
(isStrictlyNegativePerm(left) && isStrictlyNegativePerm(right)) || backup()
1729+
case sil.PermSub(left, right) => backup()
17241730
case sil.PermMul(a, b) =>
17251731
(isStrictlyPositivePerm(a) && isStrictlyNegativePerm(b)) || (isStrictlyNegativePerm(a) && isStrictlyPositivePerm(b))
17261732
case sil.PermDiv(a, b) =>
@@ -1733,7 +1739,7 @@ class QuantifiedPermModule(val verifier: Verifier)
17331739
((n > IntLit(0)) && isStrictlyNegativePerm(b)) || ((n < IntLit(0)) && isStrictlyPositivePerm(b))
17341740
case sil.CondExp(cond, thn, els) =>
17351741
CondExp(translateExp(cond), isStrictlyNegativePerm(thn), isStrictlyNegativePerm(els))
1736-
case _ => backup
1742+
case _ => backup()
17371743
}
17381744
}
17391745

0 commit comments

Comments
 (0)