diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/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({std::move(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(std::move(Argv), Action, *FileMgr, + PCHContainerOps, *Diags, Consumer); + }); + } if (Success && !Action.hasScanned()) Diags->Report(diag::err_fe_expected_compiler_job) diff --git a/clang/test/ClangScanDeps/modules-cc1.cpp b/clang/test/ClangScanDeps/modules-cc1.cpp new file mode 100644 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-cc1.cpp @@ -0,0 +1,29 @@ +// Check that clang-scan-deps works with cc1 command lines + +// RUN: rm -rf %t +// RUN: split-file %s %t + + +//--- modules_cc1.cpp +#include "header.h" + +//--- header.h + +//--- module.modulemap +module header1 { header "header.h" } + +//--- cdb.json.template +[{ + "file": "DIR/modules_cc1.cpp", + "directory": "DIR", + "command": "clang -cc1 DIR/modules_cc1.cpp -fimplicit-module-maps -o modules_cc1.o" +}] + +// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -j 1 -mode preprocess-dependency-directives > %t/result +// RUN: cat %t/result | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t + +// CHECK: modules_cc1.o: +// CHECK-NEXT: [[PREFIX]]/modules_cc1.cpp +// CHECK-NEXT: [[PREFIX]]/module.modulemap +// CHECK-NEXT: [[PREFIX]]/header.h