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