Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- ModuleDepCollector.h - Callbacks to collect deps ---------*- 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 #ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
0010 #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
0011 
0012 #include "clang/Basic/LLVM.h"
0013 #include "clang/Basic/Module.h"
0014 #include "clang/Basic/SourceManager.h"
0015 #include "clang/Frontend/CompilerInvocation.h"
0016 #include "clang/Frontend/Utils.h"
0017 #include "clang/Lex/HeaderSearch.h"
0018 #include "clang/Lex/PPCallbacks.h"
0019 #include "clang/Serialization/ASTReader.h"
0020 #include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
0021 #include "llvm/ADT/DenseMap.h"
0022 #include "llvm/ADT/Hashing.h"
0023 #include "llvm/ADT/StringSet.h"
0024 #include "llvm/Support/raw_ostream.h"
0025 #include <optional>
0026 #include <string>
0027 #include <unordered_map>
0028 #include <variant>
0029 
0030 namespace clang {
0031 namespace tooling {
0032 namespace dependencies {
0033 
0034 class DependencyActionController;
0035 class DependencyConsumer;
0036 
0037 /// Modular dependency that has already been built prior to the dependency scan.
0038 struct PrebuiltModuleDep {
0039   std::string ModuleName;
0040   std::string PCMFile;
0041   std::string ModuleMapFile;
0042 
0043   explicit PrebuiltModuleDep(const Module *M)
0044       : ModuleName(M->getTopLevelModuleName()),
0045         PCMFile(M->getASTFile()->getName()),
0046         ModuleMapFile(M->PresumedModuleMapFile) {}
0047 };
0048 
0049 /// This is used to identify a specific module.
0050 struct ModuleID {
0051   /// The name of the module. This may include `:` for C++20 module partitions,
0052   /// or a header-name for C++20 header units.
0053   std::string ModuleName;
0054 
0055   /// The context hash of a module represents the compiler options that affect
0056   /// the resulting command-line invocation.
0057   ///
0058   /// Modules with the same name and ContextHash but different invocations could
0059   /// cause non-deterministic build results.
0060   ///
0061   /// Modules with the same name but a different \c ContextHash should be
0062   /// treated as separate modules for the purpose of a build.
0063   std::string ContextHash;
0064 
0065   bool operator==(const ModuleID &Other) const {
0066     return std::tie(ModuleName, ContextHash) ==
0067            std::tie(Other.ModuleName, Other.ContextHash);
0068   }
0069 
0070   bool operator<(const ModuleID& Other) const {
0071     return std::tie(ModuleName, ContextHash) <
0072            std::tie(Other.ModuleName, Other.ContextHash);
0073   }
0074 };
0075 
0076 /// P1689ModuleInfo - Represents the needed information of standard C++20
0077 /// modules for P1689 format.
0078 struct P1689ModuleInfo {
0079   /// The name of the module. This may include `:` for partitions.
0080   std::string ModuleName;
0081 
0082   /// Optional. The source path to the module.
0083   std::string SourcePath;
0084 
0085   /// If this module is a standard c++ interface unit.
0086   bool IsStdCXXModuleInterface = true;
0087 
0088   enum class ModuleType {
0089     NamedCXXModule
0090     // To be supported
0091     // AngleHeaderUnit,
0092     // QuoteHeaderUnit
0093   };
0094   ModuleType Type = ModuleType::NamedCXXModule;
0095 };
0096 
0097 /// An output from a module compilation, such as the path of the module file.
0098 enum class ModuleOutputKind {
0099   /// The module file (.pcm). Required.
0100   ModuleFile,
0101   /// The path of the dependency file (.d), if any.
0102   DependencyFile,
0103   /// The null-separated list of names to use as the targets in the dependency
0104   /// file, if any. Defaults to the value of \c ModuleFile, as in the driver.
0105   DependencyTargets,
0106   /// The path of the serialized diagnostic file (.dia), if any.
0107   DiagnosticSerializationFile,
0108 };
0109 
0110 struct ModuleDeps {
0111   /// The identifier of the module.
0112   ModuleID ID;
0113 
0114   /// Whether this is a "system" module.
0115   bool IsSystem;
0116 
0117   /// The path to the modulemap file which defines this module.
0118   ///
0119   /// This can be used to explicitly build this module. This file will
0120   /// additionally appear in \c FileDeps as a dependency.
0121   std::string ClangModuleMapFile;
0122 
0123   /// A collection of absolute paths to module map files that this module needs
0124   /// to know about. The ordering is significant.
0125   std::vector<std::string> ModuleMapFileDeps;
0126 
0127   /// A collection of prebuilt modular dependencies this module directly depends
0128   /// on, not including transitive dependencies.
0129   std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
0130 
0131   /// A list of module identifiers this module directly depends on, not
0132   /// including transitive dependencies.
0133   ///
0134   /// This may include modules with a different context hash when it can be
0135   /// determined that the differences are benign for this compilation.
0136   std::vector<ModuleID> ClangModuleDeps;
0137 
0138   /// The set of libraries or frameworks to link against when
0139   /// an entity from this module is used.
0140   llvm::SmallVector<Module::LinkLibrary, 2> LinkLibraries;
0141 
0142   /// Invokes \c Cb for all file dependencies of this module. Each provided
0143   /// \c StringRef is only valid within the individual callback invocation.
0144   void forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const;
0145 
0146   /// Get (or compute) the compiler invocation that can be used to build this
0147   /// module. Does not include argv[0].
0148   const std::vector<std::string> &getBuildArguments();
0149 
0150 private:
0151   friend class ModuleDepCollector;
0152   friend class ModuleDepCollectorPP;
0153 
0154   /// The base directory for relative paths in \c FileDeps.
0155   std::string FileDepsBaseDir;
0156 
0157   /// A collection of paths to files that this module directly depends on, not
0158   /// including transitive dependencies.
0159   std::vector<std::string> FileDeps;
0160 
0161   std::variant<std::monostate, CowCompilerInvocation, std::vector<std::string>>
0162       BuildInfo;
0163 };
0164 
0165 using PrebuiltModuleVFSMapT = llvm::StringMap<llvm::StringSet<>>;
0166 
0167 class ModuleDepCollector;
0168 
0169 /// Callback that records textual includes and direct modular includes/imports
0170 /// during preprocessing. At the end of the main file, it also collects
0171 /// transitive modular dependencies and passes everything to the
0172 /// \c DependencyConsumer of the parent \c ModuleDepCollector.
0173 class ModuleDepCollectorPP final : public PPCallbacks {
0174 public:
0175   ModuleDepCollectorPP(ModuleDepCollector &MDC) : MDC(MDC) {}
0176 
0177   void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
0178                         SrcMgr::CharacteristicKind FileType, FileID PrevFID,
0179                         SourceLocation Loc) override;
0180   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
0181                           StringRef FileName, bool IsAngled,
0182                           CharSourceRange FilenameRange,
0183                           OptionalFileEntryRef File, StringRef SearchPath,
0184                           StringRef RelativePath, const Module *SuggestedModule,
0185                           bool ModuleImported,
0186                           SrcMgr::CharacteristicKind FileType) override;
0187   void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
0188                     const Module *Imported) override;
0189 
0190   void EndOfMainFile() override;
0191 
0192 private:
0193   /// The parent dependency collector.
0194   ModuleDepCollector &MDC;
0195 
0196   void handleImport(const Module *Imported);
0197 
0198   /// Adds direct modular dependencies that have already been built to the
0199   /// ModuleDeps instance.
0200   void
0201   addAllSubmodulePrebuiltDeps(const Module *M, ModuleDeps &MD,
0202                               llvm::DenseSet<const Module *> &SeenSubmodules);
0203   void addModulePrebuiltDeps(const Module *M, ModuleDeps &MD,
0204                              llvm::DenseSet<const Module *> &SeenSubmodules);
0205 
0206   /// Traverses the previously collected direct modular dependencies to discover
0207   /// transitive modular dependencies and fills the parent \c ModuleDepCollector
0208   /// with both.
0209   /// Returns the ID or nothing if the dependency is spurious and is ignored.
0210   std::optional<ModuleID> handleTopLevelModule(const Module *M);
0211   void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
0212                            llvm::DenseSet<const Module *> &AddedModules);
0213   void addModuleDep(const Module *M, ModuleDeps &MD,
0214                     llvm::DenseSet<const Module *> &AddedModules);
0215 
0216   /// Traverses the affecting modules and updates \c MD with references to the
0217   /// parent \c ModuleDepCollector info.
0218   void addAllAffectingClangModules(const Module *M, ModuleDeps &MD,
0219                               llvm::DenseSet<const Module *> &AddedModules);
0220   void addAffectingClangModule(const Module *M, ModuleDeps &MD,
0221                           llvm::DenseSet<const Module *> &AddedModules);
0222 };
0223 
0224 /// Collects modular and non-modular dependencies of the main file by attaching
0225 /// \c ModuleDepCollectorPP to the preprocessor.
0226 class ModuleDepCollector final : public DependencyCollector {
0227 public:
0228   ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
0229                      CompilerInstance &ScanInstance, DependencyConsumer &C,
0230                      DependencyActionController &Controller,
0231                      CompilerInvocation OriginalCI,
0232                      PrebuiltModuleVFSMapT PrebuiltModuleVFSMap,
0233                      ScanningOptimizations OptimizeArgs, bool EagerLoadModules,
0234                      bool IsStdModuleP1689Format);
0235 
0236   void attachToPreprocessor(Preprocessor &PP) override;
0237   void attachToASTReader(ASTReader &R) override;
0238 
0239   /// Apply any changes implied by the discovered dependencies to the given
0240   /// invocation, (e.g. disable implicit modules, add explicit module paths).
0241   void applyDiscoveredDependencies(CompilerInvocation &CI);
0242 
0243 private:
0244   friend ModuleDepCollectorPP;
0245 
0246   /// The compiler instance for scanning the current translation unit.
0247   CompilerInstance &ScanInstance;
0248   /// The consumer of collected dependency information.
0249   DependencyConsumer &Consumer;
0250   /// Callbacks for computing dependency information.
0251   DependencyActionController &Controller;
0252   /// Mapping from prebuilt AST files to their sorted list of VFS overlay files.
0253   PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
0254   /// Path to the main source file.
0255   std::string MainFile;
0256   /// Hash identifying the compilation conditions of the current TU.
0257   std::string ContextHash;
0258   /// Non-modular file dependencies. This includes the main source file and
0259   /// textually included header files.
0260   std::vector<std::string> FileDeps;
0261   /// Direct and transitive modular dependencies of the main source file.
0262   llvm::MapVector<const Module *, std::unique_ptr<ModuleDeps>> ModularDeps;
0263   /// Secondary mapping for \c ModularDeps allowing lookup by ModuleID without
0264   /// a preprocessor. Storage owned by \c ModularDeps.
0265   llvm::DenseMap<ModuleID, ModuleDeps *> ModuleDepsByID;
0266   /// Direct modular dependencies that have already been built.
0267   llvm::MapVector<const Module *, PrebuiltModuleDep> DirectPrebuiltModularDeps;
0268   /// Working set of direct modular dependencies.
0269   llvm::SetVector<const Module *> DirectModularDeps;
0270   /// Options that control the dependency output generation.
0271   std::unique_ptr<DependencyOutputOptions> Opts;
0272   /// A Clang invocation that's based on the original TU invocation and that has
0273   /// been partially transformed into one that can perform explicit build of
0274   /// a discovered modular dependency. Note that this still needs to be adjusted
0275   /// for each individual module.
0276   CowCompilerInvocation CommonInvocation;
0277   /// Whether to optimize the modules' command-line arguments.
0278   ScanningOptimizations OptimizeArgs;
0279   /// Whether to set up command-lines to load PCM files eagerly.
0280   bool EagerLoadModules;
0281   /// If we're generating dependency output in P1689 format
0282   /// for standard C++ modules.
0283   bool IsStdModuleP1689Format;
0284 
0285   std::optional<P1689ModuleInfo> ProvidedStdCXXModule;
0286   std::vector<P1689ModuleInfo> RequiredStdCXXModules;
0287 
0288   /// Checks whether the module is known as being prebuilt.
0289   bool isPrebuiltModule(const Module *M);
0290 
0291   /// Adds \p Path to \c FileDeps, making it absolute if necessary.
0292   void addFileDep(StringRef Path);
0293   /// Adds \p Path to \c MD.FileDeps, making it absolute if necessary.
0294   void addFileDep(ModuleDeps &MD, StringRef Path);
0295 
0296   /// Get a Clang invocation adjusted to build the given modular dependency.
0297   /// This excludes paths that are yet-to-be-provided by the build system.
0298   CowCompilerInvocation getInvocationAdjustedForModuleBuildWithoutOutputs(
0299       const ModuleDeps &Deps,
0300       llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
0301 
0302   /// Collect module map files for given modules.
0303   llvm::DenseSet<const FileEntry *>
0304   collectModuleMapFiles(ArrayRef<ModuleID> ClangModuleDeps) const;
0305 
0306   /// Add module map files to the invocation, if needed.
0307   void addModuleMapFiles(CompilerInvocation &CI,
0308                          ArrayRef<ModuleID> ClangModuleDeps) const;
0309   /// Add module files (pcm) to the invocation, if needed.
0310   void addModuleFiles(CompilerInvocation &CI,
0311                       ArrayRef<ModuleID> ClangModuleDeps) const;
0312   void addModuleFiles(CowCompilerInvocation &CI,
0313                       ArrayRef<ModuleID> ClangModuleDeps) const;
0314 
0315   /// Add paths that require looking up outputs to the given dependencies.
0316   void addOutputPaths(CowCompilerInvocation &CI, ModuleDeps &Deps);
0317 
0318   /// Compute the context hash for \p Deps, and create the mapping
0319   /// \c ModuleDepsByID[Deps.ID] = &Deps.
0320   void associateWithContextHash(const CowCompilerInvocation &CI,
0321                                 ModuleDeps &Deps);
0322 };
0323 
0324 /// Resets codegen options that don't affect modules/PCH.
0325 void resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
0326                                const LangOptions &LangOpts,
0327                                CodeGenOptions &CGOpts);
0328 
0329 } // end namespace dependencies
0330 } // end namespace tooling
0331 } // end namespace clang
0332 
0333 namespace llvm {
0334 inline hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID) {
0335   return hash_combine(ID.ModuleName, ID.ContextHash);
0336 }
0337 
0338 template <> struct DenseMapInfo<clang::tooling::dependencies::ModuleID> {
0339   using ModuleID = clang::tooling::dependencies::ModuleID;
0340   static inline ModuleID getEmptyKey() { return ModuleID{"", ""}; }
0341   static inline ModuleID getTombstoneKey() {
0342     return ModuleID{"~", "~"}; // ~ is not a valid module name or context hash
0343   }
0344   static unsigned getHashValue(const ModuleID &ID) { return hash_value(ID); }
0345   static bool isEqual(const ModuleID &LHS, const ModuleID &RHS) {
0346     return LHS == RHS;
0347   }
0348 };
0349 } // namespace llvm
0350 
0351 #endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H