verifast-docs

C Translation Units

This document describes how VeriFast verifies a .c file. It does so when the .c file is specified as a command-line argument of the verifast command-line tool, or when the .c file is loaded into the VeriFast IDE and the Verify command is issued.

VeriFast first performs preprocessing on the .c file. While doing so, it checks that the expansion of a header file does not depend on macros defined before the inclusion of the header file. That is, it checks that the expansion of header files is context-free. This is part of ensuring the soundness of the verification of C programs consisting of multiple .c files.

The sequence of tokens obtained after preprocessing is called a translation unit. VeriFast then parses the translation unit, checking that it conforms with the grammar shown below.

It then checks well-formedness of the various declarations, and then verifies each function that has a specification. It verifies the functions in the order in which they appear in the translation unit. We detail the well-formedness conditions for the various declarations and we describe the verification of functions below.

Declarations

translation-unit:
    external-declaration
    translation-unit external-declaration

external-declaration:
    function-definition
    declaration
    ghost-declaration-block

ghost-declaration-block:
    /*@ ghost-declaration-list @*/

ghost-declaration-list:
    ghost-declaration
    ghost-declaration-list ghost-declaration

ghost-declaration:
    inductive-datatype-declaration
    fixpoint-function-definition
    predicate-declaration
    predicate-family-declaration
    predicate-family-instance-definition
    predicate-constructor-definition
    lemma-function-declaration
    box-class-declaration

Inductive datatypes

inductive-datatype-declaration:
    inductive identifier generic-parametersopt = |opt inductive-datatype-case-list ;

generic-parameters:
    < identifier-list >

inductive-datatype-case-list:
    inductive-datatype-case-declaration
    inductive-datatype-case-list | inductive-datatype-case-declaration

inductive-datatype-case-declaration:
    identifier
    identifier ( parameter-listopt )

We describe inductive datatypes by example. The declaration

inductive list<t> = nil | cons(t, list<t>);

introduces the generic type name list and generic pure function names nil and cons. For any type T, type list<T> denotes the smallest set that satisfies the following constraints:

The inductive datatype declarations of a translation unit may refer to each other. That is, types may be defined by mutual induction. VeriFast checks that each type is well-defined (recursion through positive positions only) and inhabited.

Fixpoint functions

fixpoint-function-definition:
    fixpoint function-definition

A fixpoint function definition defines a pure function in one of three ways:

  1. primitive recursive definition
  2. simple non-recursive definition
  3. definition by well-founded recursion

We describe each case by example. The declaration

fixpoint int length<t>(list<t> xs) {
    switch (xs) {
        case nil: return 0;
        case cons(x, xs0): return length(xs0);
    }
}

introduces the generic pure function name length by primitive recursion on its argument xs. The body of a fixpoint function defined by primitive recursion must consist solely of a switch statement whose operand is one of the function’s parameters. The type of this parameter (called the inductive parameter) must be an inductive datatype. The body of each case must be of the form return E;. The expression E may call fixpoint functions defined earlier, and it may also recursively call the fixpoint function being defined. In the latter case, the argument supplied for the inductive parameter must be one of the variables bound by the parameter list of the current case. (For example, the recursive call length(xs0) above is allowed because xs0 is a variable bound in the header of the case.

The declaration

fixpoint int abs(int x) { return x < 0 ? -x : x; }

introduces the pure function name abs. The body of a fixpoint function defined non-recursively must be of the form return E; where E calls only fixpoint functions defined earlier.

For fixpoint functions defined by well-founded recursion, see the wf_funcX.c examples.

Predicates

predicate-declaration:
    predicate identifier generic-parametersopt predicate-parameters ;
    predicate-keyword identifier generic-parametersopt predicate-parameters = assertion ;

predicate-keyword:
    predicate
    copredicate

predicate-parameters:
    ( parameter-list )
    ( parameter-list ; parameter-list )

predicate-family-declaration:
    predicate_family identifier ( parameter-list ) predicate-parameters ;

predicate-family-instance-definition:
    predicate_family_instance identifier ( argument-expression-list ) predicate-parameters = assertion ;

predicate-constructor-definition:
    predicate_ctor identifier ( parameter-list ) ( parameter-list ) = assertion ;

Lemma functions

lemma-function-declaration:
    lemma-keyword declaration
    lemma-keyword function-definition

lemma-keyword:
    lemma
    lemma_auto
    lemma_auto ( expression )

Function definitions

function-definition:
    declaration-specifiers declarator declaration-listopt compound-statement

declaration-list:
    declaration
    declaration-list declaration

Declarations

declaration:
    declaration-specifiers init-declarator-listopt ;
    static_assert-declaration

declaration-specifiers:
    storage-class-specifier declaration-specifiersopt
    type-specifier declaration-specifiersopt
    type-qualifier declaration-specifiersopt
    function-specifier declaration-specifiersopt
    alignment-specifier declaration-specifiersopt

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator

init-declarator:
    declarator
    declarator = initializer

storage-class-specifier:
    typedef
    extern
    static
    _Thread_local
    auto
    register

type-specifier:
    void
    char
    short
    int
    long
    float
    double
    signed
    unsigned
    _Bool
    _Complex
    atomic-type-specifier
    struct-or-union-specifier
    enum-specifier
    typedef-name
    identifier generic-argumentsopt
    real
    fixpoint ( type-list )
    predicate predicate-parameters
    any

generic-arguments:
    < type-list >

type-list:
    type
    type-list , type

type:
    declaration-specifiers

struct-or-union-specifier:
    struct-or-union identifieropt { struct-declaration-list }
    struct-or-union identifier

struct-or-union:
    struct
    union

struct-declaration-list:
    struct-declaration
    struct-declaration-list struct-declaration

struct-declaration:
    specifier-qualifier-list struct-declarator-listopt ;
    static_assert-declaration

specifier-qualifier-list:
    type-specifier specifier-qualifier-listopt
    type-qualifier specifier-qualifier-listopt
    alignment-specifier specifier-qualifier-listopt

struct-declarator-list:
    struct-declarator
    struct-declarator-list , struct-declarator

struct-declarator:
    declarator
    declaratoropt : constant-expression

enum-specifier:
    enum identifieropt { enumerator-list }
    enum identifieropt { enumerator-list , }
    enum identifier

enumerator-list:
    enumerator
    enumerator-list , enumerator

enumerator:
    enumeration-constant
    enumeration-constant = constant-expression

atomic-type-specifier:
    _Atomic ( type-name )

type-qualifier:
    const
    restrict
    volatile
    _Atomic

function-specifier:
    inline
    _Noreturn

alignment-specifier:
    _Alignas ( type-name )
    _Alignas ( constant-expression )

declarator:
    pointeropt direct-declarator

direct-declarator:
    identifier
    ( declarator )
    direct-declarator [ type-qualifier-listopt assignment-expressionopt ]
    direct-declarator [ static type-qualifier-listopt assignment-expression ]
    direct-declarator [ type-qualifier-list static assignment-expression ]
    direct-declarator [ type-qualifier-listopt * ]
    direct-declarator generic-parametersopt ( parameter-type-list ) specification-clausesopt
    direct-declarator ( identifier-listopt )

specification-clauses:
    specification-clause
    specification-clauses specification-clause

specification-clause:
    /*@ specification-ghost-clause @*/
    specification-ghost-clause

specification-ghost-clause:
    nonghost_callers_only
    : identifier argumentsopt
    requires assertion ;
    ensures assertion ;
    terminates ;

arguments:
    ( argument-expression-list )

pointer:
    * type-qualifier-listopt
    * type-qualifier-listopt pointer

type-qualifier-list:
    type-qualifier
    type-qualifier-list type-qualifier

parameter-type-list:
    parameter-list
    parameter-list , ...

parameter-list:
    parameter-declaration
    parameter-list , parameter-declaration

parameter-declaration:
    declaration-specifiers declarator
    declaration-specifiers abstract-declaratoropt

identifier-list:
    identifier
    identifier-list , identifier

type-name:
    specifier-qualifier-list abstract-declaratoropt

abstract-declarator:
    pointer
    pointeropt direct-abstract-declarator

direct-abstract-declarator:
    ( abstract-declarator )
    direct-abstract-declaratoropt [ type-qualifier-listopt assignment-expressionopt ]
    direct-abstract-declaratoropt [ static type-qualifier-listopt assignment-expression ]
    direct-abstract-declaratoropt [ type-qualifier-list static assignment-expression ]
    direct-abstract-declaratoropt [ * ]
    direct-abstract_declaratoropt ( parameter-type-listopt )

typedef-name:
    identifier

initializer:
    assignment-expression
    { initializer-list }
    { initializer-list , }

initializer-list:
    designationopt initializer
    initializer-list , designationopt initializer

designation:
    designator-list =

designator-list:
    designator
    designator-list designator

designator:
    [ constant-expression ]
    . identifier

static_assert-declaration:
    _Static_assert ( constant-expression , string-literal ) ;

Shared boxes

See Shared boxes: rely-guarantee reasoning in VeriFast.

Statements and blocks

statement:
    labeled-statement
    compound-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement
    ghost-statement-block
    ghost-statement

labeled-statement:
    identifier : statement
    case constant-expression : statement
    case identifier case-argumentsopt : statement
    default : statement

compound-statement:
    { block-item-listopt }

block-item-list:
    block-item
    block-item-list block-item

block-item:
    declaration
    statement

expression-statement:
    expressionopt ;

selection-statement:
    if ( expression ) statement
    if ( expression ) statement else statement
    switch ( expression ) statement

iteration-statement:
    while ( expression ) loop-annotations statement
    do loop-annotations statement while ( expression ) ;
    for ( expressionopt ; expressionopt ; expressionopt ) loop-annotations statement
    for ( declaration expressionopt ; expressionopt ) loop-annotations statement

loop-annotations:
    loop-annotation
    loop-annotations loop-annotation

loop-annotation:
    /*@ loop-ghost-annotation @*/
    loop-ghost-annotation

loop-ghost-annotation:
    invariant assertion ;
    requires assertion ;
    ensures assertion ;
    decreases expression ;

jump-statement:
    goto identifier ;
    continue ;
    break ;
    return expressionopt ;

ghost-statement-block:
    /*@ ghost-statement @*/

ghost-statement:
    open coefficientopt predicate-assertion ;
    close coefficientopt predicate-assertion ;
    leak assertion ;
    invariant assertion ;
    produce_lemma_function_pointer_chunk identifier generic-argumentsopt arguments ( identifier-list ) compound-statement statement
    duplicate_lemma_function_pointer_chunk ( expression ) ;
    produce_function_pointer_chunk identifier generic-argumentsopt ( expression ) arguments ( identifier-list ) compound-statement
    merge_fractions assertion ;
    shared-boxes-ghost-statements
    statement

Shared boxes

See Shared boxes: rely-guarantee reasoning in VeriFast.

Assertions

primary-assertion:
    coefficientopt points-to-assertion
    coefficientopt predicate-assertion
    expression
    switch ( expression ) { switch-assertion-case-list }
    ( assertion )
    forall_ ( type identifier ; expression )
    emp

coefficient:
    [ pattern ]

points-to-assertion:
    conditional-expression |-> pattern

predicate-assertion:
    identifier generic-argumentsopt patternsopt patterns

patterns:
    ( pattern-listopt )

pattern-list:
    pattern
    pattern-list , pattern

pattern:
    _
    ? identifier
    identifier patterns
    expression
    ^ expression

switch-assertion-case-list:
    switch-assertion-case
    switch-assertion-case-list switch-assertion-case

switch-assertion-case:
    case identifier case-argumentsopt : return assertion ;

case-arguments:
    ( identifier-listopt )

assertion:
    primary-assertion
    primary-assertion &*& assertion
    expression ? assertion : assertion
    ensures assertion

Expressions

primary-expression:
    identifier generic-argumentsopt
    constant
    string-literal
    ( expression )
    generic-selection
    switch ( expression ) { switch-expression-case-list }

switch-expression-case-list:
    switch-expression-case
    switch-expression-case-list switch-expression-case

switch-expression-case:
    case identifier case-argumentsopt : return expression ;

generic-selection:
    _Generic ( assignment-expression , generic-assoc-list )

generic-assoc-list:
    generic-association
    generic-assoc-list , generic-association

generic-association:
    type-name : assignment-expression
    default : assignment-expression

postfix-expression:
    primary-expression
    postfix-expression [ expression ]
    postfix-expression ( argument-expression-listopt )
    postfix-expression . identifier
    postfix-expression -> identifier
    postfix-expression ++
    postfix-expression -
    ( type-name ) { initializer-list }
    ( type-name ) { initializer-list , }

argument-expression-list:
    assignment-expression
    argument-expression-list , assignment-expression

unary-expression:
    postfix-expression
    ++ unary-expression
    - unary-expression
    unary-operator cast-expression
    sizeof unary-expression
    sizeof ( type-name )
    _Alignof ( type-name )

unary-operator: one of
    & * + - ~ !

cast-expression:
    unary-expression
    ( type-name ) cast-expression

multiplicative-expression:
    cast-expression
    multiplicative-expression * cast-expression
    multiplicative-expression / cast-expression
    multiplicative-expression % cast-expression

additive-expression:
    multiplicative-expression
    additive-expression + multiplicative-expression
    additive-expression - multiplicative-expression

shift-expression:
    additive-expression
    shift-expression << additive-expression
    shift-expression >> additive-expression

truncating-expression:
    shift-expression
    /*@ truncating @*/ postfix-expression
    truncating postfix-expression

relational-expression:
    truncating-expression
    relational-expression < truncating-expression
    relational-expression > truncating-expression
    relational-expression <= truncating-expression
    relational-expression >= truncating-expression

equality-expression:
    relational-expression
    equality-expression == relational-expression
    equality-expression != relational-expression

AND-expression:
    equality-expression
    AND-expression & equality-expression

exclusive-OR-expression:
    AND-expression
    exclusive-OR-expression ^ AND-expression

inclusive-OR-expression:
    exclusive-OR-expression
    inclusive-OR-expression | exclusive-OR-expression

logical-AND-expression:
    inclusive-OR-expression
    logical-AND-expression && inclusive-OR-expression

logical-OR-expression:
    logical-AND-expression
    logical-OR-expression || logical-AND-expression

conditional-expression:
    logical-OR-expression
    logical-OR-expression ? expression : conditional-expression

assignment-expression:
    conditional-expression
    unary-expression assignment-operator assignment-expression

assignment-operator: one of
    = *= /= %= += -= <<= >>= &= ^= |=

expression:
    assignment-expression
    expression , assignment-expression

constant-expression:
    conditional-expression