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
handleBeginSource(CompilerInstance & CI)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
handleEndSource()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.
setDiagnosticConsumer(DiagnosticConsumer * DiagConsumer)275 void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
276 this->DiagConsumer = DiagConsumer;
277 }
278
279 /// Set a \c DiagnosticOptions to use during driver command-line parsing.
setDiagnosticOptions(DiagnosticOptions * DiagOpts)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.
setDiagnosticConsumer(DiagnosticConsumer * DiagConsumer)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.
getFiles()374 FileManager &getFiles() { return *Files; }
375
getSourcePaths()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>
newFrontendActionFactory()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>
newFrontendActionFactory(FactoryT * ConsumerFactory,SourceFileCallbacks * Callbacks)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