|
|
@ -12,6 +12,9 @@ module L = Logging
|
|
|
|
|
|
|
|
|
|
|
|
type t = {exec: string; argv: string list; orig_argv: string list; quoting_style: ClangQuotes.style}
|
|
|
|
type t = {exec: string; argv: string list; orig_argv: string list; quoting_style: ClangQuotes.style}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(** bad for every clang invocation *)
|
|
|
|
|
|
|
|
let clang_blacklisted_flags = ["-fembed-bitcode-marker"; "-fno-canonical-system-headers"]
|
|
|
|
|
|
|
|
|
|
|
|
let fcp_dir =
|
|
|
|
let fcp_dir =
|
|
|
|
Config.bin_dir ^/ Filename.parent_dir_name ^/ Filename.parent_dir_name
|
|
|
|
Config.bin_dir ^/ Filename.parent_dir_name ^/ Filename.parent_dir_name
|
|
|
|
^/ "facebook-clang-plugins"
|
|
|
|
^/ "facebook-clang-plugins"
|
|
|
@ -67,22 +70,54 @@ let file_arg_cmd_sanitizer cmd =
|
|
|
|
|
|
|
|
|
|
|
|
let include_override_regex = Option.map ~f:Str.regexp Config.clang_include_to_override_regex
|
|
|
|
let include_override_regex = Option.map ~f:Str.regexp Config.clang_include_to_override_regex
|
|
|
|
|
|
|
|
|
|
|
|
let filter_and_replace_unsupported_args ?(replace_option_arg= fun _ s -> s)
|
|
|
|
(** Filter arguments from [args], looking into argfiles too. [replace_options_arg prev arg] returns
|
|
|
|
|
|
|
|
[arg'], where [arg'] is the new version of [arg] given the preceding arguments (in reverse order) [prev]. *)
|
|
|
|
|
|
|
|
let filter_and_replace_unsupported_args ?(replace_options_arg= fun _ s -> s)
|
|
|
|
?(blacklisted_flags= []) ?(blacklisted_flags_with_arg= []) ?(post_args= []) args =
|
|
|
|
?(blacklisted_flags= []) ?(blacklisted_flags_with_arg= []) ?(post_args= []) args =
|
|
|
|
let rec aux (prev, res_rev) args =
|
|
|
|
(* [prev] is the previously seen argument, [res_rev] is the reversed result, [changed] is true if
|
|
|
|
|
|
|
|
some change has been performed *)
|
|
|
|
|
|
|
|
let rec aux (prev_is_blacklisted_with_arg, res_rev, changed) args =
|
|
|
|
match args with
|
|
|
|
match args with
|
|
|
|
| [] ->
|
|
|
|
| [] ->
|
|
|
|
(* return non-reversed list *)
|
|
|
|
(prev_is_blacklisted_with_arg, res_rev, changed)
|
|
|
|
List.rev_append res_rev post_args
|
|
|
|
| _ :: tl when prev_is_blacklisted_with_arg ->
|
|
|
|
|
|
|
|
(* in the unlikely event that a blacklisted flag with arg sits as the last option in some
|
|
|
|
|
|
|
|
arg file, we need to remove its argument now *)
|
|
|
|
|
|
|
|
aux (false, res_rev, true) tl
|
|
|
|
|
|
|
|
| at_argfile :: tl when String.is_prefix at_argfile ~prefix:"@"
|
|
|
|
|
|
|
|
-> (
|
|
|
|
|
|
|
|
let argfile = String.slice at_argfile 1 (String.length at_argfile) in
|
|
|
|
|
|
|
|
match In_channel.read_lines argfile with
|
|
|
|
|
|
|
|
| lines ->
|
|
|
|
|
|
|
|
(* poor parsing of arguments with some stripping supported; hope that tools generating
|
|
|
|
|
|
|
|
argfiles more or less put one argument per line *)
|
|
|
|
|
|
|
|
let strip s =
|
|
|
|
|
|
|
|
String.strip s
|
|
|
|
|
|
|
|
|> Utils.strip_balanced_once ~drop:(function '"' | '\'' -> true | _ -> false)
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
let last_in_file_is_blacklisted, rev_res_with_file_args, changed_file =
|
|
|
|
|
|
|
|
List.map ~f:strip lines |> aux (prev_is_blacklisted_with_arg, res_rev, false)
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
if changed_file then aux (last_in_file_is_blacklisted, rev_res_with_file_args, true) tl
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
(* keep the same argfile if we haven't needed to change anything in it *)
|
|
|
|
|
|
|
|
aux (last_in_file_is_blacklisted, at_argfile :: res_rev, changed) tl
|
|
|
|
|
|
|
|
| exception e ->
|
|
|
|
|
|
|
|
L.external_warning "Error reading argument file '%s': %s@\n" at_argfile
|
|
|
|
|
|
|
|
(Exn.to_string e) ;
|
|
|
|
|
|
|
|
aux (false, at_argfile :: res_rev, changed) tl )
|
|
|
|
| flag :: tl when List.mem ~equal:String.equal blacklisted_flags flag ->
|
|
|
|
| flag :: tl when List.mem ~equal:String.equal blacklisted_flags flag ->
|
|
|
|
aux (flag, res_rev) tl
|
|
|
|
aux (false, res_rev, true) tl
|
|
|
|
| flag1 :: flag2 :: tl when List.mem ~equal:String.equal blacklisted_flags_with_arg flag1 ->
|
|
|
|
| flag :: tl when List.mem ~equal:String.equal blacklisted_flags_with_arg flag ->
|
|
|
|
aux (flag2, res_rev) tl
|
|
|
|
(* remove the flag and its arg separately in case we are at the end of an argfile *)
|
|
|
|
|
|
|
|
aux (true, res_rev, true) tl
|
|
|
|
| arg :: tl ->
|
|
|
|
| arg :: tl ->
|
|
|
|
let res_rev' = replace_option_arg prev arg :: res_rev in
|
|
|
|
let arg' = replace_options_arg res_rev arg in
|
|
|
|
aux (arg, res_rev') tl
|
|
|
|
aux (false, arg' :: res_rev, changed || not (phys_equal arg arg')) tl
|
|
|
|
in
|
|
|
|
in
|
|
|
|
aux ("", []) args
|
|
|
|
match aux (false, [], false) args with _, res_rev, _ ->
|
|
|
|
|
|
|
|
(* return non-reversed list *)
|
|
|
|
|
|
|
|
List.rev_append res_rev post_args
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(* Work around various path or library issues occurring when one tries to substitute Apple's version
|
|
|
|
(* Work around various path or library issues occurring when one tries to substitute Apple's version
|
|
|
@ -90,26 +125,29 @@ let filter_and_replace_unsupported_args ?(replace_option_arg= fun _ s -> s)
|
|
|
|
fatal warnings. *)
|
|
|
|
fatal warnings. *)
|
|
|
|
let clang_cc1_cmd_sanitizer cmd =
|
|
|
|
let clang_cc1_cmd_sanitizer cmd =
|
|
|
|
(* command line options not supported by the opensource compiler or the plugins *)
|
|
|
|
(* command line options not supported by the opensource compiler or the plugins *)
|
|
|
|
let blacklisted_flags = ["-fembed-bitcode-marker"; "-fno-canonical-system-headers"] in
|
|
|
|
|
|
|
|
let blacklisted_flags_with_arg = ["-mllvm"] in
|
|
|
|
let blacklisted_flags_with_arg = ["-mllvm"] in
|
|
|
|
let replace_option_arg option arg =
|
|
|
|
let replace_options_arg options arg =
|
|
|
|
if String.equal option "-arch" && String.equal arg "armv7k" then "armv7"
|
|
|
|
match options with
|
|
|
|
(* replace armv7k arch with armv7 *)
|
|
|
|
| option :: _ ->
|
|
|
|
else if String.is_suffix arg ~suffix:"dep.tmp" then (
|
|
|
|
if String.equal option "-arch" && String.equal arg "armv7k" then "armv7"
|
|
|
|
(* compilation-database Buck integration produces path to `dep.tmp` file that doesn't exist. Create it *)
|
|
|
|
(* replace armv7k arch with armv7 *)
|
|
|
|
Unix.mkdir_p (Filename.dirname arg) ;
|
|
|
|
else if String.is_suffix arg ~suffix:"dep.tmp" then (
|
|
|
|
arg )
|
|
|
|
(* compilation-database Buck integration produces path to `dep.tmp` file that doesn't exist. Create it *)
|
|
|
|
else if String.equal option "-dependency-file"
|
|
|
|
Unix.mkdir_p (Filename.dirname arg) ;
|
|
|
|
&& Option.is_some Config.buck_compilation_database
|
|
|
|
arg )
|
|
|
|
(* In compilation database mode, dependency files are not assumed to exist *)
|
|
|
|
else if String.equal option "-dependency-file"
|
|
|
|
then "/dev/null"
|
|
|
|
&& Option.is_some Config.buck_compilation_database
|
|
|
|
else if String.equal option "-isystem" then
|
|
|
|
(* In compilation database mode, dependency files are not assumed to exist *)
|
|
|
|
match include_override_regex with
|
|
|
|
then "/dev/null"
|
|
|
|
| Some regexp when Str.string_match regexp arg 0 ->
|
|
|
|
else if String.equal option "-isystem" then
|
|
|
|
fcp_dir ^/ "clang" ^/ "install" ^/ "lib" ^/ "clang" ^/ "5.0.0" ^/ "include"
|
|
|
|
match include_override_regex with
|
|
|
|
| _ ->
|
|
|
|
| Some regexp when Str.string_match regexp arg 0 ->
|
|
|
|
arg
|
|
|
|
fcp_dir ^/ "clang" ^/ "install" ^/ "lib" ^/ "clang" ^/ "5.0.0" ^/ "include"
|
|
|
|
else arg
|
|
|
|
| _ ->
|
|
|
|
|
|
|
|
arg
|
|
|
|
|
|
|
|
else arg
|
|
|
|
|
|
|
|
| [] ->
|
|
|
|
|
|
|
|
arg
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let args_defines =
|
|
|
|
let args_defines =
|
|
|
|
if Config.bufferoverrun && not Config.biabduction then ["-D__INFER_BUFFEROVERRUN"] else []
|
|
|
|
if Config.bufferoverrun && not Config.biabduction then ["-D__INFER_BUFFEROVERRUN"] else []
|
|
|
@ -124,8 +162,8 @@ let clang_cc1_cmd_sanitizer cmd =
|
|
|
|
argv_cons "-Wno-everything"
|
|
|
|
argv_cons "-Wno-everything"
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let clang_arguments =
|
|
|
|
let clang_arguments =
|
|
|
|
filter_and_replace_unsupported_args ~blacklisted_flags ~blacklisted_flags_with_arg
|
|
|
|
filter_and_replace_unsupported_args ~blacklisted_flags:clang_blacklisted_flags
|
|
|
|
~replace_option_arg ~post_args:(List.rev post_args_rev) cmd.argv
|
|
|
|
~blacklisted_flags_with_arg ~replace_options_arg ~post_args:(List.rev post_args_rev) cmd.argv
|
|
|
|
in
|
|
|
|
in
|
|
|
|
file_arg_cmd_sanitizer {cmd with argv= clang_arguments}
|
|
|
|
file_arg_cmd_sanitizer {cmd with argv= clang_arguments}
|
|
|
|
|
|
|
|
|
|
|
@ -133,7 +171,10 @@ let clang_cc1_cmd_sanitizer cmd =
|
|
|
|
let mk quoting_style ~prog ~args =
|
|
|
|
let mk quoting_style ~prog ~args =
|
|
|
|
(* Some arguments break the compiler so they need to be removed even before the normalization step *)
|
|
|
|
(* Some arguments break the compiler so they need to be removed even before the normalization step *)
|
|
|
|
let blacklisted_flags_with_arg = ["-index-store-path"] in
|
|
|
|
let blacklisted_flags_with_arg = ["-index-store-path"] in
|
|
|
|
let sanitized_args = filter_and_replace_unsupported_args ~blacklisted_flags_with_arg args in
|
|
|
|
let sanitized_args =
|
|
|
|
|
|
|
|
filter_and_replace_unsupported_args ~blacklisted_flags:clang_blacklisted_flags
|
|
|
|
|
|
|
|
~blacklisted_flags_with_arg args
|
|
|
|
|
|
|
|
in
|
|
|
|
{exec= prog; orig_argv= sanitized_args; argv= sanitized_args; quoting_style}
|
|
|
|
{exec= prog; orig_argv= sanitized_args; argv= sanitized_args; quoting_style}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|