Warning: That file was not part of the compilation database. It may have many parsing errors.
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/Basic/VirtualFileSystem.h" |
37 | #include "clang/Frontend/FrontendAction.h" |
38 | #include "clang/Frontend/PCHContainerOperations.h" |
39 | #include "clang/Tooling/ArgumentsAdjusters.h" |
40 | #include "llvm/ADT/ArrayRef.h" |
41 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
42 | #include "llvm/ADT/StringMap.h" |
43 | #include "llvm/ADT/StringRef.h" |
44 | #include "llvm/ADT/StringSet.h" |
45 | #include "llvm/ADT/Twine.h" |
46 | #include "llvm/Option/Option.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 |
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 |
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<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(const Twine &Code, const Twine &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 | const Twine &Code, const std::vector<std::string> &Args, |
227 | const Twine &FileName = "input.cc", const Twine &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. |
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<vfs::FileSystem> BaseFS = |
323 | vfs::getRealFileSystem()); |
324 | |
325 | ~ClangTool(); |
326 | |
327 | /// Set a \c DiagnosticConsumer to use during parsing. |
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 | /// Returns the file manager used in the tool. |
360 | /// |
361 | /// The file manager is shared between all translation units. |
362 | FileManager &getFiles() { return *Files; } |
363 | |
364 | llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; } |
365 | |
366 | private: |
367 | const CompilationDatabase &Compilations; |
368 | std::vector<std::string> SourcePaths; |
369 | std::shared_ptr<PCHContainerOperations> PCHContainerOps; |
370 | |
371 | llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem; |
372 | llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem; |
373 | llvm::IntrusiveRefCntPtr<FileManager> Files; |
374 | |
375 | // Contains a list of pairs (<file name>, <file content>). |
376 | std::vector<std::pair<StringRef, StringRef>> MappedFileContents; |
377 | |
378 | llvm::StringSet<> SeenWorkingDirectories; |
379 | |
380 | ArgumentsAdjuster ArgsAdjuster; |
381 | |
382 | DiagnosticConsumer *DiagConsumer = nullptr; |
383 | }; |
384 | |
385 | template <typename T> |
386 | std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() { |
387 | class SimpleFrontendActionFactory : public FrontendActionFactory { |
388 | public: |
389 | FrontendAction *create() override { return new T; } |
390 | }; |
391 | |
392 | return std::unique_ptr<FrontendActionFactory>( |
393 | new SimpleFrontendActionFactory); |
394 | } |
395 | |
396 | template <typename FactoryT> |
397 | inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( |
398 | FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) { |
399 | class FrontendActionFactoryAdapter : public FrontendActionFactory { |
400 | public: |
401 | explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, |
402 | SourceFileCallbacks *Callbacks) |
403 | : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} |
404 | |
405 | FrontendAction *create() override { |
406 | return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks); |
407 | } |
408 | |
409 | private: |
410 | class ConsumerFactoryAdaptor : public ASTFrontendAction { |
411 | public: |
412 | ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, |
413 | SourceFileCallbacks *Callbacks) |
414 | : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} |
415 | |
416 | std::unique_ptr<ASTConsumer> |
417 | CreateASTConsumer(CompilerInstance &, StringRef) override { |
418 | return ConsumerFactory->newASTConsumer(); |
419 | } |
420 | |
421 | protected: |
422 | bool BeginSourceFileAction(CompilerInstance &CI) override { |
423 | if (!ASTFrontendAction::BeginSourceFileAction(CI)) |
424 | return false; |
425 | if (Callbacks) |
426 | return Callbacks->handleBeginSource(CI); |
427 | return true; |
428 | } |
429 | |
430 | void EndSourceFileAction() override { |
431 | if (Callbacks) |
432 | Callbacks->handleEndSource(); |
433 | ASTFrontendAction::EndSourceFileAction(); |
434 | } |
435 | |
436 | private: |
437 | FactoryT *ConsumerFactory; |
438 | SourceFileCallbacks *Callbacks; |
439 | }; |
440 | FactoryT *ConsumerFactory; |
441 | SourceFileCallbacks *Callbacks; |
442 | }; |
443 | |
444 | return std::unique_ptr<FrontendActionFactory>( |
445 | new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks)); |
446 | } |
447 | |
448 | /// Returns the absolute path of \c File, by prepending it with |
449 | /// the current directory if \c File is not absolute. |
450 | /// |
451 | /// Otherwise returns \c File. |
452 | /// If 'File' starts with "./", the returned path will not contain the "./". |
453 | /// Otherwise, the returned path will contain the literal path-concatenation of |
454 | /// the current directory and \c File. |
455 | /// |
456 | /// The difference to llvm::sys::fs::make_absolute is the canonicalization this |
457 | /// does by removing "./" and computing native paths. |
458 | /// |
459 | /// \param File Either an absolute or relative path. |
460 | std::string getAbsolutePath(StringRef File); |
461 | |
462 | /// Changes CommandLine to contain implicit flags that would have been |
463 | /// defined had the compiler driver been invoked through the path InvokedAs. |
464 | /// |
465 | /// For example, when called with \c InvokedAs set to `i686-linux-android-g++`, |
466 | /// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will |
467 | /// be inserted after the first argument in \c CommandLine. |
468 | /// |
469 | /// This function will not add new `-target` or `--driver-mode` flags if they |
470 | /// are already present in `CommandLine` (even if they have different settings |
471 | /// than would have been inserted). |
472 | /// |
473 | /// \pre `llvm::InitializeAllTargets()` has been called. |
474 | /// |
475 | /// \param CommandLine the command line used to invoke the compiler driver or |
476 | /// Clang tool, including the path to the executable as \c CommandLine[0]. |
477 | /// \param InvokedAs the path to the driver used to infer implicit flags. |
478 | /// |
479 | /// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling |
480 | /// infrastructure expects that CommandLine[0] is a tool path relative to which |
481 | /// the builtin headers can be found. |
482 | void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, |
483 | StringRef InvokedAs); |
484 | |
485 | /// Creates a \c CompilerInvocation. |
486 | CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics, |
487 | const llvm::opt::ArgStringList &CC1Args); |
488 | |
489 | } // namespace tooling |
490 | |
491 | } // namespace clang |
492 | |
493 | #endif // LLVM_CLANG_TOOLING_TOOLING_H |
494 |
Warning: That file was not part of the compilation database. It may have many parsing errors.