28#include "llvm/ADT/IntrusiveRefCntPtr.h"
29#include "llvm/Support/Allocator.h"
30#include "llvm/Support/Error.h"
31#include "llvm/Support/MemoryBuffer.h"
32#include "llvm/TargetParser/Host.h"
43 PCHContainerOps = std::make_shared<PCHContainerOperations>();
45 PCHContainerOps->registerReader(
46 std::make_unique<ObjectFilePCHContainerReader>());
48 PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
50 if (Service.shouldTraceVFS())
51 FS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(FS));
53 switch (Service.getMode()) {
55 DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
56 Service.getSharedCache(), FS);
66static std::unique_ptr<DiagnosticOptions>
68 std::vector<const char *> CLI;
69 for (
const std::string &Arg : CommandLine)
70 CLI.push_back(Arg.c_str());
77 StringRef WorkingDirectory,
const std::vector<std::string> &CommandLine,
79 std::optional<llvm::MemoryBufferRef> TUBuffer) {
82 std::string DiagnosticOutput;
83 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
88 DiagPrinter, TUBuffer))
89 return llvm::Error::success();
90 return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
91 llvm::inconvertibleErrorCode());
95 StringRef WorkingDirectory,
const std::vector<std::string> &CommandLine,
97 StringRef ModuleName) {
100 std::string DiagnosticOutput;
101 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
106 DiagPrinter, ModuleName))
107 return llvm::Error::success();
108 return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
109 llvm::inconvertibleErrorCode());
117 Argv.reserve(ArgStrs.size());
118 for (
const std::string &Arg : ArgStrs)
119 Argv.push_back(Arg.c_str());
121 std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
122 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
123 "clang LLVM compiler", FS);
124 Driver->setTitle(
"clang_based_tool");
126 llvm::BumpPtrAllocator Alloc;
132 Diags.
Report(diag::err_drv_expand_response_file)
133 << llvm::toString(std::move(E));
137 const std::unique_ptr<driver::Compilation> Compilation(
142 if (Compilation->containsError())
155 std::shared_ptr<clang::PCHContainerOperations> &PCHContainerOps,
159 std::string Executable = CommandLine[0];
161 llvm::opt::ArgStringList Argv;
162 for (
const std::string &Str :
ArrayRef(CommandLine).drop_front())
163 Argv.push_back(Str.c_str());
165 auto Invocation = std::make_shared<CompilerInvocation>();
171 if (!Action.
runInvocation(std::move(Invocation), std::move(FS),
180bool DependencyScanningWorker::scanDependencies(
181 StringRef WorkingDirectory,
const std::vector<std::string> &CommandLine,
183 DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
184 std::optional<StringRef> ModuleName) {
185 std::vector<const char *> CCommandLine(CommandLine.size(),
nullptr);
186 llvm::transform(CommandLine, CCommandLine.begin(),
187 [](
const std::string &Str) { return Str.c_str(); });
193 DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
194 Controller, DepFS, ModuleName);
197 if (CommandLine[1] ==
"-cc1") {
199 PCHContainerOps, *Diags, Consumer);
202 CommandLine, *Diags, FS, [&](
const driver::Command &Cmd) {
213 std::vector<std::string> Argv;
222 PCHContainerOps, *Diags, Consumer);
226 if (
Success && !Action.hasScanned())
227 Diags->
Report(diag::err_fe_expected_compiler_job)
228 << llvm::join(CommandLine,
" ");
231 if (!Action.hasDiagConsumerFinished())
234 return Success && Action.hasScanned();
238 StringRef WorkingDirectory,
const std::vector<std::string> &CommandLine,
242 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
244 std::optional<std::vector<std::string>> ModifiedCommandLine;
252 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
254 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
255 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
256 auto InputPath = TUBuffer->getBufferIdentifier();
259 llvm::MemoryBuffer::getMemBufferCopy(TUBuffer->getBuffer()));
263 OverlayFS->pushOverlay(InMemoryOverlay);
264 ModifiedFS = OverlayFS;
265 ModifiedCommandLine = CommandLine;
266 ModifiedCommandLine->emplace_back(InputPath);
269 const std::vector<std::string> &FinalCommandLine =
270 ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
271 auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
273 return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer,
274 Controller, DC, FinalFS, std::nullopt);
278 StringRef WorkingDirectory,
const std::vector<std::string> &CommandLine,
282 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
288 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
289 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
290 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
293 llvm::sys::fs::createUniquePath(ModuleName +
"-%%%%%%%%.input", FakeInputPath,
295 InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(
""));
298 OverlayFS->pushOverlay(InMemoryOverlay);
299 auto ModifiedCommandLine = CommandLine;
300 ModifiedCommandLine.emplace_back(FakeInputPath);
302 return scanDependencies(WorkingDirectory, ModifiedCommandLine, Consumer,
303 Controller, DC, OverlayFS, ModuleName);
static bool createAndRunToolInvocation(std::vector< std::string > CommandLine, DependencyScanningAction &Action, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, std::shared_ptr< clang::PCHContainerOperations > &PCHContainerOps, DiagnosticsEngine &Diags, DependencyConsumer &Consumer)
static std::unique_ptr< DiagnosticOptions > createDiagOptions(const std::vector< std::string > &CommandLine)
static bool forEachDriverJob(ArrayRef< std::string > ArgStrs, DiagnosticsEngine &Diags, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, llvm::function_ref< bool(const driver::Command &Cmd)> Callback)
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation's diagnostic options and replace any existing one ...
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
virtual void finish()
Callback to inform the diagnostic client that processing of all source files has ended.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
DiagnosticConsumer * getClient()
Command - An executable path/name and argument vector to execute.
const Tool & getCreator() const
getCreator - Return the Tool which caused the creation of this job.
const llvm::opt::ArgStringList & getArguments() const
const char * getExecutable() const
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef< const char * > Args)
Returns the driver mode option's value, i.e.
llvm::Error expandResponseFiles(SmallVectorImpl< const char * > &Args, bool ClangCLMode, llvm::BumpPtrAllocator &Alloc, llvm::vfs::FileSystem *FS=nullptr)
Expand response files from a clang driver or cc1 invocation.
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
@ Success
Annotation was successful.