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