let rec ctype_of_data l = match l with
      | F.D1null | F.D1base _ -> Cil.voidPtrType
      | F.D1proj (_, F.Pfield f) -> f.ftype
      | F.D1proj (l, F.Pidx _) -> Cil.typeOf_array_elem (ctype_of_data l)
      | F.D1addr (vi,_) -> TPtr (vi.vtype, [])
      | F.D1var (Some (vi, _), _) -> vi.vtype
      | F.D1var (None,v) ->
          let t = match F.ctype_of_fvar v with
            | Some t -> t
            | None -> unsupported "unknown type of %a" F.pp_var v
          in t
      | F.D1depl (_, F.Pfield f) -> TPtr (f.ftype, [])
      | F.D1depl (l, F.Pidx _) ->
          let t_addr_array = ctype_of_data l in
          let t_array = Cil.typeOf_pointed t_addr_array in
          let t_elem = Cil.typeOf_array_elem t_array in
          TPtr (t_elem, [])
      | F.D1indir (l) -> Cil.typeOf_pointed (ctype_of_data l)
      | F.D1shift (l, _) -> ctype_of_data l
      | F.D1mu (l, _, _) -> ctype_of_data l
      | F.D1muRange (l, _) -> ctype_of_data l
      | F.D1muI (l, _, _) -> ctype_of_data l
      | F.D1muIrange (l, _) -> ctype_of_data l