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 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 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. 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. 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. 370 FileManager &getFiles() { return *Files; } 371 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> 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> 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