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"
24 #include "clang/Driver/Driver.h"
25 #include "clang/Driver/Job.h"
26 #include "clang/Driver/Options.h"
27 #include "clang/Driver/Tool.h"
28 #include "clang/Driver/ToolChain.h"
29 #include "clang/Frontend/ASTUnit.h"
39 #include "llvm/ADT/ArrayRef.h"
40 #include "llvm/ADT/IntrusiveRefCntPtr.h"
41 #include "llvm/ADT/SmallString.h"
42 #include "llvm/ADT/StringRef.h"
43 #include "llvm/ADT/Twine.h"
44 #include "llvm/Option/ArgList.h"
45 #include "llvm/Option/OptTable.h"
46 #include "llvm/Option/Option.h"
47 #include "llvm/Support/Casting.h"
48 #include "llvm/Support/Debug.h"
49 #include "llvm/Support/ErrorHandling.h"
50 #include "llvm/Support/FileSystem.h"
51 #include "llvm/Support/Host.h"
52 #include "llvm/Support/MemoryBuffer.h"
53 #include "llvm/Support/Path.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.
78  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) {
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(*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  // Since the input might only be virtual, don't check whether it exists.
307  Driver->setCheckInputsExist(false);
308  const std::unique_ptr<driver::Compilation> Compilation(
309  Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
310  if (!Compilation)
311  return false;
312  const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
313  &Diagnostics, Compilation.get());
314  if (!CC1Args)
315  return false;
316  std::unique_ptr<CompilerInvocation> Invocation(
317  newInvocation(&Diagnostics, *CC1Args));
318  // FIXME: remove this when all users have migrated!
319  for (const auto &It : MappedFileContents) {
320  // Inject the code as the given file name into the preprocessor options.
321  std::unique_ptr<llvm::MemoryBuffer> Input =
322  llvm::MemoryBuffer::getMemBuffer(It.getValue());
323  Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(),
324  Input.release());
325  }
326  return runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
327  std::move(PCHContainerOps));
328 }
329 
330 bool ToolInvocation::runInvocation(
331  const char *BinaryName, driver::Compilation *Compilation,
332  std::shared_ptr<CompilerInvocation> Invocation,
333  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
334  // Show the invocation, with -v.
335  if (Invocation->getHeaderSearchOpts().Verbose) {
336  llvm::errs() << "clang Invocation:\n";
337  Compilation->getJobs().Print(llvm::errs(), "\n", true);
338  llvm::errs() << "\n";
339  }
340 
341  return Action->runInvocation(std::move(Invocation), Files,
342  std::move(PCHContainerOps), DiagConsumer);
343 }
344 
346  std::shared_ptr<CompilerInvocation> Invocation, FileManager *Files,
347  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
348  DiagnosticConsumer *DiagConsumer) {
349  // Create a compiler instance to handle the actual work.
350  CompilerInstance Compiler(std::move(PCHContainerOps));
351  Compiler.setInvocation(std::move(Invocation));
352  Compiler.setFileManager(Files);
353 
354  // The FrontendAction can have lifetime requirements for Compiler or its
355  // members, and we need to ensure it's deleted earlier than Compiler. So we
356  // pass it to an std::unique_ptr declared after the Compiler variable.
357  std::unique_ptr<FrontendAction> ScopedToolAction(create());
358 
359  // Create the compiler's actual diagnostics engine.
360  Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
361  if (!Compiler.hasDiagnostics())
362  return false;
363 
364  Compiler.createSourceManager(*Files);
365 
366  const bool Success = Compiler.ExecuteAction(*ScopedToolAction);
367 
368  Files->clearStatCaches();
369  return Success;
370 }
371 
373  ArrayRef<std::string> SourcePaths,
374  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
376  : Compilations(Compilations), SourcePaths(SourcePaths),
377  PCHContainerOps(std::move(PCHContainerOps)),
378  OverlayFileSystem(new vfs::OverlayFileSystem(std::move(BaseFS))),
379  InMemoryFileSystem(new vfs::InMemoryFileSystem),
380  Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) {
381  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
385 }
386 
387 ClangTool::~ClangTool() = default;
388 
389 void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
390  MappedFileContents.push_back(std::make_pair(FilePath, Content));
391 }
392 
394  ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
395 }
396 
398  ArgsAdjuster = nullptr;
399 }
400 
401 static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
402  void *MainAddr) {
403  // Allow users to override the resource dir.
404  for (StringRef Arg : Args)
405  if (Arg.startswith("-resource-dir"))
406  return;
407 
408  // If there's no override in place add our resource dir.
409  Args.push_back("-resource-dir=" +
410  CompilerInvocation::GetResourcesPath(Argv0, MainAddr));
411 }
412 
414  // Exists solely for the purpose of lookup of the resource path.
415  // This just needs to be some symbol in the binary.
416  static int StaticSymbol;
417 
418  // First insert all absolute paths into the in-memory VFS. These are global
419  // for all compile commands.
420  if (SeenWorkingDirectories.insert("/").second)
421  for (const auto &MappedFile : MappedFileContents)
422  if (llvm::sys::path::is_absolute(MappedFile.first))
423  InMemoryFileSystem->addFile(
424  MappedFile.first, 0,
425  llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
426 
427  bool ProcessingFailed = false;
428  bool FileSkipped = false;
429  // Compute all absolute paths before we run any actions, as those will change
430  // the working directory.
431  std::vector<std::string> AbsolutePaths;
432  AbsolutePaths.reserve(SourcePaths.size());
433  for (const auto &SourcePath : SourcePaths) {
434  auto AbsPath = getAbsolutePath(*OverlayFileSystem, SourcePath);
435  if (!AbsPath) {
436  llvm::errs() << "Skipping " << SourcePath
437  << ". Error while getting an absolute path: "
438  << llvm::toString(AbsPath.takeError()) << "\n";
439  continue;
440  }
441  AbsolutePaths.push_back(std::move(*AbsPath));
442  }
443 
444  // Remember the working directory in case we need to restore it.
445  std::string InitialWorkingDir;
446  if (RestoreCWD) {
447  if (auto CWD = OverlayFileSystem->getCurrentWorkingDirectory()) {
448  InitialWorkingDir = std::move(*CWD);
449  } else {
450  llvm::errs() << "Could not get working directory: "
451  << CWD.getError().message() << "\n";
452  }
453  }
454 
455  for (llvm::StringRef File : AbsolutePaths) {
456  // Currently implementations of CompilationDatabase::getCompileCommands can
457  // change the state of the file system (e.g. prepare generated headers), so
458  // this method needs to run right before we invoke the tool, as the next
459  // file may require a different (incompatible) state of the file system.
460  //
461  // FIXME: Make the compilation database interface more explicit about the
462  // requirements to the order of invocation of its members.
463  std::vector<CompileCommand> CompileCommandsForFile =
464  Compilations.getCompileCommands(File);
465  if (CompileCommandsForFile.empty()) {
466  llvm::errs() << "Skipping " << File << ". Compile command not found.\n";
467  FileSkipped = true;
468  continue;
469  }
470  for (CompileCommand &CompileCommand : CompileCommandsForFile) {
471  // FIXME: chdir is thread hostile; on the other hand, creating the same
472  // behavior as chdir is complex: chdir resolves the path once, thus
473  // guaranteeing that all subsequent relative path operations work
474  // on the same path the original chdir resulted in. This makes a
475  // difference for example on network filesystems, where symlinks might be
476  // switched during runtime of the tool. Fixing this depends on having a
477  // file system abstraction that allows openat() style interactions.
478  if (OverlayFileSystem->setCurrentWorkingDirectory(
480  llvm::report_fatal_error("Cannot chdir into \"" +
481  Twine(CompileCommand.Directory) + "\n!");
482 
483  // Now fill the in-memory VFS with the relative file mappings so it will
484  // have the correct relative paths. We never remove mappings but that
485  // should be fine.
486  if (SeenWorkingDirectories.insert(CompileCommand.Directory).second)
487  for (const auto &MappedFile : MappedFileContents)
488  if (!llvm::sys::path::is_absolute(MappedFile.first))
489  InMemoryFileSystem->addFile(
490  MappedFile.first, 0,
491  llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
492 
493  std::vector<std::string> CommandLine = CompileCommand.CommandLine;
494  if (ArgsAdjuster)
495  CommandLine = ArgsAdjuster(CommandLine, CompileCommand.Filename);
496  assert(!CommandLine.empty());
497 
498  // Add the resource dir based on the binary of this tool. argv[0] in the
499  // compilation database may refer to a different compiler and we want to
500  // pick up the very same standard library that compiler is using. The
501  // builtin headers in the resource dir need to match the exact clang
502  // version the tool is using.
503  // FIXME: On linux, GetMainExecutable is independent of the value of the
504  // first argument, thus allowing ClangTool and runToolOnCode to just
505  // pass in made-up names here. Make sure this works on other platforms.
506  injectResourceDir(CommandLine, "clang_tool", &StaticSymbol);
507 
508  // FIXME: We need a callback mechanism for the tool writer to output a
509  // customized message for each file.
510  LLVM_DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; });
511  ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
512  PCHContainerOps);
513  Invocation.setDiagnosticConsumer(DiagConsumer);
514 
515  if (!Invocation.run()) {
516  // FIXME: Diagnostics should be used instead.
517  llvm::errs() << "Error while processing " << File << ".\n";
518  ProcessingFailed = true;
519  }
520  }
521  }
522 
523  if (!InitialWorkingDir.empty()) {
524  if (auto EC =
525  OverlayFileSystem->setCurrentWorkingDirectory(InitialWorkingDir))
526  llvm::errs() << "Error when trying to restore working dir: "
527  << EC.message() << "\n";
528  }
529  return ProcessingFailed ? 1 : (FileSkipped ? 2 : 0);
530 }
531 
532 namespace {
533 
534 class ASTBuilderAction : public ToolAction {
535  std::vector<std::unique_ptr<ASTUnit>> &ASTs;
536 
537 public:
538  ASTBuilderAction(std::vector<std::unique_ptr<ASTUnit>> &ASTs) : ASTs(ASTs) {}
539 
540  bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
541  FileManager *Files,
542  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
543  DiagnosticConsumer *DiagConsumer) override {
544  std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
545  Invocation, std::move(PCHContainerOps),
546  CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(),
547  DiagConsumer,
548  /*ShouldOwnClient=*/false),
549  Files);
550  if (!AST)
551  return false;
552 
553  ASTs.push_back(std::move(AST));
554  return true;
555  }
556 };
557 
558 } // namespace
559 
560 int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
561  ASTBuilderAction Action(ASTs);
562  return run(&Action);
563 }
564 
565 void ClangTool::setRestoreWorkingDir(bool RestoreCWD) {
566  this->RestoreCWD = RestoreCWD;
567 }
568 
569 namespace clang {
570 namespace tooling {
571 
572 std::unique_ptr<ASTUnit>
573 buildASTFromCode(const Twine &Code, const Twine &FileName,
574  std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
575  return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
576  "clang-tool", std::move(PCHContainerOps));
577 }
578 
579 std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
580  const Twine &Code, const std::vector<std::string> &Args,
581  const Twine &FileName, const Twine &ToolName,
582  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
583  ArgumentsAdjuster Adjuster) {
584  SmallString<16> FileNameStorage;
585  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
586 
587  std::vector<std::unique_ptr<ASTUnit>> ASTs;
588  ASTBuilderAction Action(ASTs);
593  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
595  new FileManager(FileSystemOptions(), OverlayFileSystem));
596 
597  ToolInvocation Invocation(
598  getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
599  &Action, Files.get(), std::move(PCHContainerOps));
600 
601  SmallString<1024> CodeStorage;
602  InMemoryFileSystem->addFile(FileNameRef, 0,
603  llvm::MemoryBuffer::getMemBuffer(
604  Code.toNullTerminatedStringRef(CodeStorage)));
605  if (!Invocation.run())
606  return nullptr;
607 
608  assert(ASTs.size() == 1);
609  return std::move(ASTs[0]);
610 }
611 
612 } // namespace tooling
613 } // 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: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:269
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation&#39;s diagnostic options and replace any existing one ...
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the &#39;real&#39; file system, as seen by the operating system.
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:1294
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:202
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1487
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:401
The virtual file system interface.
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.
Definition: Format.h:2031
void clearArgumentsAdjusters()
Clear the command line arguments adjuster chain.
Definition: Tooling.cpp:397
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
An in-memory file system.
A file system that allows overlaying one AbstractFileSystem on top of another.
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:59
void setFileManager(FileManager *Value)
Replace the current file manager and virtual file system.
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:560
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:167
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:431
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.
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:579
void clearStatCaches()
Removes all FileSystemStatCache objects from the manager.
std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
iterator begin()
Definition: Job.h:191
static driver::Driver * newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName, IntrusiveRefCntPtr< vfs::FileSystem > VFS)
Builds a clang driver initialized for running clang tools.
Definition: Tooling.cpp:77
void setTitle(std::string Value)
Definition: Driver.h:310
int run(ToolAction *Action)
Runs an action over all files specified in the command line.
Definition: Tooling.cpp:413
void mapVirtualFile(StringRef FilePath, StringRef Content)
Map a virtual file to be used while running the tool.
Definition: Tooling.cpp:389
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.
Defines the virtual file system interface vfs::FileSystem.
CompilerInvocation * newInvocation(DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args)
Creates a CompilerInvocation.
Definition: Tooling.cpp:118
size_type size() const
Definition: Job.h:190
std::string toString(const til::SExpr *E)
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:573
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:345
IntrusiveRefCntPtr< vfs::FileSystem > getVirtualFileSystem() const
Definition: FileManager.h:225
void setRestoreWorkingDir(bool RestoreCWD)
Sets whether working directory should be restored after calling run().
Definition: Tooling.cpp:565
Defines the Diagnostic IDs-related interfaces.
ClangTool(const CompilationDatabase &Compilations, ArrayRef< std::string > SourcePaths, std::shared_ptr< PCHContainerOperations > PCHContainerOps=std::make_shared< PCHContainerOperations >(), IntrusiveRefCntPtr< vfs::FileSystem > BaseFS=vfs::getRealFileSystem())
Constructs a clang tool to run over a list of files.
Definition: Tooling.cpp:372
void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster)
Append a command line arguments adjuster to the adjuster chain.
Definition: Tooling.cpp:393
#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
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.