├── bors.toml
├── docs
├── licenses
│ ├── JGraphT.txt
│ ├── SLF4J.txt
│ ├── Kiama.txt
│ ├── Log4j.txt
│ ├── SLF4S.txt
│ ├── ScalaTest.txt
│ ├── Scala.txt
│ └── Scallop.txt
├── logo_name.png
└── graal.md
├── src
├── test
│ ├── resources
│ │ ├── frontends
│ │ │ ├── vyper
│ │ │ │ ├── testsresourcesissuesissue006a.vy.vpr
│ │ │ │ ├── testsresourcesissuesissue020b.vy.vpr
│ │ │ │ ├── testsresourcesissuesissue020g.vy.vpr
│ │ │ │ ├── testsresourcesissuesissue022d.vy.vpr
│ │ │ │ ├── testsresourcesissuesissue028a.vy.vpr
│ │ │ │ └── testsresourcesissuesissue030a.vy.vpr
│ │ │ └── gobra
│ │ │ │ ├── forall-simple3.gobra.vpr
│ │ │ │ ├── trigger-simple3.gobra.vpr
│ │ │ │ ├── forall-simple1.gobra.vpr
│ │ │ │ └── global-const-4.gobra.vpr
│ │ ├── issue387
│ │ │ ├── va10.vpr
│ │ │ ├── va11.vpr
│ │ │ ├── va9.vpr
│ │ │ ├── va0.vpr
│ │ │ ├── va5.vpr
│ │ │ ├── va7.vpr
│ │ │ ├── va13.vpr
│ │ │ ├── va8.vpr
│ │ │ ├── va4.vpr
│ │ │ ├── va15.vpr
│ │ │ ├── va12.vpr
│ │ │ ├── va3.vpr
│ │ │ ├── va2.vpr
│ │ │ ├── va6.vpr
│ │ │ ├── va1.vpr
│ │ │ ├── jonas_viktor.vpr
│ │ │ └── va14.vpr
│ │ ├── misc
│ │ │ └── disableNL.vpr
│ │ ├── errorMessageTests
│ │ │ ├── misc
│ │ │ │ ├── simple.vpr
│ │ │ │ ├── 0348-1.vpr
│ │ │ │ └── 0348-2.vpr
│ │ │ ├── combinedRewrites
│ │ │ │ ├── involved.vpr
│ │ │ │ ├── simple.vpr
│ │ │ │ └── involved2.vpr
│ │ │ ├── assertionFolding
│ │ │ │ ├── simple.vpr
│ │ │ │ └── complex.vpr
│ │ │ ├── methodInlining
│ │ │ │ ├── simple.vpr
│ │ │ │ ├── withArgs.vpr
│ │ │ │ ├── withArgsNRes.vpr
│ │ │ │ └── withFields.vpr
│ │ │ └── whileToIfGoto
│ │ │ │ ├── simple.vpr
│ │ │ │ └── nested.vpr
│ │ ├── symbExLogTests
│ │ │ ├── symbLogTest_Unfolding.vpr.elog
│ │ │ ├── symbLogTest_issue259.vpr
│ │ │ ├── symbLogTest_Looping.vpr
│ │ │ ├── symbLogTest_minimal.vpr
│ │ │ ├── symbLogTest_Unfolding.vpr
│ │ │ ├── symbLogTest_basics.vpr.elog
│ │ │ ├── symbLogTest_issue259.vpr.elog
│ │ │ ├── symbLogTest_basics.vpr
│ │ │ ├── symbLogTest_MethodCall.vpr
│ │ │ ├── symbLogTest_Looping.vpr.elog
│ │ │ ├── symbLogTest_minimal.vpr.elog
│ │ │ ├── symbLogTest_MethodCall.vpr.elog
│ │ │ ├── symbLogTest_Branching.vpr
│ │ │ ├── symbLogTest_linkedListMinimal.vpr
│ │ │ ├── symbLogTest_Incompleteness.vpr
│ │ │ ├── symbLogTest_Incompleteness.vpr.elog
│ │ │ ├── symbLogTest_ImpureBranching.vpr
│ │ │ └── symbLogTest_linkedListMinimal.vpr.elog
│ │ ├── oldaxiomatization
│ │ │ ├── lesscomplete.vpr
│ │ │ ├── range_axiom_issue.vpr
│ │ │ ├── sets.vpr
│ │ │ └── example1.vpr
│ │ ├── counterexamples
│ │ │ ├── negative.vpr
│ │ │ ├── permissions.vpr
│ │ │ ├── cyclic-ref.vpr
│ │ │ ├── functions.vpr
│ │ │ ├── ref-sequence.vpr
│ │ │ ├── method-call.vpr
│ │ │ ├── sequence.vpr
│ │ │ ├── predicate.vpr
│ │ │ ├── simple-refs.vpr
│ │ │ ├── simple-refs-rec.vpr
│ │ │ └── lseg.vpr
│ │ ├── conditionalizePermissions
│ │ │ ├── welldef.vpr
│ │ │ ├── carbon_0179.vpr
│ │ │ ├── let.vpr
│ │ │ ├── silicon_0008.vpr
│ │ │ └── silicon_0713.vpr
│ │ ├── moreCompleteExhale
│ │ │ ├── 0822.vpr
│ │ │ ├── disjunctiveAliasing.vpr
│ │ │ ├── 0896.vpr
│ │ │ ├── 0523.vpr
│ │ │ └── 0604.vpr
│ │ ├── consistency
│ │ │ └── consistency.vpr
│ │ ├── conditionalRewriter
│ │ │ └── test1.vpr
│ │ └── snapshots
│ │ │ └── test_exp.vpr
│ └── scala
│ │ ├── ViperTutorialExamples.scala
│ │ ├── SiliconTestsSmokeDetection.scala
│ │ ├── SiliconTestsQuasihavoc.scala
│ │ ├── SiliconTestsParallelBranches.scala
│ │ ├── SiliconTestsSIFPlugin.scala
│ │ ├── SiliconTestsOldAxiomatization.scala
│ │ ├── SiliconTestsMoreCompleteExhale.scala
│ │ ├── SiliconTestsOldPermSemantics.scala
│ │ ├── SiliconTestsSimplifiedUnfold.scala
│ │ ├── SiliconTestsConditionalizePermissions.scala
│ │ ├── SiliconBackendTypeTest.scala
│ │ ├── SiliconTestsMoreJoins.scala
│ │ ├── AdtPluginTests.scala
│ │ ├── ConcurrentInstantiationTests.scala
│ │ ├── SiliconTests.scala
│ │ ├── TriggerGeneratorTests.scala
│ │ ├── SiliconCounterexampleVariablesTests.scala
│ │ └── tests.scala
└── main
│ ├── resources
│ ├── magic_wand_snap_functions_declarations.smt2
│ ├── cvc5config.smt2
│ ├── predicate_snap_functions_declarations.smt2
│ ├── field_value_functions_declarations.smt2
│ ├── predicate_snap_functions_axioms_no_triggers.smt2
│ ├── field_value_functions_axioms_no_triggers.smt2
│ ├── z3config.smt2
│ ├── logback.xml
│ ├── sortwrappers.smt2
│ ├── field_value_functions_axioms.smt2
│ ├── predicate_snap_functions_axioms.smt2
│ └── preamble.smt2
│ └── scala
│ ├── decider
│ ├── package.scala
│ └── SMTLib2PreambleReader.scala
│ ├── logger
│ ├── renderer
│ │ └── Renderer.scala
│ ├── records
│ │ ├── structural
│ │ │ ├── StructuralRecord.scala
│ │ │ ├── JoiningRecord.scala
│ │ │ └── BranchingRecord.scala
│ │ ├── scoping
│ │ │ ├── CloseScopeRecord.scala
│ │ │ ├── OpenScopeRecord.scala
│ │ │ └── ScopingRecord.scala
│ │ ├── SymbolicRecord.scala
│ │ ├── data
│ │ │ ├── MemberRecord.scala
│ │ │ ├── ConsumeRecord.scala
│ │ │ ├── EvaluateRecord.scala
│ │ │ ├── ExecuteRecord.scala
│ │ │ ├── ProduceRecord.scala
│ │ │ ├── ConditionalEdgeRecord.scala
│ │ │ ├── ImpliesRecord.scala
│ │ │ ├── MethodCallRecord.scala
│ │ │ ├── CondExpRecord.scala
│ │ │ ├── DeciderAssumeRecord.scala
│ │ │ ├── MethodRecord.scala
│ │ │ ├── DeciderAssertRecord.scala
│ │ │ ├── FunctionRecord.scala
│ │ │ ├── PredicateRecord.scala
│ │ │ ├── WellformednessCheckRecord.scala
│ │ │ ├── CommentRecord.scala
│ │ │ ├── ProverAssertRecord.scala
│ │ │ ├── SingleMergeRecord.scala
│ │ │ └── DataRecord.scala
│ │ └── RecordData.scala
│ └── LogConfig.scala
│ ├── resources
│ ├── Property.scala
│ └── Resources.scala
│ ├── interfaces
│ ├── decider
│ │ ├── TermConverter.scala
│ │ └── Prover.scala
│ ├── VerificationUnit.scala
│ ├── Preamble.scala
│ └── state
│ │ └── Chunks.scala
│ ├── state
│ ├── package.scala
│ ├── Heap.scala
│ ├── Store.scala
│ └── FunctionPreconditionTransformer.scala
│ ├── rules
│ ├── FunctionSupporter.scala
│ ├── ConsumptionResult.scala
│ ├── PermissionSupporter.scala
│ └── LetSupporter.scala
│ ├── extensions
│ ├── TryBlockParserPlugin.scala
│ └── TryBlockStmt.scala
│ ├── debugger
│ ├── DebugTypechecker.scala
│ └── DebugParser.scala
│ ├── supporters
│ ├── DefaultMapsContributor.scala
│ ├── DefaultMultisetsContributor.scala
│ ├── qps
│ │ └── PredicateSnapGenerator.scala
│ └── CfgSupporter.scala
│ ├── reporting
│ ├── MultiRunLineRecorder.scala
│ ├── Exceptions.scala
│ ├── MultiRunCountingRecorder.scala
│ └── package.scala
│ ├── package.scala
│ └── verifier
│ └── WorkerVerifier.scala
├── .gitmodules
├── utils
├── assembly
│ ├── silicon.sh
│ ├── assembly.bat
│ ├── package.bat
│ └── silicon.bat
├── scripts
│ ├── extract_runtime_sbt_test.txt
│ ├── sum.scala
│ └── tidy_smtlib.scala
├── autohotkey
│ └── silicon.ahk
└── patches
│ └── programmatically-change-logback-pattern.diff
├── .github
├── dependabot.yml
└── workflows
│ └── update-submodules.yml
├── project
├── build.properties
└── plugins.sbt
├── annotation
├── build.sbt
├── annotation.iml
└── README.md
├── common
└── src
│ └── main
│ └── scala
│ ├── package.scala
│ ├── collections
│ ├── package.scala
│ ├── immutable
│ │ ├── MultiMap.scala
│ │ └── package.scala
│ └── mutable
│ │ └── MultiMap.scala
│ ├── concurrency
│ └── package.scala
│ ├── config
│ └── package.scala
│ └── io
│ └── package.scala
├── silicon.sh
├── .gitignore
└── silicon.bat
/bors.toml:
--------------------------------------------------------------------------------
1 | status = ["test-and-assemble"]
2 |
--------------------------------------------------------------------------------
/docs/licenses/JGraphT.txt:
--------------------------------------------------------------------------------
1 | http://jgrapht.org/LGPL.html
--------------------------------------------------------------------------------
/docs/licenses/SLF4J.txt:
--------------------------------------------------------------------------------
1 | http://www.slf4j.org/license.html
--------------------------------------------------------------------------------
/docs/licenses/Kiama.txt:
--------------------------------------------------------------------------------
1 | http://www.gnu.org/licenses/lgpl.html
--------------------------------------------------------------------------------
/docs/licenses/Log4j.txt:
--------------------------------------------------------------------------------
1 | http://logging.apache.org/log4j/2.x/license.html
--------------------------------------------------------------------------------
/docs/licenses/SLF4S.txt:
--------------------------------------------------------------------------------
1 | http://www.apache.org/licenses/LICENSE-2.0.html
--------------------------------------------------------------------------------
/src/test/resources/frontends/vyper/testsresourcesissuesissue006a.vy.vpr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/vyper/testsresourcesissuesissue020b.vy.vpr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/vyper/testsresourcesissuesissue020g.vy.vpr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/vyper/testsresourcesissuesissue022d.vy.vpr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/vyper/testsresourcesissuesissue028a.vy.vpr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/vyper/testsresourcesissuesissue030a.vy.vpr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/licenses/ScalaTest.txt:
--------------------------------------------------------------------------------
1 | http://www.apache.org/licenses/LICENSE-2.0.html
--------------------------------------------------------------------------------
/docs/logo_name.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viperproject/silicon/HEAD/docs/logo_name.png
--------------------------------------------------------------------------------
/docs/licenses/Scala.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viperproject/silicon/HEAD/docs/licenses/Scala.txt
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "silver"]
2 | path = silver
3 | url = https://github.com/viperproject/silver.git
4 |
--------------------------------------------------------------------------------
/src/main/resources/magic_wand_snap_functions_declarations.smt2:
--------------------------------------------------------------------------------
1 | (declare-fun MWSF_apply ($MWSF $Snap) $Snap)
2 |
--------------------------------------------------------------------------------
/utils/assembly/silicon.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | java -Xss64m -cp silicon.jar viper.silicon.SiliconRunner $@
4 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va10.vpr:
--------------------------------------------------------------------------------
1 | field next: Ref
2 |
3 | method test02(t1: Ref, t2: Ref)
4 | requires acc(t1.next, wildcard)
5 | requires acc(t2.next)
6 | {
7 | assert t1 != t2
8 | }
9 |
--------------------------------------------------------------------------------
/utils/scripts/extract_runtime_sbt_test.txt:
--------------------------------------------------------------------------------
1 | $ perl -0ne 'print "$1, $2, $3\n" while(/\[info\] - (.*?) \[Silicon-Silver\]\n.*\n.*? (\d+\.?\d*) (sec \(verify\))/g)' times.txt | sort -n -t , -k 2 -r > times_sec.txt
--------------------------------------------------------------------------------
/src/test/resources/misc/disableNL.vpr:
--------------------------------------------------------------------------------
1 | method f(x: Int, y: Int) returns (res: Int)
2 | requires 0 <= x <= 10
3 | requires 0 <= y <= 10
4 | ensures 0 <= res <= 100 // this fails with --disableNL
5 | {
6 | res := x * y
7 | }
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/misc/simple.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var i:Bool
7 | assert(false && i)
8 | }
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/combinedRewrites/involved.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 |
7 | assert(true && (!true || !!false))
8 | }
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/combinedRewrites/simple.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | assert(true && false || false && true)
7 | }
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Unfolding.vpr.elog:
--------------------------------------------------------------------------------
1 | predicate tuple
2 |
3 | method setTuple
4 | execute unfold acc(tuple(this), write)
5 | execute this.left := l
6 | execute this.right := r
7 | execute fold acc(tuple(this), write)
8 |
9 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | updates:
4 | - package-ecosystem: github-actions
5 | directory: "/"
6 | schedule:
7 | interval: monthly
8 | day: monday
9 | groups:
10 | all:
11 | patterns:
12 | - "*"
13 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_issue259.vpr:
--------------------------------------------------------------------------------
1 | method foo(n:Int,b:Bool,c:Bool)
2 | {
3 | if ( b ) {
4 | assert true
5 | } else {
6 | assert true
7 | //:: ExpectedOutput(assert.failed:assertion.false)
8 | assert false
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/combinedRewrites/involved2.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | assert( !true || (!!true && false) || (false || false) )
7 | }
8 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Looping.vpr:
--------------------------------------------------------------------------------
1 | method outEdgeStateConsolidation(i: Int)
2 | {
3 | var j: Int
4 | var res: Int
5 | j := 1
6 | while(j < 2)
7 | {
8 | res := 1
9 | j := j + 1
10 | }
11 | res := 2
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va11.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 |
3 | function foo(x: Ref, y: Ref): Int
4 | requires acc(x.f) && acc(y.f)
5 | { x == y ? 1 : 0 }
6 |
7 | method test(x: Ref, y: Ref) {
8 | inhale acc(x.f) && acc(y.f)
9 | var v: Int := foo(x, y)
10 | assert v == 0
11 | }
12 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | #
5 | # Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | sbt.version=1.6.2
8 |
--------------------------------------------------------------------------------
/src/test/resources/oldaxiomatization/lesscomplete.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method test_seq_semiequal()
5 | {
6 | //:: ExpectedOutput(assert.failed:assertion.false)
7 | assert Seq(true, false) != Seq(true, true)
8 | }
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/assertionFolding/simple.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var i:Bool := false
7 | //assert(true && f(i))
8 | assert(1 + 1 == 2)
9 | assert(1 + 1 == 3)
10 | }
--------------------------------------------------------------------------------
/annotation/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val annotation = (project in file("."))
2 | .settings(
3 | // Enable macro expansion
4 | scalacOptions += "-Ymacro-annotations",
5 | libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.13.5",
6 | libraryDependencies += "org.scala-lang.modules" % "scala-xml_2.13" % "2.0.0-RC1"
7 | )
--------------------------------------------------------------------------------
/utils/assembly/assembly.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | SetLocal
3 |
4 | set THIS_DIR=%~dp0
5 | set BASE_DIR=%THIS_DIR%..\..\
6 |
7 | pushd %THIS_DIR%
8 |
9 | pushd %BASE_DIR%
10 | call sbt assembly
11 | popd
12 |
13 | copy %BASE_DIR%\target\scala-2.10\silicon.jar %THIS_DIR%\.
14 |
15 | call %THIS_DIR%\silicon.bat
16 |
17 | popd
18 | exit /B 0
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/methodInlining/simple.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var x:Int := 1
7 | foo(x)
8 | }
9 |
10 | method foo(y:Int)
11 | requires y + 2 < 1
12 | ensures true
13 | {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/gobra/forall-simple3.gobra.vpr:
--------------------------------------------------------------------------------
1 | function foo_pkg_F(n_pkg_V0: Int): Bool
2 | requires true
3 |
4 |
5 | method bar_pkg_F()
6 | requires (forall k_pkg_V1: Int :: { foo_pkg_F(k_pkg_V1) } foo_pkg_F(k_pkg_V1))
7 | {
8 |
9 | // decl
10 |
11 |
12 | // decl
13 |
14 |
15 | label returnLabel
16 | }
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/negative.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method fun(x:Int)
5 | requires x == 42
6 | {
7 | var y: Int := -x
8 | //:: ExpectedCounterexample(assert.failed:assertion.false, (x == 42, y == -42))
9 | assert(false)
10 | }
11 |
--------------------------------------------------------------------------------
/src/test/resources/conditionalizePermissions/welldef.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | function ok(): Bool
7 |
8 |
9 | function val(): Ref
10 | requires ok()
11 |
12 |
13 | method test()
14 | {
15 | inhale ok() ==> acc(val().f)
16 | }
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/whileToIfGoto/simple.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var i:Int := 1
7 |
8 | while(i < 5)
9 | invariant i < 5
10 | {
11 | i := i + 1
12 | }
13 |
14 | assert(i == 5)
15 | }
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_minimal.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 | field g: Int
3 |
4 | method topOfStackInIgnoredSepSetCheck(b: Bool, x: Ref)
5 | {
6 | inhale b ? acc(x.f) : true
7 | }
8 |
9 | predicate P4(b: Bool, x: Ref) {
10 | b ? acc(x.f) : true
11 | }
12 |
13 | method minimal4(b: Bool, x: Ref)
14 | {
15 | inhale acc(x.f)
16 | fold P4(b, x)
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va9.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 |
3 | method t10(r: Ref, o: Ref)
4 | requires acc(r.f) && acc(o.f)
5 | ensures acc(r.f) && acc(o.f)
6 | {
7 | r.f := 2
8 | o.f := 2
9 | assert o != r
10 | exhale acc(o.f)
11 | inhale acc(o.f)
12 | assert r.f == 2
13 | //:: ExpectedOutput(assert.failed:assertion.false)
14 | assert o.f == 2
15 | }
16 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.0.0")
8 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
--------------------------------------------------------------------------------
/src/main/scala/decider/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon
8 |
9 | package object decider {
10 | type Mark = Int
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/permissions.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | method foo(x: Ref, y: Ref)
7 | requires acc(x.f, 1/2) && acc(y.f, 1/2)
8 | {
9 | //:: ExpectedCounterexample(assignment.failed:insufficient.permission, (acc(x.f, 1/2)))
10 | x.f := y.f * 2 + 2
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va0.vpr:
--------------------------------------------------------------------------------
1 | //:: IgnoreFile(/silicon/issue/387/)
2 | // Note: this test can be included in a branch (work in progress), but the main version of Silicon doesn't currently handle it with default options.
3 | field f: Int
4 |
5 | method test(x: Ref, y: Ref, z: Ref) {
6 | inhale acc(x.f) && acc(y.f)
7 | inhale z == x || z == y
8 | assert acc(z.f)
9 | z.f := 123
10 | }
11 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va5.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 | field g: Int
3 | field h: Ref
4 |
5 | function fun0(x: Ref): Int
6 | requires acc(x.h) && acc(x.h.g)
7 | { x.h.g }
8 |
9 | predicate Q(x: Ref) {
10 | acc(x.f) && acc(x.h) && (x.h != null ==> acc(x.h.g))
11 | }
12 |
13 | function fun5(x: Ref): Int
14 | requires acc(Q(x))
15 | { unfolding acc(Q(x)) in x.f + (x.h == null ? 0 : x.h.g) }
16 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Unfolding.vpr:
--------------------------------------------------------------------------------
1 | field left: Int
2 | field right: Int
3 |
4 | predicate tuple(this: Ref) {
5 | acc(this.left) && acc(this.right)
6 | }
7 |
8 | method setTuple(this: Ref, l: Int, r: Int)
9 | requires tuple(this)
10 | ensures tuple(this)
11 | {
12 | unfold tuple(this)
13 | this.left := l
14 | this.right := r
15 | fold tuple(this)
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_basics.vpr.elog:
--------------------------------------------------------------------------------
1 | method m1
2 | execute var i: Int
3 | execute var j: Int
4 | execute var b: Bool
5 | execute i := 1
6 | execute i := 1 + 2
7 | execute i := 1 + 2 + 3
8 | execute j := i * 2 + 1
9 | execute b := 1 == 1
10 | execute b := i != j
11 | execute b := false && true
12 |
13 | method m2
14 | execute assert i + 1 == 2
15 |
16 |
--------------------------------------------------------------------------------
/src/test/resources/moreCompleteExhale/0822.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field val : Int
5 |
6 | method test(x: Ref, y: Ref) {
7 | inhale acc(x.val) && acc(y.val, x != y ? write : none)
8 | x.val := 4
9 | y.val := 3
10 | //:: ExpectedOutput(assert.failed:assertion.false)
11 | assert x.val == 4
12 | }
--------------------------------------------------------------------------------
/src/test/resources/issue387/va7.vpr:
--------------------------------------------------------------------------------
1 | field next: Ref
2 |
3 | predicate valid(this: Ref) {
4 | acc(this.next, write)
5 | && (this.next != null ==> acc(valid(this.next), write))
6 | }
7 |
8 | function size(this: Ref): Int
9 | requires this != null
10 | requires acc(valid(this), write)
11 | ensures result >= 1
12 | { unfolding acc(valid(this), write) in (this.next == null ? 1 : 1 + size(this.next)) }
13 |
--------------------------------------------------------------------------------
/src/test/resources/oldaxiomatization/range_axiom_issue.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method refSeq()
5 | {
6 | var tmp: Seq[Ref]
7 | // make sure we don't get errors if we use only seq types other than int
8 | // (since there are special range axioms only for int seqs that can lead to errors if int seqs are not defined)
9 | }
--------------------------------------------------------------------------------
/src/test/resources/issue387/va13.vpr:
--------------------------------------------------------------------------------
1 | field discriminant: Int
2 | field next: Ref
3 |
4 | function contains(x: Ref): Bool
5 | requires acc(BoxList(x))
6 | {
7 | (unfolding acc(BoxList(x)) in x.discriminant == 0) &&
8 | (unfolding acc(BoxList(x)) in contains(x.next))
9 | }
10 |
11 | predicate BoxList(self: Ref) {
12 | acc(self.discriminant) &&
13 | acc(self.next) &&
14 | acc(BoxList(self.next))
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/methodInlining/withArgs.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var a: Int := 2
7 | foo(a, 5)
8 | }
9 |
10 | method foo(x: Int, y: Int)
11 | requires true
12 | requires x <= 2
13 | requires x + y < y + x + 1
14 | ensures true
15 | ensures 2 == 1
16 | {
17 |
18 | }
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/cyclic-ref.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field next: Ref
5 |
6 | method foo(a: Ref, b: Ref)
7 | requires acc(a.next) && acc(b.next)
8 | {
9 | a.next := b
10 | b.next := a
11 | //:: ExpectedCounterexample(assert.failed:assertion.false, (a.next.next == a, b == b.next.next))
12 | assert(false)
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/functions.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | function foo(z: Int): Int
5 | {
6 | 42
7 | }
8 |
9 | method bar()
10 | requires foo(3) == 42
11 | {
12 | var x: Int := 5
13 | var y: Int := foo(x)
14 | //:: ExpectedCounterexample(assert.failed:assertion.false, (x == 5, y == 42))
15 | assert(false)
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/ref-sequence.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field seq: Seq[Int]
5 |
6 | method foo(x: Ref) returns (value: Int)
7 | requires acc(x.seq) && |x.seq| > 1
8 | //:: ExpectedCounterexample(postcondition.violated:assertion.false, (x.seq[1] == 42))
9 | ensures value != 42
10 | {
11 | value := x.seq[1]
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/assertionFolding/complex.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | define m2 {
5 | assert(i - (5 + 3) > 8 )
6 | }
7 |
8 | define m1 {
9 | assert(11 - i > 0)
10 | m2
11 | }
12 |
13 | method main()
14 | {
15 | var i:Int := 10
16 | //assert(true && f(i))
17 | assert(1 + 1 == 2)
18 | m1
19 |
20 | }
--------------------------------------------------------------------------------
/common/src/main/scala/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon
8 |
9 | package object common {
10 | trait Mergeable[S <: Mergeable[S]] {
11 | def merge(other: S): S
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/scala/logger/renderer/Renderer.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.renderer
8 |
9 | trait Renderer[S, T] {
10 | def renderMember(s: S): T
11 |
12 | def render(memberList: Iterable[S]): T
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_issue259.vpr.elog:
--------------------------------------------------------------------------------
1 | method foo
2 | Branch 1:
3 | comment: Reachable
4 | Branch b@4@01:
5 | comment: Reachable
6 | execute assert true
7 | Branch !(b@4@01):
8 | comment: Reachable
9 | Branch 2:
10 | comment: Reachable
11 | Branch !(b@4@01):
12 | comment: Reachable
13 | execute assert true
14 | execute assert false
15 | Branch b@4@01:
16 | comment: Unreachable
17 |
18 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_basics.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method m1()
5 | {
6 | var i: Int
7 | var j: Int
8 | var b: Bool
9 | i := 1
10 | i := 1 + 2
11 | i := 1 + 2 + 3
12 | j := (i * 2) + 1
13 |
14 | b := (1 == 1)
15 | b := (i != j)
16 | b := false && true
17 | }
18 |
19 | method m2(i: Int)
20 | requires i == 1
21 | {
22 | assert(i+1 == 2)
23 | }
--------------------------------------------------------------------------------
/annotation/annotation.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/structural/StructuralRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.structural
8 |
9 | import viper.silicon.logger.records.SymbolicRecord
10 |
11 | trait StructuralRecord extends SymbolicRecord
12 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/whileToIfGoto/nested.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var i:Int := 1
7 | var j:Bool := true
8 |
9 | while(i < 5)
10 | invariant i <= 5
11 | {
12 | while(j)
13 | invariant i <= 5
14 | {
15 | j := false
16 | }
17 | i := i + 1
18 | }
19 |
20 | assert(i == 5)
21 | }
--------------------------------------------------------------------------------
/src/test/resources/issue387/va8.vpr:
--------------------------------------------------------------------------------
1 | field value: Int
2 | field next: Ref
3 | field f: Int
4 |
5 | function itemat(node: Ref, i: Int): Int
6 | requires acc(valid(node), wildcard) && i >= 0
7 | {
8 | unfolding acc(valid(node), wildcard) in ((i == 0 || node.next == null) ? node.value : itemat(node.next, i-1))
9 | }
10 |
11 | predicate valid(this: Ref) {
12 | acc(this.next, write) &&
13 | acc(this.value, write) &&
14 | ((this.next != null) ==> acc(valid(this.next), write))
15 | }
16 |
--------------------------------------------------------------------------------
/silicon.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # To verify a Silver file 'test.sil', run './silicon.sh test.sil'.
4 |
5 | set -e
6 |
7 | BASEDIR="$(realpath "$(dirname "$0")")"
8 |
9 | CP_FILE="$BASEDIR/silicon_classpath.txt"
10 |
11 | if [ ! -f "$CP_FILE" ]; then
12 | (cd "$BASEDIR"; sbt "export runtime:dependencyClasspath" | tail -n1 > "$CP_FILE")
13 | fi
14 |
15 | exec java -Xss30M -Dlogback.configurationFile="$BASEDIR/src/main/resources/logback.xml" -cp "$(cat "$CP_FILE")" viper.silicon.SiliconRunner "$@"
16 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/method-call.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | method client(a: Ref)
7 | requires acc(a.f)
8 | {
9 | //:: ExpectedCounterexample(call.precondition:assertion.false, (a.f == 5))
10 | set(a, 5)
11 | a.f := 6
12 | }
13 |
14 | method set(x: Ref, i: Int)
15 | requires acc(x.f) && x.f != i
16 | ensures acc(x.f) && x.f == i
17 | {
18 | x.f := i
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .idea_modules
3 | common/target
4 | project/project
5 | project/target
6 | target
7 | .settings/
8 | .cache
9 | .scala_dependencies
10 | .history
11 | stats/
12 | bin/**
13 | tmp_*
14 | tmp/
15 | utils/assembly/silicon.jar
16 | utils/scripts/z3_tidy.jar
17 | utils/tidy_smtlib/tidy_smtlib.jar
18 | utils/scripts/tidy_smtlib.jar
19 | silicon_classpath.txt
20 | lib/
21 | src/test/resources/symbExLogTests/*.alog
22 | .DS_Store
23 | viper_tutorial_examples
24 | .bsp/
25 | .bloop/
26 | .metals/
27 |
--------------------------------------------------------------------------------
/src/test/resources/moreCompleteExhale/disjunctiveAliasing.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | function fn(x: Ref, y: Ref, z: Ref): Int
7 | requires acc(x.f) && acc(y.f)
8 | requires (z == x) || (z == y)
9 | {
10 | z.f
11 | }
12 |
13 | method m(x: Ref, y: Ref, z: Ref)
14 | requires acc(x.f) && acc(y.f)
15 | requires (z == x) || (z == y)
16 | {
17 | var tmp: Int
18 | tmp := z.f
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/misc/0348-1.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | /* See ErrorMessageTransformationTests.scala */
5 |
6 | function foo(x: Ref): Int
7 |
8 | function bar(i: Int): Bool
9 | requires 0 < i
10 |
11 | method test(x: Ref) {
12 | // assume bar(foo(x)) ~~> assert bar's precondition
13 | var i: Int
14 | i := foo(x)
15 | exhale 0 < i // ~~> goal: report error "0 < foo(x)" might not hold
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va4.vpr:
--------------------------------------------------------------------------------
1 | field discriminant: Int
2 |
3 | predicate Option(self: Ref) {
4 | acc(self.discriminant, write)
5 | }
6 |
7 | function Option$discriminant(self: Ref): Int
8 | requires acc(Option(self), 1/2)
9 | {
10 | (unfolding acc(Option(self), 1/2) in self.discriminant)
11 | }
12 |
13 | method test() {
14 | var _3: Ref
15 | inhale acc(Option(_3), write)
16 | inhale Option$discriminant(_3) == 1
17 | unfold acc(Option(_3), write)
18 | assert _3.discriminant == 1
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/resources/conditionalizePermissions/carbon_0179.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | predicate P1(r$: Ref)
5 |
6 | predicate P3(r$: Ref)
7 |
8 | method test2()
9 | {
10 | var b: Ref
11 | var k: Perm
12 |
13 | inhale acc(P1(b))
14 | inhale acc(P3(b))
15 |
16 | exhale perm(P3(b)) >= write ? acc(P3(b)) : (perm(P1(b)) > none ? acc(P1(b), write - perm(P3(b))) : true)
17 |
18 | assert perm(P1(b)) == write
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/scala/ViperTutorialExamples.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | import org.scalatest.DoNotDiscover
10 |
11 | @DoNotDiscover
12 | class ViperTutorialExamples extends SiliconTests {
13 | override val testDirectories = Seq("viper_tutorial_examples")
14 | }
15 |
--------------------------------------------------------------------------------
/src/test/resources/conditionalizePermissions/let.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | function ok(): Bool
7 |
8 |
9 | function val(): Ref
10 | requires ok()
11 |
12 | method test()
13 | {
14 | // Test that the condition is not pushed inside the let expression to get e.g.
15 | // inhale let x == (val()) in acc(x.f, ok() ? write : none)
16 | // which would not be well-defined.
17 | inhale ok() ==> let x == (val()) in acc(x.f)
18 | }
--------------------------------------------------------------------------------
/src/test/resources/issue387/va15.vpr:
--------------------------------------------------------------------------------
1 | field discriminant: Int
2 |
3 | field next: Ref
4 |
5 | function contains(_pure_1: Ref): Bool
6 | requires acc(BoxList(_pure_1), read$())
7 | {
8 | !(unfolding acc(BoxList(_pure_1), read$()) in _pure_1.discriminant == 0) &&
9 | (unfolding acc(BoxList(_pure_1), read$()) in contains(_pure_1.next))
10 | }
11 |
12 | predicate BoxList(self: Ref) {
13 | acc(self.discriminant) && acc(self.next) && acc(BoxList(self.next))
14 | }
15 |
16 | function read$(): Perm
17 | ensures none < result
18 | ensures result < write
19 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va12.vpr:
--------------------------------------------------------------------------------
1 | field Cell_x: Int
2 |
3 | function Cell_get(this: Ref): Int
4 | requires acc(this.Cell_x, write)
5 | { this.Cell_x }
6 |
7 | method forallCellGet10(c: Ref) returns (d: Ref)
8 | requires c != null
9 | requires acc(c.Cell_x, write)
10 | requires forall i1: Int :: (0 <= i1 && i1 < Cell_get(c)) ==> (Cell_get(c) > i1)
11 | ensures acc(c.Cell_x, write)
12 | ensures forall i2: Int :: (0 <= i2 && i2 < Cell_get(c)) ==> (Cell_get(c) > i2)
13 | // ensures forall i3: Int :: (0 <= i3 && i3 < Cell_get(c)) ==> (Cell_get(c) != i3)
14 | {}
15 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_MethodCall.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method twice(i: Int) returns (r: Int)
5 | requires i >= 0
6 | ensures r == 2*i
7 | {
8 | r := 2 * i
9 | }
10 |
11 | method m1(arg: Int)
12 | {
13 | var a: Int
14 | a := 1
15 | a := twice(1+1)
16 | a := 2
17 | }
18 |
19 | method m2(b: Bool)
20 | {
21 | var a: Int
22 | if(b) {
23 | a := twice(2)
24 | }
25 | else {
26 | a := twice(3)
27 | }
28 | a := twice(4)
29 | }
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsSmokeDetection.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsSmokeDetection extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("smoke")
11 |
12 | override val commandLineArguments: Seq[String] = Seq("--enableSmokeDetection")
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Looping.vpr.elog:
--------------------------------------------------------------------------------
1 | method outEdgeStateConsolidation
2 | execute var j: Int
3 | execute var res: Int
4 | execute j := 1
5 | Branch 1:
6 | comment: Reachable
7 | Branch j@5@01 < 2:
8 | comment: Reachable
9 | execute res := 1
10 | execute j := j + 1
11 | Branch !(j@5@01 < 2):
12 | comment: Reachable
13 | Branch 2:
14 | comment: Reachable
15 | Branch !(j@5@01 < 2):
16 | comment: Reachable
17 | execute res := 2
18 | Branch j@5@01 < 2:
19 | comment: Reachable
20 |
21 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/methodInlining/withArgsNRes.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method main()
5 | {
6 | var a: Int := 2
7 | var res1: Int
8 | var res2: Int
9 | res1, res2 := foo(a, 5)
10 |
11 | assert(res2 == a)
12 | assert(res1 == res2 + 5)
13 | }
14 |
15 | method foo(x: Int, y: Int) returns (r1: Int, r2: Int)
16 | requires x >= 0 && y >= 0
17 | ensures r2 == x
18 | ensures r1 == r2 + y - 1
19 | {
20 | r2 := x
21 | r1 := r2 + y
22 | }
--------------------------------------------------------------------------------
/src/test/resources/frontends/gobra/trigger-simple3.gobra.vpr:
--------------------------------------------------------------------------------
1 | function foo_pkg_F(n_pkg_V0: Int): Bool
2 | requires true
3 |
4 |
5 | function bar_pkg_F(n_pkg_V1: Int): Bool
6 | requires true
7 |
8 |
9 | method example_pkg_F()
10 | requires (forall i_pkg_V2: Int :: { foo_pkg_F(i_pkg_V2) } { bar_pkg_F(i_pkg_V2) } 0 < i_pkg_V2 ==> 0 <= i_pkg_V2)
11 | requires (exists i_pkg_V3: Int :: { foo_pkg_F(i_pkg_V3) } { bar_pkg_F(i_pkg_V3) } (0 < i_pkg_V3 ? 0 <= i_pkg_V3 : true))
12 | {
13 |
14 | // decl
15 |
16 |
17 | // decl
18 |
19 |
20 | label returnLabel
21 | }
--------------------------------------------------------------------------------
/src/main/scala/resources/Property.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.resources
8 |
9 | case class Property(expression: PropertyExpression[kinds.Boolean], name: String, description: String) {
10 | require(!name.contains(" "), "Property names may not contain whitespace characters.")
11 |
12 | override def toString = name
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/scoping/CloseScopeRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.scoping
8 |
9 | class CloseScopeRecord(val refId: Int) extends ScopingRecord {
10 |
11 | override val toTypeString: String = "close"
12 |
13 | override lazy val toSimpleString: String = {
14 | refId.toString
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_minimal.vpr.elog:
--------------------------------------------------------------------------------
1 | predicate P4
2 | Branch b@1@00:
3 | comment: Reachable
4 | Branch !(b@1@00):
5 | comment: Reachable
6 |
7 | method topOfStackInIgnoredSepSetCheck
8 | execute inhale (b ? acc(x.f, write) : true)
9 | Branch b@2@01:
10 | comment: Reachable
11 | Branch !(b@2@01):
12 | comment: Reachable
13 |
14 | method minimal4
15 | execute inhale acc(x.f, write)
16 | execute fold acc(P4(b, x), write)
17 | Branch b@8@01:
18 | comment: Reachable
19 | Branch !(b@8@01):
20 | comment: Reachable
21 |
22 |
--------------------------------------------------------------------------------
/utils/assembly/package.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | SetLocal
3 |
4 | set THIS_DIR=%~dp0
5 | set BASE_DIR=%THIS_DIR%\..\..
6 | set SIL_DIR=%BASE_DIR%\..\sil
7 | set ZIP_EXE=zip
8 |
9 | pushd %THIS_DIR%
10 |
11 | call assembly.bat
12 |
13 | mkdir examples
14 |
15 | xcopy /S %SIL_DIR%\src\test\resources\all examples
16 | xcopy /S /I %SIL_DIR%\src\test\resources\quantifiedpermissions examples\quantifiedpermissions
17 |
18 | REM http://www.info-zip.org/Zip.html
19 | zip -r silicon.zip silicon.jar silicon.bat silicon.sh examples
20 |
21 | del silicon.jar
22 | rmdir /S /Q examples
23 |
24 | popd
25 | exit /B 0
--------------------------------------------------------------------------------
/src/main/scala/interfaces/decider/TermConverter.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.interfaces.decider
8 |
9 | import viper.silicon.state.terms.{Term, Sort, Decl}
10 |
11 | trait TermConverter[T, S, D] {
12 | def convert(term: Term): T
13 | def convert(sort: Sort): S
14 | def convertSanitized(s: Sort): S
15 | def convert(decl: Decl): D
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/methodInlining/withFields.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f:Int
5 |
6 | method main()
7 | {
8 | var a: Ref
9 | var res: Int
10 | a := new(f)
11 | a.f := 5
12 | exhale(acc(a.f, wildcard))
13 | res := foo(a, 4)
14 |
15 | assert(a.f == res)
16 | }
17 |
18 | method foo(x: Ref, y: Int) returns (r1: Int)
19 | requires acc(x.f) && x.f == 5
20 | ensures r1 == y
21 | ensures acc(x.f, wildcard) && x.f == r1
22 | {
23 | r1 := y
24 | x.f := r1
25 | }
--------------------------------------------------------------------------------
/src/test/resources/oldaxiomatization/sets.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 |
5 | method t1(x: Int, xs: Set[Int]) {
6 | var n: Set[Int] := Set[Int]()
7 | assert |n| == 0
8 | assert n != Set(x)
9 | assert |Set(1)| == 1
10 | }
11 |
12 | method t2() {
13 | assert 1 in Set(1,2,3)
14 | var a: Set[Int] := Set(1)
15 | var b: Set[Int] := Set(2)
16 | assert (a union b) == Set(1,2)
17 | assert ((Set(1)) union (Set(1))) == Set(1)
18 |
19 | assert 1 in ((Set(1,2)) intersection (Set(100,1)))
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsQuasihavoc.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsQuasihavoc extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("quasihavoc")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--enableMoreCompleteExhale")
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/scala/interfaces/VerificationUnit.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.interfaces
8 |
9 | import viper.silicon.state.State
10 | import viper.silver.components.StatefulComponent
11 |
12 | trait VerificationUnit[U/* <: viper.silver.ast.Node*/] extends StatefulComponent {
13 | def units: Seq[U]
14 | def verify(s: State, unit: U): Seq[VerificationResult]
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsParallelBranches.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsParallelBranches extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("examples")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--parallelizeBranches")
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsSIFPlugin.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2025 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsSIFPlugin extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("sif")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--plugin=viper.silver.plugin.sif.SIFPlugin")
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsOldAxiomatization.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2025 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsOldAxiomatization extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("oldaxiomatization")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--useOldAxiomatization")
15 | }
16 |
--------------------------------------------------------------------------------
/utils/assembly/silicon.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | SetLocal EnableDelayedExpansion
3 |
4 | REM ======== Basic configuration ========
5 |
6 | set BASE_DIR=%~dp0
7 | set FWD_ARGS=%*
8 | set MAIN=viper.silicon.SiliconRunner
9 |
10 | REM ======== Path-dependent configuration ========
11 |
12 | set JAVA_EXE=java
13 | set CP=%BASE_DIR%\silicon.jar
14 |
15 | REM ======== Java ========
16 |
17 | set JVM_OPTS=-Xss64m
18 | set MAIN_OPTS=
19 | set CMD=%JAVA_EXE% %JVM_OPTS% -cp "%CP%" %MAIN% %MAIN_OPTS% %FWD_ARGS%
20 |
21 | REM ======== Executing ========
22 |
23 | REM echo.
24 | REM echo %CMD%
25 | REM echo.
26 |
27 | call %CMD%
28 |
29 | exit /B 0
--------------------------------------------------------------------------------
/src/test/resources/moreCompleteExhale/0896.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | predicate P(x: Ref) {
7 | acc(x.f)
8 | }
9 |
10 | method foo(x: Ref, y: Ref)
11 | {
12 | inhale acc(x.f) && x.f == 4 && acc(y.f) && y.f == 5
13 | fold P(x)
14 | fold P(y)
15 |
16 | var myseq: Seq[Ref] := Seq(x, y)
17 |
18 | assert forall r: Ref :: {r in myseq} r in myseq ==> unfolding P(r) in r.f > 2
19 |
20 | assert x in myseq
21 | assert y in myseq
22 |
23 | //:: ExpectedOutput(assert.failed:assertion.false)
24 | assert false
25 | }
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsMoreCompleteExhale.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsMoreCompleteExhale extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("moreCompleteExhale", "issue387")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--exhaleMode=1")
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsOldPermSemantics.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2025 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsOldPermSemantics extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("oldpermsemantics")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--respectFunctionPrePermAmounts")
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsSimplifiedUnfold.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2025 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsSimplifiedUnfold extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("all/predicates")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--enableSimplifiedUnfolds"
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsConditionalizePermissions.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | class SiliconTestsConditionalizePermissions extends SiliconTests {
10 | override val testDirectories: Seq[String] = Seq("conditionalizePermissions")
11 |
12 | override val commandLineArguments: Seq[String] = Seq(
13 | "--timeout", "300" /* seconds */,
14 | "--conditionalizePermissions")
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/sequence.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method update(values: Seq[Int]) returns (updatedValues: Seq[Int])
5 | requires |values| > 3
6 | ensures |values| == |updatedValues|
7 | ensures updatedValues[0] != updatedValues[1]
8 | //:: ExpectedCounterexample(postcondition.violated:assertion.false, (updatedValues[1] == 42, updatedValues[2] == 42))
9 | ensures updatedValues[1] != updatedValues[2]
10 | {
11 | updatedValues := values[0 := 0]
12 | updatedValues := updatedValues[1 := 42]
13 | updatedValues := updatedValues[2 := 42]
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/scoping/OpenScopeRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.scoping
8 |
9 | import viper.silicon.logger.records.data.DataRecord
10 |
11 | class OpenScopeRecord(ref: DataRecord) extends ScopingRecord {
12 | val refId: Int = ref.id
13 |
14 | override val toTypeString: String = "open"
15 |
16 | override lazy val toSimpleString: String = {
17 | refId.toString
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/predicate.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field x: Int
5 | field y: Int
6 |
7 | predicate StructA(this: Ref) {
8 | acc(this.x) && acc(this.y)
9 | }
10 |
11 | predicate StructB(this: Ref) {
12 | acc(this.x) && acc(this.y)
13 | }
14 |
15 | method foo(a: Ref, b: Ref)
16 | requires StructA(a)
17 | requires StructB(b)
18 | //:: ExpectedCounterexample(postcondition.violated:assertion.false, (a.x == 3))
19 | ensures acc(a.x) && a.x == 42
20 | {
21 | unfold StructA(a)
22 | unfold StructB(b)
23 | a.x := 3
24 | a.y := 4
25 | b.x := 5
26 | b.y := 6
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_MethodCall.vpr.elog:
--------------------------------------------------------------------------------
1 | method twice
2 | execute r := 2 * i
3 |
4 | method m1
5 | execute var a: Int
6 | execute a := 1
7 | execute a := twice(1 + 1)
8 | execute a := 2
9 |
10 | method m2
11 | execute var a: Int
12 | Branch 1:
13 | comment: Reachable
14 | Branch b@13@01:
15 | comment: Reachable
16 | execute a := twice(2)
17 | execute a := twice(4)
18 | Branch !(b@13@01):
19 | comment: Reachable
20 | Branch 2:
21 | comment: Reachable
22 | Branch !(b@13@01):
23 | comment: Reachable
24 | execute a := twice(3)
25 | execute a := twice(4)
26 | Branch b@13@01:
27 | comment: Reachable
28 |
29 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/simple-refs.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field left: Int
5 | field right: Int
6 |
7 | method simple(x: Ref, y: Ref) returns (n:Int)
8 | requires acc(x.left) && acc(x.right)
9 | requires acc(y.left) && acc(y.right)
10 | requires y.left == 3 && y.right == 4
11 | requires x.left == 42 && x.right > 52
12 | ensures acc(x.left) && acc(x.right)
13 | ensures acc(y.left) && acc(y.right)
14 | //:: ExpectedCounterexample(postcondition.violated:assertion.false, (x.left == 84))
15 | ensures x.left == 42
16 | {
17 | n := x.left
18 | label ret
19 | x.left := x.left * 2
20 | x.right := 201
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/resources/errorMessageTests/misc/0348-2.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | /* See ErrorMessageTransformationTests.scala */
5 |
6 | field f: Int
7 |
8 | predicate P(x: Ref) { acc(x.f) }
9 |
10 | function inner(x: Ref): Int
11 | requires P(x)
12 |
13 | function outer(x: Ref, v: Int): Bool
14 | requires P(x)
15 | requires unfolding P(x) in v == 0
16 |
17 | method test(y: Ref) {
18 | inhale P(y)
19 | // assume outer(x, inner(x)) ~~> assert outer's precondition
20 | var x: Ref
21 | x := y
22 | var v: Int
23 | v := inner(y)
24 | exhale unfolding P(x) in v == 0 // ~~> goal: report error "inner(y) == 0" might not hold
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/resources/conditionalizePermissions/silicon_0008.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 |
5 | field f: Int
6 |
7 | method deAlias(x: Ref, y: Ref, k: Perm)
8 | requires k >= none
9 | requires acc(x.f, k) && acc(y.f, k)
10 | // The following postcondition should fail in default greedy Silicon because --conditionalizePermissions creates a
11 | // situation where the two chunks may or may not alias in the same branch, so they cannot definitively be merged,
12 | // so greedy Silicon cannot prove the postcondition using any individual chunk.
13 | //:: ExpectedOutput(postcondition.violated:insufficient.permission)
14 | ensures x == y ==> acc(x.f, 2 * k)
15 | {}
--------------------------------------------------------------------------------
/src/test/resources/issue387/va3.vpr:
--------------------------------------------------------------------------------
1 | /* An excerpt from test file quantifiedpermissions/misc/functions.sil that at some point failed
2 | * while working on a fix for Silicon issue #387.
3 | */
4 |
5 | field f: Int
6 | field ss: Seq[Ref]
7 |
8 | predicate P01(x: Ref, n: Int) {
9 | acc(x.ss)
10 | && |x.ss| == n
11 | && 3 <= n
12 | && (forall i: Int, j: Int :: i >= 0 && i < |x.ss| && j >= 0 && j < |x.ss| && i != j ==> x.ss[i] != x.ss[j])
13 | && (forall j: Int :: 0 <= j && j < 3 ==> acc(x.ss[j].f))
14 | && (forall j: Int :: 3 <= j && j < n ==> acc(x.ss[j].f))
15 | }
16 |
17 | function fun04(x: Ref, n: Int, i: Int): Int
18 | requires acc(P01(x, n))
19 | requires 0 < i && i < n
20 | {
21 | unfolding acc(P01(x, n)) in x.ss[i].f
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconBackendTypeTest.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2021 ETH Zurich.
6 |
7 | import viper.silicon.Silicon
8 | import viper.silver.reporter.NoopReporter
9 | import viper.silver.testing.BackendTypeTest
10 | import viper.silver.verifier.Verifier
11 |
12 | class SiliconBackendTypeTest extends BackendTypeTest {
13 | override val verifier: Verifier = {
14 | val reporter = NoopReporter
15 | val debugInfo = ("startedBy" -> "viper.silicon.SiliconSMTTypeTest") :: Nil
16 | new Silicon(reporter, debugInfo)
17 | }
18 | }
--------------------------------------------------------------------------------
/utils/autohotkey/silicon.ahk:
--------------------------------------------------------------------------------
1 | ; Make sure that this file is UTF-8 encoded with a BOM!
2 | ; AutoHotkey won't correctly recognise it otherwise.
3 |
4 | ; Control key Ctrl- ^
5 | ; Alt key Alt- !
6 | ; Shift key Shift- +
7 | ; Windows key Win- #
8 |
9 | SetKeyDelay -1 0
10 |
11 | ; Lambda l
12 | ^#l::send λ
13 |
14 | ; Gamma G,g
15 | #+g::send Γ
16 | #g::send γ
17 |
18 | ; Pi P, p
19 | #+p::send Π
20 | #p::send π
21 |
22 | ; Sigma S, s
23 | #+s::send Σ
24 | #s::send σ
25 |
26 | ; Phi p
27 | #f::send f
28 |
29 | ; not equal, equal
30 | #=::send ≠
31 | +#=::send ≡
32 |
33 | ; empty set (actually a stroken-through letter O)
34 | #0::Send Ø
35 |
36 | ; Tau t, Turnstyle / Right tack, Negation thereof
37 | ; #t::send τ
38 | ; ^#t::send ⊢
39 | ; ^#+t::Send ⊬
--------------------------------------------------------------------------------
/src/main/scala/logger/records/SymbolicRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records
8 |
9 | import viper.silicon.logger.LogConfig
10 |
11 | import scala.annotation.unused
12 |
13 | trait SymbolicRecord {
14 | var id: Int = -1
15 |
16 | override def toString: String = {
17 | s"$toTypeString $toSimpleString"
18 | }
19 |
20 | def toTypeString: String
21 |
22 | def toSimpleString: String
23 |
24 | def getData(@unused config: LogConfig): RecordData = {
25 | new RecordData()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/annotation/README.md:
--------------------------------------------------------------------------------
1 | # Flyweight ASTs
2 |
3 | This directory contains the macro code to generate flyweight terms.
4 |
5 | Flyweight ASTs are not used in the master branch as it did not increase performance as expected and thus is of no practical use. However the macro implementation may be used for different purposes in the future.
6 |
7 | The file `Terms.example.scala` in this directory shows how the flyweight annotation can be used in practice.
8 |
9 | If ever needed again, the `annotation` subproject needs to be included in Silicon's `build.sbt` again:
10 |
11 | ```
12 | lazy val annotation = project in file("annotation")
13 | // ...
14 |
15 | // Silicon specific project settings
16 | lazy val silicon = (project in file("."))
17 | .dependsOn(annotation)
18 | // ...
19 | ```
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/MemberRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.logger.LogConfig
10 | import viper.silicon.logger.records.RecordData
11 | import viper.silicon.state.terms.Term
12 |
13 | trait MemberRecord extends DataRecord {
14 | var lastFailedProverQuery: Option[Term] = None
15 |
16 | override def getData(config: LogConfig): RecordData = {
17 | val data = super.getData(config)
18 | data.lastSMTQuery = lastFailedProverQuery
19 | data
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/scoping/ScopingRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.scoping
8 |
9 | import viper.silicon.logger.LogConfig
10 | import viper.silicon.logger.records.{RecordData, SymbolicRecord}
11 |
12 | trait ScopingRecord extends SymbolicRecord {
13 | val refId: Int
14 | var timeMs: Long = 0
15 |
16 | override def getData(config: LogConfig): RecordData = {
17 | val data = super.getData(config)
18 | data.refId = Some(refId)
19 | data.timeMs = Some(timeMs)
20 | data
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/resources/cvc5config.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; Requires CVC5 >= 1.0.0
6 | (set-option :print-success true)
7 |
8 | (set-logic ALL)
9 | (set-option :seed 0)
10 | (set-option :sat-random-seed 0)
11 |
12 | ; default options as used by boogie
13 | (set-option :incremental true) ; required for push and pop
14 | (set-option :condense-function-values false)
15 | (set-option :strict-parsing false)
16 | (set-option :produce-models true) ; enabled to support proverStdIO. retrieveAndSaveModel
17 |
18 | ; Translated from z3config
19 | (set-option :global-declarations true)
20 | (set-option :type-checking true)
21 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Branching.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method m1(b1: Bool, b2: Bool)
5 | {
6 | var a: Int
7 | a := (b1 ? (b2 ? 2 : 3) : ((b1 && b2) ? 4 : 5))
8 | a := 1+(b1 ? 1 : 2)+2
9 | a := 1
10 | }
11 |
12 | method m2(b: Bool) returns (a: Int)
13 | {
14 | a := 1
15 | if(a == 1){
16 | a := (b ? ((a==1) ? 2 : 3) : ((a!=1) ? 4 : 5))
17 | }
18 | else{
19 | a := -2
20 | }
21 |
22 |
23 | if(!!b){
24 | a := 2
25 | }
26 | else{
27 | a := 3
28 | }
29 | a := 4
30 | }
31 |
32 | method m3(b: Bool, c: Bool)
33 | {
34 | var a: Int
35 | if(b) {
36 | a := (c ? 1 : 2)
37 | }
38 | else {
39 | a := 3 + 4
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/test/resources/conditionalizePermissions/silicon_0713.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 |
5 | field int: Int
6 | field unrelated: Int
7 |
8 | method conv_layer(a: Set[Ref])
9 | requires (forall r: Ref :: r in a ==> acc(r.int, write))
10 | {
11 | label beforeFrame
12 | while (true)
13 | invariant true ==>
14 | (forall r: Ref :: r in a ==> acc(r.int, write)) &&
15 | [
16 | // on inhale
17 | (forperm
18 | obj: Ref [obj.unrelated] :: obj.unrelated ==
19 | old[beforeFrame](obj.unrelated)) &&
20 | (forperm
21 | obj: Ref [obj.int] :: obj.int == old[beforeFrame](obj.int)),
22 |
23 | // on exhale
24 | true
25 | ]
26 | { inhale false }
27 | }
--------------------------------------------------------------------------------
/src/main/resources/predicate_snap_functions_declarations.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; The definitions are parametric
6 | ; - $PRD$ is a Silver predicate name
7 | ; - $S$ is the sort corresponding to the type of the predicate arguments
8 |
9 | (declare-fun $PSF.domain_$PRD$ ($PSF<$PRD$>) Set<$Snap>)
10 | (declare-fun $PSF.has_domain_$PRD$ ($PSF<$PRD$>) Bool)
11 | (declare-fun $PSF.lookup_$PRD$ ($PSF<$PRD$> $Snap) $S$)
12 | (declare-fun $PSF.after_$PRD$ ($PSF<$PRD$> $PSF<$PRD$>) Bool)
13 | (declare-fun $PSF.loc_$PRD$ ($S$ $Snap) Bool)
14 | (declare-fun $PSF.perm_$PRD$ ($PPM $Snap) $Perm)
15 | (declare-const $psfTOP_$PRD$ $PSF<$PRD$>)
16 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va2.vpr:
--------------------------------------------------------------------------------
1 | method test() {
2 |
3 | var _1: Ref
4 | var _preserve: Ref
5 | var read: Perm := 1/8
6 |
7 | inhale acc(usize(_preserve), write-read)
8 | inhale acc(_1.val_ref, read) && acc(usize(_1.val_ref), read)
9 | inhale _preserve == _1.val_ref
10 | assert acc(usize(_1.val_ref), write)
11 | inhale 5 < (unfolding acc(usize(_1.val_ref), read) in _1.val_ref.val_int)
12 |
13 | assert 5 < (unfolding acc(usize(_1.val_ref), read) in _1.val_ref.val_int)
14 | exhale acc(usize(_1.val_ref), 2/8)
15 | assert 5 < (unfolding acc(usize(_1.val_ref), 3/8) in _1.val_ref.val_int) // Fails with --enableMoreCompleteExhale
16 | assert acc(usize(_1.val_ref), 6/8)
17 | }
18 |
19 | field val_int: Int
20 |
21 | field val_ref: Ref
22 |
23 | predicate usize(self: Ref) {
24 | acc(self.val_int, write)
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/scala/resources/Resources.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.resources
8 |
9 | import viper.silicon.Map
10 |
11 | object Resources {
12 | val resourceDescriptions: Map[ResourceID, ResourceDescription] =
13 | Map(PredicateID -> new PredicateDescription,
14 | FieldID-> new FieldDescription,
15 | MagicWandID -> new MagicWandDescription)
16 | }
17 |
18 | sealed abstract class ResourceID
19 | sealed abstract class BaseID extends ResourceID
20 |
21 | case object PredicateID extends BaseID
22 | case object FieldID extends BaseID
23 | case object MagicWandID extends ResourceID
24 |
--------------------------------------------------------------------------------
/src/main/resources/field_value_functions_declarations.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; The definitions are parametric
6 | ; - $FLD$ is a Silver field name
7 | ; - $S$ is the sort corresponding to the type of the field
8 | ; - $T$ is the sanitized name of the sort corresponding to the type of the field
9 |
10 | (declare-fun $FVF.domain_$FLD$ ($FVF<$FLD$>) Set<$Ref>)
11 | (declare-fun $FVF.has_domain_$FLD$ ($FVF<$FLD$>) Bool)
12 | (declare-fun $FVF.lookup_$FLD$ ($FVF<$FLD$> $Ref) $S$)
13 | (declare-fun $FVF.after_$FLD$ ($FVF<$FLD$> $FVF<$FLD$>) Bool)
14 | (declare-fun $FVF.loc_$FLD$ ($S$ $Ref) Bool)
15 | (declare-fun $FVF.perm_$FLD$ ($FPM $Ref) $Perm)
16 | (declare-const $fvfTOP_$FLD$ $FVF<$FLD$>)
17 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/simple-refs-rec.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field left: Int
5 | field right: Int
6 | field next: Ref
7 | field valid: Bool
8 |
9 | method simple(x: Ref, y: Ref, z: Ref, r: Int) returns (n: Int)
10 | requires acc(x.left) && acc(x.right)
11 | requires acc(y.left) && acc(y.right)
12 | requires acc(z.next) && acc(z.next.right)
13 | requires acc(x.valid) && x.valid
14 | requires r == 155
15 | requires y.left == 3 && y.right == 4
16 | requires x.left == 42 && x.right > 52
17 | requires z.next.right == 12
18 | //:: ExpectedCounterexample(postcondition.violated:assertion.false, (n == 42))
19 | ensures n == 1
20 | {
21 | n := x.left
22 | var b: Bool := false
23 | var s: Int := 99
24 | label ret
25 | x.left := 101
26 | x.right := 201
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/ConsumeRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state._
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class ConsumeRecord(v: ast.Exp, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Exp = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "consume"
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/EvaluateRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class EvaluateRecord(v: ast.Exp, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Exp = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "evaluate"
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/ExecuteRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class ExecuteRecord(v: ast.Stmt, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Stmt = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "execute"
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/ProduceRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class ProduceRecord(v: ast.Exp, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Exp = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "produce"
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/gobra/forall-simple1.gobra.vpr:
--------------------------------------------------------------------------------
1 | method test1_pkg_F()
2 | requires (forall m_pkg_V0: Int :: true)
3 | {
4 |
5 | // decl
6 |
7 |
8 | // decl
9 |
10 |
11 | label returnLabel
12 | }
13 |
14 | method test2_pkg_F()
15 | requires (forall x_pkg_V1: Int, y_pkg_V1: Int :: x_pkg_V1 < y_pkg_V1)
16 | requires (forall x_pkg_V2: Int, y_pkg_V2: Int :: { x_pkg_V2,y_pkg_V2 } x_pkg_V2 < y_pkg_V2)
17 | {
18 |
19 | // decl
20 |
21 |
22 | // decl
23 |
24 |
25 | label returnLabel
26 | }
27 |
28 | method test3_pkg_F()
29 | {
30 |
31 | // decl
32 |
33 |
34 | // decl
35 |
36 |
37 | // assert forall n_pkg_V3: int :: { } true
38 |
39 | assert (forall n_pkg_V3: Int :: true)
40 |
41 | // assert forall n_pkg_V4: int :: { n_pkg_V4 } true
42 |
43 | assert (forall n_pkg_V4: Int :: { n_pkg_V4 } true)
44 | label returnLabel
45 | }
--------------------------------------------------------------------------------
/docs/graal.md:
--------------------------------------------------------------------------------
1 | # Preliminary steps for compiling to a GraalVM native image
2 | This assumes a working *GraalVM Community Edition* installation with all the necessary environment variables (like `JAVA_HOME`) set correctly.
3 |
4 | 1. Prepare an empty directory `` for the program trace
5 | 1. With the Silicon JAR and some non-trivial Viper file `` in the current working directory, run Silicon on `` using the *native image agent*:
6 | `java -Xss256m -agentlib:native-image-agent=config-output-dir= -jar silicon.jar `.
7 | This is necessary because Silicon uses some dynamic JVM features (like loading the AdtPlugin at runtime) that cannot be statically inferred by the native image compiler.
8 | 1. Compile the Silicon JAR to a native image using the data gathered during the previous step:
9 | `native-image -H:ConfigurationFileDirectories= -jar silicon.jar`
10 |
--------------------------------------------------------------------------------
/common/src/main/scala/collections/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common
8 |
9 | package object collections {
10 | /** Computes the cross product (cartesian product) of a sequence of sequences.
11 | * Code taken from http://stackoverflow.com/a/8569263/491216.
12 | *
13 | * @param xs The sequence of sequences to compute the cross product of.
14 | * @tparam A Type of the inner sequence's elements.
15 | * @return The computed cross product.
16 | */
17 | def crossProduct[A](xs: Iterable[Iterable[A]]): Seq[Seq[A]] =
18 | xs.foldLeft(Vector(Vector.empty[A])) {
19 | (x, y) => for (a <- x; b <- y) yield a :+ b
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/ConditionalEdgeRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class ConditionalEdgeRecord(v: ast.Exp, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Exp = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "conditional edge"
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/ImpliesRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class ImpliesRecord(v: ast.Implies, s: State, p: PathConditionStack, val env: String) extends DataRecord {
16 | val value: ast.Implies = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "implies"
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/MethodCallRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class MethodCallRecord(v: ast.MethodCall, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.MethodCall = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "method call"
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_linkedListMinimal.vpr:
--------------------------------------------------------------------------------
1 | field data: Int
2 | field next: Ref
3 | field head: Ref
4 |
5 | predicate lseg(this: Ref, end: Ref)
6 | {
7 | this != end ==>
8 | acc(this.data) && acc(this.next) && acc(lseg(this.next, end)) &&
9 | unfolding acc(lseg(this.next, end)) in this.next != end ==> this.data <= this.next.data
10 | }
11 |
12 | predicate List(this: Ref)
13 | {
14 | acc(this.head) && acc(lseg(this.head, null))
15 | }
16 |
17 | method insert(this: Ref, elem: Int) returns (index: Int)
18 | requires acc(List(this))
19 | {
20 | var tmp: Ref
21 | index := 0
22 |
23 | unfold acc(List(this))
24 |
25 | // if(this.head != null) {
26 | unfold acc(lseg(this.head, null))
27 | // }
28 | // inhale acc(this.head)
29 | // inhale acc(this.head.data)
30 |
31 | if(this.head == null || elem <= this.head.data) {
32 | // fold acc(lseg(this.head, null))
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/CondExpRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.State
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class CondExpRecord(v: ast.CondExp, s: State, p: PathConditionStack, val env: String) extends DataRecord {
16 | val value: ast.CondExp = v
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 |
20 | override val toTypeString: String = "conditional expression"
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/scala/state/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon
8 |
9 | import viper.silicon.interfaces.state.NonQuantifiedChunk
10 | import viper.silver.ast
11 | import viper.silicon.rules.PermMapDefinition
12 | import viper.silicon.rules.moreCompleteExhaleSupporter.TaggedSummarisingSnapshot
13 | import viper.silicon.state.terms.Term
14 |
15 | package object state {
16 | type PmCache =
17 | Map[
18 | (ast.Resource, Seq[QuantifiedBasicChunk]),
19 | PermMapDefinition]
20 |
21 | type SsCache =
22 | Map[
23 | (ast.Resource, Seq[NonQuantifiedChunk], Seq[Term]),
24 | (Option[TaggedSummarisingSnapshot], Option[Seq[Term]], Term, Option[ast.Exp])]
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/DeciderAssumeRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.state._
11 | import viper.silicon.state.terms.Term
12 | import viper.silver.ast
13 |
14 | class DeciderAssumeRecord(val terms: Iterable[Term]) extends DataRecord {
15 | val value: ast.Node = null
16 | val state: State = null
17 | val pcs: InsertionOrderedSet[Term] = null
18 |
19 | override val toTypeString: String = "decider assume"
20 |
21 | override lazy val toSimpleString: String = {
22 | if (terms != null) terms.mkString(" ")
23 | else "null"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/MethodRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.terms.Term
12 | import viper.silver.ast
13 |
14 | class MethodRecord(v: ast.Method, p: PathConditionStack) extends MemberRecord {
15 | val value: ast.Method = v
16 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
17 |
18 | override val toTypeString: String = "method"
19 |
20 | override lazy val toSimpleString: String = {
21 | if (value != null) value.name
22 | else "null"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/DeciderAssertRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.state._
11 | import viper.silicon.state.terms.Term
12 | import viper.silver.ast
13 |
14 | class DeciderAssertRecord(val term: Term, val timeout: Option[Int]) extends DataRecord {
15 | val value: ast.Node = null
16 | val state: State = null
17 | val pcs: InsertionOrderedSet[Term] = null
18 |
19 | override val toTypeString: String = "decider assert"
20 |
21 | override lazy val toSimpleString: String = {
22 | if (term != null) term.toString
23 | else "null"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/FunctionRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.terms.Term
12 | import viper.silver.ast
13 |
14 | class FunctionRecord(v: ast.Function, p: PathConditionStack) extends MemberRecord {
15 | val value: ast.Function = v
16 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
17 |
18 | override val toTypeString: String = "function"
19 |
20 | override lazy val toSimpleString: String = {
21 | if (value != null) value.name
22 | else "null"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/common/src/main/scala/collections/immutable/MultiMap.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common.collections.immutable
8 |
9 | object MultiMap {
10 | /* Adapted from http://blog.xebia.com/multimap-in-scala/ */
11 | implicit class MultiMap[A, B](val map: Map[A, Set[B]]) extends AnyVal {
12 | def addBinding(key: A, value: B): Map[A, Set[B]] =
13 | map + (key -> (map.getOrElse(key, Set.empty) + value))
14 |
15 | def removeBinding(key: A, value: B): Map[A, Set[B]] = map.get(key) match {
16 | case None => map
17 | case Some(set) => map + (key -> (set - value))
18 | }
19 | }
20 |
21 | object MultiMap {
22 | def empty[A, B]: MultiMap[A, B] = new MultiMap(Map.empty)
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/PredicateRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state.terms.Term
12 | import viper.silver.ast
13 |
14 | class PredicateRecord(v: ast.Predicate, p: PathConditionStack) extends MemberRecord {
15 | val value: ast.Predicate = v
16 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
17 |
18 | override val toTypeString: String = "predicate"
19 |
20 | override lazy val toSimpleString: String = {
21 | if (value != null) value.name
22 | else "null"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTestsMoreJoins.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 | import viper.silver.testing.AnnotatedTestInput
9 |
10 | class SiliconTestsMoreJoins extends SiliconTests {
11 | override val testDirectories: Seq[String] = Seq("examples")
12 | val excludedFiles = Set(
13 | "examples/vmcai2016/linked-list-predicates.vpr" // Incompleteness with moreJoins
14 | )
15 |
16 | override def isTestToBeIncluded(testInput: AnnotatedTestInput): Boolean = {
17 | super.isTestToBeIncluded(testInput) && !excludedFiles.contains(testInput.name)
18 | }
19 |
20 | override val commandLineArguments: Seq[String] = Seq(
21 | "--timeout", "300" /* seconds */,
22 | "--moreJoins=2"
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/WellformednessCheckRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state._
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class WellformednessCheckRecord(v: Seq[ast.Exp], s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Node = null
17 | val conditions: Seq[ast.Exp] = v
18 | val state: State = s
19 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
20 |
21 | override val toTypeString: String = "WellformednessCheck"
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/structural/JoiningRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.structural
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.logger.records.data.DataRecord
12 | import viper.silicon.state.State
13 | import viper.silicon.state.terms.Term
14 | import viper.silver.ast
15 |
16 | class JoiningRecord(s: State, p: PathConditionStack) extends DataRecord with StructuralRecord {
17 | val value: ast.Node = null
18 | val state: State = s
19 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
20 |
21 | override val toTypeString: String = "joining"
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/RecordData.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.Map
11 | import viper.silicon.state.{Heap, Store}
12 | import viper.silicon.state.terms.Term
13 |
14 | class RecordData {
15 | var refId: Option[Int] = None
16 | var isSmtQuery: Boolean = false
17 | var smtStatistics: Option[Map[String, String]] = None
18 | var timeMs: Option[Long] = None
19 | var pos: Option[String] = None
20 | var lastSMTQuery: Option[Term] = None
21 | var store: Option[Store] = None
22 | var heap: Option[Heap] = None
23 | var oldHeap: Option[Heap] = None
24 | var pcs: Option[InsertionOrderedSet[Term]] = None
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/resources/consistency/consistency.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 | field r: Ref
6 |
7 | method epstest(x: Ref)
8 | //:: ExpectedOutput(internal:feature.unsupported)
9 | requires acc(x.f, epsilon)
10 | {}
11 |
12 | predicate recpred(x: Ref) {
13 | acc(x.f) && acc(x.r) && (x.r != null ==> acc(recpred(x.r)) && unfolding acc(recpred(x.r)) in x.r.f != 0)
14 | }
15 |
16 | method use_recpred(x: Ref)
17 | requires acc(recpred(x))
18 | {
19 | var v: Int := unfolding acc(recpred(x)) in x.f
20 | }
21 |
22 |
23 | // Issue #271
24 |
25 | field g: Int
26 |
27 | predicate pair(x: Ref) {
28 | //:: ExpectedOutput(internal:feature.unsupported)
29 | [acc(x.f) && acc(x.g),
30 | acc(x.g) && acc(x.f)]
31 | }
32 |
33 | function getf(x: Ref): Int
34 | //:: ExpectedOutput(internal:feature.unsupported)
35 | requires [acc(x.f) && acc(x.g),
36 | acc(x.g) && acc(x.f)]
37 | { x.f }
38 |
--------------------------------------------------------------------------------
/src/test/resources/counterexamples/lseg.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field elem : Int
5 | field next : Ref
6 |
7 | predicate lseg(first: Ref, last: Ref, values: Seq[Int])
8 | {
9 | first != last ==>
10 | acc(first.elem) && acc(first.next) &&
11 | 0 < |values| &&
12 | first.elem == values[0] &&
13 | lseg(first.next, last, values[1..])
14 | }
15 |
16 | method removeFirst(first: Ref, last: Ref, values: Seq[Int]) returns (value: Int, second: Ref)
17 | requires lseg(first, last, values)
18 | requires first != last
19 | ensures lseg(second, last, values[1..])
20 | // we have insufficient field permissions when second is equal to last:
21 | //:: ExpectedCounterexample(not.wellformed:insufficient.permission, (second == last))
22 | ensures value != unfolding lseg(second, last, values[1..]) in second.elem
23 | {
24 | unfold lseg(first, last, values)
25 | value := first.elem
26 | second := first.next
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va6.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 |
3 | predicate P02(xs: Seq[Ref], n: Int) {
4 | |xs| == n
5 | && 3 <= n
6 | && (forall i: Int, j: Int :: i >= 0 && i < |xs| && j >= 0 && j < |xs| && i != j ==> xs[i] != xs[j])
7 | && (forall j: Int :: 0 <= j && j < 3 ==> acc(xs[j].f))
8 | && (forall j: Int :: 3 <= j && j < n ==> acc(xs[j].f))
9 | }
10 |
11 | function fun06(xs: Seq[Ref], n: Int, i: Int): Int
12 | requires acc(P02(xs, n))
13 | requires 0 < i && i < n
14 | {
15 | unfolding acc(P02(xs, n)) in xs[i].f
16 | }
17 |
18 | method test05(xs: Seq[Ref], n: Int, i: Int) {
19 | inhale acc(P02(xs, n))
20 | inhale 6 < n
21 | inhale i == 4
22 |
23 | unfold acc(P02(xs, n))
24 | var v1: Int := xs[i].f
25 | fold acc(P02(xs, n))
26 |
27 | assert v1 == fun06(xs, n, i)
28 |
29 | unfold acc(P02(xs, n))
30 | xs[i].f := 0
31 | fold acc(P02(xs, n))
32 |
33 | var v2: Int := fun06(xs, n, i)
34 | assert v2 == 0
35 | //:: ExpectedOutput(assert.failed:assertion.false)
36 | assert v2 == v1
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/scala/rules/FunctionSupporter.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.rules
8 |
9 | import viper.silicon.state._
10 | import viper.silicon.state.terms._
11 |
12 | object functionSupporter {
13 | def limitedVersion(function: HeapDepFun): HeapDepFun = {
14 | val id = function.id.withSuffix("%", "limited")
15 | HeapDepFun(id, function.argSorts, function.resultSort)
16 | }
17 |
18 | def statelessVersion(function: HeapDepFun): Fun = {
19 | val id = function.id.withSuffix("%", "stateless")
20 | Fun(id, function.argSorts.tail, terms.sorts.Bool)
21 | }
22 |
23 | def preconditionVersion(function: HeapDepFun): HeapDepFun = {
24 | val id = function.id.withSuffix("%", "precondition")
25 | HeapDepFun(id, function.argSorts, terms.sorts.Bool)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Incompleteness.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 |
3 | method m1_1(x: Ref)
4 | {
5 | inhale acc(x.f, 1/2) && acc(x.f, 1/2)
6 | assert acc(x.f)
7 | }
8 |
9 | method m1_2(x: Ref, y: Ref)
10 | {
11 | inhale acc(x.f, 1/2) && acc(y.f, 1/2)
12 | inhale x == y
13 | assert acc(x.f)
14 | }
15 |
16 | method m1_3(x: Ref, y: Ref, z: Ref)
17 | {
18 | inhale acc(x.f) && acc(y.f)
19 | inhale z == x || z == y
20 | // assert acc(z.f)
21 | }
22 |
23 | method m2_1(x: Ref)
24 | {
25 | inhale acc(x.f, 1/2) && acc(x.f, 1/2) && x.f == 0
26 | exhale acc(x.f, 1/2)
27 | assert x.f == 0
28 | }
29 |
30 | method m2_2(x: Ref, y: Ref)
31 | {
32 | inhale acc(x.f, 1/2) && acc(y.f, 1/2) && x.f == 0
33 | exhale acc(x.f, 1/2)
34 | inhale x == y
35 | // assert y.f == 0
36 | }
37 |
38 | method m3_1(x: Ref, y: Ref, z: Ref)
39 | {
40 | inhale acc(x.f) && acc(y.f) && z == x
41 | assert x != y
42 | inhale acc(z.f, 1/10)
43 | // assert true
44 | // assert false
45 | }
46 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_Incompleteness.vpr.elog:
--------------------------------------------------------------------------------
1 | method m1_1
2 | execute inhale acc(x.f, 1 / 2) && acc(x.f, 1 / 2)
3 | execute assert acc(x.f, write)
4 |
5 | method m1_2
6 | execute inhale acc(x.f, 1 / 2) && acc(y.f, 1 / 2)
7 | execute inhale x == y
8 | execute assert acc(x.f, write)
9 |
10 | method m1_3
11 | execute inhale acc(x.f, write) && acc(y.f, write)
12 | execute inhale z == x || z == y
13 | Join
14 | Branch z@14@01 == x@12@01:
15 | comment: Reachable
16 | Branch z@14@01 != x@12@01:
17 | comment: Reachable
18 |
19 | method m2_1
20 | execute inhale acc(x.f, 1 / 2) && (acc(x.f, 1 / 2) && x.f == 0)
21 | execute exhale acc(x.f, 1 / 2)
22 | execute assert x.f == 0
23 |
24 | method m2_2
25 | execute inhale acc(x.f, 1 / 2) && (acc(y.f, 1 / 2) && x.f == 0)
26 | execute exhale acc(x.f, 1 / 2)
27 | execute inhale x == y
28 |
29 | method m3_1
30 | execute inhale acc(x.f, write) && (acc(y.f, write) && z == x)
31 | execute assert x != y
32 | execute inhale acc(z.f, 1 / 10)
33 |
34 |
--------------------------------------------------------------------------------
/src/test/resources/conditionalRewriter/test1.vpr:
--------------------------------------------------------------------------------
1 | field f: Ref
2 |
3 | predicate P(x: Ref)
4 | predicate Q(x: Ref)
5 | predicate R(x: Ref)
6 |
7 | method test0(b: Bool, x: Ref)
8 | requires acc(x.f)
9 | requires b ==> x != null
10 |
11 | method test10(b: Bool, x: Ref)
12 | requires b ==> acc(x.f)
13 |
14 | method test20(b: Bool, x: Ref, i: Int)
15 | requires P(x) && (b ==> x != null)
16 | requires i != 0 && (b ==> acc(x.f))
17 |
18 | method test30(b: Bool, x: Ref, i: Int)
19 | requires b ==> acc(x.f) && true
20 |
21 | method test40(b: Bool, x: Ref, i: Int)
22 | requires b ==> acc(x.f) && (true && true)
23 | requires b ==> (acc(x.f) && true) && true
24 |
25 | method test1000(b: Bool, x: Ref, i: Int)
26 | requires P(x) && (b ==> x != null)
27 | requires i != 0 && (b ==> acc(x.f))
28 | {
29 | assert x != null || x == null
30 | assert b ==> (acc(x.f) && (x.f != null || x.f == null))
31 | assert b ==> i != 0 && (acc(x.f) && x != null)
32 | assert b ==> (i != 0 && acc(x.f)) && x != null
33 | assert b ==> (acc(x.f) && x != null) && i != 0
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/resources/moreCompleteExhale/0523.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 |
6 | function req(x: Ref): Bool
7 | requires acc(x.f, 2/1)
8 | { true }
9 |
10 | method test(x: Ref) {
11 | inhale acc(x.f)
12 | assert req(x)
13 | //:: ExpectedOutput(assert.failed:assertion.false)
14 | assert false
15 | }
16 |
17 |
18 |
19 | /////// Example from issue 594
20 |
21 | field val$_Int: Int
22 |
23 | function getter_pkg_F(param_pkg_V0: Ref): Int
24 | requires acc(SomePredicate_pkg_F(param_pkg_V0), write)
25 | {
26 | (unfolding acc(SomePredicate_pkg_F(param_pkg_V0), write) in param_pkg_V0.val$_Int)
27 | }
28 |
29 | predicate SomePredicate_pkg_F(param_pkg_V0: Ref) {
30 | true && acc(param_pkg_V0.val$_Int, write)
31 | }
32 |
33 | method client2_pkg_F(param_pkg_V0: Ref) returns (res_pkg_V0: Int)
34 | requires acc(SomePredicate_pkg_F(param_pkg_V0), 1 / 2)
35 | ensures acc(SomePredicate_pkg_F(param_pkg_V0), 1 / 2)
36 | ensures res_pkg_V0 == getter_pkg_F(param_pkg_V0)
--------------------------------------------------------------------------------
/src/main/scala/extensions/TryBlockParserPlugin.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2020 ETH Zurich.
6 |
7 | package viper.silicon.extensions
8 |
9 | import viper.silver.parser.FastParser
10 | import viper.silver.plugin.{ParserPluginTemplate, SilverPlugin}
11 |
12 | class TryBlockParserPlugin(fp: FastParser) extends SilverPlugin with ParserPluginTemplate {
13 | import fastparse._
14 | import viper.silver.parser.FastParserCompanion.{PositionParsing, reservedKw, whitespace}
15 | import fp.{ParserExtension, lineCol, _file, stmtBlock}
16 |
17 | def tryBlock[$: P]: P[PTryBlock] = P((P(PTryKeyword) ~ stmtBlock()) map (PTryBlock.apply _).tupled).pos
18 |
19 | override def beforeParse(input: String, isImported: Boolean): String = {
20 | ParserExtension.addNewKeywords(Set(PTryKeyword))
21 | ParserExtension.addNewStmtAtEnd(tryBlock(_))
22 |
23 | input
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/AdtPluginTests.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2021 ETH Zurich.
6 |
7 |
8 | package viper.silicon.tests
9 |
10 | import viper.silicon.Silicon
11 | import viper.silver.reporter.NoopReporter
12 |
13 |
14 | class AdtPluginTests extends SiliconTests {
15 |
16 | override val testDirectories: Seq[String] = Seq("adt")
17 |
18 | override val silicon: Silicon = {
19 | val reporter = NoopReporter
20 | val debugInfo = ("startedBy" -> "viper.silicon.AdtPluginTests") :: Nil
21 | new Silicon(reporter, debugInfo)
22 | }
23 |
24 | override def verifiers = List(silicon)
25 |
26 | override def configureVerifiersFromConfigMap(configMap: Map[String, Any]): Unit = {
27 | val newConfigMap = configMap.updated("silicon:plugin", "viper.silver.plugin.standard.adt.AdtPlugin")
28 | super.configureVerifiersFromConfigMap(newConfigMap)
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va1.vpr:
--------------------------------------------------------------------------------
1 | field val: Int
2 |
3 | define read 1/8
4 |
5 | method test_fields(x: Ref, y: Ref) {
6 | inhale acc(y.val, 1/2)
7 | inhale acc(x.val, 1/2)
8 | inhale y == x
9 |
10 | inhale 5 < y.val
11 | assert 5 < x.val
12 |
13 | exhale acc(y.val, 2/3)
14 | assert 5 < y.val
15 | assert 5 < x.val
16 | }
17 |
18 | method test_fields2(x: Ref, y: Ref, z: Ref) {
19 | inhale acc(z.val, 1/3)
20 | inhale acc(y.val, 1/3)
21 | inhale acc(x.val, 1/3)
22 | inhale x == y
23 |
24 | inhale 5 < y.val
25 | inhale y == z
26 |
27 | exhale acc(x.val, 1/3)
28 | assert 5 < z.val
29 | }
30 |
31 | predicate usize(self: Ref) {
32 | acc(self.val, write)
33 | }
34 |
35 | function get(self: Ref, p: Perm): Int
36 | requires none < p
37 | requires acc(usize(self), p)
38 |
39 |
40 | method test_predicates(x: Ref, y: Ref) {
41 | inhale acc(usize(y), 1/2)
42 | inhale acc(usize(x), 1/2)
43 | inhale y == x
44 |
45 | inhale 5 < get(y, 1/100)
46 | assert 5 < get(x, 1/100)
47 |
48 | // exhale acc(usize(x), 2/3)
49 | // assert 5 < get(x, 1/100)
50 | // assert 5 < get(y, 1/100)
51 | }
52 |
--------------------------------------------------------------------------------
/docs/licenses/Scallop.txt:
--------------------------------------------------------------------------------
1 | Copyright (C) 2012 Platon Pronko
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | UTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 |
--------------------------------------------------------------------------------
/src/main/resources/predicate_snap_functions_axioms_no_triggers.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; The axioms are parametric
6 | ; - $FLD$ is a Silver field name
7 | ; - $S$ is the sort corresponding to the type of the field
8 |
9 | ; ATTENTION: The triggers mention the sort wrappers introduced for FVFs.
10 | ; The axiom therefore needs to be emitted after the sort wrappers have
11 | ; been emitted.
12 |
13 | (assert (forall ((vs $PSF<$S$>) (ws $PSF<$S$>)) (!
14 | (=>
15 | (and
16 | (Set_equal ($PSF.domain_$PRD$ vs) ($PSF.domain_$PRD$ ws))
17 | (forall ((x $Snap)) (!
18 | (=>
19 | (Set_in x ($PSF.domain_$FRD$ vs))
20 | (= ($PSF.lookup_$PRD$ vs x) ($PSF.lookup_$PRD$ ws x)))
21 | :qid |qp.$PSF<$S$>-eq-inner|
22 | )))
23 | (= vs ws))
24 | :qid |qp.$PSF<$S$>-eq-outer|
25 | )))
26 |
27 | (assert (forall ((s $Snap) (f $S$)) (!
28 | (= ($PSF.loc_$PRD$ f s) true)
29 | )))
--------------------------------------------------------------------------------
/common/src/main/scala/concurrency/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common
8 |
9 | import java.util.concurrent.{Callable, Future, TimeUnit}
10 | import scala.language.implicitConversions
11 |
12 | package object concurrency {
13 | class SynchronousFuture[T](callable: Callable[T]) extends Future[T] {
14 | private var result: Option[T] = None
15 |
16 | val isCancelled = false
17 |
18 | def isDone = result.isDefined
19 |
20 | def get(): T = {
21 | result match {
22 | case Some(t) => t
23 | case None =>
24 | val t = callable.call()
25 | result = Some(t)
26 | t
27 | }
28 | }
29 |
30 | def get(timeout: Long, unit: TimeUnit) = ???
31 |
32 | def cancel(mayInterruptIfRunning: Boolean) = ???
33 | }
34 |
35 | implicit def functionToCallable[R](f: => R): Callable[R] = new Callable[R]{
36 | def call: R = f
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/scala/debugger/DebugTypechecker.scala:
--------------------------------------------------------------------------------
1 | package viper.silicon.debugger
2 |
3 | import viper.silver.FastMessaging
4 | import viper.silver.parser._
5 |
6 | class DebugResolver(override val p: PProgram, names: NameAnalyser) extends Resolver(p){
7 | override val typechecker: DebugTypeChecker = new DebugTypeChecker(names)
8 | }
9 |
10 | class DebugTypeChecker(override val names: NameAnalyser) extends TypeChecker(names) {
11 | var debugVariableTypes: Map[String, PType] = Map.empty
12 |
13 | override def checkInternal(exp: PExp): Unit = {
14 | exp match {
15 | case pviu: PVersionedIdnUseExp =>
16 | acceptAndCheckTypedEntityWithVersion(Seq(pviu), s"Could not resolve the type of ${pviu.versionedName}")
17 | case _ => super.checkInternal(exp)
18 | }
19 | }
20 |
21 | def acceptAndCheckTypedEntityWithVersion(idnUses: Seq[PVersionedIdnUseExp], errorMessage: => String): Unit = {
22 | idnUses.foreach { use =>
23 | val decl1 = debugVariableTypes.get(use.versionedName)
24 |
25 | decl1 match {
26 | case Some(value) => use.typ = value
27 | case None => messages ++= FastMessaging.message(use, errorMessage)
28 | }
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/CommentRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.state._
12 | import viper.silicon.state.terms.Term
13 | import viper.silver.ast
14 |
15 | class CommentRecord(str: String, s: State, p: PathConditionStack) extends DataRecord {
16 | val value: ast.Node = null
17 | val state: State = s
18 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
19 | val comment: String = str
20 |
21 | override val toTypeString: String = "comment"
22 |
23 | override lazy val toSimpleString: String = {
24 | if (comment != null) comment
25 | else "null"
26 | }
27 |
28 | override lazy val toString: String = {
29 | if (comment != null) {
30 | s"comment $comment"
31 | } else {
32 | "comment "
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/scala/supporters/DefaultMapsContributor.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.supporters
8 |
9 | import scala.reflect.{ClassTag, classTag}
10 | import viper.silicon.Config
11 | import viper.silver.ast
12 | import viper.silicon.state.terms.{Sort, Term, sorts}
13 |
14 | class DefaultMapsContributor(val domainTranslator: DomainsTranslator[Term], config: Config) extends BuiltinDomainsContributor {
15 |
16 | override type BuiltinDomainType = ast.MapType
17 |
18 | val builtinDomainTypeTag: ClassTag[BuiltinDomainType] = classTag[ast.MapType]
19 |
20 | override def defaultSourceResource: String = "/dafny_axioms/maps.vpr"
21 |
22 | override def userProvidedSourceFilepath: Option[String] = config.mapAxiomatizationFile.toOption
23 |
24 | override def sourceDomainName: String = "$Map"
25 |
26 | override def targetSortFactory(argumentSorts: Iterable[Sort]): Sort = {
27 | assert(argumentSorts.size == 2)
28 | sorts.Map(argumentSorts.head, argumentSorts.tail.head)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/scala/state/Heap.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.state
8 |
9 | import viper.silicon.interfaces.state.Chunk
10 |
11 | trait Heap {
12 | def values: Iterable[Chunk]
13 | def +(chunk: Chunk): Heap
14 | def +(other: Heap): Heap
15 | def -(chunk: Chunk): Heap
16 | }
17 |
18 | trait HeapFactory[H <: Heap] {
19 | def apply(): H
20 | def apply(chunks: Iterable[Chunk]): H
21 | }
22 |
23 | object Heap extends HeapFactory[ListBackedHeap] {
24 | def apply() = new ListBackedHeap(Vector.empty)
25 | def apply(chunks: Iterable[Chunk]) = new ListBackedHeap(chunks.toVector)
26 | }
27 |
28 | final class ListBackedHeap private[state] (chunks: Vector[Chunk])
29 | extends Heap {
30 |
31 | def values = chunks
32 |
33 | def +(ch: Chunk) = new ListBackedHeap(chunks :+ ch)
34 | def +(h: Heap) = new ListBackedHeap(chunks ++ h.values)
35 |
36 | def -(ch: Chunk) = {
37 | val (prefix, suffix) = chunks.span(_ != ch)
38 |
39 | new ListBackedHeap(prefix ++ suffix.tail)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/scala/reporting/MultiRunLineRecorder.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.reporting
8 |
9 | import java.io.PrintWriter
10 |
11 | /* A multi-run recorder that directly writes each recorded line (`def record(...)`) to the underlying sink.
12 | *
13 | * WARNING: Not thread-safe! See also MultiRunRecorder.scala.
14 | *
15 | * Best used via the global MultiRunRecorders singleton, e.g.:
16 | * MultiRunRecorders.get[MultiRunLogger]("myLogfile").record(myData)
17 | */
18 | class MultiRunLineRecorder(val sink: PrintWriter, sourceProvider: () => Option[String])
19 | extends PrintWriterBasedMultiRunRecorder {
20 |
21 | def source: Option[String] = sourceProvider()
22 |
23 | protected def onSourceChanged(previousSource: Option[String], currentSource: Option[String]): Unit = {
24 | sink.println(formatNewSource(currentSource))
25 | }
26 |
27 | def record(a: Any, ln: Boolean = true): Unit = {
28 | detectSourceChange()
29 |
30 | if (ln) sink.println(a)
31 | else sink.print(a)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/scala/reporting/Exceptions.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.reporting
8 |
9 | import viper.silver.ast
10 | import viper.silver.verifier.AbstractError
11 |
12 | trait SiliconException extends RuntimeException {
13 | def asViperError: AbstractError
14 | }
15 |
16 | case class ExternalToolError(tool: String, message: String)
17 | extends RuntimeException(message)
18 | with SiliconException {
19 |
20 | val asViperError = new AbstractError {
21 | def pos = ast.NoPosition
22 | def fullId = "external.tool.error"
23 | def readableMessage = s"Problem with external tool $tool: $message"
24 | }
25 | }
26 |
27 | case class ProverInteractionFailed(proverId: String, message: String)
28 | extends RuntimeException(message)
29 | with SiliconException {
30 |
31 | val asViperError = new AbstractError {
32 | def pos = ast.NoPosition
33 | def fullId = "prover.interaction.failed"
34 | def readableMessage = s"Interaction with prover (instance $proverId) failed: $message"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/resources/field_value_functions_axioms_no_triggers.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; The axioms are parametric
6 | ; - $FLD$ is a Silver field name
7 | ; - $S$ is the sort corresponding to the type of the field
8 | ; - $T$ is the sanitized name of the sort corresponding to the type of the field
9 |
10 | ; ATTENTION: The triggers mention the sort wrappers introduced for FVFs.
11 | ; The axiom therefore needs to be emitted after the sort wrappers have
12 | ; been emitted.
13 |
14 | (assert (forall ((vs $FVF<$T$>) (ws $FVF<$T$>)) (!
15 | (=>
16 | (and
17 | (Set_equal ($FVF.domain_$FLD$ vs) ($FVF.domain_$FLD$ ws))
18 | (forall ((x $Ref)) (!
19 | (=>
20 | (Set_in x ($FVF.domain_$FLD$ vs))
21 | (= ($FVF.lookup_$FLD$ vs x) ($FVF.lookup_$FLD$ ws x)))
22 | :qid |qp.$FVF<$T$>-eq-inner|
23 | )))
24 | (= vs ws))
25 | :qid |qp.$FVF<$T$>-eq-outer|
26 | )))
27 |
28 | (assert (forall ((r $Ref) (pm $FPM)) (!
29 | ($Perm.isValidVar ($FVF.perm_$FLD$ pm r))
30 | )))
31 |
32 | (assert (forall ((r $Ref) (f $S$)) (!
33 | (= ($FVF.loc_$FLD$ f r) true)
34 | )))
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/ProverAssertRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.logger.records.RecordData
11 | import viper.silicon.Map
12 | import viper.silicon.logger.LogConfig
13 | import viper.silicon.state.State
14 | import viper.silicon.state.terms.Term
15 | import viper.silver.ast
16 |
17 | class ProverAssertRecord(val term: Term, val timeout: Option[Int]) extends DataRecord {
18 | val value: ast.Node = null
19 | val state: State = null
20 | val pcs: InsertionOrderedSet[Term] = null
21 | var statistics: Option[Map[String, String]] = None
22 |
23 | override val toTypeString: String = "prover assert"
24 |
25 | override lazy val toSimpleString: String = {
26 | if (term != null) term.toString
27 | else "null"
28 | }
29 |
30 | override def getData(config: LogConfig): RecordData = {
31 | val data = super.getData(config)
32 | data.isSmtQuery = true
33 | data.smtStatistics = statistics
34 | data
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/silicon.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set CURR_DIR=%cd%
4 | set BASE_DIR=%~dp0
5 |
6 | :: switch to repository root to check for classpath file and possibly call sbt.
7 | cd "%BASE_DIR%"
8 |
9 | :: Only call sbt if the classpath file is missing.
10 | if not exist silicon_classpath.txt (
11 | rem Read all lines of the sbt runtime classpath output and parse it against the regex supplied to findstr.
12 | rem The regex looks for lines not starting with '[' and ending in '.jar' as the classpath usually does
13 | rem (and log lines don't, since they are prefixed with [LOGLEVEL]).
14 | echo Generating missing silicon_classpath.txt file from sbt classpath
15 | for /f "tokens=*" %%i in ('sbt "export runtime:dependencyClasspath" ^| findstr "[^\[].*\.jar$"') do (
16 | echo |set /p=%%i > silicon_classpath.txt
17 | )
18 | )
19 |
20 | :: Read classpath file in rather cumbersome way to avoid the 1024 character buffer limit.
21 | :: Note: this solutions breaks, once the classpath is longer than 8192 characters!
22 | for /f "delims=" %%x in (silicon_classpath.txt) do set CP=%%x
23 |
24 | :: switch back to original directory
25 | cd "%CURR_DIR%"
26 |
27 | set JVM_OPTS=-Xss16m -Dlogback.configurationFile="%BASE_DIR%\src\main\resources\logback.xml" -Dfile.encoding=UTF-8
28 |
29 | call java %JVM_OPTS% -cp "%CP%" viper.silicon.SiliconRunner %*
30 |
--------------------------------------------------------------------------------
/src/test/resources/snapshots/test_exp.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 |
3 | function zero(x: Ref): Bool
4 | requires acc(x.f)
5 | { x.f == 0 }
6 |
7 | function dangling(x: Ref): Bool
8 | { x == null }
9 |
10 | method test00(xs: Set[Ref], y: Ref) {
11 | assume forall x: Ref :: {zero(x)}
12 | x == y ==> dangling(x)
13 | }
14 |
15 | method test01(xs: Set[Ref], y: Ref) {
16 | inhale forall x: Ref :: x in xs ==> acc(x.f)
17 |
18 | assume forall x: Ref :: {zero(x)}
19 | x == y ==> dangling(x)
20 | }
21 |
22 | method test02(xs: Set[Ref], y: Ref) {
23 | inhale forall x: Ref :: x in xs ==> acc(x.f)
24 | inhale acc(y.f)
25 |
26 | assume forall x: Ref :: {zero(x)}
27 | x == y ==> dangling(x)
28 | }
29 |
30 |
31 | method test03(xs: Set[Ref], y: Ref) {
32 | assume forall x: Ref :: {zero(x)}
33 | //:: ExpectedOutput(application.precondition:insufficient.permission)
34 | x == y ==> zero(x)
35 | }
36 |
37 | method test04(xs: Set[Ref], y: Ref) {
38 | inhale forall x: Ref :: x in xs ==> acc(x.f)
39 |
40 | assume forall x: Ref :: {zero(x)}
41 | //:: ExpectedOutput(application.precondition:insufficient.permission)
42 | x == y ==> zero(x)
43 | }
44 |
45 | method test05(xs: Set[Ref], y: Ref) {
46 | inhale forall x: Ref :: x in xs ==> acc(x.f)
47 | inhale acc(y.f)
48 |
49 | assume forall x: Ref :: {zero(x)}
50 | x == y ==> zero(x)
51 | }
52 |
--------------------------------------------------------------------------------
/common/src/main/scala/collections/immutable/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common.collections
8 |
9 | import scala.collection.immutable.ListSet
10 |
11 | package object immutable {
12 | type InsertionOrderedSet[E] = ListSet[E]
13 |
14 | object InsertionOrderedSet {
15 | def empty[E]: InsertionOrderedSet[E] = ListSet.empty
16 |
17 | def apply[E](): InsertionOrderedSet[E] = ListSet.empty
18 | def apply[E](e: E): InsertionOrderedSet[E] = ListSet.empty + e
19 | def apply[E](es: InsertionOrderedSet[E]): InsertionOrderedSet[E] = es
20 | def apply[E](es: Iterable[E]): InsertionOrderedSet[E] = ListSet.empty ++ es
21 | }
22 |
23 | // type InsertionOrderedSet[E] = Set[E]
24 | //
25 | // object InsertionOrderedSet {
26 | // def empty[E]: InsertionOrderedSet[E] = Set.empty
27 | //
28 | // def apply[E](): InsertionOrderedSet[E] = Set.empty
29 | // def apply[E](e: E): InsertionOrderedSet[E] = Set.empty + e
30 | // def apply[E](es: InsertionOrderedSet[E]): InsertionOrderedSet[E] = es
31 | // def apply[E](es: Iterable[E]): InsertionOrderedSet[E] = Set.empty ++ es
32 | // }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/scala/supporters/DefaultMultisetsContributor.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.supporters
8 |
9 | import scala.reflect.{ClassTag, classTag}
10 | import viper.silicon.Config
11 | import viper.silver.ast
12 | import viper.silicon.state.terms._
13 | import viper.silicon.verifier.Verifier
14 |
15 | class DefaultMultisetsContributor(val domainTranslator: DomainsTranslator[Term], config: Config)
16 | extends BuiltinDomainsContributor {
17 |
18 | type BuiltinDomainType = ast.MultisetType
19 | val builtinDomainTypeTag: ClassTag[BuiltinDomainType] = classTag[ast.MultisetType]
20 |
21 | lazy val defaultSourceResource: String = {
22 | if (Verifier.config.useOldAxiomatization())
23 | "/dafny_axioms/multisets_old.vpr"
24 | else
25 | "/dafny_axioms/multisets.vpr"
26 | }
27 | val userProvidedSourceFilepath: Option[String] = config.multisetAxiomatizationFile.toOption
28 | val sourceDomainName: String = "$Multiset"
29 |
30 | def targetSortFactory(argumentSorts: Iterable[Sort]): Sort = {
31 | assert(argumentSorts.size == 1)
32 | sorts.Multiset(argumentSorts.head)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/common/src/main/scala/collections/mutable/MultiMap.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common.collections.mutable
8 |
9 | import scala.collection.mutable
10 |
11 | /** Copy of scala.collection.mutable.MultiMap where all internally used
12 | * sets and maps have been replaced by those that guarantee a deterministic
13 | * traversal order.
14 | */
15 | trait MMultiMap[A, B] extends mutable.LinkedHashMap[A, mutable.LinkedHashSet[B]] {
16 | def addBinding(key: A, value: B): this.type = {
17 | get(key) match {
18 | case None =>
19 | val set = new mutable.LinkedHashSet[B]()
20 | set += value
21 | this(key) = set
22 | case Some(set) =>
23 | set += value
24 | }
25 | this
26 | }
27 |
28 | def removeBinding(key: A, value: B): this.type = {
29 | get(key) match {
30 | case None =>
31 | case Some(set) =>
32 | set -= value
33 | if (set.isEmpty) this -= key
34 | }
35 | this
36 | }
37 |
38 | def entryExists(key: A, p: B => Boolean): Boolean = get(key) match {
39 | case None => false
40 | case Some(set) => set exists p
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/resources/z3config.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; Tested with Z3 4.8.7 and 4.12.1
6 |
7 | ; ATTENTION: Continuing multi-line statements must be indented with at least
8 | ; one tab or two spaces. All other lines must not start with tabs
9 | ; or more than one space.
10 |
11 | ; Currently, print-success MUST come first, because it guarantees that every query to Z3, including
12 | ; setting options, is answered by a success (or error) reply from Z3. Silicon currently relies on
13 | ; these replies when it interacts with Z3 via stdio.
14 | (set-option :print-success true) ; Boogie: false
15 | (set-option :global-decls true) ; Necessary for push pop mode
16 |
17 | ; These options are taken from Dafny 4.0.0 and proven to work decently well with up-to-date Z3 (currently 4.12.1),
18 | ; unlike the options used previously.
19 | (set-option :auto_config false)
20 | (set-option :smt.case_split 3)
21 | (set-option :smt.delay_units true)
22 | (set-option :type_check true)
23 | (set-option :smt.mbqi false)
24 | (set-option :pp.bv_literals false)
25 | (set-option :smt.qi.eager_threshold 100)
26 | (set-option :smt.arith.solver 2)
27 | (set-option :model.v2 true)
28 |
29 | ; We want unlimited multipatterns
30 | (set-option :smt.qi.max_multi_patterns 1000)
31 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
11 |
12 |
13 | %msg%n
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main/scala/reporting/MultiRunCountingRecorder.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.reporting
8 |
9 | import java.io.PrintWriter
10 | import scala.collection.mutable
11 |
12 | /* A multi-run recorder that counts how often an item was recorded (`def record(...)`), and after each
13 | * run, writes the recorded item-count pairs to the underlying sink.
14 | *
15 | * WARNING: Not thread-safe! See also MultiRunRecorder.scala.
16 | *
17 | * Best used via the global MultiRunRecorders singleton, e.g.:
18 | * MultiRunRecorders.get[MultiRunCountingRecorder[String]]("myLogfile").record(myData)
19 | */
20 | class MultiRunCountingRecorder[K](val sink: PrintWriter, sourceProvider: () => Option[String])
21 | extends BufferingPrintWriterBasedMultiRunRecorder {
22 |
23 | private val data = mutable.HashMap.empty[K, Int]
24 |
25 | def source: Option[String] = sourceProvider()
26 |
27 | def record(key: K): Unit = {
28 | detectSourceChange()
29 |
30 | val count = data.getOrElseUpdate(key, 0)
31 | data(key) = count + 1
32 | }
33 |
34 | protected def writeAndClearRecordedData(): Unit = {
35 | data.foreach { case (key, value) =>
36 | sink.println(s"$key: $value")
37 | }
38 |
39 | data.clear()
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/scala/rules/ConsumptionResult.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.rules
8 |
9 | import viper.silicon.state.terms.{Forall, Term, Var}
10 | import viper.silicon.state.terms.perms.IsNonPositive
11 | import viper.silver.ast
12 | import viper.silicon.verifier.Verifier
13 |
14 | sealed trait ConsumptionResult {
15 | def isComplete: Boolean
16 | def ||(other: => ConsumptionResult): ConsumptionResult
17 | }
18 |
19 | private case class Complete() extends ConsumptionResult {
20 | override def isComplete: Boolean = true
21 | override def ||(other: => ConsumptionResult): ConsumptionResult = this
22 | }
23 |
24 | private case class Incomplete(permsNeeded: Term, permsNeededExp: Option[ast.Exp]) extends ConsumptionResult {
25 | override def isComplete: Boolean = false
26 | override def ||(other: => ConsumptionResult): ConsumptionResult = other
27 | }
28 |
29 | object ConsumptionResult {
30 | def apply(term: Term, exp: Option[ast.Exp], qvars: Seq[Var], v: Verifier, timeout: Int): ConsumptionResult = {
31 | val toCheck = if (qvars.isEmpty) {
32 | IsNonPositive(term)
33 | } else {
34 | Forall(qvars, IsNonPositive(term), Seq())
35 | }
36 | if (v.decider.check(toCheck, timeout))
37 | Complete()
38 | else
39 | Incomplete(term, exp)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/scala/logger/LogConfig.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger
8 |
9 | import spray.json._
10 | import viper.silicon.logger.records.data.DataRecord
11 |
12 | case class LogConfig(isBlackList: Boolean,
13 | includeStore: Boolean, includeHeap: Boolean, includeOldHeap: Boolean, includePcs: Boolean,
14 | recordConfigs: List[RecordConfig]) {
15 | def getRecordConfig(d: DataRecord): Option[RecordConfig] = {
16 | for (rc <- recordConfigs) {
17 | if (rc.kind.equals(d.toTypeString)) {
18 | rc.value match {
19 | case Some(value) => if (value.equals(d.toSimpleString)) return Some(rc)
20 | case None => return Some(rc)
21 | }
22 | }
23 | }
24 | None
25 | }
26 | }
27 |
28 | object LogConfig {
29 | def default(): LogConfig = LogConfig(
30 | isBlackList = true,
31 | includeStore = false, includeHeap = false, includeOldHeap = false, includePcs = false,
32 | List())
33 | }
34 |
35 | case class RecordConfig(kind: String, value: Option[String])
36 |
37 | object LogConfigProtocol extends DefaultJsonProtocol {
38 |
39 | // recordConfigFormat has to appear before logConfigFormat!
40 | implicit val recordConfigFormat = jsonFormat2(RecordConfig.apply)
41 | implicit val logConfigFormat = jsonFormat6(LogConfig.apply)
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/scala/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper
8 |
9 | import scala.language.implicitConversions
10 |
11 | package object silicon {
12 | type TriggerSet[T] = Seq[T]
13 | type TriggerSets[T] = Seq[TriggerSet[T]]
14 |
15 | /* Immutable collections with a deterministic iteration order */
16 |
17 | type Map[K, +V] = scala.collection.immutable.TreeSeqMap[K, V]
18 | val Map = scala.collection.immutable.TreeSeqMap
19 |
20 | @inline
21 | def toMap[K, V](it: Iterable[(K, V)]): Map[K, V] = Map.empty ++ it
22 |
23 | type Stack[+E] = Seq[E]
24 | val Stack = List
25 |
26 | /* Mutable collections with a deterministic iteration order */
27 |
28 | type MList[A] = collection.mutable.ListBuffer[A]
29 | val MList = collection.mutable.ListBuffer
30 |
31 | type MSet[A] = collection.mutable.LinkedHashSet[A]
32 | val MSet = collection.mutable.LinkedHashSet
33 |
34 | type MMap[K, V] = collection.mutable.LinkedHashMap[K, V]
35 | val MMap = collection.mutable.LinkedHashMap
36 |
37 | type MStack[A] = collection.immutable.List[A]
38 | val MStack = collection.immutable.List
39 |
40 | /* Implicits converting from Predef.Map/Set to the Map/Set types defined above */
41 |
42 | object implicits {
43 | @inline
44 | implicit def predefMapToMap[K, V](map: Predef.Map[K, V]): Map[K, V] = Map.empty ++ map
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/scala/extensions/TryBlockStmt.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2020 ETH Zurich.
6 |
7 | package viper.silicon.extensions
8 |
9 | import viper.silver.ast._
10 | import viper.silver.ast.pretty.PrettyPrintPrimitives
11 | import viper.silver.parser.{NameAnalyser, PExtender, PStmt, Translator, TypeChecker, PKw, PKeywordStmt, PReserved}
12 |
13 | /** Keyword used to define `try` statement. */
14 | case object PTryKeyword extends PKw("try") with PKeywordStmt
15 |
16 | final case class PTryBlock(kw: PReserved[PTryKeyword.type], body: PStmt)(val pos: (Position, Position) = (NoPosition, NoPosition)) extends PExtender with PStmt {
17 |
18 | override def translateStmt(translator: Translator): Stmt = {
19 | TryBlock(translator.stmt(body))(translator.liftPos(this))
20 | }
21 |
22 | override def typecheck(typeChecker: TypeChecker, nameAnalyser: NameAnalyser): Option[Seq[String]] = {
23 | typeChecker.check(body)
24 |
25 | None
26 | }
27 | }
28 |
29 | final case class TryBlock(body: Stmt)
30 | (val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos)
31 | extends ExtensionStmt {
32 |
33 | def extensionSubnodes: Seq[Node] = Seq(body)
34 |
35 | def prettyPrint: PrettyPrintPrimitives#Cont = {
36 | import viper.silver.ast.pretty.FastPrettyPrinter._
37 |
38 | text("try") <+> showBlock(body)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/utils/patches/programmatically-change-logback-pattern.diff:
--------------------------------------------------------------------------------
1 | diff -r 19832d947290 src/main/scala/Silicon.scala
2 | --- a/src/main/scala/Silicon.scala Wed Jun 07 11:46:54 2017 +0200
3 | +++ b/src/main/scala/Silicon.scala Wed Jun 07 22:31:49 2017 +0200
4 | @@ -118,6 +118,8 @@
5 | lifetimeState = LifetimeState.Configured
6 |
7 | _config = new Config(args)
8 | +
9 | + setLogLevelsFromConfig()
10 | }
11 |
12 | def debugInfo(debugInfo: Seq[(String, Any)]) { this.debugInfo = debugInfo }
13 | @@ -132,8 +134,6 @@
14 |
15 | lifetimeState = LifetimeState.Started
16 |
17 | - setLogLevelsFromConfig()
18 | -
19 | verifier = new DefaultMainVerifier(config)
20 | verifier.start()
21 | }
22 | @@ -304,9 +304,14 @@
23 | }
24 |
25 | private def setLogLevelsFromConfig() {
26 | - val logger = LoggerFactory.getLogger(this.getClass.getPackage.getName).asInstanceOf[Logger]
27 | + val logger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]
28 | logger.setLevel(Level.toLevel(config.logLevel()))
29 |
30 | + val appender = logger.getAppender("STDOUT").asInstanceOf[ch.qos.logback.core.ConsoleAppender[_]]
31 | + val encoder = appender.getEncoder.asInstanceOf[ch.qos.logback.classic.encoder.PatternLayoutEncoder]
32 | + encoder.setPattern("%-7([%highlight(%level)]) %msg%n")
33 | + encoder.start() /* Apparently required for setPattern to have any effect */
34 | +
35 | config.logger.foreach { case (loggerName, level) =>
36 | val logger = LoggerFactory.getLogger(loggerName).asInstanceOf[Logger]
37 | logger.setLevel(Level.toLevel(level))
38 |
--------------------------------------------------------------------------------
/src/main/scala/verifier/WorkerVerifier.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.verifier
8 |
9 | import viper.silicon.supporters._
10 | import viper.silver.ast
11 | import viper.silver.components.StatefulComponent
12 | import viper.silver.reporter.Reporter
13 |
14 | class WorkerVerifier(mainVerifier: MainVerifier,
15 | uniqueId: String,
16 | override val reporter: Reporter,
17 | override val debugMode: Boolean)
18 | extends BaseVerifier(Verifier.config, uniqueId)
19 | with DefaultMethodVerificationUnitProvider
20 | with DefaultCfgVerificationUnitProvider {
21 |
22 | private val statefulSubcomponents = List[StatefulComponent](
23 | methodSupporter,
24 | cfgSupporter
25 | )
26 |
27 | def verificationPoolManager: VerificationPoolManager = mainVerifier.verificationPoolManager
28 |
29 | override def openSymbExLogger(member: ast.Member): Unit = {
30 | symbExLog = mainVerifier.rootSymbExLogger.openMemberScope(member, decider.pcs)
31 | }
32 |
33 | /* Lifetime */
34 |
35 | override def start(): Unit = {
36 | super.start()
37 | statefulSubcomponents foreach (_.start())
38 | }
39 |
40 | override def reset(): Unit = {
41 | super.reset()
42 | statefulSubcomponents foreach (_.reset())
43 | }
44 |
45 | override def stop(): Unit = {
46 | super.stop()
47 | statefulSubcomponents foreach (_.stop())
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/SingleMergeRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.decider.PathConditionStack
11 | import viper.silicon.interfaces.state.{Chunk, NonQuantifiedChunk}
12 | import viper.silicon.state._
13 | import viper.silicon.state.terms.Term
14 | import viper.silver.ast
15 |
16 | class SingleMergeRecord(val destChunks: Seq[Chunk],
17 | val newChunks: Seq[Chunk],
18 | p: PathConditionStack) extends DataRecord {
19 | val value: ast.Node = null
20 | val state: State = null
21 | val pcs: InsertionOrderedSet[Term] = if (p != null) p.assumptions else null
22 |
23 | override val toTypeString: String = "single merge"
24 |
25 | override lazy val toSimpleString: String = {
26 | if (destChunks != null && newChunks != null) (destChunks ++ newChunks).mkString(" ")
27 | else "SingleMerge "
28 | }
29 |
30 | override lazy val toString: String = {
31 | if (destChunks != null && newChunks != null) {
32 | val newChunksString = newChunks.mkString(" ")
33 | if (newChunksString == "") {
34 | s"single merge ${destChunks.mkString(" ")} <="
35 | } else {
36 | s"single merge ${destChunks.mkString(" ")} <= $newChunksString"
37 | }
38 | } else {
39 | "SingleMerge "
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/resources/sortwrappers.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; Having (at least) the first axiom makes $SortWrappers.$S$To$Snap injective, which is
6 | ; necessary because Z3 otherwise won't know that an assumption such as
7 | ; IntToSnap(x) = IntToSnap(y)
8 | ; implies that
9 | ; x = y.
10 | (assert (forall ((x $T$)) (!
11 | (= x ($SortWrappers.$SnapTo$S$($SortWrappers.$S$To$Snap x)))
12 | :pattern (($SortWrappers.$S$To$Snap x))
13 | :qid |$Snap.$SnapTo$S$To$Snap|
14 | )))
15 | (assert (forall ((x $Snap)) (!
16 | (= x ($SortWrappers.$S$To$Snap($SortWrappers.$SnapTo$S$ x)))
17 | :pattern (($SortWrappers.$SnapTo$S$ x))
18 | :qid |$Snap.$S$To$SnapTo$S$|
19 | )))
20 |
21 | ; On several examples, e.g., AVLTree.iterative.sil, Z3 instantiates the sort
22 | ; wrapper axioms somewhat often. It might be possible to include the wrappers
23 | ; in the $Snap datatype by declaring the it as
24 | ;
25 | ; (declare-datatypes () (($Snap
26 | ; $Snap.unit
27 | ; ($SortWrappers.$RefTo$Snap ($SortWrappers.$SnapTo$Ref $Ref))
28 | ; ($Snap.combine ($Snap.first $Snap) ($Snap.second $Snap)))))
29 | ;
30 | ; Might be worth investigating some time.
31 | ;
32 | ; Another way of reducing the number of wrapper applications could be to
33 | ; overload the $Snap.combine function, which Z3 permits. E.g.,
34 | ;
35 | ; (declare-datatypes () (($Snap
36 | ; $Snap.unit
37 | ; ($Snap.combine ($Snap.first $Ref) ($Snap.second $Snap))
38 | ; ($Snap.combine ($Snap.first $Snap) ($Snap.second $Snap)))))
39 |
--------------------------------------------------------------------------------
/src/main/scala/logger/records/data/DataRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.data
8 |
9 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
10 | import viper.silicon.logger.LogConfig
11 | import viper.silicon.logger.records.{RecordData, SymbolicRecord}
12 | import viper.silicon.state.terms.Term
13 | import viper.silicon.utils
14 | import viper.silver.ast
15 | import viper.silver.ast.Positioned
16 |
17 | trait DataRecord extends SymbolicRecord {
18 | val value: ast.Node
19 | // TODO: It would be nicer to use the PathConditionStack instead of the
20 | // Decider's internal representation for the pcs.
21 | // However, the recording happens to early such that the wrong
22 | // PathConditionStack Object is stored when using the PathConditionStack
23 | // TODO: Oops.
24 | val pcs: InsertionOrderedSet[Term]
25 |
26 | override lazy val toString: String = {
27 | s"$toTypeString $toSimpleString"
28 | }
29 |
30 | override lazy val toSimpleString: String = {
31 | if (value != null) value.toString()
32 | else "null"
33 | }
34 |
35 | override def getData(config: LogConfig): RecordData = {
36 | val data = super.getData(config)
37 | value match {
38 | case posValue: ast.Node with Positioned => data.pos = Some(utils.ast.sourceLineColumn(posValue))
39 | case _ =>
40 | }
41 | if (pcs != null && config.includePcs) {
42 | data.pcs = Some(pcs)
43 | }
44 | data
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/resources/field_value_functions_axioms.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; The axioms are parametric
6 | ; - $FLD$ is a Silver field name
7 | ; - $S$ is the sort corresponding to the type of the field
8 | ; - $T$ is the sanitized name of the sort corresponding to the type of the field
9 |
10 | ; ATTENTION: The triggers mention the sort wrappers introduced for FVFs.
11 | ; The axiom therefore needs to be emitted after the sort wrappers have
12 | ; been emitted.
13 |
14 | (assert (forall ((vs $FVF<$FLD$>) (ws $FVF<$FLD$>)) (!
15 | (=>
16 | (and
17 | (Set_equal ($FVF.domain_$FLD$ vs) ($FVF.domain_$FLD$ ws))
18 | (forall ((x $Ref)) (!
19 | (=>
20 | (Set_in x ($FVF.domain_$FLD$ vs))
21 | (= ($FVF.lookup_$FLD$ vs x) ($FVF.lookup_$FLD$ ws x)))
22 | :pattern (($FVF.lookup_$FLD$ vs x) ($FVF.lookup_$FLD$ ws x))
23 | :qid |qp.$FVF<$FLD$>-eq-inner|
24 | )))
25 | (= vs ws))
26 | :pattern (($SortWrappers.$FVF<$FLD$>To$Snap vs) ($FVF.has_domain_$FLD$ vs)
27 | ($SortWrappers.$FVF<$FLD$>To$Snap ws) ($FVF.has_domain_$FLD$ ws)
28 | )
29 | :qid |qp.$FVF<$FLD$>-eq-outer|
30 | )))
31 |
32 | (assert (forall ((r $Ref) (pm $FPM)) (!
33 | ($Perm.isValidVar ($FVF.perm_$FLD$ pm r))
34 | :pattern (($FVF.perm_$FLD$ pm r))
35 | :qid |qp.$FVF<$FLD$>-validvar|)))
36 |
37 | (assert (forall ((r $Ref) (f $S$)) (!
38 | (= ($FVF.loc_$FLD$ f r) true)
39 | :pattern (($FVF.loc_$FLD$ f r))
40 | :qid |qp.$FVF<$FLD$>-loc|)))
41 |
--------------------------------------------------------------------------------
/src/main/resources/predicate_snap_functions_axioms.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; The axioms are parametric
6 | ; - $PRD$ is a Silver predicate name
7 | ; - $S$ is the sort corresponding to the type of the field
8 |
9 | ; ATTENTION: The triggers mention the sort wrappers introduced for PSFs.
10 | ; The axiom therefore needs to be emitted after the sort wrappers have
11 | ; been emitted.
12 |
13 | (assert (forall ((vs $PSF<$PRD$>) (ws $PSF<$PRD$>)) (!
14 | (=>
15 | (and
16 | (Set_equal ($PSF.domain_$PRD$ vs) ($PSF.domain_$PRD$ ws))
17 | (forall ((x $Snap)) (!
18 | (=>
19 | (Set_in x ($PSF.domain_$PRD$ vs))
20 | (= ($PSF.lookup_$PRD$ vs x) ($PSF.lookup_$PRD$ ws x)))
21 | ; :pattern ((Set_in x ($PSF.domain_$PRD$ vs)))
22 | :pattern (($PSF.lookup_$PRD$ vs x) ($PSF.lookup_$PRD$ ws x))
23 | :qid |qp.$PSF<$PRD$>-eq-inner|
24 | )))
25 | (= vs ws))
26 | :pattern (($SortWrappers.$PSF<$PRD$>To$Snap vs) ($PSF.has_domain_$PRD$ vs)
27 | ($SortWrappers.$PSF<$PRD$>To$Snap ws) ($PSF.has_domain_$PRD$ ws)
28 | ; ($PSF.after_$PRD$ vs ws)
29 | )
30 | :qid |qp.$PSF<$PRD$>-eq-outer|
31 | )))
32 |
33 | (assert (forall ((s $Snap) (pm $PPM)) (!
34 | ($Perm.isValidVar ($PSF.perm_$PRD$ pm s))
35 | :pattern (($PSF.perm_$PRD$ pm s))
36 | :qid |qp.$PSF<$PRD$>-validvar|)))
37 |
38 | (assert (forall ((s $Snap) (f $S$)) (!
39 | (= ($PSF.loc_$PRD$ f s) true)
40 | :pattern (($PSF.loc_$PRD$ f s))
41 | :qid |qp.$PSF<$PRD$>-loc|)))
42 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_ImpureBranching.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | field f: Int
5 | field g: Int
6 |
7 | predicate P(b: Bool, x: Ref) {
8 | b ? acc(x.f) : acc(x.g)
9 | }
10 |
11 | method test1(b: Bool, x: Ref)
12 | ensures acc(P(b, x))
13 | {
14 | inhale b ? acc(x.f) : acc(x.g)
15 |
16 | fold P(b, x)
17 | }
18 |
19 | method test2(b: Bool, x: Ref)
20 | ensures acc(P(b, x))
21 | {
22 | var a: Int
23 | inhale (b ==> acc(x.f)) && (!b ==> acc(x.g))
24 | a := 1
25 | fold P(b, x)
26 | }
27 |
28 | method test3(b: Bool, x: Ref)
29 | {
30 | var a: Int
31 | inhale (b ==> acc(x.f))
32 | a := 1
33 | }
34 |
35 | method test4(b: Bool, x:Ref)
36 | requires (b ==> acc(x.f))
37 | {
38 | var a: Int
39 | a := 1
40 | }
41 |
42 | method test5(b1: Bool, b2: Bool, x: Ref)
43 | {
44 | var a: Int
45 | inhale (b1 ==> acc(x.f))
46 | inhale (b2 ==> acc(x.f))
47 | a := 1
48 | }
49 |
50 | method test5a(b1: Bool, b2: Bool, x: Ref)
51 | {
52 | var a: Int
53 | if (b1) {
54 | inhale acc(x.f)
55 | }
56 | if (b2) {
57 | inhale acc(x.f)
58 | }
59 | a := 1
60 | }
61 |
62 | method test5b(b1: Bool, b2: Bool, x: Ref)
63 | {
64 | var a: Int
65 | inhale (b1 ? acc(x.f) : true)
66 | inhale (b2 ? acc(x.f) : true)
67 | a := 1
68 | }
69 |
70 | method test6(b1: Bool, b2: Bool, x: Ref)
71 | {
72 | var a: Int
73 | inhale (b1 ? acc(x.f) : acc(x.g))
74 | inhale (b2 ? acc(x.f) : acc(x.g))
75 | a := 1
76 | }
77 |
78 | method test7(b: Bool, x: Ref)
79 | {
80 | var a: Int
81 | inhale (b ? acc(x.f) : acc(x.g))
82 | a := 1
83 | }
84 |
85 | method test8(b: Bool, x: Ref)
86 | {
87 | var a: Int
88 | inhale (true && true && true && (b ? acc(x.f) : acc(x.g)))
89 | a := 1
90 | }
--------------------------------------------------------------------------------
/src/test/scala/ConcurrentInstantiationTests.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | import java.util.concurrent.Executors
10 |
11 | import org.scalatest.funsuite.AnyFunSuite
12 | import viper.silicon.Silicon
13 |
14 | import scala.concurrent.duration._
15 | import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor, Future}
16 |
17 | /** See also Silicon issue #315. */
18 | class ConcurrentInstantiationTests extends AnyFunSuite {
19 | test("ConcurrentInstantiationTest1") {
20 | implicit val ec: ExecutionContextExecutor =
21 | ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
22 |
23 | val numTasks = 10
24 |
25 | val tasks: Seq[Future[Unit]] = for (_ <- 1 to numTasks) yield Future {
26 | val verifier = new Silicon()
27 | verifier.parseCommandLine(Seq("--logLevel", "ALL", "dummy-program.sil"))
28 | }
29 |
30 | val aggregated: Future[Seq[Unit]] = Future.sequence(tasks)
31 |
32 | Await.result(aggregated, Duration.create("20s"))
33 | }
34 |
35 | test("ConcurrentInstantiationTest2") {
36 | implicit val ec: ExecutionContextExecutor =
37 | ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
38 |
39 | val numTasks = 10
40 |
41 | val tasks: Seq[Future[Unit]] = for (_ <- 1 to numTasks) yield Future {
42 | val verifier = new Silicon()
43 | verifier.parseCommandLine(Seq("dummy-program.sil"))
44 | verifier.start()
45 | }
46 |
47 | val aggregated: Future[Seq[Unit]] = Future.sequence(tasks)
48 |
49 | Await.result(aggregated, Duration.create("20s"))
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/resources/preamble.smt2:
--------------------------------------------------------------------------------
1 | ; This Source Code Form is subject to the terms of the Mozilla Public
2 | ; License, v. 2.0. If a copy of the MPL was not distributed with this
3 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | ; Requires Z3 >= 4.3.2
6 |
7 | ; ATTENTION: Continuing multi-line statements must be indented with at least
8 | ; one tab or two spaces. All other lines must not start with tabs
9 | ; or more than one space.
10 |
11 | ; --- Snapshots ---
12 |
13 | (declare-datatypes (($Snap 0)) ((
14 | ($Snap.unit)
15 | ($Snap.combine ($Snap.first $Snap) ($Snap.second $Snap)))))
16 |
17 | ; --- References ---
18 |
19 | (declare-sort $Ref 0)
20 | (declare-const $Ref.null $Ref)
21 |
22 | ; --- Permissions ---
23 |
24 | (declare-sort $FPM 0)
25 | (declare-sort $PPM 0)
26 | (define-sort $Perm () Real)
27 |
28 | (define-const $Perm.Write $Perm 1.0)
29 | (define-const $Perm.No $Perm 0.0)
30 |
31 | (define-fun $Perm.isValidVar ((p $Perm)) Bool
32 | (<= $Perm.No p))
33 |
34 | (define-fun $Perm.isReadVar ((p $Perm)) Bool
35 | (and ($Perm.isValidVar p)
36 | (not (= p $Perm.No))))
37 |
38 | ; min function for permissions
39 | (define-fun $Perm.min ((p1 $Perm) (p2 $Perm)) Real
40 | (ite (<= p1 p2) p1 p2))
41 |
42 | ; --- Sort wrappers ---
43 |
44 | ; Sort wrappers are no longer part of the static preamble. Instead, they are
45 | ; emitted as part of the program-specific preamble.
46 |
47 | ; --- Math ---
48 |
49 | ;function Math#min(a: int, b: int): int;
50 | (define-fun $Math.min ((a Int) (b Int)) Int
51 | (ite (<= a b) a b))
52 |
53 | ;function Math#clip(a: int): int;
54 | (define-fun $Math.clip ((a Int)) Int
55 | (ite (< a 0) 0 a))
56 |
57 | ; --- End static preamble ---
58 |
59 | ; (get-proof "stdout")
60 | ; (get-info :all-statistics)
61 |
62 | ; (push)
63 | ; (check-sat)
64 | ; (pop)
65 |
--------------------------------------------------------------------------------
/src/main/scala/interfaces/Preamble.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.interfaces
8 |
9 | import viper.silver.ast
10 | import viper.silver.components.StatefulComponent
11 | import viper.silicon.interfaces.decider.ProverLike
12 |
13 | trait PreambleReader[I, O] {
14 | def readPreamble(resource: I): Iterable[O]
15 | def readParametricPreamble(resource: String, substitutions: Map[I, O]): Iterable[O]
16 |
17 | def emitPreamble(preamble: Iterable[O], sink: ProverLike, isOptions: Boolean): Unit
18 |
19 | def emitPreamble(resource: I, sink: ProverLike, isOptions: Boolean): Unit = {
20 | emitPreamble(readPreamble(resource), sink, isOptions)
21 | }
22 |
23 | def emitParametricPreamble(resource: String, substitutions: Map[I, O], sink: ProverLike): Unit
24 | }
25 |
26 | trait PreambleContributor[+SO, +SY, +AX] extends StatefulComponent {
27 | def analyze(program: ast.Program): Unit
28 |
29 | def sortsAfterAnalysis: Iterable[SO]
30 | def declareSortsAfterAnalysis(sink: ProverLike): Unit
31 |
32 | def declareSymbolsAfterAnalysis(sink: ProverLike): Unit
33 |
34 | def emitAxiomsAfterAnalysis(sink: ProverLike): Unit
35 | }
36 |
37 | trait VerifyingPreambleContributor[+SO, +SY, +AX, U <: ast.Node]
38 | extends PreambleContributor[SO, SY, AX]
39 | with VerificationUnit[U] {
40 |
41 | def sortsAfterVerification: Iterable[SO]
42 | def declareSortsAfterVerification(sink: ProverLike): Unit
43 |
44 | def symbolsAfterVerification: Iterable[SY]
45 | def declareSymbolsAfterVerification(sink: ProverLike): Unit
46 |
47 | def axiomsAfterVerification: Iterable[AX]
48 | def emitAxiomsAfterVerification(sink: ProverLike): Unit
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/scala/supporters/qps/PredicateSnapGenerator.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.supporters.qps
8 |
9 | import viper.silver.ast
10 | import viper.silver.ast.{Predicate, Program}
11 | import viper.silicon.Map
12 | import viper.silicon.state.terms.{Var, sorts}
13 | import viper.silicon.state.{Identifier, SymbolConverter, terms}
14 | import viper.silver.components.StatefulComponent
15 | import viper.silicon.supporters.SnapshotSupporter
16 |
17 | class PredicateSnapGenerator(symbolConverter: SymbolConverter, snapshotSupporter: SnapshotSupporter)
18 | extends StatefulComponent {
19 |
20 | var snapMap: Map[String, terms.Sort] = Map()
21 | var formalVarMap: Map[String, Seq[terms.Var]] = Map()
22 |
23 | def setup(program:Program): Unit =
24 | program visit {
25 | case ast.PredicateAccess(_, predname) =>
26 | val predicate = program.findPredicate(predname)
27 | val sort = predname -> predicate.body.map(snapshotSupporter.optimalSnapshotSort(_, program)._1).getOrElse(terms.sorts.Snap)
28 | val formalArgs:Seq[Var] = predicate.formalArgs.map(formalArg => Var(Identifier(formalArg.name), symbolConverter.toSort(formalArg.typ), false))
29 | formalVarMap += predname -> formalArgs
30 | snapMap += sort
31 | }
32 |
33 | def getSnap(predicate:Predicate): (terms.Sort, Boolean) =
34 | if (snapMap.contains(predicate.name)) {
35 | (snapMap(predicate.name), true)
36 | } else {
37 | (sorts.Snap, false)
38 | }
39 |
40 | /* Lifecycle */
41 |
42 | def start(): Unit = {}
43 |
44 | def reset(): Unit = {
45 | snapMap = Map.empty
46 | formalVarMap = Map.empty
47 | }
48 |
49 | def stop(): Unit = {}
50 | }
51 |
--------------------------------------------------------------------------------
/common/src/main/scala/config/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common
8 |
9 | import java.util.{Comparator, Scanner}
10 |
11 | package object config {
12 | def wildcardToRegex(str: String) =
13 | str.replace(".", "\\.")
14 | .replace("?", ".?")
15 | .replace("*", ".*?")
16 | .replace("$", "\\$")
17 |
18 | /* Inspired by http://sambarrow.com/compare-version-string-in-scala-java/ */
19 | object VersionComparator extends Comparator[String] {
20 | override def compare(version1: String, version2: String): Int = {
21 | val scanner1 = new Scanner(version1)
22 | val scanner2 = new Scanner(version2)
23 |
24 | scanner1.useDelimiter("\\.")
25 | scanner2.useDelimiter("\\.")
26 |
27 | while (scanner1.hasNextInt && scanner2.hasNextInt) {
28 | val component1 = scanner1.nextInt
29 | val component2 = scanner2.nextInt
30 |
31 | if (component1 > component2)
32 | return 1
33 | else if (component1 < component2)
34 | return -1
35 | }
36 |
37 | if (scanner1.hasNextInt) 1
38 | else if (scanner2.hasNextInt) -1
39 | else 0
40 | }
41 | }
42 |
43 | final case class Version(version: String) {
44 | def >(other: Version) = VersionComparator.compare(version, other.version) == 1
45 | def >=(other: Version) = VersionComparator.compare(version, other.version) >= 0
46 | def <(other: Version) = VersionComparator.compare(version, other.version) == -1
47 | def <=(other: Version) = VersionComparator.compare(version, other.version) <= 0
48 | def ==(other: Version) = version == other.version
49 | def ^(other: Version) = version.startsWith(s"$other.") || this == other
50 |
51 | override val toString = version
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/jonas_viktor.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 |
5 | // first version of the example
6 |
7 | domain ArrayDomain {}
8 |
9 | field val_int: Int
10 | field val_ref: Ref
11 |
12 | function idx_into(a: ArrayDomain, a_len: Int): Int
13 | function array_len(a: ArrayDomain): Int
14 | function to_domain(self: Ref): ArrayDomain
15 | requires acc(Array(self), read$())
16 |
17 | function read$(): Perm
18 | ensures none < result
19 | ensures result < write
20 |
21 | predicate Array(self: Ref)
22 | predicate usize(self: Ref) {
23 | acc(self.val_int, write)
24 | }
25 |
26 | method foo() {
27 | var a: Ref
28 | var a_len: Int
29 | var _3: Ref
30 | var unknown: Ref
31 | var i: Ref
32 | inhale acc(a.val_ref, write) && acc(Array(a.val_ref), write)
33 |
34 | inhale acc(_3.val_ref, write) && acc(usize(unknown), read$()) // <- removing this makes it pass
35 |
36 | exhale acc(a.val_ref, read$())
37 |
38 | inhale acc(usize(i), write) && acc(a.val_ref, read$())
39 |
40 | inhale (unfolding acc(usize(i), write) in
41 | (forall q: Int :: { idx_into(to_domain(a.val_ref), q) }
42 | !(q < i.val_int) ||
43 | idx_into(to_domain(a.val_ref), q) <=
44 | idx_into(to_domain(a.val_ref), i.val_int)))
45 |
46 | assert (unfolding acc(usize(i), write) in
47 | (forall q: Int :: { idx_into(to_domain(a.val_ref), q) }
48 | !(q < i.val_int) ||
49 | idx_into(to_domain(a.val_ref), q) <=
50 | idx_into(to_domain(a.val_ref), i.val_int)))
51 | }
52 |
53 |
54 | // second version of the example
55 |
56 | function holds(a: Ref, b: Int): Bool
57 |
58 | method foo2() {
59 | var a: Ref
60 | var _3: Ref
61 |
62 | inhale acc(a.val_ref, write)
63 |
64 | inhale acc(_3.val_ref, write) // <- removing this makes it pass
65 |
66 | exhale acc(a.val_ref, 1 / 2)
67 | inhale acc(a.val_ref, 1 / 2)
68 |
69 | inhale forall q: Int :: holds(a.val_ref, q)
70 | assert forall q: Int :: holds(a.val_ref, q)
71 | }
--------------------------------------------------------------------------------
/src/main/scala/logger/records/structural/BranchingRecord.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.logger.records.structural
8 |
9 | import viper.silicon.logger.records.SymbolicRecord
10 | import viper.silicon.state.terms.Term
11 | import viper.silver.ast.Exp
12 |
13 | class BranchingRecord(possibleBranchesCount: Int, val condition: Option[Term], val conditionExp: Option[Exp]) extends StructuralRecord {
14 | private var currentBranchIndex = 0
15 | private val branches: Vector[BranchInfo] = Vector.tabulate(possibleBranchesCount)(_ => new BranchInfo())
16 |
17 | def getCurrentBranch: BranchInfo = {
18 | assert(0 <= currentBranchIndex && currentBranchIndex < branches.length)
19 | branches(currentBranchIndex)
20 | }
21 |
22 | def appendLog(r: SymbolicRecord): Unit =
23 | getCurrentBranch.records :+= r
24 |
25 | def markReachable(): Unit = {
26 | getCurrentBranch.isReachable = true
27 | getCurrentBranch.startTimeMs = System.currentTimeMillis()
28 | }
29 |
30 | def switchToNextBranch(): Unit = {
31 | currentBranchIndex = currentBranchIndex + 1
32 | }
33 |
34 | def getBranches: Vector[Seq[SymbolicRecord]] = {
35 | branches.map(log => log.records)
36 | }
37 |
38 | def getBranchInfos: Vector[BranchInfo] = {
39 | branches
40 | }
41 |
42 | def isReachable(branchIndex: Int): Boolean = {
43 | assert(branchIndex < branches.length)
44 | branches(branchIndex).isReachable
45 | }
46 |
47 | override val toTypeString: String = "branching"
48 |
49 | override lazy val toSimpleString: String = {
50 | condition match {
51 | case Some(cond) => cond.toString()
52 | case _ => "null"
53 | }
54 | }
55 | }
56 |
57 | class BranchInfo {
58 | var isReachable: Boolean = false
59 | var startTimeMs: Long = 0
60 | var records: Seq[SymbolicRecord] = Seq[SymbolicRecord]()
61 | }
62 |
--------------------------------------------------------------------------------
/src/test/resources/issue387/va14.vpr:
--------------------------------------------------------------------------------
1 | field discriminant: Int
2 |
3 | field enum_None: Ref
4 |
5 | field enum_Some: Ref
6 |
7 | field f$0: Ref
8 |
9 | field f$elem: Ref
10 |
11 | field f$next: Ref
12 |
13 | field tuple_0: Ref
14 |
15 | field tuple_1: Ref
16 |
17 | field tuple_2: Ref
18 |
19 | field val_bool: Bool
20 |
21 | field val_int: Int
22 |
23 | field val_ref: Ref
24 |
25 |
26 | function contains(_pure_1: Ref, _pure_2: Int, _pure_3: Int): Bool
27 | requires acc(List(_pure_1))
28 | {
29 | (unfolding acc(List(_pure_1) ) in (
30 | unfolding acc(BoxList(_pure_1.f$next) ) in _pure_1.f$next.discriminant == 0)) &&
31 | (unfolding acc(List(_pure_1) ) in
32 | (unfolding acc(BoxList(_pure_1.f$next) ) in
33 | contains(_pure_1.f$next.enum_Some, _pure_2, _pure_3)))
34 | }
35 |
36 | predicate i32(self: Ref) {
37 | acc(self.val_int, write)
38 | }
39 |
40 | predicate isize(self: Ref) {
41 | acc(self.val_int, write)
42 | }
43 |
44 | predicate BoxyList(self: Ref) {
45 | acc(self.val_ref, write) && acc(List(self.val_ref), write)
46 | }
47 |
48 | predicate BoxList(self: Ref) {
49 | acc(self.discriminant, write) && (0 <= self.discriminant && self.discriminant <= 1 && (acc(self.enum_Some, write) && (acc(List(self.enum_Some), write))))
50 | }
51 |
52 | predicate BoxListSome(self: Ref) {
53 | acc(self.f$0, write) && acc(List(self.f$0), write)
54 | }
55 |
56 | predicate List(self: Ref) {
57 | acc(self.f$next, write) && (acc(BoxList(self.f$next), write) && (acc(self.f$elem, write) && acc(tuple3$i32$i32$i32(self.f$elem), write)))
58 | }
59 |
60 | predicate ref$BoxList(self: Ref) {
61 | acc(self.val_ref, write) && acc(BoxList(self.val_ref), write)
62 | }
63 |
64 | predicate ref$List(self: Ref) {
65 | acc(self.val_ref, write) && acc(List(self.val_ref), write)
66 | }
67 |
68 | predicate tuple0$(self: Ref) {
69 | true
70 | }
71 |
72 | predicate tuple3$i32$i32$i32(self: Ref) {
73 | acc(self.tuple_0, write) && (acc(i32(self.tuple_0), write) && (acc(self.tuple_1, write) && (acc(i32(self.tuple_1), write) && (acc(self.tuple_2, write) && acc(i32(self.tuple_2), write)))))
74 | }
75 |
76 | predicate DeadBorrowToken$(borrow: Int)
77 |
--------------------------------------------------------------------------------
/src/test/resources/frontends/gobra/global-const-4.gobra.vpr:
--------------------------------------------------------------------------------
1 | domain ConstantSimpleUntypedBoolConst_pkg_G {
2 |
3 | function constant_SimpleUntypedBoolConst_pkg_G(): Bool
4 |
5 | axiom get_constantSimpleUntypedBoolConst_pkg_G {
6 | constant_SimpleUntypedBoolConst_pkg_G() == true
7 | }
8 | }
9 |
10 | domain ConstantSimpleTypedBoolConst_pkg_G {
11 |
12 | function constant_SimpleTypedBoolConst_pkg_G(): Bool
13 |
14 | axiom get_constantSimpleTypedBoolConst_pkg_G {
15 | constant_SimpleTypedBoolConst_pkg_G() == true
16 | }
17 | }
18 |
19 | domain ConstantBoolExprConst_pkg_G {
20 |
21 | function constant_BoolExprConst_pkg_G(): Bool
22 |
23 | axiom get_constantBoolExprConst_pkg_G {
24 | constant_BoolExprConst_pkg_G() == true
25 | }
26 | }
27 |
28 | domain ConstantDoesDeclOrderMatter_pkg_G {
29 |
30 | function constant_DoesDeclOrderMatter_pkg_G(): Bool
31 |
32 | axiom get_constantDoesDeclOrderMatter_pkg_G {
33 | constant_DoesDeclOrderMatter_pkg_G() == true
34 | }
35 | }
36 |
37 | domain ConstantTypedIntConst_pkg_G {
38 |
39 | function constant_TypedIntConst_pkg_G(): Int
40 |
41 | axiom get_constantTypedIntConst_pkg_G {
42 | constant_TypedIntConst_pkg_G() == 42
43 | }
44 | }
45 |
46 | domain ConstantmultiConst1_pkg_G {
47 |
48 | function constant_multiConst1_pkg_G(): Int
49 |
50 | axiom get_constantmultiConst1_pkg_G {
51 | constant_multiConst1_pkg_G() == 1
52 | }
53 | }
54 |
55 | domain ConstantmultiConst2_pkg_G {
56 |
57 | function constant_multiConst2_pkg_G(): Bool
58 |
59 | axiom get_constantmultiConst2_pkg_G {
60 | constant_multiConst2_pkg_G() == false
61 | }
62 | }
63 |
64 | domain ConstantmultiConst3_pkg_G {
65 |
66 | function constant_multiConst3_pkg_G(): Int
67 |
68 | axiom get_constantmultiConst3_pkg_G {
69 | constant_multiConst3_pkg_G() == 3
70 | }
71 | }
72 |
73 | method client_pkg_F()
74 | {
75 |
76 | // decl
77 |
78 |
79 | // decl
80 |
81 |
82 | // assert DoesDeclOrderMatter_pkg_G && BoolExprConst_pkg_G
83 |
84 | assert constant_DoesDeclOrderMatter_pkg_G() && constant_BoolExprConst_pkg_G()
85 | label returnLabel
86 | }
--------------------------------------------------------------------------------
/src/test/resources/moreCompleteExhale/0604.vpr:
--------------------------------------------------------------------------------
1 | field f: Int
2 |
3 | method test01(x: Ref, y: Ref) {
4 | inhale acc(x.f, 1/2) && acc(y.f, 1/2)
5 | exhale acc(x.f, wildcard)
6 | //:: ExpectedOutput(exhale.failed:insufficient.permission)
7 | exhale acc(y.f, 1/2)
8 | }
9 |
10 | method test02(x: Ref, y: Ref) {
11 | inhale acc(x.f, 1/2) && acc(y.f, 1/2)
12 | //:: ExpectedOutput(exhale.failed:insufficient.permission)
13 | exhale acc(x.f, wildcard) && acc(y.f, 1/2)
14 | }
15 |
16 | method test03(x: Ref, y: Ref) {
17 | inhale acc(x.f, 1/3) && acc(y.f, 1/4)
18 | //:: ExpectedOutput(exhale.failed:insufficient.permission)
19 | exhale acc(x.f, wildcard) && acc(y.f, 1/4)
20 | }
21 |
22 | method test20(x: Ref, y: Ref) {
23 | inhale acc(x.f, 1/2) && acc(y.f, 1/2)
24 | exhale acc(y.f, 1/2) && acc(x.f, wildcard)
25 | }
26 |
27 | method test21(x: Ref, y: Ref) {
28 | inhale acc(x.f, 2/3) && acc(y.f, 1/2)
29 | assert x != y
30 | exhale acc(x.f, wildcard) && acc(y.f, 1/2)
31 | }
32 |
33 | method test30a(a: Ref, c: Int)
34 | requires acc(a.f, wildcard)
35 | ensures acc(a.f, wildcard)
36 | {
37 | if (0 < c) {
38 | test30a(a, c - 1)
39 | }
40 |
41 | assert(a.f == old(a.f))
42 | }
43 |
44 | method test30b(a: Ref) {
45 | inhale acc(a.f, wildcard)
46 | label L
47 |
48 | exhale acc(a.f, wildcard)
49 | inhale acc(a.f, wildcard)
50 |
51 | assert(a.f == old[L](a.f))
52 |
53 | exhale acc(a.f, wildcard)
54 | }
55 |
56 | method test30c(a: Ref) {
57 | inhale acc(a.f, wildcard)
58 | exhale acc(a.f, wildcard)
59 | assert acc(a.f, wildcard)
60 | }
61 |
62 | predicate P(x: Ref) { acc(x.f, wildcard) }
63 |
64 | method test40(x: Ref, y: Ref)
65 | requires acc(x.f, 1/2) && acc(y.f, 1/2)
66 | {
67 | fold P(x)
68 | exhale acc(x.f, perm(x.f))
69 | exhale acc(y.f, perm(y.f))
70 | unfold P(x)
71 | if (y == x) {
72 | assert y.f == old(y.f)
73 | }
74 | }
75 |
76 | method test50(x: Ref, y: Ref)
77 | {
78 | inhale acc(P(x), 1/2) && acc(P(y), 1/2)
79 | //:: ExpectedOutput(exhale.failed:insufficient.permission)
80 | exhale acc(P(x), wildcard) && acc(P(y), 1/2)
81 | }
82 |
--------------------------------------------------------------------------------
/src/test/resources/oldaxiomatization/example1.vpr:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | method test1()
5 | {
6 | var m : Map[Int, Bool] := Map()
7 | assert |Map[Int, Bool]()| == 0
8 | assert |m| == 0
9 |
10 | var d : Set[Int] := domain(m)
11 | assert d == Set()
12 |
13 | var r : Set[Bool] := range(m)
14 | assert |range(m)| == 0
15 | }
16 |
17 | method test2()
18 | {
19 | var m : Map[Int, Bool] := Map()
20 | m := m[2 := true]
21 |
22 | assert m[2]
23 | assert domain(m) == Set(2)
24 | assert range(m) == Set(true)
25 | }
26 |
27 | method test3()
28 | {
29 | var m : Map[Int, Int] := Map(2 := 12, 3 := 24, 4 := 36)
30 |
31 | assert |m| == 3
32 | assert m[2] == 12 && m[3] == 24 && m[4] == 36
33 | assert domain(m) == Set(4, 2, 3)
34 | assert range(m) == Set(24, 12, 36)
35 | assert 3 in m
36 | assert !(1 in m)
37 | }
38 |
39 | method test4()
40 | {
41 | var m1 : Map[Int, Bool] := Map(2 := false, 4 := true, 6 := false)
42 | var m2 : Map[Int, Bool] := Map(6 := false, 2 := false)
43 |
44 | assert !(4 in m2)
45 | assert m1 != m2
46 | assert m2[4 := true][4]
47 | assert m1 == m1[4 := true]
48 | assert m1 == m2[4 := true]
49 | }
50 |
51 | method test5(m : Map[Int, Map[Int, Bool]])
52 | requires forall i : Int :: { i in m } (0 <= i && i < 4 <==> i in m)
53 | requires forall i : Int, j : Int :: { j in m[i] } i in m ==> (0 <= j && j < 4 <==> j in m[i])
54 | requires forall i : Int, j : Int :: { m[i][j] } i in m && j in m ==> (m[i][j] <==> i == j)
55 | {
56 | assert m[2][2]
57 | assert !m[1][2]
58 | assert domain(m) == Set(0, 1, 2, 3)
59 | assert domain(m[0]) == Set(0, 1, 2, 3)
60 | assert m[2] == Map(0 := false, 1 := false, 2 := true, 3 := false)
61 | assert Map(0 := false, 1 := false, 2 := true, 3 := false) in range(m)
62 | }
63 |
64 | field val : Int
65 |
66 | method test6(m : Map[Int, Ref], x : Int)
67 | requires forall i: Int, j: Int :: { i in m, j in m } i in m && j in m && i != j ==> m[i] != m[j]
68 | requires forall k : Int :: { k in m } k in m ==> acc(m[k].val)
69 | {
70 | if (x in m)
71 | {
72 | m[x].val := m[x].val + x
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/src/main/scala/interfaces/state/Chunks.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.interfaces.state
8 |
9 | import viper.silicon
10 | import viper.silicon.resources.ResourceID
11 | import viper.silicon.state.terms.{Term, Var}
12 | import viper.silver.ast
13 |
14 | trait Chunk {
15 | def substitute(terms: silicon.Map[Term, Term]): Chunk
16 | }
17 | trait ChunkIdentifer
18 |
19 | trait GeneralChunk extends Chunk {
20 | val resourceID: ResourceID
21 | val id: ChunkIdentifer
22 | val perm: Term
23 | def applyCondition(newCond: Term, newCondExp: Option[ast.Exp]): GeneralChunk
24 | def permMinus(perm: Term, permExp: Option[ast.Exp]): GeneralChunk
25 | def permPlus(perm: Term, permExp: Option[ast.Exp]): GeneralChunk
26 |
27 | def permScale(perm: Term, permExp: Option[ast.Exp]): GeneralChunk
28 |
29 | val permExp: Option[ast.Exp]
30 | }
31 |
32 | trait NonQuantifiedChunk extends GeneralChunk {
33 | val args: Seq[Term]
34 | val argsExp: Option[Seq[ast.Exp]]
35 | val snap: Term
36 | override def applyCondition(newCond: Term, newCondExp: Option[ast.Exp]): NonQuantifiedChunk
37 | override def permMinus(perm: Term, permExp: Option[ast.Exp]): NonQuantifiedChunk
38 | override def permPlus(perm: Term, permExp: Option[ast.Exp]): NonQuantifiedChunk
39 | def withPerm(perm: Term, permExp: Option[ast.Exp]): NonQuantifiedChunk
40 | def withSnap(snap: Term, snapExp: Option[ast.Exp]): NonQuantifiedChunk
41 | }
42 |
43 | trait QuantifiedChunk extends GeneralChunk {
44 | val quantifiedVars: Seq[Var]
45 | val quantifiedVarExps: Option[Seq[ast.LocalVarDecl]]
46 |
47 | def snapshotMap: Term
48 | def valueAt(arguments: Seq[Term]): Term
49 | override def applyCondition(newCond: Term, newCondExp: Option[ast.Exp]): QuantifiedChunk
50 | override def permMinus(perm: Term, permExp: Option[ast.Exp]): QuantifiedChunk
51 | override def permPlus(perm: Term, permExp: Option[ast.Exp]): QuantifiedChunk
52 | def withSnapshotMap(snap: Term): QuantifiedChunk
53 | }
--------------------------------------------------------------------------------
/src/main/scala/rules/PermissionSupporter.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2021 ETH Zurich.
6 |
7 | package viper.silicon.rules
8 |
9 | import viper.silver.ast
10 | import viper.silver.verifier.PartialVerificationError
11 | import viper.silicon.interfaces.VerificationResult
12 | import viper.silicon.state.State
13 | import viper.silicon.state.terms.{Term, Var, perms}
14 | import viper.silicon.verifier.Verifier
15 | import viper.silver.verifier.reasons.{NegativePermission, NonPositivePermission}
16 |
17 | object permissionSupporter extends SymbolicExecutionRules {
18 | def assertNotNegative(s: State, tPerm: Term, ePerm: ast.Exp, ePermNew: Option[ast.Exp], pve: PartialVerificationError, v: Verifier)
19 | (Q: (State, Verifier) => VerificationResult)
20 | : VerificationResult = {
21 |
22 | tPerm match {
23 | case k: Var if s.constrainableARPs.contains(k) =>
24 | Q(s, v)
25 | case _ =>
26 | v.decider.assert(perms.IsNonNegative(tPerm)) {
27 | case true => Q(s, v)
28 | case false =>
29 | val assertExp = ePermNew.map(ep => perms.IsNonNegative(ep)(ep.pos, ep.info, ep.errT))
30 | createFailure(pve dueTo NegativePermission(ePerm), v, s, perms.IsNonNegative(tPerm), assertExp)
31 | }
32 | }
33 | }
34 |
35 | def assertPositive(s: State, tPerm: Term, ePerm: ast.Exp, pve: PartialVerificationError, v: Verifier)
36 | (Q: (State, Verifier) => VerificationResult)
37 | : VerificationResult = {
38 |
39 | tPerm match {
40 | case k: Var if s.constrainableARPs.contains(k) =>
41 | Q(s, v)
42 | case _ =>
43 | v.decider.assert(perms.IsPositive(tPerm)) {
44 | case true => Q(s, v)
45 | case false => createFailure(pve dueTo NonPositivePermission(ePerm), v, s, perms.IsPositive(tPerm), Option.when(withExp)(perms.IsPositive(ePerm)()))
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/scala/debugger/DebugParser.scala:
--------------------------------------------------------------------------------
1 | package viper.silicon.debugger
2 |
3 | import fastparse._
4 | import viper.silver.ast._
5 | import viper.silver.parser._
6 |
7 | import scala.collection.mutable
8 | class DebugParser extends FastParser {
9 |
10 | import FastParserCompanion.{PositionParsing, reservedKw}
11 |
12 | def versionedIdentifier[$: P]: P[Unit] = CharIn("A-Z", "a-z", "$_") ~~ CharIn("0-9", "A-Z", "a-z", "$_").repX ~~ CharIn("@") ~~ CharIn("0-9") ~~ CharIn("0-9").repX
13 |
14 | def versionedIdent[$: P]: P[String] = versionedIdentifier.!.opaque("versionedIdentifier")
15 |
16 | def versionedidnuse[$: P]: P[PVersionedIdnUseExp] = P(versionedIdent).map { case id =>
17 | val parts = id.split("@")
18 | ((pp: (Position, Position)) => PVersionedIdnUseExp(name = parts(0), version = parts(1))(pp))
19 | }.pos
20 |
21 | def debugOldLabel[$: P]: P[String] = (StringIn("debug") ~~ CharIn("@") ~~ CharIn("0-9", "A-Z", "a-z", "#$_.:").repX).!.opaque("debugOldLabel")
22 |
23 | def debugOldLabelUse[$: P]: P[PVersionedIdnUseExp] = P(debugOldLabel).map { case id =>
24 | val parts = id.split("@")
25 | ((pp: (Position, Position)) => PVersionedIdnUseExp(name = parts(0), version = parts(1))(pp))
26 | }.pos
27 |
28 | def debugOld[$: P]: P[PExp] = P(P(PKwOp.Old) ~ "[" ~ debugOldLabelUse ~ "](" ~ exp ~ ")").map {
29 | case (okw, a, b) => (pp: (Position, Position)) => PDebugLabelledOldExp(okw, a, b)(pp)
30 | }.pos
31 |
32 | ParserExtension.addNewExpAtStart(debugOld(_))
33 | ParserExtension.addNewExpAtStart(versionedidnuse(_))
34 | }
35 |
36 |
37 | class DebugTranslator(p: PProgram, override val members: mutable.Map[String, Node]) extends Translator(p) {
38 |
39 | override protected def expInternal(pexp: PExp, pos: PExp, info: Info): Exp = {
40 | pexp match {
41 | case pviu@PVersionedIdnUseExp(_, _, _) =>
42 | pexp.typ match {
43 | case null => sys.error("should not occur in type-checked program")
44 | case _ => LocalVarWithVersion(pviu.versionedName, ttyp(pexp.typ))(pos, info)
45 | }
46 | case PDebugLabelledOldExp(_, lbl, e) =>
47 | DebugLabelledOld(exp(e), lbl.versionedName)(pos, info)
48 | case _ => super.expInternal(pexp, pos, info)
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconTests.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | import java.nio.file.Path
10 |
11 | import viper.silicon.{Silicon, SiliconFrontend}
12 | import viper.silver.reporter.NoopReporter
13 | import viper.silver.testing.{LocatedAnnotation, MissingOutput, SilSuite, UnexpectedOutput}
14 | import viper.silver.verifier.Verifier
15 |
16 | class SiliconTests extends SilSuite {
17 | private val siliconTestDirectories =
18 | Seq("consistency")
19 |
20 | private val silTestDirectories =
21 | Seq("all",
22 | "quantifiedpermissions", "quantifiedpredicates", "quantifiedcombinations",
23 | "wands", "termination", "refute",
24 | "examples")
25 |
26 | val testDirectories: Seq[String] = siliconTestDirectories ++ silTestDirectories
27 |
28 | override def frontend(verifier: Verifier, files: Seq[Path]): SiliconFrontend = {
29 | require(files.length == 1, "tests should consist of exactly one file")
30 |
31 | val fe = new SiliconFrontend(NoopReporter)
32 | fe.init(verifier)
33 | fe.reset(files.head)
34 | fe
35 | }
36 |
37 | override def annotationShouldLeadToTestCancel(ann: LocatedAnnotation): Boolean = {
38 | ann match {
39 | case UnexpectedOutput(_, _, _, _, _, _) => true
40 | case MissingOutput(_, _, _, _, _, issue) => issue != 34
41 | case _ => false
42 | }
43 | }
44 |
45 | val silicon: Silicon = {
46 | val reporter = NoopReporter
47 | val debugInfo = ("startedBy" -> "viper.silicon.SiliconTests") :: Nil
48 | new Silicon(reporter, debugInfo)
49 | }
50 |
51 | def verifiers: Seq[Silicon] = Seq(silicon)
52 |
53 | override def configureVerifiersFromConfigMap(configMap: Map[String, Any]): Unit = {
54 | val args = Silicon.optionsFromScalaTestConfigMap(prefixSpecificConfigMap(configMap).getOrElse("silicon", Map()))
55 | silicon.parseCommandLine(commandLineArguments ++ args :+ Silicon.dummyInputFilename)
56 | }
57 |
58 | val commandLineArguments: Seq[String] =
59 | Seq("--timeout", "600" /* seconds */)
60 | }
61 |
--------------------------------------------------------------------------------
/.github/workflows/update-submodules.yml:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | #
5 | # Copyright (c) 2011-2022 ETH Zurich.
6 |
7 | name: Update Submodules
8 |
9 | on:
10 | workflow_dispatch: # allow to manually trigger this workflow
11 | schedule:
12 | - cron: '0 6 * * *' # run every day at 06:00 UTC
13 |
14 | jobs:
15 | # Update silver and create a PR if there are any changes
16 | update:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Check out the repo
20 | uses: actions/checkout@v4
21 | with:
22 | submodules: true
23 |
24 | - name: Get current commits
25 | run: echo "PREV_SILVER_REF=$(git -C silver rev-parse HEAD)" >> $GITHUB_ENV
26 |
27 | - name: Update Silver submodule
28 | run: git checkout master && git pull
29 | working-directory: silver
30 |
31 | - name: Get new commits
32 | run: echo "CUR_SILVER_REF=$(git -C silver rev-parse HEAD)" >> $GITHUB_ENV
33 |
34 | - name: Create PR body
35 | run: |
36 | if [[ "${{ env.PREV_SILVER_REF }}" != "${{ env.CUR_SILVER_REF }}" ]]; then
37 | echo 'PR_BODY_LINE=* Updates Silver from `${{ env.PREV_SILVER_REF }}` to `${{ env.CUR_SILVER_REF }}`.' >> $GITHUB_ENV
38 | else
39 | echo 'PR_BODY_LINE=' >> $GITHUB_ENV
40 | fi
41 |
42 | - name: Open a pull request
43 | id: pr
44 | uses: peter-evans/create-pull-request@v7
45 | if: (env.PREV_SILVER_REF != env.CUR_SILVER_REF)
46 | with:
47 | # Use viper-admin's token to workaround a restriction of GitHub.
48 | # See: https://github.com/peter-evans/create-pull-request/issues/48
49 | token: ${{ secrets.UPDATE_SILVER }}
50 | commit-message: Updates submodules
51 | title: Update Submodules
52 | branch: auto-update-submodules
53 | delete-branch: true
54 | labels: |
55 | automated pr
56 | body: |
57 | ${{ env.PR_BODY_LINE1 }}
58 |
59 | - name: Enable auto-merge of PR
60 | if: (env.PREV_SILVER_REF != env.CUR_SILVER_REF)
61 | run: gh pr merge --merge --auto "${{ steps.pr.outputs.pull-request-number }}"
62 | env:
63 | GH_TOKEN: ${{ secrets.UPDATE_SILVER }}
64 |
65 |
--------------------------------------------------------------------------------
/src/main/scala/state/Store.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.state
8 |
9 | import viper.silver.ast
10 | import viper.silicon.{Map, toMap}
11 | import viper.silicon.state.terms.Term
12 | import viper.silver.ast.AbstractLocalVar
13 |
14 | trait Store {
15 | def values: Map[ast.AbstractLocalVar, (Term, Option[ast.Exp])]
16 | def termValues: Map[ast.AbstractLocalVar, Term]
17 | def expValues: Map[ast.AbstractLocalVar, Option[ast.Exp]]
18 | def apply(key: ast.AbstractLocalVar): Term
19 | def get(key: ast.AbstractLocalVar): Option[Term]
20 | def getExp(key: ast.AbstractLocalVar): Option[ast.Exp]
21 | def +(kv: (ast.AbstractLocalVar, (Term, Option[ast.Exp]))): Store
22 | def +(other: Store): Store
23 | }
24 |
25 | trait StoreFactory[ST <: Store] {
26 | def apply(): ST
27 | def apply(bindings: Map[ast.AbstractLocalVar, (Term, Option[ast.Exp])]): ST
28 | def apply(pair: (ast.AbstractLocalVar, (Term, Option[ast.Exp]))): ST
29 | def apply(pairs: Iterable[(ast.AbstractLocalVar, (Term, Option[ast.Exp]))]): ST
30 | }
31 |
32 | object Store extends StoreFactory[MapBackedStore] {
33 | def apply() = new MapBackedStore(Map.empty)
34 | def apply(pair: (AbstractLocalVar, (Term, Option[ast.Exp]))) = new MapBackedStore(Map(pair))
35 | def apply(bindings: Map[AbstractLocalVar, (Term, Option[ast.Exp])]) = new MapBackedStore(toMap(bindings))
36 | def apply(bindings: Iterable[(AbstractLocalVar, (Term, Option[ast.Exp]))]) = new MapBackedStore(toMap(bindings))
37 | }
38 |
39 | final class MapBackedStore private[state] (map: Map[ast.AbstractLocalVar, (Term, Option[ast.Exp])])
40 | extends Store {
41 |
42 | val values = map
43 |
44 | def termValues = values.map{case (localVar, pair) => localVar -> pair._1}
45 | def expValues = values.map{case (localVar, pair) => localVar -> pair._2}
46 | def apply(key: ast.AbstractLocalVar) = map(key)._1
47 | def get(key: ast.AbstractLocalVar) = termValues.get(key)
48 | def getExp(key: ast.AbstractLocalVar) = expValues.get(key) match {
49 | case Some(e) => e
50 | case None => None
51 | }
52 | def +(entry: (ast.AbstractLocalVar, (Term, Option[ast.Exp]))) = new MapBackedStore(map + entry)
53 | def +(other: Store) = new MapBackedStore(map ++ other.values)
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/scala/supporters/CfgSupporter.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.supporters
8 |
9 | import com.typesafe.scalalogging.Logger
10 | import viper.silicon.decider.Decider
11 | import viper.silicon.interfaces._
12 | import viper.silicon.rules.{executionFlowController, executor}
13 | import viper.silicon.state.State.OldHeaps
14 | import viper.silicon.state.{State, Store}
15 | import viper.silicon.verifier.{Verifier, VerifierComponent}
16 | import viper.silver.ast
17 | import viper.silver.cfg.silver.SilverCfg
18 | import viper.silver.components.StatefulComponent
19 |
20 | trait CfgVerificationUnit extends VerificationUnit[SilverCfg]
21 |
22 | trait DefaultCfgVerificationUnitProvider extends VerifierComponent { v: Verifier =>
23 | def logger: Logger
24 | def decider: Decider
25 |
26 | object cfgSupporter extends CfgVerificationUnit with StatefulComponent {
27 | import executor._
28 |
29 | private var _units: Seq[SilverCfg] = _
30 |
31 | def analyze(program: ast.Program): Unit = {
32 | ???
33 | }
34 |
35 | def units = _units
36 |
37 | def verify(sInit: State, cfg: SilverCfg): Seq[VerificationResult] = {
38 | logger.debug("\n\n" + "-" * 10 + " CFG " + "-" * 10 + "\n")
39 | decider.prover.comment("%s CFG %s".format("-" * 10, "-" * 10))
40 |
41 | // SymbExLogger.insertMember(method, null, v.decider.pcs) TODO: Enable this.
42 |
43 | val g = Store()
44 |
45 | val s = sInit.copy(g = g,
46 | h = v.heapSupporter.getEmptyHeap(sInit.program),
47 | oldHeaps = OldHeaps(),
48 | methodCfg = cfg) // TODO: ???
49 |
50 | if (Verifier.config.printMethodCFGs()) {
51 | viper.silicon.common.io.toFile(
52 | cfg.toDot,
53 | new java.io.File(s"${Verifier.config.tempDirectory()}/CFG${System.identityHashCode(cfg)}.dot"))
54 | }
55 |
56 | val result = {
57 | executionFlowController.locally(s, v)((s3, v3) => {
58 | exec(s3, cfg, v3)((_, _) =>
59 | Success())}) }
60 |
61 | Seq(result)
62 | }
63 |
64 | /* Lifetime */
65 |
66 | def start(): Unit = {}
67 |
68 | def reset(): Unit = {
69 | _units = Seq.empty
70 | }
71 |
72 | def stop(): Unit = {}
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/scala/TriggerGeneratorTests.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | import org.scalatest.BeforeAndAfter
10 | import org.scalatest.funsuite.AnyFunSuite
11 | import viper.silicon.Config
12 | import viper.silicon.state.Identifier
13 | import viper.silicon.state.terms._
14 | import viper.silicon.verifier.Verifier
15 |
16 | class TriggerGeneratorTests extends AnyFunSuite with BeforeAndAfter {
17 | val triggerGenerator = new TriggerGenerator()
18 |
19 | before {
20 | Verifier.config = new Config(Seq())
21 | }
22 |
23 | test("Work in simple cases") {
24 | val i = Var(Identifier("i"), sorts.Int, false)
25 | val s = Var(Identifier("S"), sorts.Seq(sorts.Int), false)
26 | val t = SeqAt(s, i)
27 |
28 | assert(triggerGenerator.generateTriggerSetGroups(i :: Nil, t) match {
29 | case Seq((Seq(triggerGenerator.TriggerSet(Seq(`t`))), Seq())) => true
30 | case _ => false
31 | })
32 | }
33 |
34 | test("Fail in these cases") {
35 | val i = Var(Identifier("i"), sorts.Int, false)
36 | val s = Var(Identifier("S"), sorts.Seq(sorts.Int), false)
37 | val t = SeqAt(s, Plus(i, IntLiteral(1)))
38 |
39 | assert(triggerGenerator.generateTriggerSetGroups(i :: Nil, t).isEmpty)
40 | }
41 |
42 | // ignore should "not do stupid stuff" in {
43 | // val x = Var("x", sorts.Int)
44 | // val y = Var("y", sorts.Int)
45 | // val xs = Var("xs", sorts.Seq(sorts.Int))
46 | //
47 | // val lhs =
48 | // And(
49 | // SeqIn(SeqRanged(0, SeqLength(xs)), x),
50 | // SeqIn(SeqRanged(0, SeqLength(xs)), y),
51 | // SeqAt(xs, x) === SeqAt(xs, y))
52 | //
53 | // val rhs = x === y
54 | //
55 | //// val forall = Forall(x :: y :: Nil, Implies(lhs, rhs), Seq[Trigger]())
56 | //// println(forall)
57 | //
58 | // TriggerGenerator.generateTriggerGroups(x :: y :: Nil, Implies(lhs, rhs)) foreach { case (triggers, vars) =>
59 | // println(s"\ntriggers = ${triggers.mkString("\n ", "\n ", "")}")
60 | // println(s"\nvars = $vars")
61 | // }
62 | //
63 | // TriggerGenerator.generateStrictestTrigger(x :: y :: Nil, Implies(lhs, rhs)) foreach { case (triggers, vars) =>
64 | // println(s"\ntriggers = $triggers")
65 | // println(s"\nvars = $vars")
66 | // }
67 | // }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/scala/decider/SMTLib2PreambleReader.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.decider
8 |
9 | import java.io.FileNotFoundException
10 | import scala.io.Source
11 | import viper.silicon.interfaces.PreambleReader
12 | import viper.silicon.interfaces.decider.ProverLike
13 |
14 | class SMTLib2PreambleReader extends PreambleReader[String, String] {
15 | def readPreamble(resource: String): Iterable[String] = {
16 | val in = getClass.getResourceAsStream(resource)
17 |
18 | if (in == null)
19 | throw new FileNotFoundException(s"Cannot read preamble resource $resource")
20 |
21 | var lines =
22 | Source.fromInputStream(in)
23 | .getLines()
24 | .toList
25 | .filterNot(s => s.trim == "" || s.trim.startsWith(";"))
26 |
27 | in.close()
28 |
29 | var assertions = List[String]()
30 |
31 | /* Multi-line assertions are concatenated into a single string and
32 | * send to the prover, because prover.emit(str) expects Z3 to reply
33 | * to 'str' with success/error. But Z3 will only reply anything if 'str'
34 | * is a complete assertion.
35 | */
36 | while (lines.nonEmpty) {
37 | val part = (
38 | lines.head
39 | :: lines.tail.takeWhile(l => l.startsWith("\t") || l.startsWith(" ")))
40 |
41 | lines = lines.drop(part.size)
42 | assertions = part.mkString("\n") :: assertions
43 | }
44 |
45 | assertions.reverse
46 | }
47 |
48 | def readParametricPreamble(resource: String, substitutions: Map[String, String])
49 | : Iterable[String] = {
50 |
51 | val lines = readPreamble(resource)
52 | lines.map(line =>
53 | substitutions.foldLeft(line){case (lineAcc, (orig, repl)) =>
54 | lineAcc.replace(orig, repl)})
55 | }
56 |
57 | def emitPreamble(preamble: Iterable[String], sink: ProverLike, isOptions: Boolean): Unit = {
58 | if (isOptions)
59 | sink.emitSettings(preamble)
60 | else
61 | sink.emit(preamble)
62 | }
63 |
64 | def emitParametricPreamble(resource: String,
65 | substitutions: Map[String, String],
66 | sink: ProverLike)
67 | : Unit = {
68 |
69 | emitPreamble(readParametricPreamble(resource, substitutions), sink, false)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/utils/scripts/sum.scala:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | import java.io.{FileOutputStream, OutputStreamWriter, BufferedWriter}
5 | import scala.collection.mutable
6 | import scala.io.{Source, BufferedSource}
7 |
8 | /* Declarations */
9 |
10 | //[quantifier_instances] k!1813 : 1 : 0 : 1
11 |
12 | case class QIMessage(qid: String, count: Int)
13 |
14 | /* Functions */
15 |
16 | def filterQIMessages(source: BufferedSource): Iterator[QIMessage] = {
17 | val qiMessagePattern =
18 | """(?mx)\[quantifier_instances\] (.+?) : (\d+) : \d+ : \d+""".replace(" ", "\\s+").r
19 |
20 | source.getLines()
21 | .map(_.trim) /* Trim lines instead of pre/appending \s* to qiMessagePattern */
22 | .collect { case qiMessagePattern(id, count) => QIMessage(id, count.toInt) }
23 | }
24 |
25 | def sumIdentifierCounts(messages: Iterator[QIMessage]): (Long, Seq[(String, Int)], Long) = {
26 | val instantiations = mutable.HashMap[String, Int]()
27 | var totalInstantiations = 0L
28 | var messageCount = 0L
29 |
30 | messages foreach {m =>
31 | /* Count messages here because messages can only be traversed once, and
32 | * calling messages.size entails a traversal.
33 | */
34 | messageCount += 1
35 |
36 | val count = instantiations.getOrElseUpdate(m.qid, 0)
37 | instantiations.update(m.qid, count + m.count)
38 |
39 | totalInstantiations = totalInstantiations + m.count
40 | }
41 |
42 | val sortedInstantiations = instantiations.toSeq.sortWith((p1, p2) => p1._2 > p2._2) //.sortBy(p => p._2)
43 |
44 | (messageCount, sortedInstantiations, totalInstantiations)
45 | }
46 |
47 | def writeTo(instantiations: Seq[(String, Int)], sink: BufferedWriter) {
48 | instantiations.foreach { case (qid, count) =>
49 | sink.write("%-25s: %d".format(qid, count))
50 | sink.newLine()
51 | }
52 | }
53 |
54 | /* Script */
55 |
56 | if (args.length < 2) {
57 | println("Usage: sum ")
58 | } else {
59 | val inFilename = args(0)
60 | val source = Source.fromFile(inFilename)
61 | val messages = filterQIMessages(source)
62 | val (messageCount, instantiations, totalInstantiations) = sumIdentifierCounts(messages)
63 |
64 | val outFilename = args(1)
65 | val sink = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilename)))
66 | val sinkLines = writeTo(instantiations, sink)
67 | sink.close()
68 |
69 | println(s"Read $messageCount QI messages with $totalInstantiations QIs in total, wrote ${instantiations.size} counts back")
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/scala/SiliconCounterexampleVariablesTests.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2025 ETH Zurich.
6 |
7 | package viper.silicon.tests
8 |
9 | import viper.silicon.Silicon
10 | import viper.silver.testing.{CounterexampleComparison, CounterexampleVariablesTests, ExpectedCounterexample, ExpectedValuesCounterexampleAnnotation, OutputAnnotationId, TestCustomError, TestError}
11 | import viper.silicon.interfaces.SiliconVariableCounterexample
12 | import viper.silver.verifier.FailureContext
13 |
14 | import java.nio.file.Path
15 |
16 | class SiliconCounterexampleVariablesTests extends SiliconTests with CounterexampleVariablesTests {
17 |
18 | override def configureVerifiersFromConfigMap(configMap: Map[String, Any]): Unit = {
19 | val args = Silicon.optionsFromScalaTestConfigMap(prefixSpecificConfigMap(configMap).getOrElse("silicon", Map()))
20 | val additionalArgs = Seq("--counterexample=variables", "--exhaleMode=1")
21 |
22 | silicon.parseCommandLine(args ++ additionalArgs :+ Silicon.dummyInputFilename)
23 | }
24 |
25 | override def createExpectedValuesCounterexampleAnnotation(id: OutputAnnotationId, file: Path, forLineNr: Int, expectedCounterexample: ExpectedCounterexample): ExpectedValuesCounterexampleAnnotation =
26 | SiliconExpectedValuesCounterexampleAnnotation(id, file, forLineNr, expectedCounterexample)
27 | }
28 |
29 | /** represents an expected output (identified by `id`) with an associated (possibly partial) counterexample model */
30 | case class SiliconExpectedValuesCounterexampleAnnotation(id: OutputAnnotationId, file: Path, forLineNr: Int, expectedCounterexample: ExpectedCounterexample) extends
31 | ExpectedValuesCounterexampleAnnotation(id, file, forLineNr, expectedCounterexample) {
32 |
33 | def containsExpectedCounterexample(failureContext: FailureContext): Boolean =
34 | failureContext.counterExample match {
35 | case Some(silCounterexample: SiliconVariableCounterexample) => CounterexampleComparison.meetsExpectations(expectedCounterexample, silCounterexample.model)
36 | case _ => false
37 | }
38 |
39 | override def notFoundError: TestError = TestCustomError(s"Expected the following counterexample on line $forLineNr: $expectedCounterexample")
40 |
41 | override def withForLineNr(line: Int = forLineNr): ExpectedValuesCounterexampleAnnotation = SiliconExpectedValuesCounterexampleAnnotation(id, file, line, expectedCounterexample)
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/scala/state/FunctionPreconditionTransformer.scala:
--------------------------------------------------------------------------------
1 | package viper.silicon.state
2 |
3 | import viper.silicon.rules.functionSupporter
4 | import viper.silicon.state.terms.{And, App, Forall, HeapDepFun, Implies, Ite, Let, Literal, Not, Or, Quantification, Term, True}
5 | import viper.silver.ast
6 |
7 |
8 | /**
9 | * Given a term t, returns a new term tr(t) that expresses that all applications of heap-dependent functions are
10 | * well-defined (in particular, that the abstract functions that represent their preconditions hold).
11 | * In general, after checking that t is well-defined, it is sound to assume tr(t).
12 | *
13 | * I.e., given
14 | * fun(e1, ..., en)
15 | * where fun is a heap-dependent function with a precondition, it returns
16 | * tr(e1) && ... && tr(en) && fun%precondition(e1, ..., en)
17 | * where the tr(ei) terms express that all function applications in the argument terms are well-defined.
18 | *
19 | * For &&, ||, and ==>, the transformation takes into account short-circuit semantics:
20 | * If A && B is well-defined, that means that A is well-defined, and if A is true, then B is well-defined as well.
21 | * Thus, the transformation of A && B is tr(A) && (A ==> tr(B)).
22 | */
23 | object FunctionPreconditionTransformer {
24 | def transform(t: Term, p: ast.Program): Term = {
25 | val res = t match {
26 | case _:Literal => True
27 | case And(ts) => And(transform(ts.head, p), Implies(ts.head, transform(And(ts.tail), p)))
28 | case Or(ts) => And(transform(ts.head, p), Implies(Not(ts.head), transform(Or(ts.tail), p)))
29 | case Implies(t0, t1) => And(transform(t0, p), Implies(t0, transform(t1, p)))
30 | case Ite(t, t1, t2) => And(transform(t, p), Ite(t, transform(t1, p), transform(t2, p)))
31 | case Let(bindings, body) =>
32 | And(And(bindings.map(b => transform(b._2, p))), Let(bindings, transform(body, p)))
33 | case Quantification(_, vars, body, triggers, name, isGlobal, weight) =>
34 | val tBody = transform(body, p)
35 | if (tBody == True) {
36 | tBody
37 | } else {
38 | // We assume well-definedness for *all* possible values even for existential quantifiers
39 | // (since that is also what we check).
40 | Quantification(Forall, vars, tBody, triggers, name, isGlobal, weight)
41 | }
42 | case App(hdf@HeapDepFun(_, _, _), args) =>
43 | And(args.map(transform(_, p)) :+ App(functionSupporter.preconditionVersion(hdf), args))
44 | case other => And(other.subterms.map(transform(_, p)))
45 | }
46 | res
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/utils/scripts/tidy_smtlib.scala:
--------------------------------------------------------------------------------
1 | // Any copyright is dedicated to the Public Domain.
2 | // http://creativecommons.org/publicdomain/zero/1.0/
3 |
4 | import java.io.{BufferedWriter, OutputStreamWriter, FileOutputStream}
5 | import scala.io.{BufferedSource, Source}
6 | import scala.collection.mutable
7 |
8 | /* TODO: Add an option to move all Z3 declarations to the beginning of the output file.
9 | * On the one hand, it is nice to have all of them at the beginning so that they
10 | * don't clutter up the SMT-LIB code of interest. On the other hand, it might
11 | * sometimes aid debugging to know at which step a declaration has been made.
12 | *
13 | * TODO: Remove declarations that are not used in the remaining SMT-LIB code
14 | */
15 |
16 | /* Types */
17 |
18 | type Scope = mutable.ListBuffer[String]
19 | def Scope(elems: String*) = mutable.ListBuffer(elems: _*)
20 |
21 | type Scopes = mutable.Stack[Scope]
22 | def Scopes(elems: Scope*) = mutable.Stack(elems: _*)
23 |
24 | /* Functions */
25 |
26 | def tidyUp(source: BufferedSource): (Int, Scopes) = {
27 | val scopes = Scopes()
28 | var currentScope = Scope()
29 | var counter = 0
30 |
31 | source.getLines().foreach { sourceLine =>
32 | counter += 1
33 | val line = sourceLine.trim
34 |
35 | if (line.startsWith("(push")) {
36 | scopes.push(currentScope)
37 | currentScope = Scope()
38 | } else if (line.startsWith("(pop")) {
39 | val declarations = filterDeclarations(currentScope)
40 |
41 | currentScope = scopes.pop()
42 | currentScope ++= declarations
43 | } else {
44 | currentScope += sourceLine
45 | }
46 | }
47 |
48 | scopes.push(currentScope)
49 |
50 | (counter, scopes)
51 | }
52 |
53 | def writeTo(scopes: Scopes, sink: BufferedWriter): Int = {
54 | var counter = 0
55 |
56 | scopes.reverse.flatten.foreach { line =>
57 | counter += 1
58 |
59 | sink.write(line)
60 | sink.newLine()
61 | }
62 |
63 | counter
64 | }
65 |
66 | def filterDeclarations(scope: Scope): Scope = {
67 | scope.filter(_.startsWith("(declare-"))
68 | }
69 |
70 | /* Script */
71 |
72 | if (args.length < 2) {
73 | println("Usage: tidy_smtlib ")
74 | } else {
75 | val inFilename = args(0)
76 | val source = Source.fromFile(inFilename)
77 | val (sourceLines, scopes) = tidyUp(source)
78 |
79 | val outFilename = args(1)
80 | val sink = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFilename)))
81 | val sinkLines = writeTo(scopes, sink)
82 | sink.close()
83 |
84 | println(s"Read $sourceLines lines, wrote $sinkLines lines")
85 | }
86 |
--------------------------------------------------------------------------------
/common/src/main/scala/io/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.common
8 |
9 | import java.io.{
10 | File => JFile,
11 | PrintWriter => JPrintWriter,
12 | BufferedWriter => JBufferedWriter,
13 | FileWriter => JFileWriter}
14 | import java.nio.file.{Files, Paths}
15 |
16 | import org.apache.commons.io.FilenameUtils
17 |
18 | package object io {
19 | /**
20 | * Writes the `contents` to the given `file`. Existing content will be overwritten.
21 | *
22 | * @param contents The content to write.
23 | * @param file The file to which the content will be written.
24 | */
25 | def toFile(contents: String, file: JFile): Unit = {
26 | val sink = PrintWriter(file)
27 |
28 | sink.write(contents)
29 | sink.close()
30 | }
31 |
32 | /**
33 | * Creates a `java.io.PrintWriter` with `autoFlush` enabled that writes to the given `file`.
34 | * `File.mkdirs()` is called to ensure that the file path exists.
35 | *
36 | * @param file Is assumed to denote a file, not a directory.
37 | * @return The instantiated sink.
38 | */
39 | def PrintWriter(file: JFile, autoFlush: Boolean = true, append: Boolean = false): JPrintWriter = {
40 | val pf = file.getParentFile
41 | if (pf != null) pf.mkdirs()
42 |
43 | new JPrintWriter(new JBufferedWriter(new JFileWriter(file, append)), autoFlush)
44 | }
45 |
46 | def makeFilenameUnique(file: JFile,
47 | targetDirectory: Option[JFile] = None,
48 | newExtension: Option[String] = None)
49 | : JFile = {
50 |
51 | targetDirectory.foreach(d => assert(d.isDirectory, s"Expected a directory, but found $d"))
52 |
53 | val fileStr = file.toString
54 | val directory = targetDirectory.getOrElse(FilenameUtils.getFullPath(fileStr)).toString
55 | val baseName = FilenameUtils.getBaseName(fileStr)
56 | val extension = newExtension.getOrElse(FilenameUtils.getExtension(fileStr))
57 |
58 | var counter: Long = 0
59 | var uniqueBaseName = baseName
60 | var uniqueFile = Paths.get(directory, s"$uniqueBaseName.$extension")
61 |
62 | /* Note: Theoretically, this loop might not terminate */
63 | while (Files.exists(uniqueFile)) {
64 | counter += 1
65 | uniqueBaseName = baseName + counter
66 | uniqueFile = Paths.get(directory, s"$uniqueBaseName.$extension")
67 | }
68 |
69 | uniqueFile.toFile
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/test/scala/tests.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | import java.nio.file.{Path, Paths}
8 | import viper.silver.ast.Program
9 | import viper.silver.frontend.{SilFrontend, SilFrontendConfig, DefaultStates}
10 | import viper.silver.verifier.{AbstractError, AbstractVerificationError, VerificationResult, Verifier, Failure => SilFailure}
11 | import viper.silicon.Silicon
12 |
13 | package object tests {
14 | class DummyFrontend extends SilFrontend {
15 | def createVerifier(fullCmd: _root_.scala.Predef.String): Verifier =
16 | sys.error("Implementation missing")
17 |
18 | def configureVerifier(args: Seq[String]): SilFrontendConfig =
19 | sys.error("Implementation missing")
20 |
21 | def translate(silverFile: Path): (Option[Program], Seq[AbstractError]) = {
22 | _verifier = None
23 | _state = DefaultStates.Initialized
24 |
25 | reset(silverFile)
26 | runTo(Translation)
27 |
28 | //println(s"_program = ${_program}") /* Option[Program], set if parsing and translating worked */
29 | //println(s"_errors = ${_errors}") /* Seq[AbstractError], contains errors, if encountered */
30 |
31 | (_program, _errors)
32 | }
33 |
34 | override def verifier: Verifier = this._verifier.get
35 | }
36 |
37 | def instantiateFrontend(): SilFrontend = {
38 | val frontend = new DummyFrontend
39 |
40 | val backend = new Silicon(List("startedBy" -> s"Unit test ${this.getClass.getSimpleName}"))
41 | backend.parseCommandLine(List("--ignoreFile", "dummy.sil"))
42 | backend.start()
43 |
44 | frontend.init(backend)
45 |
46 | frontend
47 | }
48 |
49 | def loadProgram(filePrefix: String, fileName: String, frontend: SilFrontend): Program = {
50 | val testFile = getClass.getClassLoader.getResource(filePrefix + fileName + ".vpr")
51 | assert(testFile != null, s"File $filePrefix$fileName not found")
52 | val file = Paths.get(testFile.toURI)
53 |
54 | frontend.reset(file)
55 | frontend.runTo(frontend.Translation)
56 |
57 | frontend.translationResult
58 | }
59 |
60 | def verifyProgram(program: Program, frontend: SilFrontend): VerificationResult = {
61 | frontend.verifier.verify(program) match {
62 | case SilFailure(errors) =>
63 | SilFailure(errors.map {
64 | case a: AbstractVerificationError => a.transformedError()
65 | case rest => rest
66 | })
67 | case rest => rest
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/src/main/scala/reporting/package.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon
8 |
9 | import java.util.concurrent.ExecutionException
10 | import viper.silver.verifier.{AbortedExceptionally => VprAbortedExceptionally, Failure => VprFailure, Success => VprSuccess, VerificationResult => VprVerificationResult}
11 | import viper.silicon.interfaces.{Failure, Success, Unreachable, VerificationResult}
12 |
13 | package object reporting {
14 | /** Extract the root exception that has been wrapped in one or more `ExecutionException`s. */
15 | def unwrapExecutionExceptions(exception: ExecutionException): Throwable = {
16 | var cause: Throwable = exception
17 |
18 | do {
19 | cause = cause.getCause
20 | } while (cause.isInstanceOf[ExecutionException])
21 |
22 | cause
23 | }
24 |
25 | def exceptionToViperError(exception: Exception): Either[Error, (Exception, VprFailure)] = {
26 | val cause: Throwable = exception match {
27 | case ee: ExecutionException => reporting.unwrapExecutionExceptions(ee)
28 | case _ => exception
29 | }
30 |
31 | cause match {
32 | case ex: SiliconException =>
33 | Right((ex, VprFailure(Seq(ex.asViperError))))
34 | case ex: Exception =>
35 | Right((ex, VprFailure(Seq(VprAbortedExceptionally(ex)))))
36 | case error: Error =>
37 | Left(error)
38 | }
39 | }
40 |
41 | val noClassDefFoundErrorMessage: String = (
42 | "A NoClassDefFoundError occurred (see below). As an attempt of solving this "
43 | + "problem, please delete the file 'silicon_classpath.txt' (should be in Silicon's "
44 | + "home directory), recompile Silicon (if possible) and then execute Silicon again.")
45 |
46 | def convertToViperResult(result: VerificationResult): VprVerificationResult = {
47 | result match {
48 | case Success() | Unreachable() => VprSuccess
49 | case Failure(message, _) => VprFailure(Seq(message))
50 | }
51 | }
52 |
53 | def convertToViperResults(results: Seq[VerificationResult]): Seq[VprVerificationResult] =
54 | results.map(convertToViperResult)
55 |
56 | def condenseToViperResult(results: Seq[VerificationResult]): VprVerificationResult = {
57 | results.map(convertToViperResult)
58 | .collect { case failure: VprFailure => failure.errors }
59 | .flatten match {
60 | case Seq() => VprSuccess
61 | case errors => VprFailure(errors)
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/scala/interfaces/decider/Prover.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.interfaces.decider
8 |
9 | import viper.silicon.debugger.DebugAxiom
10 | import viper.silicon.common.collections.immutable.InsertionOrderedSet
11 | import viper.silicon.common.config.Version
12 | import viper.silver.components.StatefulComponent
13 | import viper.silicon.{Config, Map}
14 | import viper.silicon.state.terms._
15 | import viper.silicon.verifier.Verifier
16 | import viper.silver.verifier.Model
17 |
18 | sealed abstract class Result
19 | object Sat extends Result
20 | object Unsat extends Result
21 | object Unknown extends Result
22 |
23 | /* TODO: Should be generic, not hardcoded to Strings */
24 | trait ProverLike {
25 | protected val debugMode = Verifier.config.enableDebugging()
26 | var preambleAssumptions: Seq[DebugAxiom] = Seq()
27 | def emit(content: String): Unit
28 | def emit(contents: Iterable[String]): Unit = { contents foreach emit }
29 | def emitSettings(contents: Iterable[String]): Unit
30 | def assumeAxioms(terms: InsertionOrderedSet[Term], description: String): Unit = {
31 | if (debugMode)
32 | preambleAssumptions :+= new DebugAxiom(description, terms)
33 | terms foreach assume
34 | }
35 | def setOption(name: String, value: String): String
36 | def assume(term: Term): Unit
37 | def declare(decl: Decl): Unit
38 | def comment(content: String): Unit
39 | def saturate(timeout: Int, comment: String): Unit
40 | def saturate(data: Option[Config.ProverStateSaturationTimeout]): Unit
41 | }
42 |
43 | trait Prover extends ProverLike with StatefulComponent {
44 | def start(userArgsString: Option[String]): Unit
45 | def assert(goal: Term, timeout: Option[Int] = None): Boolean
46 | def check(timeout: Option[Int] = None): Result
47 | def fresh(id: String, argSorts: Seq[Sort], resultSort: Sort): Function
48 | def statistics(): Map[String, String]
49 | def hasModel(): Boolean
50 | def isModelValid(): Boolean
51 | def getModel(): Model
52 | def getReasonUnknown(): String
53 | def clearLastAssert(): Unit
54 | def name: String
55 | def minVersion: Version
56 | def maxVersion: Option[Version]
57 | def version(): Version
58 | def staticPreamble: String
59 | def randomizeSeedsOptions: Seq[String]
60 |
61 | def pushPopScopeDepth: Int
62 |
63 | def push(n: Int = 1, timeout: Option[Int] = None): Unit
64 |
65 | def pop(n: Int = 1): Unit
66 |
67 | def getAllDecls(): Seq[Decl]
68 |
69 | def getAllEmits(): Seq[String]
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/scala/rules/LetSupporter.scala:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 | //
5 | // Copyright (c) 2011-2019 ETH Zurich.
6 |
7 | package viper.silicon.rules
8 |
9 | import viper.silver.ast
10 | import viper.silver.verifier.PartialVerificationError
11 | import viper.silicon.interfaces.VerificationResult
12 | import viper.silicon.state.{State, Store}
13 | import viper.silicon.state.terms.Term
14 | import viper.silicon.verifier.Verifier
15 |
16 | trait LetSupportRules extends SymbolicExecutionRules {
17 | def handle[E <: ast.Exp]
18 | (s: State, e: ast.Exp, pve: PartialVerificationError, v: Verifier)
19 | (Q: (State, Store, E, Verifier) => VerificationResult)
20 | : VerificationResult
21 |
22 | def handle[E <: ast.Exp]
23 | (s: State, let: ast.Let, pve: PartialVerificationError, v: Verifier)
24 | (Q: (State, Store, E, Verifier) => VerificationResult)
25 | : VerificationResult
26 | }
27 |
28 | object letSupporter extends LetSupportRules {
29 | import evaluator._
30 |
31 | def handle[E <: ast.Exp]
32 | (s: State, e: ast.Exp, pve: PartialVerificationError, v: Verifier)
33 | (Q: (State, Store, E, Verifier) => VerificationResult)
34 | : VerificationResult = {
35 |
36 | e match {
37 | case let: ast.Let => handle(s, Nil, let, pve, v)(Q)
38 | case _ => Q(s, Store(), e.asInstanceOf[E], v)
39 | }
40 | }
41 |
42 | def handle[E <: ast.Exp]
43 | (s: State, let: ast.Let, pve: PartialVerificationError, v: Verifier)
44 | (Q: (State, Store, E, Verifier) => VerificationResult)
45 | : VerificationResult = {
46 |
47 | handle(s, Nil, let, pve, v)(Q)
48 | }
49 |
50 | private def handle[E <: ast.Exp]
51 | (s: State,
52 | bindings: Seq[(ast.AbstractLocalVar, (Term, Option[ast.Exp]))],
53 | let: ast.Let,
54 | pve: PartialVerificationError,
55 | v: Verifier)
56 | (Q: (State, Store, E, Verifier) => VerificationResult)
57 | : VerificationResult = {
58 |
59 | val ast.Let(x, exp, body) = let
60 |
61 | eval(s, exp, pve, v)((s1, t, expNew, v1) => {
62 | val bindings1 = bindings :+ (x.localVar, (t, expNew))
63 | val s2 = s1.copy(s1.g + (x.localVar, (t, expNew)))
64 | body match {
65 | case nestedLet: ast.Let => handle(s2, bindings1, nestedLet, pve, v1)(Q)
66 | case _ => Q(s2, Store(bindings1), body.asInstanceOf[E], v1)}})
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/test/resources/symbExLogTests/symbLogTest_linkedListMinimal.vpr.elog:
--------------------------------------------------------------------------------
1 | predicate lseg
2 | Branch this@1@00 != end@2@00:
3 | comment: Reachable
4 | Join
5 | Branch First:(Second:($t@0@00)) != end@2@00:
6 | comment: Reachable
7 | Join
8 | Branch First:(Second:(First:(Second:(Second:($t@0@00))))) != end@2@00:
9 | comment: Reachable
10 | Join
11 | Branch First:(Second:(First:(Second:(Second:($t@0@00))))) != end@2@00:
12 | comment: Reachable
13 | Branch First:(Second:(First:(Second:(Second:($t@0@00))))) == end@2@00:
14 | comment: Unreachable
15 | Branch First:(Second:(First:(Second:(Second:($t@0@00))))) == end@2@00:
16 | comment: Reachable
17 | Join
18 | Branch First:(Second:(First:(Second:(Second:($t@0@00))))) != end@2@00:
19 | comment: Unreachable
20 | Branch First:(Second:(First:(Second:(Second:($t@0@00))))) == end@2@00:
21 | comment: Reachable
22 | Join
23 | Branch First:(Second:($t@0@00)) != end@2@00:
24 | comment: Reachable
25 | Branch First:(Second:($t@0@00)) == end@2@00:
26 | comment: Unreachable
27 | Branch First:(Second:($t@0@00)) == end@2@00:
28 | comment: Reachable
29 | Join
30 | Branch First:(Second:($t@0@00)) != end@2@00:
31 | comment: Unreachable
32 | Branch First:(Second:($t@0@00)) == end@2@00:
33 | comment: Reachable
34 | Branch this@1@00 == end@2@00:
35 | comment: Reachable
36 |
37 | predicate List
38 |
39 | method insert
40 | execute var tmp: Ref
41 | execute index := 0
42 | execute unfold acc(List(this), write)
43 | execute unfold acc(lseg(this.head, null), write)
44 | Branch First:($t@6@01) != Null:
45 | comment: Reachable
46 | Branch First:($t@6@01) == Null:
47 | comment: Reachable
48 | Branch 1:
49 | comment: Reachable
50 | Join
51 | Branch First:($t@6@01) == Null:
52 | comment: Reachable
53 | Branch First:($t@6@01) != Null:
54 | comment: Reachable
55 | Branch First:($t@6@01) != Null:
56 | comment: Unreachable
57 | Branch First:($t@6@01) == Null:
58 | comment: Reachable
59 | Branch 2:
60 | comment: Reachable
61 | Join
62 | Branch First:($t@6@01) == Null:
63 | comment: Reachable
64 | Branch First:($t@6@01) != Null:
65 | comment: Reachable
66 | Branch First:($t@6@01) == Null:
67 | comment: Reachable
68 | Branch First:($t@6@01) != Null:
69 | comment: Unreachable
70 |
71 |
--------------------------------------------------------------------------------