- //===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- //  This file implements functions to run clang tools standalone instead 
- //  of running them as a plugin. 
- // 
- //  A ClangTool is initialized with a CompilationDatabase and a set of files 
- //  to run over. The tool will then run a user-specified FrontendAction over 
- //  all TUs in which the given files are compiled. 
- // 
- //  It is also possible to run a FrontendAction over a snippet of code by 
- //  calling runToolOnCode, which is useful for unit testing. 
- // 
- //  Applications that need more fine grained control over how to run 
- //  multiple FrontendActions over code can use ToolInvocation. 
- // 
- //  Example tools: 
- //  - running clang -fsyntax-only over source code from an editor to get 
- //    fast syntax checks 
- //  - running match/replace tools over C++ code 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_TOOLING_TOOLING_H 
- #define LLVM_CLANG_TOOLING_TOOLING_H 
-   
- #include "clang/AST/ASTConsumer.h" 
- #include "clang/Basic/FileManager.h" 
- #include "clang/Basic/LLVM.h" 
- #include "clang/Frontend/FrontendAction.h" 
- #include "clang/Frontend/PCHContainerOperations.h" 
- #include "clang/Tooling/ArgumentsAdjusters.h" 
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/ADT/IntrusiveRefCntPtr.h" 
- #include "llvm/ADT/StringMap.h" 
- #include "llvm/ADT/StringRef.h" 
- #include "llvm/ADT/StringSet.h" 
- #include "llvm/ADT/Twine.h" 
- #include "llvm/Option/Option.h" 
- #include "llvm/Support/VirtualFileSystem.h" 
- #include <memory> 
- #include <string> 
- #include <utility> 
- #include <vector> 
-   
- namespace clang { 
-   
- class CompilerInstance; 
- class CompilerInvocation; 
- class DiagnosticConsumer; 
- class DiagnosticsEngine; 
-   
- namespace driver { 
-   
- class Compilation; 
-   
- } // namespace driver 
-   
- namespace tooling { 
-   
- class CompilationDatabase; 
-   
- /// Retrieves the flags of the `-cc1` job in `Compilation` that has only source 
- /// files as its inputs. 
- /// Returns nullptr if there are no such jobs or multiple of them. Note that 
- /// offloading jobs are ignored. 
- const llvm::opt::ArgStringList * 
- getCC1Arguments(DiagnosticsEngine *Diagnostics, 
-                 driver::Compilation *Compilation); 
-   
- /// Interface to process a clang::CompilerInvocation. 
- /// 
- /// If your tool is based on FrontendAction, you should be deriving from 
- /// FrontendActionFactory instead. 
- class ToolAction { 
- public: 
-   virtual ~ToolAction(); 
-   
-   /// Perform an action for an invocation. 
-   virtual bool 
-   runInvocation(std::shared_ptr<CompilerInvocation> Invocation, 
-                 FileManager *Files, 
-                 std::shared_ptr<PCHContainerOperations> PCHContainerOps, 
-                 DiagnosticConsumer *DiagConsumer) = 0; 
- }; 
-   
- /// Interface to generate clang::FrontendActions. 
- /// 
- /// Having a factory interface allows, for example, a new FrontendAction to be 
- /// created for each translation unit processed by ClangTool.  This class is 
- /// also a ToolAction which uses the FrontendActions created by create() to 
- /// process each translation unit. 
- class FrontendActionFactory : public ToolAction { 
- public: 
-   ~FrontendActionFactory() override; 
-   
-   /// Invokes the compiler with a FrontendAction created by create(). 
-   bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation, 
-                      FileManager *Files, 
-                      std::shared_ptr<PCHContainerOperations> PCHContainerOps, 
-                      DiagnosticConsumer *DiagConsumer) override; 
-   
-   /// Returns a new clang::FrontendAction. 
-   virtual std::unique_ptr<FrontendAction> create() = 0; 
- }; 
-   
- /// Returns a new FrontendActionFactory for a given type. 
- /// 
- /// T must derive from clang::FrontendAction. 
- /// 
- /// Example: 
- /// std::unique_ptr<FrontendActionFactory> Factory = 
- ///   newFrontendActionFactory<clang::SyntaxOnlyAction>(); 
- template <typename T> 
- std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(); 
-   
- /// Callbacks called before and after each source file processed by a 
- /// FrontendAction created by the FrontedActionFactory returned by \c 
- /// newFrontendActionFactory. 
- class SourceFileCallbacks { 
- public: 
-   virtual ~SourceFileCallbacks() = default; 
-   
-   /// Called before a source file is processed by a FrontEndAction. 
-   /// \see clang::FrontendAction::BeginSourceFileAction 
-   virtual bool handleBeginSource(CompilerInstance &CI) { 
-     return true; 
-   } 
-   
-   /// Called after a source file is processed by a FrontendAction. 
-   /// \see clang::FrontendAction::EndSourceFileAction 
-   virtual void handleEndSource() {} 
- }; 
-   
- /// Returns a new FrontendActionFactory for any type that provides an 
- /// implementation of newASTConsumer(). 
- /// 
- /// FactoryT must implement: ASTConsumer *newASTConsumer(). 
- /// 
- /// Example: 
- /// struct ProvidesASTConsumers { 
- ///   std::unique_ptr<clang::ASTConsumer> newASTConsumer(); 
- /// } Factory; 
- /// std::unique_ptr<FrontendActionFactory> FactoryAdapter( 
- ///   newFrontendActionFactory(&Factory)); 
- template <typename FactoryT> 
- inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( 
-     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr); 
-   
- /// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. 
- /// 
- /// \param ToolAction The action to run over the code. 
- /// \param Code C++ code. 
- /// \param FileName The file name which 'Code' will be mapped as. 
- /// \param PCHContainerOps  The PCHContainerOperations for loading and creating 
- ///                         clang modules. 
- /// 
- /// \return - True if 'ToolAction' was successfully executed. 
- bool runToolOnCode(std::unique_ptr<FrontendAction> ToolAction, const Twine &Code, 
-                    const Twine &FileName = "input.cc", 
-                    std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-                        std::make_shared<PCHContainerOperations>()); 
-   
- /// The first part of the pair is the filename, the second part the 
- /// file-content. 
- using FileContentMappings = std::vector<std::pair<std::string, std::string>>; 
-   
- /// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and 
- ///        with additional other flags. 
- /// 
- /// \param ToolAction The action to run over the code. 
- /// \param Code C++ code. 
- /// \param Args Additional flags to pass on. 
- /// \param FileName The file name which 'Code' will be mapped as. 
- /// \param ToolName The name of the binary running the tool. Standard library 
- ///                 header paths will be resolved relative to this. 
- /// \param PCHContainerOps   The PCHContainerOperations for loading and creating 
- ///                          clang modules. 
- /// 
- /// \return - True if 'ToolAction' was successfully executed. 
- bool runToolOnCodeWithArgs( 
-     std::unique_ptr<FrontendAction> ToolAction, const Twine &Code, 
-     const std::vector<std::string> &Args, const Twine &FileName = "input.cc", 
-     const Twine &ToolName = "clang-tool", 
-     std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-         std::make_shared<PCHContainerOperations>(), 
-     const FileContentMappings &VirtualMappedFiles = FileContentMappings()); 
-   
- // Similar to the overload except this takes a VFS. 
- bool runToolOnCodeWithArgs( 
-     std::unique_ptr<FrontendAction> ToolAction, const Twine &Code, 
-     llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, 
-     const std::vector<std::string> &Args, const Twine &FileName = "input.cc", 
-     const Twine &ToolName = "clang-tool", 
-     std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-         std::make_shared<PCHContainerOperations>()); 
-   
- /// Builds an AST for 'Code'. 
- /// 
- /// \param Code C++ code. 
- /// \param FileName The file name which 'Code' will be mapped as. 
- /// \param PCHContainerOps The PCHContainerOperations for loading and creating 
- /// clang modules. 
- /// 
- /// \return The resulting AST or null if an error occurred. 
- std::unique_ptr<ASTUnit> 
- buildASTFromCode(StringRef Code, StringRef FileName = "input.cc", 
-                  std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-                      std::make_shared<PCHContainerOperations>()); 
-   
- /// Builds an AST for 'Code' with additional flags. 
- /// 
- /// \param Code C++ code. 
- /// \param Args Additional flags to pass on. 
- /// \param FileName The file name which 'Code' will be mapped as. 
- /// \param ToolName The name of the binary running the tool. Standard library 
- ///                 header paths will be resolved relative to this. 
- /// \param PCHContainerOps The PCHContainerOperations for loading and creating 
- /// clang modules. 
- /// 
- /// \param Adjuster A function to filter the command line arguments as specified. 
- /// 
- /// \return The resulting AST or null if an error occurred. 
- std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( 
-     StringRef Code, const std::vector<std::string> &Args, 
-     StringRef FileName = "input.cc", StringRef ToolName = "clang-tool", 
-     std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-         std::make_shared<PCHContainerOperations>(), 
-     ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(), 
-     const FileContentMappings &VirtualMappedFiles = FileContentMappings(), 
-     DiagnosticConsumer *DiagConsumer = nullptr); 
-   
- /// Utility to run a FrontendAction in a single clang invocation. 
- class ToolInvocation { 
- public: 
-   /// Create a tool invocation. 
-   /// 
-   /// \param CommandLine The command line arguments to clang. Note that clang 
-   /// uses its binary name (CommandLine[0]) to locate its builtin headers. 
-   /// Callers have to ensure that they are installed in a compatible location 
-   /// (see clang driver implementation) or mapped in via mapVirtualFile. 
-   /// \param FAction The action to be executed. 
-   /// \param Files The FileManager used for the execution. Class does not take 
-   /// ownership. 
-   /// \param PCHContainerOps The PCHContainerOperations for loading and creating 
-   /// clang modules. 
-   ToolInvocation(std::vector<std::string> CommandLine, 
-                  std::unique_ptr<FrontendAction> FAction, FileManager *Files, 
-                  std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-                      std::make_shared<PCHContainerOperations>()); 
-   
-   /// Create a tool invocation. 
-   /// 
-   /// \param CommandLine The command line arguments to clang. 
-   /// \param Action The action to be executed. 
-   /// \param Files The FileManager used for the execution. 
-   /// \param PCHContainerOps The PCHContainerOperations for loading and creating 
-   /// clang modules. 
-   ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action, 
-                  FileManager *Files, 
-                  std::shared_ptr<PCHContainerOperations> PCHContainerOps); 
-   
-   ~ToolInvocation(); 
-   
-   /// Set a \c DiagnosticConsumer to use during driver command-line parsing and 
-   /// the action invocation itself. 
-   void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { 
-     this->DiagConsumer = DiagConsumer; 
-   } 
-   
-   /// Set a \c DiagnosticOptions to use during driver command-line parsing. 
-   void setDiagnosticOptions(DiagnosticOptions *DiagOpts) { 
-     this->DiagOpts = DiagOpts; 
-   } 
-   
-   /// Run the clang invocation. 
-   /// 
-   /// \returns True if there were no errors during execution. 
-   bool run(); 
-   
-  private: 
-   bool runInvocation(const char *BinaryName, 
-                      driver::Compilation *Compilation, 
-                      std::shared_ptr<CompilerInvocation> Invocation, 
-                      std::shared_ptr<PCHContainerOperations> PCHContainerOps); 
-   
-   std::vector<std::string> CommandLine; 
-   ToolAction *Action; 
-   bool OwnsAction; 
-   FileManager *Files; 
-   std::shared_ptr<PCHContainerOperations> PCHContainerOps; 
-   DiagnosticConsumer *DiagConsumer = nullptr; 
-   DiagnosticOptions *DiagOpts = nullptr; 
- }; 
-   
- /// Utility to run a FrontendAction over a set of files. 
- /// 
- /// This class is written to be usable for command line utilities. 
- /// By default the class uses ClangSyntaxOnlyAdjuster to modify 
- /// command line arguments before the arguments are used to run 
- /// a frontend action. One could install an additional command line 
- /// arguments adjuster by calling the appendArgumentsAdjuster() method. 
- class ClangTool { 
- public: 
-   /// Constructs a clang tool to run over a list of files. 
-   /// 
-   /// \param Compilations The CompilationDatabase which contains the compile 
-   ///        command lines for the given source paths. 
-   /// \param SourcePaths The source files to run over. If a source files is 
-   ///        not found in Compilations, it is skipped. 
-   /// \param PCHContainerOps The PCHContainerOperations for loading and creating 
-   /// clang modules. 
-   /// \param BaseFS VFS used for all underlying file accesses when running the 
-   /// tool. 
-   /// \param Files The file manager to use for underlying file operations when 
-   /// running the tool. 
-   ClangTool(const CompilationDatabase &Compilations, 
-             ArrayRef<std::string> SourcePaths, 
-             std::shared_ptr<PCHContainerOperations> PCHContainerOps = 
-                 std::make_shared<PCHContainerOperations>(), 
-             IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS = 
-                 llvm::vfs::getRealFileSystem(), 
-             IntrusiveRefCntPtr<FileManager> Files = nullptr); 
-   
-   ~ClangTool(); 
-   
-   /// Set a \c DiagnosticConsumer to use during parsing. 
-   void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { 
-     this->DiagConsumer = DiagConsumer; 
-   } 
-   
-   /// Map a virtual file to be used while running the tool. 
-   /// 
-   /// \param FilePath The path at which the content will be mapped. 
-   /// \param Content A null terminated buffer of the file's content. 
-   void mapVirtualFile(StringRef FilePath, StringRef Content); 
-   
-   /// Append a command line arguments adjuster to the adjuster chain. 
-   /// 
-   /// \param Adjuster An argument adjuster, which will be run on the output of 
-   ///        previous argument adjusters. 
-   void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); 
-   
-   /// Clear the command line arguments adjuster chain. 
-   void clearArgumentsAdjusters(); 
-   
-   /// Runs an action over all files specified in the command line. 
-   /// 
-   /// \param Action Tool action. 
-   /// 
-   /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but 
-   /// some files are skipped due to missing compile commands. 
-   int run(ToolAction *Action); 
-   
-   /// Create an AST for each file specified in the command line and 
-   /// append them to ASTs. 
-   int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs); 
-   
-   /// Sets whether working directory should be restored after calling run(). By 
-   /// default, working directory is restored. However, it could be useful to 
-   /// turn this off when running on multiple threads to avoid the raciness. 
-   void setRestoreWorkingDir(bool RestoreCWD); 
-   
-   /// Sets whether an error message should be printed out if an action fails. By 
-   /// default, if an action fails, a message is printed out to stderr. 
-   void setPrintErrorMessage(bool PrintErrorMessage); 
-   
-   /// Returns the file manager used in the tool. 
-   /// 
-   /// The file manager is shared between all translation units. 
-   FileManager &getFiles() { return *Files; } 
-   
-   llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; } 
-   
- private: 
-   const CompilationDatabase &Compilations; 
-   std::vector<std::string> SourcePaths; 
-   std::shared_ptr<PCHContainerOperations> PCHContainerOps; 
-   
-   llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem; 
-   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem; 
-   llvm::IntrusiveRefCntPtr<FileManager> Files; 
-   
-   // Contains a list of pairs (<file name>, <file content>). 
-   std::vector<std::pair<StringRef, StringRef>> MappedFileContents; 
-   
-   llvm::StringSet<> SeenWorkingDirectories; 
-   
-   ArgumentsAdjuster ArgsAdjuster; 
-   
-   DiagnosticConsumer *DiagConsumer = nullptr; 
-   
-   bool RestoreCWD = true; 
-   bool PrintErrorMessage = true; 
- }; 
-   
- template <typename T> 
- std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() { 
-   class SimpleFrontendActionFactory : public FrontendActionFactory { 
-   public: 
-     std::unique_ptr<FrontendAction> create() override { 
-       return std::make_unique<T>(); 
-     } 
-   }; 
-   
-   return std::unique_ptr<FrontendActionFactory>( 
-       new SimpleFrontendActionFactory); 
- } 
-   
- template <typename FactoryT> 
- inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( 
-     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) { 
-   class FrontendActionFactoryAdapter : public FrontendActionFactory { 
-   public: 
-     explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, 
-                                           SourceFileCallbacks *Callbacks) 
-         : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} 
-   
-     std::unique_ptr<FrontendAction> create() override { 
-       return std::make_unique<ConsumerFactoryAdaptor>(ConsumerFactory, 
-                                                       Callbacks); 
-     } 
-   
-   private: 
-     class ConsumerFactoryAdaptor : public ASTFrontendAction { 
-     public: 
-       ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, 
-                              SourceFileCallbacks *Callbacks) 
-           : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} 
-   
-       std::unique_ptr<ASTConsumer> 
-       CreateASTConsumer(CompilerInstance &, StringRef) override { 
-         return ConsumerFactory->newASTConsumer(); 
-       } 
-   
-     protected: 
-       bool BeginSourceFileAction(CompilerInstance &CI) override { 
-         if (!ASTFrontendAction::BeginSourceFileAction(CI)) 
-           return false; 
-         if (Callbacks) 
-           return Callbacks->handleBeginSource(CI); 
-         return true; 
-       } 
-   
-       void EndSourceFileAction() override { 
-         if (Callbacks) 
-           Callbacks->handleEndSource(); 
-         ASTFrontendAction::EndSourceFileAction(); 
-       } 
-   
-     private: 
-       FactoryT *ConsumerFactory; 
-       SourceFileCallbacks *Callbacks; 
-     }; 
-     FactoryT *ConsumerFactory; 
-     SourceFileCallbacks *Callbacks; 
-   }; 
-   
-   return std::unique_ptr<FrontendActionFactory>( 
-       new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks)); 
- } 
-   
- /// Returns the absolute path of \c File, by prepending it with 
- /// the current directory if \c File is not absolute. 
- /// 
- /// Otherwise returns \c File. 
- /// If 'File' starts with "./", the returned path will not contain the "./". 
- /// Otherwise, the returned path will contain the literal path-concatenation of 
- /// the current directory and \c File. 
- /// 
- /// The difference to llvm::sys::fs::make_absolute is the canonicalization this 
- /// does by removing "./" and computing native paths. 
- /// 
- /// \param File Either an absolute or relative path. 
- std::string getAbsolutePath(StringRef File); 
-   
- /// An overload of getAbsolutePath that works over the provided \p FS. 
- llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS, 
-                                             StringRef File); 
-   
- /// Changes CommandLine to contain implicit flags that would have been 
- /// defined had the compiler driver been invoked through the path InvokedAs. 
- /// 
- /// For example, when called with \c InvokedAs set to `i686-linux-android-g++`, 
- /// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will 
- /// be inserted after the first argument in \c CommandLine. 
- /// 
- /// This function will not add new `-target` or `--driver-mode` flags if they 
- /// are already present in `CommandLine` (even if they have different settings 
- /// than would have been inserted). 
- /// 
- /// \pre `llvm::InitializeAllTargets()` has been called. 
- /// 
- /// \param CommandLine the command line used to invoke the compiler driver or 
- /// Clang tool, including the path to the executable as \c CommandLine[0]. 
- /// \param InvokedAs the path to the driver used to infer implicit flags. 
- /// 
- /// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling 
- /// infrastructure expects that CommandLine[0] is a tool path relative to which 
- /// the builtin headers can be found. 
- void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, 
-                                     StringRef InvokedAs); 
-   
- /// Creates a \c CompilerInvocation. 
- CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics, 
-                                   ArrayRef<const char *> CC1Args, 
-                                   const char *const BinaryName); 
-   
- } // namespace tooling 
-   
- } // namespace clang 
-   
- #endif // LLVM_CLANG_TOOLING_TOOLING_H 
-