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