1718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2718292f2SDouglas Gregor //
3718292f2SDouglas Gregor //                     The LLVM Compiler Infrastructure
4718292f2SDouglas Gregor //
5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6718292f2SDouglas Gregor // License. See LICENSE.TXT for details.
7718292f2SDouglas Gregor //
8718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
9718292f2SDouglas Gregor //
10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
11718292f2SDouglas Gregor // of a module as it relates to headers.
12718292f2SDouglas Gregor //
13718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15718292f2SDouglas Gregor #include "clang/Lex/Lexer.h"
16718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h"
17718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h"
18718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
19718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
20718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
21718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
22718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
23718292f2SDouglas Gregor #include "llvm/Support/Host.h"
245257fc63SDouglas Gregor #include "llvm/Support/PathV2.h"
25718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
26718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h"
27718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h"
28718292f2SDouglas Gregor using namespace clang;
29718292f2SDouglas Gregor 
30*2b82c2a5SDouglas Gregor Module::ExportDecl
31*2b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
32*2b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
33*2b82c2a5SDouglas Gregor                          bool Complain) {
34*2b82c2a5SDouglas Gregor   // Find the starting module.
35*2b82c2a5SDouglas Gregor   Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
36*2b82c2a5SDouglas Gregor   if (!Context) {
37*2b82c2a5SDouglas Gregor     if (Complain)
38*2b82c2a5SDouglas Gregor       Diags->Report(Unresolved.Id[0].second,
39*2b82c2a5SDouglas Gregor                     diag::err_mmap_missing_module_unqualified)
40*2b82c2a5SDouglas Gregor         << Unresolved.Id[0].first << Mod->getFullModuleName();
41*2b82c2a5SDouglas Gregor 
42*2b82c2a5SDouglas Gregor     return Module::ExportDecl();
43*2b82c2a5SDouglas Gregor   }
44*2b82c2a5SDouglas Gregor 
45*2b82c2a5SDouglas Gregor   // Dig into the module path.
46*2b82c2a5SDouglas Gregor   for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
47*2b82c2a5SDouglas Gregor     Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
48*2b82c2a5SDouglas Gregor                                         Context);
49*2b82c2a5SDouglas Gregor     if (!Sub) {
50*2b82c2a5SDouglas Gregor       if (Complain)
51*2b82c2a5SDouglas Gregor         Diags->Report(Unresolved.Id[I].second,
52*2b82c2a5SDouglas Gregor                       diag::err_mmap_missing_module_qualified)
53*2b82c2a5SDouglas Gregor           << Unresolved.Id[I].first << Context->getFullModuleName()
54*2b82c2a5SDouglas Gregor           << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
55*2b82c2a5SDouglas Gregor 
56*2b82c2a5SDouglas Gregor       return Module::ExportDecl();
57*2b82c2a5SDouglas Gregor     }
58*2b82c2a5SDouglas Gregor 
59*2b82c2a5SDouglas Gregor     Context = Sub;
60*2b82c2a5SDouglas Gregor   }
61*2b82c2a5SDouglas Gregor 
62*2b82c2a5SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
63*2b82c2a5SDouglas Gregor }
64*2b82c2a5SDouglas Gregor 
65718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
66718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
67718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
68718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
69718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
70718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
71718292f2SDouglas Gregor }
72718292f2SDouglas Gregor 
73718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
745acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
755acdf59eSDouglas Gregor                                         IEnd = Modules.end();
765acdf59eSDouglas Gregor        I != IEnd; ++I) {
775acdf59eSDouglas Gregor     delete I->getValue();
785acdf59eSDouglas Gregor   }
795acdf59eSDouglas Gregor 
80718292f2SDouglas Gregor   delete SourceMgr;
81718292f2SDouglas Gregor }
82718292f2SDouglas Gregor 
83de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
84ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
85ab0c8a84SDouglas Gregor     = Headers.find(File);
86ab0c8a84SDouglas Gregor   if (Known != Headers.end())
87ab0c8a84SDouglas Gregor     return Known->second;
88ab0c8a84SDouglas Gregor 
89b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
90b65dbfffSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
91b65dbfffSDouglas Gregor     = UmbrellaDirs.find(Dir);
92b65dbfffSDouglas Gregor   if (KnownDir != UmbrellaDirs.end())
93b65dbfffSDouglas Gregor     return KnownDir->second;
94b65dbfffSDouglas Gregor 
95b65dbfffSDouglas Gregor   // Walk up the directory hierarchy looking for umbrella headers.
96b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
97b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
98b65dbfffSDouglas Gregor   do {
99b65dbfffSDouglas Gregor     // Retrieve our parent path.
100b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
101b65dbfffSDouglas Gregor     if (DirName.empty())
102b65dbfffSDouglas Gregor       break;
103b65dbfffSDouglas Gregor 
104b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
105b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
106b65dbfffSDouglas Gregor     if (!Dir)
107b65dbfffSDouglas Gregor       break;
108b65dbfffSDouglas Gregor 
109b65dbfffSDouglas Gregor     KnownDir = UmbrellaDirs.find(Dir);
110b65dbfffSDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
111b65dbfffSDouglas Gregor       Module *Result = KnownDir->second;
112b65dbfffSDouglas Gregor 
113b65dbfffSDouglas Gregor       // Record each of the directories we stepped through as being part of
114b65dbfffSDouglas Gregor       // the module we found, since the umbrella header covers them all.
115b65dbfffSDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
116b65dbfffSDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
117b65dbfffSDouglas Gregor 
118b65dbfffSDouglas Gregor       return Result;
119b65dbfffSDouglas Gregor     }
120b65dbfffSDouglas Gregor 
121b65dbfffSDouglas Gregor     SkippedDirs.push_back(Dir);
122b65dbfffSDouglas Gregor   } while (true);
123b65dbfffSDouglas Gregor 
124ab0c8a84SDouglas Gregor   return 0;
125ab0c8a84SDouglas Gregor }
126ab0c8a84SDouglas Gregor 
127de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
12888bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
12988bdfb0eSDouglas Gregor   if (Known != Modules.end())
13088bdfb0eSDouglas Gregor     return Known->getValue();
13188bdfb0eSDouglas Gregor 
13288bdfb0eSDouglas Gregor   return 0;
13388bdfb0eSDouglas Gregor }
13488bdfb0eSDouglas Gregor 
135*2b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
136*2b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
137*2b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
138*2b82c2a5SDouglas Gregor       return Sub;
139*2b82c2a5SDouglas Gregor   }
140*2b82c2a5SDouglas Gregor 
141*2b82c2a5SDouglas Gregor   return findModule(Name);
142*2b82c2a5SDouglas Gregor }
143*2b82c2a5SDouglas Gregor 
144*2b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
145*2b82c2a5SDouglas Gregor   if (!Context)
146*2b82c2a5SDouglas Gregor     return findModule(Name);
147*2b82c2a5SDouglas Gregor 
148*2b82c2a5SDouglas Gregor   llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
149*2b82c2a5SDouglas Gregor   if (Sub != Context->SubModules.end())
150*2b82c2a5SDouglas Gregor     return Sub->getValue();
151*2b82c2a5SDouglas Gregor 
152*2b82c2a5SDouglas Gregor   return 0;
153*2b82c2a5SDouglas Gregor }
154*2b82c2a5SDouglas Gregor 
155de3ef502SDouglas Gregor std::pair<Module *, bool>
15669021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
15769021974SDouglas Gregor                               bool IsExplicit) {
15869021974SDouglas Gregor   // Try to find an existing module with this name.
15969021974SDouglas Gregor   if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
16069021974SDouglas Gregor     return std::make_pair(Found, false);
16169021974SDouglas Gregor 
16269021974SDouglas Gregor   // Create a new module with this name.
16369021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
16469021974SDouglas Gregor                               IsExplicit);
16569021974SDouglas Gregor   if (Parent)
16669021974SDouglas Gregor     Parent->SubModules[Name] = Result;
16769021974SDouglas Gregor   else
16869021974SDouglas Gregor     Modules[Name] = Result;
16969021974SDouglas Gregor   return std::make_pair(Result, true);
17069021974SDouglas Gregor }
17169021974SDouglas Gregor 
172de3ef502SDouglas Gregor Module *
17356c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
17456c64013SDouglas Gregor                                 const DirectoryEntry *FrameworkDir) {
17556c64013SDouglas Gregor   // Check whether we've already found this module.
17656c64013SDouglas Gregor   if (Module *Module = findModule(ModuleName))
17756c64013SDouglas Gregor     return Module;
17856c64013SDouglas Gregor 
17956c64013SDouglas Gregor   // Look for an umbrella header.
18056c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
18156c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
18256c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
18356c64013SDouglas Gregor   const FileEntry *UmbrellaHeader
18456c64013SDouglas Gregor     = SourceMgr->getFileManager().getFile(UmbrellaName);
18556c64013SDouglas Gregor 
18656c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
18756c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
18856c64013SDouglas Gregor   // idea.
18956c64013SDouglas Gregor   if (!UmbrellaHeader)
19056c64013SDouglas Gregor     return 0;
19156c64013SDouglas Gregor 
192755b2055SDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(),
193755b2055SDouglas Gregor                               /*IsFramework=*/true);
19456c64013SDouglas Gregor   Result->UmbrellaHeader = UmbrellaHeader;
19556c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
19656c64013SDouglas Gregor   UmbrellaDirs[FrameworkDir] = Result;
19756c64013SDouglas Gregor   Modules[ModuleName] = Result;
19856c64013SDouglas Gregor   return Result;
19956c64013SDouglas Gregor }
20056c64013SDouglas Gregor 
201514b636aSDouglas Gregor const FileEntry *
202de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
203514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
204514b636aSDouglas Gregor     return 0;
205514b636aSDouglas Gregor 
206514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
207514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
208514b636aSDouglas Gregor }
209514b636aSDouglas Gregor 
210718292f2SDouglas Gregor void ModuleMap::dump() {
211718292f2SDouglas Gregor   llvm::errs() << "Modules:";
212718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
213718292f2SDouglas Gregor                                         MEnd = Modules.end();
214718292f2SDouglas Gregor        M != MEnd; ++M)
215d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
216718292f2SDouglas Gregor 
217718292f2SDouglas Gregor   llvm::errs() << "Headers:";
218718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
219718292f2SDouglas Gregor             H = Headers.begin(),
220718292f2SDouglas Gregor          HEnd = Headers.end();
221718292f2SDouglas Gregor        H != HEnd; ++H) {
222718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
223718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
224718292f2SDouglas Gregor   }
225718292f2SDouglas Gregor }
226718292f2SDouglas Gregor 
227*2b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
228*2b82c2a5SDouglas Gregor   bool HadError = false;
229*2b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
230*2b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
231*2b82c2a5SDouglas Gregor                                               Complain);
232*2b82c2a5SDouglas Gregor     if (Export.getPointer())
233*2b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
234*2b82c2a5SDouglas Gregor     else
235*2b82c2a5SDouglas Gregor       HadError = true;
236*2b82c2a5SDouglas Gregor   }
237*2b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
238*2b82c2a5SDouglas Gregor   return HadError;
239*2b82c2a5SDouglas Gregor }
240*2b82c2a5SDouglas Gregor 
241718292f2SDouglas Gregor //----------------------------------------------------------------------------//
242718292f2SDouglas Gregor // Module map file parser
243718292f2SDouglas Gregor //----------------------------------------------------------------------------//
244718292f2SDouglas Gregor 
245718292f2SDouglas Gregor namespace clang {
246718292f2SDouglas Gregor   /// \brief A token in a module map file.
247718292f2SDouglas Gregor   struct MMToken {
248718292f2SDouglas Gregor     enum TokenKind {
249718292f2SDouglas Gregor       EndOfFile,
250718292f2SDouglas Gregor       HeaderKeyword,
251718292f2SDouglas Gregor       Identifier,
252718292f2SDouglas Gregor       ExplicitKeyword,
253*2b82c2a5SDouglas Gregor       ExportKeyword,
254755b2055SDouglas Gregor       FrameworkKeyword,
255718292f2SDouglas Gregor       ModuleKeyword,
256*2b82c2a5SDouglas Gregor       Period,
257718292f2SDouglas Gregor       UmbrellaKeyword,
258*2b82c2a5SDouglas Gregor       Star,
259718292f2SDouglas Gregor       StringLiteral,
260718292f2SDouglas Gregor       LBrace,
261718292f2SDouglas Gregor       RBrace
262718292f2SDouglas Gregor     } Kind;
263718292f2SDouglas Gregor 
264718292f2SDouglas Gregor     unsigned Location;
265718292f2SDouglas Gregor     unsigned StringLength;
266718292f2SDouglas Gregor     const char *StringData;
267718292f2SDouglas Gregor 
268718292f2SDouglas Gregor     void clear() {
269718292f2SDouglas Gregor       Kind = EndOfFile;
270718292f2SDouglas Gregor       Location = 0;
271718292f2SDouglas Gregor       StringLength = 0;
272718292f2SDouglas Gregor       StringData = 0;
273718292f2SDouglas Gregor     }
274718292f2SDouglas Gregor 
275718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
276718292f2SDouglas Gregor 
277718292f2SDouglas Gregor     SourceLocation getLocation() const {
278718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
279718292f2SDouglas Gregor     }
280718292f2SDouglas Gregor 
281718292f2SDouglas Gregor     StringRef getString() const {
282718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
283718292f2SDouglas Gregor     }
284718292f2SDouglas Gregor   };
285718292f2SDouglas Gregor 
286718292f2SDouglas Gregor   class ModuleMapParser {
287718292f2SDouglas Gregor     Lexer &L;
288718292f2SDouglas Gregor     SourceManager &SourceMgr;
289718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
290718292f2SDouglas Gregor     ModuleMap &Map;
291718292f2SDouglas Gregor 
2925257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
2935257fc63SDouglas Gregor     const DirectoryEntry *Directory;
2945257fc63SDouglas Gregor 
295718292f2SDouglas Gregor     /// \brief Whether an error occurred.
296718292f2SDouglas Gregor     bool HadError;
297718292f2SDouglas Gregor 
298718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
299718292f2SDouglas Gregor     /// parsing.
300718292f2SDouglas Gregor     TargetInfo *Target;
301718292f2SDouglas Gregor 
302718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
303718292f2SDouglas Gregor     /// during parsing.
304718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
305718292f2SDouglas Gregor 
306718292f2SDouglas Gregor     /// \brief The current token.
307718292f2SDouglas Gregor     MMToken Tok;
308718292f2SDouglas Gregor 
309718292f2SDouglas Gregor     /// \brief The active module.
310de3ef502SDouglas Gregor     Module *ActiveModule;
311718292f2SDouglas Gregor 
312718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
313718292f2SDouglas Gregor     SourceLocation consumeToken();
314718292f2SDouglas Gregor 
315718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
316718292f2SDouglas Gregor     /// (or the end of the file).
317718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
318718292f2SDouglas Gregor 
319718292f2SDouglas Gregor     void parseModuleDecl();
320718292f2SDouglas Gregor     void parseUmbrellaDecl();
321718292f2SDouglas Gregor     void parseHeaderDecl();
322*2b82c2a5SDouglas Gregor     void parseExportDecl();
323718292f2SDouglas Gregor 
324718292f2SDouglas Gregor   public:
325718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
326718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
3275257fc63SDouglas Gregor                              ModuleMap &Map,
3285257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
3295257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
3305257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
331718292f2SDouglas Gregor     {
332718292f2SDouglas Gregor       TargetOptions TargetOpts;
333718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
334718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
335718292f2SDouglas Gregor 
336718292f2SDouglas Gregor       Tok.clear();
337718292f2SDouglas Gregor       consumeToken();
338718292f2SDouglas Gregor     }
339718292f2SDouglas Gregor 
340718292f2SDouglas Gregor     bool parseModuleMapFile();
341718292f2SDouglas Gregor   };
342718292f2SDouglas Gregor }
343718292f2SDouglas Gregor 
344718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
345718292f2SDouglas Gregor retry:
346718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
347718292f2SDouglas Gregor   Tok.clear();
348718292f2SDouglas Gregor 
349718292f2SDouglas Gregor   Token LToken;
350718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
351718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
352718292f2SDouglas Gregor   switch (LToken.getKind()) {
353718292f2SDouglas Gregor   case tok::raw_identifier:
354718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
355718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
356718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
357718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
358718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
359*2b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
360755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
361718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
362718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
363718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
364718292f2SDouglas Gregor     break;
365718292f2SDouglas Gregor 
366718292f2SDouglas Gregor   case tok::eof:
367718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
368718292f2SDouglas Gregor     break;
369718292f2SDouglas Gregor 
370718292f2SDouglas Gregor   case tok::l_brace:
371718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
372718292f2SDouglas Gregor     break;
373718292f2SDouglas Gregor 
374*2b82c2a5SDouglas Gregor   case tok::period:
375*2b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
376*2b82c2a5SDouglas Gregor     break;
377*2b82c2a5SDouglas Gregor 
378718292f2SDouglas Gregor   case tok::r_brace:
379718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
380718292f2SDouglas Gregor     break;
381718292f2SDouglas Gregor 
382*2b82c2a5SDouglas Gregor   case tok::star:
383*2b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
384*2b82c2a5SDouglas Gregor     break;
385*2b82c2a5SDouglas Gregor 
386718292f2SDouglas Gregor   case tok::string_literal: {
387718292f2SDouglas Gregor     // Parse the string literal.
388718292f2SDouglas Gregor     LangOptions LangOpts;
389718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
390718292f2SDouglas Gregor     if (StringLiteral.hadError)
391718292f2SDouglas Gregor       goto retry;
392718292f2SDouglas Gregor 
393718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
394718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
395718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
396718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
397718292f2SDouglas Gregor     Saved[Length] = 0;
398718292f2SDouglas Gregor 
399718292f2SDouglas Gregor     // Form the token.
400718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
401718292f2SDouglas Gregor     Tok.StringData = Saved;
402718292f2SDouglas Gregor     Tok.StringLength = Length;
403718292f2SDouglas Gregor     break;
404718292f2SDouglas Gregor   }
405718292f2SDouglas Gregor 
406718292f2SDouglas Gregor   case tok::comment:
407718292f2SDouglas Gregor     goto retry;
408718292f2SDouglas Gregor 
409718292f2SDouglas Gregor   default:
410718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
411718292f2SDouglas Gregor     HadError = true;
412718292f2SDouglas Gregor     goto retry;
413718292f2SDouglas Gregor   }
414718292f2SDouglas Gregor 
415718292f2SDouglas Gregor   return Result;
416718292f2SDouglas Gregor }
417718292f2SDouglas Gregor 
418718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
419718292f2SDouglas Gregor   unsigned braceDepth = 0;
420718292f2SDouglas Gregor   do {
421718292f2SDouglas Gregor     switch (Tok.Kind) {
422718292f2SDouglas Gregor     case MMToken::EndOfFile:
423718292f2SDouglas Gregor       return;
424718292f2SDouglas Gregor 
425718292f2SDouglas Gregor     case MMToken::LBrace:
426718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
427718292f2SDouglas Gregor         return;
428718292f2SDouglas Gregor 
429718292f2SDouglas Gregor       ++braceDepth;
430718292f2SDouglas Gregor       break;
431718292f2SDouglas Gregor 
432718292f2SDouglas Gregor     case MMToken::RBrace:
433718292f2SDouglas Gregor       if (braceDepth > 0)
434718292f2SDouglas Gregor         --braceDepth;
435718292f2SDouglas Gregor       else if (Tok.is(K))
436718292f2SDouglas Gregor         return;
437718292f2SDouglas Gregor       break;
438718292f2SDouglas Gregor 
439718292f2SDouglas Gregor     default:
440718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
441718292f2SDouglas Gregor         return;
442718292f2SDouglas Gregor       break;
443718292f2SDouglas Gregor     }
444718292f2SDouglas Gregor 
445718292f2SDouglas Gregor    consumeToken();
446718292f2SDouglas Gregor   } while (true);
447718292f2SDouglas Gregor }
448718292f2SDouglas Gregor 
449718292f2SDouglas Gregor /// \brief Parse a module declaration.
450718292f2SDouglas Gregor ///
451718292f2SDouglas Gregor ///   module-declaration:
452755b2055SDouglas Gregor ///     'framework'[opt] 'module' identifier { module-member* }
453718292f2SDouglas Gregor ///
454718292f2SDouglas Gregor ///   module-member:
455718292f2SDouglas Gregor ///     umbrella-declaration
456718292f2SDouglas Gregor ///     header-declaration
457718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
458*2b82c2a5SDouglas Gregor ///     export-declaration
459718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
460755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
461755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
462718292f2SDouglas Gregor 
463755b2055SDouglas Gregor   // Parse 'framework' or 'explicit' keyword, if present.
464755b2055SDouglas Gregor   bool Framework = false;
465718292f2SDouglas Gregor   bool Explicit = false;
466755b2055SDouglas Gregor 
467755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
468755b2055SDouglas Gregor     consumeToken();
469755b2055SDouglas Gregor     Framework = true;
470755b2055SDouglas Gregor   }
471755b2055SDouglas Gregor   // Parse 'explicit' keyword, if present.
472755b2055SDouglas Gregor   else if (Tok.is(MMToken::ExplicitKeyword)) {
473718292f2SDouglas Gregor     consumeToken();
474718292f2SDouglas Gregor     Explicit = true;
475718292f2SDouglas Gregor   }
476718292f2SDouglas Gregor 
477718292f2SDouglas Gregor   // Parse 'module' keyword.
478718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
479718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
480718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
481718292f2SDouglas Gregor     consumeToken();
482718292f2SDouglas Gregor     HadError = true;
483718292f2SDouglas Gregor     return;
484718292f2SDouglas Gregor   }
485718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
486718292f2SDouglas Gregor 
487718292f2SDouglas Gregor   // Parse the module name.
488718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
489718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
490718292f2SDouglas Gregor     HadError = true;
491718292f2SDouglas Gregor     return;
492718292f2SDouglas Gregor   }
493718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
494718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
495718292f2SDouglas Gregor 
496718292f2SDouglas Gregor   // Parse the opening brace.
497718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
498718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
499718292f2SDouglas Gregor       << ModuleName;
500718292f2SDouglas Gregor     HadError = true;
501718292f2SDouglas Gregor     return;
502718292f2SDouglas Gregor   }
503718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
504718292f2SDouglas Gregor 
505718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
506718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
507718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
508718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
509718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
510718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
511718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
512718292f2SDouglas Gregor       << ModuleName;
513718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
514718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
515718292f2SDouglas Gregor 
516718292f2SDouglas Gregor     // Skip the module definition.
517718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
518718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
519718292f2SDouglas Gregor       consumeToken();
520718292f2SDouglas Gregor 
521718292f2SDouglas Gregor     HadError = true;
522718292f2SDouglas Gregor     return;
523718292f2SDouglas Gregor   }
524718292f2SDouglas Gregor 
525718292f2SDouglas Gregor   // Start defining this module.
526755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
527755b2055SDouglas Gregor                             Explicit);
528718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
529718292f2SDouglas Gregor 
530718292f2SDouglas Gregor   bool Done = false;
531718292f2SDouglas Gregor   do {
532718292f2SDouglas Gregor     switch (Tok.Kind) {
533718292f2SDouglas Gregor     case MMToken::EndOfFile:
534718292f2SDouglas Gregor     case MMToken::RBrace:
535718292f2SDouglas Gregor       Done = true;
536718292f2SDouglas Gregor       break;
537718292f2SDouglas Gregor 
538718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
539718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
540718292f2SDouglas Gregor       parseModuleDecl();
541718292f2SDouglas Gregor       break;
542718292f2SDouglas Gregor 
543*2b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
544*2b82c2a5SDouglas Gregor       parseExportDecl();
545*2b82c2a5SDouglas Gregor       break;
546*2b82c2a5SDouglas Gregor 
547718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
548718292f2SDouglas Gregor       parseHeaderDecl();
549718292f2SDouglas Gregor       break;
550718292f2SDouglas Gregor 
551718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
552718292f2SDouglas Gregor       parseUmbrellaDecl();
553718292f2SDouglas Gregor       break;
554718292f2SDouglas Gregor 
555718292f2SDouglas Gregor     default:
556718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
557718292f2SDouglas Gregor       consumeToken();
558718292f2SDouglas Gregor       break;
559718292f2SDouglas Gregor     }
560718292f2SDouglas Gregor   } while (!Done);
561718292f2SDouglas Gregor 
562718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
563718292f2SDouglas Gregor     consumeToken();
564718292f2SDouglas Gregor   else {
565718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
566718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
567718292f2SDouglas Gregor     HadError = true;
568718292f2SDouglas Gregor   }
569718292f2SDouglas Gregor 
570718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
571718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
572718292f2SDouglas Gregor }
573718292f2SDouglas Gregor 
574718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
575718292f2SDouglas Gregor ///
576718292f2SDouglas Gregor ///   umbrella-declaration:
577718292f2SDouglas Gregor ///     'umbrella' string-literal
578718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
579718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
580718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
581718292f2SDouglas Gregor 
582718292f2SDouglas Gregor   // Parse the header name.
583718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
584718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
585718292f2SDouglas Gregor       << "umbrella";
586718292f2SDouglas Gregor     HadError = true;
587718292f2SDouglas Gregor     return;
588718292f2SDouglas Gregor   }
589718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
590718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
591718292f2SDouglas Gregor 
5925257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
5935257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
5945257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
5955257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
5965257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
5975257fc63SDouglas Gregor     HadError = true;
5985257fc63SDouglas Gregor     return;
5995257fc63SDouglas Gregor   }
6005257fc63SDouglas Gregor 
6015257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
6025257fc63SDouglas Gregor   if (ActiveModule->Parent) {
6035257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
6045257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
6055257fc63SDouglas Gregor     HadError = true;
6065257fc63SDouglas Gregor     return;
6075257fc63SDouglas Gregor   }
6085257fc63SDouglas Gregor 
6095257fc63SDouglas Gregor   // Look for this file.
6105257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
611f545f67dSDouglas Gregor   const FileEntry *File = 0;
612f545f67dSDouglas Gregor 
613f545f67dSDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
614f545f67dSDouglas Gregor     PathName = FileName;
615f545f67dSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
616f545f67dSDouglas Gregor   } else {
617f545f67dSDouglas Gregor     // Search for the header file within the search directory.
6185257fc63SDouglas Gregor     PathName += Directory->getName();
619755b2055SDouglas Gregor     unsigned PathLength = PathName.size();
620755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
621755b2055SDouglas Gregor       // Check whether this file is in the public headers.
622755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
6235257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
624755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
625755b2055SDouglas Gregor 
626755b2055SDouglas Gregor       if (!File) {
627755b2055SDouglas Gregor         // Check whether this file is in the private headers.
628755b2055SDouglas Gregor         PathName.resize(PathLength);
629755b2055SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
630755b2055SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
631755b2055SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
632755b2055SDouglas Gregor       }
633755b2055SDouglas Gregor 
634755b2055SDouglas Gregor       // FIXME: Deal with subframeworks.
635755b2055SDouglas Gregor     } else {
636755b2055SDouglas Gregor       // Lookup for normal headers.
637755b2055SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
638755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
639755b2055SDouglas Gregor     }
640f545f67dSDouglas Gregor   }
6415257fc63SDouglas Gregor 
6425257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6435257fc63SDouglas Gregor   // Come up with a lazy way to do this.
644755b2055SDouglas Gregor   if (File) {
6455257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6465257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6475257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6485257fc63SDouglas Gregor       HadError = true;
649b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
650b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
651b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
652b65dbfffSDouglas Gregor       HadError = true;
6535257fc63SDouglas Gregor     } else {
6545257fc63SDouglas Gregor       // Record this umbrella header.
6555257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
6565257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
657b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
6585257fc63SDouglas Gregor     }
6595257fc63SDouglas Gregor   } else {
6605257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6615257fc63SDouglas Gregor       << true << FileName;
6625257fc63SDouglas Gregor     HadError = true;
6635257fc63SDouglas Gregor   }
664718292f2SDouglas Gregor }
665718292f2SDouglas Gregor 
666718292f2SDouglas Gregor /// \brief Parse a header declaration.
667718292f2SDouglas Gregor ///
668718292f2SDouglas Gregor ///   header-declaration:
669718292f2SDouglas Gregor ///     'header' string-literal
670718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
671718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
6721871ed3dSBenjamin Kramer   consumeToken();
673718292f2SDouglas Gregor 
674718292f2SDouglas Gregor   // Parse the header name.
675718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
676718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
677718292f2SDouglas Gregor       << "header";
678718292f2SDouglas Gregor     HadError = true;
679718292f2SDouglas Gregor     return;
680718292f2SDouglas Gregor   }
681718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
682718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
683718292f2SDouglas Gregor 
6845257fc63SDouglas Gregor   // Look for this file.
6855257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
686f545f67dSDouglas Gregor   if (llvm::sys::path::is_relative(FileName)) {
687f545f67dSDouglas Gregor     // FIXME: Change this search to also look for private headers!
6885257fc63SDouglas Gregor     PathName += Directory->getName();
689755b2055SDouglas Gregor 
690755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework())
691755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
692f545f67dSDouglas Gregor   }
693755b2055SDouglas Gregor 
6945257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
6955257fc63SDouglas Gregor 
6965257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6975257fc63SDouglas Gregor   // Come up with a lazy way to do this.
6985257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
6995257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
7005257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
7015257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
7025257fc63SDouglas Gregor       HadError = true;
7035257fc63SDouglas Gregor     } else {
7045257fc63SDouglas Gregor       // Record this file.
7055257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
7065257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
7075257fc63SDouglas Gregor     }
7085257fc63SDouglas Gregor   } else {
7095257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
7105257fc63SDouglas Gregor       << false << FileName;
7115257fc63SDouglas Gregor     HadError = true;
7125257fc63SDouglas Gregor   }
713718292f2SDouglas Gregor }
714718292f2SDouglas Gregor 
715*2b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
716*2b82c2a5SDouglas Gregor ///
717*2b82c2a5SDouglas Gregor ///   export-declaration:
718*2b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
719*2b82c2a5SDouglas Gregor ///
720*2b82c2a5SDouglas Gregor ///   wildcard-module-id:
721*2b82c2a5SDouglas Gregor ///     identifier
722*2b82c2a5SDouglas Gregor ///     '*'
723*2b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
724*2b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
725*2b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
726*2b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
727*2b82c2a5SDouglas Gregor 
728*2b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
729*2b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
730*2b82c2a5SDouglas Gregor   bool Wildcard = false;
731*2b82c2a5SDouglas Gregor   do {
732*2b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
733*2b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
734*2b82c2a5SDouglas Gregor                                               Tok.getLocation()));
735*2b82c2a5SDouglas Gregor       consumeToken();
736*2b82c2a5SDouglas Gregor 
737*2b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
738*2b82c2a5SDouglas Gregor         consumeToken();
739*2b82c2a5SDouglas Gregor         continue;
740*2b82c2a5SDouglas Gregor       }
741*2b82c2a5SDouglas Gregor 
742*2b82c2a5SDouglas Gregor       break;
743*2b82c2a5SDouglas Gregor     }
744*2b82c2a5SDouglas Gregor 
745*2b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
746*2b82c2a5SDouglas Gregor       Wildcard = true;
747*2b82c2a5SDouglas Gregor       break;
748*2b82c2a5SDouglas Gregor     }
749*2b82c2a5SDouglas Gregor 
750*2b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
751*2b82c2a5SDouglas Gregor     HadError = true;
752*2b82c2a5SDouglas Gregor     return;
753*2b82c2a5SDouglas Gregor   } while (true);
754*2b82c2a5SDouglas Gregor 
755*2b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
756*2b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
757*2b82c2a5SDouglas Gregor   };
758*2b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
759*2b82c2a5SDouglas Gregor }
760*2b82c2a5SDouglas Gregor 
761718292f2SDouglas Gregor /// \brief Parse a module map file.
762718292f2SDouglas Gregor ///
763718292f2SDouglas Gregor ///   module-map-file:
764718292f2SDouglas Gregor ///     module-declaration*
765718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
766718292f2SDouglas Gregor   do {
767718292f2SDouglas Gregor     switch (Tok.Kind) {
768718292f2SDouglas Gregor     case MMToken::EndOfFile:
769718292f2SDouglas Gregor       return HadError;
770718292f2SDouglas Gregor 
771718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
772755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
773718292f2SDouglas Gregor       parseModuleDecl();
774718292f2SDouglas Gregor       break;
775718292f2SDouglas Gregor 
776718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
777*2b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
778718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
779718292f2SDouglas Gregor     case MMToken::Identifier:
780718292f2SDouglas Gregor     case MMToken::LBrace:
781*2b82c2a5SDouglas Gregor     case MMToken::Period:
782718292f2SDouglas Gregor     case MMToken::RBrace:
783*2b82c2a5SDouglas Gregor     case MMToken::Star:
784718292f2SDouglas Gregor     case MMToken::StringLiteral:
785718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
786718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
787718292f2SDouglas Gregor       HadError = true;
788718292f2SDouglas Gregor       consumeToken();
789718292f2SDouglas Gregor       break;
790718292f2SDouglas Gregor     }
791718292f2SDouglas Gregor   } while (true);
792718292f2SDouglas Gregor 
793718292f2SDouglas Gregor   return HadError;
794718292f2SDouglas Gregor }
795718292f2SDouglas Gregor 
796718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
797718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
798718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
799718292f2SDouglas Gregor   if (!Buffer)
800718292f2SDouglas Gregor     return true;
801718292f2SDouglas Gregor 
802718292f2SDouglas Gregor   // Parse this module map file.
803718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
804718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
8055257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
806718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
807718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
808718292f2SDouglas Gregor 
809718292f2SDouglas Gregor   return Result;
810718292f2SDouglas Gregor }
811