From 17cc5ec7bec1ef0d10fc3461f089384ee7e51c7f Mon Sep 17 00:00:00 2001 From: Martino Luca Date: Mon, 14 Aug 2017 07:30:14 -0700 Subject: [PATCH] Remove unsupported `index-store-path` argument from clang commands Summary: The `-index-store-path` argument does not exist in Clang 5.0 and it gets discarded without any error message. The problem is that its argument, a folder, is not discarded, and Clang considers it as a source file. This leads to the following errors: - `cannot specify -o when generating multiple output files` (this happens if a `-o` argument is passed) - `error reading ''` (this can be observed when running the "normalized" version of the clang command, generated via the -### flag) This weird case can be observed when `-index-store-path` is passed in a sequence like the following: `-x c -index-store-path -c`. With this change, we remove the `index-store-path` option, and its argument, from the original clang command. Reviewed By: jvillard Differential Revision: D5601808 fbshipit-source-id: 4200308 --- infer/src/clang/ClangCommand.ml | 41 ++++++++++++------- .../clang_with_blacklisted_flags/Makefile | 22 ++++++++++ .../clang_with_blacklisted_flags/issues.exp | 1 + 3 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 infer/tests/build_systems/clang_with_blacklisted_flags/Makefile create mode 100644 infer/tests/build_systems/clang_with_blacklisted_flags/issues.exp diff --git a/infer/src/clang/ClangCommand.ml b/infer/src/clang/ClangCommand.ml index ca988c1c2..79cdaaf38 100644 --- a/infer/src/clang/ClangCommand.ml +++ b/infer/src/clang/ClangCommand.ml @@ -65,12 +65,30 @@ let file_arg_cmd_sanitizer cmd = 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) + ?(blacklisted_flags= []) ?(blacklisted_flags_with_arg= []) ?(post_args= []) args = + let rec aux (prev, res_rev) args = + match args with + | [] + -> (* return non-reversed list *) + List.rev_append res_rev post_args + | flag :: tl when List.mem ~equal:String.equal blacklisted_flags flag + -> aux (flag, res_rev) tl + | flag1 :: flag2 :: tl when List.mem ~equal:String.equal blacklisted_flags_with_arg flag1 + -> aux (flag2, res_rev) tl + | arg :: tl + -> let res_rev' = replace_option_arg prev arg :: res_rev in + aux (arg, res_rev') tl + in + aux ("", []) args + (* Work around various path or library issues occurring when one tries to substitute Apple's version of clang with a different version. Also mitigate version discrepancies in clang's fatal warnings. *) let clang_cc1_cmd_sanitizer cmd = (* command line options not supported by the opensource compiler or the plugins *) - let flags_blacklist = ["-fembed-bitcode-marker"; "-fno-canonical-system-headers"] in + let blacklisted_flags = ["-fembed-bitcode-marker"; "-fno-canonical-system-headers"] in + let blacklisted_flags_with_arg = ["-mllvm"] in let replace_option_arg option arg = if String.equal option "-arch" && String.equal arg "armv7k" then "armv7" (* replace armv7k arch with armv7 *) @@ -100,22 +118,17 @@ let clang_cc1_cmd_sanitizer cmd = level. *) argv_cons "-Wno-everything" in - let rec filter_unsupported_args_and_swap_includes (prev, res_rev) = function - | [] - -> (* return non-reversed list *) - List.rev_append res_rev (List.rev post_args_rev) - | flag :: tl when List.mem ~equal:String.equal flags_blacklist flag - -> filter_unsupported_args_and_swap_includes (flag, res_rev) tl - | flag1 :: flag2 :: tl when String.equal "-mllvm" flag1 - -> filter_unsupported_args_and_swap_includes (flag2, res_rev) tl - | arg :: tl - -> let res_rev' = replace_option_arg prev arg :: res_rev in - filter_unsupported_args_and_swap_includes (arg, res_rev') tl + let clang_arguments = + filter_and_replace_unsupported_args ~blacklisted_flags ~blacklisted_flags_with_arg + ~replace_option_arg ~post_args:(List.rev post_args_rev) cmd.argv in - let clang_arguments = filter_unsupported_args_and_swap_includes ("", []) cmd.argv in file_arg_cmd_sanitizer {cmd with argv= clang_arguments} -let mk quoting_style ~prog ~args = {exec= prog; orig_argv= args; argv= args; quoting_style} +let mk quoting_style ~prog ~args = + (* 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 sanitized_args = filter_and_replace_unsupported_args ~blacklisted_flags_with_arg args in + {exec= prog; orig_argv= sanitized_args; argv= sanitized_args; quoting_style} let command_to_run cmd = let mk_cmd normalizer = diff --git a/infer/tests/build_systems/clang_with_blacklisted_flags/Makefile b/infer/tests/build_systems/clang_with_blacklisted_flags/Makefile new file mode 100644 index 000000000..e0ce0d24b --- /dev/null +++ b/infer/tests/build_systems/clang_with_blacklisted_flags/Makefile @@ -0,0 +1,22 @@ +# Copyright (c) 2017 - present Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +TESTS_DIR = ../.. + +ANALYZER = infer +# The "-index-store-path " argument does not exist in Clang and it gets +# discarded without any error message. The problem is that its argument, +# a folder, is not discarded, and Clang considers it as a source file. This +# leads to an error. This weird case can be observed when -index-store-path is +# passed in a sequence like the one in CLANG_OPTIONS. +CLANG_OPTIONS = -x c -index-store-path . -c +INFER_OPTIONS = --report-custom-error --developer-mode --project-root ../codetoanalyze --no-keep-going +INFERPRINT_OPTIONS = --issues-tests + +SOURCES = ../codetoanalyze/hello.c + +include $(TESTS_DIR)/clang.make diff --git a/infer/tests/build_systems/clang_with_blacklisted_flags/issues.exp b/infer/tests/build_systems/clang_with_blacklisted_flags/issues.exp new file mode 100644 index 000000000..d03e4fd25 --- /dev/null +++ b/infer/tests/build_systems/clang_with_blacklisted_flags/issues.exp @@ -0,0 +1 @@ +hello.c, test, 2, NULL_DEREFERENCE, [start of procedure test()]