├── 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 | --------------------------------------------------------------------------------