• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Diagnostic.h"
35 #include "clang/Basic/FileManager.h"
36 #include "clang/Basic/LLVM.h"
37 #include "clang/Driver/Util.h"
38 #include "clang/Frontend/FrontendAction.h"
39 #include "clang/Tooling/ArgumentsAdjusters.h"
40 #include "clang/Tooling/CompilationDatabase.h"
41 #include "llvm/ADT/StringMap.h"
42 #include "llvm/ADT/Twine.h"
43 #include "llvm/Option/Option.h"
44 #include <memory>
45 #include <string>
46 #include <vector>
47 
48 namespace clang {
49 
50 namespace driver {
51 class Compilation;
52 } // end namespace driver
53 
54 class CompilerInvocation;
55 class SourceManager;
56 class FrontendAction;
57 
58 namespace tooling {
59 
60 /// \brief Interface to process a clang::CompilerInvocation.
61 ///
62 /// If your tool is based on FrontendAction, you should be deriving from
63 /// FrontendActionFactory instead.
64 class ToolAction {
65 public:
66   virtual ~ToolAction();
67 
68   /// \brief Perform an action for an invocation.
69   virtual bool runInvocation(clang::CompilerInvocation *Invocation,
70                              FileManager *Files,
71                              DiagnosticConsumer *DiagConsumer) = 0;
72 };
73 
74 /// \brief Interface to generate clang::FrontendActions.
75 ///
76 /// Having a factory interface allows, for example, a new FrontendAction to be
77 /// created for each translation unit processed by ClangTool.  This class is
78 /// also a ToolAction which uses the FrontendActions created by create() to
79 /// process each translation unit.
80 class FrontendActionFactory : public ToolAction {
81 public:
82   ~FrontendActionFactory() override;
83 
84   /// \brief Invokes the compiler with a FrontendAction created by create().
85   bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files,
86                      DiagnosticConsumer *DiagConsumer) override;
87 
88   /// \brief Returns a new clang::FrontendAction.
89   ///
90   /// The caller takes ownership of the returned action.
91   virtual clang::FrontendAction *create() = 0;
92 };
93 
94 /// \brief Returns a new FrontendActionFactory for a given type.
95 ///
96 /// T must derive from clang::FrontendAction.
97 ///
98 /// Example:
99 /// FrontendActionFactory *Factory =
100 ///   newFrontendActionFactory<clang::SyntaxOnlyAction>();
101 template <typename T>
102 std::unique_ptr<FrontendActionFactory> newFrontendActionFactory();
103 
104 /// \brief Callbacks called before and after each source file processed by a
105 /// FrontendAction created by the FrontedActionFactory returned by \c
106 /// newFrontendActionFactory.
107 class SourceFileCallbacks {
108 public:
~SourceFileCallbacks()109   virtual ~SourceFileCallbacks() {}
110 
111   /// \brief Called before a source file is processed by a FrontEndAction.
112   /// \see clang::FrontendAction::BeginSourceFileAction
handleBeginSource(CompilerInstance & CI,StringRef Filename)113   virtual bool handleBeginSource(CompilerInstance &CI, StringRef Filename) {
114     return true;
115   }
116 
117   /// \brief Called after a source file is processed by a FrontendAction.
118   /// \see clang::FrontendAction::EndSourceFileAction
handleEndSource()119   virtual void handleEndSource() {}
120 };
121 
122 /// \brief Returns a new FrontendActionFactory for any type that provides an
123 /// implementation of newASTConsumer().
124 ///
125 /// FactoryT must implement: ASTConsumer *newASTConsumer().
126 ///
127 /// Example:
128 /// struct ProvidesASTConsumers {
129 ///   clang::ASTConsumer *newASTConsumer();
130 /// } Factory;
131 /// std::unique_ptr<FrontendActionFactory> FactoryAdapter(
132 ///   newFrontendActionFactory(&Factory));
133 template <typename FactoryT>
134 inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
135     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr);
136 
137 /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
138 ///
139 /// \param ToolAction The action to run over the code.
140 /// \param Code C++ code.
141 /// \param FileName The file name which 'Code' will be mapped as.
142 ///
143 /// \return - True if 'ToolAction' was successfully executed.
144 bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
145                    const Twine &FileName = "input.cc");
146 
147 /// The first part of the pair is the filename, the second part the
148 /// file-content.
149 typedef std::vector<std::pair<std::string, std::string>> FileContentMappings;
150 
151 /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
152 ///        with additional other flags.
153 ///
154 /// \param ToolAction The action to run over the code.
155 /// \param Code C++ code.
156 /// \param Args Additional flags to pass on.
157 /// \param FileName The file name which 'Code' will be mapped as.
158 ///
159 /// \return - True if 'ToolAction' was successfully executed.
160 bool runToolOnCodeWithArgs(
161     clang::FrontendAction *ToolAction, const Twine &Code,
162     const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
163     const FileContentMappings &VirtualMappedFiles = FileContentMappings());
164 
165 /// \brief Builds an AST for 'Code'.
166 ///
167 /// \param Code C++ code.
168 /// \param FileName The file name which 'Code' will be mapped as.
169 ///
170 /// \return The resulting AST or null if an error occurred.
171 std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code,
172                                           const Twine &FileName = "input.cc");
173 
174 /// \brief Builds an AST for 'Code' with additional flags.
175 ///
176 /// \param Code C++ code.
177 /// \param Args Additional flags to pass on.
178 /// \param FileName The file name which 'Code' will be mapped as.
179 ///
180 /// \return The resulting AST or null if an error occurred.
181 std::unique_ptr<ASTUnit>
182 buildASTFromCodeWithArgs(const Twine &Code,
183                          const std::vector<std::string> &Args,
184                          const Twine &FileName = "input.cc");
185 
186 /// \brief Utility to run a FrontendAction in a single clang invocation.
187 class ToolInvocation {
188  public:
189   /// \brief Create a tool invocation.
190   ///
191   /// \param CommandLine The command line arguments to clang. Note that clang
192   /// uses its binary name (CommandLine[0]) to locate its builtin headers.
193   /// Callers have to ensure that they are installed in a compatible location
194   /// (see clang driver implementation) or mapped in via mapVirtualFile.
195   /// \param FAction The action to be executed. Class takes ownership.
196   /// \param Files The FileManager used for the execution. Class does not take
197   /// ownership.
198   ToolInvocation(std::vector<std::string> CommandLine, FrontendAction *FAction,
199                  FileManager *Files);
200 
201   /// \brief Create a tool invocation.
202   ///
203   /// \param CommandLine The command line arguments to clang.
204   /// \param Action The action to be executed.
205   /// \param Files The FileManager used for the execution.
206   ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action,
207                  FileManager *Files);
208 
209   ~ToolInvocation();
210 
211   /// \brief Set a \c DiagnosticConsumer to use during parsing.
setDiagnosticConsumer(DiagnosticConsumer * DiagConsumer)212   void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
213     this->DiagConsumer = DiagConsumer;
214   }
215 
216   /// \brief Map a virtual file to be used while running the tool.
217   ///
218   /// \param FilePath The path at which the content will be mapped.
219   /// \param Content A null terminated buffer of the file's content.
220   void mapVirtualFile(StringRef FilePath, StringRef Content);
221 
222   /// \brief Run the clang invocation.
223   ///
224   /// \returns True if there were no errors during execution.
225   bool run();
226 
227  private:
228   void addFileMappingsTo(SourceManager &SourceManager);
229 
230   bool runInvocation(const char *BinaryName,
231                      clang::driver::Compilation *Compilation,
232                      clang::CompilerInvocation *Invocation);
233 
234   std::vector<std::string> CommandLine;
235   ToolAction *Action;
236   bool OwnsAction;
237   FileManager *Files;
238   // Maps <file name> -> <file content>.
239   llvm::StringMap<StringRef> MappedFileContents;
240   DiagnosticConsumer *DiagConsumer;
241 };
242 
243 /// \brief Utility to run a FrontendAction over a set of files.
244 ///
245 /// This class is written to be usable for command line utilities.
246 /// By default the class uses ClangSyntaxOnlyAdjuster to modify
247 /// command line arguments before the arguments are used to run
248 /// a frontend action. One could install an additional command line
249 /// arguments adjuster by calling the appendArgumentsAdjuster() method.
250 class ClangTool {
251  public:
252   /// \brief Constructs a clang tool to run over a list of files.
253   ///
254   /// \param Compilations The CompilationDatabase which contains the compile
255   ///        command lines for the given source paths.
256   /// \param SourcePaths The source files to run over. If a source files is
257   ///        not found in Compilations, it is skipped.
258   ClangTool(const CompilationDatabase &Compilations,
259             ArrayRef<std::string> SourcePaths);
260 
261   ~ClangTool();
262 
263   /// \brief Set a \c DiagnosticConsumer to use during parsing.
setDiagnosticConsumer(DiagnosticConsumer * DiagConsumer)264   void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
265     this->DiagConsumer = DiagConsumer;
266   }
267 
268   /// \brief 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   void mapVirtualFile(StringRef FilePath, StringRef Content);
273 
274   /// \brief Append a command line arguments adjuster to the adjuster chain.
275   ///
276   /// \param Adjuster An argument adjuster, which will be run on the output of
277   ///        previous argument adjusters.
278   void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
279 
280   /// \brief Clear the command line arguments adjuster chain.
281   void clearArgumentsAdjusters();
282 
283   /// Runs an action over all files specified in the command line.
284   ///
285   /// \param Action Tool action.
286   int run(ToolAction *Action);
287 
288   /// \brief Create an AST for each file specified in the command line and
289   /// append them to ASTs.
290   int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
291 
292   /// \brief Returns the file manager used in the tool.
293   ///
294   /// The file manager is shared between all translation units.
getFiles()295   FileManager &getFiles() { return *Files; }
296 
297  private:
298   const CompilationDatabase &Compilations;
299   std::vector<std::string> SourcePaths;
300 
301   llvm::IntrusiveRefCntPtr<FileManager> Files;
302   // Contains a list of pairs (<file name>, <file content>).
303   std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
304 
305   ArgumentsAdjuster ArgsAdjuster;
306 
307   DiagnosticConsumer *DiagConsumer;
308 };
309 
310 template <typename T>
newFrontendActionFactory()311 std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
312   class SimpleFrontendActionFactory : public FrontendActionFactory {
313   public:
314     clang::FrontendAction *create() override { return new T; }
315   };
316 
317   return std::unique_ptr<FrontendActionFactory>(
318       new SimpleFrontendActionFactory);
319 }
320 
321 template <typename FactoryT>
newFrontendActionFactory(FactoryT * ConsumerFactory,SourceFileCallbacks * Callbacks)322 inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
323     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
324   class FrontendActionFactoryAdapter : public FrontendActionFactory {
325   public:
326     explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
327                                           SourceFileCallbacks *Callbacks)
328       : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
329 
330     clang::FrontendAction *create() override {
331       return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
332     }
333 
334   private:
335     class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
336     public:
337       ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
338                              SourceFileCallbacks *Callbacks)
339         : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
340 
341       std::unique_ptr<clang::ASTConsumer>
342       CreateASTConsumer(clang::CompilerInstance &, StringRef) override {
343         return ConsumerFactory->newASTConsumer();
344       }
345 
346     protected:
347       bool BeginSourceFileAction(CompilerInstance &CI,
348                                  StringRef Filename) override {
349         if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename))
350           return false;
351         if (Callbacks)
352           return Callbacks->handleBeginSource(CI, Filename);
353         return true;
354       }
355       void EndSourceFileAction() override {
356         if (Callbacks)
357           Callbacks->handleEndSource();
358         clang::ASTFrontendAction::EndSourceFileAction();
359       }
360 
361     private:
362       FactoryT *ConsumerFactory;
363       SourceFileCallbacks *Callbacks;
364     };
365     FactoryT *ConsumerFactory;
366     SourceFileCallbacks *Callbacks;
367   };
368 
369   return std::unique_ptr<FrontendActionFactory>(
370       new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks));
371 }
372 
373 /// \brief Returns the absolute path of \c File, by prepending it with
374 /// the current directory if \c File is not absolute.
375 ///
376 /// Otherwise returns \c File.
377 /// If 'File' starts with "./", the returned path will not contain the "./".
378 /// Otherwise, the returned path will contain the literal path-concatenation of
379 /// the current directory and \c File.
380 ///
381 /// The difference to llvm::sys::fs::make_absolute is the canonicalization this
382 /// does by removing "./" and computing native paths.
383 ///
384 /// \param File Either an absolute or relative path.
385 std::string getAbsolutePath(StringRef File);
386 
387 /// \brief Creates a \c CompilerInvocation.
388 clang::CompilerInvocation *newInvocation(
389     clang::DiagnosticsEngine *Diagnostics,
390     const llvm::opt::ArgStringList &CC1Args);
391 
392 } // end namespace tooling
393 } // end namespace clang
394 
395 #endif // LLVM_CLANG_TOOLING_TOOLING_H
396