xref: /netbsd-src/external/apache2/llvm/dist/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
1 //===- ModuleDepCollector.h - Callbacks to collect deps ---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
11 #define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
12 
13 #include "clang/Basic/LLVM.h"
14 #include "clang/Basic/SourceManager.h"
15 #include "clang/Frontend/CompilerInvocation.h"
16 #include "clang/Frontend/Utils.h"
17 #include "clang/Lex/HeaderSearch.h"
18 #include "clang/Lex/PPCallbacks.h"
19 #include "clang/Serialization/ASTReader.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <string>
24 #include <unordered_map>
25 
26 namespace clang {
27 namespace tooling {
28 namespace dependencies {
29 
30 class DependencyConsumer;
31 
32 /// This is used to identify a specific module.
33 struct ModuleID {
34   /// The name of the module. This may include `:` for C++20 module partitions,
35   /// or a header-name for C++20 header units.
36   std::string ModuleName;
37 
38   /// The context hash of a module represents the set of compiler options that
39   /// may make one version of a module incompatible with another. This includes
40   /// things like language mode, predefined macros, header search paths, etc...
41   ///
42   /// Modules with the same name but a different \c ContextHash should be
43   /// treated as separate modules for the purpose of a build.
44   std::string ContextHash;
45 };
46 
47 struct ModuleDeps {
48   /// The identifier of the module.
49   ModuleID ID;
50 
51   /// Whether this is a "system" module.
52   bool IsSystem;
53 
54   /// The path to the modulemap file which defines this module.
55   ///
56   /// This can be used to explicitly build this module. This file will
57   /// additionally appear in \c FileDeps as a dependency.
58   std::string ClangModuleMapFile;
59 
60   /// The path to where an implicit build would put the PCM for this module.
61   std::string ImplicitModulePCMPath;
62 
63   /// A collection of absolute paths to files that this module directly depends
64   /// on, not including transitive dependencies.
65   llvm::StringSet<> FileDeps;
66 
67   /// A list of module identifiers this module directly depends on, not
68   /// including transitive dependencies.
69   ///
70   /// This may include modules with a different context hash when it can be
71   /// determined that the differences are benign for this compilation.
72   std::vector<ModuleID> ClangModuleDeps;
73 
74   // Used to track which modules that were discovered were directly imported by
75   // the primary TU.
76   bool ImportedByMainFile = false;
77 
78   /// Compiler invocation that can be used to build this module (without paths).
79   CompilerInvocation Invocation;
80 
81   /// Gets the canonical command line suitable for passing to clang.
82   ///
83   /// \param LookupPCMPath This function is called to fill in "-fmodule-file="
84   ///                      arguments and the "-o" argument. It needs to return
85   ///                      a path for where the PCM for the given module is to
86   ///                      be located.
87   /// \param LookupModuleDeps This function is called to collect the full
88   ///                         transitive set of dependencies for this
89   ///                         compilation and fill in "-fmodule-map-file="
90   ///                         arguments.
91   std::vector<std::string> getCanonicalCommandLine(
92       std::function<StringRef(ModuleID)> LookupPCMPath,
93       std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const;
94 
95   /// Gets the canonical command line suitable for passing to clang, excluding
96   /// arguments containing modules-related paths: "-fmodule-file=", "-o",
97   /// "-fmodule-map-file=".
98   std::vector<std::string> getCanonicalCommandLineWithoutModulePaths() const;
99 };
100 
101 namespace detail {
102 /// Collect the paths of PCM and module map files for the modules in \c Modules
103 /// transitively.
104 void collectPCMAndModuleMapPaths(
105     llvm::ArrayRef<ModuleID> Modules,
106     std::function<StringRef(ModuleID)> LookupPCMPath,
107     std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps,
108     std::vector<std::string> &PCMPaths, std::vector<std::string> &ModMapPaths);
109 } // namespace detail
110 
111 class ModuleDepCollector;
112 
113 /// Callback that records textual includes and direct modular includes/imports
114 /// during preprocessing. At the end of the main file, it also collects
115 /// transitive modular dependencies and passes everything to the
116 /// \c DependencyConsumer of the parent \c ModuleDepCollector.
117 class ModuleDepCollectorPP final : public PPCallbacks {
118 public:
ModuleDepCollectorPP(CompilerInstance & I,ModuleDepCollector & MDC)119   ModuleDepCollectorPP(CompilerInstance &I, ModuleDepCollector &MDC)
120       : Instance(I), MDC(MDC) {}
121 
122   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
123                    SrcMgr::CharacteristicKind FileType,
124                    FileID PrevFID) override;
125   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
126                           StringRef FileName, bool IsAngled,
127                           CharSourceRange FilenameRange, const FileEntry *File,
128                           StringRef SearchPath, StringRef RelativePath,
129                           const Module *Imported,
130                           SrcMgr::CharacteristicKind FileType) override;
131   void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
132                     const Module *Imported) override;
133 
134   void EndOfMainFile() override;
135 
136 private:
137   /// The compiler instance for the current translation unit.
138   CompilerInstance &Instance;
139   /// The parent dependency collector.
140   ModuleDepCollector &MDC;
141   /// Working set of direct modular dependencies.
142   llvm::DenseSet<const Module *> DirectModularDeps;
143 
144   void handleImport(const Module *Imported);
145 
146   /// Traverses the previously collected direct modular dependencies to discover
147   /// transitive modular dependencies and fills the parent \c ModuleDepCollector
148   /// with both.
149   ModuleID handleTopLevelModule(const Module *M);
150   void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
151                            llvm::DenseSet<const Module *> &AddedModules);
152   void addModuleDep(const Module *M, ModuleDeps &MD,
153                     llvm::DenseSet<const Module *> &AddedModules);
154 };
155 
156 /// Collects modular and non-modular dependencies of the main file by attaching
157 /// \c ModuleDepCollectorPP to the preprocessor.
158 class ModuleDepCollector final : public DependencyCollector {
159 public:
160   ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
161                      CompilerInstance &I, DependencyConsumer &C);
162 
163   void attachToPreprocessor(Preprocessor &PP) override;
164   void attachToASTReader(ASTReader &R) override;
165 
166 private:
167   friend ModuleDepCollectorPP;
168 
169   /// The compiler instance for the current translation unit.
170   CompilerInstance &Instance;
171   /// The consumer of collected dependency information.
172   DependencyConsumer &Consumer;
173   /// Path to the main source file.
174   std::string MainFile;
175   /// Hash identifying the compilation conditions of the current TU.
176   std::string ContextHash;
177   /// Non-modular file dependencies. This includes the main source file and
178   /// textually included header files.
179   std::vector<std::string> FileDeps;
180   /// Direct and transitive modular dependencies of the main source file.
181   std::unordered_map<const Module *, ModuleDeps> ModularDeps;
182   /// Options that control the dependency output generation.
183   std::unique_ptr<DependencyOutputOptions> Opts;
184 };
185 
186 } // end namespace dependencies
187 } // end namespace tooling
188 } // end namespace clang
189 
190 #endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_MODULE_DEP_COLLECTOR_H
191