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 specified. |
227 | /// |
228 | /// \return The resulting AST or null if an error occurred. |
229 | std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( |
230 | StringRef Code, const std::vector<std::string> &Args, |
231 | StringRef FileName = "input.cc" , StringRef ToolName = "clang-tool" , |
232 | std::shared_ptr<PCHContainerOperations> PCHContainerOps = |
233 | std::make_shared<PCHContainerOperations>(), |
234 | ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(), |
235 | const FileContentMappings &VirtualMappedFiles = FileContentMappings(), |
236 | DiagnosticConsumer *DiagConsumer = nullptr); |
237 | |
238 | /// Utility to run a FrontendAction in a single clang invocation. |
239 | class ToolInvocation { |
240 | public: |
241 | /// Create a tool invocation. |
242 | /// |
243 | /// \param CommandLine The command line arguments to clang. Note that clang |
244 | /// uses its binary name (CommandLine[0]) to locate its builtin headers. |
245 | /// Callers have to ensure that they are installed in a compatible location |
246 | /// (see clang driver implementation) or mapped in via mapVirtualFile. |
247 | /// \param FAction The action to be executed. |
248 | /// \param Files The FileManager used for the execution. Class does not take |
249 | /// ownership. |
250 | /// \param PCHContainerOps The PCHContainerOperations for loading and creating |
251 | /// clang modules. |
252 | ToolInvocation(std::vector<std::string> CommandLine, |
253 | std::unique_ptr<FrontendAction> FAction, FileManager *Files, |
254 | std::shared_ptr<PCHContainerOperations> PCHContainerOps = |
255 | std::make_shared<PCHContainerOperations>()); |
256 | |
257 | /// Create a tool invocation. |
258 | /// |
259 | /// \param CommandLine The command line arguments to clang. |
260 | /// \param Action The action to be executed. |
261 | /// \param Files The FileManager used for the execution. |
262 | /// \param PCHContainerOps The PCHContainerOperations for loading and creating |
263 | /// clang modules. |
264 | ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action, |
265 | FileManager *Files, |
266 | std::shared_ptr<PCHContainerOperations> PCHContainerOps); |
267 | |
268 | ~ToolInvocation(); |
269 | |
270 | ToolInvocation(const ToolInvocation &) = delete; |
271 | ToolInvocation &operator=(const ToolInvocation &) = delete; |
272 | |
273 | /// Set a \c DiagnosticConsumer to use during driver command-line parsing and |
274 | /// the action invocation itself. |
275 | void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { |
276 | this->DiagConsumer = DiagConsumer; |
277 | } |
278 | |
279 | /// Set a \c DiagnosticOptions to use during driver command-line parsing. |
280 | void setDiagnosticOptions(DiagnosticOptions *DiagOpts) { |
281 | this->DiagOpts = DiagOpts; |
282 | } |
283 | |
284 | /// Run the clang invocation. |
285 | /// |
286 | /// \returns True if there were no errors during execution. |
287 | bool run(); |
288 | |
289 | private: |
290 | bool runInvocation(const char *BinaryName, |
291 | driver::Compilation *Compilation, |
292 | std::shared_ptr<CompilerInvocation> Invocation, |
293 | std::shared_ptr<PCHContainerOperations> PCHContainerOps); |
294 | |
295 | std::vector<std::string> CommandLine; |
296 | ToolAction *Action; |
297 | bool OwnsAction; |
298 | FileManager *Files; |
299 | std::shared_ptr<PCHContainerOperations> PCHContainerOps; |
300 | DiagnosticConsumer *DiagConsumer = nullptr; |
301 | DiagnosticOptions *DiagOpts = nullptr; |
302 | }; |
303 | |
304 | /// Utility to run a FrontendAction over a set of files. |
305 | /// |
306 | /// This class is written to be usable for command line utilities. |
307 | /// By default the class uses ClangSyntaxOnlyAdjuster to modify |
308 | /// command line arguments before the arguments are used to run |
309 | /// a frontend action. One could install an additional command line |
310 | /// arguments adjuster by calling the appendArgumentsAdjuster() method. |
311 | class ClangTool { |
312 | public: |
313 | /// Constructs a clang tool to run over a list of files. |
314 | /// |
315 | /// \param Compilations The CompilationDatabase which contains the compile |
316 | /// command lines for the given source paths. |
317 | /// \param SourcePaths The source files to run over. If a source files is |
318 | /// not found in Compilations, it is skipped. |
319 | /// \param PCHContainerOps The PCHContainerOperations for loading and creating |
320 | /// clang modules. |
321 | /// \param BaseFS VFS used for all underlying file accesses when running the |
322 | /// tool. |
323 | /// \param Files The file manager to use for underlying file operations when |
324 | /// running the tool. |
325 | ClangTool(const CompilationDatabase &Compilations, |
326 | ArrayRef<std::string> SourcePaths, |
327 | std::shared_ptr<PCHContainerOperations> PCHContainerOps = |
328 | std::make_shared<PCHContainerOperations>(), |
329 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS = |
330 | llvm::vfs::getRealFileSystem(), |
331 | IntrusiveRefCntPtr<FileManager> Files = nullptr); |
332 | |
333 | ~ClangTool(); |
334 | |
335 | /// Set a \c DiagnosticConsumer to use during parsing. |
336 | void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { |
337 | this->DiagConsumer = DiagConsumer; |
338 | } |
339 | |
340 | /// Map a virtual file to be used while running the tool. |
341 | /// |
342 | /// \param FilePath The path at which the content will be mapped. |
343 | /// \param Content A null terminated buffer of the file's content. |
344 | void mapVirtualFile(StringRef FilePath, StringRef Content); |
345 | |
346 | /// Append a command line arguments adjuster to the adjuster chain. |
347 | /// |
348 | /// \param Adjuster An argument adjuster, which will be run on the output of |
349 | /// previous argument adjusters. |
350 | void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); |
351 | |
352 | /// Clear the command line arguments adjuster chain. |
353 | void clearArgumentsAdjusters(); |
354 | |
355 | /// Runs an action over all files specified in the command line. |
356 | /// |
357 | /// \param Action Tool action. |
358 | /// |
359 | /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but |
360 | /// some files are skipped due to missing compile commands. |
361 | int run(ToolAction *Action); |
362 | |
363 | /// Create an AST for each file specified in the command line and |
364 | /// append them to ASTs. |
365 | int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs); |
366 | |
367 | /// Sets whether an error message should be printed out if an action fails. By |
368 | /// default, if an action fails, a message is printed out to stderr. |
369 | void setPrintErrorMessage(bool PrintErrorMessage); |
370 | |
371 | /// Returns the file manager used in the tool. |
372 | /// |
373 | /// The file manager is shared between all translation units. |
374 | FileManager &getFiles() { return *Files; } |
375 | |
376 | llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; } |
377 | |
378 | private: |
379 | const CompilationDatabase &Compilations; |
380 | std::vector<std::string> SourcePaths; |
381 | std::shared_ptr<PCHContainerOperations> PCHContainerOps; |
382 | |
383 | llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem; |
384 | llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem; |
385 | llvm::IntrusiveRefCntPtr<FileManager> Files; |
386 | |
387 | // Contains a list of pairs (<file name>, <file content>). |
388 | std::vector<std::pair<StringRef, StringRef>> MappedFileContents; |
389 | |
390 | llvm::StringSet<> SeenWorkingDirectories; |
391 | |
392 | ArgumentsAdjuster ArgsAdjuster; |
393 | |
394 | DiagnosticConsumer *DiagConsumer = nullptr; |
395 | |
396 | bool PrintErrorMessage = true; |
397 | }; |
398 | |
399 | template <typename T> |
400 | std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() { |
401 | class SimpleFrontendActionFactory : public FrontendActionFactory { |
402 | public: |
403 | std::unique_ptr<FrontendAction> create() override { |
404 | return std::make_unique<T>(); |
405 | } |
406 | }; |
407 | |
408 | return std::unique_ptr<FrontendActionFactory>( |
409 | new SimpleFrontendActionFactory); |
410 | } |
411 | |
412 | template <typename FactoryT> |
413 | inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( |
414 | FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) { |
415 | class FrontendActionFactoryAdapter : public FrontendActionFactory { |
416 | public: |
417 | explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, |
418 | SourceFileCallbacks *Callbacks) |
419 | : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} |
420 | |
421 | std::unique_ptr<FrontendAction> create() override { |
422 | return std::make_unique<ConsumerFactoryAdaptor>(ConsumerFactory, |
423 | Callbacks); |
424 | } |
425 | |
426 | private: |
427 | class ConsumerFactoryAdaptor : public ASTFrontendAction { |
428 | public: |
429 | ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, |
430 | SourceFileCallbacks *Callbacks) |
431 | : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} |
432 | |
433 | std::unique_ptr<ASTConsumer> |
434 | CreateASTConsumer(CompilerInstance &, StringRef) override { |
435 | return ConsumerFactory->newASTConsumer(); |
436 | } |
437 | |
438 | protected: |
439 | bool BeginSourceFileAction(CompilerInstance &CI) override { |
440 | if (!ASTFrontendAction::BeginSourceFileAction(CI)) |
441 | return false; |
442 | if (Callbacks) |
443 | return Callbacks->handleBeginSource(CI); |
444 | return true; |
445 | } |
446 | |
447 | void EndSourceFileAction() override { |
448 | if (Callbacks) |
449 | Callbacks->handleEndSource(); |
450 | ASTFrontendAction::EndSourceFileAction(); |
451 | } |
452 | |
453 | private: |
454 | FactoryT *ConsumerFactory; |
455 | SourceFileCallbacks *Callbacks; |
456 | }; |
457 | FactoryT *ConsumerFactory; |
458 | SourceFileCallbacks *Callbacks; |
459 | }; |
460 | |
461 | return std::unique_ptr<FrontendActionFactory>( |
462 | new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks)); |
463 | } |
464 | |
465 | /// Returns the absolute path of \c File, by prepending it with |
466 | /// the current directory if \c File is not absolute. |
467 | /// |
468 | /// Otherwise returns \c File. |
469 | /// If 'File' starts with "./", the returned path will not contain the "./". |
470 | /// Otherwise, the returned path will contain the literal path-concatenation of |
471 | /// the current directory and \c File. |
472 | /// |
473 | /// The difference to llvm::sys::fs::make_absolute is the canonicalization this |
474 | /// does by removing "./" and computing native paths. |
475 | /// |
476 | /// \param File Either an absolute or relative path. |
477 | std::string getAbsolutePath(StringRef File); |
478 | |
479 | /// An overload of getAbsolutePath that works over the provided \p FS. |
480 | llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS, |
481 | StringRef File); |
482 | |
483 | /// Changes CommandLine to contain implicit flags that would have been |
484 | /// defined had the compiler driver been invoked through the path InvokedAs. |
485 | /// |
486 | /// For example, when called with \c InvokedAs set to `i686-linux-android-g++`, |
487 | /// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will |
488 | /// be inserted after the first argument in \c CommandLine. |
489 | /// |
490 | /// This function will not add new `-target` or `--driver-mode` flags if they |
491 | /// are already present in `CommandLine` (even if they have different settings |
492 | /// than would have been inserted). |
493 | /// |
494 | /// \pre `llvm::InitializeAllTargets()` has been called. |
495 | /// |
496 | /// \param CommandLine the command line used to invoke the compiler driver or |
497 | /// Clang tool, including the path to the executable as \c CommandLine[0]. |
498 | /// \param InvokedAs the path to the driver used to infer implicit flags. |
499 | /// |
500 | /// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling |
501 | /// infrastructure expects that CommandLine[0] is a tool path relative to which |
502 | /// the builtin headers can be found. |
503 | void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, |
504 | StringRef InvokedAs); |
505 | |
506 | /// Helper function that expands response files in command line. |
507 | void addExpandedResponseFiles(std::vector<std::string> &CommandLine, |
508 | llvm::StringRef WorkingDir, |
509 | llvm::cl::TokenizerCallback Tokenizer, |
510 | llvm::vfs::FileSystem &FS); |
511 | |
512 | /// Creates a \c CompilerInvocation. |
513 | CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics, |
514 | ArrayRef<const char *> CC1Args, |
515 | const char *const BinaryName); |
516 | |
517 | } // namespace tooling |
518 | |
519 | } // namespace clang |
520 | |
521 | #endif // LLVM_CLANG_TOOLING_TOOLING_H |
522 | |