diff --git a/infer/src/backend/infer.ml b/infer/src/backend/infer.ml index 40f48466d..5a94e9634 100644 --- a/infer/src/backend/infer.ml +++ b/infer/src/backend/infer.ml @@ -56,13 +56,16 @@ let touch_start_file () = try Unix.close (Unix.openfile start flags file_perm) with Unix.Unix_error (Unix.EEXIST, _, _) -> () -type build_mode = Analyze | Ant | Buck | Gradle | Java | Javac | Make | Mvn | Ndk | Xcode +type build_mode = + | Analyze | Ant | Buck | ClangCompilationDatabase | Gradle | Java | Javac | Make | Mvn | Ndk + | Xcode let build_mode_of_string path = match Filename.basename path with | "analyze" -> Analyze | "ant" -> Ant | "buck" -> Buck + | "clang-compilation-database" -> ClangCompilationDatabase | "gradle" | "gradlew" -> Gradle | "java" -> Java | "javac" -> Javac @@ -147,7 +150,7 @@ let analyze = function | Java | Javac -> (* In Java and Javac modes, analysis is invoked from capture. *) () - | Analyze | Ant | Buck | Gradle | Make | Mvn | Ndk | Xcode -> + | Analyze | Ant | Buck | ClangCompilationDatabase | Gradle | Make | Mvn | Ndk | Xcode -> if not (Sys.file_exists Config.(results_dir // captured_dir_name)) then ( L.err "There was nothing to analyze, exiting" ; Config.print_usage_exit () diff --git a/infer/src/integration/BuckCompilationDatabase.ml b/infer/src/integration/BuckCompilationDatabase.ml index 8077b0095..793469eeb 100644 --- a/infer/src/integration/BuckCompilationDatabase.ml +++ b/infer/src/integration/BuckCompilationDatabase.ml @@ -74,15 +74,13 @@ let create_files_stack compilation_database = stack let swap_command cmd = + let plusplus = "++" in let clang = "clang" in let clangplusplus = "clang++" in - if Utils.string_is_suffix clang cmd then - Config.wrappers_dir // clang - else if Utils.string_is_suffix clangplusplus cmd then + if Utils.string_is_suffix plusplus cmd then Config.wrappers_dir // clangplusplus else - (* The command in the compilation database json emitted by buck can only be clang or clang++ *) - failwithf "Unexpected command name in Buck compilation database: %s" cmd + Config.wrappers_dir // clang let run_compilation_file compilation_database file = try diff --git a/infer/tests/build_systems/build_integration_tests.py b/infer/tests/build_systems/build_integration_tests.py index 4cffbd1e5..0b373609f 100755 --- a/infer/tests/build_systems/build_integration_tests.py +++ b/infer/tests/build_systems/build_integration_tests.py @@ -63,6 +63,7 @@ EXPECTED_OUTPUTS_DIR = os.path.join(SCRIPT_DIR, 'expected_outputs') ALL_TESTS = [ 'assembly', 'buck', + 'clang_compilation_database', 'cmake', 'componentkit', 'delete', @@ -442,6 +443,26 @@ class BuildIntegrationTest(unittest.TestCase): # remove build/ directory shutil.rmtree(build_root) + def test_clang_compilation_database_integration( + self, + enabled=None, + root=os.path.join(CODETOANALYZE_DIR, 'clang_compilation_database'), + report_fname='clang_compilation_database_report.json'): + build_root = os.path.join(root, 'build') + if test('clang_compilation_database', 'clang compilation database test', + build_root, + [{'compile': ['cmake', '-DCMAKE_EXPORT_COMPILE_COMMANDS=1', '..']}, + {'compile': ['clang-compilation-database', 'compile_commands.json']}], + available=lambda: is_tool_available(['cmake', '--version']), + enabled=enabled, + # remove build/ directory just in case + preprocess=lambda: shutil.rmtree(build_root, True), + # cmake produces absolute paths using the real path + postprocess=(lambda errors: + make_paths_relative_in_report( + os.path.realpath(root), errors))): + # remove build/ directory + shutil.rmtree(build_root) def test_utf8_in_pwd_integration(self): if not 'utf8_in_pwd' in to_test: diff --git a/infer/tests/build_systems/codetoanalyze/clang_compilation_database/CMakeLists.txt b/infer/tests/build_systems/codetoanalyze/clang_compilation_database/CMakeLists.txt new file mode 100644 index 000000000..b5b5f0157 --- /dev/null +++ b/infer/tests/build_systems/codetoanalyze/clang_compilation_database/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required (VERSION 3.1) +set(CMAKE_CXX_STANDARD 11) +project (HELLO) +add_library (Hello hello.cpp) diff --git a/infer/tests/build_systems/codetoanalyze/clang_compilation_database/hello.cpp b/infer/tests/build_systems/codetoanalyze/clang_compilation_database/hello.cpp new file mode 100644 index 000000000..ec86ac272 --- /dev/null +++ b/infer/tests/build_systems/codetoanalyze/clang_compilation_database/hello.cpp @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015 - 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. + */ + +void test() { + int* s = nullptr; // requires -std=c++11 flag + *s = 42; +} diff --git a/infer/tests/build_systems/expected_outputs/clang_compilation_database_report.json b/infer/tests/build_systems/expected_outputs/clang_compilation_database_report.json new file mode 100644 index 000000000..1361926e2 --- /dev/null +++ b/infer/tests/build_systems/expected_outputs/clang_compilation_database_report.json @@ -0,0 +1,7 @@ +[ + { + "bug_type": "NULL_DEREFERENCE", + "file": "hello.cpp", + "procedure": "test" + } +]