diff --git a/analyzer/codechecker_analyzer/buildlog/log_parser.py b/analyzer/codechecker_analyzer/buildlog/log_parser.py index 54636d4c49..ad3bc9dbfa 100644 --- a/analyzer/codechecker_analyzer/buildlog/log_parser.py +++ b/analyzer/codechecker_analyzer/buildlog/log_parser.py @@ -216,6 +216,13 @@ '-iwithprefixbefore' ] +XCLANG_FLAGS_TO_SKIP = ['-module-file-info', + '-S', + '-emit-llvm', + '-emit-llvm-bc', + '-emit-llvm-only', + '-emit-llvm-uselists', + '-rewrite-objc'] COMPILE_OPTIONS_MERGED = \ re.compile('(' + '|'.join(COMPILE_OPTIONS_MERGED) + ')') @@ -674,6 +681,24 @@ def __collect_clang_compile_opts(flag_iterator, details): return True +def __collect_transform_xclang_opts(flag_iterator, details): + """Some specific -Xclang constucts need to be filtered out. + + To generate the proper plist reports and not LLVM IR or + ASCII text as an output the flags need to be removed. + """ + if flag_iterator.item == "-Xclang": + next(flag_iterator) + next_flag = flag_iterator.item + if next_flag in XCLANG_FLAGS_TO_SKIP: + return True + + details['analyzer_options'].extend(["-Xclang", next_flag]) + return True + + return False + + def __collect_transform_include_opts(flag_iterator, details): """ This function collects the compilation (i.e. not linker or preprocessor) @@ -920,6 +945,7 @@ def parse_options(compilation_db_entry, clang_flag_collectors = [ __skip_sources, __skip_clang, + __collect_transform_xclang_opts, __get_output, __determine_action_type, __get_arch, diff --git a/analyzer/tests/unit/test_option_parser.py b/analyzer/tests/unit/test_option_parser.py index a236e110d9..97e47fb88a 100644 --- a/analyzer/tests/unit/test_option_parser.py +++ b/analyzer/tests/unit/test_option_parser.py @@ -291,6 +291,34 @@ def test_ignore_warning_flags_clang(self): self.assertEqual(["-std=gnu++14"], res.analyzer_options) + def test_ignore_xclang_flags_clang(self): + """Skip some specific xclang constructs""" + + def fake_clang_version(a, b): + return True + + clang_flags = ["-std=gnu++14", + "-Xclang", "-module-file-info", + "-Xclang", "-S", + "-Xclang", "-emit-llvm", + "-Xclang", "-emit-llvm-bc", + "-Xclang", "-emit-llvm-only", + "-Xclang", "-emit-llvm-uselists", + "-Xclang", "-rewrite-objc", + "-Xclang", "-disable-O0-optnone"] + + xclang_skip = { + "directory": "/tmp", + "command": + "clang++ {} -c /tmp/a.cpp".format(' '.join(clang_flags)), + "file": "/tmp/a.cpp"} + + res = log_parser.parse_options( + xclang_skip, get_clangsa_version_func=fake_clang_version) + + self.assertEqual(["-std=gnu++14", "-Xclang", "-disable-O0-optnone"], + res.analyzer_options) + def test_preprocess_and_compile_with_extra_file_clang(self): """ -MF flag is followed by a dependency file. We shouldn't consider this