clang  10.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;
121  CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, *Diagnostics);
122  Invocation->getFrontendOpts().DisableFree = false;
123  Invocation->getCodeGenOpts().DisableFree = false;
124  return Invocation;
125 }
126 
127 bool runToolOnCode(std::unique_ptr<FrontendAction> ToolAction,
128  const Twine &Code, const Twine &FileName,
129  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
130  return runToolOnCodeWithArgs(std::move(ToolAction), Code,
131  std::vector<std::string>(), FileName,
132  "clang-tool", std::move(PCHContainerOps));
133 }
134 
135 } // namespace tooling
136 } // namespace clang
137 
138 static std::vector<std::string>
139 getSyntaxOnlyToolArgs(const Twine &ToolName,
140  const std::vector<std::string> &ExtraArgs,
141  StringRef FileName) {
142  std::vector<std::string> Args;
143  Args.push_back(ToolName.str());
144  Args.push_back("-fsyntax-only");
145  Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
146  Args.push_back(FileName.str());
147  return Args;
148 }
149 
150 namespace clang {
151 namespace tooling {
152 
154  std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
156  const std::vector<std::string> &Args, const Twine &FileName,
157  const Twine &ToolName,
158  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
159  SmallString<16> FileNameStorage;
160  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
161 
163  new FileManager(FileSystemOptions(), VFS));
165  ToolInvocation Invocation(
166  getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
167  std::move(ToolAction), Files.get(), std::move(PCHContainerOps));
168  return Invocation.run();
169 }
170 
172  std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
173  const std::vector<std::string> &Args, const Twine &FileName,
174  const Twine &ToolName,
175  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
176  const FileContentMappings &VirtualMappedFiles) {
178  new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
180  new llvm::vfs::InMemoryFileSystem);
181  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
182 
183  SmallString<1024> CodeStorage;
184  InMemoryFileSystem->addFile(FileName, 0,
185  llvm::MemoryBuffer::getMemBuffer(
186  Code.toNullTerminatedStringRef(CodeStorage)));
187 
188  for (auto &FilenameWithContent : VirtualMappedFiles) {
189  InMemoryFileSystem->addFile(
190  FilenameWithContent.first, 0,
191  llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second));
192  }
193 
194  return runToolOnCodeWithArgs(std::move(ToolAction), Code, OverlayFileSystem,
195  Args, FileName, ToolName);
196 }
197 
199  StringRef File) {
200  StringRef RelativePath(File);
201  // FIXME: Should '.\\' be accepted on Win32?
202  if (RelativePath.startswith("./")) {
203  RelativePath = RelativePath.substr(strlen("./"));
204  }
205 
206  SmallString<1024> AbsolutePath = RelativePath;
207  if (auto EC = FS.makeAbsolute(AbsolutePath))
208  return llvm::errorCodeToError(EC);
209  llvm::sys::path::native(AbsolutePath);
210  return AbsolutePath.str();
211 }
212 
213 std::string getAbsolutePath(StringRef File) {
214  return llvm::cantFail(getAbsolutePath(*llvm::vfs::getRealFileSystem(), File));
215 }
216 
217 void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
218  StringRef InvokedAs) {
219  if (!CommandLine.empty() && !InvokedAs.empty()) {
220  bool AlreadyHasTarget = false;
221  bool AlreadyHasMode = false;
222  // Skip CommandLine[0].
223  for (auto Token = ++CommandLine.begin(); Token != CommandLine.end();
224  ++Token) {
225  StringRef TokenRef(*Token);
226  AlreadyHasTarget |=
227  (TokenRef == "-target" || TokenRef.startswith("-target="));
228  AlreadyHasMode |= (TokenRef == "--driver-mode" ||
229  TokenRef.startswith("--driver-mode="));
230  }
231  auto TargetMode =
233  if (!AlreadyHasMode && TargetMode.DriverMode) {
234  CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
235  }
236  if (!AlreadyHasTarget && TargetMode.TargetIsValid) {
237  CommandLine.insert(++CommandLine.begin(), {"-target",
238  TargetMode.TargetPrefix});
239  }
240  }
241 }
242 
243 } // namespace tooling
244 } // namespace clang
245 
246 namespace {
247 
248 class SingleFrontendActionFactory : public FrontendActionFactory {
249  std::unique_ptr<FrontendAction> Action;
250 
251 public:
252  SingleFrontendActionFactory(std::unique_ptr<FrontendAction> Action)
253  : Action(std::move(Action)) {}
254 
255  std::unique_ptr<FrontendAction> create() override {
256  return std::move(Action);
257  }
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,
270  std::unique_ptr<FrontendAction> FAction, FileManager *Files,
271  std::shared_ptr<PCHContainerOperations> PCHContainerOps)
272  : CommandLine(std::move(CommandLine)),
273  Action(new SingleFrontendActionFactory(std::move(FAction))),
274  OwnsAction(true), Files(Files),
275  PCHContainerOps(std::move(PCHContainerOps)) {}
276 
278  if (OwnsAction)
279  delete Action;
280 }
281 
282 void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
283  SmallString<1024> PathStorage;
284  llvm::sys::path::native(FilePath, PathStorage);
285  MappedFileContents[PathStorage] = Content;
286 }
287 
289  std::vector<const char*> Argv;
290  for (const std::string &Str : CommandLine)
291  Argv.push_back(Str.c_str());
292  const char *const BinaryName = Argv[0];
294  unsigned MissingArgIndex, MissingArgCount;
295  llvm::opt::InputArgList ParsedArgs = driver::getDriverOptTable().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->clearStatCache();
373  return Success;
374 }
375 
377  ArrayRef<std::string> SourcePaths,
378  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
381  : Compilations(Compilations), SourcePaths(SourcePaths),
382  PCHContainerOps(std::move(PCHContainerOps)),
383  OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))),
384  InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
385  Files(Files ? Files
386  : new FileManager(FileSystemOptions(), OverlayFileSystem)) {
387  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
391  if (Files)
392  Files->setVirtualFileSystem(OverlayFileSystem);
393 }
394 
395 ClangTool::~ClangTool() = default;
396 
397 void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
398  MappedFileContents.push_back(std::make_pair(FilePath, Content));
399 }
400 
402  ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
403 }
404 
406  ArgsAdjuster = nullptr;
407 }
408 
409 static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
410  void *MainAddr) {
411  // Allow users to override the resource dir.
412  for (StringRef Arg : Args)
413  if (Arg.startswith("-resource-dir"))
414  return;
415 
416  // If there's no override in place add our resource dir.
417  Args.push_back("-resource-dir=" +
418  CompilerInvocation::GetResourcesPath(Argv0, MainAddr));
419 }
420 
422  // Exists solely for the purpose of lookup of the resource path.
423  // This just needs to be some symbol in the binary.
424  static int StaticSymbol;
425 
426  // First insert all absolute paths into the in-memory VFS. These are global
427  // for all compile commands.
428  if (SeenWorkingDirectories.insert("/").second)
429  for (const auto &MappedFile : MappedFileContents)
430  if (llvm::sys::path::is_absolute(MappedFile.first))
431  InMemoryFileSystem->addFile(
432  MappedFile.first, 0,
433  llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
434 
435  bool ProcessingFailed = false;
436  bool FileSkipped = false;
437  // Compute all absolute paths before we run any actions, as those will change
438  // the working directory.
439  std::vector<std::string> AbsolutePaths;
440  AbsolutePaths.reserve(SourcePaths.size());
441  for (const auto &SourcePath : SourcePaths) {
442  auto AbsPath = getAbsolutePath(*OverlayFileSystem, SourcePath);
443  if (!AbsPath) {
444  llvm::errs() << "Skipping " << SourcePath
445  << ". Error while getting an absolute path: "
446  << llvm::toString(AbsPath.takeError()) << "\n";
447  continue;
448  }
449  AbsolutePaths.push_back(std::move(*AbsPath));
450  }
451 
452  // Remember the working directory in case we need to restore it.
453  std::string InitialWorkingDir;
454  if (RestoreCWD) {
455  if (auto CWD = OverlayFileSystem->getCurrentWorkingDirectory()) {
456  InitialWorkingDir = std::move(*CWD);
457  } else {
458  llvm::errs() << "Could not get working directory: "
459  << CWD.getError().message() << "\n";
460  }
461  }
462 
463  for (llvm::StringRef File : AbsolutePaths) {
464  // Currently implementations of CompilationDatabase::getCompileCommands can
465  // change the state of the file system (e.g. prepare generated headers), so
466  // this method needs to run right before we invoke the tool, as the next
467  // file may require a different (incompatible) state of the file system.
468  //
469  // FIXME: Make the compilation database interface more explicit about the
470  // requirements to the order of invocation of its members.
471  std::vector<CompileCommand> CompileCommandsForFile =
472  Compilations.getCompileCommands(File);
473  if (CompileCommandsForFile.empty()) {
474  llvm::errs() << "Skipping " << File << ". Compile command not found.\n";
475  FileSkipped = true;
476  continue;
477  }
478  for (CompileCommand &CompileCommand : CompileCommandsForFile) {
479  // FIXME: chdir is thread hostile; on the other hand, creating the same
480  // behavior as chdir is complex: chdir resolves the path once, thus
481  // guaranteeing that all subsequent relative path operations work
482  // on the same path the original chdir resulted in. This makes a
483  // difference for example on network filesystems, where symlinks might be
484  // switched during runtime of the tool. Fixing this depends on having a
485  // file system abstraction that allows openat() style interactions.
486  if (OverlayFileSystem->setCurrentWorkingDirectory(
488  llvm::report_fatal_error("Cannot chdir into \"" +
489  Twine(CompileCommand.Directory) + "\"!");
490 
491  // Now fill the in-memory VFS with the relative file mappings so it will
492  // have the correct relative paths. We never remove mappings but that
493  // should be fine.
494  if (SeenWorkingDirectories.insert(CompileCommand.Directory).second)
495  for (const auto &MappedFile : MappedFileContents)
496  if (!llvm::sys::path::is_absolute(MappedFile.first))
497  InMemoryFileSystem->addFile(
498  MappedFile.first, 0,
499  llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
500 
501  std::vector<std::string> CommandLine = CompileCommand.CommandLine;
502  if (ArgsAdjuster)
503  CommandLine = ArgsAdjuster(CommandLine, CompileCommand.Filename);
504  assert(!CommandLine.empty());
505 
506  // Add the resource dir based on the binary of this tool. argv[0] in the
507  // compilation database may refer to a different compiler and we want to
508  // pick up the very same standard library that compiler is using. The
509  // builtin headers in the resource dir need to match the exact clang
510  // version the tool is using.
511  // FIXME: On linux, GetMainExecutable is independent of the value of the
512  // first argument, thus allowing ClangTool and runToolOnCode to just
513  // pass in made-up names here. Make sure this works on other platforms.
514  injectResourceDir(CommandLine, "clang_tool", &StaticSymbol);
515 
516  // FIXME: We need a callback mechanism for the tool writer to output a
517  // customized message for each file.
518  LLVM_DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; });
519  ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
520  PCHContainerOps);
521  Invocation.setDiagnosticConsumer(DiagConsumer);
522 
523  if (!Invocation.run()) {
524  // FIXME: Diagnostics should be used instead.
525  if (PrintErrorMessage)
526  llvm::errs() << "Error while processing " << File << ".\n";
527  ProcessingFailed = true;
528  }
529  }
530  }
531 
532  if (!InitialWorkingDir.empty()) {
533  if (auto EC =
534  OverlayFileSystem->setCurrentWorkingDirectory(InitialWorkingDir))
535  llvm::errs() << "Error when trying to restore working dir: "
536  << EC.message() << "\n";
537  }
538  return ProcessingFailed ? 1 : (FileSkipped ? 2 : 0);
539 }
540 
541 namespace {
542 
543 class ASTBuilderAction : public ToolAction {
544  std::vector<std::unique_ptr<ASTUnit>> &ASTs;
545 
546 public:
547  ASTBuilderAction(std::vector<std::unique_ptr<ASTUnit>> &ASTs) : ASTs(ASTs) {}
548 
549  bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
550  FileManager *Files,
551  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
552  DiagnosticConsumer *DiagConsumer) override {
553  std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
554  Invocation, std::move(PCHContainerOps),
555  CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(),
556  DiagConsumer,
557  /*ShouldOwnClient=*/false),
558  Files);
559  if (!AST)
560  return false;
561 
562  ASTs.push_back(std::move(AST));
563  return true;
564  }
565 };
566 
567 } // namespace
568 
569 int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
570  ASTBuilderAction Action(ASTs);
571  return run(&Action);
572 }
573 
574 void ClangTool::setRestoreWorkingDir(bool RestoreCWD) {
575  this->RestoreCWD = RestoreCWD;
576 }
577 
578 void ClangTool::setPrintErrorMessage(bool PrintErrorMessage) {
579  this->PrintErrorMessage = PrintErrorMessage;
580 }
581 
582 namespace clang {
583 namespace tooling {
584 
585 std::unique_ptr<ASTUnit>
586 buildASTFromCode(StringRef Code, StringRef FileName,
587  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
588  return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
589  "clang-tool", std::move(PCHContainerOps));
590 }
591 
592 std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
593  StringRef Code, const std::vector<std::string> &Args, StringRef FileName,
594  StringRef ToolName, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
595  ArgumentsAdjuster Adjuster) {
596  std::vector<std::unique_ptr<ASTUnit>> ASTs;
597  ASTBuilderAction Action(ASTs);
599  new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
601  new llvm::vfs::InMemoryFileSystem);
602  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
604  new FileManager(FileSystemOptions(), OverlayFileSystem));
605 
606  ToolInvocation Invocation(
607  getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName),
608  &Action, Files.get(), std::move(PCHContainerOps));
609 
610  InMemoryFileSystem->addFile(FileName, 0,
611  llvm::MemoryBuffer::getMemBufferCopy(Code));
612  if (!Invocation.run())
613  return nullptr;
614 
615  assert(ASTs.size() == 1);
616  return std::move(ASTs[0]);
617 }
618 
619 } // namespace tooling
620 } // 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:171
Defines the clang::FileManager interface and associated types.
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
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 ...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1290
static std::vector< std::string > getSyntaxOnlyToolArgs(const Twine &ToolName, const std::vector< std::string > &ExtraArgs, StringRef FileName)
Definition: Tooling.cpp:139
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:203
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:409
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:2327
void clearArgumentsAdjusters()
Clear the command line arguments adjuster chain.
Definition: Tooling.cpp:405
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
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(), IntrusiveRefCntPtr< FileManager > Files=nullptr)
Constructs a clang tool to run over a list of files.
Definition: Tooling.cpp:376
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.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:59
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
void setPrintErrorMessage(bool PrintErrorMessage)
Sets whether an error message should be printed out if an action fails.
Definition: Tooling.cpp:578
bool run()
Run the clang invocation.
Definition: Tooling.cpp:288
const llvm::opt::OptTable & getDriverOptTable()
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:569
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:213
JobList - A sequence of jobs to perform.
Definition: Job.h:171
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo=nullptr) const
Definition: Job.cpp:435
ToolInvocation(std::vector< std::string > CommandLine, std::unique_ptr< FrontendAction > FAction, FileManager *Files, std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >())
Create a tool invocation.
Definition: Tooling.cpp:268
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:217
void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer)
Set a DiagnosticConsumer to use during parsing.
Definition: Tooling.h:262
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:356
Specifies the working directory and command of a compilation.
Options for controlling the compiler diagnostics engine.
bool runToolOnCode(std::unique_ptr< 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:127
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:592
iterator begin()
Definition: Job.h:195
bool runToolOnCodeWithArgs(std::unique_ptr< 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:171
void setTitle(std::string Value)
Definition: Driver.h:316
int run(ToolAction *Action)
Runs an action over all files specified in the command line.
Definition: Tooling.cpp:421
void mapVirtualFile(StringRef FilePath, StringRef Content)
Map a virtual file to be used while running the tool.
Definition: Tooling.cpp:397
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:586
Utility to run a FrontendAction in a single clang invocation.
Definition: Tooling.h:230
Dataflow Directional Tag Classes.
void clearStatCache()
Removes the FileSystemStatCache object from the manager.
Definition: FileManager.cpp:62
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char *> CommandLineArgs, DiagnosticsEngine &Diags)
Create a compiler invocation from a list of input options.
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:349
void setRestoreWorkingDir(bool RestoreCWD)
Sets whether working directory should be restored after calling run().
Definition: Tooling.cpp:574
Defines the Diagnostic IDs-related interfaces.
void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster)
Append a command line arguments adjuster to the adjuster chain.
Definition: Tooling.cpp:401
#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:282
llvm::vfs::FileSystem & getVirtualFileSystem() const
Definition: FileManager.h:359
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:164
virtual std::vector< CompileCommand > getCompileCommands(StringRef FilePath) const =0
Returns all compile commands in which the specified file was compiled.