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