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