clang  19.0.0git
ModuleManager.cpp
Go to the documentation of this file.
1 //===- ModuleManager.cpp - Module Manager ---------------------------------===//
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 // This file defines the ModuleManager class, which manages a set of loaded
10 // modules for the ASTReader.
11 //
12 //===----------------------------------------------------------------------===//
13 
16 #include "clang/Basic/LLVM.h"
17 #include "clang/Lex/HeaderSearch.h"
18 #include "clang/Lex/ModuleMap.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SetVector.h"
25 #include "llvm/ADT/SmallPtrSet.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/ADT/iterator.h"
29 #include "llvm/Support/Chrono.h"
30 #include "llvm/Support/DOTGraphTraits.h"
31 #include "llvm/Support/ErrorOr.h"
32 #include "llvm/Support/GraphWriter.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/VirtualFileSystem.h"
35 #include <algorithm>
36 #include <cassert>
37 #include <memory>
38 #include <string>
39 #include <system_error>
40 
41 using namespace clang;
42 using namespace serialization;
43 
45  auto Entry = FileMgr.getFile(Name, /*OpenFile=*/false,
46  /*CacheFailure=*/false);
47  if (Entry)
48  return lookup(*Entry);
49 
50  return nullptr;
51 }
52 
54  if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
55  if (OptionalFileEntryRef File = Mod->getASTFile())
56  return lookup(*File);
57 
58  return nullptr;
59 }
60 
62  return Modules.lookup(File);
63 }
64 
65 std::unique_ptr<llvm::MemoryBuffer>
66 ModuleManager::lookupBuffer(StringRef Name) {
67  auto Entry = FileMgr.getFile(Name, /*OpenFile=*/false,
68  /*CacheFailure=*/false);
69  if (!Entry)
70  return nullptr;
71  return std::move(InMemoryBuffers[*Entry]);
72 }
73 
74 static bool checkSignature(ASTFileSignature Signature,
75  ASTFileSignature ExpectedSignature,
76  std::string &ErrorStr) {
77  if (!ExpectedSignature || Signature == ExpectedSignature)
78  return false;
79 
80  ErrorStr =
81  Signature ? "signature mismatch" : "could not read module signature";
82  return true;
83 }
84 
85 static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy,
86  SourceLocation ImportLoc) {
87  if (ImportedBy) {
88  MF.ImportedBy.insert(ImportedBy);
89  ImportedBy->Imports.insert(&MF);
90  } else {
91  if (!MF.DirectlyImported)
92  MF.ImportLoc = ImportLoc;
93 
94  MF.DirectlyImported = true;
95  }
96 }
97 
100  SourceLocation ImportLoc, ModuleFile *ImportedBy,
101  unsigned Generation,
102  off_t ExpectedSize, time_t ExpectedModTime,
103  ASTFileSignature ExpectedSignature,
104  ASTFileSignatureReader ReadSignature,
105  ModuleFile *&Module,
106  std::string &ErrorStr) {
107  Module = nullptr;
108 
109  // Look for the file entry. This only fails if the expected size or
110  // modification time differ.
111  OptionalFileEntryRef Entry;
113  // If we're not expecting to pull this file out of the module cache, it
114  // might have a different mtime due to being moved across filesystems in
115  // a distributed build. The size must still match, though. (As must the
116  // contents, but we can't check that.)
117  ExpectedModTime = 0;
118  }
119  // Note: ExpectedSize and ExpectedModTime will be 0 for MK_ImplicitModule
120  // when using an ASTFileSignature.
121  if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) {
122  ErrorStr = "module file out of date";
123  return OutOfDate;
124  }
125 
126  if (!Entry) {
127  ErrorStr = "module file not found";
128  return Missing;
129  }
130 
131  // The ModuleManager's use of FileEntry nodes as the keys for its map of
132  // loaded modules is less than ideal. Uniqueness for FileEntry nodes is
133  // maintained by FileManager, which in turn uses inode numbers on hosts
134  // that support that. When coupled with the module cache's proclivity for
135  // turning over and deleting stale PCMs, this means entries for different
136  // module files can wind up reusing the same underlying inode. When this
137  // happens, subsequent accesses to the Modules map will disagree on the
138  // ModuleFile associated with a given file. In general, it is not sufficient
139  // to resolve this conundrum with a type like FileEntryRef that stores the
140  // name of the FileEntry node on first access because of path canonicalization
141  // issues. However, the paths constructed for implicit module builds are
142  // fully under Clang's control. We *can*, therefore, rely on their structure
143  // being consistent across operating systems and across subsequent accesses
144  // to the Modules map.
145  auto implicitModuleNamesMatch = [](ModuleKind Kind, const ModuleFile *MF,
146  FileEntryRef Entry) -> bool {
147  if (Kind != MK_ImplicitModule)
148  return true;
149  return Entry.getName() == MF->FileName;
150  };
151 
152  // Check whether we already loaded this module, before
153  if (ModuleFile *ModuleEntry = Modules.lookup(*Entry)) {
154  if (implicitModuleNamesMatch(Type, ModuleEntry, *Entry)) {
155  // Check the stored signature.
156  if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
157  return OutOfDate;
158 
159  Module = ModuleEntry;
160  updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
161  return AlreadyLoaded;
162  }
163  }
164 
165  // Allocate a new module.
166  auto NewModule = std::make_unique<ModuleFile>(Type, *Entry, Generation);
167  NewModule->Index = Chain.size();
168  NewModule->FileName = FileName.str();
169  NewModule->ImportLoc = ImportLoc;
170  NewModule->InputFilesValidationTimestamp = 0;
171 
172  if (NewModule->Kind == MK_ImplicitModule) {
173  std::string TimestampFilename = NewModule->getTimestampFilename();
174  llvm::vfs::Status Status;
175  // A cached stat value would be fine as well.
176  if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
177  NewModule->InputFilesValidationTimestamp =
178  llvm::sys::toTimeT(Status.getLastModificationTime());
179  }
180 
181  // Load the contents of the module
182  if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
183  // The buffer was already provided for us.
184  NewModule->Buffer = &ModuleCache->addBuiltPCM(FileName, std::move(Buffer));
185  // Since the cached buffer is reused, it is safe to close the file
186  // descriptor that was opened while stat()ing the PCM in
187  // lookupModuleFile() above, it won't be needed any longer.
188  Entry->closeFile();
189  } else if (llvm::MemoryBuffer *Buffer =
190  getModuleCache().lookupPCM(FileName)) {
191  NewModule->Buffer = Buffer;
192  // As above, the file descriptor is no longer needed.
193  Entry->closeFile();
194  } else if (getModuleCache().shouldBuildPCM(FileName)) {
195  // Report that the module is out of date, since we tried (and failed) to
196  // import it earlier.
197  Entry->closeFile();
198  return OutOfDate;
199  } else {
200  // Get a buffer of the file and close the file descriptor when done.
201  // The file is volatile because in a parallel build we expect multiple
202  // compiler processes to use the same module file rebuilding it if needed.
203  //
204  // RequiresNullTerminator is false because module files don't need it, and
205  // this allows the file to still be mmapped.
206  auto Buf = FileMgr.getBufferForFile(NewModule->File,
207  /*IsVolatile=*/true,
208  /*RequiresNullTerminator=*/false);
209 
210  if (!Buf) {
211  ErrorStr = Buf.getError().message();
212  return Missing;
213  }
214 
215  NewModule->Buffer = &getModuleCache().addPCM(FileName, std::move(*Buf));
216  }
217 
218  // Initialize the stream.
219  NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
220 
221  // Read the signature eagerly now so that we can check it. Avoid calling
222  // ReadSignature unless there's something to check though.
223  if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
224  ExpectedSignature, ErrorStr))
225  return OutOfDate;
226 
227  // We're keeping this module. Store it everywhere.
228  Module = Modules[*Entry] = NewModule.get();
229 
230  updateModuleImports(*NewModule, ImportedBy, ImportLoc);
231 
232  if (!NewModule->isModule())
233  PCHChain.push_back(NewModule.get());
234  if (!ImportedBy)
235  Roots.push_back(NewModule.get());
236 
237  Chain.push_back(std::move(NewModule));
238  return NewlyLoaded;
239 }
240 
242  auto Last = end();
243  if (First == Last)
244  return;
245 
246  // Explicitly clear VisitOrder since we might not notice it is stale.
247  VisitOrder.clear();
248 
249  // Collect the set of module file pointers that we'll be removing.
251  (llvm::pointer_iterator<ModuleIterator>(First)),
252  (llvm::pointer_iterator<ModuleIterator>(Last)));
253 
254  auto IsVictim = [&](ModuleFile *MF) {
255  return victimSet.count(MF);
256  };
257  // Remove any references to the now-destroyed modules.
258  for (auto I = begin(); I != First; ++I) {
259  I->Imports.remove_if(IsVictim);
260  I->ImportedBy.remove_if(IsVictim);
261  }
262  llvm::erase_if(Roots, IsVictim);
263 
264  // Remove the modules from the PCH chain.
265  for (auto I = First; I != Last; ++I) {
266  if (!I->isModule()) {
267  PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
268  break;
269  }
270  }
271 
272  // Delete the modules.
273  for (ModuleIterator victim = First; victim != Last; ++victim)
274  Modules.erase(victim->File);
275 
276  Chain.erase(Chain.begin() + (First - begin()), Chain.end());
277 }
278 
279 void
281  std::unique_ptr<llvm::MemoryBuffer> Buffer) {
282  const FileEntry *Entry =
283  FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
284  InMemoryBuffers[Entry] = std::move(Buffer);
285 }
286 
287 std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
288  // Fast path: if we have a cached state, use it.
289  if (FirstVisitState) {
290  auto Result = std::move(FirstVisitState);
291  FirstVisitState = std::move(Result->NextState);
292  return Result;
293  }
294 
295  // Allocate and return a new state.
296  return std::make_unique<VisitState>(size());
297 }
298 
299 void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
300  assert(State->NextState == nullptr && "Visited state is in list?");
301  State->NextState = std::move(FirstVisitState);
302  FirstVisitState = std::move(State);
303 }
304 
306  GlobalIndex = Index;
307  if (!GlobalIndex) {
308  ModulesInCommonWithGlobalIndex.clear();
309  return;
310  }
311 
312  // Notify the global module index about all of the modules we've already
313  // loaded.
314  for (ModuleFile &M : *this)
315  if (!GlobalIndex->loadedModuleFile(&M))
316  ModulesInCommonWithGlobalIndex.push_back(&M);
317 }
318 
320  if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
321  return;
322 
323  ModulesInCommonWithGlobalIndex.push_back(MF);
324 }
325 
327  InMemoryModuleCache &ModuleCache,
328  const PCHContainerReader &PCHContainerRdr,
329  const HeaderSearch &HeaderSearchInfo)
330  : FileMgr(FileMgr), ModuleCache(&ModuleCache),
331  PCHContainerRdr(PCHContainerRdr), HeaderSearchInfo(HeaderSearchInfo) {}
332 
333 void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
334  llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
335  // If the visitation order vector is the wrong size, recompute the order.
336  if (VisitOrder.size() != Chain.size()) {
337  unsigned N = size();
338  VisitOrder.clear();
339  VisitOrder.reserve(N);
340 
341  // Record the number of incoming edges for each module. When we
342  // encounter a module with no incoming edges, push it into the queue
343  // to seed the queue.
345  Queue.reserve(N);
346  llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
347  UnusedIncomingEdges.resize(size());
348  for (ModuleFile &M : llvm::reverse(*this)) {
349  unsigned Size = M.ImportedBy.size();
350  UnusedIncomingEdges[M.Index] = Size;
351  if (!Size)
352  Queue.push_back(&M);
353  }
354 
355  // Traverse the graph, making sure to visit a module before visiting any
356  // of its dependencies.
357  while (!Queue.empty()) {
358  ModuleFile *CurrentModule = Queue.pop_back_val();
359  VisitOrder.push_back(CurrentModule);
360 
361  // For any module that this module depends on, push it on the
362  // stack (if it hasn't already been marked as visited).
363  for (ModuleFile *M : llvm::reverse(CurrentModule->Imports)) {
364  // Remove our current module as an impediment to visiting the
365  // module we depend on. If we were the last unvisited module
366  // that depends on this particular module, push it into the
367  // queue to be visited.
368  unsigned &NumUnusedEdges = UnusedIncomingEdges[M->Index];
369  if (NumUnusedEdges && (--NumUnusedEdges == 0))
370  Queue.push_back(M);
371  }
372  }
373 
374  assert(VisitOrder.size() == N && "Visitation order is wrong?");
375 
376  FirstVisitState = nullptr;
377  }
378 
379  auto State = allocateVisitState();
380  unsigned VisitNumber = State->NextVisitNumber++;
381 
382  // If the caller has provided us with a hit-set that came from the global
383  // module index, mark every module file in common with the global module
384  // index that is *not* in that set as 'visited'.
385  if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
386  for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
387  {
388  ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
389  if (!ModuleFilesHit->count(M))
390  State->VisitNumber[M->Index] = VisitNumber;
391  }
392  }
393 
394  for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
395  ModuleFile *CurrentModule = VisitOrder[I];
396  // Should we skip this module file?
397  if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
398  continue;
399 
400  // Visit the module.
401  assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
402  State->VisitNumber[CurrentModule->Index] = VisitNumber;
403  if (!Visitor(*CurrentModule))
404  continue;
405 
406  // The visitor has requested that cut off visitation of any
407  // module that the current module depends on. To indicate this
408  // behavior, we mark all of the reachable modules as having been visited.
409  ModuleFile *NextModule = CurrentModule;
410  do {
411  // For any module that this module depends on, push it on the
412  // stack (if it hasn't already been marked as visited).
413  for (llvm::SetVector<ModuleFile *>::iterator
414  M = NextModule->Imports.begin(),
415  MEnd = NextModule->Imports.end();
416  M != MEnd; ++M) {
417  if (State->VisitNumber[(*M)->Index] != VisitNumber) {
418  State->Stack.push_back(*M);
419  State->VisitNumber[(*M)->Index] = VisitNumber;
420  }
421  }
422 
423  if (State->Stack.empty())
424  break;
425 
426  // Pop the next module off the stack.
427  NextModule = State->Stack.pop_back_val();
428  } while (true);
429  }
430 
431  returnVisitState(std::move(State));
432 }
433 
434 bool ModuleManager::lookupModuleFile(StringRef FileName, off_t ExpectedSize,
435  time_t ExpectedModTime,
436  OptionalFileEntryRef &File) {
437  if (FileName == "-") {
438  File = expectedToOptional(FileMgr.getSTDIN());
439  return false;
440  }
441 
442  // Open the file immediately to ensure there is no race between stat'ing and
443  // opening the file.
444  File = FileMgr.getOptionalFileRef(FileName, /*OpenFile=*/true,
445  /*CacheFailure=*/false);
446 
447  if (File &&
448  ((ExpectedSize && ExpectedSize != File->getSize()) ||
449  (ExpectedModTime && ExpectedModTime != File->getModificationTime())))
450  // Do not destroy File, as it may be referenced. If we need to rebuild it,
451  // it will be destroyed by removeModules.
452  return true;
453 
454  return false;
455 }
456 
457 #ifndef NDEBUG
458 namespace llvm {
459 
460  template<>
461  struct GraphTraits<ModuleManager> {
462  using NodeRef = ModuleFile *;
463  using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
464  using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
465 
467  return Node->Imports.begin();
468  }
469 
471  return Node->Imports.end();
472  }
473 
474  static nodes_iterator nodes_begin(const ModuleManager &Manager) {
475  return nodes_iterator(Manager.begin());
476  }
477 
478  static nodes_iterator nodes_end(const ModuleManager &Manager) {
479  return nodes_iterator(Manager.end());
480  }
481  };
482 
483  template<>
484  struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
485  explicit DOTGraphTraits(bool IsSimple = false)
486  : DefaultDOTGraphTraits(IsSimple) {}
487 
488  static bool renderGraphFromBottomUp() { return true; }
489 
490  std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
491  return M->ModuleName;
492  }
493  };
494 
495 } // namespace llvm
496 
498  llvm::ViewGraph(*this, "Modules");
499 }
500 #endif
DynTypedNode Node
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool checkSignature(ASTFileSignature Signature, ASTFileSignature ExpectedSignature, std::string &ErrorStr)
static void updateModuleImports(ModuleFile &MF, ModuleFile *ImportedBy, SourceLocation ImportLoc)
LineState State
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition: FileEntry.h:57
void closeFile() const
Definition: FileEntry.h:354
Cached information about one file (either on disk or in the virtual file system).
Definition: FileEntry.h:300
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
std::error_code getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result)
Get the 'stat' information for the given Path.
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
Definition: FileManager.h:240
llvm::Expected< FileEntryRef > getSTDIN()
Get the FileEntryRef for stdin, returning an error if stdin cannot be read.
const FileEntry * getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime)
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
llvm::ErrorOr< const FileEntry * > getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
A global index for a set of module files, providing information about the identifiers within those mo...
bool loadedModuleFile(ModuleFile *File)
Note that the given module file has been loaded.
Encapsulates the information needed to find the file referenced by a #include or #include_next,...
Definition: HeaderSearch.h:253
ModuleMap & getModuleMap()
Retrieve the module map.
Definition: HeaderSearch.h:837
In-memory cache for modules.
llvm::MemoryBuffer & addPCM(llvm::StringRef Filename, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Store the PCM under the Filename.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
Definition: ModuleMap.cpp:826
Describes a module or submodule.
Definition: Module.h:105
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const =0
Returns the serialized AST inside the PCH container Buffer.
Encodes a location in the source.
The base class of the type hierarchy.
Definition: Type.h:1813
Information about a module that has been loaded by the ASTReader.
Definition: ModuleFile.h:124
bool DirectlyImported
Whether this module has been directly imported by the user.
Definition: ModuleFile.h:197
llvm::SetVector< ModuleFile * > ImportedBy
List of modules which depend on this module.
Definition: ModuleFile.h:509
SourceLocation ImportLoc
The source location where this module was first imported.
Definition: ModuleFile.h:233
unsigned Index
The index of this module in the list of modules.
Definition: ModuleFile.h:133
llvm::SetVector< ModuleFile * > Imports
List of modules which this module directly imported.
Definition: ModuleFile.h:512
std::string ModuleName
The name of the module.
Definition: ModuleFile.h:142
Manages the set of modules loaded by an AST reader.
Definition: ModuleManager.h:47
ModuleManager(FileManager &FileMgr, InMemoryModuleCache &ModuleCache, const PCHContainerReader &PCHContainerRdr, const HeaderSearch &HeaderSearchInfo)
bool lookupModuleFile(StringRef FileName, off_t ExpectedSize, time_t ExpectedModTime, OptionalFileEntryRef &File)
Attempt to resolve the given module file name to a file entry.
AddModuleResult
The result of attempting to add a new module.
@ Missing
The module file is missing.
@ OutOfDate
The module file is out-of-date.
@ NewlyLoaded
The module file was just loaded in response to this call.
@ AlreadyLoaded
The module file had already been loaded.
void moduleFileAccepted(ModuleFile *MF)
Notification from the AST reader that the given module file has been "accepted", and will not (can no...
ModuleFile * lookup(const FileEntry *File) const
Returns the module associated with the given module file.
void viewGraph()
View the graphviz representation of the module graph.
ModuleIterator begin()
Forward iterator to traverse all loaded modules.
void setGlobalIndex(GlobalModuleIndex *Index)
Set the global module index.
ModuleFile * lookupByFileName(StringRef FileName) const
Returns the module associated with the given file name.
void removeModules(ModuleIterator First)
Remove the modules starting from First (to the end).
ModuleIterator end()
Forward iterator end-point to traverse all loaded modules.
std::unique_ptr< llvm::MemoryBuffer > lookupBuffer(StringRef Name)
Returns the in-memory (virtual file) buffer with the given name.
void addInMemoryBuffer(StringRef FileName, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Add an in-memory buffer the list of known buffers.
InMemoryModuleCache & getModuleCache() const
void visit(llvm::function_ref< bool(ModuleFile &M)> Visitor, llvm::SmallPtrSetImpl< ModuleFile * > *ModuleFilesHit=nullptr)
Visit each of the modules.
unsigned size() const
Number of modules loaded.
AddModuleResult addModule(StringRef FileName, ModuleKind Type, SourceLocation ImportLoc, ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, ASTFileSignature ExpectedSignature, ASTFileSignatureReader ReadSignature, ModuleFile *&Module, std::string &ErrorStr)
Attempts to create a new module and add it to the list of known modules.
ASTFileSignature(*)(StringRef) ASTFileSignatureReader
llvm::pointee_iterator< SmallVectorImpl< std::unique_ptr< ModuleFile > >::iterator > ModuleIterator
ModuleFile * lookupByModuleName(StringRef ModName) const
Returns the module associated with the given module name.
ModuleKind
Specifies the kind of module that has been loaded.
Definition: ModuleFile.h:42
@ MK_ExplicitModule
File is an explicitly-loaded module.
Definition: ModuleFile.h:47
@ MK_ImplicitModule
File is an implicitly-loaded module.
Definition: ModuleFile.h:44
@ MK_PrebuiltModule
File is from a prebuilt module path.
Definition: ModuleFile.h:59
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
The signature of a module, which is a hash of the AST content.
Definition: Module.h:57
std::string getNodeLabel(ModuleFile *M, const ModuleManager &)
static ChildIteratorType child_end(NodeRef Node)
static nodes_iterator nodes_begin(const ModuleManager &Manager)
static ChildIteratorType child_begin(NodeRef Node)
pointer_iterator< ModuleManager::ModuleConstIterator > nodes_iterator
llvm::SetVector< ModuleFile * >::const_iterator ChildIteratorType
static nodes_iterator nodes_end(const ModuleManager &Manager)