xref: /llvm-project/clang/lib/Lex/ModuleMap.cpp (revision d28d1b8dc02578f48e8363db4fa0632a4fd79666)
1 //===--- ModuleMap.cpp - Describe the layout of modules ---------*- 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 // This file defines the ModuleMap implementation, which describes the layout
11 // of a module as it relates to headers.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/Lex/ModuleMap.h"
15 #include "clang/Lex/Lexer.h"
16 #include "clang/Lex/LiteralSupport.h"
17 #include "clang/Lex/LexDiagnostic.h"
18 #include "clang/Basic/Diagnostic.h"
19 #include "clang/Basic/FileManager.h"
20 #include "clang/Basic/TargetInfo.h"
21 #include "clang/Basic/TargetOptions.h"
22 #include "llvm/Support/Allocator.h"
23 #include "llvm/Support/Host.h"
24 #include "llvm/Support/PathV2.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/ADT/StringSwitch.h"
28 using namespace clang;
29 
30 //----------------------------------------------------------------------------//
31 // Module
32 //----------------------------------------------------------------------------//
33 
34 ModuleMap::Module::~Module() {
35   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
36                                         IEnd = SubModules.end();
37        I != IEnd; ++I) {
38     delete I->getValue();
39   }
40 
41 }
42 
43 std::string ModuleMap::Module::getFullModuleName() const {
44   llvm::SmallVector<StringRef, 2> Names;
45 
46   // Build up the set of module names (from innermost to outermost).
47   for (const Module *M = this; M; M = M->Parent)
48     Names.push_back(M->Name);
49 
50   std::string Result;
51   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
52                                                       IEnd = Names.rend();
53        I != IEnd; ++I) {
54     if (!Result.empty())
55       Result += '.';
56 
57     Result += *I;
58   }
59 
60   return Result;
61 }
62 
63 StringRef ModuleMap::Module::getTopLevelModuleName() const {
64   const Module *Top = this;
65   while (Top->Parent)
66     Top = Top->Parent;
67 
68   return Top->Name;
69 }
70 
71 static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
72   OS << std::string(' ', Spaces);
73 }
74 
75 void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
76   indent(OS, Indent);
77   if (IsFramework)
78     OS << "framework ";
79   if (IsExplicit)
80     OS << "explicit ";
81   OS << Name << " {\n";
82 
83   if (UmbrellaHeader) {
84     indent(OS, Indent + 2);
85     OS << "umbrella \"" << UmbrellaHeader->getName() << "\"\n";
86   }
87 
88   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
89     indent(OS, Indent + 2);
90     OS << "header \"" << Headers[I]->getName() << "\"\n";
91   }
92 
93   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
94                                               MIEnd = SubModules.end();
95        MI != MIEnd; ++MI)
96     MI->getValue()->print(OS, Indent + 2);
97 
98   indent(OS, Indent);
99   OS << "}\n";
100 }
101 
102 void ModuleMap::Module::dump() const {
103   print(llvm::errs());
104 }
105 
106 //----------------------------------------------------------------------------//
107 // Module map
108 //----------------------------------------------------------------------------//
109 
110 ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
111   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
112   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
113             new DiagnosticsEngine(DiagIDs));
114   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
115   SourceMgr = new SourceManager(*Diags, FileMgr);
116 }
117 
118 ModuleMap::~ModuleMap() {
119   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
120                                         IEnd = Modules.end();
121        I != IEnd; ++I) {
122     delete I->getValue();
123   }
124 
125   delete SourceMgr;
126 }
127 
128 ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
129   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
130     = Headers.find(File);
131   if (Known != Headers.end())
132     return Known->second;
133 
134   const DirectoryEntry *Dir = File->getDir();
135   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
136     = UmbrellaDirs.find(Dir);
137   if (KnownDir != UmbrellaDirs.end())
138     return KnownDir->second;
139 
140   // Walk up the directory hierarchy looking for umbrella headers.
141   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
142   StringRef DirName = Dir->getName();
143   do {
144     // Retrieve our parent path.
145     DirName = llvm::sys::path::parent_path(DirName);
146     if (DirName.empty())
147       break;
148 
149     // Resolve the parent path to a directory entry.
150     Dir = SourceMgr->getFileManager().getDirectory(DirName);
151     if (!Dir)
152       break;
153 
154     KnownDir = UmbrellaDirs.find(Dir);
155     if (KnownDir != UmbrellaDirs.end()) {
156       Module *Result = KnownDir->second;
157 
158       // Record each of the directories we stepped through as being part of
159       // the module we found, since the umbrella header covers them all.
160       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
161         UmbrellaDirs[SkippedDirs[I]] = Result;
162 
163       return Result;
164     }
165 
166     SkippedDirs.push_back(Dir);
167   } while (true);
168 
169   return 0;
170 }
171 
172 ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
173   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
174   if (Known != Modules.end())
175     return Known->getValue();
176 
177   return 0;
178 }
179 
180 ModuleMap::Module *
181 ModuleMap::inferFrameworkModule(StringRef ModuleName,
182                                 const DirectoryEntry *FrameworkDir) {
183   // Check whether we've already found this module.
184   if (Module *Module = findModule(ModuleName))
185     return Module;
186 
187   // Look for an umbrella header.
188   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
189   llvm::sys::path::append(UmbrellaName, "Headers");
190   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
191   const FileEntry *UmbrellaHeader
192     = SourceMgr->getFileManager().getFile(UmbrellaName);
193 
194   // FIXME: If there's no umbrella header, we could probably scan the
195   // framework to load *everything*. But, it's not clear that this is a good
196   // idea.
197   if (!UmbrellaHeader)
198     return 0;
199 
200   Module *Result = new Module(ModuleName, SourceLocation(),
201                               /*IsFramework=*/true);
202   Result->UmbrellaHeader = UmbrellaHeader;
203   Headers[UmbrellaHeader] = Result;
204   UmbrellaDirs[FrameworkDir] = Result;
205   Modules[ModuleName] = Result;
206   return Result;
207 }
208 
209 void ModuleMap::dump() {
210   llvm::errs() << "Modules:";
211   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
212                                         MEnd = Modules.end();
213        M != MEnd; ++M)
214     M->getValue()->print(llvm::errs(), 2);
215 
216   llvm::errs() << "Headers:";
217   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
218             H = Headers.begin(),
219          HEnd = Headers.end();
220        H != HEnd; ++H) {
221     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
222                  << H->second->getFullModuleName() << "\n";
223   }
224 }
225 
226 //----------------------------------------------------------------------------//
227 // Module map file parser
228 //----------------------------------------------------------------------------//
229 
230 namespace clang {
231   /// \brief A token in a module map file.
232   struct MMToken {
233     enum TokenKind {
234       EndOfFile,
235       HeaderKeyword,
236       Identifier,
237       ExplicitKeyword,
238       FrameworkKeyword,
239       ModuleKeyword,
240       UmbrellaKeyword,
241       StringLiteral,
242       LBrace,
243       RBrace
244     } Kind;
245 
246     unsigned Location;
247     unsigned StringLength;
248     const char *StringData;
249 
250     void clear() {
251       Kind = EndOfFile;
252       Location = 0;
253       StringLength = 0;
254       StringData = 0;
255     }
256 
257     bool is(TokenKind K) const { return Kind == K; }
258 
259     SourceLocation getLocation() const {
260       return SourceLocation::getFromRawEncoding(Location);
261     }
262 
263     StringRef getString() const {
264       return StringRef(StringData, StringLength);
265     }
266   };
267 
268   class ModuleMapParser {
269     Lexer &L;
270     SourceManager &SourceMgr;
271     DiagnosticsEngine &Diags;
272     ModuleMap &Map;
273 
274     /// \brief The directory that this module map resides in.
275     const DirectoryEntry *Directory;
276 
277     /// \brief Whether an error occurred.
278     bool HadError;
279 
280     /// \brief Default target information, used only for string literal
281     /// parsing.
282     TargetInfo *Target;
283 
284     /// \brief Stores string data for the various string literals referenced
285     /// during parsing.
286     llvm::BumpPtrAllocator StringData;
287 
288     /// \brief The current token.
289     MMToken Tok;
290 
291     /// \brief The active module.
292     ModuleMap::Module *ActiveModule;
293 
294     /// \brief Consume the current token and return its location.
295     SourceLocation consumeToken();
296 
297     /// \brief Skip tokens until we reach the a token with the given kind
298     /// (or the end of the file).
299     void skipUntil(MMToken::TokenKind K);
300 
301     void parseModuleDecl();
302     void parseUmbrellaDecl();
303     void parseHeaderDecl();
304 
305   public:
306     typedef ModuleMap::Module Module;
307 
308     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
309                              DiagnosticsEngine &Diags,
310                              ModuleMap &Map,
311                              const DirectoryEntry *Directory)
312       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
313         Directory(Directory), HadError(false), ActiveModule(0)
314     {
315       TargetOptions TargetOpts;
316       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
317       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
318 
319       Tok.clear();
320       consumeToken();
321     }
322 
323     bool parseModuleMapFile();
324   };
325 }
326 
327 SourceLocation ModuleMapParser::consumeToken() {
328 retry:
329   SourceLocation Result = Tok.getLocation();
330   Tok.clear();
331 
332   Token LToken;
333   L.LexFromRawLexer(LToken);
334   Tok.Location = LToken.getLocation().getRawEncoding();
335   switch (LToken.getKind()) {
336   case tok::raw_identifier:
337     Tok.StringData = LToken.getRawIdentifierData();
338     Tok.StringLength = LToken.getLength();
339     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
340                  .Case("header", MMToken::HeaderKeyword)
341                  .Case("explicit", MMToken::ExplicitKeyword)
342                  .Case("framework", MMToken::FrameworkKeyword)
343                  .Case("module", MMToken::ModuleKeyword)
344                  .Case("umbrella", MMToken::UmbrellaKeyword)
345                  .Default(MMToken::Identifier);
346     break;
347 
348   case tok::eof:
349     Tok.Kind = MMToken::EndOfFile;
350     break;
351 
352   case tok::l_brace:
353     Tok.Kind = MMToken::LBrace;
354     break;
355 
356   case tok::r_brace:
357     Tok.Kind = MMToken::RBrace;
358     break;
359 
360   case tok::string_literal: {
361     // Parse the string literal.
362     LangOptions LangOpts;
363     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
364     if (StringLiteral.hadError)
365       goto retry;
366 
367     // Copy the string literal into our string data allocator.
368     unsigned Length = StringLiteral.GetStringLength();
369     char *Saved = StringData.Allocate<char>(Length + 1);
370     memcpy(Saved, StringLiteral.GetString().data(), Length);
371     Saved[Length] = 0;
372 
373     // Form the token.
374     Tok.Kind = MMToken::StringLiteral;
375     Tok.StringData = Saved;
376     Tok.StringLength = Length;
377     break;
378   }
379 
380   case tok::comment:
381     goto retry;
382 
383   default:
384     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
385     HadError = true;
386     goto retry;
387   }
388 
389   return Result;
390 }
391 
392 void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
393   unsigned braceDepth = 0;
394   do {
395     switch (Tok.Kind) {
396     case MMToken::EndOfFile:
397       return;
398 
399     case MMToken::LBrace:
400       if (Tok.is(K) && braceDepth == 0)
401         return;
402 
403       ++braceDepth;
404       break;
405 
406     case MMToken::RBrace:
407       if (braceDepth > 0)
408         --braceDepth;
409       else if (Tok.is(K))
410         return;
411       break;
412 
413     default:
414       if (braceDepth == 0 && Tok.is(K))
415         return;
416       break;
417     }
418 
419    consumeToken();
420   } while (true);
421 }
422 
423 /// \brief Parse a module declaration.
424 ///
425 ///   module-declaration:
426 ///     'framework'[opt] 'module' identifier { module-member* }
427 ///
428 ///   module-member:
429 ///     umbrella-declaration
430 ///     header-declaration
431 ///     'explicit'[opt] module-declaration
432 void ModuleMapParser::parseModuleDecl() {
433   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
434          Tok.is(MMToken::FrameworkKeyword));
435 
436   // Parse 'framework' or 'explicit' keyword, if present.
437   bool Framework = false;
438   bool Explicit = false;
439 
440   if (Tok.is(MMToken::FrameworkKeyword)) {
441     consumeToken();
442     Framework = true;
443   }
444   // Parse 'explicit' keyword, if present.
445   else if (Tok.is(MMToken::ExplicitKeyword)) {
446     consumeToken();
447     Explicit = true;
448   }
449 
450   // Parse 'module' keyword.
451   if (!Tok.is(MMToken::ModuleKeyword)) {
452     Diags.Report(Tok.getLocation(),
453                  diag::err_mmap_expected_module_after_explicit);
454     consumeToken();
455     HadError = true;
456     return;
457   }
458   consumeToken(); // 'module' keyword
459 
460   // Parse the module name.
461   if (!Tok.is(MMToken::Identifier)) {
462     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
463     HadError = true;
464     return;
465   }
466   StringRef ModuleName = Tok.getString();
467   SourceLocation ModuleNameLoc = consumeToken();
468 
469   // Parse the opening brace.
470   if (!Tok.is(MMToken::LBrace)) {
471     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
472       << ModuleName;
473     HadError = true;
474     return;
475   }
476   SourceLocation LBraceLoc = consumeToken();
477 
478   // Determine whether this (sub)module has already been defined.
479   llvm::StringMap<Module *> &ModuleSpace
480     = ActiveModule? ActiveModule->SubModules : Map.Modules;
481   llvm::StringMap<Module *>::iterator ExistingModule
482     = ModuleSpace.find(ModuleName);
483   if (ExistingModule != ModuleSpace.end()) {
484     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
485       << ModuleName;
486     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
487                  diag::note_mmap_prev_definition);
488 
489     // Skip the module definition.
490     skipUntil(MMToken::RBrace);
491     if (Tok.is(MMToken::RBrace))
492       consumeToken();
493 
494     HadError = true;
495     return;
496   }
497 
498   // Start defining this module.
499   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
500                             Explicit);
501   ModuleSpace[ModuleName] = ActiveModule;
502 
503   bool Done = false;
504   do {
505     switch (Tok.Kind) {
506     case MMToken::EndOfFile:
507     case MMToken::RBrace:
508       Done = true;
509       break;
510 
511     case MMToken::ExplicitKeyword:
512     case MMToken::ModuleKeyword:
513       parseModuleDecl();
514       break;
515 
516     case MMToken::HeaderKeyword:
517       parseHeaderDecl();
518       break;
519 
520     case MMToken::UmbrellaKeyword:
521       parseUmbrellaDecl();
522       break;
523 
524     default:
525       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
526       consumeToken();
527       break;
528     }
529   } while (!Done);
530 
531   if (Tok.is(MMToken::RBrace))
532     consumeToken();
533   else {
534     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
535     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
536     HadError = true;
537   }
538 
539   // We're done parsing this module. Pop back to our parent scope.
540   ActiveModule = ActiveModule->Parent;
541 }
542 
543 /// \brief Parse an umbrella header declaration.
544 ///
545 ///   umbrella-declaration:
546 ///     'umbrella' string-literal
547 void ModuleMapParser::parseUmbrellaDecl() {
548   assert(Tok.is(MMToken::UmbrellaKeyword));
549   SourceLocation UmbrellaLoc = consumeToken();
550 
551   // Parse the header name.
552   if (!Tok.is(MMToken::StringLiteral)) {
553     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
554       << "umbrella";
555     HadError = true;
556     return;
557   }
558   StringRef FileName = Tok.getString();
559   SourceLocation FileNameLoc = consumeToken();
560 
561   // Check whether we already have an umbrella header.
562   if (ActiveModule->UmbrellaHeader) {
563     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
564       << ActiveModule->getFullModuleName()
565       << ActiveModule->UmbrellaHeader->getName();
566     HadError = true;
567     return;
568   }
569 
570   // Only top-level modules can have umbrella headers.
571   if (ActiveModule->Parent) {
572     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
573       << ActiveModule->getFullModuleName();
574     HadError = true;
575     return;
576   }
577 
578   // Look for this file.
579   llvm::SmallString<128> PathName;
580   PathName += Directory->getName();
581   unsigned PathLength = PathName.size();
582   const FileEntry *File = 0;
583   if (ActiveModule->isPartOfFramework()) {
584     // Check whether this file is in the public headers.
585     llvm::sys::path::append(PathName, "Headers");
586     llvm::sys::path::append(PathName, FileName);
587     File = SourceMgr.getFileManager().getFile(PathName);
588 
589     if (!File) {
590       // Check whether this file is in the private headers.
591       PathName.resize(PathLength);
592       llvm::sys::path::append(PathName, "PrivateHeaders");
593       llvm::sys::path::append(PathName, FileName);
594       File = SourceMgr.getFileManager().getFile(PathName);
595     }
596 
597     // FIXME: Deal with subframeworks.
598   } else {
599     // Lookup for normal headers.
600     llvm::sys::path::append(PathName, FileName);
601     File = SourceMgr.getFileManager().getFile(PathName);
602   }
603 
604   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
605   // Come up with a lazy way to do this.
606   if (File) {
607     if (const Module *OwningModule = Map.Headers[File]) {
608       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
609         << FileName << OwningModule->getFullModuleName();
610       HadError = true;
611     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
612       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
613         << OwningModule->getFullModuleName();
614       HadError = true;
615     } else {
616       // Record this umbrella header.
617       ActiveModule->UmbrellaHeader = File;
618       Map.Headers[File] = ActiveModule;
619       Map.UmbrellaDirs[Directory] = ActiveModule;
620     }
621   } else {
622     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
623       << true << FileName;
624     HadError = true;
625   }
626 }
627 
628 /// \brief Parse a header declaration.
629 ///
630 ///   header-declaration:
631 ///     'header' string-literal
632 void ModuleMapParser::parseHeaderDecl() {
633   assert(Tok.is(MMToken::HeaderKeyword));
634   consumeToken();
635 
636   // Parse the header name.
637   if (!Tok.is(MMToken::StringLiteral)) {
638     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
639       << "header";
640     HadError = true;
641     return;
642   }
643   StringRef FileName = Tok.getString();
644   SourceLocation FileNameLoc = consumeToken();
645 
646   // Look for this file.
647   llvm::SmallString<128> PathName;
648   PathName += Directory->getName();
649 
650   if (ActiveModule->isPartOfFramework())
651     llvm::sys::path::append(PathName, "Headers");
652 
653   llvm::sys::path::append(PathName, FileName);
654 
655   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
656   // Come up with a lazy way to do this.
657   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
658     if (const Module *OwningModule = Map.Headers[File]) {
659       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
660         << FileName << OwningModule->getFullModuleName();
661       HadError = true;
662     } else {
663       // Record this file.
664       ActiveModule->Headers.push_back(File);
665       Map.Headers[File] = ActiveModule;
666     }
667   } else {
668     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
669       << false << FileName;
670     HadError = true;
671   }
672 }
673 
674 /// \brief Parse a module map file.
675 ///
676 ///   module-map-file:
677 ///     module-declaration*
678 bool ModuleMapParser::parseModuleMapFile() {
679   do {
680     switch (Tok.Kind) {
681     case MMToken::EndOfFile:
682       return HadError;
683 
684     case MMToken::ModuleKeyword:
685     case MMToken::FrameworkKeyword:
686       parseModuleDecl();
687       break;
688 
689     case MMToken::ExplicitKeyword:
690     case MMToken::HeaderKeyword:
691     case MMToken::Identifier:
692     case MMToken::LBrace:
693     case MMToken::RBrace:
694     case MMToken::StringLiteral:
695     case MMToken::UmbrellaKeyword:
696       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
697       HadError = true;
698       consumeToken();
699       break;
700     }
701   } while (true);
702 
703   return HadError;
704 }
705 
706 bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
707   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
708   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
709   if (!Buffer)
710     return true;
711 
712   // Parse this module map file.
713   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
714   Diags->getClient()->BeginSourceFile(LangOpts);
715   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
716   bool Result = Parser.parseModuleMapFile();
717   Diags->getClient()->EndSourceFile();
718 
719   return Result;
720 }
721