brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · b94d1b4 Raw
213 lines · c
1//===- DependencyScannerImpl.h - Implements dependency scanning *- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNER_H10#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNER_H11 12#include "clang/Driver/Compilation.h"13#include "clang/Frontend/CompilerInstance.h"14#include "clang/Frontend/CompilerInvocation.h"15#include "clang/Frontend/TextDiagnosticPrinter.h"16#include "clang/Serialization/ObjectFilePCHContainerReader.h"17#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"18#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"19 20namespace clang {21class DiagnosticConsumer;22 23namespace tooling {24namespace dependencies {25class DependencyScanningService;26class DependencyScanningWorker;27 28class DependencyConsumer;29class DependencyActionController;30class DependencyScanningWorkerFilesystem;31 32class DependencyScanningAction {33public:34  DependencyScanningAction(35      DependencyScanningService &Service, StringRef WorkingDirectory,36      DependencyConsumer &Consumer, DependencyActionController &Controller,37      IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,38      std::optional<StringRef> ModuleName = std::nullopt)39      : Service(Service), WorkingDirectory(WorkingDirectory),40        Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)) {}41  bool runInvocation(std::unique_ptr<CompilerInvocation> Invocation,42                     IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,43                     std::shared_ptr<PCHContainerOperations> PCHContainerOps,44                     DiagnosticConsumer *DiagConsumer);45 46  bool hasScanned() const { return Scanned; }47  bool hasDiagConsumerFinished() const { return DiagConsumerFinished; }48 49  /// Take the cc1 arguments corresponding to the most recent invocation used50  /// with this action. Any modifications implied by the discovered dependencies51  /// will have already been applied.52  std::vector<std::string> takeLastCC1Arguments() {53    std::vector<std::string> Result;54    std::swap(Result, LastCC1Arguments); // Reset LastCC1Arguments to empty.55    return Result;56  }57 58private:59  void setLastCC1Arguments(CompilerInvocation &&CI) {60    if (MDC)61      MDC->applyDiscoveredDependencies(CI);62    LastCC1Arguments = CI.getCC1CommandLine();63  }64 65  DependencyScanningService &Service;66  StringRef WorkingDirectory;67  DependencyConsumer &Consumer;68  DependencyActionController &Controller;69  IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;70  std::optional<CompilerInstance> ScanInstanceStorage;71  std::shared_ptr<ModuleDepCollector> MDC;72  std::vector<std::string> LastCC1Arguments;73  bool Scanned = false;74  bool DiagConsumerFinished = false;75};76 77// Helper functions and data types.78std::unique_ptr<DiagnosticOptions>79createDiagOptions(ArrayRef<std::string> CommandLine);80 81struct DignosticsEngineWithDiagOpts {82  // We need to bound the lifetime of the DiagOpts used to create the83  // DiganosticsEngine with the DiagnosticsEngine itself.84  std::unique_ptr<DiagnosticOptions> DiagOpts;85  IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine;86 87  DignosticsEngineWithDiagOpts(ArrayRef<std::string> CommandLine,88                               IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,89                               DiagnosticConsumer &DC);90};91 92struct TextDiagnosticsPrinterWithOutput {93  // We need to bound the lifetime of the data that supports the DiagPrinter94  // with it together so they have the same lifetime.95  std::string DiagnosticOutput;96  llvm::raw_string_ostream DiagnosticsOS;97  std::unique_ptr<DiagnosticOptions> DiagOpts;98  TextDiagnosticPrinter DiagPrinter;99 100  TextDiagnosticsPrinterWithOutput(ArrayRef<std::string> CommandLine)101      : DiagnosticsOS(DiagnosticOutput),102        DiagOpts(createDiagOptions(CommandLine)),103        DiagPrinter(DiagnosticsOS, *DiagOpts) {}104};105 106std::pair<std::unique_ptr<driver::Driver>, std::unique_ptr<driver::Compilation>>107buildCompilation(ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,108                 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,109                 llvm::BumpPtrAllocator &Alloc);110 111std::unique_ptr<CompilerInvocation>112createCompilerInvocation(ArrayRef<std::string> CommandLine,113                         DiagnosticsEngine &Diags);114 115std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>>116initVFSForTUBufferScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,117                           ArrayRef<std::string> CommandLine,118                           StringRef WorkingDirectory,119                           llvm::MemoryBufferRef TUBuffer);120 121std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>,122          std::vector<std::string>>123initVFSForByNameScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,124                         ArrayRef<std::string> CommandLine,125                         StringRef WorkingDirectory, StringRef ModuleName);126 127bool initializeScanCompilerInstance(128    CompilerInstance &ScanInstance,129    IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,130    DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service,131    IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS);132 133SmallVector<StringRef>134getInitialStableDirs(const CompilerInstance &ScanInstance);135 136std::optional<PrebuiltModulesAttrsMap>137computePrebuiltModulesASTMap(CompilerInstance &ScanInstance,138                             SmallVector<StringRef> &StableDirs);139 140std::unique_ptr<DependencyOutputOptions>141takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance);142 143/// Create the dependency collector that will collect the produced144/// dependencies. May return the created ModuleDepCollector depending145/// on the scanning format.146std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector(147    CompilerInstance &ScanInstance,148    std::unique_ptr<DependencyOutputOptions> DepOutputOpts,149    StringRef WorkingDirectory, DependencyConsumer &Consumer,150    DependencyScanningService &Service, CompilerInvocation &Inv,151    DependencyActionController &Controller,152    PrebuiltModulesAttrsMap PrebuiltModulesASTMap,153    llvm::SmallVector<StringRef> &StableDirs);154 155class CompilerInstanceWithContext {156  // Context157  DependencyScanningWorker &Worker;158  llvm::StringRef CWD;159  std::vector<std::string> CommandLine;160 161  // Context - file systems162  llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS;163 164  // Context - Diagnostics engine.165  std::unique_ptr<TextDiagnosticsPrinterWithOutput> DiagPrinterWithOS;166  // DiagConsumer may points to DiagPrinterWithOS->DiagPrinter, or a custom167  // DiagnosticConsumer passed in from initialize.168  DiagnosticConsumer *DiagConsumer = nullptr;169  std::unique_ptr<DignosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts;170 171  // Context - compiler invocation172  // Compilation's command's arguments may be owned by Alloc when expanded from173  // response files, so we need to keep Alloc alive in the context.174  llvm::BumpPtrAllocator Alloc;175  std::unique_ptr<clang::driver::Driver> Driver;176  std::unique_ptr<clang::driver::Compilation> Compilation;177  std::unique_ptr<CompilerInvocation> OriginalInvocation;178 179  // Context - output options180  std::unique_ptr<DependencyOutputOptions> OutputOpts;181 182  // Context - stable directory handling183  llvm::SmallVector<StringRef> StableDirs;184  PrebuiltModulesAttrsMap PrebuiltModuleASTMap;185 186  // Compiler Instance187  std::unique_ptr<CompilerInstance> CIPtr;188 189  // Source location offset.190  int32_t SrcLocOffset = 0;191 192public:193  CompilerInstanceWithContext(DependencyScanningWorker &Worker, StringRef CWD,194                              const std::vector<std::string> &CMD)195      : Worker(Worker), CWD(CWD), CommandLine(CMD) {};196 197  // The three methods below returns false when they fail, with the detail198  // accumulated in DiagConsumer.199  bool initialize(DiagnosticConsumer *DC);200  bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer,201                           DependencyActionController &Controller);202  bool finalize();203 204  // The method below turns the return status from the above methods205  // into an llvm::Error using a default DiagnosticConsumer.206  llvm::Error handleReturnStatus(bool Success);207};208} // namespace dependencies209} // namespace tooling210} // namespace clang211 212#endif213