let get_lval_assertion (lv : lval) =
  (* one has to build assertions for:
     - pointer dereferencing: only if lval host is of the form (Mem expr)
     - array access: several may occur, one for each offset of the form (Index _,_)
  *)

  (* so we :
     A. compute all assertions for array accesses by
       1. transforming the offset recurvise structure
          in an ad hoc list (offsets_as_list)
       2. keeping offsets which are array accesses (all_array_offsets)
       3. rebuilding Cil offsets from these (final_array_offsets)
       4. building lvals and terms from these
          (final_array_lvals, final_array_terms)
     B. add an assertion for a potential pointer dereferencing
        (lval lv's host is a Mem expr), unless it is a function pointer
        dereferencing (in which case we emit a warning))
  *)

  let (lhost, init_offset) = lv in
  let rec fetch_all_offsets acc off =
    match off with
      | NoOffset -> acc
      | Field (fi, next_off) -> fetch_all_offsets ((MyField fi) :: acc) next_off
      | Index (e, next_off) -> fetch_all_offsets ((MyIndex e) :: acc) next_off
  in let offsets_as_list = List.rev (fetch_all_offsets [] init_offset)
  in let all_array_offsets =
      fst (
        List.fold_left
          (fun (acc_off,acc_prefix) moff ->
             match moff with
               | MyIndex _ ->
                   ((moff :: acc_prefix) :: acc_off, moff :: acc_prefix)
               | _ -> (acc_off, moff :: acc_prefix)
          ) ([],[]) offsets_as_list)

  in let rec build_offset_from_list off_list =
    match off_list with
      | [] -> NoOffset
      | (MyField fi) :: tl -> Field (fi, build_offset_from_list tl)
      | (MyIndex e) :: tl -> Index (e, build_offset_from_list tl)
  in let final_array_offsets =
    List.map
      (fun off_list ->
         build_offset_from_list (List.rev off_list)
      ) all_array_offsets
(*
  in let () =
    debug "Final list of offsets is\n" ;
    List.iter (fun off  -> debug "%a\n" d_offset off) final_array_offsets
*)

  in let final_array_lvals = (List.map (fun off -> (lhost,off)) final_array_offsets)
  in let final_array_terms =
      List.fold_left
        (fun acc lv ->
           if isFunctionType (typeOfLval lv) then (
             rte_warn "no predicate available yet to check validity of function pointer dereferencing %a"
               Cil.d_lval lv
             ;
             acc)
           else
             (translate_C_expr_to_term ~cast:false 
                (mkAddrOf ~loc:(CurrentLoc.get())lv)) 
             :: acc)
        []
        final_array_lvals
  in let final_terms =
      match lv with
        | Mem exp, _ ->
            if isFunctionType (typeOfLval lv) then (
              rte_warn "no predicate available yet to check validity of function pointer dereferencing %a"
                Cil.d_lval lv
              ;
              final_array_terms
            ) else
              (translate_C_expr_to_term ~cast:false exp) :: final_array_terms
        | Var _, _ -> final_array_terms
  in List.map (fun t -> (Logic_const.pvalid t, None) ) final_terms