clang  15.0.0git
ModuleDepCollector.h
Go to the documentation of this file.
1 //===- ModuleDepCollector.h - Callbacks to collect deps ---------*- 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 #ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
10 #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
11 
12 #include "clang/Basic/LLVM.h"
15 #include "clang/Frontend/Utils.h"
16 #include "clang/Lex/HeaderSearch.h"
17 #include "clang/Lex/PPCallbacks.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/StringSet.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <string>
23 #include <unordered_map>
24 
25 namespace clang {
26 namespace tooling {
27 namespace dependencies {
28 
29 class DependencyConsumer;
30 
31 /// Modular dependency that has already been built prior to the dependency scan.
36 
37  explicit PrebuiltModuleDep(const Module *M)
38  : ModuleName(M->getTopLevelModuleName()),
39  PCMFile(M->getASTFile()->getName()),
40  ModuleMapFile(M->PresumedModuleMapFile) {}
41 };
42 
43 /// This is used to identify a specific module.
44 struct ModuleID {
45  /// The name of the module. This may include `:` for C++20 module partitions,
46  /// or a header-name for C++20 header units.
48 
49  /// The context hash of a module represents the set of compiler options that
50  /// may make one version of a module incompatible with another. This includes
51  /// things like language mode, predefined macros, header search paths, etc...
52  ///
53  /// Modules with the same name but a different \c ContextHash should be
54  /// treated as separate modules for the purpose of a build.
56 
57  bool operator==(const ModuleID &Other) const {
58  return ModuleName == Other.ModuleName && ContextHash == Other.ContextHash;
59  }
60 };
61 
63  std::size_t operator()(const ModuleID &MID) const {
64  return llvm::hash_combine(MID.ModuleName, MID.ContextHash);
65  }
66 };
67 
68 struct ModuleDeps {
69  /// The identifier of the module.
71 
72  /// Whether this is a "system" module.
73  bool IsSystem;
74 
75  /// The path to the modulemap file which defines this module.
76  ///
77  /// This can be used to explicitly build this module. This file will
78  /// additionally appear in \c FileDeps as a dependency.
80 
81  /// The path to where an implicit build would put the PCM for this module.
83 
84  /// A collection of absolute paths to files that this module directly depends
85  /// on, not including transitive dependencies.
86  llvm::StringSet<> FileDeps;
87 
88  /// A collection of absolute paths to module map files that this module needs
89  /// to know about.
90  std::vector<std::string> ModuleMapFileDeps;
91 
92  /// A collection of prebuilt modular dependencies this module directly depends
93  /// on, not including transitive dependencies.
94  std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
95 
96  /// A list of module identifiers this module directly depends on, not
97  /// including transitive dependencies.
98  ///
99  /// This may include modules with a different context hash when it can be
100  /// determined that the differences are benign for this compilation.
101  std::vector<ModuleID> ClangModuleDeps;
102 
103  // Used to track which modules that were discovered were directly imported by
104  // the primary TU.
105  bool ImportedByMainFile = false;
106 
107  /// Compiler invocation that can be used to build this module (without paths).
109 
110  /// Gets the canonical command line suitable for passing to clang.
111  ///
112  /// \param LookupPCMPath This function is called to fill in "-fmodule-file="
113  /// arguments and the "-o" argument. It needs to return
114  /// a path for where the PCM for the given module is to
115  /// be located.
116  std::vector<std::string> getCanonicalCommandLine(
117  std::function<StringRef(ModuleID)> LookupPCMPath) const;
118 
119  /// Gets the canonical command line suitable for passing to clang, excluding
120  /// "-fmodule-file=" and "-o" arguments.
121  std::vector<std::string> getCanonicalCommandLineWithoutModulePaths() const;
122 };
123 
124 class ModuleDepCollector;
125 
126 /// Callback that records textual includes and direct modular includes/imports
127 /// during preprocessing. At the end of the main file, it also collects
128 /// transitive modular dependencies and passes everything to the
129 /// \c DependencyConsumer of the parent \c ModuleDepCollector.
130 class ModuleDepCollectorPP final : public PPCallbacks {
131 public:
133 
136  FileID PrevFID) override;
137  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
138  StringRef FileName, bool IsAngled,
139  CharSourceRange FilenameRange,
140  Optional<FileEntryRef> File, StringRef SearchPath,
141  StringRef RelativePath, const Module *Imported,
142  SrcMgr::CharacteristicKind FileType) override;
143  void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
144  const Module *Imported) override;
145 
146  void EndOfMainFile() override;
147 
148 private:
149  /// The parent dependency collector.
150  ModuleDepCollector &MDC;
151  /// Working set of direct modular dependencies.
152  llvm::DenseSet<const Module *> DirectModularDeps;
153  /// Working set of direct modular dependencies that have already been built.
154  llvm::DenseSet<const Module *> DirectPrebuiltModularDeps;
155 
156  void handleImport(const Module *Imported);
157 
158  /// Adds direct modular dependencies that have already been built to the
159  /// ModuleDeps instance.
160  void
161  addAllSubmodulePrebuiltDeps(const Module *M, ModuleDeps &MD,
162  llvm::DenseSet<const Module *> &SeenSubmodules);
163  void addModulePrebuiltDeps(const Module *M, ModuleDeps &MD,
164  llvm::DenseSet<const Module *> &SeenSubmodules);
165 
166  /// Traverses the previously collected direct modular dependencies to discover
167  /// transitive modular dependencies and fills the parent \c ModuleDepCollector
168  /// with both.
169  ModuleID handleTopLevelModule(const Module *M);
170  void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
171  llvm::DenseSet<const Module *> &AddedModules);
172  void addModuleDep(const Module *M, ModuleDeps &MD,
173  llvm::DenseSet<const Module *> &AddedModules);
174 };
175 
176 /// Collects modular and non-modular dependencies of the main file by attaching
177 /// \c ModuleDepCollectorPP to the preprocessor.
179 public:
180  ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
181  CompilerInstance &ScanInstance, DependencyConsumer &C,
182  CompilerInvocation &&OriginalCI, bool OptimizeArgs);
183 
184  void attachToPreprocessor(Preprocessor &PP) override;
185  void attachToASTReader(ASTReader &R) override;
186 
187 private:
188  friend ModuleDepCollectorPP;
189 
190  /// The compiler instance for scanning the current translation unit.
191  CompilerInstance &ScanInstance;
192  /// The consumer of collected dependency information.
193  DependencyConsumer &Consumer;
194  /// Path to the main source file.
195  std::string MainFile;
196  /// Hash identifying the compilation conditions of the current TU.
197  std::string ContextHash;
198  /// Non-modular file dependencies. This includes the main source file and
199  /// textually included header files.
200  std::vector<std::string> FileDeps;
201  /// Direct and transitive modular dependencies of the main source file.
202  std::unordered_map<const Module *, ModuleDeps> ModularDeps;
203  /// Options that control the dependency output generation.
204  std::unique_ptr<DependencyOutputOptions> Opts;
205  /// The original Clang invocation passed to dependency scanner.
206  CompilerInvocation OriginalInvocation;
207  /// Whether to optimize the modules' command-line arguments.
208  bool OptimizeArgs;
209 
210  /// Checks whether the module is known as being prebuilt.
211  bool isPrebuiltModule(const Module *M);
212 
213  /// Constructs a CompilerInvocation that can be used to build the given
214  /// module, excluding paths to discovered modular dependencies that are yet to
215  /// be built.
216  CompilerInvocation makeInvocationForModuleBuildWithoutPaths(
217  const ModuleDeps &Deps,
218  llvm::function_ref<void(CompilerInvocation &)> Optimize) const;
219 };
220 
221 } // end namespace dependencies
222 } // end namespace tooling
223 } // end namespace clang
224 
225 #endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
clang::tooling::dependencies::PrebuiltModuleDep::ModuleName
std::string ModuleName
Definition: ModuleDepCollector.h:33
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::tooling::dependencies::PrebuiltModuleDep::ModuleMapFile
std::string ModuleMapFile
Definition: ModuleDepCollector.h:35
clang::tooling::dependencies::PrebuiltModuleDep::PCMFile
std::string PCMFile
Definition: ModuleDepCollector.h:34
clang::tooling::dependencies::DependencyConsumer
Definition: DependencyScanningWorker.h:32
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
clang::PPCallbacks
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Definition: PPCallbacks.h:35
clang::tooling::dependencies::ModuleDepCollector::ModuleDepCollector
ModuleDepCollector(std::unique_ptr< DependencyOutputOptions > Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, CompilerInvocation &&OriginalCI, bool OptimizeArgs)
Definition: ModuleDepCollector.cpp:352
clang::tooling::dependencies::ModuleDeps::getCanonicalCommandLine
std::vector< std::string > getCanonicalCommandLine(std::function< StringRef(ModuleID)> LookupPCMPath) const
Gets the canonical command line suitable for passing to clang.
Definition: ModuleDepCollector.cpp:102
clang::tooling::dependencies::ModuleDeps::PrebuiltModuleDeps
std::vector< PrebuiltModuleDep > PrebuiltModuleDeps
A collection of prebuilt modular dependencies this module directly depends on, not including transiti...
Definition: ModuleDepCollector.h:94
llvm::Optional< FileEntryRef >
SourceManager.h
clang::SrcMgr::CharacteristicKind
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:79
clang::tooling::dependencies::ModuleDeps::FileDeps
llvm::StringSet FileDeps
A collection of absolute paths to files that this module directly depends on, not including transitiv...
Definition: ModuleDepCollector.h:86
clang::tooling::dependencies::ModuleDeps::ModuleMapFileDeps
std::vector< std::string > ModuleMapFileDeps
A collection of absolute paths to module map files that this module needs to know about.
Definition: ModuleDepCollector.h:90
clang::Token
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
CompilerInvocation.h
clang::tooling::dependencies::PrebuiltModuleDep::PrebuiltModuleDep
PrebuiltModuleDep(const Module *M)
Definition: ModuleDepCollector.h:37
clang::tooling::dependencies::ModuleDeps::IsSystem
bool IsSystem
Whether this is a "system" module.
Definition: ModuleDepCollector.h:73
clang::tooling::dependencies::ModuleDepCollector::attachToPreprocessor
void attachToPreprocessor(Preprocessor &PP) override
Definition: ModuleDepCollector.cpp:359
size_t
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Definition: opencl-c-base.h:117
clang::tooling::dependencies::ModuleDeps::ID
ModuleID ID
The identifier of the module.
Definition: ModuleDepCollector.h:70
clang::Module
Describes a module or submodule.
Definition: Module.h:96
clang::tooling::dependencies::ModuleIDHasher
Definition: ModuleDepCollector.h:62
clang::tooling::dependencies::PrebuiltModuleDep
Modular dependency that has already been built prior to the dependency scan.
Definition: ModuleDepCollector.h:32
Utils.h
clang::tooling::dependencies::ModuleDeps::ImportedByMainFile
bool ImportedByMainFile
Definition: ModuleDepCollector.h:105
clang::tooling::dependencies::ModuleDeps::getCanonicalCommandLineWithoutModulePaths
std::vector< std::string > getCanonicalCommandLineWithoutModulePaths() const
Gets the canonical command line suitable for passing to clang, excluding "-fmodule-file=" and "-o" ar...
Definition: ModuleDepCollector.cpp:119
clang::tooling::dependencies::ModuleDepCollectorPP
Callback that records textual includes and direct modular includes/imports during preprocessing.
Definition: ModuleDepCollector.h:130
clang::tooling::dependencies::ModuleID::ModuleName
std::string ModuleName
The name of the module.
Definition: ModuleDepCollector.h:47
llvm::DenseSet
Definition: Sema.h:77
clang::DependencyCollector
An interface for collecting the dependencies of a compilation.
Definition: Utils.h:61
getName
static std::string getName(const CallEvent &Call)
Definition: ReturnValueChecker.cpp:61
clang::CompilerInstance
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Definition: CompilerInstance.h:72
clang::format::hash_combine
static void hash_combine(std::size_t &seed, const T &v)
Definition: UnwrappedLineParser.cpp:743
clang::tooling::dependencies::ModuleID::operator==
bool operator==(const ModuleID &Other) const
Definition: ModuleDepCollector.h:57
clang::PPCallbacks::FileChangeReason
FileChangeReason
Definition: PPCallbacks.h:39
clang::tooling::dependencies::ModuleIDHasher::operator()
std::size_t operator()(const ModuleID &MID) const
Definition: ModuleDepCollector.h:63
llvm::ArrayRef
Definition: LLVM.h:34
clang::tooling::dependencies::ModuleDepCollector::attachToASTReader
void attachToASTReader(ASTReader &R) override
Definition: ModuleDepCollector.cpp:363
HeaderSearch.h
clang::tooling::dependencies::ModuleDeps
Definition: ModuleDepCollector.h:68
clang::tooling::dependencies::ModuleDepCollectorPP::EndOfMainFile
void EndOfMainFile() override
Callback invoked when the end of the main file is reached.
Definition: ModuleDepCollector.cpp:179
clang::tooling::dependencies::ModuleDeps::ClangModuleMapFile
std::string ClangModuleMapFile
The path to the modulemap file which defines this module.
Definition: ModuleDepCollector.h:79
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:253
clang::tooling::dependencies::ModuleDepCollectorPP::InclusionDirective
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, Optional< FileEntryRef > File, StringRef SearchPath, StringRef RelativePath, const Module *Imported, SrcMgr::CharacteristicKind FileType) override
Callback invoked whenever an inclusion directive of any kind (#include, #import, etc....
Definition: ModuleDepCollector.cpp:148
LLVM.h
clang::tooling::dependencies::ModuleDepCollectorPP::moduleImport
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) override
Callback invoked whenever there was an explicit module-import syntax.
Definition: ModuleDepCollector.cpp:161
clang::ASTReader
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:340
clang::tooling::dependencies::ModuleID::ContextHash
std::string ContextHash
The context hash of a module represents the set of compiler options that may make one version of a mo...
Definition: ModuleDepCollector.h:55
clang
Definition: CalledOnceCheck.h:17
PPCallbacks.h
clang::tooling::dependencies::ModuleDeps::ImplicitModulePCMPath
std::string ImplicitModulePCMPath
The path to where an implicit build would put the PCM for this module.
Definition: ModuleDepCollector.h:82
ASTReader.h
clang::FileID
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Definition: SourceLocation.h:38
clang::CompilerInvocation
Helper class for holding the data necessary to invoke the compiler.
Definition: CompilerInvocation.h:193
clang::tooling::dependencies::ModuleDepCollector
Collects modular and non-modular dependencies of the main file by attaching ModuleDepCollectorPP to t...
Definition: ModuleDepCollector.h:178
clang::tooling::dependencies::ModuleDeps::BuildInvocation
CompilerInvocation BuildInvocation
Compiler invocation that can be used to build this module (without paths).
Definition: ModuleDepCollector.h:108
clang::tooling::dependencies::ModuleDepCollectorPP::FileChanged
void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID) override
Callback invoked whenever a source file is entered or exited.
Definition: ModuleDepCollector.cpp:123
clang::tooling::dependencies::ModuleID
This is used to identify a specific module.
Definition: ModuleDepCollector.h:44
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:131
clang::tooling::dependencies::ModuleDeps::ClangModuleDeps
std::vector< ModuleID > ClangModuleDeps
A list of module identifiers this module directly depends on, not including transitive dependencies.
Definition: ModuleDepCollector.h:101
clang::tooling::dependencies::ModuleDepCollectorPP::ModuleDepCollectorPP
ModuleDepCollectorPP(ModuleDepCollector &MDC)
Definition: ModuleDepCollector.h:132