clang  9.0.0svn
Tooling.cpp
Go to the documentation of this file.
1 //===- Tooling.cpp - Running clang standalone tools -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements functions to run clang tools standalone instead
10 // of running them as a plugin.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Tooling/Tooling.h"
15 #include "clang/Basic/Diagnostic.h"
20 #include "clang/Basic/LLVM.h"
22 #include "clang/Driver/Driver.h"
23 #include "clang/Driver/Job.h"
24 #include "clang/Driver/Options.h"
25 #include "clang/Driver/Tool.h"
26 #include "clang/Driver/ToolChain.h"
27 #include "clang/Frontend/ASTUnit.h"
37 #include "llvm/ADT/ArrayRef.h"
38 #include "llvm/ADT/IntrusiveRefCntPtr.h"
39 #include "llvm/ADT/SmallString.h"
40 #include "llvm/ADT/StringRef.h"
41 #include "llvm/ADT/Twine.h"
42 #include "llvm/Option/ArgList.h"
43 #include "llvm/Option/OptTable.h"
44 #include "llvm/Option/Option.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/Debug.h"
47 #include "llvm/Support/ErrorHandling.h"
48 #include "llvm/Support/FileSystem.h"
49 #include "llvm/Support/Host.h"
50 #include "llvm/Support/MemoryBuffer.h"
51 #include "llvm/Support/Path.h"
52 #include "llvm/Support/VirtualFileSystem.h"
53 #include "llvm/Support/raw_ostream.h"
54 #include <cassert>
55 #include <cstring>
56 #include <memory>
57 #include <string>
58 #include <system_error>
59 #include <utility>
60 #include <vector>
61 
62 #define DEBUG_TYPE "clang-tooling"
63 
64 using namespace clang;
65 using namespace tooling;
66 
67 ToolAction::~ToolAction() = default;
68 
70 
71 // FIXME: This file contains structural duplication with other parts of the
72 // code that sets up a compiler to run tools on it, and we should refactor
73 // it to be based on the same framework.
74 
75 /// Builds a clang driver initialized for running clang tools.
76 static driver::Driver *
77 newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName,
79  driver::Driver *CompilerDriver =
80  new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
81  *Diagnostics, std::move(VFS));
82  CompilerDriver->setTitle("clang_based_tool");
83  return CompilerDriver;
84 }
85 
86 /// Retrieves the clang CC1 specific flags out of the compilation's jobs.
87 ///
88 /// Returns nullptr on error.
89 static const llvm::opt::ArgStringList *getCC1Arguments(
90  DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation) {
91  // We expect to get back exactly one Command job, if we didn't something
92  // failed. Extract that job from the Compilation.
93  const driver::JobList &Jobs = Compilation->getJobs();
94  if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
95  SmallString<256> error_msg;
96  llvm::raw_svector_ostream error_stream(error_msg);
97  Jobs.Print(error_stream, "; ", true);
98  Diagnostics->Report(diag::err_fe_expected_compiler_job)
99  << error_stream.str();
100  return nullptr;
101  }
102 
103  // The one job we find should be to invoke clang again.
104  const auto &Cmd = cast<driver::Command>(*Jobs.begin());
105  if (StringRef(Cmd.getCreator().getName()) != "clang") {
106  Diagnostics->Report(diag::err_fe_expected_clang_command);
107  return nullptr;
108  }
109 
110  return &Cmd.getArguments();
111 }
112 
113 namespace clang {
114 namespace tooling {
115 
116 /// Returns a clang build invocation initialized from the CC1 flags.
118  DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args) {
119  assert(!CC1Args.empty() && "Must at least contain the program name!");
120  CompilerInvocation *Invocation = new CompilerInvocation;
122  *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
123  *Diagnostics);
124  Invocation->getFrontendOpts().DisableFree = false;
125  Invocation->getCodeGenOpts().DisableFree = false;
126  return Invocation;
127 }
128 
129 bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code,
130  const Twine &FileName,
131  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
132  return runToolOnCodeWithArgs(ToolAction, Code, std::vector<std::string>(),
133  FileName, "clang-tool",
134  std::move(PCHContainerOps));
135 }
136 
137 } // namespace tooling
138 } // namespace clang
139 
140 static std::vector<std::string>
141 getSyntaxOnlyToolArgs(const Twine &ToolName,
142  const std::vector<std::string> &ExtraArgs,
143  StringRef FileName) {
144  std::vector<std::string> Args;
145  Args.push_back(ToolName.str());
146  Args.push_back("-fsyntax-only");
147  Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
148  Args.push_back(FileName.str());
149  return Args;
150 }
151 
152 namespace clang {
153 namespace tooling {
154 
156  FrontendAction *ToolAction, const Twine &Code,
158  const std::vector<std::string> &Args, const Twine &FileName,
159  const Twine &ToolName,
160  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
161  SmallString<16> FileNameStorage;
162  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
163 
165  new FileManager(FileSystemOptions(), VFS));
167  ToolInvocation Invocation(
168  getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
169  ToolAction, Files.get(),
170  std::move(PCHContainerOps));
171  return Invocation.run();
172 }
173 
175  FrontendAction *ToolAction, const Twine &Code,
176  const std::vector<std::string> &Args, const Twine &FileName,
177  const Twine &ToolName,
178  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
179  const FileContentMappings &VirtualMappedFiles) {
181  new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
183  new llvm::vfs::InMemoryFileSystem);
184  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
185 
186  SmallString<1024> CodeStorage;
187  InMemoryFileSystem->addFile(FileName, 0,
188  llvm::MemoryBuffer::getMemBuffer(
189  Code.toNullTerminatedStringRef(CodeStorage)));
190 
191  for (auto &FilenameWithContent : VirtualMappedFiles) {
192  InMemoryFileSystem->addFile(
193  FilenameWithContent.first, 0,
194  llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second));
195  }
196 
197  return runToolOnCodeWithArgs(ToolAction, Code, OverlayFileSystem, Args,
198  FileName, ToolName);
199 }
200 
202  StringRef File) {
203  StringRef RelativePath(File);
204  // FIXME: Should '.\\' be accepted on Win32?
205  if (RelativePath.startswith("./")) {
206  RelativePath = RelativePath.substr(strlen("./"));
207  }
208 
209  SmallString<1024> AbsolutePath = RelativePath;
210  if (auto EC = FS.makeAbsolute(AbsolutePath))
211  return llvm::errorCodeToError(EC);
212  llvm::sys::path::native(AbsolutePath);
213  return AbsolutePath.str();
214 }
215 
216 std::string getAbsolutePath(StringRef File) {
217  return llvm::cantFail(getAbsolutePath(*llvm::vfs::getRealFileSystem(), File));
218 }
219 
220 void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
221  StringRef InvokedAs) {
222  if (!CommandLine.empty() && !InvokedAs.empty()) {
223  bool AlreadyHasTarget = false;
224  bool AlreadyHasMode = false;
225  // Skip CommandLine[0].
226  for (auto Token = ++CommandLine.begin(); Token != CommandLine.end();
227  ++Token) {
228  StringRef TokenRef(*Token);
229  AlreadyHasTarget |=
230  (TokenRef == "-target" || TokenRef.startswith("-target="));
231  AlreadyHasMode |= (TokenRef == "--driver-mode" ||
232  TokenRef.startswith("--driver-mode="));
233  }
234  auto TargetMode =
236  if (!AlreadyHasMode && TargetMode.DriverMode) {
237  CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
238  }
239  if (!AlreadyHasTarget && TargetMode.TargetIsValid) {
240  CommandLine.insert(++CommandLine.begin(), {"-target",
241  TargetMode.TargetPrefix});
242  }
243  }
244 }
245 
246 } // namespace tooling
247 } // namespace clang
248 
249 namespace {
250 
251 class SingleFrontendActionFactory : public FrontendActionFactory {
252  FrontendAction *Action;
253 
254 public:
255  SingleFrontendActionFactory(FrontendAction *Action) : Action(Action) {}
256 
257  FrontendAction *create() override { return Action; }
258 };
259 
260 } // namespace
261 
263  std::vector<std::string> CommandLine, ToolAction *Action,
264  FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
265  : CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false),
266  Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {}
267 
269  std::vector<std::string> CommandLine, FrontendAction *FAction,
270  FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
271  : CommandLine(std::move(CommandLine)),
272  Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true),
273  Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {}
274 
276  if (OwnsAction)
277  delete Action;
278 }
279 
280 void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
281  SmallString<1024> PathStorage;
282  llvm::sys::path::native(FilePath, PathStorage);
283  MappedFileContents[PathStorage] = Content;
284 }
285 
287  std::vector<const char*> Argv;
288  for (const std::string &Str : CommandLine)
289  Argv.push_back(Str.c_str());
290  const char *const BinaryName = Argv[0];
292  unsigned MissingArgIndex, MissingArgCount;
293  std::unique_ptr<llvm::opt::OptTable> Opts = driver::createDriverOptTable();
294  llvm::opt::InputArgList ParsedArgs = Opts->ParseArgs(
295  ArrayRef<const char *>(Argv).slice(1), MissingArgIndex, MissingArgCount);
296  ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
297  TextDiagnosticPrinter DiagnosticPrinter(
298  llvm::errs(), &*DiagOpts);
299  DiagnosticsEngine Diagnostics(
301  DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
302 
303  const std::unique_ptr<driver::Driver> Driver(
304  newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
305  // The "input file not found" diagnostics from the driver are useful.
306  // The driver is only aware of the VFS working directory, but some clients
307  // change this at the FileManager level instead.
308  // In this case the checks have false positives, so skip them.
309  if (!Files->getFileSystemOpts().WorkingDir.empty())
310  Driver->setCheckInputsExist(false);
311  const std::unique_ptr<driver::Compilation> Compilation(
312  Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
313  if (!Compilation)
314  return false;
315  const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
316  &Diagnostics, Compilation.get());
317  if (!CC1Args)
318  return false;
319  std::unique_ptr<CompilerInvocation> Invocation(
320  newInvocation(&Diagnostics, *CC1Args));
321  // FIXME: remove this when all users have migrated!
322  for (const auto &It : MappedFileContents) {
323  // Inject the code as the given file name into the preprocessor options.
324  std::unique_ptr<llvm::MemoryBuffer> Input =
325  llvm::MemoryBuffer::getMemBuffer(It.getValue());
326  Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(),
327  Input.release());
328  }
329  return runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
330  std::move(PCHContainerOps));
331 }
332 
333 bool ToolInvocation::runInvocation(
334  const char *BinaryName, driver::Compilation *Compilation,
335  std::shared_ptr<CompilerInvocation> Invocation,
336  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
337  // Show the invocation, with -v.
338  if (Invocation->getHeaderSearchOpts().Verbose) {
339  llvm::errs() << "clang Invocation:\n";
340  Compilation->getJobs().Print(llvm::errs(), "\n", true);
341  llvm::errs() << "\n";
342  }
343 
344  return Action->runInvocation(std::move(Invocation), Files,
345  std::move(PCHContainerOps), DiagConsumer);
346 }
347 
349  std::shared_ptr<CompilerInvocation> Invocation, FileManager *Files,
350  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
351  DiagnosticConsumer *DiagConsumer) {
352  // Create a compiler instance to handle the actual work.
353  CompilerInstance Compiler(std::move(PCHContainerOps));
354  Compiler.setInvocation(std::move(Invocation));
355  Compiler.setFileManager(Files);
356 
357  // The FrontendAction can have lifetime requirements for Compiler or its
358  // members, and we need to ensure it's deleted earlier than Compiler. So we
359  // pass it to an std::unique_ptr declared after the Compiler variable.
360  std::unique_ptr<FrontendAction> ScopedToolAction(create());
361 
362  // Create the compiler's actual diagnostics engine.
363  Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
364  if (!Compiler.hasDiagnostics())
365  return false;
366 
367  Compiler.createSourceManager(*Files);
368 
369  const bool Success = Compiler.ExecuteAction(*ScopedToolAction);
370 
371  Files->clearStatCache();
372  return Success;
373 }
374 
376  ArrayRef<std::string> SourcePaths,
377  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
379  : Compilations(Compilations), SourcePaths(SourcePaths),
380  PCHContainerOps(std::move(PCHContainerOps)),
381  OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))),
382  InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
383  Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) {
384  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
388 }
389 
390 ClangTool::~ClangTool() = default;
391 
392 void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
393  MappedFileContents.push_back(std::make_pair(FilePath, Content));
394 }
395 
397  ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
398 }
399 
401  ArgsAdjuster = nullptr;
402 }
403 
404 static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
405  void *MainAddr) {
406  // Allow users to override the resource dir.
407  for (StringRef Arg : Args)
408  if (Arg.startswith("-resource-dir"))
409  return;
410 
411  // If there's no override in place add our resource dir.
412  Args.push_back("-resource-dir=" +
413  CompilerInvocation::GetResourcesPath(Argv0, MainAddr));
414 }
415 
417  // Exists solely for the purpose of lookup of the resource path.
418  // This just needs to be some symbol in the binary.
419  static int StaticSymbol;
420 
421  // First insert all absolute paths into the in-memory VFS. These are global
422  // for all compile commands.
423  if (SeenWorkingDirectories.insert("/").second)
424  for (const auto &MappedFile : MappedFileContents)
425  if (llvm::sys::path::is_absolute(MappedFile.first))
426  InMemoryFileSystem->addFile(
427  MappedFile.first, 0,
428  llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
429 
430  bool ProcessingFailed = false;
431  bool FileSkipped = false;
432  // Compute all absolute paths before we run any actions, as those will change
433  // the working directory.
434  std::vector<std::string> AbsolutePaths;
435  AbsolutePaths.reserve(SourcePaths.size());
436  for (const auto &SourcePath : SourcePaths) {
437  auto AbsPath = getAbsolutePath(*OverlayFileSystem, SourcePath);
438  if (!AbsPath) {
439  llvm::errs() << "Skipping " << SourcePath
440  << ". Error while getting an absolute path: "
441  << llvm::toString(AbsPath.takeError()) << "\n";
442  continue;
443  }
444  AbsolutePaths.push_back(std::move(*AbsPath));
445  }
446 
447  // Remember the working directory in case we need to restore it.
448  std::string InitialWorkingDir;
449  if (RestoreCWD) {
450  if (auto CWD = OverlayFileSystem->getCurrentWorkingDirectory()) {
451  InitialWorkingDir = std::move(*CWD);
452  } else {
453  llvm::errs() << "Could not get working directory: "
454  << CWD.getError().message() << "\n";
455  }
456  }
457 
458  for (llvm::StringRef File : AbsolutePaths) {
459  // Currently implementations of CompilationDatabase::getCompileCommands can
460  // change the state of the file system (e.g. prepare generated headers), so
461  // this method needs to run right before we invoke the tool, as the next
462  // file may require a different (incompatible) state of the file system.
463  //
464  // FIXME: Make the compilation database interface more explicit about the
465  // requirements to the order of invocation of its members.
466  std::vector<CompileCommand> CompileCommandsForFile =
467  Compilations.getCompileCommands(File);
468  if (CompileCommandsForFile.empty()) {
469  llvm::errs() << "Skipping " << File << ". Compile command not found.\n";
470  FileSkipped = true;
471  continue;
472  }
473  for (CompileCommand &CompileCommand : CompileCommandsForFile) {
474  // FIXME: chdir is thread hostile; on the other hand, creating the same
475  // behavior as chdir is complex: chdir resolves the path once, thus
476  // guaranteeing that all subsequent relative path operations work
477  // on the same path the original chdir resulted in. This makes a
478  // difference for example on network filesystems, where symlinks might be
479  // switched during runtime of the tool. Fixing this depends on having a
480  // file system abstraction that allows openat() style interactions.
481  if (OverlayFileSystem->setCurrentWorkingDirectory(
483  llvm::report_fatal_error("Cannot chdir into \"" +
484  Twine(CompileCommand.Directory) + "\n!");
485 
486  // Now fill the in-memory VFS with the relative file mappings so it will
487  // have the correct relative paths. We never remove mappings but that
488  // should be fine.
489  if (SeenWorkingDirectories.insert(CompileCommand.Directory).second)
490  for (const auto &MappedFile : MappedFileContents)
491  if (!llvm::sys::path::is_absolute(MappedFile.first))
492  InMemoryFileSystem->addFile(
493  MappedFile.first, 0,
494  llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
495 
496  std::vector<std::string> CommandLine = CompileCommand.CommandLine;
497  if (ArgsAdjuster)
498  CommandLine = ArgsAdjuster(CommandLine, CompileCommand.Filename);
499  assert(!CommandLine.empty());
500 
501  // Add the resource dir based on the binary of this tool. argv[0] in the
502  // compilation database may refer to a different compiler and we want to
503  // pick up the very same standard library that compiler is using. The
504  // builtin headers in the resource dir need to match the exact clang
505  // version the tool is using.
506  // FIXME: On linux, GetMainExecutable is independent of the value of the
507  // first argument, thus allowing ClangTool and runToolOnCode to just
508  // pass in made-up names here. Make sure this works on other platforms.
509  injectResourceDir(CommandLine, "clang_tool", &StaticSymbol);
510 
511  // FIXME: We need a callback mechanism for the tool writer to output a
512  // customized message for each file.
513  LLVM_DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; });
514  ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
515  PCHContainerOps);
516  Invocation.setDiagnosticConsumer(DiagConsumer);
517 
518  if (!Invocation.run()) {
519  // FIXME: Diagnostics should be used instead.
520  llvm::errs() << "Error while processing " << File << ".\n";
521  ProcessingFailed = true;
522  }
523  }
524  }
525 
526  if (!InitialWorkingDir.empty()) {
527  if (auto EC =
528  OverlayFileSystem->setCurrentWorkingDirectory(InitialWorkingDir))
529  llvm::errs() << "Error when trying to restore working dir: "
530  << EC.message() << "\n";
531  }
532  return ProcessingFailed ? 1 : (FileSkipped ? 2 : 0);
533 }
534 
535 namespace {
536 
537 class ASTBuilderAction : public ToolAction {
538  std::vector<std::unique_ptr<ASTUnit>> &ASTs;
539 
540 public:
541  ASTBuilderAction(std::vector<std::unique_ptr<ASTUnit>> &ASTs) : ASTs(ASTs) {}
542 
543  bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
544  FileManager *Files,
545  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
546  DiagnosticConsumer *DiagConsumer) override {
547  std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
548  Invocation, std::move(PCHContainerOps),
549  CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(),
550  DiagConsumer,
551  /*ShouldOwnClient=*/false),
552  Files);
553  if (!AST)
554  return false;
555 
556  ASTs.push_back(std::move(AST));
557  return true;
558  }
559 };
560 
561 } // namespace
562 
563 int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
564  ASTBuilderAction Action(ASTs);
565  return run(&Action);
566 }
567 
568 void ClangTool::setRestoreWorkingDir(bool RestoreCWD) {
569  this->RestoreCWD = RestoreCWD;
570 }
571 
572 namespace clang {
573 namespace tooling {
574 
575 std::unique_ptr<ASTUnit>
576 buildASTFromCode(StringRef Code, StringRef FileName,
577  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
578  return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
579  "clang-tool", std::move(PCHContainerOps));
580 }
581 
582 std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
583  StringRef Code, const std::vector<std::string> &Args, StringRef FileName,
584  StringRef ToolName, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
585  ArgumentsAdjuster Adjuster) {
586  std::vector<std::unique_ptr<ASTUnit>> ASTs;
587  ASTBuilderAction Action(ASTs);
589  new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
591  new llvm::vfs::InMemoryFileSystem);
592  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
594  new FileManager(FileSystemOptions(), OverlayFileSystem));
595 
596  ToolInvocation Invocation(
597  getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName),
598  &Action, Files.get(), std::move(PCHContainerOps));
599 
600  InMemoryFileSystem->addFile(FileName, 0,
601  llvm::MemoryBuffer::getMemBufferCopy(Code));
602  if (!Invocation.run())
603  return nullptr;
604 
605  assert(ASTs.size() == 1);
606  return std::move(ASTs[0]);
607 }
608 
609 } // namespace tooling
610 } // namespace clang
bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, DiagnosticsEngine *Diags=nullptr, bool DefaultDiagColor=true, bool DefaultShowOpt=true)
Fill out Opts based on the options given in Args.
std::vector< std::string > CommandLineArguments
A sequence of command line arguments.
Interface to process a clang::CompilerInvocation.
Definition: Tooling.h:73
Implements support for file system lookup, file system caching, and directory search management...
Definition: FileManager.h:116
Defines the clang::FileManager interface and associated types.
ToolInvocation(std::vector< std::string > CommandLine, FrontendAction *FAction, FileManager *Files, std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >())
Create a tool invocation.
Definition: Tooling.cpp:268
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:29
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation&#39;s diagnostic options and replace any existing one ...
Abstract base class for actions which can be performed by the frontend.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1296
static bool CreateFromArgs(CompilerInvocation &Res, const char *const *ArgBegin, const char *const *ArgEnd, DiagnosticsEngine &Diags)
Create a compiler invocation from a list of input options.
static std::vector< std::string > getSyntaxOnlyToolArgs(const Twine &ToolName, const std::vector< std::string > &ExtraArgs, StringRef FileName)
Definition: Tooling.cpp:141
static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName)
Return any implicit target and/or mode flag for an invocation of the compiler driver as ProgName...
Definition: ToolChain.cpp:214
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1489
ArgumentsAdjuster getClangStripDependencyFileAdjuster()
Gets an argument adjuster which removes dependency-file related command line arguments.
static void injectResourceDir(CommandLineArguments &Args, const char *Argv0, void *MainAddr)
Definition: Tooling.cpp:404
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, ArgumentsAdjuster Second)
Gets an argument adjuster which adjusts the arguments in sequence with the First adjuster and then wi...
Interface to generate clang::FrontendActions.
Definition: Tooling.h:91
void createSourceManager(FileManager &FileMgr)
Create the source manager and replace any existing one with it.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Definition: Format.h:2222
void clearArgumentsAdjusters()
Clear the command line arguments adjuster chain.
Definition: Tooling.cpp:400
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
std::string Directory
The working directory the command was executed from.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:148
CompileCommand Cmd
Defines the Diagnostic-related interfaces.
std::unique_ptr< llvm::opt::OptTable > createDriverOptTable()
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:57
void setFileManager(FileManager *Value)
Replace the current file manager and virtual file system.
static driver::Driver * newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS)
Builds a clang driver initialized for running clang tools.
Definition: Tooling.cpp:77
bool run()
Run the clang invocation.
Definition: Tooling.cpp:286
ArgumentsAdjuster getClangStripOutputAdjuster()
Gets an argument adjuster which removes output-related command line arguments.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr)
Get the directory where the compiler headers reside, relative to the compiler binary (found by the pa...
std::string Filename
The source file associated with the command.
int buildASTs(std::vector< std::unique_ptr< ASTUnit >> &ASTs)
Create an AST for each file specified in the command line and append them to ASTs.
Definition: Tooling.cpp:563
std::string WorkingDir
If set, paths are resolved as if the working directory was set to the value of WorkingDir.
std::function< CommandLineArguments(const CommandLineArguments &, StringRef Filename)> ArgumentsAdjuster
A prototype of a command line adjuster.
std::string getAbsolutePath(StringRef File)
Returns the absolute path of File, by prepending it with the current directory if File is not absolut...
Definition: Tooling.cpp:216
JobList - A sequence of jobs to perform.
Definition: Job.h:171
bool runToolOnCodeWithArgs(FrontendAction *ToolAction, const Twine &Code, const std::vector< std::string > &Args, const Twine &FileName="input.cc", const Twine &ToolName="clang-tool", std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >(), const FileContentMappings &VirtualMappedFiles=FileContentMappings())
Runs (and deletes) the tool on &#39;Code&#39; with the -fsyntax-only flag and with additional other flags...
Definition: Tooling.cpp:174
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo=nullptr) const
Definition: Job.cpp:435
void addTargetAndModeForProgramName(std::vector< std::string > &CommandLine, StringRef InvokedAs)
Changes CommandLine to contain implicit flags that would have been defined had the compiler driver be...
Definition: Tooling.cpp:220
void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer)
Set a DiagnosticConsumer to use during parsing.
Definition: Tooling.h:264
Interface for compilation databases.
#define false
Definition: stdbool.h:17
static const llvm::opt::ArgStringList * getCC1Arguments(DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation)
Retrieves the clang CC1 specific flags out of the compilation&#39;s jobs.
Definition: Tooling.cpp:89
bool ExecuteAction(FrontendAction &Act)
ExecuteAction - Execute the provided action against the compiler&#39;s CompilerInvocation object...
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
FileSystemOptions & getFileSystemOpts()
Returns the current file system options.
Definition: FileManager.h:221
Specifies the working directory and command of a compilation.
Options for controlling the compiler diagnostics engine.
std::unique_ptr< ASTUnit > buildASTFromCodeWithArgs(StringRef Code, const std::vector< std::string > &Args, StringRef FileName="input.cc", StringRef ToolName="clang-tool", std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >(), ArgumentsAdjuster Adjuster=getClangStripDependencyFileAdjuster())
Builds an AST for &#39;Code&#39; with additional flags.
Definition: Tooling.cpp:582
iterator begin()
Definition: Job.h:195
void setTitle(std::string Value)
Definition: Driver.h:311
int run(ToolAction *Action)
Runs an action over all files specified in the command line.
Definition: Tooling.cpp:416
void mapVirtualFile(StringRef FilePath, StringRef Content)
Map a virtual file to be used while running the tool.
Definition: Tooling.cpp:392
std::unique_ptr< ASTUnit > buildASTFromCode(StringRef Code, StringRef FileName="input.cc", std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >())
Builds an AST for &#39;Code&#39;.
Definition: Tooling.cpp:576
Utility to run a FrontendAction in a single clang invocation.
Definition: Tooling.h:232
Dataflow Directional Tag Classes.
void clearStatCache()
Removes the FileSystemStatCache object from the manager.
Definition: FileManager.cpp:62
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
Used for handling and querying diagnostic IDs.
Helper class for holding the data necessary to invoke the compiler.
CompilerInvocation * newInvocation(DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args)
Creates a CompilerInvocation.
Definition: Tooling.cpp:117
size_type size() const
Definition: Job.h:194
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
Defines the clang::FileSystemOptions interface.
std::vector< std::string > CommandLine
The command line that was executed.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster()
Gets an argument adjuster that converts input command line arguments to the "syntax check only" varia...
Keeps track of options that affect how file operations are performed.
void setInvocation(std::shared_ptr< CompilerInvocation > Value)
setInvocation - Replace the current invocation.
bool runInvocation(std::shared_ptr< CompilerInvocation > Invocation, FileManager *Files, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagConsumer) override
Invokes the compiler with a FrontendAction created by create().
Definition: Tooling.cpp:348
void setRestoreWorkingDir(bool RestoreCWD)
Sets whether working directory should be restored after calling run().
Definition: Tooling.cpp:568
Defines the Diagnostic IDs-related interfaces.
void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster)
Append a command line arguments adjuster to the adjuster chain.
Definition: Tooling.cpp:396
ClangTool(const CompilationDatabase &Compilations, ArrayRef< std::string > SourcePaths, std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >(), IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS=llvm::vfs::getRealFileSystem())
Constructs a clang tool to run over a list of files.
Definition: Tooling.cpp:375
#define true
Definition: stdbool.h:16
void mapVirtualFile(StringRef FilePath, StringRef Content)
Map a virtual file to be used while running the tool.
Definition: Tooling.cpp:280
bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code, const Twine &FileName="input.cc", std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >())
Runs (and deletes) the tool on &#39;Code&#39; with the -fsyntax-only flag.
Definition: Tooling.cpp:129
llvm::vfs::FileSystem & getVirtualFileSystem() const
Definition: FileManager.h:224
virtual bool runInvocation(std::shared_ptr< CompilerInvocation > Invocation, FileManager *Files, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagConsumer)=0
Perform an action for an invocation.
std::vector< std::pair< std::string, std::string > > FileContentMappings
The first part of the pair is the filename, the second part the file-content.
Definition: Tooling.h:166
virtual std::vector< CompileCommand > getCompileCommands(StringRef FilePath) const =0
Returns all compile commands in which the specified file was compiled.