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