diff --git a/Changelog b/Changelog
index aacc4b81d5e9f897a7bc53bc49984711c81523be..eb55a0f193c38649f62eacc08d6d786ed110d9b2 100644
--- a/Changelog
+++ b/Changelog
@@ -18,6 +18,10 @@
 Open Source Release <next-release>
 ###############################################################################
 
+-*  Kernel    [2025-02-13] ACSL arrays can have an arbitrary term as length,
+              provided it can be evaluated to an integer constant.
+              Fixes ##2695 and #@1413
+o!  Kernel    [2025-02-13] Move some functions from Logic_typing to Logic_utils
 o   Kernel    [2025-02-05] New parameter builder `Float` for decimal
               command-line parameters.
 o!  Kernel    [2025-02-05] Remove the parameter `Functor_info` for every
diff --git a/src/kernel_internals/parsing/logic_parser.mly b/src/kernel_internals/parsing/logic_parser.mly
index ddcd31fd94fbc2832557e86d476d56dc10232114..63bc207ce6c3e062ed1efad68f3e8476f871a0b8 100644
--- a/src/kernel_internals/parsing/logic_parser.mly
+++ b/src/kernel_internals/parsing/logic_parser.mly
@@ -715,9 +715,8 @@ constant:
 ;
 
 array_size:
-| INT_CONSTANT { ASinteger $1 }
-| full_identifier { ASidentifier $1 }
-| /* empty */ { ASnone }
+| lexpr {Some $1}
+| /* empty */ { None }
 ;
 
 var_spec_bis:
diff --git a/src/kernel_internals/typing/unfold_loops.ml b/src/kernel_internals/typing/unfold_loops.ml
index 00acccab823e4902ae8a27076c2dd69a95cd7b1c..0803899a600f3b5e300ffd8c0c5ac6c8ce620f2d 100644
--- a/src/kernel_internals/typing/unfold_loops.ml
+++ b/src/kernel_internals/typing/unfold_loops.ml
@@ -38,7 +38,7 @@ let empty_info =
 
 let update_info global_find_init emitter info spec =
   match spec with
-  | {term_type=typ}  when Logic_typing.is_integral_type typ ->
+  | {term_type=typ}  when Logic_utils.is_integral_type typ ->
     if Option.is_some info.unroll_number && not info.ignore_unroll then begin
       Kernel.warning ~once:true ~current:true
         "ignoring unfolding directive (directive already defined)";
diff --git a/src/kernel_services/analysis/logic_deps.ml b/src/kernel_services/analysis/logic_deps.ml
index 31981c9d5f412332dc646103ebb3ea71b9924730..8016760c61ce48ba1640a5496aa5fd4438946d4b 100644
--- a/src/kernel_services/analysis/logic_deps.ml
+++ b/src/kernel_services/analysis/logic_deps.ml
@@ -369,7 +369,7 @@ let populate_zone ctx visit cil_node current_zones =
         (* Dependencies of [\initialized(p)] or [\dangling(p)] are the
             dependencies of [*p]. *)
         if is_same_label current_label lbl then (
-          let typ = Logic_typing.type_of_pointed t.term_type in
+          let typ = Logic_utils.type_of_pointed t.term_type in
           let tlv = Cil.mkTermMem ~addr:t ~off:TNoOffset in
           let tlv' = Logic_const.term (TLval tlv) typ in
           self#do_term_lval tlv';
diff --git a/src/kernel_services/ast_printing/logic_print.ml b/src/kernel_services/ast_printing/logic_print.ml
index 30188295ad06b52857273e6ecf26fcdc767786d4..349ef74b0b63c4bfca82d4be35759ea7c323179d 100644
--- a/src/kernel_services/ast_printing/logic_print.ml
+++ b/src/kernel_services/ast_printing/logic_print.ml
@@ -26,10 +26,49 @@ open Format
 open Pretty_utils
 open Logic_ptree
 
-let print_array_size fmt = function
-  | ASidentifier s
-  | ASinteger s -> pp_print_string fmt s
-  | ASnone -> ()
+let get_relation_string = function
+    Lt -> "<" | Gt -> ">" | Le -> "<=" | Ge -> ">=" | Eq -> "==" | Neq -> "!="
+
+let get_binop_string = function
+    Badd -> "+"
+  | Bsub -> "-"
+  | Bmul -> "*"
+  | Bdiv -> "/"
+  | Bmod -> "%"
+  | Bbw_and -> "&"
+  | Bbw_or -> "|"
+  | Bbw_xor -> "^"
+  | Blshift -> "<<"
+  | Brshift -> ">>"
+
+let get_unop_string = function
+    Uminus -> "-" | Ustar -> "*" | Uamp -> "&" | Ubw_not -> "~"
+
+let getParenthLevel e =
+  match e.lexpr_node with
+  | PLnamed _ -> 95
+  | PLlambda _ | PLlet _ | PLrange _ -> 90
+  | PLforall _ | PLexists _ -> 87
+  | PLimplies _ | PLiff _ -> 85
+  | PLand _ | PLor _ | PLxor _ -> 80
+  | PLif _ -> 77
+  | PLbinop (_,(Bbw_and | Bbw_or | Bbw_xor),_) -> 75
+  | PLrepeat _ -> 72
+  | PLrel _ -> 70
+  | PLbinop (_,(Badd|Bsub|Blshift|Brshift),_) -> 60
+  | PLbinop (_,(Bmul|Bdiv|Bmod),_) -> 40
+  | PLunop ((Uamp|Uminus|Ubw_not),_) | PLcast _ | PLnot _ -> 30
+  | PLunop (Ustar,_) | PLdot _ | PLarrow _ | PLarrget _
+  | PLsizeof _ | PLsizeofE _ -> 20
+  | PLapp _ | PLold _ | PLat _
+  | PLoffset _ | PLbase_addr _ | PLblock_length _
+  | PLupdate _  | PLinitField _ | PLinitIndex _
+  | PLvalid _ | PLvalid_read _ | PLobject_pointer _ | PLvalid_function _
+  | PLinitialized _ | PLdangling _
+  | PLallocable _ | PLfreeable _ | PLfresh _
+  | PLseparated _ | PLunion _ | PLinter _ -> 10
+  | PLvar _ | PLconstant _ | PLresult | PLnull | PLtypeof _ | PLtype _
+  | PLfalse | PLtrue | PLcomprehension _ | PLempty | PLset _ | PLlist _ -> 0
 
 let print_constant fmt = function
   | IntConstant s -> pp_print_string fmt s
@@ -37,7 +76,11 @@ let print_constant fmt = function
   | StringConstant s -> fprintf fmt "\"%s\"" s
   | WStringConstant s -> fprintf fmt "\"%s\"" s
 
-let rec print_logic_type name fmt typ =
+let rec print_array_size fmt = function
+  | Some lexpr -> print_lexpr fmt lexpr
+  | None -> ()
+
+and print_logic_type name fmt typ =
   let pname = match name with
     | Some d -> (fun fmt -> fprintf fmt "@ %t" d)
     | None -> (fun _ -> ())
@@ -90,56 +133,12 @@ let rec print_logic_type name fmt typ =
     in
     print_logic_type (Some pname) fmt ret
 
-let print_typed_ident fmt (t,s) =
+and print_typed_ident fmt (t,s) =
   print_logic_type (Some (fun fmt -> pp_print_string fmt s)) fmt t
 
-let print_quantifiers fmt l = pp_list ~sep:",@ " print_typed_ident fmt l
-
-let get_relation_string = function
-    Lt -> "<" | Gt -> ">" | Le -> "<=" | Ge -> ">=" | Eq -> "==" | Neq -> "!="
-
-let get_binop_string = function
-    Badd -> "+"
-  | Bsub -> "-"
-  | Bmul -> "*"
-  | Bdiv -> "/"
-  | Bmod -> "%"
-  | Bbw_and -> "&"
-  | Bbw_or -> "|"
-  | Bbw_xor -> "^"
-  | Blshift -> "<<"
-  | Brshift -> ">>"
-
-let get_unop_string = function
-    Uminus -> "-" | Ustar -> "*" | Uamp -> "&" | Ubw_not -> "~"
-
-let getParenthLevel e =
-  match e.lexpr_node with
-  | PLnamed _ -> 95
-  | PLlambda _ | PLlet _ | PLrange _ -> 90
-  | PLforall _ | PLexists _ -> 87
-  | PLimplies _ | PLiff _ -> 85
-  | PLand _ | PLor _ | PLxor _ -> 80
-  | PLif _ -> 77
-  | PLbinop (_,(Bbw_and | Bbw_or | Bbw_xor),_) -> 75
-  | PLrepeat _ -> 72
-  | PLrel _ -> 70
-  | PLbinop (_,(Badd|Bsub|Blshift|Brshift),_) -> 60
-  | PLbinop (_,(Bmul|Bdiv|Bmod),_) -> 40
-  | PLunop ((Uamp|Uminus|Ubw_not),_) | PLcast _ | PLnot _ -> 30
-  | PLunop (Ustar,_) | PLdot _ | PLarrow _ | PLarrget _
-  | PLsizeof _ | PLsizeofE _ -> 20
-  | PLapp _ | PLold _ | PLat _
-  | PLoffset _ | PLbase_addr _ | PLblock_length _
-  | PLupdate _  | PLinitField _ | PLinitIndex _
-  | PLvalid _ | PLvalid_read _ | PLobject_pointer _ | PLvalid_function _
-  | PLinitialized _ | PLdangling _
-  | PLallocable _ | PLfreeable _ | PLfresh _
-  | PLseparated _ | PLunion _ | PLinter _ -> 10
-  | PLvar _ | PLconstant _ | PLresult | PLnull | PLtypeof _ | PLtype _
-  | PLfalse | PLtrue | PLcomprehension _ | PLempty | PLset _ | PLlist _ -> 0
+and print_quantifiers fmt l = pp_list ~sep:",@ " print_typed_ident fmt l
 
-let rec print_path_elt fmt = function
+and print_path_elt fmt = function
   | PLpathField s -> fprintf fmt ".%s" s
   | PLpathIndex i -> fprintf fmt "[@[%a@]]" print_lexpr i
 
diff --git a/src/kernel_services/ast_queries/logic_to_c.ml b/src/kernel_services/ast_queries/logic_to_c.ml
index f75aef98facc4fdf163641521c73f6a4279cdc41..e5cb96743ee445a8c322e345b2c51b013b5c5d57 100644
--- a/src/kernel_services/ast_queries/logic_to_c.ml
+++ b/src/kernel_services/ast_queries/logic_to_c.ml
@@ -128,19 +128,19 @@ and loc_to_exp ?result {term_node = lnode ; term_type = ltype; term_loc = loc} =
   | Tinter _ | Tcomprehension _ -> error_lval()
   | Tat ({term_node = TAddrOf (TVar _, TNoOffset)} as taddroflval, _) ->
     loc_to_exp ?result taddroflval
-  | TCast (true, Linteger, t) when Logic_typing.is_integral_type t.term_type ->
+  | TCast (true, Linteger, t) when Logic_utils.is_integral_type t.term_type ->
     loc_to_exp ?result t
-  | TCast (true, Lreal, t) when Logic_typing.is_integral_type t.term_type ->
+  | TCast (true, Lreal, t) when Logic_utils.is_integral_type t.term_type ->
     List.map
       (fun x -> new_exp ~loc (CastE (logic_type_to_typ Lreal, x)))
       (loc_to_exp ?result t)
-  | TCast (true, Lreal, t) when Logic_typing.is_arithmetic_type t.term_type ->
+  | TCast (true, Lreal, t) when Logic_utils.is_arithmetic_type t.term_type ->
     loc_to_exp ?result t
   | TCast (true, set, t)
     when
       Logic_const.is_set_type set &&
       Logic_utils.is_same_type
-        (Logic_typing.type_of_set_elem set) t.term_type ->
+        (Logic_utils.type_of_set_elem set) t.term_type ->
     loc_to_exp ?result t
   | Tnull -> [ Cil.mkCast ~newt:(Cil_const.voidPtrType) (Cil.zero ~loc) ]
 
@@ -167,9 +167,9 @@ let rec loc_to_lval ?result t =
      a coercion to set here.
   *)
   | TCast (true, set, t) when
-      Logic_typing.is_set_type set &&
+      Logic_utils.is_set_type set &&
       Logic_utils.is_same_type
-        (Logic_typing.type_of_set_elem set) t.term_type ->
+        (Logic_utils.type_of_set_elem set) t.term_type ->
     loc_to_lval ?result t
   | Tinter _ -> error_lval() (* TODO *)
   | Tcomprehension _ -> error_lval()
diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml
index 73ffdee63447b992dbfddf48f2b05eae91215ccd..dbb92a754748fc4ca242dad1c9b3d61f2dfc2528 100644
--- a/src/kernel_services/ast_queries/logic_typing.ml
+++ b/src/kernel_services/ast_queries/logic_typing.ml
@@ -101,14 +101,6 @@ let wcharlist_of_string s =
   done;
   List.rev (!res)
 
-let type_of_list_elem t = Logic_const.type_of_list_elem (unroll_type t)
-
-let is_list_type t = Logic_const.is_list_type (unroll_type t)
-
-let type_of_set_elem t = Logic_const.type_of_element (unroll_type t)
-
-let is_set_type t = Logic_const.is_set_type (unroll_type t)
-
 let plain_mk_mem ?loc t ofs = match t.term_node with
   | TAddrOf lv -> Logic_const.addTermOffsetLval ofs lv
   | TStartOf lv ->
@@ -586,24 +578,6 @@ let rec arithmetic_conversion ty1 ty2 =
       "arithmetic conversion between non arithmetic types %a and %a"
       Cil_printer.pp_logic_type ty1 Cil_printer.pp_logic_type ty2
 
-let plain_arithmetic_type t = Cil.isLogicArithmeticType t
-let plain_integral_type t = Cil.isLogicIntegralType t
-let plain_boolean_type t = Cil.isLogicBooleanType t
-let plain_fun_ptr t = Cil.isLogicFunPtrType t
-
-let is_arithmetic_type = plain_or_set plain_arithmetic_type
-let is_integral_type = plain_or_set plain_integral_type
-let is_fun_ptr = plain_or_set plain_fun_ptr
-
-let rec type_of_pointed t =
-  match unroll_type t with
-    Ctype ty when isPointerType ty -> Ctype (Cil.typeOf_pointed ty)
-  | Ltype ({lt_name = "set"} as lt,[t]) ->
-    Ltype(lt,[type_of_pointed t])
-  | _ ->
-    Kernel.fatal ~current:true "type %a is not a pointer type"
-      Cil_printer.pp_logic_type t
-
 let rec ctype_of_pointed t =
   match unroll_type t with
     Ctype ty when isPointerType ty -> Cil.typeOf_pointed ty
@@ -612,15 +586,6 @@ let rec ctype_of_pointed t =
     Kernel.fatal ~current:true "type %a is not a pointer type"
       Cil_printer.pp_logic_type t
 
-let type_of_array_elem =
-  plain_or_set
-    (fun t ->
-       match unroll_type t with
-         Ctype ty when isArrayType ty -> Ctype (Cil.typeOf_array_elem ty)
-       | _ ->
-         Kernel.fatal ~current:true "type %a is not an array type"
-           Cil_printer.pp_logic_type t)
-
 let rec ctype_of_array_elem t =
   match unroll_type t with
   | Ctype ty when isArrayType ty -> Cil.typeOf_array_elem ty
@@ -635,19 +600,6 @@ let mk_mem ?loc t ofs =
         (type_of_pointed t.term_type))
     t
 
-let is_plain_array_type t =
-  match unroll_type t with
-  | Ctype ct -> Cil.isArrayType ct
-  | _ -> false
-
-let is_plain_pointer_type t =
-  match unroll_type t with
-  | Ctype ct -> Cil.isPointerType ct
-  | _ -> false
-
-let is_array_type = plain_or_set is_plain_array_type
-let is_pointer_type = plain_or_set is_plain_pointer_type
-
 module type S =
 sig
   val type_of_field:
@@ -1047,6 +999,26 @@ struct
     with Not_found ->
       C.error loc "logic label `%s' not found" l
 
+  let rec size_exp ctxt loc size =
+    match size.term_node with
+    | TLval (TVar ({ lv_kind = LVGlobal } as lvar), TNoOffset) ->
+      begin (* logic variable, so try to unfold its definition *)
+        match Logic_env.find_logic_cons lvar with
+        | { l_labels = [] ; l_body = (LBterm term) ; l_profile = [] } ->
+          size_exp ctxt loc term
+        | _ -> raise Not_found
+      end
+    | _ ->
+      (match (Cil.constFoldTerm size).term_node with
+       | TConst (Integer _ | LChr _ | LEnum _) ->
+         (try
+            Logic_to_c.term_to_exp size
+          with
+          | Logic_to_c.No_conversion ->
+            ctxt.error loc "size of ACSL array cannot be represented in C")
+       | _ ->
+         ctxt.error loc "size of array must be a constant")
+
   let logic_type ctxt loc env t =
     (* force calls to go through ctxt *)
     let module [@warning "-60"] C = struct end in
@@ -1057,38 +1029,15 @@ struct
     | LTint ikind -> Ctype (Cil_const.mk_tint ikind)
     | LTfloat fkind -> Ctype (Cil_const.mk_tfloat fkind)
     | LTarray (ty,length) ->
-
-      let size = match length with
-        | ASnone -> None
-        | ASinteger s ->
-          let t = parseInt loc s in
-          (match t.term_node with
-           | TConst lconst ->
-             Some (new_exp ~loc (Const (lconstant_to_constant lconst)))
-           | _ -> Kernel.fatal ~loc "integer literal not parsed as constant")
-        | ASidentifier s ->
-          let size = ctxt.type_term ctxt env
-              {lexpr_node=PLvar(s);lexpr_loc=loc} in
-          if size.term_type <> Linteger then
-            ctxt.error loc "size of array must be an integral value";
-          try
-            let rec size_exp size =
-              match size.term_node with
-              | TConst lconst -> (* the identifier was a macro to an integer *)
-                Some (new_exp ~loc (Const (lconstant_to_constant lconst)))
-              | TLval (TVar( {lv_kind=LVGlobal} as lvar), TNoOffset) ->
-                begin (* logic variable, so try to unfold its definition *)
-                  match Logic_env.find_logic_cons lvar with
-                  | {l_labels=[];l_body=(LBterm term);l_profile=[]} ->
-                    size_exp term
-                  | _ -> raise Not_found
-                end
-              | _ -> raise Not_found
-            in size_exp size
-          with Not_found ->
-            ctxt.error loc "size of array must be an integral value";
-      in Ctype (Cil_const.mk_tarray (ctype ty) size)
-
+      begin match Option.map (ctxt.type_term ctxt env) length with
+        | None -> Ctype (Cil_const.mk_tarray (ctype ty) None)
+        | Some size ->
+          match size.term_type with
+          | Linteger ->
+            let size = Some (size_exp ctxt loc size) in
+            Ctype (Cil_const.mk_tarray (ctype ty) size)
+          | _ -> ctxt.error loc "size of array must be an integral value"
+      end
     | LTpointer ty -> Ctype (Cil_const.mk_tptr (ctype ty))
     | LTenum e ->
       (try Ctype (ctxt.find_type Enum e)
@@ -1414,7 +1363,7 @@ struct
       with
       | Ctype oldt, Ctype newt ->
         c_mk_cast ~force e oldt newt
-      | t1, Lboolean when is_integral_type t1 ->
+      | t1, Lboolean when Logic_utils.is_integral_type t1 ->
         let e = mk_cast e Linteger in
         Logic_const.term ~loc (TBinOp(Ne,e,lzero ~loc())) Lboolean
       | Lboolean, Linteger when explicit ->
@@ -1423,11 +1372,11 @@ struct
         C.error loc "invalid implicit cast from %a to %a"
           Cil_printer.pp_logic_type e.term_type
           Cil_printer.pp_logic_type newt
-      | Lboolean, Ctype t2 when is_integral_type newt && explicit ->
+      | Lboolean, Ctype t2 when Logic_utils.is_integral_type newt && explicit ->
         Logic_const.term ~loc (TCast (false, Ctype t2,e)) newt
       | ty1, Ltype({lt_name="set"},[ty2])
-        when is_pointer_type ty1 &&
-             is_plain_pointer_type ty2 &&
+        when Logic_utils.is_pointer_type ty1 &&
+             Logic_utils.plain_pointer_type ty2 &&
              isLogicCharType (type_of_pointed ty2) ->
         location_to_char_ptr e
       | Ltype({lt_name = "set"},[_]), Ltype({lt_name="set"},[ty2]) ->
@@ -1583,8 +1532,8 @@ struct
          if overloaded then raise Not_applicable
          else C.error loc "%s" s)
     | t1, Ltype ({lt_name = "set"},[t2]) when
-        is_pointer_type t1 &&
-        is_plain_pointer_type t2 &&
+        Logic_utils.is_pointer_type t1 &&
+        Logic_utils.plain_pointer_type t2 &&
         isLogicCharType (type_of_pointed t2) ->
       nt, location_to_char_ptr oterm
     (* can convert implicitly a singleton into a set,
@@ -1770,7 +1719,7 @@ struct
     | Ltype({lt_name = "set"}, [t1]), t2 ->
       let (env, ot, nt) = partial_unif ~overloaded loc term t1 t2 env in
       env, make_set_type ot, make_set_type nt
-    | t1,t2 when plain_boolean_type t1 && plain_boolean_type t2 ->
+    | t1,t2 when Cil.isLogicBooleanType t1 && Cil.isLogicBooleanType t2 ->
       env,ot,nt
     | ((Ctype _ | Linteger | Lreal | Lboolean),
        (Ctype _ | Linteger | Lreal | Lboolean)) ->
@@ -2042,16 +1991,14 @@ struct
 
   let list_conversion loc t ot nt env =
     if is_same_type ot nt then ot
-    else if plain_integral_type ot && plain_integral_type nt then ot
-    else if plain_arithmetic_type ot && plain_arithmetic_type nt then ot
+    else if Cil.isLogicIntegralType ot && Cil.isLogicIntegralType nt then ot
+    else if Cil.isLogicArithmeticType ot && Cil.isLogicArithmeticType nt then ot
     else let _,_,t = partial_unif ~overloaded:false loc t ot nt env in
       t
 
   let list_promotion typ =
-    if plain_integral_type typ then
-      Linteger
-    else if plain_arithmetic_type typ then
-      Lreal
+    if Cil.isLogicIntegralType typ then Linteger
+    else if Cil.isLogicArithmeticType typ then Lreal
     else typ
 
   let list_coercion typ t =
@@ -2322,7 +2269,7 @@ struct
                  term_type = type2}
     in
     let (toff, t_off2, opt_idx_let), ofs_type =
-      let check_type typ = plain_integral_type typ
+      let check_type typ = Cil.isLogicIntegralType typ
                            || C.error loc "range is only allowed for last offset"
       and mk_field f = TField(f,TNoOffset),TField(f,TNoOffset),(fun x -> x)
       and mk_idx idx =
@@ -3238,7 +3185,7 @@ struct
       f loc op (mk_cast t1 t) (mk_cast t2 t)
     in
     begin match op with
-      | _ when plain_arithmetic_type ty1 && plain_arithmetic_type ty2 ->
+      | _ when Cil.isLogicArithmeticType ty1 && Cil.isLogicArithmeticType ty2 ->
         conditional_conversion t1 t2
       | Eq | Neq when isLogicPointer t1 && isLogicNull t2 ->
         let t1 = mk_logic_pointer_or_StartOf t1 in
@@ -3292,7 +3239,7 @@ struct
       | TStartOf lv
       | Tat ({term_node = TStartOf lv}, _) ->
         f lv t
-      | TAddrOf lv when is_fun_ptr t.term_type ->
+      | TAddrOf lv when Logic_utils.is_fun_ptr t.term_type ->
         f lv
           { t with
             term_type = type_of_pointed t.term_type;
@@ -3305,7 +3252,7 @@ struct
   and term_from f t =
     let check_from t =
       match t.term_node with
-      | TAddrOf lv when is_fun_ptr t.term_type ->
+      | TAddrOf lv when Logic_utils.is_fun_ptr t.term_type ->
         f lv
           { t with
             term_type = type_of_pointed t.term_type;
@@ -3387,14 +3334,14 @@ struct
   and type_int_term ctxt env t =
     let module [@warning "-60"] C = struct end in
     let tt = ctxt.type_term ctxt env t in
-    if not (plain_integral_type tt.term_type) then
+    if not (Cil.isLogicIntegralType tt.term_type) then
       ctxt.error t.lexpr_loc
         "integer expected but %a found" Cil_printer.pp_logic_type tt.term_type;
     tt
 
   and type_bool_term ctxt env t =
     let tt = ctxt.type_term ctxt env t in
-    if not (plain_boolean_type tt.term_type) then
+    if not (Cil.isLogicBooleanType tt.term_type) then
       ctxt.error t.lexpr_loc "boolean expected but %a found"
         Cil_printer.pp_logic_type tt.term_type;
     mk_cast tt Lboolean
@@ -4528,3 +4475,17 @@ struct
       (fun _ -> rollback_transaction ())
 
 end
+
+(* deprecated functions *)
+
+let is_arithmetic_type = Logic_utils.is_arithmetic_type
+let is_integral_type = Logic_utils.is_integral_type
+let is_fun_ptr = Logic_utils.is_fun_ptr
+let is_array_type = Logic_utils.is_array_type
+let is_pointer_type = Logic_utils.is_pointer_type
+let is_set_type = Logic_utils.is_set_type
+let is_list_type = Logic_utils.is_list_type
+let type_of_set_elem = Logic_utils.type_of_set_elem
+let type_of_list_elem = Logic_utils.type_of_list_elem
+let type_of_pointed = Logic_utils.type_of_pointed
+let type_of_array_elem = Logic_utils.type_of_array_elem
diff --git a/src/kernel_services/ast_queries/logic_typing.mli b/src/kernel_services/ast_queries/logic_typing.mli
index 6b13c293e9010af73077887812faea826022d616..f12b1ebd22a3cf6fb855fdecb783bfadd3b1ab86 100644
--- a/src/kernel_services/ast_queries/logic_typing.mli
+++ b/src/kernel_services/ast_queries/logic_typing.mli
@@ -41,22 +41,6 @@ val type_binop: Logic_ptree.binop -> Cil_types.binop
 val unescape: string -> string
 val wcharlist_of_string: string -> int64 list
 
-val is_arithmetic_type: Cil_types.logic_type -> bool
-val is_integral_type: Cil_types.logic_type -> bool
-val is_set_type: Cil_types.logic_type -> bool
-val is_array_type: Cil_types.logic_type -> bool
-val is_pointer_type: Cil_types.logic_type -> bool
-
-(** @since Aluminium-20160501 *)
-val is_list_type: Cil_types.logic_type -> bool
-
-(** @since Aluminium-20160501 *)
-val type_of_list_elem : logic_type -> logic_type
-
-val type_of_pointed: logic_type -> logic_type
-val type_of_array_elem: logic_type -> logic_type
-val type_of_set_elem: logic_type -> logic_type
-
 val ctype_of_pointed: logic_type -> typ
 val ctype_of_array_elem: logic_type -> typ
 
@@ -361,3 +345,50 @@ val get_importer:
   builder:module_builder ->
   loc:Logic_ptree.location ->
   string list -> unit
+
+(** / **)
+
+(* deprecated functions only used for migration *)
+val is_arithmetic_type: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_arithmetic_type } ]
+[@@deprecated "use Logic_utils.is_arithmetic_type, or ocamlmig for migration"]
+
+val is_integral_type: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_integral_type } ]
+[@@deprecated "use Logic_utils.is_integral_type, or ocamlmig for migration"]
+
+val is_fun_ptr: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_fun_ptr } ]
+[@@deprecated "use Logic_utils.is_fun_ptr, or ocamlmig for migration"]
+
+val is_array_type: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_array_type } ]
+[@@deprecated "use Logic_utils.is_array_type, or ocamlmig for migration"]
+
+val is_pointer_type: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_pointer_type } ]
+[@@deprecated "use Logic_utils.is_pointer_type, or ocamlmig for migration"]
+
+val is_set_type: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_set_type } ]
+[@@deprecated "use Logic_utils.is_set_type, or ocamlmig for migration"]
+
+val is_list_type: Cil_types.logic_type -> bool
+[@@migrate { repl = Logic_utils.is_list_type } ]
+[@@deprecated "use Logic_utils.is_list_type, or ocamlmig for migration"]
+
+val type_of_set_elem: logic_type -> logic_type
+[@@migrate { repl = Logic_utils.type_of_set_elem } ]
+[@@deprecated "use Logic_utils.type_of_set_elem, or ocamlmig for migration"]
+
+val type_of_list_elem: logic_type -> logic_type
+[@@migrate { repl = Logic_utils.type_of_list_elem } ]
+[@@deprecated "use Logic_utils.type_of_list_elem, or ocamlmig for migration"]
+
+val type_of_pointed: logic_type -> logic_type
+[@@migrate { repl = Logic_utils.type_of_pointed }]
+[@@deprecated "use Logic_utils.type_of_pointed, or ocamlmig for migration"]
+
+val type_of_array_elem: logic_type -> logic_type
+[@@migrate { repl = Logic_utils.type_of_array_elem }]
+[@@deprecated "use Logic_utils.type_of_array_elem, or ocamlmig for migration"]
diff --git a/src/kernel_services/ast_queries/logic_utils.ml b/src/kernel_services/ast_queries/logic_utils.ml
index f652344a316ef66245991c1b7f5299b0d7c23d2e..6def39ffbe979ad52c59a03c08607a28bbcd3077 100644
--- a/src/kernel_services/ast_queries/logic_utils.ml
+++ b/src/kernel_services/ast_queries/logic_utils.ml
@@ -72,6 +72,51 @@ let is_instance_of vars t1 t2 =
 (** {1 From C to logic}*)
 (* ************************************************************************* *)
 
+let plain_arithmetic_type t = Cil.isLogicArithmeticType t
+let plain_integral_type t = Cil.isLogicIntegralType t
+let plain_fun_ptr t = Cil.isLogicFunPtrType t
+
+let is_arithmetic_type = plain_or_set plain_arithmetic_type
+let is_integral_type = plain_or_set plain_integral_type
+let is_fun_ptr = plain_or_set plain_fun_ptr
+
+let is_list_type t = Logic_const.is_list_type (unroll_type t)
+let type_of_list_elem t = Logic_const.type_of_list_elem (unroll_type t)
+
+let is_set_type t = Logic_const.is_set_type (unroll_type t)
+let type_of_set_elem t = Logic_const.type_of_element (unroll_type t)
+
+let plain_array_type t =
+  match unroll_type t with
+  | Ctype ct -> Cil.isArrayType ct
+  | _ -> false
+
+let plain_pointer_type t =
+  match unroll_type t with
+  | Ctype ct -> Cil.isPointerType ct
+  | _ -> false
+
+let is_array_type = plain_or_set plain_array_type
+let is_pointer_type = plain_or_set plain_pointer_type
+
+let type_of_array_elem =
+  Logic_const.transform_element
+    (fun t ->
+       match unroll_type t with
+         Ctype ty when isArrayType ty -> Ctype (Cil.typeOf_array_elem ty)
+       | _ ->
+         Kernel.fatal ~current:true "type %a is not an array type"
+           Cil_datatype.Logic_type.pretty t)
+
+let type_of_pointed =
+  Logic_const.transform_element
+    (fun t ->
+       match unroll_type t with
+         Ctype ty when isPointerType ty -> Ctype (Cil.typeOf_pointed ty)
+       | _ ->
+         Kernel.fatal ~current:true "type %a is not a pointer type"
+           Cil_datatype.Logic_type.pretty t)
+
 let isLogicType f t = plain_or_set (Logic_const.isLogicCType f) t
 
 (** true if the type is a C array (or a set of)*)
@@ -1266,15 +1311,37 @@ let is_same_pl_constant c1 c2 =
   | (IntConstant _| FloatConstant _
     | StringConstant _ | WStringConstant _), _ -> false
 
-let is_same_pl_array_size c1 c2 =
+let is_same_unop op1 op2 =
+  let open Logic_ptree in
+  match op1,op2 with
+  | Uminus, Uminus
+  | Ubw_not, Ubw_not
+  | Ustar, Ustar
+  | Uamp, Uamp -> true
+  | (Uminus | Ustar | Uamp | Ubw_not), _ -> false
+
+let is_same_binop op1 op2 =
   let open Logic_ptree in
+  match op1, op2 with
+  | Badd, Badd | Bsub, Bsub | Bmul, Bmul | Bdiv, Bdiv | Bmod, Bmod
+  | Bbw_and, Bbw_and | Bbw_or, Bbw_or | Bbw_xor, Bbw_xor
+  | Blshift, Blshift | Brshift, Brshift -> true
+  | (Badd | Bsub | Bmul | Bdiv | Bmod | Bbw_and | Bbw_or
+    | Bbw_xor | Blshift | Brshift),_ -> false
+
+let is_same_relation r1 r2 =
+  let open Logic_ptree in
+  match r1, r2 with
+  | Lt, Lt | Gt, Gt | Le, Le | Ge, Ge | Eq, Eq | Neq, Neq -> true
+  | (Lt | Gt | Le | Ge | Eq | Neq), _ -> false
+
+let rec is_same_pl_array_size c1 c2 =
   match c1,c2 with
-  | ASnone, ASnone -> true
-  | ASinteger s1, ASinteger s2
-  | ASidentifier s1, ASidentifier s2 -> s1 = s2
-  | (ASnone | ASinteger _| ASidentifier _), _ -> false
+  | None, None -> true
+  | Some e1, Some e2 -> is_same_lexpr e1 e2
+  | _, _ -> false
 
-let rec is_same_pl_type t1 t2 =
+and is_same_pl_type t1 t2 =
   let open Logic_ptree in
   match t1, t2 with
   | LTvoid, LTvoid
@@ -1319,34 +1386,10 @@ let rec is_same_pl_type t1 t2 =
     | LTunion _ | LTnamed _ | LTstruct _ | LTattribute _),_ ->
     false
 
-let is_same_quantifiers =
-  is_same_list (fun (t1,x1) (t2,x2) -> x1 = x2 && is_same_pl_type t1 t2)
-
-let is_same_unop op1 op2 =
-  let open Logic_ptree in
-  match op1,op2 with
-  | Uminus, Uminus
-  | Ubw_not, Ubw_not
-  | Ustar, Ustar
-  | Uamp, Uamp -> true
-  | (Uminus | Ustar | Uamp | Ubw_not), _ -> false
-
-let is_same_binop op1 op2 =
-  let open Logic_ptree in
-  match op1, op2 with
-  | Badd, Badd | Bsub, Bsub | Bmul, Bmul | Bdiv, Bdiv | Bmod, Bmod
-  | Bbw_and, Bbw_and | Bbw_or, Bbw_or | Bbw_xor, Bbw_xor
-  | Blshift, Blshift | Brshift, Brshift -> true
-  | (Badd | Bsub | Bmul | Bdiv | Bmod | Bbw_and | Bbw_or
-    | Bbw_xor | Blshift | Brshift),_ -> false
-
-let is_same_relation r1 r2 =
-  let open Logic_ptree in
-  match r1, r2 with
-  | Lt, Lt | Gt, Gt | Le, Le | Ge, Ge | Eq, Eq | Neq, Neq -> true
-  | (Lt | Gt | Le | Ge | Eq | Neq), _ -> false
+and is_same_quantifiers qs1 qs2 =
+  is_same_list (fun (t1,x1) (t2,x2) -> x1 = x2 && is_same_pl_type t1 t2) qs1 qs2
 
-let rec is_same_path_elt p1 p2 =
+and is_same_path_elt p1 p2 =
   let open Logic_ptree in
   match p1, p2 with
     PLpathField s1, PLpathField s2 -> s1 = s2
diff --git a/src/kernel_services/ast_queries/logic_utils.mli b/src/kernel_services/ast_queries/logic_utils.mli
index 3b30f7059955a60b217bd38ddf29fff09da98441..976924b3f1dec9cf06f8071a900c7c0a3b335918 100644
--- a/src/kernel_services/ast_queries/logic_utils.mli
+++ b/src/kernel_services/ast_queries/logic_utils.mli
@@ -75,13 +75,56 @@ val is_instance_of: string list -> logic_type -> logic_type -> bool
     [true] (this is the default), C typedef will be expanded as well. *)
 val unroll_type : ?unroll_typedef:bool -> logic_type -> logic_type
 
+(** {3 tests and extraction of element type}
+    @before Frama-C+dev these function were in {!Logic_typing}
+*)
+(** {4 tests for an individual (non set) type}
+    [plain_xxx t] returns [true] iff [t] is a [xxx]
+    @before Frama-C+dev these functions were not exported
+*)
+
+val plain_arithmetic_type: Cil_types.logic_type -> bool
+val plain_integral_type: Cil_types.logic_type -> bool
+val plain_fun_ptr: Cil_types.logic_type -> bool
+val plain_array_type: Cil_types.logic_type -> bool
+val plain_pointer_type: Cil_types.logic_type -> bool
+
+(** {4 tests for potential sets}
+    [is_xxx t] returns true iff [t] is a [xxx] _or_ a set of [xxx]
+*)
+
+val is_arithmetic_type: Cil_types.logic_type -> bool
+val is_integral_type: Cil_types.logic_type -> bool
+val is_fun_ptr: Cil_types.logic_type -> bool
+val is_array_type: Cil_types.logic_type -> bool
+val is_pointer_type: Cil_types.logic_type -> bool
+
+(** {4 sets and lists} *)
+
+val is_list_type: Cil_types.logic_type -> bool
+val is_set_type: Cil_types.logic_type -> bool
+
+(** {4 extract elements} *)
+
+val type_of_set_elem: logic_type -> logic_type
+val type_of_list_elem : logic_type -> logic_type
+
+(** returns the type of the element pointed to by the type. If the
+    source type is a set of pointers, returns a set of elements.
+*)
+val type_of_pointed: logic_type -> logic_type
+
+(** same as {!type_of_pointed} but for arrays (or set of arrays). *)
+val type_of_array_elem: logic_type -> logic_type
+
+(** {3 Predefined tests over types} *)
+
 (** [isLogicType test typ] is [false] for pure logic types and the result
     of test for C types.
     In case of a set type, the function tests the element type.
 *)
 val isLogicType : (typ -> bool) -> logic_type -> bool
 
-(** {3 Predefined tests over types} *)
 val isLogicArrayType : logic_type -> bool
 
 val isLogicCharType : logic_type -> bool
diff --git a/src/kernel_services/parsetree/logic_ptree.ml b/src/kernel_services/parsetree/logic_ptree.ml
index 8fb37977157888468abead725b04a22bf23d1f13..b9755bab3e444cea9b7ded208caecec2917cfd56 100644
--- a/src/kernel_services/parsetree/logic_ptree.ml
+++ b/src/kernel_services/parsetree/logic_ptree.ml
@@ -24,6 +24,18 @@
 
 (* Logic parse trees *)
 
+type location = Cil_types.location
+
+(** comparison operators. *)
+type relation = Lt | Gt | Le | Ge | Eq | Neq
+
+(** arithmetic and logic binary operators. *)
+type binop = Badd | Bsub | Bmul | Bdiv | Bmod | Bbw_and | Bbw_or | Bbw_xor |
+             Blshift | Brshift
+
+(** unary operators. *)
+type unop = Uminus | Ustar | Uamp | Ubw_not
+
 (** logic constants. *)
 type constant =
     IntConstant of string (** integer constant *)
@@ -31,14 +43,13 @@ type constant =
   | StringConstant of string (** string constant *)
   | WStringConstant of string (** wide string constant *)
 
-(** size of logic array. *)
-type array_size =
-    ASinteger of string (** integer constant *)
-  | ASidentifier of string (** a variable or macro*)
-  | ASnone (**  none *)
+(** size of logic array.
+    @before Frama-C+dev was a sum type with only integer constants and variables
+*)
+type array_size = lexpr option
 
 (** logic types. *)
-type logic_type =
+and logic_type =
   | LTvoid (** C void *)
   | LTboolean (** booleans *)
   | LTinteger (** mathematical integers. *)
@@ -54,25 +65,13 @@ type logic_type =
   | LTarrow of logic_type list * logic_type
   | LTattribute of logic_type * Cil_types.attribute (* Only const and volatile can appear here *)
 
-type location = Cil_types.location
-
 (** quantifier-bound variables *)
-type quantifiers = (logic_type * string) list
-
-(** comparison operators. *)
-type relation = Lt | Gt | Le | Ge | Eq | Neq
-
-(** arithmetic and logic binary operators. *)
-type binop = Badd | Bsub | Bmul | Bdiv | Bmod | Bbw_and | Bbw_or | Bbw_xor |
-             Blshift | Brshift
-
-(** unary operators. *)
-type unop = Uminus | Ustar | Uamp | Ubw_not
+and quantifiers = (logic_type * string) list
 
 (** logical expression. The distinction between locations, terms and
     predicate is done during typing.
 *)
-type lexpr = {
+and lexpr = {
   lexpr_node : lexpr_node; (** kind of expression. *)
   lexpr_loc : location (** position in the source code. *)
 }
diff --git a/src/plugins/aorai/data_for_aorai.ml b/src/plugins/aorai/data_for_aorai.ml
index 95d12ef6ad397e5dd0c7f75db75d771945098cb6..badd56eec9b45343c2662e330b4774d0b31eec09 100644
--- a/src/plugins/aorai/data_for_aorai.ml
+++ b/src/plugins/aorai/data_for_aorai.ml
@@ -746,8 +746,8 @@ let type_expr metaenv env ?tr ?current e =
       let t1 = e1.term_type in
       let t2 = e2.term_type in
       let t =
-        if Logic_typing.is_arithmetic_type t1
-        && Logic_typing.is_arithmetic_type t2
+        if Logic_utils.is_arithmetic_type t1
+        && Logic_utils.is_arithmetic_type t2
         then
           let t = Logic_typing.arithmetic_conversion t1 t2 in
           Logic_const.term
@@ -757,22 +757,22 @@ let type_expr metaenv env ?tr ?current e =
           (match bop with
            | Logic_ptree.Badd
              when
-               Logic_typing.is_integral_type t2
+               Logic_utils.is_integral_type t2
                && Logic_utils.isLogicPointerType t1 ->
              Logic_const.term (TBinOp (PlusPI,e1,e2)) t1
            | Logic_ptree.Bsub
              when
-               Logic_typing.is_integral_type t2
+               Logic_utils.is_integral_type t2
                && Logic_utils.isLogicPointerType t1 ->
              Logic_const.term (TBinOp (MinusPI,e1,e2)) t1
            | Logic_ptree.Badd
              when
-               Logic_typing.is_integral_type t1
+               Logic_utils.is_integral_type t1
                && Logic_utils.isLogicPointerType t2 ->
              Logic_const.term (TBinOp (PlusPI,e2,e1)) t2
            | Logic_ptree.Bsub
              when
-               Logic_typing.is_integral_type t1
+               Logic_utils.is_integral_type t1
                && Logic_utils.isLogicPointerType t2 ->
              Logic_const.term (TBinOp (MinusPI,e2,e1)) t2
            | Logic_ptree.Bsub
@@ -793,13 +793,13 @@ let type_expr metaenv env ?tr ?current e =
       env, t, cond
     | PUnop(Logic_ptree.Uminus,e) ->
       let env,t,cond = aux env cond e in
-      if Logic_typing.is_arithmetic_type t.term_type then
+      if Logic_utils.is_arithmetic_type t.term_type then
         env,Logic_const.term (TUnOp (Neg,t)) Linteger,cond
       else Aorai_option.abort
           "Invalid operand for unary -: unexpected %a" Printer.pp_term t
     | PUnop(Logic_ptree.Ubw_not,e) ->
       let env,t,cond = aux env cond e in
-      if Logic_typing.is_arithmetic_type t.term_type then
+      if Logic_utils.is_arithmetic_type t.term_type then
         env,Logic_const.term (TUnOp (BNot,t)) Linteger,cond
       else Aorai_option.abort
           "Invalid operand for bitwise not: unexpected %a" Printer.pp_term t
@@ -823,7 +823,7 @@ let type_expr metaenv env ?tr ?current e =
         env,
         Logic_const.term
           (TLval (TMem t, TNoOffset))
-          (Logic_typing.type_of_pointed t.term_type),
+          (Logic_utils.type_of_pointed t.term_type),
         cond
       else
         Aorai_option.abort "Cannot dereference term %a" Printer.pp_term t
@@ -832,19 +832,19 @@ let type_expr metaenv env ?tr ?current e =
       let env, t2, cond = aux env cond e2 in
       let t =
         if Logic_utils.isLogicPointerType t1.term_type
-        && Logic_typing.is_integral_type t2.term_type
+        && Logic_utils.is_integral_type t2.term_type
         then
           Logic_const.term
             (TBinOp (PlusPI,t1,t2))
-            (Logic_typing.type_of_pointed t1.term_type)
+            (Logic_utils.type_of_pointed t1.term_type)
         else if Logic_utils.isLogicPointerType t2.term_type
-             && Logic_typing.is_integral_type t1.term_type
+             && Logic_utils.is_integral_type t1.term_type
         then
           Logic_const.term
             (TBinOp (PlusPI,t2,t1))
-            (Logic_typing.type_of_pointed t2.term_type)
+            (Logic_utils.type_of_pointed t2.term_type)
         else if Logic_utils.isLogicArrayType t1.term_type
-             && Logic_typing.is_integral_type t2.term_type
+             && Logic_utils.is_integral_type t2.term_type
         then
           (match t1.term_node with
            | TStartOf lv | TLval lv ->
@@ -852,20 +852,20 @@ let type_expr metaenv env ?tr ?current e =
                (TLval
                   (Logic_const.addTermOffsetLval
                      (TIndex (t2, TNoOffset)) lv))
-               (Logic_typing.type_of_array_elem t1.term_type)
+               (Logic_utils.type_of_array_elem t1.term_type)
            | _ ->
              Aorai_option.fatal
                "Unsupported operation: %a[%a]"
                Printer.pp_term t1 Printer.pp_term t2)
         else if Logic_utils.isLogicArrayType t2.term_type
-             && Logic_typing.is_integral_type t1.term_type
+             && Logic_utils.is_integral_type t1.term_type
         then
           (match t2.term_node with
            | TStartOf lv | TLval lv ->
              Logic_const.term
                (TLval
                   (Logic_const.addTermOffsetLval (TIndex (t1, TNoOffset)) lv))
-               (Logic_typing.type_of_array_elem t2.term_type)
+               (Logic_utils.type_of_array_elem t2.term_type)
            | _ ->
              Aorai_option.fatal
                "Unsupported operation: %a[%a]"
@@ -891,7 +891,7 @@ let type_expr metaenv env ?tr ?current e =
       if Logic_utils.isLogicPointerType t.term_type then begin
         let off, ty =
           LTyping.type_of_field loc s
-            (Logic_typing.type_of_pointed t.term_type)
+            (Logic_utils.type_of_pointed t.term_type)
         in
         let lv = Logic_const.addTermOffsetLval off (TMem t,TNoOffset) in
         env, Logic_const.term (TLval lv) ty, cond
diff --git a/src/plugins/e-acsl/src/code_generator/memory_translate.ml b/src/plugins/e-acsl/src/code_generator/memory_translate.ml
index 045f1809d337ae24225724fe9db2a5a87ca7a039..2647a1a17b987b07f528b915d760acb4c0cdf961 100644
--- a/src/plugins/e-acsl/src/code_generator/memory_translate.ml
+++ b/src/plugins/e-acsl/src/code_generator/memory_translate.ml
@@ -360,7 +360,7 @@ let extract_quantifiers ~loc args =
                  eliminate_ranges_from_index_of_toffset ~loc toffset quantifiers
                in
                let lty_noset =
-                 Logic_typing.type_of_pointed @@
+                 Logic_utils.type_of_pointed @@
                  if Logic_const.is_set_type arg.term_type then
                    Logic_const.type_of_element arg.term_type
                  else
diff --git a/src/plugins/e-acsl/src/code_generator/translate_terms.ml b/src/plugins/e-acsl/src/code_generator/translate_terms.ml
index 72ac32a46788357e3fee60d36b7fcaa7173aa25f..e0e8e5929c58676462b4353cd6eac81ffdf3f611 100644
--- a/src/plugins/e-acsl/src/code_generator/translate_terms.ml
+++ b/src/plugins/e-acsl/src/code_generator/translate_terms.ml
@@ -325,7 +325,7 @@ and context_insensitive_term_to_exp_il ?inplace t =
     let bop = Interlang_gen.binop bop in
     let ty = Typing.get_typ ~logic_env t in
     if not (Gmp_types.Z.is_t ty) && not (Gmp_types.Q.is_t ty) then
-      assert (Logic_typing.is_integral_type t.term_type);
+      assert (Logic_utils.is_integral_type t.term_type);
     M.return @@ IL.(Exp.of_exp_node ~origin:t @@
                     BinOp {ity; binop = bop; op1 = e1; op2 = e2})
   | TBinOp((Lt | Gt | Le | Ge | Eq | Ne) as bop, t1, t2) ->
@@ -350,7 +350,7 @@ and context_insensitive_term_to_exp_il ?inplace t =
     let ity = Typing.get_number_ty ~logic_env t in
     let bop = Interlang_gen.binop binop in
     if not (Gmp_types.Z.is_t ty || Gmp_types.Q.is_t ty) then
-      assert (Logic_typing.is_integral_type t.term_type);
+      assert (Logic_utils.is_integral_type t.term_type);
     M.return @@ IL.(Exp.of_exp_node ~origin:t @@
                     BinOp {ity; binop = bop; op1 = e1; op2 = e2})
   | _ -> M.not_covered Printer.pp_term t
@@ -454,7 +454,7 @@ and context_insensitive_term_to_exp_old ~adata ?(inplace=false) kf env t =
       let e, env = Gmp.Q.binop ~loc (Some t) bop env kf e1 e2 in
       e, adata, env, Analyses_types.C_number, ""
     else begin
-      assert (Logic_typing.is_integral_type t.term_type);
+      assert (Logic_utils.is_integral_type t.term_type);
       let e = Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)) in
       e, adata, env, Analyses_types.C_number, ""
     end
@@ -520,7 +520,7 @@ and context_insensitive_term_to_exp_old ~adata ?(inplace=false) kf env t =
       let e, env = Gmp.Q.binop ~loc (Some t) bop env kf e1 e2 in
       e, adata, env, Analyses_types.C_number, ""
     else begin
-      assert (Logic_typing.is_integral_type t.term_type);
+      assert (Logic_utils.is_integral_type t.term_type);
       (* no guard required since RTEs are generated separately *)
       let e2, adata, env = t2_to_exp adata env in
       let e = Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)) in
@@ -724,7 +724,7 @@ and context_insensitive_term_to_exp_old ~adata ?(inplace=false) kf env t =
       let e, env = Gmp.Z.new_var ~loc ~name env kf t mk_stmts in
       e, adata, env, Analyses_types.C_number, ""
     else begin
-      assert (Logic_typing.is_integral_type t.term_type);
+      assert (Logic_utils.is_integral_type t.term_type);
       let e1, adata, env = t1_to_exp adata env in
       let e2, adata, env = t2_to_exp adata env in
       let e = Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)) in
@@ -788,7 +788,7 @@ and context_insensitive_term_to_exp_old ~adata ?(inplace=false) kf env t =
       let e, env = Gmp.Z.new_var ~loc ~name env kf t mk_stmts in
       e, adata, env, Analyses_types.C_number, ""
     else begin
-      assert (Logic_typing.is_integral_type t.term_type);
+      assert (Logic_utils.is_integral_type t.term_type);
       let e = Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)) in
       e, adata, env, Analyses_types.C_number, ""
     end
diff --git a/src/plugins/eva/legacy/eval_terms.ml b/src/plugins/eva/legacy/eval_terms.ml
index 41cad438e9c73282b0e9a3d3ce13f8754b3c2ea3..0a645e1e49ced5a77f5e5a9b341a559fb0716e9d 100644
--- a/src/plugins/eva/legacy/eval_terms.ml
+++ b/src/plugins/eva/legacy/eval_terms.ml
@@ -1149,12 +1149,12 @@ let rec eval_term ~alarm_mode env t =
        nothing to do, AND coercion from an integer type to a floating-point
        type, that require a conversion. *)
     (match Logic_const.plain_or_set Fun.id ltyp with
-     | Linteger when Logic_typing.is_integral_type t.term_type
+     | Linteger when Logic_utils.is_integral_type t.term_type
                   || Logic_const.is_boolean_type t.term_type -> r
      | Ctype typ when Cil.isIntegralOrPointerType typ -> r
      | Lreal ->
        let eover =
-         if Logic_typing.is_integral_type t.term_type
+         if Logic_utils.is_integral_type t.term_type
          then V.cast_int_to_float Fval.Real r.eover
          else V.cast_float_to_float Fval.Real r.eover
        in
@@ -1164,7 +1164,7 @@ let rec eval_term ~alarm_mode env t =
          empty = r.empty }
      | ltyp ->
        if Logic_const.is_boolean_type ltyp
-       && Logic_typing.is_integral_type t.term_type
+       && Logic_utils.is_integral_type t.term_type
        then cast_to_bool r
        else if Logic_utils.is_same_type ltyp t.term_type then
          (* coercion from singleton to set *)
diff --git a/src/plugins/wp/AssignsCompleteness.ml b/src/plugins/wp/AssignsCompleteness.ml
index 26faf49539775c73889972887f37be70b5763d83..3d02cf58c8a21234d6374b437337245c8f51ecec 100644
--- a/src/plugins/wp/AssignsCompleteness.ml
+++ b/src/plugins/wp/AssignsCompleteness.ml
@@ -127,7 +127,7 @@ let check_assigns kf assigns =
       else acc
     in
     let vfrom acc = function
-      | t, FromAny when Logic_typing.is_pointer_type t.it_content.term_type ->
+      | t, FromAny when Logic_utils.is_pointer_type t.it_content.term_type ->
         incomplete acc
           begin fun _kf ->
             Wp_parameters.warning ~wkey:wkey_pedantic
diff --git a/src/plugins/wp/Cvalues.ml b/src/plugins/wp/Cvalues.ml
index f57fd630a5c5eb46781a6d21be88d3e5a54a6c35..1af43c04595fa5f057a01c983b58ff8d308ab7a4 100644
--- a/src/plugins/wp/Cvalues.ml
+++ b/src/plugins/wp/Cvalues.ml
@@ -501,8 +501,8 @@ let map_logic f = function
   | Lset ls -> Lset (List.map (map_sloc f) ls)
 
 let plain lt e =
-  if Logic_typing.is_set_type lt then
-    let te = Logic_typing.type_of_set_elem lt in
+  if Logic_utils.is_set_type lt then
+    let te = Logic_utils.type_of_set_elem lt in
     Vset [Vset.Set(tau_of_ltype te,e)]
   else
     Vexp e
@@ -831,12 +831,12 @@ struct
         | Vset s -> a.vset <- List.rev_append s a.vset
         | Lset s -> a.sloc <- List.rev_append s a.sloc
       ) vs ;
-    flush (Logic_typing.is_pointer_type t) a
+    flush (Logic_utils.is_pointer_type t) a
 
   let inter t vs =
     match List.map (fun v -> Vset.concretize (vset v)) vs with
     | [] ->
-      if Logic_typing.is_pointer_type t
+      if Logic_utils.is_pointer_type t
       then Lset [] else Vset []
     | v::vs ->
       let s = List.fold_left Vset.inter v vs in
diff --git a/src/plugins/wp/LogicSemantics.ml b/src/plugins/wp/LogicSemantics.ml
index 0496a6436a04c14d101e37663f0531fdfdfb0085..b81a2ee26a7d86ab0f4d041ada91002d317bad28 100644
--- a/src/plugins/wp/LogicSemantics.ml
+++ b/src/plugins/wp/LogicSemantics.ml
@@ -108,8 +108,8 @@ struct
   let collection_of_term env t =
     let v = C.logic env t in
     match v with
-    | Vexp s when Logic_typing.is_set_type t.term_type ->
-      let te = Logic_typing.type_of_set_elem t.term_type in
+    | Vexp s when Logic_utils.is_set_type t.term_type ->
+      let te = Logic_utils.type_of_set_elem t.term_type in
       Vset [Vset.Set(tau_of_ltype te,s)]
     | w -> w
 
@@ -364,7 +364,7 @@ struct
     | _ -> None
 
   let compare_term env vrel lrel frel a b =
-    if Logic_typing.is_pointer_type a.term_type then
+    if Logic_utils.is_pointer_type a.term_type then
       lrel (loc_of_term env a) (loc_of_term env b)
     else match float_of_logic_type a.term_type with
       | Some f -> frel f (val_of_term env a) (val_of_term env b)
@@ -393,8 +393,8 @@ struct
   let arith env fint freal a b =
     let va = C.logic env a in
     let vb = C.logic env b in
-    let ta = Logic_typing.is_integral_type a.term_type in
-    let tb = Logic_typing.is_integral_type b.term_type in
+    let ta = Logic_utils.is_integral_type a.term_type in
+    let tb = Logic_utils.is_integral_type b.term_type in
     if ta && tb
     then fint va vb
     else freal (toreal ta va) (toreal tb vb)
@@ -665,7 +665,7 @@ struct
         | _ -> base
       end
 
-    | TUnOp(Neg,t) when not (Logic_typing.is_integral_type t.term_type) ->
+    | TUnOp(Neg,t) when not (Logic_utils.is_integral_type t.term_type) ->
       L.map F.e_opp (C.logic env t)
     | TUnOp(unop,t) -> term_unop unop (C.logic env t)
     | TBinOp(binop,a,b) -> term_binop env binop a b
diff --git a/src/plugins/wp/MemoryContext.ml b/src/plugins/wp/MemoryContext.ml
index b0910d07888573c343db91b9998557052bf37e35..e9587f382c05566fa230e3d2938739d3c160e5c3 100644
--- a/src/plugins/wp/MemoryContext.ml
+++ b/src/plugins/wp/MemoryContext.ml
@@ -112,8 +112,8 @@ open Logic_const
 
 let rec ptr_of = function
   | Ctype t -> Ctype (Cil_const.mk_tptr t)
-  | t when Logic_typing.is_set_type t ->
-    let t = Logic_typing.type_of_set_elem t in
+  | t when Logic_utils.is_set_type t ->
+    let t = Logic_utils.type_of_set_elem t in
     Logic_const.make_set_type (ptr_of t)
   | _ -> assert false
 
@@ -226,7 +226,7 @@ let normalize ps =
   List.filter (fun p -> not(Logic_utils.is_trivially_true p)) ps
 
 let ptrset { term_type = t } =
-  let open Logic_typing in
+  let open Logic_utils in
   is_pointer_type t || (is_set_type t && is_pointer_type (type_of_element t))
 
 (* -------------------------------------------------------------------------- *)
diff --git a/tests/syntax/acsl_type_expression_array.c b/tests/syntax/acsl_type_expression_array.c
new file mode 100644
index 0000000000000000000000000000000000000000..3e35f4ad30a05197e4ddacb28447823991ca7173
--- /dev/null
+++ b/tests/syntax/acsl_type_expression_array.c
@@ -0,0 +1,14 @@
+#include <stddef.h>
+typedef struct sub_type {
+    int tag;
+} sub_type;
+
+typedef struct {
+    int *ptr;
+    int foo[sizeof(sub_type)];
+} TEST_TYPE;
+
+int main(){
+  size_t test = sizeof(int[sizeof(sub_type)]);
+  /*@ assert test == sizeof(int[sizeof(sub_type)]); */
+}
diff --git a/tests/syntax/oracle/acsl_type_expression_array.res.oracle b/tests/syntax/oracle/acsl_type_expression_array.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..fd1712a6d474cac27832626165f9ed47ea7175a5
--- /dev/null
+++ b/tests/syntax/oracle/acsl_type_expression_array.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing acsl_type_expression_array.c (with preprocessing)
+/* Generated by Frama-C */
+#include "stddef.h"
+struct sub_type {
+   int tag ;
+};
+typedef struct sub_type sub_type;
+int main(void)
+{
+  int __retres;
+  size_t test = sizeof(int [sizeof(sub_type)]);
+  /*@ assert test ≡ sizeof(int [sizeof(sub_type)]); */ ;
+  __retres = 0;
+  return __retres;
+}
+
+