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.
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-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:
nil<T> is an element of the set.v is a value of type T and l is an element of the set, then cons<T>(v, l) is an element of the set.v of type T and element l of the set, nil<T> is distinct from cons<T>(v, l).v1 and v2 of type T and elements l1 and l2 of the set, cons<T>(v1, l1) is equal to cons<T>(v2, l2) only if v1 is equal to v2 and l1 is equal to l2.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-function-definition:
    fixpoint function-definition
A fixpoint function definition defines a pure function in one of three ways:
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.
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-function-declaration:
    lemma-keyword declaration
    lemma-keyword function-definition
lemma-keyword:
    lemma
    lemma_auto
    lemma_auto ( expression )
function-definition:
    declaration-specifiers declarator declaration-listopt compound-statement
declaration-list:
    declaration
    declaration-list declaration
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 ) ;
See Shared boxes: rely-guarantee reasoning in VeriFast.
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
See Shared boxes: rely-guarantee reasoning in VeriFast.
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
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