diff --git a/doc/userman/user-changes.tex b/doc/userman/user-changes.tex
index ed3e8db288f30e688d1cb6fd3a8989616c318471..7c2c49598b83b2ac98437f7f7db4537c9537c708 100644
--- a/doc/userman/user-changes.tex
+++ b/doc/userman/user-changes.tex
@@ -5,6 +5,14 @@ release. First we list changes of the last release.
 
 \section*{\nextframacversion}
 
+\begin{itemize}
+\item \textbf{Normalizing the Source Code:} added options
+  \texttt{-keep-unused-types} and its opposite,
+  \texttt{-remove-unused-types}.
+\end{itemize}
+
+\section*{18.0 (Argon)}
+
 \begin{itemize}
 \item \textbf{Feedback Options:} change options governing status of warning categories
 \item \textbf{Normalizing the Source Code:} added category \texttt{@inline} to
diff --git a/doc/userman/user-sources.tex b/doc/userman/user-sources.tex
index 1b0cd0706fd5d1cc78e1b075d53403f0f26ab2f7..8fc0e1180af15d70df8d4e32022b3a26e3597857 100644
--- a/doc/userman/user-sources.tex
+++ b/doc/userman/user-sources.tex
@@ -249,6 +249,10 @@ a negative value, and choose the smallest rank possible starting from
   set by default. So you mostly use the opposite form, namely
   \optiondef{-}{remove-unused-specified-functions}.
 
+\item \optiondef{-}{keep-unused-types} does not remove unused types and
+  enum/struct/union declarations. By default, such types are removed,
+  that is, its opposite option \optiondef{-}{remove-unused-types} is set.
+
 \item \texttt{\optiondef{-}{machdep} <machine architecture name>} defines the
   target platform. The default value is a \texttt{x86\_32} bits
   platform. Analyzers may take into account the \emph{endianness} of the
diff --git a/man/frama-c.1 b/man/frama-c.1
index a9ad49458ae172586ce531afabf03cb8214380be..052066d3bbbaeca95e3dd43189b82a87aada67b4 100644
--- a/man/frama-c.1
+++ b/man/frama-c.1
@@ -25,7 +25,7 @@
 .\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file
 .\" and run `make man/frama-c.1`.
 
-.TH FRAMA-C 1 2018-01-17
+.TH FRAMA-C 1 2019-07-29
 .SH NAME
 .PP
 frama\-c[.byte] \- a static analyzer for C programs
@@ -403,6 +403,11 @@ see \f[B]\-remove\-unused\-specified\-functions\f[].
 .RS
 .RE
 .TP
+.B \-keep\-unused\-types
+see \f[B]\-remove\-unused\-types\f[].
+.RS
+.RE
+.TP
 .B \-kernel\-log \f[I]kind:file\f[]
 copies log messages from the Frama\-C's kernel to file.
 \f[I]kind\f[] specifies which kinds of messages to be copied (e.g.
@@ -587,6 +592,14 @@ Functions having the attribute \f[B]FRAMAC_BUILTIN\f[] are always kept.
 .RS
 .RE
 .TP
+.B \-remove\-unused\-types
+remove types and struct/union/enum declarations that are not referenced
+anywhere else in the code.
+This is the default.
+Use \f[B]\-keep\-unused\-types\f[] to keep these definitions.
+.RS
+.RE
+.TP
 .B \-safe\-arrays
 for multidimensional arrays or arrays that are fields inside structs,
 assumes that all accesses must be in bound (set by default).
diff --git a/man/frama-c.1.header b/man/frama-c.1.header
index 62f871e6410ab6985527989b74671d77b766e9f6..e5046fe091c7ef2b426b67cdf86193bc9595f94e 100644
--- a/man/frama-c.1.header
+++ b/man/frama-c.1.header
@@ -2,7 +2,7 @@
 .\"                                                                        
 .\"  This file is part of Frama-C.                                         
 .\"                                                                        
-.\"  Copyright (C) 2007-2018                                               
+.\"  Copyright (C) 2007-2019                                               
 .\"    CEA (Commissariat à l'énergie atomique et aux énergies              
 .\"         alternatives)                                                  
 .\"                                                                        
@@ -25,4 +25,4 @@
 .\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file
 .\" and run `make man/frama-c.1`.
 
-.TH FRAMA-C 1 2018-01-17
+.TH FRAMA-C 1 2019-07-29
diff --git a/man/frama-c.1.md b/man/frama-c.1.md
index b4aece519c794ac664fcb063ce6b7d4e7484c328..7e21eccfa57736ffd7be6ef615dfeb6f1a0e11e4 100644
--- a/man/frama-c.1.md
+++ b/man/frama-c.1.md
@@ -242,6 +242,9 @@ Defaults to no.
 -keep-unused-specified-functions
 : see **-remove-unused-specified-functions**.
 
+-keep-unused-types
+: see **-remove-unused-types**.
+
 -kernel-log *kind:file*
 : copies log messages from the Frama-C's kernel to file. *kind* specifies which
 kinds of messages to be copied (e.g. **w** for warnings, **e** for errors,
@@ -359,6 +362,11 @@ functions were fully inlined.
 in the code. This is the default. Functions having the attribute
 **FRAMAC_BUILTIN** are always kept.
 
+-remove-unused-types
+: remove types and struct/union/enum declarations that are not referenced
+anywhere else in the code. This is the default. Use **-keep-unused-types**
+to keep these definitions.
+
 -safe-arrays
 : for multidimensional arrays or arrays that are fields inside structs,
 assumes that all accesses must be in bound (set by default).
diff --git a/src/kernel_internals/typing/rmtmps.ml b/src/kernel_internals/typing/rmtmps.ml
index 64ada096ee7a1e7e525bb816713a0869ec9c3022..496842818065bbd43ca7fbb95954bb1f0cf4ffe6 100644
--- a/src/kernel_internals/typing/rmtmps.ml
+++ b/src/kernel_internals/typing/rmtmps.ml
@@ -71,7 +71,6 @@ module InfoHashtbl = Hashtbl.Make(struct
       | Var v -> Cil_datatype.Varinfo.hash v
   end)
 
-(* Used by external plug-ins: *)
 let keepUnused = ref false
 
 (* Possibly no longer used: *)
@@ -885,10 +884,10 @@ let removeUnmarked isRoot ast reachable_tbl =
 
 type rootsFilter = global -> bool
 
-let removeUnusedTemps ?(isRoot : rootsFilter = isExportedRoot) ast =
+let removeUnused ?(isRoot=isExportedRoot) ast =
   if not !keepUnused then
     begin
-      Kernel.debug ~dkey "Removing unused temporaries" ;
+      Kernel.debug ~dkey "Removing unused" ;
 
       (* digest any pragmas that would create additional roots *)
       let keepers = categorizePragmas ast in
diff --git a/src/kernel_internals/typing/rmtmps.mli b/src/kernel_internals/typing/rmtmps.mli
index 510a6565b0551e9045c09aa3913ec2d8735dd80d..015a4f4dff344aee76e5b7996216088814ccff0e 100644
--- a/src/kernel_internals/typing/rmtmps.mli
+++ b/src/kernel_internals/typing/rmtmps.mli
@@ -51,18 +51,18 @@
 
 (* Some clients may wish to augment or replace the standard strategy
  * for finding the initially reachable roots.  The optional
- * "isRoot" argument to Rmtmps.removeUnusedTemps grants this
- * flexibility.  If given, it should name a function which will return
- * true if a given global should be treated as a retained root.
+ * "isRoot" argument to Rmtmps.removeUnused grants this
+ * flexibility.  It specifies the globals which will serve as roots
+ * to be kept. Starting from these roots, all reachable (used) AST
+ * elements will be kept.
  *
- * Function Rmtmps.isDefaultRoot encapsulates the default root
+ * Function [Rmtmps.isExportedRoot] encapsulates the default root
  * collection, which consists of those global variables and functions
  * which are visible to the linker and runtime loader.  A client's
  * root filter can use this if the goal is to augment rather than
- * replace the standard logic.  Function Rmtmps.isExportedRoot is an
- * alternate name for this same function.
+ * replace the standard logic.
  *
- * Function Rmtmps.isCompleteProgramRoot is an example of an alternate
+ * Function [Rmtmps.isCompleteProgramRoot] is an example of an alternate
  * root collection.  This function assumes that it is operating on a
  * complete program rather than just one object file.  It treats
  * "main()" as a root, as well as any function carrying the
@@ -75,12 +75,11 @@
 *)
 
 
-type rootsFilter = Cil_types.global -> bool
-val isExportedRoot : rootsFilter
-val isCompleteProgramRoot : rootsFilter
+val isExportedRoot : Cil_types.global -> bool
+val isCompleteProgramRoot : Cil_types.global -> bool
 
 (* process a complete Cil file *)
-val removeUnusedTemps: ?isRoot:rootsFilter -> Cil_types.file -> unit
+val removeUnused: ?isRoot:(Cil_types.global -> bool) -> Cil_types.file -> unit
 
 (** removes unused labels for which [is_removable] is true.
     [is_removable] defaults to the negation of boolean flag of [Label]
diff --git a/src/kernel_services/ast_queries/file.ml b/src/kernel_services/ast_queries/file.ml
index 60ee0168a457e35ea8e96e1e344080082729d802..356d822f8d2ce918a5f55d998e6185980a2215b4 100644
--- a/src/kernel_services/ast_queries/file.ml
+++ b/src/kernel_services/ast_queries/file.ml
@@ -607,8 +607,9 @@ let () =
 (** Keep defined entry point even if not defined, and possibly the functions
     with only specifications (according to parameter
     keep_unused_specified_function). This function is meant to be passed to
-    {!Rmtmps.removeUnusedTemps}. *)
+    {!Rmtmps.removeUnused}. *)
 let keep_entry_point ?(specs=Kernel.Keep_unused_specified_functions.get ()) g =
+  let keepTypes = Kernel.Keep_unused_types.get () in
   Rmtmps.isExportedRoot g ||
   match g with
   | GFun({svar = v; sspec = spec},_)
@@ -618,6 +619,8 @@ let keep_entry_point ?(specs=Kernel.Keep_unused_specified_functions.get ()) g =
     || (specs && not (is_empty_funspec spec))
   (* and the declarations carrying specifications according to the
      command line.*)
+  | GType _ | GCompTag _ | GCompTagDecl _ | GEnumTag _ | GEnumTagDecl _ ->
+    keepTypes
   | _ -> false
 
 let files_to_cabs_cil files =
@@ -1096,7 +1099,7 @@ let prepare_cil_file ast =
   Transform_before_cleanup.apply ast;
   (* Remove unused temp variables and globals. *)
   Kernel.feedback ~level:2 "cleaning unused parts";
-  Rmtmps.removeUnusedTemps ~isRoot:keep_entry_point ast;
+  Rmtmps.removeUnused ~isRoot:keep_entry_point ast;
   if Kernel.Check.get () then begin
     Filecheck.check_ast ~is_normalized:false ~ast "Removed temp vars"
   end;
diff --git a/src/kernel_services/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml
index e77d3bf7ff4029797ed397fff4a6d27ca01e2d02..02f357e8ebbc52cf9fb7883e3551c04d322a9a6b 100644
--- a/src/kernel_services/plugin_entry_points/kernel.ml
+++ b/src/kernel_services/plugin_entry_points/kernel.ml
@@ -1131,6 +1131,15 @@ module Keep_unused_specified_functions =
           let help = "keep specified-but-unused functions"
         end)
 
+let () = Parameter_customize.set_group normalisation
+let () = Parameter_customize.set_negative_option_name "-remove-unused-types"
+module Keep_unused_types =
+  False(struct
+    let option_name = "-keep-unused-types"
+    let module_name = "Keep_unused_types"
+    let help = "keep unused types (false by default)"
+  end)
+
 let () = Parameter_customize.set_group normalisation
 module SimplifyTrivialLoops =
   True(struct
diff --git a/src/kernel_services/plugin_entry_points/kernel.mli b/src/kernel_services/plugin_entry_points/kernel.mli
index cf9edf9d0fb2f117fcdb109e04ba00d9577bd207..7976e6c86673f65f73788c64e6a77b384b0a0fed 100644
--- a/src/kernel_services/plugin_entry_points/kernel.mli
+++ b/src/kernel_services/plugin_entry_points/kernel.mli
@@ -396,7 +396,10 @@ module KeepSwitch: Parameter_sig.Bool
   (** Behavior of option "-keep-switch" *)
 
 module Keep_unused_specified_functions: Parameter_sig.Bool
-(** Behavior of option "-keep-unused-specified-function". *)
+(** Behavior of option "-keep-unused-specified-functions". *)
+
+module Keep_unused_types: Parameter_sig.Bool
+(** Behavior of option "-keep-unused-types". *)
 
 module SimplifyTrivialLoops: Parameter_sig.Bool
 (** Behavior of option "-simplify-trivial-loops". *)