SPARK 26 Release Notes

We present here a few highlights of the new features in SPARK 26. You can access the complete list here.

Language Extensions

Multiple Levels of Ghost Code

SPARK now offers multiple levels of ghost code. Ghost entities, assertion expressions, and specification pragmas can be associated with named assertion levels. Assertion levels, defined using the Assertion_Level pragma can then be enabled or disabled through an Assertion_Policy pragma.

Two levels of ghost code are predefined: Runtime and Static. Ghost code marked Runtime is always enabled; ghost code marked Static is never enabled.

Assertion Levels for SPARKlib Containers

The SPARK library introduces several assertion levels that are used in the container libraries.

The assertion level SPARKlib_Defensive` allows enabling preconditions on container operations. This level is useful in particular if these operations are called from unproved code.

The assertion level SPARKlib_Logic` is for models of formal containers. It can be enabled in the full runtime. In the light runtime, it is also used for the ghost versions of the big numbers library and functional Containers library. As these libraries require finalization, the assertion level SPARKlib_Logic` cannot be enabled in the light runtime.

New Program_Exit Aspect for Abrupt Program Termination

SPARK now offers a new Program_Exit aspect for specifying that the subprogram will terminate the whole program abruptly. The boolean expression given with this aspect, if any, shall be true when the program is terminated, which permits reasoning about intended program termination.

New Exit_Cases for Termination Conditions

SPARK now offers a new Exit_Cases aspect for specifying subprogram termination conditions.

A subprogram can terminate by returning normally, by propagating an exception or by abruptly terminating the program. If a subprogram does not always terminate normally, then it can be annotated with an Exit_Cases aspect. This aspect allows partitioning the input state into cases and specifying for each case what the expected termination kind is:

  • Normal_Return, the subprogram shall return normally;

  • Program_Exit, the subprogram shall abruptly terminate the program;

  • Exception_Raised, the subprogram shall raise an (unspecified) exception; or

  • (Exception_Raised => E), the subprogram shall raise the exception E.

Support for Invalid Values

SPARK now supports invalid values via a new Potentially_Invalid aspect. The Potentially_Invalid aspect can be used to annotate standalone objects, subprogram parameters, function result, and instances of Ada.Unchecked_Conversion to specify that they might have values that do not abide by the constraints of their type. A validity check is introduced whenever such objects are evaluated. The ‘Valid and ‘Valid_Scalars attributes can be used to assess their validity both in the code and in contracts.

Support for the finally Construct

SPARK now supports the finally` keyword, a GNAT extension, which makes it possible to have a sequence of statements be executed when another sequence of statements is completed, whether normally or abnormally.

User Experience

Success Message After Full Verification

Previously, when all checks were proved (or annotated), GNATprove exited quietly with no explicit success message. Now, SPARK outputs a success message and prints the number of checks that were proved.

Support for Generics when Using –limit Switches

Similar to the –limit-subp switch, the switches –limit-line and –limit-region now also support prefixing the location by a generic instantiation. The same is true for locations specified in a file passed to the –limit-lines switch.

No Resource-Leak Checks in Nonexecutable Ghost Code

Taking advantage of the new support for multiple levels of ghost code, GNATprove no longer emits checks for resource leaks inside assertion pragmas, specification aspects, and ghost code that is associated with an assertion level that cannot be enabled at run time.

Warning Management via the Command Line

In addition to the existing warning management capabilities, such as pragma Warnings and the –warnings switch, GNATProve now supports three switches -W, -A and -D, which allow users to enable warnings, suppress them, and promote them to errors, respectively. This can be done for predefined warning categories, which are identified by names appended to the warnings by default.

SARIF Output

GNATProve now generates a gnatprove.sarif file at the same location as the gnatprove.out file that contains a summary of the run in SARIF format.

Improved Message with the –info Switch

Previously, the –info switch could be used to enable a number of additional info messages, mostly related to proof. Now, a small number of these messages have been enabled by default (the messages related to inlining and loop unrolling), and the other info messages have been promoted into warnings that are disabled by default. Being warnings, they can be controlled by the -A, -W and -D switches and pragma Warnings (Off). The –info switch remains available to enable these warnings collectively.

Revised –no-global-generation Switch Behavior

In previous versions of SPARK, the –no-global-generation switch prevented flow analysis from automatically generating Global contracts for subprograms without explicit global contracts. In this version of SPARK, the –no-global-generation switch has been modified to emit warnings when non-null Global contracts are generated for a subprogram with no explicit Global contracts. This change improves the stability of the feature, making it usable in more contexts.

Improved Documentation of Proof Limitations

The section on proof limitations in the SPARK User’s Guide has been extended to include cases where the verification might fail due to the tool imprecision. The GNATprove tool has also been extended to detect more of these cases and to emit warnings when the –info switch is used.

Incompatible Changes in the SPARK Library

Renaming of Insertion Primitives in Formal Vectors

Similarly to Ada standard containers, the Containers.Formal.Vectors and Containers.Formal.Unbounded_Vectors packages of the SPARK library provide versions of the Append, Insert, and Prepend primitives taking a vector as a new item. These primitives have been renamed Append_Vector, Insert_Vector, and Prepend_Vector to match what has been done for the standard vector packages of Ada.

Simplification of Reference Function in Formal Containers

The mode of the first parameters of the Reference functions declared in the Containers.Formal.Vectors, Containers.Formal.Doubly_Linked_Lists, Containers.Formal.Hashed_Maps, and Containers.Formal.Ordered_Maps packages of the SPARK library has been modified to simplify its usage. It is now an aliased parameter of mode IN OUT instead of an access parameter.

Similarly, the mode of the first parameters of the Reference functions declared in the Containers.Formal.Unbounded_Vectors, Containers.Formal.Unbounded_Doubly_Linked_Lists, Containers.Formal.Unbounded_Hashed_Maps, and Containers.Formal.Unbounded_Ordered_Maps packages of the SPARK library is now a parameter of mode IN instead of an access parameter.

Change in Generic Instances for Models of Formal Containers

The actual parameter supplied for equality over elements of functional sequences and maps has been changed in the generic instances introduced for the various models of all formal containers. It is now the user-supplied equality function over keys or elements instead of a non-executable function standing for the logical equality. It makes it possible to enable these ghost models at run time, but it changes the meaning of comparison operators ("=", "<=", and "<") over these models, since they make use of this equality function. This change cannot modify the execution of a SPARK program in any way, as this is non-executable ghost code. However, it might affect the provability of user code if it uses these operators in its contracts. The ghost functions Equal, and Equal_Prefix on sequences, and Equal and Elements_Equal on functional maps are used as a replacement for these operators in the contracts of the container library so as to avoid degrading provability. User code might need to be changed in a similar way.

Executable Ghost Code in Containers

It is now possible to execute most preconditions in the functional and formal container library. Ghost models in the formal container library are also executable in the full runtime. As a result, enabling all assertions and ghost code, for example using -gnata, now has the result of enabling these preconditions and ghost models as well. It is possible to disable them globally by adding pragma Check_Policy (SPARKlib_Defensive => Ignore); and pragma Check_Policy (SPARKlib_Logic => Ignore); to the global configuration switch of the user project.