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