From 2a3171cf6e8e45189331ac9cd17fb3ec09f5a3ce Mon Sep 17 00:00:00 2001 From: Julien Signoles <julien.signoles@cea.fr> Date: Fri, 23 Aug 2019 17:45:45 +0200 Subject: [PATCH] [translate] improve add_cast --- src/plugins/e-acsl/translate.ml | 59 +++++++++++++++------------------ 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/plugins/e-acsl/translate.ml b/src/plugins/e-acsl/translate.ml index 4bb94006097..a969738ea00 100644 --- a/src/plugins/e-acsl/translate.ml +++ b/src/plugins/e-acsl/translate.ml @@ -93,46 +93,37 @@ let add_cast ~loc ?name env ctx strnum t_opt e = e, env | Some ctx -> let ty = Cil.typeOf e in - (* TODO RATIONAL: - spaghetti code below. Would be nice to be improved (or at least - more commented) ==> boolean pattern matching? *) - if Gmp.Z.is_t ctx then - if Gmp.Z.is_t ty then - e, env - else if Real.is_t ty then + match Gmp.Z.is_t ty, Gmp.Z.is_t ctx with + | true, true -> + (* Z --> Z *) + e, env + | false, true -> + if Real.is_t ty then + (* R --> Z *) Real.cast_to_z ~loc ?name e env else - (* Convert the C integer into a mpz. - Remember: - - very long constants have been temporary converted into strings; - - possible to get a non integral type (or Gmp.z_t) with a non-one in - the case of \null *) + (* C integer --> Z *) let e = - if Cil.isIntegralType ty || strnum = Str_Z then - e - else if not (Cil.isIntegralType ty) && strnum = C_number then + if not (Cil.isIntegralType ty) && strnum = C_number then + (* special case for \null that must be casted to long: it is the + only non integral value that can be seen as an integer, while the + type system infers that it is C-representable (see + tests/runtime/null.i) *) Cil.mkCast e Cil.longType (* \null *) - else begin - (* TODO RATIONAL: this case seems to be possible: - getting a very long rational constants (so a string) to be casted - to an integer *) - assert (not (Cil.isIntegralType ty) && strnum = Str_R); - assert false - end + else + e in mk_mpz e - else if Real.is_t ctx then - if Real.is_t (Cil.typeOf e) then e, env - else Real.mk_real ~loc ?name e env t_opt - else (* the context is neither MPZ nor MPQ *) - (* handle a C-integer context *) - if Gmp.Z.is_t ty || strnum = Str_Z then - (* we get an mpz, but it fits into a C integer: convert it *) + | _, false -> + if Real.is_t ctx then + if Real.is_t (Cil.typeOf e) then (* R --> R *) e, env + else (* C integer or Z --> R *) Real.mk_real ~loc ?name e env t_opt + else if Gmp.Z.is_t ty || strnum = Str_Z then + (* Z --> C type or the integer is represented by a string: + anyway, it fits into a C integer: convert it *) let fname, new_ty = - if Cil.isSignedInteger ctx then - "__gmpz_get_si", Cil.longType - else - "__gmpz_get_ui", Cil.ulongType + if Cil.isSignedInteger ctx then "__gmpz_get_si", Cil.longType + else "__gmpz_get_ui", Cil.ulongType in let _, e, env = Env.new_var @@ -145,8 +136,10 @@ let add_cast ~loc ?name env ctx strnum t_opt e = in e, env else if Real.is_t ty || strnum = Str_R then + (* R --> C type or the real is represented by a string *) Real.add_cast ~loc ?name e env ctx else + (* C type --> another C type *) Cil.mkCastT ~force:false ~e ~oldt:ty ~newt:ctx, env let constant_to_exp ~loc t c = -- GitLab