From 4b91b5f064499cdc7a4330c59b2ed9c49be2b862 Mon Sep 17 00:00:00 2001 From: Julien Signoles <julien.signoles@cea.fr> Date: Wed, 23 Nov 2011 18:00:00 +0000 Subject: [PATCH] [e-acsl] \result --- src/plugins/e-acsl/TODO | 3 +- src/plugins/e-acsl/env.ml | 8 +- .../tests/e-acsl-runtime/oracle/gen_result.c | 694 ++++++++++++++++++ .../e-acsl-runtime/oracle/result.err.oracle | 0 .../e-acsl-runtime/oracle/result.res.oracle | 217 ++++++ .../e-acsl/tests/e-acsl-runtime/result.i | 31 + src/plugins/e-acsl/visit.ml | 46 +- 7 files changed, 977 insertions(+), 22 deletions(-) create mode 100644 src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_result.c create mode 100644 src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.err.oracle create mode 100644 src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.res.oracle create mode 100644 src/plugins/e-acsl/tests/e-acsl-runtime/result.i diff --git a/src/plugins/e-acsl/TODO b/src/plugins/e-acsl/TODO index 07935b4b05f..7a4303f1380 100644 --- a/src/plugins/e-acsl/TODO +++ b/src/plugins/e-acsl/TODO @@ -1,11 +1,11 @@ à traiter avant la 1ère release: - quantifications sans exentension de syntaxe -- \return ######## # CODE # ######## +- mixed assumes and ensures - function contracts for functions only declared ==> le noyau génère un "assigns \nothing" pour ces fonctions... ce assign n'est de toute façon pas gérer @@ -25,6 +25,7 @@ # KNOWN BUGS # ############## - \at incorrect si StmtLabel faisant référence au stmt courant (voir test at.i) +- incorrect d'utiliser un \old dans le post-state si pre-state == post-state ######### # TESTS # diff --git a/src/plugins/e-acsl/env.ml b/src/plugins/e-acsl/env.ml index f36034d506b..c60851c3471 100644 --- a/src/plugins/e-acsl/env.ml +++ b/src/plugins/e-acsl/env.ml @@ -148,13 +148,17 @@ let new_var ?(global=false) env t ty mk_stmts = let local_env, _ = top env in if global then (* do not use memoisation here: it is incorrect for terms corresponding to - impure expressions *) + impure expressions + [JS 2011/11/23] actually it is correct now since globals are only use for + \at *) do_new_var ~global env t ty mk_stmts else try match t with | None -> raise No_term - | Some t -> Term.Map.find t local_env.mpz_tbl.new_exps, env + | Some t -> + Options.feedback "memoized %a" Term.pretty t; + Term.Map.find t local_env.mpz_tbl.new_exps, env with Not_found | No_term -> do_new_var ~global env t ty mk_stmts diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_result.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_result.c new file mode 100644 index 00000000000..46b82c22313 --- /dev/null +++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_result.c @@ -0,0 +1,694 @@ +/* Generated by Frama-C */ +typedef unsigned long size_t; +typedef unsigned long mp_limb_t; +typedef unsigned long mp_bitcnt_t; +struct __anonstruct___mpz_struct_6 { + int _mp_alloc ; + int _mp_size ; + mp_limb_t *_mp_d ; +}; +typedef struct __anonstruct___mpz_struct_6 __mpz_struct; +typedef __mpz_struct mpz_t[1]; +typedef mp_limb_t *mp_ptr; +typedef mp_limb_t const *mp_srcptr; +typedef long mp_size_t; +struct __anonstruct___mpq_struct_7 { + __mpz_struct _mp_num ; + __mpz_struct _mp_den ; +}; +typedef struct __anonstruct___mpq_struct_7 __mpq_struct; +typedef __mpz_struct const *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __mpq_struct const *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; +/* compiler builtin: + long __builtin_expect(long, long); */ +/*@ assigns \nothing; */ +extern int printf(char const * __restrict __format , ...); +__inline static void __gmpz_abs(mpz_ptr __gmp_w, mpz_srcptr __gmp_u); +/*@ requires \valid(x); + assigns *x; */ +extern void __gmpz_clear(__mpz_struct * /*[1]*/ x); +/*@ requires \valid(z1); + requires \valid(z2); + assigns \nothing; */ +extern int __gmpz_cmp(__mpz_struct const * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2) __attribute__(( +__pure__)); +__inline static int __gmpz_fits_uint_p(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +__inline static int __gmpz_fits_ulong_p(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +__inline static int __gmpz_fits_ushort_p(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +/*@ requires \valid(z); + assigns \nothing; */ +extern long __gmpz_get_si(__mpz_struct const * /*[1]*/ z) __attribute__(( +__pure__)); +__inline static unsigned long __gmpz_get_ui(__mpz_struct const * /*[1]*/ z) __attribute__(( +__pure__)); +__inline static mp_limb_t __gmpz_getlimbn(mpz_srcptr __gmp_z, + mp_size_t __gmp_n) __attribute__(( +__pure__)); +/*@ ensures \valid(\old(x)); + assigns *x; */ +extern void __gmpz_init(__mpz_struct * /*[1]*/ x); +/*@ ensures \valid(\old(z)); + assigns *z; + assigns *z \from n; */ +extern void __gmpz_init_set_si(__mpz_struct * /*[1]*/ z, long n); +__inline static void __gmpz_neg(__mpz_struct * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2); +__inline static int __gmpz_perfect_square_p(mpz_srcptr __gmp_a) __attribute__(( +__pure__)); +__inline static mp_bitcnt_t __gmpz_popcount(mpz_srcptr __gmp_u) __attribute__(( +__pure__)); +extern void __gmpz_set(mpz_ptr, mpz_srcptr); +__inline static void __gmpz_set_q(mpz_ptr __gmp_w, mpq_srcptr __gmp_u); +__inline static size_t __gmpz_size(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +/*@ requires \valid(z1); + requires \valid(z2); + requires \valid(z3); + assigns *z1; +*/ +extern void __gmpz_sub(__mpz_struct * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2, + __mpz_struct const * /*[1]*/ z3); +/*@ requires \valid(z1); + requires \valid(z2); + requires \valid(z3); + assigns *z1; +*/ +extern void __gmpz_tdiv_q(__mpz_struct * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2, + __mpz_struct const * /*[1]*/ z3); +__inline static void __gmpq_abs(mpq_ptr __gmp_w, mpq_srcptr __gmp_u); +__inline static void __gmpq_neg(mpq_ptr __gmp_w, mpq_srcptr __gmp_u); +extern void __gmpq_set(mpq_ptr, mpq_srcptr); +__inline static mp_limb_t __gmpn_add(mp_ptr __gmp_wp, mp_srcptr __gmp_xp, + mp_size_t __gmp_xsize, + mp_srcptr __gmp_yp, + mp_size_t __gmp_ysize); +__inline static mp_limb_t __gmpn_add_1(mp_ptr __gmp_dst, mp_srcptr __gmp_src, + mp_size_t __gmp_size, + mp_limb_t __gmp_n); +extern mp_limb_t __gmpn_add_n(mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +__inline static int __gmpn_cmp(mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, + mp_size_t __gmp_size) __attribute__((__pure__)); +__inline static mp_limb_t __gmpn_neg(mp_ptr __gmp_rp, mp_srcptr __gmp_up, + mp_size_t __gmp_n); +extern int __gmpn_perfect_square_p(mp_srcptr, mp_size_t) __attribute__(( +__pure__)); +extern mp_bitcnt_t __gmpn_popcount(mp_srcptr, mp_size_t) __attribute__(( +__pure__)); +__inline static mp_limb_t __gmpn_sub(mp_ptr __gmp_wp, mp_srcptr __gmp_xp, + mp_size_t __gmp_xsize, + mp_srcptr __gmp_yp, + mp_size_t __gmp_ysize); +__inline static mp_limb_t __gmpn_sub_1(mp_ptr __gmp_dst, mp_srcptr __gmp_src, + mp_size_t __gmp_size, + mp_limb_t __gmp_n); +extern mp_limb_t __gmpn_sub_n(mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +__inline static void __gmpz_abs(mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) { __gmpz_set(__gmp_w,__gmp_u); } + if (__gmp_w->_mp_size >= 0) { __gmp_w->_mp_size = __gmp_w->_mp_size; } + else { __gmp_w->_mp_size = - __gmp_w->_mp_size; } + return; +} + +__inline static int __gmpz_fits_uint_p(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +__inline static int __gmpz_fits_uint_p(mpz_srcptr __gmp_z) +{ + int __retres; + mp_size_t __gmp_n; + mp_ptr __gmp_p; + int tmp; + __gmp_n = (long)__gmp_z->_mp_size; + __gmp_p = __gmp_z->_mp_d; + if (__gmp_n == (mp_size_t)0) { tmp = 1; } + else { + if (__gmp_n == (mp_size_t)1) { + if (*(__gmp_p + 0) <= (mp_limb_t)(~ ((unsigned int)0))) { tmp = 1; } + else { tmp = 0; } + } + else { tmp = 0; } + } + __retres = tmp; + goto return_label; + return_label: /* internal */ + return (__retres); +} + +__inline static int __gmpz_fits_ulong_p(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +__inline static int __gmpz_fits_ulong_p(mpz_srcptr __gmp_z) +{ + int __retres; + mp_size_t __gmp_n; + mp_ptr __gmp_p; + int tmp; + __gmp_n = (long)__gmp_z->_mp_size; + __gmp_p = __gmp_z->_mp_d; + if (__gmp_n == (mp_size_t)0) { tmp = 1; } + else { + if (__gmp_n == (mp_size_t)1) { + if (*(__gmp_p + 0) <= ~ ((unsigned long)0)) { tmp = 1; } + else { tmp = 0; } + } + else { tmp = 0; } + } + __retres = tmp; + goto return_label; + return_label: /* internal */ + return (__retres); +} + +__inline static int __gmpz_fits_ushort_p(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +__inline static int __gmpz_fits_ushort_p(mpz_srcptr __gmp_z) +{ + int __retres; + mp_size_t __gmp_n; + mp_ptr __gmp_p; + int tmp; + __gmp_n = (long)__gmp_z->_mp_size; + __gmp_p = __gmp_z->_mp_d; + if (__gmp_n == (mp_size_t)0) { tmp = 1; } + else { + if (__gmp_n == (mp_size_t)1) { + if (*(__gmp_p + 0) <= (mp_limb_t)((unsigned short)(~ 0))) { tmp = 1; } + else { tmp = 0; } + } + else { tmp = 0; } + } + __retres = tmp; + goto return_label; + return_label: /* internal */ + return (__retres); +} + +/*@ requires \valid(z); + assigns \nothing; */ +__inline static unsigned long __gmpz_get_ui(__mpz_struct const * /*[1]*/ z) __attribute__(( +__pure__)); +__inline static unsigned long __gmpz_get_ui(__mpz_struct const * /*[1]*/ z) +{ + mp_ptr __gmp_p; + mp_size_t __gmp_n; + mp_limb_t __gmp_l; + mp_limb_t tmp; + __gmp_p = z->_mp_d; + __gmp_n = (long)z->_mp_size; + __gmp_l = *(__gmp_p + 0); + if (__gmp_n != (mp_size_t)0) { tmp = __gmp_l; } + else { tmp = (unsigned long)0; } + return (tmp); +} + +__inline static mp_limb_t __gmpz_getlimbn(mpz_srcptr __gmp_z, + mp_size_t __gmp_n) __attribute__(( +__pure__)); +__inline static mp_limb_t __gmpz_getlimbn(mpz_srcptr __gmp_z, + mp_size_t __gmp_n) +{ + mp_limb_t __gmp_result; + long tmp_1; + int tmp_0; + __gmp_result = (unsigned long)0; + { /*undefined sequence*/ + if (__gmp_n >= (mp_size_t)0) { + int tmp; + { /*undefined sequence*/ + if (__gmp_z->_mp_size >= 0) { tmp = __gmp_z->_mp_size; } + else { tmp = - __gmp_z->_mp_size; } + ; + } + if (__gmp_n < (mp_size_t)tmp) { tmp_0 = 1; } + else { tmp_0 = 0; } + } + else { tmp_0 = 0; } + tmp_1 = __builtin_expect((long)(tmp_0 != 0),(long)1); + } + if (tmp_1) { __gmp_result = *(__gmp_z->_mp_d + __gmp_n); } + return (__gmp_result); +} + +/*@ requires \valid(z1); + requires \valid(z2); + assigns *z1; */ +__inline static void __gmpz_neg(__mpz_struct * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2) +{ + if (z1 != z2) { __gmpz_set(z1,z2); } + z1->_mp_size = - z1->_mp_size; + return; +} + +__inline static int __gmpz_perfect_square_p(mpz_srcptr __gmp_a) __attribute__(( +__pure__)); +__inline static int __gmpz_perfect_square_p(mpz_srcptr __gmp_a) +{ + mp_size_t __gmp_asize; + int __gmp_result; + long tmp; + __gmp_asize = (long)__gmp_a->_mp_size; + __gmp_result = __gmp_asize >= (mp_size_t)0; + tmp = __builtin_expect((long)((__gmp_asize > (mp_size_t)0) != 0),(long)1); + if (tmp) { + __gmp_result = __gmpn_perfect_square_p((mp_limb_t const *)__gmp_a->_mp_d, + __gmp_asize); + } + return (__gmp_result); +} + +__inline static mp_bitcnt_t __gmpz_popcount(mpz_srcptr __gmp_u) __attribute__(( +__pure__)); +__inline static mp_bitcnt_t __gmpz_popcount(mpz_srcptr __gmp_u) +{ + mp_size_t __gmp_usize; + mp_bitcnt_t __gmp_result; + long tmp; + __gmp_usize = (long)__gmp_u->_mp_size; + if (__gmp_usize < (mp_size_t)0) { __gmp_result = ~ ((unsigned long)0); } + else { __gmp_result = (unsigned long)0; } + tmp = __builtin_expect((long)((__gmp_usize > (mp_size_t)0) != 0),(long)1); + if (tmp) { + __gmp_result = __gmpn_popcount((mp_limb_t const *)__gmp_u->_mp_d, + __gmp_usize); + } + return (__gmp_result); +} + +__inline static void __gmpz_set_q(mpz_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + __gmpz_tdiv_q(__gmp_w,& __gmp_u->_mp_num,& __gmp_u->_mp_den); + return; +} + +__inline static size_t __gmpz_size(mpz_srcptr __gmp_z) __attribute__(( +__pure__)); +__inline static size_t __gmpz_size(mpz_srcptr __gmp_z) +{ + size_t __retres; + int tmp; + if (__gmp_z->_mp_size >= 0) { tmp = __gmp_z->_mp_size; } + else { tmp = - __gmp_z->_mp_size; } + __retres = (unsigned long)tmp; + return (__retres); +} + +__inline static void __gmpq_abs(mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) { __gmpq_set(__gmp_w,__gmp_u); } + if (__gmp_w->_mp_num._mp_size >= 0) { + __gmp_w->_mp_num._mp_size = __gmp_w->_mp_num._mp_size; + } + else { __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; } + return; +} + +__inline static void __gmpq_neg(mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) { __gmpq_set(__gmp_w,__gmp_u); } + __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; + return; +} + +__inline static mp_limb_t __gmpn_add(mp_ptr __gmp_wp, mp_srcptr __gmp_xp, + mp_size_t __gmp_xsize, + mp_srcptr __gmp_yp, + mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + while (1) { + { + mp_size_t __gmp_i; + mp_limb_t __gmp_x; + __gmp_i = __gmp_ysize; + if (__gmp_i != (mp_size_t)0) { + mp_limb_t tmp_1; + tmp_1 = __gmpn_add_n(__gmp_wp,__gmp_xp,__gmp_yp,__gmp_i); + if (tmp_1) { + while (1) { + mp_size_t tmp; + mp_limb_t tmp_0; + if (__gmp_i >= __gmp_xsize) { + __gmp_c = (unsigned long)1; + goto __gmp_done; + } + __gmp_x = *(__gmp_xp + __gmp_i); + { /*undefined sequence*/ + tmp = __gmp_i; + __gmp_i += (mp_size_t)1; + tmp_0 = (__gmp_x + (mp_limb_t)1) & (~ ((unsigned long)0) >> 0); + *(__gmp_wp + tmp) = tmp_0; + } + if (! (tmp_0 == (mp_limb_t)0)) { break; } + } + } + } + if (__gmp_wp != __gmp_xp) { + while (1) { + { + mp_size_t __gmp_j; + __gmp_j = __gmp_i; + while (__gmp_j < __gmp_xsize) { + *(__gmp_wp + __gmp_j) = *(__gmp_xp + __gmp_j); + __gmp_j += (mp_size_t)1; + } + } + + break; + } + } + __gmp_c = (unsigned long)0; + __gmp_done: ; + } + + break; + } + return (__gmp_c); +} + +__inline static mp_limb_t __gmpn_add_1(mp_ptr __gmp_dst, mp_srcptr __gmp_src, + mp_size_t __gmp_size, + mp_limb_t __gmp_n) +{ + mp_limb_t __gmp_c; + while (1) { + { + mp_size_t __gmp_i; + mp_limb_t __gmp_x; + mp_limb_t __gmp_r; + __gmp_x = *(__gmp_src + 0); + __gmp_r = __gmp_x + __gmp_n; + *(__gmp_dst + 0) = __gmp_r; + if (__gmp_r < __gmp_n) { + __gmp_c = (unsigned long)1; + __gmp_i = (long)1; + while (__gmp_i < __gmp_size) { + __gmp_x = *(__gmp_src + __gmp_i); + __gmp_r = __gmp_x + (mp_limb_t)1; + *(__gmp_dst + __gmp_i) = __gmp_r; + __gmp_i += (mp_size_t)1; + if (! (__gmp_r < (mp_limb_t)1)) { + if (__gmp_src != __gmp_dst) { + while (1) { + { + mp_size_t __gmp_j; + __gmp_j = __gmp_i; + while (__gmp_j < __gmp_size) { + *(__gmp_dst + __gmp_j) = *(__gmp_src + __gmp_j); + __gmp_j += (mp_size_t)1; + } + } + + break; + } + } + __gmp_c = (unsigned long)0; + break; + } + } + } + else { + if (__gmp_src != __gmp_dst) { + while (1) { + { + mp_size_t __gmp_j_0; + __gmp_j_0 = (long)1; + while (__gmp_j_0 < __gmp_size) { + *(__gmp_dst + __gmp_j_0) = *(__gmp_src + __gmp_j_0); + __gmp_j_0 += (mp_size_t)1; + } + } + + break; + } + } + __gmp_c = (unsigned long)0; + } + } + + break; + } + return (__gmp_c); +} + +__inline static int __gmpn_cmp(mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, + mp_size_t __gmp_size) __attribute__((__pure__)); +__inline static int __gmpn_cmp(mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, + mp_size_t __gmp_size) +{ + int __gmp_result; + while (1) { + { + mp_size_t __gmp_i; + mp_limb_t __gmp_x; + mp_limb_t __gmp_y; + __gmp_result = 0; + __gmp_i = __gmp_size; + while (1) { + __gmp_i -= (mp_size_t)1; + if (! (__gmp_i >= (mp_size_t)0)) { break; } + __gmp_x = *(__gmp_xp + __gmp_i); + __gmp_y = *(__gmp_yp + __gmp_i); + if (__gmp_x != __gmp_y) { + if (__gmp_x > __gmp_y) { __gmp_result = 1; } + else { __gmp_result = -1; } + break; + } + } + } + + break; + } + return (__gmp_result); +} + +__inline static mp_limb_t __gmpn_sub(mp_ptr __gmp_wp, mp_srcptr __gmp_xp, + mp_size_t __gmp_xsize, + mp_srcptr __gmp_yp, + mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + while (1) { + { + mp_size_t __gmp_i; + mp_limb_t __gmp_x; + __gmp_i = __gmp_ysize; + if (__gmp_i != (mp_size_t)0) { + mp_limb_t tmp_0; + tmp_0 = __gmpn_sub_n(__gmp_wp,__gmp_xp,__gmp_yp,__gmp_i); + if (tmp_0) { + while (1) { + mp_size_t tmp; + if (__gmp_i >= __gmp_xsize) { + __gmp_c = (unsigned long)1; + goto __gmp_done; + } + __gmp_x = *(__gmp_xp + __gmp_i); + { /*undefined sequence*/ + tmp = __gmp_i; + __gmp_i += (mp_size_t)1; + *(__gmp_wp + tmp) = (__gmp_x - (mp_limb_t)1) & (~ ((unsigned long)0) >> 0); + } + if (! (__gmp_x == (mp_limb_t)0)) { break; } + } + } + } + if (__gmp_wp != __gmp_xp) { + while (1) { + { + mp_size_t __gmp_j; + __gmp_j = __gmp_i; + while (__gmp_j < __gmp_xsize) { + *(__gmp_wp + __gmp_j) = *(__gmp_xp + __gmp_j); + __gmp_j += (mp_size_t)1; + } + } + + break; + } + } + __gmp_c = (unsigned long)0; + __gmp_done: ; + } + + break; + } + return (__gmp_c); +} + +__inline static mp_limb_t __gmpn_sub_1(mp_ptr __gmp_dst, mp_srcptr __gmp_src, + mp_size_t __gmp_size, + mp_limb_t __gmp_n) +{ + mp_limb_t __gmp_c; + while (1) { + { + mp_size_t __gmp_i; + mp_limb_t __gmp_x; + mp_limb_t __gmp_r; + __gmp_x = *(__gmp_src + 0); + __gmp_r = __gmp_x - __gmp_n; + *(__gmp_dst + 0) = __gmp_r; + if (__gmp_x < __gmp_n) { + __gmp_c = (unsigned long)1; + __gmp_i = (long)1; + while (__gmp_i < __gmp_size) { + __gmp_x = *(__gmp_src + __gmp_i); + __gmp_r = __gmp_x - (mp_limb_t)1; + *(__gmp_dst + __gmp_i) = __gmp_r; + __gmp_i += (mp_size_t)1; + if (! (__gmp_x < (mp_limb_t)1)) { + if (__gmp_src != __gmp_dst) { + while (1) { + { + mp_size_t __gmp_j; + __gmp_j = __gmp_i; + while (__gmp_j < __gmp_size) { + *(__gmp_dst + __gmp_j) = *(__gmp_src + __gmp_j); + __gmp_j += (mp_size_t)1; + } + } + + break; + } + } + __gmp_c = (unsigned long)0; + break; + } + } + } + else { + if (__gmp_src != __gmp_dst) { + while (1) { + { + mp_size_t __gmp_j_0; + __gmp_j_0 = (long)1; + while (__gmp_j_0 < __gmp_size) { + *(__gmp_dst + __gmp_j_0) = *(__gmp_src + __gmp_j_0); + __gmp_j_0 += (mp_size_t)1; + } + } + + break; + } + } + __gmp_c = (unsigned long)0; + } + } + + break; + } + return (__gmp_c); +} + +__inline static mp_limb_t __gmpn_neg(mp_ptr __gmp_rp, mp_srcptr __gmp_up, + mp_size_t __gmp_n) +{ + mp_limb_t __gmp_ul; + mp_limb_t __gmp_cy; + __gmp_cy = (unsigned long)0; + while (1) { + { + mp_srcptr tmp; + mp_ptr tmp_0; + { /*undefined sequence*/ tmp = __gmp_up; __gmp_up ++; __gmp_ul = *tmp; + } + { /*undefined sequence*/ + tmp_0 = __gmp_rp; + __gmp_rp ++; + *tmp_0 = - __gmp_ul - __gmp_cy; + } + __gmp_cy |= (unsigned long)(__gmp_ul != (mp_limb_t)0); + } + + __gmp_n -= (mp_size_t)1; + if (! (__gmp_n != (mp_size_t)0)) { break; } + } + return (__gmp_cy); +} + +/*@ terminates \false; + ensures \false; + assigns \nothing; */ +extern void exit(int status); +void e_acsl_fail(char *msg) +{ + printf("%s\n",msg); + exit(1); + return; +} + +/*@ ensures \result ≡ (int)(\old(x)-\old(x)); */ +int f(int x) +{ + int e_acsl_1; + int e_acsl_3; + e_acsl_3 = x; + e_acsl_1 = x; + x = 0; + { + mpz_t e_acsl_2; + mpz_t e_acsl_4; + int e_acsl_5; + __gmpz_init_set_si((__mpz_struct *)(e_acsl_2),(long)e_acsl_1); + __gmpz_init((__mpz_struct *)(e_acsl_4)); + __gmpz_sub((__mpz_struct *)(e_acsl_4),(__mpz_struct const *)(e_acsl_2), + (__mpz_struct const *)(e_acsl_2)); + e_acsl_5 = (int)__gmpz_get_si((__mpz_struct const *)(e_acsl_4)); + if (! (x == e_acsl_5)) { + e_acsl_fail((char *)"(\\result == (int)(\\old(x)-\\old(x)))"); + } + __gmpz_clear((__mpz_struct *)(e_acsl_2)); + __gmpz_clear((__mpz_struct *)(e_acsl_4)); + return (x); + } + +} + +int Y = 1; +/*@ ensures \result ≡ Y; */ +int g(int x) +{ + if (! (x == Y)) { e_acsl_fail((char *)"(\\result == Y)"); } + return (x); +} + +/*@ ensures \result ≡ 0; */ +int h(void) +{ + int __retres; + __retres = 0; + { + mpz_t e_acsl_1; + mpz_t e_acsl_2; + int e_acsl_3; + __gmpz_init_set_si((__mpz_struct *)(e_acsl_1),(long)__retres); + __gmpz_init_set_si((__mpz_struct *)(e_acsl_2),(long)0); + e_acsl_3 = __gmpz_cmp((__mpz_struct const *)(e_acsl_1), + (__mpz_struct const *)(e_acsl_2)); + if (! (e_acsl_3 == 0)) { e_acsl_fail((char *)"(\\result == 0)"); } + __gmpz_clear((__mpz_struct *)(e_acsl_1)); + __gmpz_clear((__mpz_struct *)(e_acsl_2)); + return (__retres); + } + +} + +int main(void) +{ + int __retres; + f(1); + g(Y); + h(); + __retres = 0; + return (__retres); +} + + diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.err.oracle b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.err.oracle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.res.oracle b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.res.oracle new file mode 100644 index 00000000000..6728e58d32b --- /dev/null +++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/result.res.oracle @@ -0,0 +1,217 @@ +[e-acsl] memoized \old(x) +[e-acsl] memoized \old(x) +[e-acsl] memoized \old(x)-\old(x) +tests/e-acsl-runtime/result.i:7:[e-acsl] warning: missing guard for ensuring that the given integer is C-representable +[e-acsl] memoized \result +[e-acsl] memoized 0 +[value] Analyzing a complete application starting at main +[value] Computing initial state +[value] Initial state computed +[value] Values of globals at initialization + Y ∈ {1} +[value] computing for function f <- main. + Called from PROJECT_FILE.i:188. +[value] computing for function mpz_init_set_si <- f <- main. + Called from PROJECT_FILE.i:143. +PROJECT_FILE.i:33:[value] Function mpz_init_set_si: postcondition got status valid. +[value] Done for function mpz_init_set_si +[value] computing for function mpz_init <- f <- main. + Called from PROJECT_FILE.i:144. +PROJECT_FILE.i:21:[value] Function mpz_init: postcondition got status valid. +[value] Done for function mpz_init +[value] computing for function mpz_sub <- f <- main. + Called from PROJECT_FILE.i:145. +PROJECT_FILE.i:70:[value] Function mpz_sub: precondition got status valid. +PROJECT_FILE.i:71:[value] Function mpz_sub: precondition got status valid. +PROJECT_FILE.i:72:[value] Function mpz_sub: precondition got status valid. +[value] Done for function mpz_sub +[value] computing for function mpz_get_si <- f <- main. + Called from PROJECT_FILE.i:146. +PROJECT_FILE.i:96:[value] Function mpz_get_si: precondition got status valid. +[value] Done for function mpz_get_si +[value] computing for function e_acsl_fail <- f <- main. + Called from PROJECT_FILE.i:148. +[value] computing for function printf <- e_acsl_fail <- f <- main. + Called from PROJECT_FILE.i:129. +[value] Done for function printf +[value] computing for function exit <- e_acsl_fail <- f <- main. + Called from PROJECT_FILE.i:129. +PROJECT_FILE.i:119:[value] Function exit: postcondition got status invalid. +[value] Done for function exit +[value] Recording results for e_acsl_fail +[value] Done for function e_acsl_fail +[value] computing for function mpz_clear <- f <- main. + Called from PROJECT_FILE.i:150. +PROJECT_FILE.i:43:[value] Function mpz_clear: precondition got status valid. +[value] Done for function mpz_clear +[value] computing for function mpz_clear <- f <- main. + Called from PROJECT_FILE.i:151. +[value] Done for function mpz_clear +PROJECT_FILE.i:131:[value] Function f: postcondition got status valid. +[value] Recording results for f +[value] Done for function f +[value] computing for function g <- main. + Called from PROJECT_FILE.i:189. +PROJECT_FILE.i:158:[value] Function g: postcondition got status valid. +[value] Recording results for g +[value] Done for function g +[value] computing for function h <- main. + Called from PROJECT_FILE.i:190. +[value] computing for function mpz_init_set_si <- h <- main. + Called from PROJECT_FILE.i:174. +[value] Done for function mpz_init_set_si +[value] computing for function mpz_init_set_si <- h <- main. + Called from PROJECT_FILE.i:175. +[value] Done for function mpz_init_set_si +[value] computing for function mpz_cmp <- h <- main. + Called from PROJECT_FILE.i:176. +PROJECT_FILE.i:49:[value] Function mpz_cmp: precondition got status valid. +PROJECT_FILE.i:50:[value] Function mpz_cmp: precondition got status valid. +[value] Done for function mpz_cmp +[value] computing for function e_acsl_fail <- h <- main. + Called from PROJECT_FILE.i:177. +[value] computing for function printf <- e_acsl_fail <- h <- main. + Called from PROJECT_FILE.i:129. +[value] Done for function printf +[value] computing for function exit <- e_acsl_fail <- h <- main. + Called from PROJECT_FILE.i:129. +[value] Done for function exit +[value] Recording results for e_acsl_fail +[value] Done for function e_acsl_fail +[value] computing for function mpz_clear <- h <- main. + Called from PROJECT_FILE.i:178. +[value] Done for function mpz_clear +[value] computing for function mpz_clear <- h <- main. + Called from PROJECT_FILE.i:179. +[value] Done for function mpz_clear +PROJECT_FILE.i:165:[value] Function h: postcondition got status valid. +[value] Recording results for h +[value] Done for function h +[value] Recording results for main +[value] done for function main +[value] ====== VALUES COMPUTED ====== +[value] Values for function g: +[value] Values for function e_acsl_fail: + NON TERMINATING FUNCTION +[value] Values for function f: + x ∈ {0} + e_acsl_1 ∈ {1} + e_acsl_3 ∈ {1} +[value] Values for function h: + __retres ∈ {0} +[value] Values for function main: + __retres ∈ {0} +/* Generated by Frama-C */ +struct __anonstruct___mpz_struct_1 { + int _mp_alloc ; + int _mp_size ; + unsigned long *_mp_d ; +}; +typedef struct __anonstruct___mpz_struct_1 __mpz_struct; +typedef __mpz_struct mpz_t[1]; +/*@ ensures \valid(\old(x)); + assigns *x; */ +extern void mpz_init(__mpz_struct * /*[1]*/ x); +/*@ ensures \valid(\old(z)); + assigns *z; + assigns *z \from n; */ +extern void mpz_init_set_si(__mpz_struct * /*[1]*/ z, long n); +/*@ requires \valid(x); + assigns *x; */ +extern void mpz_clear(__mpz_struct * /*[1]*/ x); +/*@ requires \valid(z1); + requires \valid(z2); + assigns \nothing; */ +extern int mpz_cmp(__mpz_struct const * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2); +/*@ requires \valid(z1); + requires \valid(z2); + requires \valid(z3); + assigns *z1; +*/ +extern void mpz_sub(__mpz_struct * /*[1]*/ z1, + __mpz_struct const * /*[1]*/ z2, + __mpz_struct const * /*[1]*/ z3); +/*@ requires \valid(z); + assigns \nothing; */ +extern long mpz_get_si(__mpz_struct const * /*[1]*/ z); +/*@ terminates \false; + ensures \false; + assigns \nothing; */ +extern void exit(int status); +/*@ assigns \nothing; */ +extern int printf(char const * , ...); +void e_acsl_fail(char *msg) +{ + printf("%s\n",msg); + exit(1); + return; +} + +/*@ ensures \result ≡ (int)(\old(x)-\old(x)); */ +int f(int x) +{ + int e_acsl_1; + int e_acsl_3; + e_acsl_3 = x; + e_acsl_1 = x; + x = 0; + { + mpz_t e_acsl_2; + mpz_t e_acsl_4; + int e_acsl_5; + mpz_init_set_si((__mpz_struct *)(e_acsl_2),(long)e_acsl_1); + mpz_init((__mpz_struct *)(e_acsl_4)); + mpz_sub((__mpz_struct *)(e_acsl_4),(__mpz_struct const *)(e_acsl_2), + (__mpz_struct const *)(e_acsl_2)); + e_acsl_5 = (int)mpz_get_si((__mpz_struct const *)(e_acsl_4)); + if (! (x == e_acsl_5)) { + e_acsl_fail((char *)"(\\result == (int)(\\old(x)-\\old(x)))"); + } + mpz_clear((__mpz_struct *)(e_acsl_2)); + mpz_clear((__mpz_struct *)(e_acsl_4)); + return (x); + } + +} + +int Y = 1; +/*@ ensures \result ≡ Y; */ +int g(int x) +{ + if (! (x == Y)) { e_acsl_fail((char *)"(\\result == Y)"); } + return (x); +} + +/*@ ensures \result ≡ 0; */ +int h(void) +{ + int __retres; + __retres = 0; + { + mpz_t e_acsl_1; + mpz_t e_acsl_2; + int e_acsl_3; + mpz_init_set_si((__mpz_struct *)(e_acsl_1),(long)__retres); + mpz_init_set_si((__mpz_struct *)(e_acsl_2),(long)0); + e_acsl_3 = mpz_cmp((__mpz_struct const *)(e_acsl_1), + (__mpz_struct const *)(e_acsl_2)); + if (! (e_acsl_3 == 0)) { e_acsl_fail((char *)"(\\result == 0)"); } + mpz_clear((__mpz_struct *)(e_acsl_1)); + mpz_clear((__mpz_struct *)(e_acsl_2)); + return (__retres); + } + +} + +int main(void) +{ + int __retres; + f(1); + g(Y); + h(); + __retres = 0; + return (__retres); +} + + diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/result.i b/src/plugins/e-acsl/tests/e-acsl-runtime/result.i new file mode 100644 index 00000000000..b18c3c412ae --- /dev/null +++ b/src/plugins/e-acsl/tests/e-acsl-runtime/result.i @@ -0,0 +1,31 @@ +/* run.config + COMMENT: \result + EXECNOW: LOG gen_result.c BIN gen_result.out FRAMAC_SHARE=./share @frama-c@ ./tests/e-acsl-runtime/result.i -e-acsl-project p -e-acsl-include-headers -then-on p -print -ocode ./tests/e-acsl-runtime/result/gen_result.c > /dev/null && gcc -o ./tests/e-acsl-runtime/result/gen_result.out ./tests/e-acsl-runtime/result/gen_result.c -lgmp +*/ + +// && ./tests/e-acsl-runtime/result/gen_result.out +/*@ ensures \result == (int)(x - x); */ +int f(int x) { + x = 0; + return x; } + +int Y = 1; + +// does not work since it is converted into \result == \old(x) and, +// in this particular case, the pre-state and the post-state are the same and +// it does not work yet (related to issue in at.i). +// /*@ ensures \result == x; */ +/*@ ensures \result == Y; */ +int g(int x) { + return x; +} + +/*@ ensures \result == 0; */ +int h() { return 0; } + +int main(void) { + f(1); + g(Y); + h(); + return 0; +} diff --git a/src/plugins/e-acsl/visit.ml b/src/plugins/e-acsl/visit.ml index 84de17b01a6..1d852dd77cc 100644 --- a/src/plugins/e-acsl/visit.ml +++ b/src/plugins/e-acsl/visit.ml @@ -145,7 +145,16 @@ let constant_to_exp ?(loc=Location.unknown) = function let rec thost_to_host env = function | TVar { lv_origin = Some v } -> Var v, env | TVar { lv_origin = None } -> Misc.not_yet "logic variable" - | TResult _typ -> Misc.not_yet "\\result" + | TResult _typ -> + let vis = Env.get_visitor env in + let kf = Extlib.the vis#current_kf in + let stmt = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> assert false + in + (match stmt.skind with + | Return(Some { enode = Lval (lhost, NoOffset) }, _) -> lhost, env + | _ -> assert false) | TMem t -> let e, env = term_to_exp env (Ctype intType) t in Options.warning ~source:(fst e.eloc) ~once:true @@ -307,7 +316,7 @@ and context_insensitive_term_to_exp env t = That is this variable which is the resulting expression. ACSL typing rule ensures that the type of this variable is the same as the one of [e]. *) - let res, env = + let res, new_env = Env.new_var ~global:true env (Some t) (typeOf e) (fun lv' e' -> @@ -316,15 +325,16 @@ and context_insensitive_term_to_exp env t = initialize it. *) new_v := Some (lv', e'); []) in - let env_ref = ref env in - (* visitor modifying in place the labeled statement in order to store [e] in - the resulting variable at this location which is the only correct one. *) + let env_ref = ref new_env in + (* visitor modifying in place the labeled statement in order to store [e] + in the resulting variable at this location which is the only correct + one. *) let o = object inherit Visitor.frama_c_inplace method vstmt_aux stmt = let new_lv, new_e = Extlib.the !new_v in - (* either a standard C affectation or an mpz one according to type of - [e] *) + (* either a standard C affectation or an mpz one according to type of + [e] *) let new_stmt = if Mpz.is_t (typeOf new_e) then Mpz.init_set new_e e @@ -332,23 +342,21 @@ and context_insensitive_term_to_exp env t = mkStmtOneInstr ~valid_sid:true (Set((Var new_lv, NoOffset), e, Location.unknown)) in - assert (!env_ref == env); - (* generate the new block of code for the labeled statement and the - corresponding environment *) - let block, env = - Env.pop_and_get env new_stmt ~global_clear:false Env.Middle + assert (!env_ref == new_env); + (* generate the new block of code for the labeled statement and the + corresponding environment *) + let block, new_env = + Env.pop_and_get new_env new_stmt ~global_clear:false Env.Middle in let pre = match label with | LogicLabel(_, s) when s = "Here" || s = "Post" -> true | StmtLabel _ | LogicLabel _ -> false in - env_ref := Env.extend_stmt_in_place env stmt ~pre block; -(* Options.feedback "the new stmt is (sid %d): %a" stmt.sid - Stmt.pretty stmt;*) + env_ref := Env.extend_stmt_in_place new_env stmt ~pre block; ChangeTo stmt end in - let bhv = (Env.get_visitor env)#behavior in + let bhv = (Env.get_visitor new_env)#behavior in let new_stmt = Visitor.visitFramacStmt o (get_stmt bhv stmt) in set_stmt bhv stmt new_stmt; res, !env_ref, false @@ -379,11 +387,11 @@ and comparison_to_exp ?(loc=Location.unknown) ?e1 env bop t1 t2 t_opt = let ctx = match e1 with | None -> principal_type_from_term t1 t2 | Some(_, ctx) -> -(* Options.feedback "principality oriented by %a" d_logic_type ctx;*) + (* Options.feedback "principality oriented by %a" d_logic_type ctx;*) principal_type_from_term { t1 with term_type = ctx } t2 in -(* Options.feedback "principal type of %a and %a is %a" - d_term t1 d_term t2 d_logic_type ctx;*) + (* Options.feedback "principal type of %a and %a is %a" + d_term t1 d_term t2 d_logic_type ctx;*) let e1, env = match e1 with | None -> term_to_exp env ctx t1 | Some(e1, ctx1) when Cil_datatype.Logic_type.equal ctx ctx1 -> e1, env -- GitLab