Index: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp =================================================================== --- clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -385,6 +385,9 @@ if (!Compilation) return false; + if (Compilation->containsError()) + return false; + for (const driver::Command &Job : Compilation->getJobs()) { if (!Callback(Job)) return false; @@ -392,6 +395,26 @@ return true; } +static bool createAndRunToolInvocation( + std::vector CommandLine, DependencyScanningAction &Action, + FileManager &FM, + std::shared_ptr &PCHContainerOps, + DiagnosticsEngine &Diags, DependencyConsumer &Consumer) { + + // Save executable path before providing CommandLine to ToolInvocation + std::string Executable = CommandLine[0]; + ToolInvocation Invocation(std::move(CommandLine), &Action, &FM, + PCHContainerOps); + Invocation.setDiagnosticConsumer(Diags.getClient()); + Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions()); + if (!Invocation.run()) + return false; + + std::vector Args = Action.takeLastCC1Arguments(); + Consumer.handleBuildCommand({Executable, std::move(Args)}); + return true; +} + bool DependencyScanningWorker::computeDependencies( StringRef WorkingDirectory, const std::vector &CommandLine, DependencyConsumer &Consumer, DependencyActionController &Controller, @@ -454,37 +477,37 @@ DependencyScanningAction Action(WorkingDirectory, Consumer, Controller, DepFS, Format, OptimizeArgs, EagerLoadModules, DisableFree, ModuleName); - bool Success = forEachDriverJob( - FinalCommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) { - if (StringRef(Cmd.getCreator().getName()) != "clang") { - // Non-clang command. Just pass through to the dependency - // consumer. - Consumer.handleBuildCommand( - {Cmd.getExecutable(), - {Cmd.getArguments().begin(), Cmd.getArguments().end()}}); - return true; - } - - std::vector Argv; - Argv.push_back(Cmd.getExecutable()); - Argv.insert(Argv.end(), Cmd.getArguments().begin(), - Cmd.getArguments().end()); - - // Create an invocation that uses the underlying file - // system to ensure that any file system requests that - // are made by the driver do not go through the - // dependency scanning filesystem. - ToolInvocation Invocation(std::move(Argv), &Action, &*FileMgr, - PCHContainerOps); - Invocation.setDiagnosticConsumer(Diags->getClient()); - Invocation.setDiagnosticOptions(&Diags->getDiagnosticOptions()); - if (!Invocation.run()) - return false; - - std::vector Args = Action.takeLastCC1Arguments(); - Consumer.handleBuildCommand({Cmd.getExecutable(), std::move(Args)}); - return true; - }); + + bool Success = false; + if (FinalCommandLine[1] == "-cc1") { + Success = createAndRunToolInvocation(FinalCommandLine, Action, *FileMgr, + PCHContainerOps, *Diags, Consumer); + } else { + Success = forEachDriverJob( + FinalCommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) { + if (StringRef(Cmd.getCreator().getName()) != "clang") { + // Non-clang command. Just pass through to the dependency + // consumer. + Consumer.handleBuildCommand( + {Cmd.getExecutable(), + {Cmd.getArguments().begin(), Cmd.getArguments().end()}}); + return true; + } + + // Insert -cc1 comand line options into Argv + std::vector Argv; + Argv.push_back(Cmd.getExecutable()); + Argv.insert(Argv.end(), Cmd.getArguments().begin(), + Cmd.getArguments().end()); + + // Create an invocation that uses the underlying file + // system to ensure that any file system requests that + // are made by the driver do not go through the + // dependency scanning filesystem. + return createAndRunToolInvocation(Argv, Action, *FileMgr, + PCHContainerOps, *Diags, Consumer); + }); + } if (Success && !Action.hasScanned()) Diags->Report(diag::err_fe_expected_compiler_job) Index: clang/unittests/Tooling/DependencyScannerTest.cpp =================================================================== --- clang/unittests/Tooling/DependencyScannerTest.cpp +++ clang/unittests/Tooling/DependencyScannerTest.cpp @@ -240,6 +240,42 @@ "test.cpp.o: /root/test.cpp /root/header.h\n"); } +TEST(DependencyScanner, ScanDepsWithCC1) { + std::vector CommandLine = {"clang", + "-cc1", + "-triple", + "x86_64-apple-macosx10.7", + "-x", + "c++", + "test.cpp", + "-o", + "test.cpp.o"}; + StringRef CWD = "/root"; + + auto VFS = new llvm::vfs::InMemoryFileSystem(); + VFS->setCurrentWorkingDirectory(CWD); + auto Sept = llvm::sys::path::get_separator(); + std::string HeaderPath = + std::string(llvm::formatv("{0}root{0}header.h", Sept)); + std::string TestPath = std::string(llvm::formatv("{0}root{0}test.cpp", Sept)); + + VFS->addFile(HeaderPath, 0, llvm::MemoryBuffer::getMemBuffer("\n")); + VFS->addFile(TestPath, 0, + llvm::MemoryBuffer::getMemBuffer("#include \"header.h\"\n")); + + DependencyScanningService Service(ScanningMode::DependencyDirectivesScan, + ScanningOutputFormat::Make); + DependencyScanningTool ScanTool(Service, VFS); + + std::string DepFile; + ASSERT_THAT_ERROR( + ScanTool.getDependencyFile(CommandLine, CWD).moveInto(DepFile), + llvm::Succeeded()); + using llvm::sys::path::convert_to_slash; + EXPECT_EQ(convert_to_slash(DepFile), + "test.cpp.o: /root/test.cpp /root/header.h\n"); +} + TEST(DependencyScanner, ScanDepsWithModuleLookup) { std::vector CommandLine = { "clang",