diff --git a/src/kernel_services/ast_queries/file.ml b/src/kernel_services/ast_queries/file.ml
index 402bf50a070abbcb31fc98deefc04b330eeab1a5..77f6394a474424a899cac185a8d1b09f76b2ccf8 100644
--- a/src/kernel_services/ast_queries/file.ml
+++ b/src/kernel_services/ast_queries/file.ml
@@ -36,9 +36,11 @@ let pretty_cpp_opt_kind fmt =
 type file =
   | NeedCPP of
       Filepath.Normalized.t (* filename of the [.c] to preprocess *)
-      * string (* Preprocessor command.
-                  [filename.c -o tempfilname.i] will be appended at the
-                    end.*)
+      * string (* Preprocessing command, as given by -cpp-command, or
+                  the default value, but without extra arguments *)
+      * string list (* Extra arguments to be given to the preprocessing
+                       command, as given by -cpp-extra-args-per-file or
+                       a JSON Compilation Database. *)
       * cpp_opt_kind
   | NoCPP of Filepath.Normalized.t (** filename of a preprocessed [.c] *)
   | External of Filepath.Normalized.t * string
@@ -51,7 +53,7 @@ module D =
       type t = file
       let name = "File"
       let reprs =
-        [ NeedCPP(Filepath.Normalized.unknown, "", Unknown);
+        [ NeedCPP(Filepath.Normalized.unknown, "", [], Unknown);
           NoCPP Filepath.Normalized.unknown;
           External(Filepath.Normalized.unknown, "")
         ]
@@ -65,11 +67,12 @@ module D =
           | External (f,p) ->
             Format.fprintf fmt "@[File.External (%a,%S)@]"
               Filepath.Normalized.pretty f p
-          | NeedCPP (f,cmd,kind) ->
+          | NeedCPP (f,cmd,extra,kind) ->
             Format.fprintf
-              fmt "@[File.NeedCPP (%a,%S,%a)@]"
+              fmt "@[File.NeedCPP (%a,%S,%S,%a)@]"
               Filepath.Normalized.pretty f
               cmd
+              (String.concat " " extra)
               pretty_cpp_opt_kind kind
         in
         Type.par p_caller Type.Call fmt pp
@@ -85,7 +88,7 @@ let get_suffixes () =
     [ ".c"; ".i"; ".h" ]
 
 let get_name s =
-  let file = match s with  NeedCPP (s,_,_) | NoCPP s | External (s,_) -> s in
+  let file = match s with  NeedCPP (s,_,_,_) | NoCPP s | External (s,_) -> s in
   Filepath.Normalized.to_pretty_string file
 
 (* ************************************************************************* *)
@@ -118,24 +121,23 @@ let get_preprocessor_command () =
 
 let from_filename ?cpp f =
   let cpp =
-    let cmdline = Kernel.CppCommand.get() in
-    if cmdline <> "" then cmdline
-    else
-      let extra_by_file =
-        try Kernel.CppExtraArgsPerFile.find f
-        with Not_found -> ""
-      in
-      let jcdb_flags = Json_compilation_database.get_flags f in
-      if extra_by_file <> "" && jcdb_flags <> [] then
-        Kernel.warning ~wkey:Kernel.wkey_jcdb
-          "found flags for file %a@ both in -cpp-extra-args-per-file and@ \
-           in the json compilation database;@ the latter will be ignored"
-          Filepath.Normalized.pretty f;
-      let cpp =
-        if cpp = None then get_preprocessor_command () else Option.get cpp
-      in
-      let flags = if extra_by_file <> "" then [extra_by_file] else jcdb_flags in
-      String.concat " " (cpp :: flags)
+    let cpp_command = Kernel.CppCommand.get() in
+    if cpp_command <> "" then cpp_command
+    else if cpp = None then get_preprocessor_command ()
+    else Option.get cpp
+  in
+  let extra =
+    let extra_by_file =
+      try Kernel.CppExtraArgsPerFile.find f
+      with Not_found -> ""
+    in
+    let jcdb_flags = Json_compilation_database.get_flags f in
+    if extra_by_file <> "" && jcdb_flags <> [] then
+      Kernel.warning ~wkey:Kernel.wkey_jcdb
+        "found flags for file %a@ both in -cpp-extra-args-per-file and@ \
+         in the json compilation database;@ the latter will be ignored"
+        Filepath.Normalized.pretty f;
+    if extra_by_file <> "" then [extra_by_file] else jcdb_flags
   in
   if Filename.check_suffix (f:>string) ".i" then begin
     NoCPP f
@@ -154,7 +156,7 @@ let from_filename ?cpp f =
         Kernel.warning ~once:true
           "Default pre-processor does not keep comments. Any ACSL annotation \
            on non-pre-processed file will be discarded.";
-      NeedCPP (f, cpp, is_cpp_gnu_like ())
+      NeedCPP (f, cpp, extra, is_cpp_gnu_like ())
     end else
       Kernel.abort "No working pre-processor found. You can only analyze \
                     pre-processed .i files."
@@ -440,7 +442,7 @@ let concat_strs ?(pre="") ?(sep=" ") l =
 
 let build_cpp_cmd = function
   | NoCPP _ | External _ -> None
-  | NeedCPP (f, cmdl, is_gnu_like) ->
+  | NeedCPP (f, cmdl, extra, is_gnu_like) ->
     if not (Sys.file_exists (f :> string)) then
       Kernel.abort "source file %a does not exist"
         Filepath.Normalized.pretty f;
@@ -519,16 +521,16 @@ let build_cpp_cmd = function
     in
     let supp_args =
       string_of_supp_args
-        (Kernel.CppExtraArgs.get () @ gnu_implicit_args @ supported_cpp_arch_args)
+        (Kernel.CppExtraArgs.get () @ gnu_implicit_args @ supported_cpp_arch_args @ extra)
         include_args define_args
     in
     let cpp_command = replace_in_cpp_cmd cmdl supp_args (f:>string) (ppf:>string) in
     Kernel.feedback ~dkey:Kernel.dkey_pp
       "@{<i>preprocessing@} with \"%s\""
       cpp_command;
-    Some (cpp_command, ppf, supported_cpp_arch_args)
+    Some (cpp_command, ppf, supp_args)
 
-let parse_cabs cpp_command_no_output = function
+let parse_cabs cpp_command = function
   | NoCPP f ->
     if not (Sys.file_exists (f:>string)) then
       Kernel.abort "preprocessed file %a does not exist"
@@ -536,8 +538,8 @@ let parse_cabs cpp_command_no_output = function
     Kernel.feedback "Parsing %a (no preprocessing)"
       Datatype.Filepath.pretty f;
     Frontc.parse f ()
-  | NeedCPP (f, cmdl, is_gnu_like) ->
-    let cpp_command, ppf, supported_cpp_arch_args = Option.get cpp_command_no_output in
+  | NeedCPP (f, cmdl, _extra, is_gnu_like) ->
+    let cpp_command, ppf, supp_args = Option.get cpp_command in
     Kernel.feedback "Parsing %a (with preprocessing)"
       Datatype.Filepath.pretty f;
     if Sys.command cpp_command <> 0 then begin
@@ -581,13 +583,9 @@ let parse_cabs cpp_command_no_output = function
                   "trying to preprocess annotation with an unknown \
                    preprocessor."; true))
       then begin
-        let pp_annot_supp_args =
-          Format.asprintf "-nostdinc %s"
-            (concat_strs supported_cpp_arch_args)
-        in
         let ppf' =
           try Logic_preprocess.file ".c"
-                (replace_in_cpp_cmd cmdl pp_annot_supp_args)
+                (replace_in_cpp_cmd cmdl supp_args)
                 (ppf : Filepath.Normalized.t :> string)
           with Sys_error _ as e ->
             safe_remove_file ppf;
diff --git a/src/kernel_services/ast_queries/file.mli b/src/kernel_services/ast_queries/file.mli
index 979ee3d7721c834f9ca225eb581cd408a6a4a8f8..5cbfef57263eb571b3967497ca1e6fbbae8b8a3a 100644
--- a/src/kernel_services/ast_queries/file.mli
+++ b/src/kernel_services/ast_queries/file.mli
@@ -30,10 +30,14 @@ type cpp_opt_kind = Gnu | Not_gnu | Unknown
     Note: [string] is used here instead of [Filepath], to preserve
           names given on the command line, without normalization. *)
 type file =
-  | NeedCPP of Filepath.Normalized.t * string * cpp_opt_kind
-  (** The first string is the filename of the [.c] to preprocess.
-      The second one is the preprocessor command ([filename.c -o
-      tempfilname.i] will be appended at the end).*)
+  | NeedCPP of Filepath.Normalized.t * string * string list * cpp_opt_kind
+  (** File which needs preprocessing.
+      NeedCPP(filepath, cmd, extra, cpp_opt_kind):
+      - filepath: source file to be preprocessed;
+      - cmd: preprocessing command, before replacement of '%'-arguments;
+      - extra: list of extra arguments (e.g. from a JCDB);
+      - cpp_opt_kind: whether the preprocessor supports GNU options
+        such as -I/-D. *)
   | NoCPP of Filepath.Normalized.t
   (** Already pre-processed file [.i] *)
   | External of Filepath.Normalized.t * string
diff --git a/tests/jcdb/jcdb.c b/tests/jcdb/jcdb.c
index f2389fe2e8ada1276a640ceb2689b7ff4f5a6f76..caf9e83a15294ec38baa1aec35760c73ecbcd5c9 100644
--- a/tests/jcdb/jcdb.c
+++ b/tests/jcdb/jcdb.c
@@ -4,6 +4,7 @@ OPT: -json-compilation-database @PTEST_DIR@ -print
 OPT: @PTEST_DIR@/jcdb2.c -json-compilation-database @PTEST_DIR@/with_arguments.json -print
 OPT: -json-compilation-database @PTEST_DIR@/with_arguments.json -no-autoload-plugins -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs
 EXECNOW: LOG list_files.res LOG list_files.err share/analysis-scripts/list_files.py @PTEST_DIR@/compile_commands_working.json > @PTEST_DIR@/result/list_files.res 2> @PTEST_DIR@/result/list_files.err
+EXECNOW: LOG logic-pp-include.res LOG logic-pp-include.err @frama-c@ -json-compilation-database @PTEST_DIR@/logic-pp-include @PTEST_DIR@/logic-pp-include/no-stdio.c -print -no-autoload-plugins > @PTEST_DIR@/result/logic-pp-include.res 2> @PTEST_DIR@/result/logic-pp-include.err
 */
 #include <stdio.h>
 
diff --git a/tests/jcdb/logic-pp-include/compile_commands.json b/tests/jcdb/logic-pp-include/compile_commands.json
new file mode 100644
index 0000000000000000000000000000000000000000..9e4246444d3e953299c8e11a2716c4d678b88369
--- /dev/null
+++ b/tests/jcdb/logic-pp-include/compile_commands.json
@@ -0,0 +1,11 @@
+[
+    {
+        "arguments": [
+            "-include",
+            "stdio.h",
+            "-DZERO=0"
+        ],
+        "directory": ".",
+        "file": "no-stdio.c"
+    }
+]
diff --git a/tests/jcdb/logic-pp-include/no-stdio.c b/tests/jcdb/logic-pp-include/no-stdio.c
new file mode 100644
index 0000000000000000000000000000000000000000..78444816bb2ae859c54f7156033ff7df90c39aa0
--- /dev/null
+++ b/tests/jcdb/logic-pp-include/no-stdio.c
@@ -0,0 +1,5 @@
+// compile_commands.json must have "-includestdio.h" and define ZERO
+int main(){
+  printf("bla\n");
+  return ZERO;
+}
diff --git a/tests/jcdb/oracle/logic-pp-include.err b/tests/jcdb/oracle/logic-pp-include.err
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/jcdb/oracle/logic-pp-include.res b/tests/jcdb/oracle/logic-pp-include.res
new file mode 100644
index 0000000000000000000000000000000000000000..a6aedf5c3dda4ac6f804a2708246461654bef1c8
--- /dev/null
+++ b/tests/jcdb/oracle/logic-pp-include.res
@@ -0,0 +1,15 @@
+[kernel] Parsing tests/jcdb/logic-pp-include/no-stdio.c (with preprocessing)
+/* Generated by Frama-C */
+#include "errno.h"
+#include "stdarg.h"
+#include "stddef.h"
+#include "stdio.h"
+int main(void)
+{
+  int __retres;
+  printf("bla\n");
+  __retres = 0;
+  return __retres;
+}
+
+