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 
302b82c2a5SDouglas Gregor Module::ExportDecl
312b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
322b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
332b82c2a5SDouglas Gregor                          bool Complain) {
34f5eedd05SDouglas Gregor   // We may have just a wildcard.
35f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
36f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
37f5eedd05SDouglas Gregor     return Module::ExportDecl(0, true);
38f5eedd05SDouglas Gregor   }
39f5eedd05SDouglas Gregor 
402b82c2a5SDouglas Gregor   // Find the starting module.
412b82c2a5SDouglas Gregor   Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
422b82c2a5SDouglas Gregor   if (!Context) {
432b82c2a5SDouglas Gregor     if (Complain)
442b82c2a5SDouglas Gregor       Diags->Report(Unresolved.Id[0].second,
452b82c2a5SDouglas Gregor                     diag::err_mmap_missing_module_unqualified)
462b82c2a5SDouglas Gregor         << Unresolved.Id[0].first << Mod->getFullModuleName();
472b82c2a5SDouglas Gregor 
482b82c2a5SDouglas Gregor     return Module::ExportDecl();
492b82c2a5SDouglas Gregor   }
502b82c2a5SDouglas Gregor 
512b82c2a5SDouglas Gregor   // Dig into the module path.
522b82c2a5SDouglas Gregor   for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
532b82c2a5SDouglas Gregor     Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
542b82c2a5SDouglas Gregor                                         Context);
552b82c2a5SDouglas Gregor     if (!Sub) {
562b82c2a5SDouglas Gregor       if (Complain)
572b82c2a5SDouglas Gregor         Diags->Report(Unresolved.Id[I].second,
582b82c2a5SDouglas Gregor                       diag::err_mmap_missing_module_qualified)
592b82c2a5SDouglas Gregor           << Unresolved.Id[I].first << Context->getFullModuleName()
602b82c2a5SDouglas Gregor           << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
612b82c2a5SDouglas Gregor 
622b82c2a5SDouglas Gregor       return Module::ExportDecl();
632b82c2a5SDouglas Gregor     }
642b82c2a5SDouglas Gregor 
652b82c2a5SDouglas Gregor     Context = Sub;
662b82c2a5SDouglas Gregor   }
672b82c2a5SDouglas Gregor 
682b82c2a5SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
692b82c2a5SDouglas Gregor }
702b82c2a5SDouglas Gregor 
71718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
72718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
73718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
74718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
75718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
76718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
77718292f2SDouglas Gregor }
78718292f2SDouglas Gregor 
79718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
805acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
815acdf59eSDouglas Gregor                                         IEnd = Modules.end();
825acdf59eSDouglas Gregor        I != IEnd; ++I) {
835acdf59eSDouglas Gregor     delete I->getValue();
845acdf59eSDouglas Gregor   }
855acdf59eSDouglas Gregor 
86718292f2SDouglas Gregor   delete SourceMgr;
87718292f2SDouglas Gregor }
88718292f2SDouglas Gregor 
89de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
90ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
91ab0c8a84SDouglas Gregor     = Headers.find(File);
92ab0c8a84SDouglas Gregor   if (Known != Headers.end())
93ab0c8a84SDouglas Gregor     return Known->second;
94ab0c8a84SDouglas Gregor 
95b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
96b65dbfffSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
97b65dbfffSDouglas Gregor     = UmbrellaDirs.find(Dir);
98b65dbfffSDouglas Gregor   if (KnownDir != UmbrellaDirs.end())
99b65dbfffSDouglas Gregor     return KnownDir->second;
100b65dbfffSDouglas Gregor 
101b65dbfffSDouglas Gregor   // Walk up the directory hierarchy looking for umbrella headers.
102b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
103b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
104b65dbfffSDouglas Gregor   do {
105b65dbfffSDouglas Gregor     // Retrieve our parent path.
106b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
107b65dbfffSDouglas Gregor     if (DirName.empty())
108b65dbfffSDouglas Gregor       break;
109b65dbfffSDouglas Gregor 
110b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
111b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
112b65dbfffSDouglas Gregor     if (!Dir)
113b65dbfffSDouglas Gregor       break;
114b65dbfffSDouglas Gregor 
115b65dbfffSDouglas Gregor     KnownDir = UmbrellaDirs.find(Dir);
116b65dbfffSDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
117b65dbfffSDouglas Gregor       Module *Result = KnownDir->second;
118b65dbfffSDouglas Gregor 
119b65dbfffSDouglas Gregor       // Record each of the directories we stepped through as being part of
120b65dbfffSDouglas Gregor       // the module we found, since the umbrella header covers them all.
121b65dbfffSDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
122b65dbfffSDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
123b65dbfffSDouglas Gregor 
124b65dbfffSDouglas Gregor       return Result;
125b65dbfffSDouglas Gregor     }
126b65dbfffSDouglas Gregor 
127b65dbfffSDouglas Gregor     SkippedDirs.push_back(Dir);
128b65dbfffSDouglas Gregor   } while (true);
129b65dbfffSDouglas Gregor 
130ab0c8a84SDouglas Gregor   return 0;
131ab0c8a84SDouglas Gregor }
132ab0c8a84SDouglas Gregor 
133de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
13488bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
13588bdfb0eSDouglas Gregor   if (Known != Modules.end())
13688bdfb0eSDouglas Gregor     return Known->getValue();
13788bdfb0eSDouglas Gregor 
13888bdfb0eSDouglas Gregor   return 0;
13988bdfb0eSDouglas Gregor }
14088bdfb0eSDouglas Gregor 
1412b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
1422b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
1432b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
1442b82c2a5SDouglas Gregor       return Sub;
1452b82c2a5SDouglas Gregor   }
1462b82c2a5SDouglas Gregor 
1472b82c2a5SDouglas Gregor   return findModule(Name);
1482b82c2a5SDouglas Gregor }
1492b82c2a5SDouglas Gregor 
1502b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
1512b82c2a5SDouglas Gregor   if (!Context)
1522b82c2a5SDouglas Gregor     return findModule(Name);
1532b82c2a5SDouglas Gregor 
1542b82c2a5SDouglas Gregor   llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
1552b82c2a5SDouglas Gregor   if (Sub != Context->SubModules.end())
1562b82c2a5SDouglas Gregor     return Sub->getValue();
1572b82c2a5SDouglas Gregor 
1582b82c2a5SDouglas Gregor   return 0;
1592b82c2a5SDouglas Gregor }
1602b82c2a5SDouglas Gregor 
161de3ef502SDouglas Gregor std::pair<Module *, bool>
16269021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
16369021974SDouglas Gregor                               bool IsExplicit) {
16469021974SDouglas Gregor   // Try to find an existing module with this name.
16569021974SDouglas Gregor   if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
16669021974SDouglas Gregor     return std::make_pair(Found, false);
16769021974SDouglas Gregor 
16869021974SDouglas Gregor   // Create a new module with this name.
16969021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
17069021974SDouglas Gregor                               IsExplicit);
17169021974SDouglas Gregor   if (Parent)
17269021974SDouglas Gregor     Parent->SubModules[Name] = Result;
17369021974SDouglas Gregor   else
17469021974SDouglas Gregor     Modules[Name] = Result;
17569021974SDouglas Gregor   return std::make_pair(Result, true);
17669021974SDouglas Gregor }
17769021974SDouglas Gregor 
178de3ef502SDouglas Gregor Module *
17956c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
18056c64013SDouglas Gregor                                 const DirectoryEntry *FrameworkDir) {
18156c64013SDouglas Gregor   // Check whether we've already found this module.
18256c64013SDouglas Gregor   if (Module *Module = findModule(ModuleName))
18356c64013SDouglas Gregor     return Module;
18456c64013SDouglas Gregor 
18556c64013SDouglas Gregor   // Look for an umbrella header.
18656c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
18756c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
18856c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
18956c64013SDouglas Gregor   const FileEntry *UmbrellaHeader
19056c64013SDouglas Gregor     = SourceMgr->getFileManager().getFile(UmbrellaName);
19156c64013SDouglas Gregor 
19256c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
19356c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
19456c64013SDouglas Gregor   // idea.
19556c64013SDouglas Gregor   if (!UmbrellaHeader)
19656c64013SDouglas Gregor     return 0;
19756c64013SDouglas Gregor 
198755b2055SDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(),
199755b2055SDouglas Gregor                               /*IsFramework=*/true);
200*d8bd7537SDouglas Gregor   // umbrella "umbrella-header-name"
20156c64013SDouglas Gregor   Result->UmbrellaHeader = UmbrellaHeader;
20256c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
20356c64013SDouglas Gregor   UmbrellaDirs[FrameworkDir] = Result;
204*d8bd7537SDouglas Gregor 
205*d8bd7537SDouglas Gregor   // export *
206*d8bd7537SDouglas Gregor   Result->Exports.push_back(Module::ExportDecl(0, true));
207*d8bd7537SDouglas Gregor 
20856c64013SDouglas Gregor   Modules[ModuleName] = Result;
20956c64013SDouglas Gregor   return Result;
21056c64013SDouglas Gregor }
21156c64013SDouglas Gregor 
212514b636aSDouglas Gregor const FileEntry *
213de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
214514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
215514b636aSDouglas Gregor     return 0;
216514b636aSDouglas Gregor 
217514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
218514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
219514b636aSDouglas Gregor }
220514b636aSDouglas Gregor 
221718292f2SDouglas Gregor void ModuleMap::dump() {
222718292f2SDouglas Gregor   llvm::errs() << "Modules:";
223718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
224718292f2SDouglas Gregor                                         MEnd = Modules.end();
225718292f2SDouglas Gregor        M != MEnd; ++M)
226d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
227718292f2SDouglas Gregor 
228718292f2SDouglas Gregor   llvm::errs() << "Headers:";
229718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
230718292f2SDouglas Gregor             H = Headers.begin(),
231718292f2SDouglas Gregor          HEnd = Headers.end();
232718292f2SDouglas Gregor        H != HEnd; ++H) {
233718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
234718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
235718292f2SDouglas Gregor   }
236718292f2SDouglas Gregor }
237718292f2SDouglas Gregor 
2382b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
2392b82c2a5SDouglas Gregor   bool HadError = false;
2402b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
2412b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
2422b82c2a5SDouglas Gregor                                               Complain);
243f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
2442b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
2452b82c2a5SDouglas Gregor     else
2462b82c2a5SDouglas Gregor       HadError = true;
2472b82c2a5SDouglas Gregor   }
2482b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
2492b82c2a5SDouglas Gregor   return HadError;
2502b82c2a5SDouglas Gregor }
2512b82c2a5SDouglas Gregor 
2520093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
2530093b3c7SDouglas Gregor   if (Loc.isInvalid())
2540093b3c7SDouglas Gregor     return 0;
2550093b3c7SDouglas Gregor 
2560093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
2570093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
2580093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
2590093b3c7SDouglas Gregor     return 0;
2600093b3c7SDouglas Gregor 
2610093b3c7SDouglas Gregor 
2620093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
2630093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
2640093b3c7SDouglas Gregor   const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
2650093b3c7SDouglas Gregor   if (!ExpansionFile)
2660093b3c7SDouglas Gregor     return 0;
2670093b3c7SDouglas Gregor 
2680093b3c7SDouglas Gregor   // Find the module that owns this header.
2690093b3c7SDouglas Gregor   return findModuleForHeader(ExpansionFile);
2700093b3c7SDouglas Gregor }
2710093b3c7SDouglas Gregor 
272718292f2SDouglas Gregor //----------------------------------------------------------------------------//
273718292f2SDouglas Gregor // Module map file parser
274718292f2SDouglas Gregor //----------------------------------------------------------------------------//
275718292f2SDouglas Gregor 
276718292f2SDouglas Gregor namespace clang {
277718292f2SDouglas Gregor   /// \brief A token in a module map file.
278718292f2SDouglas Gregor   struct MMToken {
279718292f2SDouglas Gregor     enum TokenKind {
280718292f2SDouglas Gregor       EndOfFile,
281718292f2SDouglas Gregor       HeaderKeyword,
282718292f2SDouglas Gregor       Identifier,
283718292f2SDouglas Gregor       ExplicitKeyword,
2842b82c2a5SDouglas Gregor       ExportKeyword,
285755b2055SDouglas Gregor       FrameworkKeyword,
286718292f2SDouglas Gregor       ModuleKeyword,
2872b82c2a5SDouglas Gregor       Period,
288718292f2SDouglas Gregor       UmbrellaKeyword,
2892b82c2a5SDouglas Gregor       Star,
290718292f2SDouglas Gregor       StringLiteral,
291718292f2SDouglas Gregor       LBrace,
292718292f2SDouglas Gregor       RBrace
293718292f2SDouglas Gregor     } Kind;
294718292f2SDouglas Gregor 
295718292f2SDouglas Gregor     unsigned Location;
296718292f2SDouglas Gregor     unsigned StringLength;
297718292f2SDouglas Gregor     const char *StringData;
298718292f2SDouglas Gregor 
299718292f2SDouglas Gregor     void clear() {
300718292f2SDouglas Gregor       Kind = EndOfFile;
301718292f2SDouglas Gregor       Location = 0;
302718292f2SDouglas Gregor       StringLength = 0;
303718292f2SDouglas Gregor       StringData = 0;
304718292f2SDouglas Gregor     }
305718292f2SDouglas Gregor 
306718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
307718292f2SDouglas Gregor 
308718292f2SDouglas Gregor     SourceLocation getLocation() const {
309718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
310718292f2SDouglas Gregor     }
311718292f2SDouglas Gregor 
312718292f2SDouglas Gregor     StringRef getString() const {
313718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
314718292f2SDouglas Gregor     }
315718292f2SDouglas Gregor   };
316718292f2SDouglas Gregor 
317718292f2SDouglas Gregor   class ModuleMapParser {
318718292f2SDouglas Gregor     Lexer &L;
319718292f2SDouglas Gregor     SourceManager &SourceMgr;
320718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
321718292f2SDouglas Gregor     ModuleMap &Map;
322718292f2SDouglas Gregor 
3235257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
3245257fc63SDouglas Gregor     const DirectoryEntry *Directory;
3255257fc63SDouglas Gregor 
326718292f2SDouglas Gregor     /// \brief Whether an error occurred.
327718292f2SDouglas Gregor     bool HadError;
328718292f2SDouglas Gregor 
329718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
330718292f2SDouglas Gregor     /// parsing.
331718292f2SDouglas Gregor     TargetInfo *Target;
332718292f2SDouglas Gregor 
333718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
334718292f2SDouglas Gregor     /// during parsing.
335718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
336718292f2SDouglas Gregor 
337718292f2SDouglas Gregor     /// \brief The current token.
338718292f2SDouglas Gregor     MMToken Tok;
339718292f2SDouglas Gregor 
340718292f2SDouglas Gregor     /// \brief The active module.
341de3ef502SDouglas Gregor     Module *ActiveModule;
342718292f2SDouglas Gregor 
343718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
344718292f2SDouglas Gregor     SourceLocation consumeToken();
345718292f2SDouglas Gregor 
346718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
347718292f2SDouglas Gregor     /// (or the end of the file).
348718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
349718292f2SDouglas Gregor 
350718292f2SDouglas Gregor     void parseModuleDecl();
351718292f2SDouglas Gregor     void parseUmbrellaDecl();
352718292f2SDouglas Gregor     void parseHeaderDecl();
3532b82c2a5SDouglas Gregor     void parseExportDecl();
354718292f2SDouglas Gregor 
355718292f2SDouglas Gregor   public:
356718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
357718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
3585257fc63SDouglas Gregor                              ModuleMap &Map,
3595257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
3605257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
3615257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
362718292f2SDouglas Gregor     {
363718292f2SDouglas Gregor       TargetOptions TargetOpts;
364718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
365718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
366718292f2SDouglas Gregor 
367718292f2SDouglas Gregor       Tok.clear();
368718292f2SDouglas Gregor       consumeToken();
369718292f2SDouglas Gregor     }
370718292f2SDouglas Gregor 
371718292f2SDouglas Gregor     bool parseModuleMapFile();
372718292f2SDouglas Gregor   };
373718292f2SDouglas Gregor }
374718292f2SDouglas Gregor 
375718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
376718292f2SDouglas Gregor retry:
377718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
378718292f2SDouglas Gregor   Tok.clear();
379718292f2SDouglas Gregor 
380718292f2SDouglas Gregor   Token LToken;
381718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
382718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
383718292f2SDouglas Gregor   switch (LToken.getKind()) {
384718292f2SDouglas Gregor   case tok::raw_identifier:
385718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
386718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
387718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
388718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
389718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
3902b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
391755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
392718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
393718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
394718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
395718292f2SDouglas Gregor     break;
396718292f2SDouglas Gregor 
397718292f2SDouglas Gregor   case tok::eof:
398718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
399718292f2SDouglas Gregor     break;
400718292f2SDouglas Gregor 
401718292f2SDouglas Gregor   case tok::l_brace:
402718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
403718292f2SDouglas Gregor     break;
404718292f2SDouglas Gregor 
4052b82c2a5SDouglas Gregor   case tok::period:
4062b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
4072b82c2a5SDouglas Gregor     break;
4082b82c2a5SDouglas Gregor 
409718292f2SDouglas Gregor   case tok::r_brace:
410718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
411718292f2SDouglas Gregor     break;
412718292f2SDouglas Gregor 
4132b82c2a5SDouglas Gregor   case tok::star:
4142b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
4152b82c2a5SDouglas Gregor     break;
4162b82c2a5SDouglas Gregor 
417718292f2SDouglas Gregor   case tok::string_literal: {
418718292f2SDouglas Gregor     // Parse the string literal.
419718292f2SDouglas Gregor     LangOptions LangOpts;
420718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
421718292f2SDouglas Gregor     if (StringLiteral.hadError)
422718292f2SDouglas Gregor       goto retry;
423718292f2SDouglas Gregor 
424718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
425718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
426718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
427718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
428718292f2SDouglas Gregor     Saved[Length] = 0;
429718292f2SDouglas Gregor 
430718292f2SDouglas Gregor     // Form the token.
431718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
432718292f2SDouglas Gregor     Tok.StringData = Saved;
433718292f2SDouglas Gregor     Tok.StringLength = Length;
434718292f2SDouglas Gregor     break;
435718292f2SDouglas Gregor   }
436718292f2SDouglas Gregor 
437718292f2SDouglas Gregor   case tok::comment:
438718292f2SDouglas Gregor     goto retry;
439718292f2SDouglas Gregor 
440718292f2SDouglas Gregor   default:
441718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
442718292f2SDouglas Gregor     HadError = true;
443718292f2SDouglas Gregor     goto retry;
444718292f2SDouglas Gregor   }
445718292f2SDouglas Gregor 
446718292f2SDouglas Gregor   return Result;
447718292f2SDouglas Gregor }
448718292f2SDouglas Gregor 
449718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
450718292f2SDouglas Gregor   unsigned braceDepth = 0;
451718292f2SDouglas Gregor   do {
452718292f2SDouglas Gregor     switch (Tok.Kind) {
453718292f2SDouglas Gregor     case MMToken::EndOfFile:
454718292f2SDouglas Gregor       return;
455718292f2SDouglas Gregor 
456718292f2SDouglas Gregor     case MMToken::LBrace:
457718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
458718292f2SDouglas Gregor         return;
459718292f2SDouglas Gregor 
460718292f2SDouglas Gregor       ++braceDepth;
461718292f2SDouglas Gregor       break;
462718292f2SDouglas Gregor 
463718292f2SDouglas Gregor     case MMToken::RBrace:
464718292f2SDouglas Gregor       if (braceDepth > 0)
465718292f2SDouglas Gregor         --braceDepth;
466718292f2SDouglas Gregor       else if (Tok.is(K))
467718292f2SDouglas Gregor         return;
468718292f2SDouglas Gregor       break;
469718292f2SDouglas Gregor 
470718292f2SDouglas Gregor     default:
471718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
472718292f2SDouglas Gregor         return;
473718292f2SDouglas Gregor       break;
474718292f2SDouglas Gregor     }
475718292f2SDouglas Gregor 
476718292f2SDouglas Gregor    consumeToken();
477718292f2SDouglas Gregor   } while (true);
478718292f2SDouglas Gregor }
479718292f2SDouglas Gregor 
480718292f2SDouglas Gregor /// \brief Parse a module declaration.
481718292f2SDouglas Gregor ///
482718292f2SDouglas Gregor ///   module-declaration:
483755b2055SDouglas Gregor ///     'framework'[opt] 'module' identifier { module-member* }
484718292f2SDouglas Gregor ///
485718292f2SDouglas Gregor ///   module-member:
486718292f2SDouglas Gregor ///     umbrella-declaration
487718292f2SDouglas Gregor ///     header-declaration
488718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
4892b82c2a5SDouglas Gregor ///     export-declaration
490718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
491755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
492755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
493718292f2SDouglas Gregor 
494755b2055SDouglas Gregor   // Parse 'framework' or 'explicit' keyword, if present.
495755b2055SDouglas Gregor   bool Framework = false;
496718292f2SDouglas Gregor   bool Explicit = false;
497755b2055SDouglas Gregor 
498755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
499755b2055SDouglas Gregor     consumeToken();
500755b2055SDouglas Gregor     Framework = true;
501755b2055SDouglas Gregor   }
502755b2055SDouglas Gregor   // Parse 'explicit' keyword, if present.
503755b2055SDouglas Gregor   else if (Tok.is(MMToken::ExplicitKeyword)) {
504718292f2SDouglas Gregor     consumeToken();
505718292f2SDouglas Gregor     Explicit = true;
506718292f2SDouglas Gregor   }
507718292f2SDouglas Gregor 
508718292f2SDouglas Gregor   // Parse 'module' keyword.
509718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
510718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
511718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
512718292f2SDouglas Gregor     consumeToken();
513718292f2SDouglas Gregor     HadError = true;
514718292f2SDouglas Gregor     return;
515718292f2SDouglas Gregor   }
516718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
517718292f2SDouglas Gregor 
518718292f2SDouglas Gregor   // Parse the module name.
519718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
520718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
521718292f2SDouglas Gregor     HadError = true;
522718292f2SDouglas Gregor     return;
523718292f2SDouglas Gregor   }
524718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
525718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
526718292f2SDouglas Gregor 
527718292f2SDouglas Gregor   // Parse the opening brace.
528718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
529718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
530718292f2SDouglas Gregor       << ModuleName;
531718292f2SDouglas Gregor     HadError = true;
532718292f2SDouglas Gregor     return;
533718292f2SDouglas Gregor   }
534718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
535718292f2SDouglas Gregor 
536718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
537718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
538718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
539718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
540718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
541718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
542718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
543718292f2SDouglas Gregor       << ModuleName;
544718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
545718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
546718292f2SDouglas Gregor 
547718292f2SDouglas Gregor     // Skip the module definition.
548718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
549718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
550718292f2SDouglas Gregor       consumeToken();
551718292f2SDouglas Gregor 
552718292f2SDouglas Gregor     HadError = true;
553718292f2SDouglas Gregor     return;
554718292f2SDouglas Gregor   }
555718292f2SDouglas Gregor 
556718292f2SDouglas Gregor   // Start defining this module.
557755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
558755b2055SDouglas Gregor                             Explicit);
559718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
560718292f2SDouglas Gregor 
561718292f2SDouglas Gregor   bool Done = false;
562718292f2SDouglas Gregor   do {
563718292f2SDouglas Gregor     switch (Tok.Kind) {
564718292f2SDouglas Gregor     case MMToken::EndOfFile:
565718292f2SDouglas Gregor     case MMToken::RBrace:
566718292f2SDouglas Gregor       Done = true;
567718292f2SDouglas Gregor       break;
568718292f2SDouglas Gregor 
569718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
570718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
571718292f2SDouglas Gregor       parseModuleDecl();
572718292f2SDouglas Gregor       break;
573718292f2SDouglas Gregor 
5742b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
5752b82c2a5SDouglas Gregor       parseExportDecl();
5762b82c2a5SDouglas Gregor       break;
5772b82c2a5SDouglas Gregor 
578718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
579718292f2SDouglas Gregor       parseHeaderDecl();
580718292f2SDouglas Gregor       break;
581718292f2SDouglas Gregor 
582718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
583718292f2SDouglas Gregor       parseUmbrellaDecl();
584718292f2SDouglas Gregor       break;
585718292f2SDouglas Gregor 
586718292f2SDouglas Gregor     default:
587718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
588718292f2SDouglas Gregor       consumeToken();
589718292f2SDouglas Gregor       break;
590718292f2SDouglas Gregor     }
591718292f2SDouglas Gregor   } while (!Done);
592718292f2SDouglas Gregor 
593718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
594718292f2SDouglas Gregor     consumeToken();
595718292f2SDouglas Gregor   else {
596718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
597718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
598718292f2SDouglas Gregor     HadError = true;
599718292f2SDouglas Gregor   }
600718292f2SDouglas Gregor 
601718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
602718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
603718292f2SDouglas Gregor }
604718292f2SDouglas Gregor 
605718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
606718292f2SDouglas Gregor ///
607718292f2SDouglas Gregor ///   umbrella-declaration:
608718292f2SDouglas Gregor ///     'umbrella' string-literal
609718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
610718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
611718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
612718292f2SDouglas Gregor 
613718292f2SDouglas Gregor   // Parse the header name.
614718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
615718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
616718292f2SDouglas Gregor       << "umbrella";
617718292f2SDouglas Gregor     HadError = true;
618718292f2SDouglas Gregor     return;
619718292f2SDouglas Gregor   }
620718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
621718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
622718292f2SDouglas Gregor 
6235257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
6245257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
6255257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
6265257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
6275257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
6285257fc63SDouglas Gregor     HadError = true;
6295257fc63SDouglas Gregor     return;
6305257fc63SDouglas Gregor   }
6315257fc63SDouglas Gregor 
6325257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
6335257fc63SDouglas Gregor   if (ActiveModule->Parent) {
6345257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
6355257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
6365257fc63SDouglas Gregor     HadError = true;
6375257fc63SDouglas Gregor     return;
6385257fc63SDouglas Gregor   }
6395257fc63SDouglas Gregor 
6405257fc63SDouglas Gregor   // Look for this file.
6415257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
642f545f67dSDouglas Gregor   const FileEntry *File = 0;
643f545f67dSDouglas Gregor 
644f545f67dSDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
645f545f67dSDouglas Gregor     PathName = FileName;
646f545f67dSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
647f545f67dSDouglas Gregor   } else {
648f545f67dSDouglas Gregor     // Search for the header file within the search directory.
6495257fc63SDouglas Gregor     PathName += Directory->getName();
650755b2055SDouglas Gregor     unsigned PathLength = PathName.size();
651755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
652755b2055SDouglas Gregor       // Check whether this file is in the public headers.
653755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
6545257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
655755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
656755b2055SDouglas Gregor 
657755b2055SDouglas Gregor       if (!File) {
658755b2055SDouglas Gregor         // Check whether this file is in the private headers.
659755b2055SDouglas Gregor         PathName.resize(PathLength);
660755b2055SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
661755b2055SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
662755b2055SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
663755b2055SDouglas Gregor       }
664755b2055SDouglas Gregor 
665755b2055SDouglas Gregor       // FIXME: Deal with subframeworks.
666755b2055SDouglas Gregor     } else {
667755b2055SDouglas Gregor       // Lookup for normal headers.
668755b2055SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
669755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
670755b2055SDouglas Gregor     }
671f545f67dSDouglas Gregor   }
6725257fc63SDouglas Gregor 
6735257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6745257fc63SDouglas Gregor   // Come up with a lazy way to do this.
675755b2055SDouglas Gregor   if (File) {
6765257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6775257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6785257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6795257fc63SDouglas Gregor       HadError = true;
680b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
681b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
682b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
683b65dbfffSDouglas Gregor       HadError = true;
6845257fc63SDouglas Gregor     } else {
6855257fc63SDouglas Gregor       // Record this umbrella header.
6865257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
6875257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
688b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
6895257fc63SDouglas Gregor     }
6905257fc63SDouglas Gregor   } else {
6915257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6925257fc63SDouglas Gregor       << true << FileName;
6935257fc63SDouglas Gregor     HadError = true;
6945257fc63SDouglas Gregor   }
695718292f2SDouglas Gregor }
696718292f2SDouglas Gregor 
697718292f2SDouglas Gregor /// \brief Parse a header declaration.
698718292f2SDouglas Gregor ///
699718292f2SDouglas Gregor ///   header-declaration:
700718292f2SDouglas Gregor ///     'header' string-literal
701718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
702718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
7031871ed3dSBenjamin Kramer   consumeToken();
704718292f2SDouglas Gregor 
705718292f2SDouglas Gregor   // Parse the header name.
706718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
707718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
708718292f2SDouglas Gregor       << "header";
709718292f2SDouglas Gregor     HadError = true;
710718292f2SDouglas Gregor     return;
711718292f2SDouglas Gregor   }
712718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
713718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
714718292f2SDouglas Gregor 
7155257fc63SDouglas Gregor   // Look for this file.
7165257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
717f545f67dSDouglas Gregor   if (llvm::sys::path::is_relative(FileName)) {
718f545f67dSDouglas Gregor     // FIXME: Change this search to also look for private headers!
7195257fc63SDouglas Gregor     PathName += Directory->getName();
720755b2055SDouglas Gregor 
721755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework())
722755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
723f545f67dSDouglas Gregor   }
724755b2055SDouglas Gregor 
7255257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
7265257fc63SDouglas Gregor 
7275257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
7285257fc63SDouglas Gregor   // Come up with a lazy way to do this.
7295257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
7305257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
7315257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
7325257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
7335257fc63SDouglas Gregor       HadError = true;
7345257fc63SDouglas Gregor     } else {
7355257fc63SDouglas Gregor       // Record this file.
7365257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
7375257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
7385257fc63SDouglas Gregor     }
7395257fc63SDouglas Gregor   } else {
7405257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
7415257fc63SDouglas Gregor       << false << FileName;
7425257fc63SDouglas Gregor     HadError = true;
7435257fc63SDouglas Gregor   }
744718292f2SDouglas Gregor }
745718292f2SDouglas Gregor 
7462b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
7472b82c2a5SDouglas Gregor ///
7482b82c2a5SDouglas Gregor ///   export-declaration:
7492b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
7502b82c2a5SDouglas Gregor ///
7512b82c2a5SDouglas Gregor ///   wildcard-module-id:
7522b82c2a5SDouglas Gregor ///     identifier
7532b82c2a5SDouglas Gregor ///     '*'
7542b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
7552b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
7562b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
7572b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
7582b82c2a5SDouglas Gregor 
7592b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
7602b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
7612b82c2a5SDouglas Gregor   bool Wildcard = false;
7622b82c2a5SDouglas Gregor   do {
7632b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
7642b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
7652b82c2a5SDouglas Gregor                                               Tok.getLocation()));
7662b82c2a5SDouglas Gregor       consumeToken();
7672b82c2a5SDouglas Gregor 
7682b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
7692b82c2a5SDouglas Gregor         consumeToken();
7702b82c2a5SDouglas Gregor         continue;
7712b82c2a5SDouglas Gregor       }
7722b82c2a5SDouglas Gregor 
7732b82c2a5SDouglas Gregor       break;
7742b82c2a5SDouglas Gregor     }
7752b82c2a5SDouglas Gregor 
7762b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
7772b82c2a5SDouglas Gregor       Wildcard = true;
778f5eedd05SDouglas Gregor       consumeToken();
7792b82c2a5SDouglas Gregor       break;
7802b82c2a5SDouglas Gregor     }
7812b82c2a5SDouglas Gregor 
7822b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
7832b82c2a5SDouglas Gregor     HadError = true;
7842b82c2a5SDouglas Gregor     return;
7852b82c2a5SDouglas Gregor   } while (true);
7862b82c2a5SDouglas Gregor 
7872b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
7882b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
7892b82c2a5SDouglas Gregor   };
7902b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
7912b82c2a5SDouglas Gregor }
7922b82c2a5SDouglas Gregor 
793718292f2SDouglas Gregor /// \brief Parse a module map file.
794718292f2SDouglas Gregor ///
795718292f2SDouglas Gregor ///   module-map-file:
796718292f2SDouglas Gregor ///     module-declaration*
797718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
798718292f2SDouglas Gregor   do {
799718292f2SDouglas Gregor     switch (Tok.Kind) {
800718292f2SDouglas Gregor     case MMToken::EndOfFile:
801718292f2SDouglas Gregor       return HadError;
802718292f2SDouglas Gregor 
803718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
804755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
805718292f2SDouglas Gregor       parseModuleDecl();
806718292f2SDouglas Gregor       break;
807718292f2SDouglas Gregor 
808718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
8092b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
810718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
811718292f2SDouglas Gregor     case MMToken::Identifier:
812718292f2SDouglas Gregor     case MMToken::LBrace:
8132b82c2a5SDouglas Gregor     case MMToken::Period:
814718292f2SDouglas Gregor     case MMToken::RBrace:
8152b82c2a5SDouglas Gregor     case MMToken::Star:
816718292f2SDouglas Gregor     case MMToken::StringLiteral:
817718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
818718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
819718292f2SDouglas Gregor       HadError = true;
820718292f2SDouglas Gregor       consumeToken();
821718292f2SDouglas Gregor       break;
822718292f2SDouglas Gregor     }
823718292f2SDouglas Gregor   } while (true);
824718292f2SDouglas Gregor 
825718292f2SDouglas Gregor   return HadError;
826718292f2SDouglas Gregor }
827718292f2SDouglas Gregor 
828718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
829718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
830718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
831718292f2SDouglas Gregor   if (!Buffer)
832718292f2SDouglas Gregor     return true;
833718292f2SDouglas Gregor 
834718292f2SDouglas Gregor   // Parse this module map file.
835718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
836718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
8375257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
838718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
839718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
840718292f2SDouglas Gregor 
841718292f2SDouglas Gregor   return Result;
842718292f2SDouglas Gregor }
843