Clang Project

clang_source_code/include/clang/Tooling/Tooling.h
1//===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===//
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//  A ClangTool is initialized with a CompilationDatabase and a set of files
13//  to run over. The tool will then run a user-specified FrontendAction over
14//  all TUs in which the given files are compiled.
15//
16//  It is also possible to run a FrontendAction over a snippet of code by
17//  calling runToolOnCode, which is useful for unit testing.
18//
19//  Applications that need more fine grained control over how to run
20//  multiple FrontendActions over code can use ToolInvocation.
21//
22//  Example tools:
23//  - running clang -fsyntax-only over source code from an editor to get
24//    fast syntax checks
25//  - running match/replace tools over C++ code
26//
27//===----------------------------------------------------------------------===//
28
29#ifndef LLVM_CLANG_TOOLING_TOOLING_H
30#define LLVM_CLANG_TOOLING_TOOLING_H
31
32#include "clang/AST/ASTConsumer.h"
33#include "clang/Basic/FileManager.h"
34#include "clang/Basic/LLVM.h"
35#include "clang/Frontend/FrontendAction.h"
36#include "clang/Frontend/PCHContainerOperations.h"
37#include "clang/Tooling/ArgumentsAdjusters.h"
38#include "llvm/ADT/ArrayRef.h"
39#include "llvm/ADT/IntrusiveRefCntPtr.h"
40#include "llvm/ADT/StringMap.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/ADT/StringSet.h"
43#include "llvm/ADT/Twine.h"
44#include "llvm/Option/Option.h"
45#include "llvm/Support/VirtualFileSystem.h"
46#include <memory>
47#include <string>
48#include <utility>
49#include <vector>
50
51namespace clang {
52
53class CompilerInstance;
54class CompilerInvocation;
55class DiagnosticConsumer;
56class DiagnosticsEngine;
57class SourceManager;
58
59namespace driver {
60
61class Compilation;
62
63// namespace driver
64
65namespace tooling {
66
67class CompilationDatabase;
68
69/// Interface to process a clang::CompilerInvocation.
70///
71/// If your tool is based on FrontendAction, you should be deriving from
72/// FrontendActionFactory instead.
73class ToolAction {
74public:
75  virtual ~ToolAction();
76
77  /// Perform an action for an invocation.
78  virtual bool
79  runInvocation(std::shared_ptr<CompilerInvocationInvocation,
80                FileManager *Files,
81                std::shared_ptr<PCHContainerOperationsPCHContainerOps,
82                DiagnosticConsumer *DiagConsumer) = 0;
83};
84
85/// Interface to generate clang::FrontendActions.
86///
87/// Having a factory interface allows, for example, a new FrontendAction to be
88/// created for each translation unit processed by ClangTool.  This class is
89/// also a ToolAction which uses the FrontendActions created by create() to
90/// process each translation unit.
91class FrontendActionFactory : public ToolAction {
92public:
93  ~FrontendActionFactory() override;
94
95  /// Invokes the compiler with a FrontendAction created by create().
96  bool runInvocation(std::shared_ptr<CompilerInvocationInvocation,
97                     FileManager *Files,
98                     std::shared_ptr<PCHContainerOperationsPCHContainerOps,
99                     DiagnosticConsumer *DiagConsumer) override;
100
101  /// Returns a new clang::FrontendAction.
102  ///
103  /// The caller takes ownership of the returned action.
104  virtual FrontendAction *create() = 0;
105};
106
107/// Returns a new FrontendActionFactory for a given type.
108///
109/// T must derive from clang::FrontendAction.
110///
111/// Example:
112/// FrontendActionFactory *Factory =
113///   newFrontendActionFactory<clang::SyntaxOnlyAction>();
114template <typename T>
115std::unique_ptr<FrontendActionFactorynewFrontendActionFactory();
116
117/// Callbacks called before and after each source file processed by a
118/// FrontendAction created by the FrontedActionFactory returned by \c
119/// newFrontendActionFactory.
120class SourceFileCallbacks {
121public:
122  virtual ~SourceFileCallbacks() = default;
123
124  /// Called before a source file is processed by a FrontEndAction.
125  /// \see clang::FrontendAction::BeginSourceFileAction
126  virtual bool handleBeginSource(CompilerInstance &CI) {
127    return true;
128  }
129
130  /// Called after a source file is processed by a FrontendAction.
131  /// \see clang::FrontendAction::EndSourceFileAction
132  virtual void handleEndSource() {}
133};
134
135/// Returns a new FrontendActionFactory for any type that provides an
136/// implementation of newASTConsumer().
137///
138/// FactoryT must implement: ASTConsumer *newASTConsumer().
139///
140/// Example:
141/// struct ProvidesASTConsumers {
142///   clang::ASTConsumer *newASTConsumer();
143/// } Factory;
144/// std::unique_ptr<FrontendActionFactory> FactoryAdapter(
145///   newFrontendActionFactory(&Factory));
146template <typename FactoryT>
147inline std::unique_ptr<FrontendActionFactorynewFrontendActionFactory(
148    FactoryT *ConsumerFactorySourceFileCallbacks *Callbacks = nullptr);
149
150/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
151///
152/// \param ToolAction The action to run over the code.
153/// \param Code C++ code.
154/// \param FileName The file name which 'Code' will be mapped as.
155/// \param PCHContainerOps  The PCHContainerOperations for loading and creating
156///                         clang modules.
157///
158/// \return - True if 'ToolAction' was successfully executed.
159bool runToolOnCode(FrontendAction *ToolActionconst Twine &Code,
160                   const Twine &FileName = "input.cc",
161                   std::shared_ptr<PCHContainerOperationsPCHContainerOps =
162                       std::make_shared<PCHContainerOperations>());
163
164/// The first part of the pair is the filename, the second part the
165/// file-content.
166using FileContentMappings = std::vector<std::pair<std::stringstd::string>>;
167
168/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
169///        with additional other flags.
170///
171/// \param ToolAction The action to run over the code.
172/// \param Code C++ code.
173/// \param Args Additional flags to pass on.
174/// \param FileName The file name which 'Code' will be mapped as.
175/// \param ToolName The name of the binary running the tool. Standard library
176///                 header paths will be resolved relative to this.
177/// \param PCHContainerOps   The PCHContainerOperations for loading and creating
178///                          clang modules.
179///
180/// \return - True if 'ToolAction' was successfully executed.
181bool runToolOnCodeWithArgs(
182    FrontendAction *ToolActionconst Twine &Code,
183    const std::vector<std::string> &Argsconst Twine &FileName = "input.cc",
184    const Twine &ToolName = "clang-tool",
185    std::shared_ptr<PCHContainerOperationsPCHContainerOps =
186        std::make_shared<PCHContainerOperations>(),
187    const FileContentMappings &VirtualMappedFiles = FileContentMappings());
188
189// Similar to the overload except this takes a VFS.
190bool runToolOnCodeWithArgs(
191    FrontendAction *ToolActionconst Twine &Code,
192    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystemVFS,
193    const std::vector<std::string> &Argsconst Twine &FileName = "input.cc",
194    const Twine &ToolName = "clang-tool",
195    std::shared_ptr<PCHContainerOperationsPCHContainerOps =
196        std::make_shared<PCHContainerOperations>());
197
198/// Builds an AST for 'Code'.
199///
200/// \param Code C++ code.
201/// \param FileName The file name which 'Code' will be mapped as.
202/// \param PCHContainerOps The PCHContainerOperations for loading and creating
203/// clang modules.
204///
205/// \return The resulting AST or null if an error occurred.
206std::unique_ptr<ASTUnit>
207buildASTFromCode(StringRef CodeStringRef FileName = "input.cc",
208                 std::shared_ptr<PCHContainerOperationsPCHContainerOps =
209                     std::make_shared<PCHContainerOperations>());
210
211/// Builds an AST for 'Code' with additional flags.
212///
213/// \param Code C++ code.
214/// \param Args Additional flags to pass on.
215/// \param FileName The file name which 'Code' will be mapped as.
216/// \param ToolName The name of the binary running the tool. Standard library
217///                 header paths will be resolved relative to this.
218/// \param PCHContainerOps The PCHContainerOperations for loading and creating
219/// clang modules.
220///
221/// \param Adjuster A function to filter the command line arguments as specified.
222///
223/// \return The resulting AST or null if an error occurred.
224std::unique_ptr<ASTUnitbuildASTFromCodeWithArgs(
225    StringRef Codeconst std::vector<std::string> &Args,
226    StringRef FileName = "input.cc"StringRef ToolName = "clang-tool",
227    std::shared_ptr<PCHContainerOperationsPCHContainerOps =
228        std::make_shared<PCHContainerOperations>(),
229    ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster());
230
231/// Utility to run a FrontendAction in a single clang invocation.
232class ToolInvocation {
233public:
234  /// Create a tool invocation.
235  ///
236  /// \param CommandLine The command line arguments to clang. Note that clang
237  /// uses its binary name (CommandLine[0]) to locate its builtin headers.
238  /// Callers have to ensure that they are installed in a compatible location
239  /// (see clang driver implementation) or mapped in via mapVirtualFile.
240  /// \param FAction The action to be executed. Class takes ownership.
241  /// \param Files The FileManager used for the execution. Class does not take
242  /// ownership.
243  /// \param PCHContainerOps The PCHContainerOperations for loading and creating
244  /// clang modules.
245  ToolInvocation(std::vector<std::stringCommandLineFrontendAction *FAction,
246                 FileManager *Files,
247                 std::shared_ptr<PCHContainerOperationsPCHContainerOps =
248                     std::make_shared<PCHContainerOperations>());
249
250  /// Create a tool invocation.
251  ///
252  /// \param CommandLine The command line arguments to clang.
253  /// \param Action The action to be executed.
254  /// \param Files The FileManager used for the execution.
255  /// \param PCHContainerOps The PCHContainerOperations for loading and creating
256  /// clang modules.
257  ToolInvocation(std::vector<std::stringCommandLineToolAction *Action,
258                 FileManager *Files,
259                 std::shared_ptr<PCHContainerOperationsPCHContainerOps);
260
261  ~ToolInvocation();
262
263  /// Set a \c DiagnosticConsumer to use during parsing.
264  void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
265    this->DiagConsumer = DiagConsumer;
266  }
267
268  /// Map a virtual file to be used while running the tool.
269  ///
270  /// \param FilePath The path at which the content will be mapped.
271  /// \param Content A null terminated buffer of the file's content.
272  // FIXME: remove this when all users have migrated!
273  void mapVirtualFile(StringRef FilePathStringRef Content);
274
275  /// Run the clang invocation.
276  ///
277  /// \returns True if there were no errors during execution.
278  bool run();
279
280 private:
281  void addFileMappingsTo(SourceManager &SourceManager);
282
283  bool runInvocation(const char *BinaryName,
284                     driver::Compilation *Compilation,
285                     std::shared_ptr<CompilerInvocationInvocation,
286                     std::shared_ptr<PCHContainerOperationsPCHContainerOps);
287
288  std::vector<std::stringCommandLine;
289  ToolAction *Action;
290  bool OwnsAction;
291  FileManager *Files;
292  std::shared_ptr<PCHContainerOperationsPCHContainerOps;
293  // Maps <file name> -> <file content>.
294  llvm::StringMap<StringRef> MappedFileContents;
295  DiagnosticConsumer *DiagConsumer = nullptr;
296};
297
298/// Utility to run a FrontendAction over a set of files.
299///
300/// This class is written to be usable for command line utilities.
301/// By default the class uses ClangSyntaxOnlyAdjuster to modify
302/// command line arguments before the arguments are used to run
303/// a frontend action. One could install an additional command line
304/// arguments adjuster by calling the appendArgumentsAdjuster() method.
305class ClangTool {
306public:
307  /// Constructs a clang tool to run over a list of files.
308  ///
309  /// \param Compilations The CompilationDatabase which contains the compile
310  ///        command lines for the given source paths.
311  /// \param SourcePaths The source files to run over. If a source files is
312  ///        not found in Compilations, it is skipped.
313  /// \param PCHContainerOps The PCHContainerOperations for loading and creating
314  /// clang modules.
315  /// \param BaseFS VFS used for all underlying file accesses when running the
316  /// tool.
317  ClangTool(const CompilationDatabase &Compilations,
318            ArrayRef<std::stringSourcePaths,
319            std::shared_ptr<PCHContainerOperationsPCHContainerOps =
320                std::make_shared<PCHContainerOperations>(),
321            IntrusiveRefCntPtr<llvm::vfs::FileSystemBaseFS =
322                llvm::vfs::getRealFileSystem());
323
324  ~ClangTool();
325
326  /// Set a \c DiagnosticConsumer to use during parsing.
327  void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
328    this->DiagConsumer = DiagConsumer;
329  }
330
331  /// Map a virtual file to be used while running the tool.
332  ///
333  /// \param FilePath The path at which the content will be mapped.
334  /// \param Content A null terminated buffer of the file's content.
335  void mapVirtualFile(StringRef FilePathStringRef Content);
336
337  /// Append a command line arguments adjuster to the adjuster chain.
338  ///
339  /// \param Adjuster An argument adjuster, which will be run on the output of
340  ///        previous argument adjusters.
341  void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
342
343  /// Clear the command line arguments adjuster chain.
344  void clearArgumentsAdjusters();
345
346  /// Runs an action over all files specified in the command line.
347  ///
348  /// \param Action Tool action.
349  ///
350  /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but
351  /// some files are skipped due to missing compile commands.
352  int run(ToolAction *Action);
353
354  /// Create an AST for each file specified in the command line and
355  /// append them to ASTs.
356  int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
357
358  /// Sets whether working directory should be restored after calling run(). By
359  /// default, working directory is restored. However, it could be useful to
360  /// turn this off when running on multiple threads to avoid the raciness.
361  void setRestoreWorkingDir(bool RestoreCWD);
362
363  /// Returns the file manager used in the tool.
364  ///
365  /// The file manager is shared between all translation units.
366  FileManager &getFiles() { return *Files; }
367
368  llvm::ArrayRef<std::stringgetSourcePaths() const { return SourcePaths; }
369
370private:
371  const CompilationDatabase &Compilations;
372  std::vector<std::stringSourcePaths;
373  std::shared_ptr<PCHContainerOperationsPCHContainerOps;
374
375  llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem;
376  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
377  llvm::IntrusiveRefCntPtr<FileManagerFiles;
378
379  // Contains a list of pairs (<file name>, <file content>).
380  std::vector<std::pair<StringRefStringRef>> MappedFileContents;
381
382  llvm::StringSet<> SeenWorkingDirectories;
383
384  ArgumentsAdjuster ArgsAdjuster;
385
386  DiagnosticConsumer *DiagConsumer = nullptr;
387
388  bool RestoreCWD = true;
389};
390
391template <typename T>
392std::unique_ptr<FrontendActionFactorynewFrontendActionFactory() {
393  class SimpleFrontendActionFactory : public FrontendActionFactory {
394  public:
395    FrontendAction *create() override { return new T; }
396  };
397
398  return std::unique_ptr<FrontendActionFactory>(
399      new SimpleFrontendActionFactory);
400}
401
402template <typename FactoryT>
403inline std::unique_ptr<FrontendActionFactorynewFrontendActionFactory(
404    FactoryT *ConsumerFactorySourceFileCallbacks *Callbacks) {
405  class FrontendActionFactoryAdapter : public FrontendActionFactory {
406  public:
407    explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
408                                          SourceFileCallbacks *Callbacks)
409        : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
410
411    FrontendAction *create() override {
412      return new ConsumerFactoryAdaptor(ConsumerFactoryCallbacks);
413    }
414
415  private:
416    class ConsumerFactoryAdaptor : public ASTFrontendAction {
417    public:
418      ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
419                             SourceFileCallbacks *Callbacks)
420          : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
421
422      std::unique_ptr<ASTConsumer>
423      CreateASTConsumer(CompilerInstance &, StringRef) override {
424        return ConsumerFactory->newASTConsumer();
425      }
426
427    protected:
428      bool BeginSourceFileAction(CompilerInstance &CI) override {
429        if (!ASTFrontendAction::BeginSourceFileAction(CI))
430          return false;
431        if (Callbacks)
432          return Callbacks->handleBeginSource(CI);
433        return true;
434      }
435
436      void EndSourceFileAction() override {
437        if (Callbacks)
438          Callbacks->handleEndSource();
439        ASTFrontendAction::EndSourceFileAction();
440      }
441
442    private:
443      FactoryT *ConsumerFactory;
444      SourceFileCallbacks *Callbacks;
445    };
446    FactoryT *ConsumerFactory;
447    SourceFileCallbacks *Callbacks;
448  };
449
450  return std::unique_ptr<FrontendActionFactory>(
451      new FrontendActionFactoryAdapter(ConsumerFactoryCallbacks));
452}
453
454/// Returns the absolute path of \c File, by prepending it with
455/// the current directory if \c File is not absolute.
456///
457/// Otherwise returns \c File.
458/// If 'File' starts with "./", the returned path will not contain the "./".
459/// Otherwise, the returned path will contain the literal path-concatenation of
460/// the current directory and \c File.
461///
462/// The difference to llvm::sys::fs::make_absolute is the canonicalization this
463/// does by removing "./" and computing native paths.
464///
465/// \param File Either an absolute or relative path.
466std::string getAbsolutePath(StringRef File);
467
468/// An overload of getAbsolutePath that works over the provided \p FS.
469llvm::Expected<std::stringgetAbsolutePath(llvm::vfs::FileSystem &FS,
470                                            StringRef File);
471
472/// Changes CommandLine to contain implicit flags that would have been
473/// defined had the compiler driver been invoked through the path InvokedAs.
474///
475/// For example, when called with \c InvokedAs set to `i686-linux-android-g++`,
476/// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will
477/// be inserted after the first argument in \c CommandLine.
478///
479/// This function will not add new `-target` or `--driver-mode` flags if they
480/// are already present in `CommandLine` (even if they have different settings
481/// than would have been inserted).
482///
483/// \pre `llvm::InitializeAllTargets()` has been called.
484///
485/// \param CommandLine the command line used to invoke the compiler driver or
486/// Clang tool, including the path to the executable as \c CommandLine[0].
487/// \param InvokedAs the path to the driver used to infer implicit flags.
488///
489/// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling
490/// infrastructure expects that CommandLine[0] is a tool path relative to which
491/// the builtin headers can be found.
492void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
493                                    StringRef InvokedAs);
494
495/// Creates a \c CompilerInvocation.
496CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
497                                  const llvm::opt::ArgStringList &CC1Args);
498
499// namespace tooling
500
501// namespace clang
502
503#endif // LLVM_CLANG_TOOLING_TOOLING_H
504
clang::tooling::ToolAction::runInvocation
clang::tooling::FrontendActionFactory::runInvocation
clang::tooling::FrontendActionFactory::create
clang::tooling::SourceFileCallbacks::handleBeginSource
clang::tooling::SourceFileCallbacks::handleEndSource
clang::tooling::ToolInvocation::setDiagnosticConsumer
clang::tooling::ToolInvocation::mapVirtualFile
clang::tooling::ToolInvocation::run
clang::tooling::ToolInvocation::addFileMappingsTo
clang::tooling::ToolInvocation::runInvocation
clang::tooling::ToolInvocation::CommandLine
clang::tooling::ToolInvocation::Action
clang::tooling::ToolInvocation::OwnsAction
clang::tooling::ToolInvocation::Files
clang::tooling::ToolInvocation::PCHContainerOps
clang::tooling::ToolInvocation::MappedFileContents
clang::tooling::ToolInvocation::DiagConsumer
clang::tooling::ClangTool::setDiagnosticConsumer
clang::tooling::ClangTool::mapVirtualFile
clang::tooling::ClangTool::appendArgumentsAdjuster
clang::tooling::ClangTool::clearArgumentsAdjusters
clang::tooling::ClangTool::run
clang::tooling::ClangTool::buildASTs
clang::tooling::ClangTool::setRestoreWorkingDir
clang::tooling::ClangTool::getFiles
clang::tooling::ClangTool::getSourcePaths
clang::tooling::ClangTool::Compilations
clang::tooling::ClangTool::SourcePaths
clang::tooling::ClangTool::PCHContainerOps
clang::tooling::ClangTool::OverlayFileSystem
clang::tooling::ClangTool::InMemoryFileSystem
clang::tooling::ClangTool::Files
clang::tooling::ClangTool::MappedFileContents
clang::tooling::ClangTool::SeenWorkingDirectories
clang::tooling::ClangTool::ArgsAdjuster
clang::tooling::ClangTool::DiagConsumer
clang::tooling::ClangTool::RestoreCWD
clang::tooling::ClangTool::appendArgumentsAdjuster