1 //===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements functions to run clang tools standalone instead
10 // of running them as a plugin.
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.
16 // It is also possible to run a FrontendAction over a snippet of code by
17 // calling runToolOnCode, which is useful for unit testing.
19 // Applications that need more fine grained control over how to run
20 // multiple FrontendActions over code can use ToolInvocation.
23 // - running clang -fsyntax-only over source code from an editor to get
25 // - running match/replace tools over C++ code
27 //===----------------------------------------------------------------------===//
29 #ifndef LLVM_CLANG_TOOLING_TOOLING_H
30 #define LLVM_CLANG_TOOLING_TOOLING_H
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"
53 class CompilerInstance;
54 class CompilerInvocation;
55 class DiagnosticConsumer;
56 class DiagnosticsEngine;
67 class CompilationDatabase;
69 /// Interface to process a clang::CompilerInvocation.
71 /// If your tool is based on FrontendAction, you should be deriving from
72 /// FrontendActionFactory instead.
75 virtual ~ToolAction();
77 /// Perform an action for an invocation.
79 runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
81 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
82 DiagnosticConsumer *DiagConsumer) = 0;
85 /// Interface to generate clang::FrontendActions.
87 /// Having a factory interface allows, for example, a new FrontendAction to be
88 /// created for each translation unit processed by ClangTool. This class is
89 /// also a ToolAction which uses the FrontendActions created by create() to
90 /// process each translation unit.
91 class FrontendActionFactory : public ToolAction {
93 ~FrontendActionFactory() override;
95 /// Invokes the compiler with a FrontendAction created by create().
96 bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
98 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
99 DiagnosticConsumer *DiagConsumer) override;
101 /// Returns a new clang::FrontendAction.
102 virtual std::unique_ptr<FrontendAction> create() = 0;
105 /// Returns a new FrontendActionFactory for a given type.
107 /// T must derive from clang::FrontendAction.
110 /// FrontendActionFactory *Factory =
111 /// newFrontendActionFactory<clang::SyntaxOnlyAction>();
112 template <typename T>
113 std::unique_ptr<FrontendActionFactory> newFrontendActionFactory();
115 /// Callbacks called before and after each source file processed by a
116 /// FrontendAction created by the FrontedActionFactory returned by \c
117 /// newFrontendActionFactory.
118 class SourceFileCallbacks {
120 virtual ~SourceFileCallbacks() = default;
122 /// Called before a source file is processed by a FrontEndAction.
123 /// \see clang::FrontendAction::BeginSourceFileAction
124 virtual bool handleBeginSource(CompilerInstance &CI) {
128 /// Called after a source file is processed by a FrontendAction.
129 /// \see clang::FrontendAction::EndSourceFileAction
130 virtual void handleEndSource() {}
133 /// Returns a new FrontendActionFactory for any type that provides an
134 /// implementation of newASTConsumer().
136 /// FactoryT must implement: ASTConsumer *newASTConsumer().
139 /// struct ProvidesASTConsumers {
140 /// clang::ASTConsumer *newASTConsumer();
142 /// std::unique_ptr<FrontendActionFactory> FactoryAdapter(
143 /// newFrontendActionFactory(&Factory));
144 template <typename FactoryT>
145 inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
146 FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr);
148 /// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
150 /// \param ToolAction The action to run over the code.
151 /// \param Code C++ code.
152 /// \param FileName The file name which 'Code' will be mapped as.
153 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
156 /// \return - True if 'ToolAction' was successfully executed.
157 bool runToolOnCode(std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
158 const Twine &FileName = "input.cc",
159 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
160 std::make_shared<PCHContainerOperations>());
162 /// The first part of the pair is the filename, the second part the
164 using FileContentMappings = std::vector<std::pair<std::string, std::string>>;
166 /// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
167 /// with additional other flags.
169 /// \param ToolAction The action to run over the code.
170 /// \param Code C++ code.
171 /// \param Args Additional flags to pass on.
172 /// \param FileName The file name which 'Code' will be mapped as.
173 /// \param ToolName The name of the binary running the tool. Standard library
174 /// header paths will be resolved relative to this.
175 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
178 /// \return - True if 'ToolAction' was successfully executed.
179 bool runToolOnCodeWithArgs(
180 std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
181 const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
182 const Twine &ToolName = "clang-tool",
183 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
184 std::make_shared<PCHContainerOperations>(),
185 const FileContentMappings &VirtualMappedFiles = FileContentMappings());
187 // Similar to the overload except this takes a VFS.
188 bool runToolOnCodeWithArgs(
189 std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
190 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
191 const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
192 const Twine &ToolName = "clang-tool",
193 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
194 std::make_shared<PCHContainerOperations>());
196 /// Builds an AST for 'Code'.
198 /// \param Code C++ code.
199 /// \param FileName The file name which 'Code' will be mapped as.
200 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
203 /// \return The resulting AST or null if an error occurred.
204 std::unique_ptr<ASTUnit>
205 buildASTFromCode(StringRef Code, StringRef FileName = "input.cc",
206 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
207 std::make_shared<PCHContainerOperations>());
209 /// Builds an AST for 'Code' with additional flags.
211 /// \param Code C++ code.
212 /// \param Args Additional flags to pass on.
213 /// \param FileName The file name which 'Code' will be mapped as.
214 /// \param ToolName The name of the binary running the tool. Standard library
215 /// header paths will be resolved relative to this.
216 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
219 /// \param Adjuster A function to filter the command line arguments as specified.
221 /// \return The resulting AST or null if an error occurred.
222 std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
223 StringRef Code, const std::vector<std::string> &Args,
224 StringRef FileName = "input.cc", StringRef ToolName = "clang-tool",
225 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
226 std::make_shared<PCHContainerOperations>(),
227 ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster());
229 /// Utility to run a FrontendAction in a single clang invocation.
230 class ToolInvocation {
232 /// Create a tool invocation.
234 /// \param CommandLine The command line arguments to clang. Note that clang
235 /// uses its binary name (CommandLine[0]) to locate its builtin headers.
236 /// Callers have to ensure that they are installed in a compatible location
237 /// (see clang driver implementation) or mapped in via mapVirtualFile.
238 /// \param FAction The action to be executed.
239 /// \param Files The FileManager used for the execution. Class does not take
241 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
243 ToolInvocation(std::vector<std::string> CommandLine,
244 std::unique_ptr<FrontendAction> FAction, FileManager *Files,
245 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
246 std::make_shared<PCHContainerOperations>());
248 /// Create a tool invocation.
250 /// \param CommandLine The command line arguments to clang.
251 /// \param Action The action to be executed.
252 /// \param Files The FileManager used for the execution.
253 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
255 ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action,
257 std::shared_ptr<PCHContainerOperations> PCHContainerOps);
261 /// Set a \c DiagnosticConsumer to use during parsing.
262 void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
263 this->DiagConsumer = DiagConsumer;
266 /// Map a virtual file to be used while running the tool.
268 /// \param FilePath The path at which the content will be mapped.
269 /// \param Content A null terminated buffer of the file's content.
270 // FIXME: remove this when all users have migrated!
271 void mapVirtualFile(StringRef FilePath, StringRef Content);
273 /// Run the clang invocation.
275 /// \returns True if there were no errors during execution.
279 void addFileMappingsTo(SourceManager &SourceManager);
281 bool runInvocation(const char *BinaryName,
282 driver::Compilation *Compilation,
283 std::shared_ptr<CompilerInvocation> Invocation,
284 std::shared_ptr<PCHContainerOperations> PCHContainerOps);
286 std::vector<std::string> CommandLine;
290 std::shared_ptr<PCHContainerOperations> PCHContainerOps;
291 // Maps <file name> -> <file content>.
292 llvm::StringMap<StringRef> MappedFileContents;
293 DiagnosticConsumer *DiagConsumer = nullptr;
296 /// Utility to run a FrontendAction over a set of files.
298 /// This class is written to be usable for command line utilities.
299 /// By default the class uses ClangSyntaxOnlyAdjuster to modify
300 /// command line arguments before the arguments are used to run
301 /// a frontend action. One could install an additional command line
302 /// arguments adjuster by calling the appendArgumentsAdjuster() method.
305 /// Constructs a clang tool to run over a list of files.
307 /// \param Compilations The CompilationDatabase which contains the compile
308 /// command lines for the given source paths.
309 /// \param SourcePaths The source files to run over. If a source files is
310 /// not found in Compilations, it is skipped.
311 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
313 /// \param BaseFS VFS used for all underlying file accesses when running the
315 /// \param Files The file manager to use for underlying file operations when
316 /// running the tool.
317 ClangTool(const CompilationDatabase &Compilations,
318 ArrayRef<std::string> SourcePaths,
319 std::shared_ptr<PCHContainerOperations> PCHContainerOps =
320 std::make_shared<PCHContainerOperations>(),
321 IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS =
322 llvm::vfs::getRealFileSystem(),
323 IntrusiveRefCntPtr<FileManager> Files = nullptr);
327 /// Set a \c DiagnosticConsumer to use during parsing.
328 void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
329 this->DiagConsumer = DiagConsumer;
332 /// Map a virtual file to be used while running the tool.
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);
338 /// Append a command line arguments adjuster to the adjuster chain.
340 /// \param Adjuster An argument adjuster, which will be run on the output of
341 /// previous argument adjusters.
342 void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
344 /// Clear the command line arguments adjuster chain.
345 void clearArgumentsAdjusters();
347 /// Runs an action over all files specified in the command line.
349 /// \param Action Tool action.
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);
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);
359 /// Sets whether working directory should be restored after calling run(). By
360 /// default, working directory is restored. However, it could be useful to
361 /// turn this off when running on multiple threads to avoid the raciness.
362 void setRestoreWorkingDir(bool RestoreCWD);
364 /// Sets whether an error message should be printed out if an action fails. By
365 /// default, if an action fails, a message is printed out to stderr.
366 void setPrintErrorMessage(bool PrintErrorMessage);
368 /// Returns the file manager used in the tool.
370 /// The file manager is shared between all translation units.
371 FileManager &getFiles() { return *Files; }
373 llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; }
376 const CompilationDatabase &Compilations;
377 std::vector<std::string> SourcePaths;
378 std::shared_ptr<PCHContainerOperations> PCHContainerOps;
380 llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem;
381 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
382 llvm::IntrusiveRefCntPtr<FileManager> Files;
384 // Contains a list of pairs (<file name>, <file content>).
385 std::vector<std::pair<StringRef, StringRef>> MappedFileContents;
387 llvm::StringSet<> SeenWorkingDirectories;
389 ArgumentsAdjuster ArgsAdjuster;
391 DiagnosticConsumer *DiagConsumer = nullptr;
393 bool RestoreCWD = true;
394 bool PrintErrorMessage = true;
397 template <typename T>
398 std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
399 class SimpleFrontendActionFactory : public FrontendActionFactory {
401 std::unique_ptr<FrontendAction> create() override {
402 return std::make_unique<T>();
406 return std::unique_ptr<FrontendActionFactory>(
407 new SimpleFrontendActionFactory);
410 template <typename FactoryT>
411 inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
412 FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
413 class FrontendActionFactoryAdapter : public FrontendActionFactory {
415 explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
416 SourceFileCallbacks *Callbacks)
417 : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
419 std::unique_ptr<FrontendAction> create() override {
420 return std::make_unique<ConsumerFactoryAdaptor>(ConsumerFactory,
425 class ConsumerFactoryAdaptor : public ASTFrontendAction {
427 ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
428 SourceFileCallbacks *Callbacks)
429 : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
431 std::unique_ptr<ASTConsumer>
432 CreateASTConsumer(CompilerInstance &, StringRef) override {
433 return ConsumerFactory->newASTConsumer();
437 bool BeginSourceFileAction(CompilerInstance &CI) override {
438 if (!ASTFrontendAction::BeginSourceFileAction(CI))
441 return Callbacks->handleBeginSource(CI);
445 void EndSourceFileAction() override {
447 Callbacks->handleEndSource();
448 ASTFrontendAction::EndSourceFileAction();
452 FactoryT *ConsumerFactory;
453 SourceFileCallbacks *Callbacks;
455 FactoryT *ConsumerFactory;
456 SourceFileCallbacks *Callbacks;
459 return std::unique_ptr<FrontendActionFactory>(
460 new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks));
463 /// Returns the absolute path of \c File, by prepending it with
464 /// the current directory if \c File is not absolute.
466 /// Otherwise returns \c File.
467 /// If 'File' starts with "./", the returned path will not contain the "./".
468 /// Otherwise, the returned path will contain the literal path-concatenation of
469 /// the current directory and \c File.
471 /// The difference to llvm::sys::fs::make_absolute is the canonicalization this
472 /// does by removing "./" and computing native paths.
474 /// \param File Either an absolute or relative path.
475 std::string getAbsolutePath(StringRef File);
477 /// An overload of getAbsolutePath that works over the provided \p FS.
478 llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS,
481 /// Changes CommandLine to contain implicit flags that would have been
482 /// defined had the compiler driver been invoked through the path InvokedAs.
484 /// For example, when called with \c InvokedAs set to `i686-linux-android-g++`,
485 /// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will
486 /// be inserted after the first argument in \c CommandLine.
488 /// This function will not add new `-target` or `--driver-mode` flags if they
489 /// are already present in `CommandLine` (even if they have different settings
490 /// than would have been inserted).
492 /// \pre `llvm::InitializeAllTargets()` has been called.
494 /// \param CommandLine the command line used to invoke the compiler driver or
495 /// Clang tool, including the path to the executable as \c CommandLine[0].
496 /// \param InvokedAs the path to the driver used to infer implicit flags.
498 /// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling
499 /// infrastructure expects that CommandLine[0] is a tool path relative to which
500 /// the builtin headers can be found.
501 void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
502 StringRef InvokedAs);
504 /// Creates a \c CompilerInvocation.
505 CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
506 const llvm::opt::ArgStringList &CC1Args);
508 } // namespace tooling
512 #endif // LLVM_CLANG_TOOLING_TOOLING_H