val_cat - Stress Testing Calling Conventions

This test stress tests BRiCk’s calling convention ensuring that we properly handle pass-by-value, pass-by-references, and pass-by-rvalue-reference. We also use it as small performance test for out automation.

/*
 * Copyright (C) BedRock Systems Inc. 2019 Gregory Malecha
 *
 * SPDX-License-Identifier:MIT-0
 */

struct P {
    int x;

    /**
     * \internal
     *
     * \post _at (_eq this) (PR 0)
     */
    P():x(0) {}
    /**
     * \internal
     *
     * \arg{x} "x" (Vint x)
     * \post this |-> PR x
     */
    P(int x):x(x) {}

    /**
     * \internal
     *
     * \arg{p} "p" (Vptr p)
     * \prepost{m} p |-> PR m
     * \post this |-> PR m
     */
    P(const P&p):x(p.x) {}

    /**
     * Note, this specification is the same as the copy-constructor which is a stronger specification
     * than what is required for more-cosntructors.
     *
     * \internal
     *
     * \arg{p} "p" (Vptr p)
     * \prepost{m} p |-> PR m
     * \post this |-> PR m
     */
    P(const P&& p):x(p.x) {}

    /**
     * \internal
     *
     * \pre{m} this |-> PR m
     * \post emp
     */
    ~P() {}
};

struct Q {
    int x;
    explicit Q() {}
};

/**
 * \internal
 *
 * \arg{x} "x" (Vptr x)
 * \prepost{m} x |-> PR m
 * \post[Vint m] emp
 */
int by_ref(P& x) { return x.x; }

/**
 * \internal
 *
 * \arg{x} "x" (Vptr x)
 * \prepost{m} x |-> PR m
 * \post[Vint m] emp
 */
int by_val(P x) { return x.x; }

/**
 * \internal
 *
 * \arg{x} "x" (Vptr x)
 * \prepost{m} x |-> PR m
 * \post[Vint m] emp
 */
int by_ptr(P *x) { return x->x; }

/**
 * \internal
 *
 * \arg{x} "x" (Vptr x)
 * \prepost{m} x |-> PR m
 * \post[Vint m] emp
 */
int by_rref(P &&x) { return x.x; }

/**
 * \internal
 *
 * \post{p}[Vptr p] p |-> PR 1
 */
P ret_val() {
    return P(1);
}

/**
 * \internal
 *
 * \arg{x} "x" (Vptr x)
 * \prepost{m} x |-> PR m
 * \post{p}[Vptr x] emp
 */
P& ret_ref(P& x) {
    return x;
}

/**
 * \internal
 *
 * \arg{x} "x" (Vptr x)
 * \prepost{m} x |-> PR m
 * \post{p}[Vptr x] emp
 */
P&& ret_rref(P& x) {
    return static_cast<P&&>(x);
}

/**
 * \arg{a} "a" (Vbool a)
 * \require a = true
 * \post emp
 */
extern void assert(int a);

/**
 * \post[Vint 0] emp
 */
int main() {
    P p;

    by_ref(p);

    by_val(p);

    by_ptr(&p);

    by_val(P());

    by_val(P(P().x));

    by_val(P(ret_val().x));

    by_rref(P());

    (void)(P().x);

    by_ref(ret_ref(p));

    by_val(ret_rref(p));

    by_val(ret_val());

    ret_val();

    P pp(ret_rref(p));

    return 0;
}