File indexing completed on 2026-05-10 08:37:11
0001
0002
0003
0004
0005
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
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
0050 struct ModuleID {
0051
0052
0053 std::string ModuleName;
0054
0055
0056
0057
0058
0059
0060
0061
0062
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
0077
0078 struct P1689ModuleInfo {
0079
0080 std::string ModuleName;
0081
0082
0083 std::string SourcePath;
0084
0085
0086 bool IsStdCXXModuleInterface = true;
0087
0088 enum class ModuleType {
0089 NamedCXXModule
0090
0091
0092
0093 };
0094 ModuleType Type = ModuleType::NamedCXXModule;
0095 };
0096
0097
0098 enum class ModuleOutputKind {
0099
0100 ModuleFile,
0101
0102 DependencyFile,
0103
0104
0105 DependencyTargets,
0106
0107 DiagnosticSerializationFile,
0108 };
0109
0110 struct ModuleDeps {
0111
0112 ModuleID ID;
0113
0114
0115 bool IsSystem;
0116
0117
0118
0119
0120
0121 std::string ClangModuleMapFile;
0122
0123
0124
0125 std::vector<std::string> ModuleMapFileDeps;
0126
0127
0128
0129 std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
0130
0131
0132
0133
0134
0135
0136 std::vector<ModuleID> ClangModuleDeps;
0137
0138
0139
0140 llvm::SmallVector<Module::LinkLibrary, 2> LinkLibraries;
0141
0142
0143
0144 void forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const;
0145
0146
0147
0148 const std::vector<std::string> &getBuildArguments();
0149
0150 private:
0151 friend class ModuleDepCollector;
0152 friend class ModuleDepCollectorPP;
0153
0154
0155 std::string FileDepsBaseDir;
0156
0157
0158
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
0170
0171
0172
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
0194 ModuleDepCollector &MDC;
0195
0196 void handleImport(const Module *Imported);
0197
0198
0199
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
0207
0208
0209
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
0217
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
0225
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
0240
0241 void applyDiscoveredDependencies(CompilerInvocation &CI);
0242
0243 private:
0244 friend ModuleDepCollectorPP;
0245
0246
0247 CompilerInstance &ScanInstance;
0248
0249 DependencyConsumer &Consumer;
0250
0251 DependencyActionController &Controller;
0252
0253 PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
0254
0255 std::string MainFile;
0256
0257 std::string ContextHash;
0258
0259
0260 std::vector<std::string> FileDeps;
0261
0262 llvm::MapVector<const Module *, std::unique_ptr<ModuleDeps>> ModularDeps;
0263
0264
0265 llvm::DenseMap<ModuleID, ModuleDeps *> ModuleDepsByID;
0266
0267 llvm::MapVector<const Module *, PrebuiltModuleDep> DirectPrebuiltModularDeps;
0268
0269 llvm::SetVector<const Module *> DirectModularDeps;
0270
0271 std::unique_ptr<DependencyOutputOptions> Opts;
0272
0273
0274
0275
0276 CowCompilerInvocation CommonInvocation;
0277
0278 ScanningOptimizations OptimizeArgs;
0279
0280 bool EagerLoadModules;
0281
0282
0283 bool IsStdModuleP1689Format;
0284
0285 std::optional<P1689ModuleInfo> ProvidedStdCXXModule;
0286 std::vector<P1689ModuleInfo> RequiredStdCXXModules;
0287
0288
0289 bool isPrebuiltModule(const Module *M);
0290
0291
0292 void addFileDep(StringRef Path);
0293
0294 void addFileDep(ModuleDeps &MD, StringRef Path);
0295
0296
0297
0298 CowCompilerInvocation getInvocationAdjustedForModuleBuildWithoutOutputs(
0299 const ModuleDeps &Deps,
0300 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
0301
0302
0303 llvm::DenseSet<const FileEntry *>
0304 collectModuleMapFiles(ArrayRef<ModuleID> ClangModuleDeps) const;
0305
0306
0307 void addModuleMapFiles(CompilerInvocation &CI,
0308 ArrayRef<ModuleID> ClangModuleDeps) const;
0309
0310 void addModuleFiles(CompilerInvocation &CI,
0311 ArrayRef<ModuleID> ClangModuleDeps) const;
0312 void addModuleFiles(CowCompilerInvocation &CI,
0313 ArrayRef<ModuleID> ClangModuleDeps) const;
0314
0315
0316 void addOutputPaths(CowCompilerInvocation &CI, ModuleDeps &Deps);
0317
0318
0319
0320 void associateWithContextHash(const CowCompilerInvocation &CI,
0321 ModuleDeps &Deps);
0322 };
0323
0324
0325 void resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
0326 const LangOptions &LangOpts,
0327 CodeGenOptions &CGOpts);
0328
0329 }
0330 }
0331 }
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{"~", "~"};
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 }
0350
0351 #endif