Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:12

0001 //===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file implements functions to run clang tools standalone instead
0010 //  of running them as a plugin.
0011 //
0012 //  A ClangTool is initialized with a CompilationDatabase and a set of files
0013 //  to run over. The tool will then run a user-specified FrontendAction over
0014 //  all TUs in which the given files are compiled.
0015 //
0016 //  It is also possible to run a FrontendAction over a snippet of code by
0017 //  calling runToolOnCode, which is useful for unit testing.
0018 //
0019 //  Applications that need more fine grained control over how to run
0020 //  multiple FrontendActions over code can use ToolInvocation.
0021 //
0022 //  Example tools:
0023 //  - running clang -fsyntax-only over source code from an editor to get
0024 //    fast syntax checks
0025 //  - running match/replace tools over C++ code
0026 //
0027 //===----------------------------------------------------------------------===//
0028 
0029 #ifndef LLVM_CLANG_TOOLING_TOOLING_H
0030 #define LLVM_CLANG_TOOLING_TOOLING_H
0031 
0032 #include "clang/AST/ASTConsumer.h"
0033 #include "clang/Basic/FileManager.h"
0034 #include "clang/Basic/LLVM.h"
0035 #include "clang/Frontend/FrontendAction.h"
0036 #include "clang/Frontend/PCHContainerOperations.h"
0037 #include "clang/Tooling/ArgumentsAdjusters.h"
0038 #include "llvm/ADT/ArrayRef.h"
0039 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0040 #include "llvm/ADT/StringMap.h"
0041 #include "llvm/ADT/StringRef.h"
0042 #include "llvm/ADT/StringSet.h"
0043 #include "llvm/ADT/Twine.h"
0044 #include "llvm/Option/Option.h"
0045 #include "llvm/Support/VirtualFileSystem.h"
0046 #include <memory>
0047 #include <string>
0048 #include <utility>
0049 #include <vector>
0050 
0051 namespace clang {
0052 
0053 class CompilerInstance;
0054 class CompilerInvocation;
0055 class DiagnosticConsumer;
0056 class DiagnosticsEngine;
0057 
0058 namespace driver {
0059 
0060 class Compilation;
0061 
0062 } // namespace driver
0063 
0064 namespace tooling {
0065 
0066 class CompilationDatabase;
0067 
0068 /// Retrieves the flags of the `-cc1` job in `Compilation` that has only source
0069 /// files as its inputs.
0070 /// Returns nullptr if there are no such jobs or multiple of them. Note that
0071 /// offloading jobs are ignored.
0072 const llvm::opt::ArgStringList *
0073 getCC1Arguments(DiagnosticsEngine *Diagnostics,
0074                 driver::Compilation *Compilation);
0075 
0076 /// Interface to process a clang::CompilerInvocation.
0077 ///
0078 /// If your tool is based on FrontendAction, you should be deriving from
0079 /// FrontendActionFactory instead.
0080 class ToolAction {
0081 public:
0082   virtual ~ToolAction();
0083 
0084   /// Perform an action for an invocation.
0085   virtual bool
0086   runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
0087                 FileManager *Files,
0088                 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
0089                 DiagnosticConsumer *DiagConsumer) = 0;
0090 };
0091 
0092 /// Interface to generate clang::FrontendActions.
0093 ///
0094 /// Having a factory interface allows, for example, a new FrontendAction to be
0095 /// created for each translation unit processed by ClangTool.  This class is
0096 /// also a ToolAction which uses the FrontendActions created by create() to
0097 /// process each translation unit.
0098 class FrontendActionFactory : public ToolAction {
0099 public:
0100   ~FrontendActionFactory() override;
0101 
0102   /// Invokes the compiler with a FrontendAction created by create().
0103   bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
0104                      FileManager *Files,
0105                      std::shared_ptr<PCHContainerOperations> PCHContainerOps,
0106                      DiagnosticConsumer *DiagConsumer) override;
0107 
0108   /// Returns a new clang::FrontendAction.
0109   virtual std::unique_ptr<FrontendAction> create() = 0;
0110 };
0111 
0112 /// Returns a new FrontendActionFactory for a given type.
0113 ///
0114 /// T must derive from clang::FrontendAction.
0115 ///
0116 /// Example:
0117 /// std::unique_ptr<FrontendActionFactory> Factory =
0118 ///   newFrontendActionFactory<clang::SyntaxOnlyAction>();
0119 template <typename T>
0120 std::unique_ptr<FrontendActionFactory> newFrontendActionFactory();
0121 
0122 /// Callbacks called before and after each source file processed by a
0123 /// FrontendAction created by the FrontedActionFactory returned by \c
0124 /// newFrontendActionFactory.
0125 class SourceFileCallbacks {
0126 public:
0127   virtual ~SourceFileCallbacks() = default;
0128 
0129   /// Called before a source file is processed by a FrontEndAction.
0130   /// \see clang::FrontendAction::BeginSourceFileAction
0131   virtual bool handleBeginSource(CompilerInstance &CI) {
0132     return true;
0133   }
0134 
0135   /// Called after a source file is processed by a FrontendAction.
0136   /// \see clang::FrontendAction::EndSourceFileAction
0137   virtual void handleEndSource() {}
0138 };
0139 
0140 /// Returns a new FrontendActionFactory for any type that provides an
0141 /// implementation of newASTConsumer().
0142 ///
0143 /// FactoryT must implement: ASTConsumer *newASTConsumer().
0144 ///
0145 /// Example:
0146 /// struct ProvidesASTConsumers {
0147 ///   std::unique_ptr<clang::ASTConsumer> newASTConsumer();
0148 /// } Factory;
0149 /// std::unique_ptr<FrontendActionFactory> FactoryAdapter(
0150 ///   newFrontendActionFactory(&Factory));
0151 template <typename FactoryT>
0152 inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
0153     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr);
0154 
0155 /// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
0156 ///
0157 /// \param ToolAction The action to run over the code.
0158 /// \param Code C++ code.
0159 /// \param FileName The file name which 'Code' will be mapped as.
0160 /// \param PCHContainerOps  The PCHContainerOperations for loading and creating
0161 ///                         clang modules.
0162 ///
0163 /// \return - True if 'ToolAction' was successfully executed.
0164 bool runToolOnCode(std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
0165                    const Twine &FileName = "input.cc",
0166                    std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0167                        std::make_shared<PCHContainerOperations>());
0168 
0169 /// The first part of the pair is the filename, the second part the
0170 /// file-content.
0171 using FileContentMappings = std::vector<std::pair<std::string, std::string>>;
0172 
0173 /// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
0174 ///        with additional other flags.
0175 ///
0176 /// \param ToolAction The action to run over the code.
0177 /// \param Code C++ code.
0178 /// \param Args Additional flags to pass on.
0179 /// \param FileName The file name which 'Code' will be mapped as.
0180 /// \param ToolName The name of the binary running the tool. Standard library
0181 ///                 header paths will be resolved relative to this.
0182 /// \param PCHContainerOps   The PCHContainerOperations for loading and creating
0183 ///                          clang modules.
0184 ///
0185 /// \return - True if 'ToolAction' was successfully executed.
0186 bool runToolOnCodeWithArgs(
0187     std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
0188     const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
0189     const Twine &ToolName = "clang-tool",
0190     std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0191         std::make_shared<PCHContainerOperations>(),
0192     const FileContentMappings &VirtualMappedFiles = FileContentMappings());
0193 
0194 // Similar to the overload except this takes a VFS.
0195 bool runToolOnCodeWithArgs(
0196     std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
0197     llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
0198     const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
0199     const Twine &ToolName = "clang-tool",
0200     std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0201         std::make_shared<PCHContainerOperations>());
0202 
0203 /// Builds an AST for 'Code'.
0204 ///
0205 /// \param Code C++ code.
0206 /// \param FileName The file name which 'Code' will be mapped as.
0207 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
0208 /// clang modules.
0209 ///
0210 /// \return The resulting AST or null if an error occurred.
0211 std::unique_ptr<ASTUnit>
0212 buildASTFromCode(StringRef Code, StringRef FileName = "input.cc",
0213                  std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0214                      std::make_shared<PCHContainerOperations>());
0215 
0216 /// Builds an AST for 'Code' with additional flags.
0217 ///
0218 /// \param Code C++ code.
0219 /// \param Args Additional flags to pass on.
0220 /// \param FileName The file name which 'Code' will be mapped as.
0221 /// \param ToolName The name of the binary running the tool. Standard library
0222 ///                 header paths will be resolved relative to this.
0223 /// \param PCHContainerOps The PCHContainerOperations for loading and creating
0224 /// clang modules.
0225 ///
0226 /// \param Adjuster A function to filter the command line arguments as
0227 /// specified.
0228 ///
0229 /// \param BaseFS FileSystem for managing and looking up files.
0230 /// VirtualMappedFiles takes precedence.
0231 ///
0232 /// \return The resulting AST or null if an error occurred.
0233 std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
0234     StringRef Code, const std::vector<std::string> &Args,
0235     StringRef FileName = "input.cc", StringRef ToolName = "clang-tool",
0236     std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0237         std::make_shared<PCHContainerOperations>(),
0238     ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(),
0239     const FileContentMappings &VirtualMappedFiles = FileContentMappings(),
0240     DiagnosticConsumer *DiagConsumer = nullptr,
0241     IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS =
0242         llvm::vfs::getRealFileSystem());
0243 
0244 /// Utility to run a FrontendAction in a single clang invocation.
0245 class ToolInvocation {
0246 public:
0247   /// Create a tool invocation.
0248   ///
0249   /// \param CommandLine The command line arguments to clang. Note that clang
0250   /// uses its binary name (CommandLine[0]) to locate its builtin headers.
0251   /// Callers have to ensure that they are installed in a compatible location
0252   /// (see clang driver implementation) or mapped in via mapVirtualFile.
0253   /// \param FAction The action to be executed.
0254   /// \param Files The FileManager used for the execution. Class does not take
0255   /// ownership.
0256   /// \param PCHContainerOps The PCHContainerOperations for loading and creating
0257   /// clang modules.
0258   ToolInvocation(std::vector<std::string> CommandLine,
0259                  std::unique_ptr<FrontendAction> FAction, FileManager *Files,
0260                  std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0261                      std::make_shared<PCHContainerOperations>());
0262 
0263   /// Create a tool invocation.
0264   ///
0265   /// \param CommandLine The command line arguments to clang.
0266   /// \param Action The action to be executed.
0267   /// \param Files The FileManager used for the execution.
0268   /// \param PCHContainerOps The PCHContainerOperations for loading and creating
0269   /// clang modules.
0270   ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action,
0271                  FileManager *Files,
0272                  std::shared_ptr<PCHContainerOperations> PCHContainerOps);
0273 
0274   ~ToolInvocation();
0275 
0276   ToolInvocation(const ToolInvocation &) = delete;
0277   ToolInvocation &operator=(const ToolInvocation &) = delete;
0278 
0279   /// Set a \c DiagnosticConsumer to use during driver command-line parsing and
0280   /// the action invocation itself.
0281   void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
0282     this->DiagConsumer = DiagConsumer;
0283   }
0284 
0285   /// Set a \c DiagnosticOptions to use during driver command-line parsing.
0286   void setDiagnosticOptions(DiagnosticOptions *DiagOpts) {
0287     this->DiagOpts = DiagOpts;
0288   }
0289 
0290   /// Run the clang invocation.
0291   ///
0292   /// \returns True if there were no errors during execution.
0293   bool run();
0294 
0295  private:
0296   bool runInvocation(const char *BinaryName,
0297                      driver::Compilation *Compilation,
0298                      std::shared_ptr<CompilerInvocation> Invocation,
0299                      std::shared_ptr<PCHContainerOperations> PCHContainerOps);
0300 
0301   std::vector<std::string> CommandLine;
0302   ToolAction *Action;
0303   bool OwnsAction;
0304   FileManager *Files;
0305   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
0306   DiagnosticConsumer *DiagConsumer = nullptr;
0307   DiagnosticOptions *DiagOpts = nullptr;
0308 };
0309 
0310 /// Utility to run a FrontendAction over a set of files.
0311 ///
0312 /// This class is written to be usable for command line utilities.
0313 /// By default the class uses ClangSyntaxOnlyAdjuster to modify
0314 /// command line arguments before the arguments are used to run
0315 /// a frontend action. One could install an additional command line
0316 /// arguments adjuster by calling the appendArgumentsAdjuster() method.
0317 class ClangTool {
0318 public:
0319   /// Constructs a clang tool to run over a list of files.
0320   ///
0321   /// \param Compilations The CompilationDatabase which contains the compile
0322   ///        command lines for the given source paths.
0323   /// \param SourcePaths The source files to run over. If a source files is
0324   ///        not found in Compilations, it is skipped.
0325   /// \param PCHContainerOps The PCHContainerOperations for loading and creating
0326   /// clang modules.
0327   /// \param BaseFS VFS used for all underlying file accesses when running the
0328   /// tool.
0329   /// \param Files The file manager to use for underlying file operations when
0330   /// running the tool.
0331   ClangTool(const CompilationDatabase &Compilations,
0332             ArrayRef<std::string> SourcePaths,
0333             std::shared_ptr<PCHContainerOperations> PCHContainerOps =
0334                 std::make_shared<PCHContainerOperations>(),
0335             IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS =
0336                 llvm::vfs::getRealFileSystem(),
0337             IntrusiveRefCntPtr<FileManager> Files = nullptr);
0338 
0339   ~ClangTool();
0340 
0341   /// Set a \c DiagnosticConsumer to use during parsing.
0342   void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
0343     this->DiagConsumer = DiagConsumer;
0344   }
0345 
0346   /// Map a virtual file to be used while running the tool.
0347   ///
0348   /// \param FilePath The path at which the content will be mapped.
0349   /// \param Content A null terminated buffer of the file's content.
0350   void mapVirtualFile(StringRef FilePath, StringRef Content);
0351 
0352   /// Append a command line arguments adjuster to the adjuster chain.
0353   ///
0354   /// \param Adjuster An argument adjuster, which will be run on the output of
0355   ///        previous argument adjusters.
0356   void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
0357 
0358   /// Clear the command line arguments adjuster chain.
0359   void clearArgumentsAdjusters();
0360 
0361   /// Runs an action over all files specified in the command line.
0362   ///
0363   /// \param Action Tool action.
0364   ///
0365   /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but
0366   /// some files are skipped due to missing compile commands.
0367   int run(ToolAction *Action);
0368 
0369   /// Create an AST for each file specified in the command line and
0370   /// append them to ASTs.
0371   int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
0372 
0373   /// Sets whether an error message should be printed out if an action fails. By
0374   /// default, if an action fails, a message is printed out to stderr.
0375   void setPrintErrorMessage(bool PrintErrorMessage);
0376 
0377   /// Returns the file manager used in the tool.
0378   ///
0379   /// The file manager is shared between all translation units.
0380   FileManager &getFiles() { return *Files; }
0381 
0382   llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; }
0383 
0384 private:
0385   const CompilationDatabase &Compilations;
0386   std::vector<std::string> SourcePaths;
0387   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
0388 
0389   llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem;
0390   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
0391   llvm::IntrusiveRefCntPtr<FileManager> Files;
0392 
0393   // Contains a list of pairs (<file name>, <file content>).
0394   std::vector<std::pair<StringRef, StringRef>> MappedFileContents;
0395 
0396   llvm::StringSet<> SeenWorkingDirectories;
0397 
0398   ArgumentsAdjuster ArgsAdjuster;
0399 
0400   DiagnosticConsumer *DiagConsumer = nullptr;
0401 
0402   bool PrintErrorMessage = true;
0403 };
0404 
0405 template <typename T>
0406 std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
0407   class SimpleFrontendActionFactory : public FrontendActionFactory {
0408   public:
0409     std::unique_ptr<FrontendAction> create() override {
0410       return std::make_unique<T>();
0411     }
0412   };
0413 
0414   return std::unique_ptr<FrontendActionFactory>(
0415       new SimpleFrontendActionFactory);
0416 }
0417 
0418 template <typename FactoryT>
0419 inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
0420     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
0421   class FrontendActionFactoryAdapter : public FrontendActionFactory {
0422   public:
0423     explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
0424                                           SourceFileCallbacks *Callbacks)
0425         : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
0426 
0427     std::unique_ptr<FrontendAction> create() override {
0428       return std::make_unique<ConsumerFactoryAdaptor>(ConsumerFactory,
0429                                                       Callbacks);
0430     }
0431 
0432   private:
0433     class ConsumerFactoryAdaptor : public ASTFrontendAction {
0434     public:
0435       ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
0436                              SourceFileCallbacks *Callbacks)
0437           : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
0438 
0439       std::unique_ptr<ASTConsumer>
0440       CreateASTConsumer(CompilerInstance &, StringRef) override {
0441         return ConsumerFactory->newASTConsumer();
0442       }
0443 
0444     protected:
0445       bool BeginSourceFileAction(CompilerInstance &CI) override {
0446         if (!ASTFrontendAction::BeginSourceFileAction(CI))
0447           return false;
0448         if (Callbacks)
0449           return Callbacks->handleBeginSource(CI);
0450         return true;
0451       }
0452 
0453       void EndSourceFileAction() override {
0454         if (Callbacks)
0455           Callbacks->handleEndSource();
0456         ASTFrontendAction::EndSourceFileAction();
0457       }
0458 
0459     private:
0460       FactoryT *ConsumerFactory;
0461       SourceFileCallbacks *Callbacks;
0462     };
0463     FactoryT *ConsumerFactory;
0464     SourceFileCallbacks *Callbacks;
0465   };
0466 
0467   return std::unique_ptr<FrontendActionFactory>(
0468       new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks));
0469 }
0470 
0471 /// Returns the absolute path of \c File, by prepending it with
0472 /// the current directory if \c File is not absolute.
0473 ///
0474 /// Otherwise returns \c File.
0475 /// If 'File' starts with "./", the returned path will not contain the "./".
0476 /// Otherwise, the returned path will contain the literal path-concatenation of
0477 /// the current directory and \c File.
0478 ///
0479 /// The difference to llvm::sys::fs::make_absolute is the canonicalization this
0480 /// does by removing "./" and computing native paths.
0481 ///
0482 /// \param File Either an absolute or relative path.
0483 std::string getAbsolutePath(StringRef File);
0484 
0485 /// An overload of getAbsolutePath that works over the provided \p FS.
0486 llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS,
0487                                             StringRef File);
0488 
0489 /// Changes CommandLine to contain implicit flags that would have been
0490 /// defined had the compiler driver been invoked through the path InvokedAs.
0491 ///
0492 /// For example, when called with \c InvokedAs set to `i686-linux-android-g++`,
0493 /// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will
0494 /// be inserted after the first argument in \c CommandLine.
0495 ///
0496 /// This function will not add new `-target` or `--driver-mode` flags if they
0497 /// are already present in `CommandLine` (even if they have different settings
0498 /// than would have been inserted).
0499 ///
0500 /// \pre `llvm::InitializeAllTargets()` has been called.
0501 ///
0502 /// \param CommandLine the command line used to invoke the compiler driver or
0503 /// Clang tool, including the path to the executable as \c CommandLine[0].
0504 /// \param InvokedAs the path to the driver used to infer implicit flags.
0505 ///
0506 /// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling
0507 /// infrastructure expects that CommandLine[0] is a tool path relative to which
0508 /// the builtin headers can be found.
0509 void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
0510                                     StringRef InvokedAs);
0511 
0512 /// Helper function that expands response files in command line.
0513 void addExpandedResponseFiles(std::vector<std::string> &CommandLine,
0514                               llvm::StringRef WorkingDir,
0515                               llvm::cl::TokenizerCallback Tokenizer,
0516                               llvm::vfs::FileSystem &FS);
0517 
0518 /// Creates a \c CompilerInvocation.
0519 CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
0520                                   ArrayRef<const char *> CC1Args,
0521                                   const char *const BinaryName);
0522 
0523 } // namespace tooling
0524 
0525 } // namespace clang
0526 
0527 #endif // LLVM_CLANG_TOOLING_TOOLING_H