clang 18.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 return Modules.lookup(File);
63}
64
65std::unique_ptr<llvm::MemoryBuffer>
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
74static 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
85static 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,
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.
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 && FileName != "-") {
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, Generation);
167 NewModule->Index = Chain.size();
168 NewModule->FileName = FileName.str();
169 NewModule->File = Entry;
170 NewModule->ImportLoc = ImportLoc;
171 NewModule->InputFilesValidationTimestamp = 0;
172
173 if (NewModule->Kind == MK_ImplicitModule) {
174 std::string TimestampFilename = NewModule->getTimestampFilename();
175 llvm::vfs::Status Status;
176 // A cached stat value would be fine as well.
177 if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
178 NewModule->InputFilesValidationTimestamp =
179 llvm::sys::toTimeT(Status.getLastModificationTime());
180 }
181
182 // Load the contents of the module
183 if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
184 // The buffer was already provided for us.
185 NewModule->Buffer = &ModuleCache->addBuiltPCM(FileName, std::move(Buffer));
186 // Since the cached buffer is reused, it is safe to close the file
187 // descriptor that was opened while stat()ing the PCM in
188 // lookupModuleFile() above, it won't be needed any longer.
189 Entry->closeFile();
190 } else if (llvm::MemoryBuffer *Buffer =
191 getModuleCache().lookupPCM(FileName)) {
192 NewModule->Buffer = Buffer;
193 // As above, the file descriptor is no longer needed.
194 Entry->closeFile();
195 } else if (getModuleCache().shouldBuildPCM(FileName)) {
196 // Report that the module is out of date, since we tried (and failed) to
197 // import it earlier.
198 Entry->closeFile();
199 return OutOfDate;
200 } else {
201 // Open the AST file.
202 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
203 if (FileName == "-") {
204 Buf = llvm::MemoryBuffer::getSTDIN();
205 } else {
206 // Get a buffer of the file and close the file descriptor when done.
207 // The file is volatile because in a parallel build we expect multiple
208 // compiler processes to use the same module file rebuilding it if needed.
209 //
210 // RequiresNullTerminator is false because module files don't need it, and
211 // this allows the file to still be mmapped.
212 Buf = FileMgr.getBufferForFile(*NewModule->File,
213 /*IsVolatile=*/true,
214 /*RequiresNullTerminator=*/false);
215 }
216
217 if (!Buf) {
218 ErrorStr = Buf.getError().message();
219 return Missing;
220 }
221
222 NewModule->Buffer = &getModuleCache().addPCM(FileName, std::move(*Buf));
223 }
224
225 // Initialize the stream.
226 NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
227
228 // Read the signature eagerly now so that we can check it. Avoid calling
229 // ReadSignature unless there's something to check though.
230 if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
231 ExpectedSignature, ErrorStr))
232 return OutOfDate;
233
234 // We're keeping this module. Store it everywhere.
235 Module = Modules[Entry] = NewModule.get();
236
237 updateModuleImports(*NewModule, ImportedBy, ImportLoc);
238
239 if (!NewModule->isModule())
240 PCHChain.push_back(NewModule.get());
241 if (!ImportedBy)
242 Roots.push_back(NewModule.get());
243
244 Chain.push_back(std::move(NewModule));
245 return NewlyLoaded;
246}
247
249 auto Last = end();
250 if (First == Last)
251 return;
252
253 // Explicitly clear VisitOrder since we might not notice it is stale.
254 VisitOrder.clear();
255
256 // Collect the set of module file pointers that we'll be removing.
258 (llvm::pointer_iterator<ModuleIterator>(First)),
259 (llvm::pointer_iterator<ModuleIterator>(Last)));
260
261 auto IsVictim = [&](ModuleFile *MF) {
262 return victimSet.count(MF);
263 };
264 // Remove any references to the now-destroyed modules.
265 for (auto I = begin(); I != First; ++I) {
266 I->Imports.remove_if(IsVictim);
267 I->ImportedBy.remove_if(IsVictim);
268 }
269 llvm::erase_if(Roots, IsVictim);
270
271 // Remove the modules from the PCH chain.
272 for (auto I = First; I != Last; ++I) {
273 if (!I->isModule()) {
274 PCHChain.erase(llvm::find(PCHChain, &*I), PCHChain.end());
275 break;
276 }
277 }
278
279 // Delete the modules.
280 for (ModuleIterator victim = First; victim != Last; ++victim)
281 Modules.erase(victim->File);
282
283 Chain.erase(Chain.begin() + (First - begin()), Chain.end());
284}
285
286void
288 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
289 const FileEntry *Entry =
290 FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
291 InMemoryBuffers[Entry] = std::move(Buffer);
292}
293
294std::unique_ptr<ModuleManager::VisitState> ModuleManager::allocateVisitState() {
295 // Fast path: if we have a cached state, use it.
296 if (FirstVisitState) {
297 auto Result = std::move(FirstVisitState);
298 FirstVisitState = std::move(Result->NextState);
299 return Result;
300 }
301
302 // Allocate and return a new state.
303 return std::make_unique<VisitState>(size());
304}
305
306void ModuleManager::returnVisitState(std::unique_ptr<VisitState> State) {
307 assert(State->NextState == nullptr && "Visited state is in list?");
308 State->NextState = std::move(FirstVisitState);
309 FirstVisitState = std::move(State);
310}
311
313 GlobalIndex = Index;
314 if (!GlobalIndex) {
315 ModulesInCommonWithGlobalIndex.clear();
316 return;
317 }
318
319 // Notify the global module index about all of the modules we've already
320 // loaded.
321 for (ModuleFile &M : *this)
322 if (!GlobalIndex->loadedModuleFile(&M))
323 ModulesInCommonWithGlobalIndex.push_back(&M);
324}
325
327 if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
328 return;
329
330 ModulesInCommonWithGlobalIndex.push_back(MF);
331}
332
334 InMemoryModuleCache &ModuleCache,
335 const PCHContainerReader &PCHContainerRdr,
336 const HeaderSearch &HeaderSearchInfo)
337 : FileMgr(FileMgr), ModuleCache(&ModuleCache),
338 PCHContainerRdr(PCHContainerRdr), HeaderSearchInfo(HeaderSearchInfo) {}
339
340void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
341 llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
342 // If the visitation order vector is the wrong size, recompute the order.
343 if (VisitOrder.size() != Chain.size()) {
344 unsigned N = size();
345 VisitOrder.clear();
346 VisitOrder.reserve(N);
347
348 // Record the number of incoming edges for each module. When we
349 // encounter a module with no incoming edges, push it into the queue
350 // to seed the queue.
352 Queue.reserve(N);
353 llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
354 UnusedIncomingEdges.resize(size());
355 for (ModuleFile &M : llvm::reverse(*this)) {
356 unsigned Size = M.ImportedBy.size();
357 UnusedIncomingEdges[M.Index] = Size;
358 if (!Size)
359 Queue.push_back(&M);
360 }
361
362 // Traverse the graph, making sure to visit a module before visiting any
363 // of its dependencies.
364 while (!Queue.empty()) {
365 ModuleFile *CurrentModule = Queue.pop_back_val();
366 VisitOrder.push_back(CurrentModule);
367
368 // For any module that this module depends on, push it on the
369 // stack (if it hasn't already been marked as visited).
370 for (ModuleFile *M : llvm::reverse(CurrentModule->Imports)) {
371 // Remove our current module as an impediment to visiting the
372 // module we depend on. If we were the last unvisited module
373 // that depends on this particular module, push it into the
374 // queue to be visited.
375 unsigned &NumUnusedEdges = UnusedIncomingEdges[M->Index];
376 if (NumUnusedEdges && (--NumUnusedEdges == 0))
377 Queue.push_back(M);
378 }
379 }
380
381 assert(VisitOrder.size() == N && "Visitation order is wrong?");
382
383 FirstVisitState = nullptr;
384 }
385
386 auto State = allocateVisitState();
387 unsigned VisitNumber = State->NextVisitNumber++;
388
389 // If the caller has provided us with a hit-set that came from the global
390 // module index, mark every module file in common with the global module
391 // index that is *not* in that set as 'visited'.
392 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
393 for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
394 {
395 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
396 if (!ModuleFilesHit->count(M))
397 State->VisitNumber[M->Index] = VisitNumber;
398 }
399 }
400
401 for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
402 ModuleFile *CurrentModule = VisitOrder[I];
403 // Should we skip this module file?
404 if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
405 continue;
406
407 // Visit the module.
408 assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
409 State->VisitNumber[CurrentModule->Index] = VisitNumber;
410 if (!Visitor(*CurrentModule))
411 continue;
412
413 // The visitor has requested that cut off visitation of any
414 // module that the current module depends on. To indicate this
415 // behavior, we mark all of the reachable modules as having been visited.
416 ModuleFile *NextModule = CurrentModule;
417 do {
418 // For any module that this module depends on, push it on the
419 // stack (if it hasn't already been marked as visited).
420 for (llvm::SetVector<ModuleFile *>::iterator
421 M = NextModule->Imports.begin(),
422 MEnd = NextModule->Imports.end();
423 M != MEnd; ++M) {
424 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
425 State->Stack.push_back(*M);
426 State->VisitNumber[(*M)->Index] = VisitNumber;
427 }
428 }
429
430 if (State->Stack.empty())
431 break;
432
433 // Pop the next module off the stack.
434 NextModule = State->Stack.pop_back_val();
435 } while (true);
436 }
437
438 returnVisitState(std::move(State));
439}
440
441bool ModuleManager::lookupModuleFile(StringRef FileName, off_t ExpectedSize,
442 time_t ExpectedModTime,
444 File = std::nullopt;
445 if (FileName == "-")
446 return false;
447
448 // Open the file immediately to ensure there is no race between stat'ing and
449 // opening the file.
450 OptionalFileEntryRef FileOrErr =
451 expectedToOptional(FileMgr.getFileRef(FileName, /*OpenFile=*/true,
452 /*CacheFailure=*/false));
453 if (!FileOrErr)
454 return false;
455
456 File = *FileOrErr;
457
458 if ((ExpectedSize && ExpectedSize != File->getSize()) ||
459 (ExpectedModTime && ExpectedModTime != File->getModificationTime()))
460 // Do not destroy File, as it may be referenced. If we need to rebuild it,
461 // it will be destroyed by removeModules.
462 return true;
463
464 return false;
465}
466
467#ifndef NDEBUG
468namespace llvm {
469
470 template<>
471 struct GraphTraits<ModuleManager> {
473 using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
474 using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
475
477 return Node->Imports.begin();
478 }
479
481 return Node->Imports.end();
482 }
483
484 static nodes_iterator nodes_begin(const ModuleManager &Manager) {
485 return nodes_iterator(Manager.begin());
486 }
487
488 static nodes_iterator nodes_end(const ModuleManager &Manager) {
489 return nodes_iterator(Manager.end());
490 }
491 };
492
493 template<>
494 struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
495 explicit DOTGraphTraits(bool IsSimple = false)
496 : DefaultDOTGraphTraits(IsSimple) {}
497
498 static bool renderGraphFromBottomUp() { return true; }
499
500 std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
501 return M->ModuleName;
502 }
503 };
504
505} // namespace llvm
506
508 llvm::ViewGraph(*this, "Modules");
509}
510#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)
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition: FileEntry.h:57
Cached information about one file (either on disk or in the virtual file system).
Definition: FileEntry.h:366
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.
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).
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:232
ModuleMap & getModuleMap()
Retrieve the module map.
Definition: HeaderSearch.h:808
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:827
Describes a module or submodule.
Definition: Module.h:105
Wrapper around OptionalFileEntryRef that degrades to 'const FileEntry*', facilitating incremental pat...
Definition: FileEntry.h:303
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:1602
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:194
llvm::SetVector< ModuleFile * > ImportedBy
List of modules which depend on this module.
Definition: ModuleFile.h:510
SourceLocation ImportLoc
The source location where this module was first imported.
Definition: ModuleFile.h:230
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 depends on.
Definition: ModuleFile.h:513
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.
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: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)