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