diff --git a/src/kernel_services/ast_queries/ast_attributes.ml b/src/kernel_services/ast_queries/ast_attributes.ml
new file mode 100644
index 0000000000000000000000000000000000000000..cc05a2957c95587f199924e4b0dc6b3f1f2ec87d
--- /dev/null
+++ b/src/kernel_services/ast_queries/ast_attributes.ml
@@ -0,0 +1,272 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2025                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** This file contains attribute related types/functions/values. *)
+
+open Cil_types
+
+let bitfield_attribute_name = "FRAMA_C_BITFIELD_SIZE"
+
+let anonymous_attribute_name = "fc_anonymous"
+
+let anonymous_attribute = Attr(anonymous_attribute_name, [])
+
+let qualifier_attributes = [ "const"; "restrict"; "volatile"; "ghost" ]
+
+let fc_internal_attributes = ["declspec"; "arraylen"; "fc_stdlib"]
+
+let cast_irrelevant_attributes = ["visibility"]
+
+let spare_attributes_for_c_cast = fc_internal_attributes @ qualifier_attributes
+
+let spare_attributes_for_logic_cast = spare_attributes_for_c_cast
+
+(** Construct sorted lists of attributes ***)
+let attribute_name (Attr(an, _) | AttrAnnot an) =
+  Extlib.strip_underscore an
+
+let has_attribute an al =
+  let an = Extlib.strip_underscore an in
+  List.exists (fun a -> attribute_name a = an) al
+
+(* Attributes are added as they are (e.g. if we add ["__attr"] and then ["attr"]
+   both are added). When checking for the presence of an attribute [x] or trying
+   to remove it, underscores are removed at the beginning and the end of the
+   attribute for both the [x] attribute and the attributes of the list. For
+   example, if have a call:
+
+   dropAttribute "__const" [ Attr("const", []) ; Attr("__const", []) ; Attr("__const__", []) ]
+
+   The result is [].
+*)
+
+let add_attribute (Attr(an, _) | AttrAnnot an as a) al =
+  let rec insert_sorted = function
+    | [] -> [a]
+    | ((Attr(an0, _) | AttrAnnot an0 as a0) :: rest) as l ->
+      if an < an0 then a :: l
+      else if Cil_datatype.Attribute.equal a a0 then l (* Do not add if already in there *)
+      else a0 :: insert_sorted rest (* Make sure we see all attributes with
+                                     * this name *)
+  in
+  insert_sorted al
+
+(** The second attribute list is sorted *)
+let add_attributes al0 al =
+  if al0 == [] then
+    al
+  else
+    List.fold_left (fun acc a -> add_attribute a acc) al al0
+
+let drop_attribute an al =
+  let an = Extlib.strip_underscore an in
+  List.filter (fun a -> attribute_name a <> an) al
+
+let rec drop_attributes anl al =
+  match al with
+  | [] -> []
+  | a :: q ->
+    let q' = drop_attributes anl q in
+    if List.mem (attribute_name a) anl then
+      q' (* drop this attribute *)
+    else
+    if q' == q then al (* preserve sharing *) else a :: q'
+
+let find_attribute an al =
+  let an = Extlib.strip_underscore an in
+  List.fold_left (fun acc a ->
+      match a with
+      | Attr (_, param) as a0 when attribute_name a0 = an -> param @ acc
+      | _ -> acc
+    ) [] al
+
+let filter_attributes an al =
+  let an = Extlib.strip_underscore an in
+  List.filter (fun a -> attribute_name a = an) al
+
+let filter_qualifier_attributes al =
+  List.filter (fun a -> List.mem (attribute_name a) qualifier_attributes) al
+
+let split_array_attributes al =
+  List.partition (fun a -> List.mem (attribute_name a) qualifier_attributes) al
+
+(**************************************)
+(* Attribute registration and classes *)
+(**************************************)
+
+type attribute_class =
+  (** Attribute of a name. If argument is true and we are on MSVC then
+      the attribute is printed using __declspec as part of the storage
+      specifier  *)
+  | AttrName of bool
+
+  (** Attribute of a function type. If argument is true and we are on
+      MSVC then the attribute is printed just before the function name *)
+  | AttrFunType of bool
+
+  (** Attribute of a type *)
+  | AttrType
+
+  (** Attribute of a statement or a block *)
+  | AttrStmt
+
+  (** Attribute that does not correspond to either of the above classes and is
+      ignored by functions {!get_attribute_class} and {!partition_attributes}. *)
+  | AttrIgnored
+
+(* This table contains the mapping of predefined attributes to classes.
+ * Extend this table with more attributes as you need. This table is used to
+ * determine how to associate attributes with names or type during cabs2cil
+ * conversion *)
+let attribute_hash : (string, attribute_class) Hashtbl.t =
+  let table = Hashtbl.create 13 in
+  List.iter (fun a -> Hashtbl.add table a (AttrName false))
+    [ "section"; "constructor"; "destructor"; "unused"; "used"; "weak";
+      "no_instrument_function"; "alias"; "no_check_memory_usage";
+      "exception"; "model"; (* "restrict"; *)
+      "aconst"; "asm" (* Gcc uses this to specify the name to be used in
+                       * assembly for a global  *)];
+  (* Now come the MSVC declspec attributes *)
+  List.iter (fun a -> Hashtbl.add table a (AttrName true))
+    [ "thread"; "naked"; "dllimport"; "dllexport";
+      "selectany"; "allocate"; "nothrow"; "novtable"; "property";
+      "uuid"; "align" ];
+  List.iter (fun a -> Hashtbl.add table a (AttrFunType false))
+    [ "format"; "regparm"; "longcall"; "noinline"; "always_inline"; ];
+  List.iter (fun a -> Hashtbl.add table a (AttrFunType true))
+    [ "stdcall";"cdecl"; "fastcall"; "noreturn"];
+  List.iter (fun a -> Hashtbl.add table a AttrType)
+    ("mode" :: qualifier_attributes);
+  (* GCC label and statement attributes. *)
+  List.iter (fun a -> Hashtbl.add table a AttrStmt)
+    [ "hot"; "cold"; "fallthrough"; "assume"; "musttail" ];
+  table
+
+let register_attribute an ac =
+  if Hashtbl.mem attribute_hash an then begin
+    let pp fmt c =
+      match c with
+      | AttrName b -> Format.fprintf fmt "(AttrName %B)" b
+      | AttrFunType b -> Format.fprintf fmt "(AttrFunType %B)" b
+      | AttrType -> Format.fprintf fmt "AttrType"
+      | AttrIgnored -> Format.fprintf fmt "AttrIgnored"
+      | AttrStmt -> Format.fprintf fmt "AttrStmt"
+    in
+    Kernel.warning
+      "Replacing existing class for attribute %s: was %a, now %a"
+      an pp (Hashtbl.find attribute_hash an) pp ac
+  end;
+  Hashtbl.replace attribute_hash an ac
+
+let remove_attribute = Hashtbl.remove attribute_hash
+
+let get_attribute_class ~default name =
+  match Hashtbl.find attribute_hash name with
+  | exception Not_found -> default
+  | AttrIgnored -> default
+  | ac -> ac
+
+let is_known_attribute = Hashtbl.mem attribute_hash
+
+let partition_attributes
+    ~(default:attribute_class)
+    (attrs:  attribute list) :
+  attribute list * attribute list * attribute list =
+  let rec loop (n,f,t) = function
+      [] -> n, f, t
+    | (Attr(an, _) | AttrAnnot an as a) :: rest ->
+      match get_attribute_class ~default an with
+        AttrName _ -> loop (add_attribute a n, f, t) rest
+      | AttrFunType _ ->
+        loop (n, add_attribute a f, t) rest
+      | AttrType -> loop (n, f, add_attribute a t) rest
+      | AttrStmt ->
+        Kernel.warning "unexpected statement attribute %s" an;
+        loop (n,f,t) rest
+      | AttrIgnored -> loop (n, f, t) rest
+  in
+  loop ([], [], []) attrs
+
+let split_storage_modifier al =
+  let isstoragemod (Attr(an, _) | AttrAnnot an : attribute) : bool =
+    try
+      match Hashtbl.find attribute_hash an with
+      | AttrName issm -> issm
+      | _ -> false
+    with Not_found -> false
+  in
+  let stom, rest = List.partition isstoragemod al in
+  if not (Machine.msvcMode ()) then stom, rest
+  else
+    (* Put back the declspec. Put it without the leading __ since these will
+     * be added later *)
+    let stom' =
+      List.map (fun a ->
+          match a with
+          | Attr(an, args) -> Attr("declspec", [ACons(an, args)])
+          | AttrAnnot _ -> assert false
+        ) stom
+    in
+    stom', rest
+
+let frama_c_ghost_else = "fc_ghost_else"
+let () = register_attribute frama_c_ghost_else (AttrStmt)
+
+let frama_c_ghost_formal = "fc_ghost_formal"
+let () = register_attribute frama_c_ghost_formal (AttrName false)
+
+let frama_c_init_obj = "fc_initialized_object"
+let () = register_attribute frama_c_init_obj (AttrName false)
+
+let frama_c_mutable = "fc_mutable"
+let () = register_attribute frama_c_mutable (AttrName false)
+
+let frama_c_inlined = "fc_inlined"
+let () = register_attribute frama_c_inlined (AttrFunType false)
+
+let () =
+  register_attribute bitfield_attribute_name AttrType;
+  register_attribute anonymous_attribute_name AttrIgnored;
+  List.iter
+    (fun a -> register_attribute a AttrIgnored)
+    fc_internal_attributes;
+  List.iter
+    (fun a -> register_attribute a AttrType)
+    cast_irrelevant_attributes
+
+let () =
+  Cil_datatype.drop_non_logic_attributes :=
+    drop_attributes spare_attributes_for_logic_cast
+
+let () =
+  Cil_datatype.drop_fc_internal_attributes :=
+    drop_attributes fc_internal_attributes
+
+let () =
+  Cil_datatype.drop_unknown_attributes :=
+    let is_annot_or_known_attr = function
+      | Attr (name, _) -> is_known_attribute name
+      (* Attribute annotations are always known. *)
+      | AttrAnnot _ -> true
+    in
+    (fun attributes ->
+       List.filter is_annot_or_known_attr attributes)
diff --git a/src/kernel_services/ast_queries/ast_attributes.mli b/src/kernel_services/ast_queries/ast_attributes.mli
new file mode 100644
index 0000000000000000000000000000000000000000..ea0eec9e476bc6a3af1eede6c8fbe57bd1051234
--- /dev/null
+++ b/src/kernel_services/ast_queries/ast_attributes.mli
@@ -0,0 +1,186 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2025                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** This file contains attribute related types/functions/values.
+    @since Frama-C+dev
+    @before Frama-C+dev Most of these functions were in {!Cil}
+*)
+
+open Cil_types
+
+(* **************************** *)
+(** {2 Attributes lists/values} *)
+(* **************************** *)
+
+(** Name of the attribute that is automatically inserted (with an [AINT size]
+    argument when querying the type of a field that is a bitfield.
+*)
+val bitfield_attribute_name : string
+
+(** Name of the attribute that is inserted when generating a name for a varinfo
+    representing an anonymous function parameter.
+*)
+val anonymous_attribute_name : string
+
+(** Attribute identifying anonymous function parameters. *)
+val anonymous_attribute : attribute
+
+(** [const], [volatile], [restrict] and [ghost] attributes. *)
+val qualifier_attributes : string list
+
+(** Internal attributes of Frama-C.  *)
+val fc_internal_attributes : string list
+
+(** Qualifiers and internal attributes to remove when doing a C cast. *)
+val cast_irrelevant_attributes : string list
+
+(** Qualifiers and internal attributes to remove when doing a C cast. *)
+val spare_attributes_for_c_cast : string list
+
+(** Qualifiers and internal attributes to remove when doing a C cast. *)
+val spare_attributes_for_logic_cast : string list
+
+(** A block marked with this attribute is known to be a ghost else. *)
+val frama_c_ghost_else: string
+
+(** A varinfo marked with this attribute is known to be a ghost formal. *)
+val frama_c_ghost_formal: string
+
+(** a formal marked with this attribute is known to be a pointer to an
+    object being initialized by the current function, which can thus assign
+    any sub-object regardless of const status.
+*)
+val frama_c_init_obj: string
+
+(** a field struct marked with this attribute is known to be mutable, i.e.
+    it can be modified even on a const object.
+*)
+val frama_c_mutable: string
+
+(** A block marked with this attribute is known to be inlined, i.e.
+    it replaces a call to an inline function.
+*)
+val frama_c_inlined : string
+
+(* ***************************** *)
+(** {2 Attributes manipulations} *)
+(* ***************************** *)
+
+(** Returns the name of an attribute. *)
+val attribute_name : attribute -> string
+
+(** True if the named attribute appears in the attribute list. The list of
+    attributes must be sorted.
+*)
+val has_attribute : string -> attribute list -> bool
+
+(** Add an attribute. Maintains the attributes in sorted order of the second
+    argument. The attribute is not added if it is already there.
+*)
+val add_attribute : attribute -> attributes -> attribute list
+
+(** Add a list of attributes. Maintains the attributes in sorted order. The
+    second argument must be sorted, but not necessarily the first.
+*)
+val add_attributes : attribute list -> attributes -> attributes
+
+(** Remove all attributes with the given name. Maintains the attributes in
+    sorted order.
+*)
+val drop_attribute : string -> attributes -> attribute list
+
+(** Remove all attributes with names appearing in the string list.
+    Maintains the attributes in sorted order.
+*)
+val drop_attributes : string list -> attributes -> attributes
+
+(** Returns the list of parameters associated to an attribute. The list is empty
+    if there is no such attribute or it has no parameters at all.
+*)
+val find_attribute : string -> attribute list -> attrparam list
+
+(** Retains attributes with the given name *)
+val filter_attributes : string -> attribute list -> attribute list
+
+(** retains attributes corresponding to type qualifiers (6.7.3) *)
+val filter_qualifier_attributes : attribute list -> attribute list
+
+(** given some attributes on an array type, split them into those that belong
+    to the type of the elements of the array (currently, qualifiers such as
+    const and volatile), and those that must remain on the array, in that
+    order. *)
+val split_array_attributes : attribute list -> attribute list * attribute list
+
+(** Separate out the storage-modifier name attributes *)
+val split_storage_modifier: attribute list -> attribute list * attribute list
+
+(* **************************************** *)
+(** {2 Attributes classes and registration} *)
+(* **************************************** *)
+
+type attribute_class =
+  (** Attribute of a name. If argument is true and we are on MSVC then
+      the attribute is printed using __declspec as part of the storage
+      specifier  *)
+  | AttrName of bool
+
+  (** Attribute of a function type. If argument is true and we are on
+      MSVC then the attribute is printed just before the function name *)
+  | AttrFunType of bool
+
+  (** Attribute of a type *)
+  | AttrType
+
+  (** Attribute of a statement or a block *)
+  | AttrStmt
+
+  (** Attribute that does not correspond to either of the above classes and is
+      ignored by functions {!get_attribute_class} and {!partition_attributes}. *)
+  | AttrIgnored
+
+(* Table containing all registered attributes. *)
+val attribute_hash : (string, attribute_class) Hashtbl.t
+
+(** Add a new attribute with a specified class *)
+val register_attribute : string -> attribute_class -> unit
+
+(** Remove an attribute previously registered. *)
+val remove_attribute : string -> unit
+
+(** Return the class of an attributes. The class `default' is returned for
+    unknown and ignored attributes.
+*)
+val get_attribute_class : default:attribute_class -> string -> attribute_class
+
+(** {!is_known_attribute attrname} returns true if the attribute named
+    {!attrname} is known by Frama-C.
+*)
+val is_known_attribute : string -> bool
+
+(** Partition the attributes into classes: name attributes, function type and
+    type attributes. Unknown and ignored attributes are returned in the
+    `default` attribute class.
+*)
+val partition_attributes : default:attribute_class -> attribute list ->
+  attribute list * (* AttrName *)
+  attribute list * (* AttrFunType *)
+  attribute list   (* AttrType *)
diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml
index afb9866d1960c716ea147ca1c4905d68906931c9..344d7315ed71ba7ce4db326f5d19a600dea58763 100644
--- a/src/kernel_services/ast_queries/cil.ml
+++ b/src/kernel_services/ast_queries/cil.ml
@@ -56,6 +56,7 @@ open Logic_const
 open Cil_datatype
 open Cil_types
 open Machine
+open Ast_attributes
 
 (* ************************************************************************* *)
 (* Reporting messages *)
@@ -145,102 +146,22 @@ let stmt_of_instr_list ?(loc=Location.unknown) = function
 
 (**** Utility functions ******)
 
-(**** ATTRIBUTES ****)
-
-(* Attributes are added as they are (e.g. if we add ["__attr"] and then ["attr"] both are added).
-   When checking for the presence of an attribute [x] or trying to remove it, underscores are
-   removed at the beginning and the end of the attribute for both the [x] attribute and the
-   attributes of the list. For example, if have a call:
-
-   dropAttribute "__const" [ Attr("const", []) ; Attr("__const", []) ; Attr("__const__", []) ]
-
-   The result is [].
-*)
-
-let bitfield_attribute_name = "FRAMA_C_BITFIELD_SIZE"
-
-let anonymous_attribute_name = "fc_anonymous"
-let anonymous_attribute = Attr(anonymous_attribute_name, [])
-
-(** Construct sorted lists of attributes ***)
-let attributeName =
-  function Attr(a, _) | AttrAnnot a -> Extlib.strip_underscore a
-
-let addAttribute
-    (Attr(an, _) | AttrAnnot an as a: attribute) (al: attributes) =
-  let rec insertSorted = function
-      [] -> [a]
-    | ((Attr(an0, _) | AttrAnnot an0 as a0) :: rest) as l ->
-      if an < an0 then a :: l
-      else if Cil_datatype.Attribute.equal a a0 then l (* Do not add if already in there *)
-      else a0 :: insertSorted rest (* Make sure we see all attributes with
-                                    * this name *)
-  in
-  insertSorted al
-
-(** The second attribute list is sorted *)
-let addAttributes al0 (al: attributes) : attributes =
-  if al0 == [] then al else
-    List.fold_left (fun acc a -> addAttribute a acc) al al0
-
-let dropAttribute (an: string) (al: attributes) =
-  let an = Extlib.strip_underscore an in
-  List.filter (fun a -> attributeName a <> an) al
-
-let hasAttribute (an: string) (al: attribute list) : bool =
-  let an = Extlib.strip_underscore an in
-  List.exists (fun a -> attributeName a = an) al
-
-let rec dropAttributes (anl: string list) (al: attributes) =
-  match al with
-  | [] -> []
-  | a :: q ->
-    let q' = dropAttributes anl q in
-    if List.mem (attributeName a) anl then
-      q' (* drop this attribute *)
-    else
-    if q' == q then al (* preserve sharing *) else a :: q'
-
-let filterAttributes (an: string) (al: attribute list) : attribute list =
-  let an = Extlib.strip_underscore an in
-  List.filter (fun a -> attributeName a = an) al
-
-let findAttribute (an: string) (al: attribute list) : attrparam list =
-  let an = Extlib.strip_underscore an in
-  List.fold_left
-    (fun acc -> function
-       | Attr (_, param) as a0 when attributeName a0 = an -> param @ acc
-       | _ -> acc)
-    [] al
+(* Attributes *)
 
 let rec typeAttrs { tnode; tattr } =
   match tnode with
   | TVoid    -> tattr
   | TInt _   -> tattr
   | TFloat _ -> tattr
-  | TNamed t -> addAttributes tattr (typeAttrs t.ttype)
+  | TNamed t -> add_attributes tattr (typeAttrs t.ttype)
   | TPtr _   -> tattr
   | TArray _ -> tattr
-  | TComp comp -> addAttributes comp.cattr tattr
-  | TEnum enum -> addAttributes enum.eattr tattr
+  | TComp comp -> add_attributes comp.cattr tattr
+  | TEnum enum -> add_attributes enum.eattr tattr
   | TFun _   -> tattr
   | TBuiltin_va_list -> tattr
 
-let qualifier_attributes = [ "const"; "restrict"; "volatile"; "ghost" ]
-
-let fc_internal_attributes = ["declspec"; "arraylen"; "fc_stdlib"]
-
-let cast_irrelevant_attributes = ["visibility"]
-
-let filter_qualifier_attributes al =
-  List.filter
-    (fun a -> List.mem (attributeName a) qualifier_attributes) al
-
-let splitArrayAttributes =
-  List.partition
-    (fun a -> List.mem (attributeName a) qualifier_attributes)
-
-let rec typeAddAttributes ?(combine=addAttributes) a0 t =
+let rec typeAddAttributes ?(combine=add_attributes) a0 t =
   begin
     match a0 with
     | [] ->
@@ -260,9 +181,9 @@ let rec typeAddAttributes ?(combine=addAttributes) a0 t =
       | TNamed _
       | TBuiltin_va_list -> {t with tattr = add t.tattr}
       | TArray (bt, l) ->
-        let att_elt, att_typ = splitArrayAttributes a0 in
+        let att_elt, att_typ = split_array_attributes a0 in
         let bt' = arrayPushAttributes att_elt bt in
-        let tattr = addAttributes att_typ t.tattr in
+        let tattr = add_attributes att_typ t.tattr in
         Cil_const.mk_tarray ~tattr bt' l
   end
 (* Push attributes that belong to the type of the elements of the array as
@@ -276,18 +197,18 @@ and arrayPushAttributes al t =
 
 (**** Look for the presence of an attribute in a type ****)
 
-let typeHasAttribute attr typ = hasAttribute attr (typeAttrs typ)
+let typeHasAttribute attr typ = has_attribute attr (typeAttrs typ)
 
 let rec typeHasQualifier attr t =
   match t.tnode with
   | TNamed ti ->
-    hasAttribute attr t.tattr || typeHasQualifier attr ti.ttype
+    has_attribute attr t.tattr || typeHasQualifier attr ti.ttype
   | TArray (bt, _) ->
-    typeHasQualifier attr bt || (* ill-formed type *) hasAttribute attr t.tattr
-  | _ -> hasAttribute attr (typeAttrs t)
+    typeHasQualifier attr bt || (* ill-formed type *) has_attribute attr t.tattr
+  | _ -> has_attribute attr (typeAttrs t)
 
 let typeHasAttributeMemoryBlock a (ty:typ): bool =
-  let f attrs = if hasAttribute a attrs then raise Exit in
+  let f attrs = if has_attribute a attrs then raise Exit in
   let rec visit (t: typ) : unit =
     f t.tattr;
     match t.tnode with
@@ -320,7 +241,7 @@ let rec typeRemoveAttributes ?anl t =
   let tattr =
     match anl with
     | None     -> []
-    | Some anl -> dropAttributes anl t.tattr
+    | Some anl -> drop_attributes anl t.tattr
   in
   let reshare () =
     if tattr == t.tattr
@@ -351,7 +272,7 @@ let rec typeRemoveAttributesDeep (anl: string list) t =
   (* Try to preserve sharing. We use sharing to be more efficient, but also
      to detect that we have removed an attribute under typedefs *)
   let reshare () =
-    let tattr = dropAttributes anl t.tattr in
+    let tattr = drop_attributes anl t.tattr in
     if tattr == t.tattr
     then t
     else Cil_const.mk_typ ~tattr t.tnode
@@ -364,12 +285,12 @@ let rec typeRemoveAttributesDeep (anl: string list) t =
   | TPtr   t ->
     let t' = typeRemoveAttributesDeep anl t in
     if t != t'
-    then Cil_const.mk_tptr ~tattr:(dropAttributes anl t.tattr) t'
+    then Cil_const.mk_tptr ~tattr:(drop_attributes anl t.tattr) t'
     else reshare ()
   | TArray (t, l) ->
     let t' = typeRemoveAttributesDeep anl t in
     if t != t'
-    then Cil_const.mk_tarray ~tattr:(dropAttributes anl t.tattr) t' l
+    then Cil_const.mk_tarray ~tattr:(drop_attributes anl t.tattr) t' l
     else reshare ()
   | TFun  _ -> reshare ()
   | TComp _ -> reshare ()
@@ -378,7 +299,7 @@ let rec typeRemoveAttributesDeep (anl: string list) t =
     let tt = typeRemoveAttributesDeep anl ti.ttype in
     if tt == ti.ttype
     then reshare ()
-    else typeAddAttributes (dropAttributes anl t.tattr) tt
+    else typeAddAttributes (drop_attributes anl t.tattr) tt
 
 let type_remove_qualifier_attributes =
   typeRemoveAttributes qualifier_attributes
@@ -386,126 +307,10 @@ let type_remove_qualifier_attributes =
 let type_remove_qualifier_attributes_deep =
   typeRemoveAttributesDeep qualifier_attributes
 
-type attributeClass =
-  | AttrName of bool
-  (* Attribute of a name. If argument is true and we are on MSVC then
-   * the attribute is printed using __declspec as part of the storage
-   * specifier  *)
-  | AttrFunType of bool
-  (* Attribute of a function type. If argument is true and we are on
-   * MSVC then the attribute is printed just before the function name *)
-
-  | AttrType
-  (* Attribute of a type *)
-
-  | AttrStmt
-  (* Attribute of a statement or block *)
-
-  | AttrIgnored
-  (** Attribute that does not correspond to either of the above classes. *)
-
-(* This table contains the mapping of predefined attributes to classes.
- * Extend this table with more attributes as you need. This table is used to
- * determine how to associate attributes with names or type during cabs2cil
- * conversion *)
-let attributeHash: (string, attributeClass) Hashtbl.t =
-  let table = Hashtbl.create 13 in
-  List.iter (fun a -> Hashtbl.add table a (AttrName false))
-    [ "section"; "constructor"; "destructor"; "unused"; "used"; "weak";
-      "no_instrument_function"; "alias"; "no_check_memory_usage";
-      "exception"; "model"; (* "restrict"; *)
-      "aconst"; "asm" (* Gcc uses this to specify the name to be used in
-                       * assembly for a global  *)];
-  (* Now come the MSVC declspec attributes *)
-  List.iter (fun a -> Hashtbl.add table a (AttrName true))
-    [ "thread"; "naked"; "dllimport"; "dllexport";
-      "selectany"; "allocate"; "nothrow"; "novtable"; "property";
-      "uuid"; "align" ];
-  List.iter (fun a -> Hashtbl.add table a (AttrFunType false))
-    [ "format"; "regparm"; "longcall"; "noinline"; "always_inline"; ];
-  List.iter (fun a -> Hashtbl.add table a (AttrFunType true))
-    [ "stdcall";"cdecl"; "fastcall"; "noreturn"];
-  List.iter (fun a -> Hashtbl.add table a AttrType)
-    ("mode" :: qualifier_attributes);
-  (* GCC label and statement attributes. *)
-  List.iter (fun a -> Hashtbl.add table a AttrStmt)
-    [ "hot"; "cold"; "fallthrough"; "assume"; "musttail" ];
-  table
-
-let isKnownAttribute = Hashtbl.mem attributeHash
-
-let attributeClass ~default name =
-  match Hashtbl.find attributeHash name with
-  | exception Not_found -> default
-  | AttrIgnored -> default
-  | ac -> ac
-
-let registerAttribute an ac =
-  if Hashtbl.mem attributeHash an then begin
-    let pp fmt c =
-      match c with
-      | AttrName b -> Format.fprintf fmt "(AttrName %B)" b
-      | AttrFunType b -> Format.fprintf fmt "(AttrFunType %B)" b
-      | AttrType -> Format.fprintf fmt "AttrType"
-      | AttrIgnored -> Format.fprintf fmt "AttrIgnored"
-      | AttrStmt -> Format.fprintf fmt "AttrStmt"
-    in
-    Kernel.warning
-      "Replacing existing class for attribute %s: was %a, now %a"
-      an pp (Hashtbl.find attributeHash an) pp ac
-  end;
-  Hashtbl.replace attributeHash an ac
-let removeAttribute = Hashtbl.remove attributeHash
-
-(** Partition the attributes into classes *)
-let partitionAttributes
-    ~(default:attributeClass)
-    (attrs:  attribute list) :
-  attribute list * attribute list * attribute list =
-  let rec loop (n,f,t) = function
-      [] -> n, f, t
-    | (Attr(an, _) | AttrAnnot an as a) :: rest ->
-      match attributeClass ~default an with
-        AttrName _ -> loop (addAttribute a n, f, t) rest
-      | AttrFunType _ ->
-        loop (n, addAttribute a f, t) rest
-      | AttrType -> loop (n, f, addAttribute a t) rest
-      | AttrStmt ->
-        Kernel.warning "unexpected statement attribute %s" an;
-        loop (n,f,t) rest
-      | AttrIgnored -> loop (n, f, t) rest
-  in
-  loop ([], [], []) attrs
-
-let frama_c_ghost_else = "fc_ghost_else"
-let () = registerAttribute frama_c_ghost_else (AttrStmt)
-
-let frama_c_ghost_formal = "fc_ghost_formal"
-let () = registerAttribute frama_c_ghost_formal (AttrName false)
-
-let frama_c_init_obj = "fc_initialized_object"
-let () = registerAttribute frama_c_init_obj (AttrName false)
-
-let frama_c_mutable = "fc_mutable"
-let () = registerAttribute frama_c_mutable (AttrName false)
-
-let frama_c_inlined = "fc_inlined"
-let () = registerAttribute frama_c_inlined (AttrFunType false)
-
-let () =
-  registerAttribute bitfield_attribute_name AttrType;
-  registerAttribute anonymous_attribute_name AttrIgnored;
-  List.iter
-    (fun a -> registerAttribute a AttrIgnored)
-    fc_internal_attributes;
-  List.iter
-    (fun a -> registerAttribute a AttrType)
-    cast_irrelevant_attributes
-
 let unrollType (t: typ) : typ =
   let rec withAttrs (al: attributes) (t: typ) : typ =
     match t.tnode with
-    | TNamed ti -> withAttrs (addAttributes al t.tattr) ti.ttype
+    | TNamed ti -> withAttrs (add_attributes al t.tattr) ti.ttype
     | _ -> typeAddAttributes al t
   in
   withAttrs [] t
@@ -525,15 +330,15 @@ let rec unrollTypeSkel (t : typ) : typ_node =
 let rec unrollTypeDeep (t: typ) : typ =
   let rec withAttrs (al: attributes) (t: typ) : typ =
     match t.tnode with
-    | TNamed r -> withAttrs (addAttributes al t.tattr) r.ttype
+    | TNamed r -> withAttrs (add_attributes al t.tattr) r.ttype
     | TPtr bt ->
       let bt' = unrollTypeDeep bt in
-      let tattr = addAttributes al t.tattr in
+      let tattr = add_attributes al t.tattr in
       Cil_const.mk_tptr ~tattr bt'
     | TArray (bt, l) ->
-      let att_elt, att_typ = splitArrayAttributes al in
+      let att_elt, att_typ = split_array_attributes al in
       let bt' = arrayPushAttributes att_elt (unrollTypeDeep bt) in
-      let tattr = addAttributes att_typ t.tattr in
+      let tattr = add_attributes att_typ t.tattr in
       Cil_const.mk_tarray ~tattr bt' l
     | TFun (rt, args, isva) ->
       let rt' = unrollTypeDeep rt in
@@ -543,14 +348,14 @@ let rec unrollTypeDeep (t: typ) : typ =
         | Some argl ->
           Some (List.map (fun (an, at, aa) -> (an, unrollTypeDeep at, aa)) argl)
       in
-      let tattr = addAttributes al t.tattr in
+      let tattr = add_attributes al t.tattr in
       Cil_const.mk_tfun ~tattr rt' args' isva
     | _ -> typeAddAttributes al t
   in
   withAttrs [] t
 
 let is_ghost_else block =
-  hasAttribute frama_c_ghost_else block.battrs
+  has_attribute frama_c_ghost_else block.battrs
 
 let rec enforceGhostStmtCoherence ?(force_ghost=false) stmt =
   let force_ghost = force_ghost || stmt.ghost in
@@ -630,10 +435,10 @@ let makeFormalsVarDecl ?ghost (n,t,a) =
   vi
 
 let isGhostFormalVarinfo vi =
-  hasAttribute frama_c_ghost_formal vi.vattr
+  has_attribute frama_c_ghost_formal vi.vattr
 
 let isGhostFormalVarDecl (_name, _type, attr) =
-  hasAttribute frama_c_ghost_formal attr
+  has_attribute frama_c_ghost_formal attr
 
 let setFormalsDecl vi typ =
   match unrollTypeSkel typ with
@@ -641,7 +446,7 @@ let setFormalsDecl vi typ =
     let is_ghost d = vi.vghost || isGhostFormalVarDecl d in
     let makeFormalsVarDecl i (n,t,a as x) =
       let x = if n = "" then begin
-          let a  = addAttribute anonymous_attribute a in
+          let a  = add_attribute anonymous_attribute a in
           "__x" ^ string_of_int i,t,a
         end
         else x
@@ -1112,19 +917,19 @@ let transient_block b =
       "ignoring request to mark transient a block with local variables:@\n%a"
       Cil_datatype.Block.pretty b
   end else
-    b.battrs <- addAttribute (Attr (vis_tmp_attr,[])) b.battrs; b
+    b.battrs <- add_attribute (Attr (vis_tmp_attr,[])) b.battrs; b
 
 let block_of_transient b =
-  if hasAttribute vis_tmp_attr b.battrs then begin
+  if has_attribute vis_tmp_attr b.battrs then begin
     if b.blocals <> [] then
       Kernel.fatal
         "Block that is supposed to be transient declares local variabels";
-    b.battrs <- dropAttribute vis_tmp_attr b.battrs;
+    b.battrs <- drop_attribute vis_tmp_attr b.battrs;
     b.bscoping <- false
   end;
   b
 
-let is_transient_block b = hasAttribute vis_tmp_attr b.battrs
+let is_transient_block b = has_attribute vis_tmp_attr b.battrs
 
 let flatten_transient_sub_blocks b =
   let prev = ref None in
@@ -2228,7 +2033,7 @@ and visitCilStmt (vis:cilVisitor) (s: stmt) : stmt =
     let make i = mkStmt ~ghost:res.ghost (Instr i) in
     let last = mkStmt ~ghost:res.ghost res.skind in
     let block = mkBlockNonScoping (List.map make instr_list @ [ last ]) in
-    block.battrs <- addAttribute (Attr (vis_tmp_attr, [])) block.battrs;
+    block.battrs <- add_attribute (Attr (vis_tmp_attr, [])) block.battrs;
     (* Make our statement contain the instructions to prepend *)
     res.skind <- Block block;
     vis#pop_stmt s; res
@@ -2248,7 +2053,7 @@ and childrenStmt (toPrepend: instr list ref) (vis:cilVisitor) (s:stmt): stmt =
           (function (stmt,modified,writes,reads,calls) as orig->
              let stmt' = visitCilStmt vis stmt in
              (match stmt'.skind with
-              | Block b -> b.battrs <- dropAttribute vis_tmp_attr b.battrs;
+              | Block b -> b.battrs <- drop_attribute vis_tmp_attr b.battrs;
               | _ -> ());
              (* might make sense for the default to be
                 to just copy the varinfo when using the copy visitor,
@@ -2497,7 +2302,7 @@ and visitCilAttributes (vis: cilVisitor) (al: attribute list) : attribute list=
          id vis#vattr childrenAttribute) al in
   if al' != al then
     (* Must re-sort *)
-    addAttributes al' []
+    add_attributes al' []
   else
     al
 and childrenAttribute (vis: cilVisitor) (a: attribute) : attribute =
@@ -3234,29 +3039,6 @@ let rec stripCasts (e: exp) =
 let rec stripTermCasts (t: term) =
   match t.term_node with TCast(_,_, t') -> stripTermCasts t' | _ -> t
 
-(* Separate out the storage-modifier name attributes *)
-let separateStorageModifiers (al: attribute list) =
-  let isstoragemod (Attr(an, _) | AttrAnnot an : attribute) : bool =
-    try
-      match Hashtbl.find attributeHash an with
-      | AttrName issm -> issm
-      | _ -> false
-    with Not_found -> false
-  in
-  let stom, rest = List.partition isstoragemod al in
-  if not (msvcMode ()) then stom, rest
-  else
-    (* Put back the declspec. Put it without the leading __ since these will
-     * be added later *)
-    let stom' =
-      List.map
-        (function
-          | Attr(an, args) -> Attr("declspec", [ACons(an, args)])
-          | AttrAnnot _ -> assert false)
-        stom
-    in
-    stom', rest
-
 let isVoidType t =
   match unrollTypeSkel t with
   | TVoid -> true
@@ -3295,7 +3077,7 @@ let isCharPtrType t =
 let isCharConstPtrType t =
   match unrollType t with
   | { tnode = TPtr tau; tattr } when isCharType tau ->
-    hasAttribute "const" tattr
+    has_attribute "const" tattr
   | _ -> false
 
 let isIntegralType t =
@@ -3566,8 +3348,8 @@ and typeOffset basetyp = function
          is still const (except potentially a mutable subsubpart, etc.)
       *)
       let attrs =
-        if hasAttribute frama_c_mutable fi.fattr then
-          dropAttribute "const" attrs
+        if has_attribute frama_c_mutable fi.fattr then
+          drop_attribute "const" attrs
         else attrs
       in
       typeOffset (typeAddAttributes attrs fi.ftype) o
@@ -3614,7 +3396,7 @@ let rec typeOfTermLval = function
 and typeTermOffset basetyp =
   let blendAttributes baseAttrs t =
     let (_, _, contagious) =
-      partitionAttributes ~default:(AttrName false) baseAttrs in
+      partition_attributes ~default:(AttrName false) baseAttrs in
     let rec putAttributes = function
       | Ctype typ ->
         Ctype (typeAddAttributes contagious typ)
@@ -3915,11 +3697,11 @@ let rec bytesAlignOf t =
    differently when put into a struct, or in each of its fields.
 *)
 and alignOfField (fi: fieldinfo) =
-  let fieldIsPacked = hasAttribute "packed" fi.fattr
-                      || hasAttribute "packed" fi.fcomp.cattr
+  let fieldIsPacked = has_attribute "packed" fi.fattr
+                      || has_attribute "packed" fi.fcomp.cattr
   in
   if fieldIsPacked then begin
-    if hasAttribute "aligned" fi.fattr then
+    if has_attribute "aligned" fi.fattr then
       (* field is packed and aligned => process alignment *)
       let field_alignment = process_aligned_attribute ~may_reduce:true
           (fun fmt -> Format.fprintf fmt "field %s" fi.fname)
@@ -3988,7 +3770,7 @@ and process_aligned_attribute (pp:Format.formatter->unit) ~may_reduce attrs defa
      be specified as well. When used as part of a typedef, the aligned attribute
      can both increase and decrease alignment, and specifying the packed
      attribute generates a warning." *)
-  match filterAttributes "aligned" attrs with
+  match filter_attributes "aligned" attrs with
   | [] ->
     (* no __aligned__ attribute, so get the default alignment *)
     default_align ()
@@ -4432,7 +4214,7 @@ and constFold (machdep: bool) (e: exp) : exp =
       let t' = unrollType t in
       match e.enode, t'.tnode with
       | Const (CInt64(i,_k,_)), (TInt nk | TEnum {ekind = nk})
-        when dropAttributes fc_internal_attributes t'.tattr = [] ->
+        when drop_attributes fc_internal_attributes t'.tattr = [] ->
         begin
           (* If the cast has attributes, leave it alone. *)
           Kernel.debug ~dkey "ConstFold to %a : %a@."
@@ -4684,7 +4466,7 @@ and constFoldToInt ?(machdep=true) e =
 let bitsSizeOfBitfield typlv =
   match unrollType typlv with
   | { tnode = TInt _; tattr } | { tnode = TEnum _; tattr } as t ->
-    (match findAttribute bitfield_attribute_name tattr with
+    (match find_attribute bitfield_attribute_name tattr with
      | [AInt i] -> Integer.to_int_exn i
      | _ -> bitsSizeOf t)
   | t -> bitsSizeOf t
@@ -4803,9 +4585,6 @@ let mk_behavior ?(name=default_behavior_name) ?(assumes=[]) ?(requires=[])
     b_extended = extended;
   }
 
-let spare_attributes_for_c_cast =
-  fc_internal_attributes @ qualifier_attributes
-
 let type_remove_attributes_for_c_cast t =
   let attributes_to_remove =
     fc_internal_attributes @ cast_irrelevant_attributes
@@ -4813,9 +4592,6 @@ let type_remove_attributes_for_c_cast t =
   let t = typeRemoveAttributesDeep attributes_to_remove t in
   typeRemoveAttributes spare_attributes_for_c_cast t
 
-let spare_attributes_for_logic_cast =
-  spare_attributes_for_c_cast
-
 let type_remove_attributes_for_logic_type t =
   let attributes_to_remove =
     fc_internal_attributes @ cast_irrelevant_attributes
@@ -4823,22 +4599,6 @@ let type_remove_attributes_for_logic_type t =
   let t = typeRemoveAttributesDeep attributes_to_remove t in
   typeRemoveAttributes spare_attributes_for_logic_cast t
 
-let () = Cil_datatype.drop_non_logic_attributes :=
-    dropAttributes spare_attributes_for_logic_cast
-
-let () = Cil_datatype.drop_fc_internal_attributes :=
-    dropAttributes fc_internal_attributes
-
-let () =
-  Cil_datatype.drop_unknown_attributes :=
-    let is_annot_or_known_attr = function
-      | Attr (name, _) -> isKnownAttribute name
-      (* Attribute annotations are always known. *)
-      | AttrAnnot _ -> true
-    in
-    (fun attributes ->
-       List.filter is_annot_or_known_attr attributes)
-
 let need_cast ?(force=false) oldt newt =
   let oldt = type_remove_attributes_for_c_cast (unrollType oldt) in
   let newt = type_remove_attributes_for_c_cast (unrollType newt) in
@@ -4967,7 +4727,7 @@ let makeFormalVar fdec ?(ghost=fdec.svar.vghost) ?(where = "$") ?loc name typ :
   let makeit name =
     let vi = makeLocal ~ghost ?loc ~formal:true fdec name typ in
     if ghost && not fdec.svar.vghost then
-      vi.vattr <- addAttribute (Attr(frama_c_ghost_formal, [])) vi.vattr ;
+      vi.vattr <- add_attribute (Attr(frama_c_ghost_formal, [])) vi.vattr ;
     vi
   in
   let error () = Kernel.fatal ~current:true
@@ -5342,8 +5102,8 @@ let global_attributes = function
   | GAsm _ | GText _ -> []
 
 let is_in_libc attrs =
-  hasAttribute "fc_stdlib" attrs ||
-  hasAttribute "fc_stdlib_generated" attrs
+  has_attribute "fc_stdlib" attrs ||
+  has_attribute "fc_stdlib_generated" attrs
 
 let global_is_in_libc g =
   is_in_libc (global_attributes g)
@@ -5585,7 +5345,7 @@ let argsToPairOfLists args =
     (argsToList args)
 
 let remove_attributes_for_integral_promotion a =
-  dropAttributes (bitfield_attribute_name :: spare_attributes_for_c_cast) a
+  drop_attributes (bitfield_attribute_name :: spare_attributes_for_c_cast) a
 
 let rec integralPromotion t = (* c.f. ISO 6.3.1.1 *)
   let open Cil_const in
@@ -5601,7 +5361,7 @@ let rec integralPromotion t = (* c.f. ISO 6.3.1.1 *)
     let k = if isSigned IChar then ISChar else IUChar in
     integralPromotion (mk_tint ~tattr k)
   | { tnode = TInt k; tattr } ->
-    begin match findAttribute bitfield_attribute_name tattr with
+    begin match find_attribute bitfield_attribute_name tattr with
       | [AInt size] ->
         (* This attribute always fits in int. *)
         let size = Integer.to_int_exn size in
@@ -5828,10 +5588,10 @@ let qualifier_context_ptr = function
 let included_qualifiers ?(context=Identical) a1 a2 =
   let a1 = filter_qualifier_attributes a1 in
   let a2 = filter_qualifier_attributes a2 in
-  let a1 = dropAttribute "restrict" a1 in
-  let a2 = dropAttribute "restrict" a2 in
-  let a1_no_cv = dropAttributes ["const"; "volatile"] a1 in
-  let a2_no_cv = dropAttributes ["const"; "volatile"] a2 in
+  let a1 = drop_attribute "restrict" a1 in
+  let a2 = drop_attribute "restrict" a2 in
+  let a1_no_cv = drop_attributes ["const"; "volatile"] a1 in
+  let a2_no_cv = drop_attributes ["const"; "volatile"] a2 in
   let is_equal = Cil_datatype.Attributes.equal a1 a2 in
   if is_equal then true
   else begin
@@ -5920,7 +5680,7 @@ type combineWhat =
 let combineAttributes what olda a =
   match what with
   | CombineFunarg _ -> a (* override old attributes with new ones *)
-  | _ -> addAttributes olda a (* union of attributes *)
+  | _ -> add_attributes olda a (* union of attributes *)
 
 type combineFunction =
   {
@@ -6107,19 +5867,19 @@ let combineTypesGen ?emitwith (combF : combineFunction)
                     combF.typ_combine combF
                       ~strictInteger ~strictReturnTypes what ot at
                   in
-                  let a = addAttributes oa aa in
+                  let a = add_attributes oa aa in
                   (n, t, a))
                oldargslist argslist)
     in
     (* Drop missingproto as soon as one of the type is a properly declared one*)
     let olda' =
-      if not (hasAttribute "missingproto" t.tattr) then
-        dropAttribute "missingproto" oldt.tattr
+      if not (has_attribute "missingproto" t.tattr) then
+        drop_attribute "missingproto" oldt.tattr
       else oldt.tattr
     in
     let a' =
-      if not (hasAttribute "missingproto" oldt.tattr) then
-        dropAttribute "missingproto" t.tattr
+      if not (has_attribute "missingproto" oldt.tattr) then
+        drop_attribute "missingproto" t.tattr
       else t.tattr
     in
     let tattr = combineAttributes what olda' a' in
@@ -6875,7 +6635,7 @@ let is_mutable (lhost, offset) =
     match typ'.tnode, off with
     | _, NoOffset -> can_mutate
     | _, Field (fi, off) ->
-      let can_mutate = can_mutate || hasAttribute frama_c_mutable fi.fattr in
+      let can_mutate = can_mutate || has_attribute frama_c_mutable fi.fattr in
       aux can_mutate fi.ftype off
     | TArray (typ, _), Index(_, off) -> aux can_mutate typ off
     | _, Index _ ->
@@ -6893,7 +6653,7 @@ let rec is_initialized_aux on_same_obj e =
 
 and is_initialized_lhost on_same_obj lhost =
   match lhost with
-  | Var vi -> hasAttribute frama_c_init_obj vi.vattr
+  | Var vi -> has_attribute frama_c_init_obj vi.vattr
   | Mem e -> on_same_obj && is_initialized_aux false e
 
 let is_initialized e =
@@ -7332,11 +7092,11 @@ let create_alpha_renaming old_args new_args =
   List.iter2
     (fun old_vi new_vi ->
        Hashtbl.add conversion old_vi.vid new_vi;
-       if hasAttribute anonymous_attribute_name new_vi.vattr &&
-          not (hasAttribute anonymous_attribute_name old_vi.vattr)
+       if has_attribute anonymous_attribute_name new_vi.vattr &&
+          not (has_attribute anonymous_attribute_name old_vi.vattr)
        then begin
          new_vi.vname <- old_vi.vname;
-         new_vi.vattr <- dropAttribute anonymous_attribute_name new_vi.vattr;
+         new_vi.vattr <- drop_attribute anonymous_attribute_name new_vi.vattr;
        end;
        match old_vi.vlogic_var_assoc, new_vi.vlogic_var_assoc with
        | None, _ -> () (* nothing to convert in logic spec. *)
@@ -7455,3 +7215,71 @@ let typeDeepDropAllAttributes t =
 let typeAttr { tattr } = tattr
 
 let setTypeAttrs t tattr = { t with tattr }
+
+(* **************************** *)
+(* Forward attributes functions *)
+(* **************************** *)
+
+let bitfield_attribute_name = bitfield_attribute_name
+
+let anonymous_attribute_name = anonymous_attribute_name
+
+let anonymous_attribute = anonymous_attribute
+
+let frama_c_ghost_else = frama_c_ghost_else
+
+let frama_c_ghost_formal = frama_c_ghost_formal
+
+let frama_c_init_obj = frama_c_init_obj
+
+let frama_c_mutable = frama_c_mutable
+
+let frama_c_inlined = frama_c_inlined
+
+let attributeName = attribute_name
+
+let hasAttribute = has_attribute
+
+let addAttribute = add_attribute
+
+let addAttributes = add_attributes
+
+let dropAttribute = drop_attribute
+
+let dropAttributes = drop_attributes
+
+let findAttribute = find_attribute
+
+let filterAttributes = filter_attributes
+
+let filter_qualifier_attributes = filter_qualifier_attributes
+
+let splitArrayAttributes = split_array_attributes
+
+type attributeClass =
+    AttrName of bool
+  (** Attribute of a name. If argument is true and we are on MSVC then
+      the attribute is printed using __declspec as part of the storage
+      specifier  *)
+  | AttrFunType of bool
+  (** Attribute of a function type. If argument is true and we are on
+      MSVC then the attribute is printed just before the function name *)
+  | AttrType
+  (** Attribute of a type *)
+  | AttrStmt
+  (** Attribute of a statement or a block *)
+  | AttrIgnored
+  (** Attribute that does not correspond to either of the above classes and is
+      ignored by functions [attributeClass] and [partitionAttributes]. *)
+
+let registerAttribute = register_attribute
+
+let removeAttribute = remove_attribute
+
+let attributeClass = get_attribute_class
+
+let isKnownAttribute = is_known_attribute
+
+let partitionAttributes = partition_attributes
+
+let separateStorageModifiers = split_storage_modifier
diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli
index dc33546920994bbc45115aa49b8c4bb9e8c65693..c52cee769465a3584839a71f1e01036039edf749 100644
--- a/src/kernel_services/ast_queries/cil.mli
+++ b/src/kernel_services/ast_queries/cil.mli
@@ -339,9 +339,6 @@ val unrollTypeNode: typ -> typ_node
     types. Will collect all attributes *)
 val unrollTypeDeep: typ -> typ
 
-(** Separate out the storage-modifier name attributes *)
-val separateStorageModifiers: attribute list -> attribute list * attribute list
-
 (** returns the type of the result of an arithmetic operator applied to
     values of the corresponding input types.
     @since Nitrogen-20111001 (moved from Cabs2cil)
@@ -1322,101 +1319,6 @@ val instr_falls_through : instr -> bool
 (** {2 Values for manipulating attributes} *)
 (* ************************************************************************* *)
 
-(** Various classes of attributes
-    @before 30.0-Zinc [AttrStmt] and [AttrIgnored] didn't exist
-*)
-type attributeClass =
-    AttrName of bool
-  (** Attribute of a name. If argument is true and we are on MSVC then
-      the attribute is printed using __declspec as part of the storage
-      specifier  *)
-  | AttrFunType of bool
-  (** Attribute of a function type. If argument is true and we are on
-      MSVC then the attribute is printed just before the function name *)
-  | AttrType
-  (** Attribute of a type *)
-  | AttrStmt
-  (** Attribute of a statement or a block *)
-  | AttrIgnored
-  (** Attribute that does not correspond to either of the above classes and is
-      ignored by functions [attributeClass] and [partitionAttributes]. *)
-
-val registerAttribute: string -> attributeClass -> unit
-(** Add a new attribute with a specified class *)
-
-val removeAttribute: string -> unit
-(** Remove an attribute previously registered. *)
-
-val isKnownAttribute: string -> bool
-(** [isKnownAttribute attrname] returns true if the attribute named [attrname]
-    is known by Frama-C.
-    @since 30.0-Zinc
-*)
-
-val attributeClass: default:attributeClass -> string -> attributeClass
-(** Return the class of an attributes. The class `default' is returned for
-    unknown and ignored attributes.
-    @before 30.0-Zinc no [default] argument
-*)
-
-(** Partition the attributes into classes: name attributes, function type and
-    type attributes. Unknown and ignored attributes are returned in the
-    `default` attribute class.
-    @before 30.0-Zinc no [default] argument
-*)
-val partitionAttributes:  default:attributeClass ->
-  attributes -> attribute list * (* AttrName *)
-                attribute list * (* AttrFunType *)
-                attribute list   (* AttrType *)
-
-(** Add an attribute. Maintains the attributes in sorted order of the second
-    argument. The attribute is not added if it is already there. *)
-val addAttribute: attribute -> attributes -> attributes
-
-(** Add a list of attributes. Maintains the attributes in sorted order. The
-    second argument must be sorted, but not necessarily the first *)
-val addAttributes: attribute list -> attributes -> attributes
-
-(** Remove all attributes with the given name. Maintains the attributes in
-    sorted order.  *)
-val dropAttribute: string -> attributes -> attributes
-
-(** Remove all attributes with names appearing in the string list.
-    Maintains the attributes in sorted order *)
-val dropAttributes: string list -> attributes -> attributes
-
-(** A block marked with this attribute is known to be a ghost else.
-
-    @since 21.0-Scandium
-*)
-val frama_c_ghost_else: string
-
-(** A varinfo marked with this attribute is known to be a ghost formal.
-
-    @since 20.0-Calcium
-*)
-val frama_c_ghost_formal: string
-
-(** a formal marked with this attribute is known to be a pointer to an
-    object being initialized by the current function, which can thus assign
-    any sub-object regardless of const status.
-
-    @since 18.0-Argon
-*)
-val frama_c_init_obj: string
-
-(** a field struct marked with this attribute is known to be mutable, i.e.
-    it can be modified even on a const object.
-
-    @since 18.0-Argon
-*)
-val frama_c_mutable: string
-
-(** A block marked with this attribute is known to be inlined, i.e.
-    it replaces a call to an inline function.
-*)
-val frama_c_inlined: string
-
 (** [true] if the underlying left-value of the given expression is allowed to be
     assigned to thanks to a [frama_c_init_obj] attribute. *)
 val is_initialized: exp -> bool
@@ -1438,7 +1340,6 @@ val isGhostFormalVarinfo: varinfo -> bool
 *)
 val isGhostFormalVarDecl: (string * typ * attributes) -> bool
 
-
 (** [true] iff the given variable is a const global variable with non extern
     storage.
 
@@ -1452,20 +1353,6 @@ val isGlobalInitConst: varinfo -> bool
 *)
 val typeDeepDropAllAttributes: typ -> typ
 
-(** Retains attributes with the given name *)
-val filterAttributes: string -> attributes -> attributes
-
-(** True if the named attribute appears in the attribute list. The list of
-    attributes must be sorted.  *)
-val hasAttribute: string -> attributes -> bool
-
-(** Returns the name of an attribute. *)
-val attributeName: attribute -> string
-
-(** Returns the list of parameters associated to an attribute. The list is empty if there
-    is no such attribute or it has no parameters at all. *)
-val findAttribute: string -> attribute list -> attrparam list
-
 (** Returns all the attributes contained in a type. This requires a traversal
     of the type structure, in case of composite, enumeration and named types *)
 val typeAttrs: typ -> attribute list
@@ -1545,31 +1432,6 @@ val type_remove_attributes_for_c_cast: typ -> typ
 *)
 val type_remove_attributes_for_logic_type: typ -> typ
 
-(** retains attributes corresponding to type qualifiers (6.7.3) *)
-val filter_qualifier_attributes: attributes -> attributes
-
-(** given some attributes on an array type, split them into those that belong
-    to the type of the elements of the array (currently, qualifiers such as
-    const and volatile), and those that must remain on the array, in that
-    order
-    @since Oxygen-20120901 *)
-val splitArrayAttributes: attributes -> attributes * attributes
-
-val bitfield_attribute_name: string
-(** Name of the attribute that is automatically inserted (with an [AINT size]
-    argument when querying the type of a field that is a bitfield *)
-
-val anonymous_attribute_name: string
-(** Name of the attribute that is inserted when generating a name for a varinfo
-    representing an anonymous function parameter.
-    @since 24.0-Chromium
-*)
-
-val anonymous_attribute: attribute
-(** attribute identifying anonymous function parameters
-    @since 24.0-Chromium
-*)
-
 (** Convert an expression into an attrparam, if possible. Otherwise raise
     NotAnAttrParam with the offending subexpression *)
 val expToAttrParam: exp -> attrparam
@@ -2463,6 +2325,10 @@ val set_extension_handler:
     @before 30.0-Zinc This function did not take a [plugin:string] parameter
 *)
 
+(* ************************************************************************* *)
+(** {2 Deprecated types functions}                                           *)
+(* ************************************************************************* *)
+
 (** Returns the attributes of a type.
     @deprecated Frama-C+dev *)
 val typeAttr: typ -> attribute list
@@ -2474,8 +2340,169 @@ val typeAttr: typ -> attribute list
 val setTypeAttrs: typ -> attributes -> typ
 [@@alert deprecated "Use [{t with tattr = ...}] instead."]
 
-(*
-Local Variables:
-compile-command: "make -C ../../.."
-End:
+(* ************************************************************************* *)
+(** {2 Deprecated values moved to Ast_attributes}                            *)
+(* ************************************************************************* *)
+
+val bitfield_attribute_name: string
+(** Name of the attribute that is automatically inserted (with an [AINT size]
+    argument when querying the type of a field that is a bitfield.
+*)
+[@@deprecated "Use Ast_attributes.bitfield_attribute_name instead."]
+
+val anonymous_attribute_name: string
+(** Name of the attribute that is inserted when generating a name for a varinfo
+    representing an anonymous function parameter.
+    @since 24.0-Chromium
+*)
+[@@deprecated "Use Ast_attributes.anonymous_attribute_name instead."]
+
+val anonymous_attribute: attribute
+(** attribute identifying anonymous function parameters
+    @since 24.0-Chromium
+*)
+[@@deprecated "Use Ast_attributes.anonymous_attribute instead."]
+
+(** Returns the name of an attribute. *)
+val attributeName: attribute -> string
+[@@deprecated "Use Ast_attributes.attribute_name instead."]
+
+(** True if the named attribute appears in the attribute list. The list of
+    attributes must be sorted.  *)
+val hasAttribute: string -> attributes -> bool
+[@@deprecated "Use Ast_attributes.has_attribute instead."]
+
+(** Add an attribute. Maintains the attributes in sorted order of the second
+    argument. The attribute is not added if it is already there. *)
+val addAttribute: attribute -> attributes -> attributes
+[@@deprecated "Use Ast_attributes.add_attribute instead."]
+
+(** Add a list of attributes. Maintains the attributes in sorted order. The
+    second argument must be sorted, but not necessarily the first *)
+val addAttributes: attribute list -> attributes -> attributes
+[@@deprecated "Use Ast_attributes.add_attributes instead."]
+
+(** Remove all attributes with the given name. Maintains the attributes in
+    sorted order.  *)
+val dropAttribute: string -> attributes -> attributes
+[@@deprecated "Use Ast_attributes.drop_attribute instead."]
+
+(** Remove all attributes with names appearing in the string list.
+    Maintains the attributes in sorted order *)
+val dropAttributes: string list -> attributes -> attributes
+[@@deprecated "Use Ast_attributes.drop_attributes instead."]
+
+(** Returns the list of parameters associated to an attribute. The list is empty if there
+    is no such attribute or it has no parameters at all. *)
+val findAttribute: string -> attribute list -> attrparam list
+[@@deprecated "Use Ast_attributes.find_attribute instead."]
+
+(** Retains attributes with the given name *)
+val filterAttributes: string -> attributes -> attributes
+[@@deprecated "Use Ast_attributes.filter_attributes instead."]
+
+(** retains attributes corresponding to type qualifiers (6.7.3) *)
+val filter_qualifier_attributes: attributes -> attributes
+[@@deprecated "Use Ast_attributes.filter_qualifier_attributes instead."]
+
+(** given some attributes on an array type, split them into those that belong
+    to the type of the elements of the array (currently, qualifiers such as
+    const and volatile), and those that must remain on the array, in that
+    order
+    @since Oxygen-20120901 *)
+val splitArrayAttributes: attributes -> attributes * attributes
+[@@deprecated "Use Ast_attributes.split_array_attributes instead."]
+
+(** Various classes of attributes
+    @before 30.0-Zinc [AttrStmt] and [AttrIgnored] didn't exist
+*)
+type attributeClass =
+    AttrName of bool
+  (** Attribute of a name. If argument is true and we are on MSVC then
+      the attribute is printed using __declspec as part of the storage
+      specifier  *)
+  | AttrFunType of bool
+  (** Attribute of a function type. If argument is true and we are on
+      MSVC then the attribute is printed just before the function name *)
+  | AttrType
+  (** Attribute of a type *)
+  | AttrStmt
+  (** Attribute of a statement or a block *)
+  | AttrIgnored
+  (** Attribute that does not correspond to either of the above classes and is
+      ignored by functions [attributeClass] and [partitionAttributes]. *)
+[@@deprecated "Use Ast_attributes.attribute_class instead."]
+
+val registerAttribute: string -> Ast_attributes.attribute_class -> unit
+(** Add a new attribute with a specified class *)
+[@@deprecated "Use Ast_attributes.register_attribute instead."]
+
+val removeAttribute: string -> unit
+(** Remove an attribute previously registered. *)
+[@@deprecated "Use Ast_attributes.remove_attribute instead."]
+
+val attributeClass: default:Ast_attributes.attribute_class -> string -> Ast_attributes.attribute_class
+(** Return the class of an attributes. The class `default' is returned for
+    unknown and ignored attributes.
+    @before 30.0-Zinc no [default] argument
+*)
+[@@deprecated "Use Ast_attributes.get_attribute_class instead."]
+
+val isKnownAttribute: string -> bool
+(** [isKnownAttribute attrname] returns true if the attribute named [attrname]
+    is known by Frama-C.
+    @since 30.0-Zinc
+*)
+[@@deprecated "Use Ast_attributes.is_known_attribute instead."]
+
+(** Partition the attributes into classes: name attributes, function type and
+    type attributes. Unknown and ignored attributes are returned in the
+    `default` attribute class.
+    @before 30.0-Zinc no [default] argument
+*)
+val partitionAttributes:  default:Ast_attributes.attribute_class ->
+  attributes -> attribute list * (* AttrName *)
+                attribute list * (* AttrFunType *)
+                attribute list   (* AttrType *)
+[@@deprecated "Use Ast_attributes.partition_attributes instead."]
+
+(** Separate out the storage-modifier name attributes *)
+val separateStorageModifiers: attribute list -> attribute list * attribute list
+[@@deprecated "Use Ast_attributes.split_storage_modifier instead."]
+
+(** A block marked with this attribute is known to be a ghost else.
+
+    @since 21.0-Scandium
+*)
+val frama_c_ghost_else: string
+[@@deprecated "Use Ast_attributes.frama_c_ghost_else instead."]
+
+(** A varinfo marked with this attribute is known to be a ghost formal.
+
+    @since 20.0-Calcium
+*)
+val frama_c_ghost_formal: string
+[@@deprecated "Use Ast_attributes.frama_c_ghost_formal instead."]
+
+(** a formal marked with this attribute is known to be a pointer to an
+    object being initialized by the current function, which can thus assign
+    any sub-object regardless of const status.
+
+    @since 18.0-Argon
 *)
+val frama_c_init_obj: string
+[@@deprecated "Use Ast_attributes.frama_c_init_obj instead."]
+
+(** a field struct marked with this attribute is known to be mutable, i.e.
+    it can be modified even on a const object.
+
+    @since 18.0-Argon
+*)
+val frama_c_mutable: string
+[@@deprecated "Use Ast_attributes.frama_c_mutable instead."]
+
+(** A block marked with this attribute is known to be inlined, i.e.
+    it replaces a call to an inline function.
+*)
+val frama_c_inlined: string
+[@@deprecated "Use Ast_attributes.frama_c_inlined instead."]