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) {
34*f5eedd05SDouglas Gregor   // We may have just a wildcard.
35*f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
36*f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
37*f5eedd05SDouglas Gregor     return Module::ExportDecl(0, true);
38*f5eedd05SDouglas Gregor   }
39*f5eedd05SDouglas 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);
20056c64013SDouglas Gregor   Result->UmbrellaHeader = UmbrellaHeader;
20156c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
20256c64013SDouglas Gregor   UmbrellaDirs[FrameworkDir] = Result;
20356c64013SDouglas Gregor   Modules[ModuleName] = Result;
20456c64013SDouglas Gregor   return Result;
20556c64013SDouglas Gregor }
20656c64013SDouglas Gregor 
207514b636aSDouglas Gregor const FileEntry *
208de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
209514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
210514b636aSDouglas Gregor     return 0;
211514b636aSDouglas Gregor 
212514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
213514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
214514b636aSDouglas Gregor }
215514b636aSDouglas Gregor 
216718292f2SDouglas Gregor void ModuleMap::dump() {
217718292f2SDouglas Gregor   llvm::errs() << "Modules:";
218718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
219718292f2SDouglas Gregor                                         MEnd = Modules.end();
220718292f2SDouglas Gregor        M != MEnd; ++M)
221d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
222718292f2SDouglas Gregor 
223718292f2SDouglas Gregor   llvm::errs() << "Headers:";
224718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
225718292f2SDouglas Gregor             H = Headers.begin(),
226718292f2SDouglas Gregor          HEnd = Headers.end();
227718292f2SDouglas Gregor        H != HEnd; ++H) {
228718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
229718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
230718292f2SDouglas Gregor   }
231718292f2SDouglas Gregor }
232718292f2SDouglas Gregor 
2332b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
2342b82c2a5SDouglas Gregor   bool HadError = false;
2352b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
2362b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
2372b82c2a5SDouglas Gregor                                               Complain);
238*f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
2392b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
2402b82c2a5SDouglas Gregor     else
2412b82c2a5SDouglas Gregor       HadError = true;
2422b82c2a5SDouglas Gregor   }
2432b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
2442b82c2a5SDouglas Gregor   return HadError;
2452b82c2a5SDouglas Gregor }
2462b82c2a5SDouglas Gregor 
2470093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
2480093b3c7SDouglas Gregor   if (Loc.isInvalid())
2490093b3c7SDouglas Gregor     return 0;
2500093b3c7SDouglas Gregor 
2510093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
2520093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
2530093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
2540093b3c7SDouglas Gregor     return 0;
2550093b3c7SDouglas Gregor 
2560093b3c7SDouglas Gregor 
2570093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
2580093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
2590093b3c7SDouglas Gregor   const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
2600093b3c7SDouglas Gregor   if (!ExpansionFile)
2610093b3c7SDouglas Gregor     return 0;
2620093b3c7SDouglas Gregor 
2630093b3c7SDouglas Gregor   // Find the module that owns this header.
2640093b3c7SDouglas Gregor   return findModuleForHeader(ExpansionFile);
2650093b3c7SDouglas Gregor }
2660093b3c7SDouglas Gregor 
267718292f2SDouglas Gregor //----------------------------------------------------------------------------//
268718292f2SDouglas Gregor // Module map file parser
269718292f2SDouglas Gregor //----------------------------------------------------------------------------//
270718292f2SDouglas Gregor 
271718292f2SDouglas Gregor namespace clang {
272718292f2SDouglas Gregor   /// \brief A token in a module map file.
273718292f2SDouglas Gregor   struct MMToken {
274718292f2SDouglas Gregor     enum TokenKind {
275718292f2SDouglas Gregor       EndOfFile,
276718292f2SDouglas Gregor       HeaderKeyword,
277718292f2SDouglas Gregor       Identifier,
278718292f2SDouglas Gregor       ExplicitKeyword,
2792b82c2a5SDouglas Gregor       ExportKeyword,
280755b2055SDouglas Gregor       FrameworkKeyword,
281718292f2SDouglas Gregor       ModuleKeyword,
2822b82c2a5SDouglas Gregor       Period,
283718292f2SDouglas Gregor       UmbrellaKeyword,
2842b82c2a5SDouglas Gregor       Star,
285718292f2SDouglas Gregor       StringLiteral,
286718292f2SDouglas Gregor       LBrace,
287718292f2SDouglas Gregor       RBrace
288718292f2SDouglas Gregor     } Kind;
289718292f2SDouglas Gregor 
290718292f2SDouglas Gregor     unsigned Location;
291718292f2SDouglas Gregor     unsigned StringLength;
292718292f2SDouglas Gregor     const char *StringData;
293718292f2SDouglas Gregor 
294718292f2SDouglas Gregor     void clear() {
295718292f2SDouglas Gregor       Kind = EndOfFile;
296718292f2SDouglas Gregor       Location = 0;
297718292f2SDouglas Gregor       StringLength = 0;
298718292f2SDouglas Gregor       StringData = 0;
299718292f2SDouglas Gregor     }
300718292f2SDouglas Gregor 
301718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
302718292f2SDouglas Gregor 
303718292f2SDouglas Gregor     SourceLocation getLocation() const {
304718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
305718292f2SDouglas Gregor     }
306718292f2SDouglas Gregor 
307718292f2SDouglas Gregor     StringRef getString() const {
308718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
309718292f2SDouglas Gregor     }
310718292f2SDouglas Gregor   };
311718292f2SDouglas Gregor 
312718292f2SDouglas Gregor   class ModuleMapParser {
313718292f2SDouglas Gregor     Lexer &L;
314718292f2SDouglas Gregor     SourceManager &SourceMgr;
315718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
316718292f2SDouglas Gregor     ModuleMap &Map;
317718292f2SDouglas Gregor 
3185257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
3195257fc63SDouglas Gregor     const DirectoryEntry *Directory;
3205257fc63SDouglas Gregor 
321718292f2SDouglas Gregor     /// \brief Whether an error occurred.
322718292f2SDouglas Gregor     bool HadError;
323718292f2SDouglas Gregor 
324718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
325718292f2SDouglas Gregor     /// parsing.
326718292f2SDouglas Gregor     TargetInfo *Target;
327718292f2SDouglas Gregor 
328718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
329718292f2SDouglas Gregor     /// during parsing.
330718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
331718292f2SDouglas Gregor 
332718292f2SDouglas Gregor     /// \brief The current token.
333718292f2SDouglas Gregor     MMToken Tok;
334718292f2SDouglas Gregor 
335718292f2SDouglas Gregor     /// \brief The active module.
336de3ef502SDouglas Gregor     Module *ActiveModule;
337718292f2SDouglas Gregor 
338718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
339718292f2SDouglas Gregor     SourceLocation consumeToken();
340718292f2SDouglas Gregor 
341718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
342718292f2SDouglas Gregor     /// (or the end of the file).
343718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
344718292f2SDouglas Gregor 
345718292f2SDouglas Gregor     void parseModuleDecl();
346718292f2SDouglas Gregor     void parseUmbrellaDecl();
347718292f2SDouglas Gregor     void parseHeaderDecl();
3482b82c2a5SDouglas Gregor     void parseExportDecl();
349718292f2SDouglas Gregor 
350718292f2SDouglas Gregor   public:
351718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
352718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
3535257fc63SDouglas Gregor                              ModuleMap &Map,
3545257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
3555257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
3565257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
357718292f2SDouglas Gregor     {
358718292f2SDouglas Gregor       TargetOptions TargetOpts;
359718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
360718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
361718292f2SDouglas Gregor 
362718292f2SDouglas Gregor       Tok.clear();
363718292f2SDouglas Gregor       consumeToken();
364718292f2SDouglas Gregor     }
365718292f2SDouglas Gregor 
366718292f2SDouglas Gregor     bool parseModuleMapFile();
367718292f2SDouglas Gregor   };
368718292f2SDouglas Gregor }
369718292f2SDouglas Gregor 
370718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
371718292f2SDouglas Gregor retry:
372718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
373718292f2SDouglas Gregor   Tok.clear();
374718292f2SDouglas Gregor 
375718292f2SDouglas Gregor   Token LToken;
376718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
377718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
378718292f2SDouglas Gregor   switch (LToken.getKind()) {
379718292f2SDouglas Gregor   case tok::raw_identifier:
380718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
381718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
382718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
383718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
384718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
3852b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
386755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
387718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
388718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
389718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
390718292f2SDouglas Gregor     break;
391718292f2SDouglas Gregor 
392718292f2SDouglas Gregor   case tok::eof:
393718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
394718292f2SDouglas Gregor     break;
395718292f2SDouglas Gregor 
396718292f2SDouglas Gregor   case tok::l_brace:
397718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
398718292f2SDouglas Gregor     break;
399718292f2SDouglas Gregor 
4002b82c2a5SDouglas Gregor   case tok::period:
4012b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
4022b82c2a5SDouglas Gregor     break;
4032b82c2a5SDouglas Gregor 
404718292f2SDouglas Gregor   case tok::r_brace:
405718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
406718292f2SDouglas Gregor     break;
407718292f2SDouglas Gregor 
4082b82c2a5SDouglas Gregor   case tok::star:
4092b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
4102b82c2a5SDouglas Gregor     break;
4112b82c2a5SDouglas Gregor 
412718292f2SDouglas Gregor   case tok::string_literal: {
413718292f2SDouglas Gregor     // Parse the string literal.
414718292f2SDouglas Gregor     LangOptions LangOpts;
415718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
416718292f2SDouglas Gregor     if (StringLiteral.hadError)
417718292f2SDouglas Gregor       goto retry;
418718292f2SDouglas Gregor 
419718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
420718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
421718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
422718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
423718292f2SDouglas Gregor     Saved[Length] = 0;
424718292f2SDouglas Gregor 
425718292f2SDouglas Gregor     // Form the token.
426718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
427718292f2SDouglas Gregor     Tok.StringData = Saved;
428718292f2SDouglas Gregor     Tok.StringLength = Length;
429718292f2SDouglas Gregor     break;
430718292f2SDouglas Gregor   }
431718292f2SDouglas Gregor 
432718292f2SDouglas Gregor   case tok::comment:
433718292f2SDouglas Gregor     goto retry;
434718292f2SDouglas Gregor 
435718292f2SDouglas Gregor   default:
436718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
437718292f2SDouglas Gregor     HadError = true;
438718292f2SDouglas Gregor     goto retry;
439718292f2SDouglas Gregor   }
440718292f2SDouglas Gregor 
441718292f2SDouglas Gregor   return Result;
442718292f2SDouglas Gregor }
443718292f2SDouglas Gregor 
444718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
445718292f2SDouglas Gregor   unsigned braceDepth = 0;
446718292f2SDouglas Gregor   do {
447718292f2SDouglas Gregor     switch (Tok.Kind) {
448718292f2SDouglas Gregor     case MMToken::EndOfFile:
449718292f2SDouglas Gregor       return;
450718292f2SDouglas Gregor 
451718292f2SDouglas Gregor     case MMToken::LBrace:
452718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
453718292f2SDouglas Gregor         return;
454718292f2SDouglas Gregor 
455718292f2SDouglas Gregor       ++braceDepth;
456718292f2SDouglas Gregor       break;
457718292f2SDouglas Gregor 
458718292f2SDouglas Gregor     case MMToken::RBrace:
459718292f2SDouglas Gregor       if (braceDepth > 0)
460718292f2SDouglas Gregor         --braceDepth;
461718292f2SDouglas Gregor       else if (Tok.is(K))
462718292f2SDouglas Gregor         return;
463718292f2SDouglas Gregor       break;
464718292f2SDouglas Gregor 
465718292f2SDouglas Gregor     default:
466718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
467718292f2SDouglas Gregor         return;
468718292f2SDouglas Gregor       break;
469718292f2SDouglas Gregor     }
470718292f2SDouglas Gregor 
471718292f2SDouglas Gregor    consumeToken();
472718292f2SDouglas Gregor   } while (true);
473718292f2SDouglas Gregor }
474718292f2SDouglas Gregor 
475718292f2SDouglas Gregor /// \brief Parse a module declaration.
476718292f2SDouglas Gregor ///
477718292f2SDouglas Gregor ///   module-declaration:
478755b2055SDouglas Gregor ///     'framework'[opt] 'module' identifier { module-member* }
479718292f2SDouglas Gregor ///
480718292f2SDouglas Gregor ///   module-member:
481718292f2SDouglas Gregor ///     umbrella-declaration
482718292f2SDouglas Gregor ///     header-declaration
483718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
4842b82c2a5SDouglas Gregor ///     export-declaration
485718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
486755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
487755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
488718292f2SDouglas Gregor 
489755b2055SDouglas Gregor   // Parse 'framework' or 'explicit' keyword, if present.
490755b2055SDouglas Gregor   bool Framework = false;
491718292f2SDouglas Gregor   bool Explicit = false;
492755b2055SDouglas Gregor 
493755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
494755b2055SDouglas Gregor     consumeToken();
495755b2055SDouglas Gregor     Framework = true;
496755b2055SDouglas Gregor   }
497755b2055SDouglas Gregor   // Parse 'explicit' keyword, if present.
498755b2055SDouglas Gregor   else if (Tok.is(MMToken::ExplicitKeyword)) {
499718292f2SDouglas Gregor     consumeToken();
500718292f2SDouglas Gregor     Explicit = true;
501718292f2SDouglas Gregor   }
502718292f2SDouglas Gregor 
503718292f2SDouglas Gregor   // Parse 'module' keyword.
504718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
505718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
506718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
507718292f2SDouglas Gregor     consumeToken();
508718292f2SDouglas Gregor     HadError = true;
509718292f2SDouglas Gregor     return;
510718292f2SDouglas Gregor   }
511718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
512718292f2SDouglas Gregor 
513718292f2SDouglas Gregor   // Parse the module name.
514718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
515718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
516718292f2SDouglas Gregor     HadError = true;
517718292f2SDouglas Gregor     return;
518718292f2SDouglas Gregor   }
519718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
520718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
521718292f2SDouglas Gregor 
522718292f2SDouglas Gregor   // Parse the opening brace.
523718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
524718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
525718292f2SDouglas Gregor       << ModuleName;
526718292f2SDouglas Gregor     HadError = true;
527718292f2SDouglas Gregor     return;
528718292f2SDouglas Gregor   }
529718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
530718292f2SDouglas Gregor 
531718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
532718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
533718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
534718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
535718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
536718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
537718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
538718292f2SDouglas Gregor       << ModuleName;
539718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
540718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
541718292f2SDouglas Gregor 
542718292f2SDouglas Gregor     // Skip the module definition.
543718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
544718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
545718292f2SDouglas Gregor       consumeToken();
546718292f2SDouglas Gregor 
547718292f2SDouglas Gregor     HadError = true;
548718292f2SDouglas Gregor     return;
549718292f2SDouglas Gregor   }
550718292f2SDouglas Gregor 
551718292f2SDouglas Gregor   // Start defining this module.
552755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
553755b2055SDouglas Gregor                             Explicit);
554718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
555718292f2SDouglas Gregor 
556718292f2SDouglas Gregor   bool Done = false;
557718292f2SDouglas Gregor   do {
558718292f2SDouglas Gregor     switch (Tok.Kind) {
559718292f2SDouglas Gregor     case MMToken::EndOfFile:
560718292f2SDouglas Gregor     case MMToken::RBrace:
561718292f2SDouglas Gregor       Done = true;
562718292f2SDouglas Gregor       break;
563718292f2SDouglas Gregor 
564718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
565718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
566718292f2SDouglas Gregor       parseModuleDecl();
567718292f2SDouglas Gregor       break;
568718292f2SDouglas Gregor 
5692b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
5702b82c2a5SDouglas Gregor       parseExportDecl();
5712b82c2a5SDouglas Gregor       break;
5722b82c2a5SDouglas Gregor 
573718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
574718292f2SDouglas Gregor       parseHeaderDecl();
575718292f2SDouglas Gregor       break;
576718292f2SDouglas Gregor 
577718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
578718292f2SDouglas Gregor       parseUmbrellaDecl();
579718292f2SDouglas Gregor       break;
580718292f2SDouglas Gregor 
581718292f2SDouglas Gregor     default:
582718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
583718292f2SDouglas Gregor       consumeToken();
584718292f2SDouglas Gregor       break;
585718292f2SDouglas Gregor     }
586718292f2SDouglas Gregor   } while (!Done);
587718292f2SDouglas Gregor 
588718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
589718292f2SDouglas Gregor     consumeToken();
590718292f2SDouglas Gregor   else {
591718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
592718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
593718292f2SDouglas Gregor     HadError = true;
594718292f2SDouglas Gregor   }
595718292f2SDouglas Gregor 
596718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
597718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
598718292f2SDouglas Gregor }
599718292f2SDouglas Gregor 
600718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
601718292f2SDouglas Gregor ///
602718292f2SDouglas Gregor ///   umbrella-declaration:
603718292f2SDouglas Gregor ///     'umbrella' string-literal
604718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
605718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
606718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
607718292f2SDouglas Gregor 
608718292f2SDouglas Gregor   // Parse the header name.
609718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
610718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
611718292f2SDouglas Gregor       << "umbrella";
612718292f2SDouglas Gregor     HadError = true;
613718292f2SDouglas Gregor     return;
614718292f2SDouglas Gregor   }
615718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
616718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
617718292f2SDouglas Gregor 
6185257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
6195257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
6205257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
6215257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
6225257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
6235257fc63SDouglas Gregor     HadError = true;
6245257fc63SDouglas Gregor     return;
6255257fc63SDouglas Gregor   }
6265257fc63SDouglas Gregor 
6275257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
6285257fc63SDouglas Gregor   if (ActiveModule->Parent) {
6295257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
6305257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
6315257fc63SDouglas Gregor     HadError = true;
6325257fc63SDouglas Gregor     return;
6335257fc63SDouglas Gregor   }
6345257fc63SDouglas Gregor 
6355257fc63SDouglas Gregor   // Look for this file.
6365257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
637f545f67dSDouglas Gregor   const FileEntry *File = 0;
638f545f67dSDouglas Gregor 
639f545f67dSDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
640f545f67dSDouglas Gregor     PathName = FileName;
641f545f67dSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
642f545f67dSDouglas Gregor   } else {
643f545f67dSDouglas Gregor     // Search for the header file within the search directory.
6445257fc63SDouglas Gregor     PathName += Directory->getName();
645755b2055SDouglas Gregor     unsigned PathLength = PathName.size();
646755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
647755b2055SDouglas Gregor       // Check whether this file is in the public headers.
648755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
6495257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
650755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
651755b2055SDouglas Gregor 
652755b2055SDouglas Gregor       if (!File) {
653755b2055SDouglas Gregor         // Check whether this file is in the private headers.
654755b2055SDouglas Gregor         PathName.resize(PathLength);
655755b2055SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
656755b2055SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
657755b2055SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
658755b2055SDouglas Gregor       }
659755b2055SDouglas Gregor 
660755b2055SDouglas Gregor       // FIXME: Deal with subframeworks.
661755b2055SDouglas Gregor     } else {
662755b2055SDouglas Gregor       // Lookup for normal headers.
663755b2055SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
664755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
665755b2055SDouglas Gregor     }
666f545f67dSDouglas Gregor   }
6675257fc63SDouglas Gregor 
6685257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6695257fc63SDouglas Gregor   // Come up with a lazy way to do this.
670755b2055SDouglas Gregor   if (File) {
6715257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6725257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6735257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6745257fc63SDouglas Gregor       HadError = true;
675b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
676b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
677b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
678b65dbfffSDouglas Gregor       HadError = true;
6795257fc63SDouglas Gregor     } else {
6805257fc63SDouglas Gregor       // Record this umbrella header.
6815257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
6825257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
683b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
6845257fc63SDouglas Gregor     }
6855257fc63SDouglas Gregor   } else {
6865257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6875257fc63SDouglas Gregor       << true << FileName;
6885257fc63SDouglas Gregor     HadError = true;
6895257fc63SDouglas Gregor   }
690718292f2SDouglas Gregor }
691718292f2SDouglas Gregor 
692718292f2SDouglas Gregor /// \brief Parse a header declaration.
693718292f2SDouglas Gregor ///
694718292f2SDouglas Gregor ///   header-declaration:
695718292f2SDouglas Gregor ///     'header' string-literal
696718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
697718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
6981871ed3dSBenjamin Kramer   consumeToken();
699718292f2SDouglas Gregor 
700718292f2SDouglas Gregor   // Parse the header name.
701718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
702718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
703718292f2SDouglas Gregor       << "header";
704718292f2SDouglas Gregor     HadError = true;
705718292f2SDouglas Gregor     return;
706718292f2SDouglas Gregor   }
707718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
708718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
709718292f2SDouglas Gregor 
7105257fc63SDouglas Gregor   // Look for this file.
7115257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
712f545f67dSDouglas Gregor   if (llvm::sys::path::is_relative(FileName)) {
713f545f67dSDouglas Gregor     // FIXME: Change this search to also look for private headers!
7145257fc63SDouglas Gregor     PathName += Directory->getName();
715755b2055SDouglas Gregor 
716755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework())
717755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
718f545f67dSDouglas Gregor   }
719755b2055SDouglas Gregor 
7205257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
7215257fc63SDouglas Gregor 
7225257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
7235257fc63SDouglas Gregor   // Come up with a lazy way to do this.
7245257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
7255257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
7265257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
7275257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
7285257fc63SDouglas Gregor       HadError = true;
7295257fc63SDouglas Gregor     } else {
7305257fc63SDouglas Gregor       // Record this file.
7315257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
7325257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
7335257fc63SDouglas Gregor     }
7345257fc63SDouglas Gregor   } else {
7355257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
7365257fc63SDouglas Gregor       << false << FileName;
7375257fc63SDouglas Gregor     HadError = true;
7385257fc63SDouglas Gregor   }
739718292f2SDouglas Gregor }
740718292f2SDouglas Gregor 
7412b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
7422b82c2a5SDouglas Gregor ///
7432b82c2a5SDouglas Gregor ///   export-declaration:
7442b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
7452b82c2a5SDouglas Gregor ///
7462b82c2a5SDouglas Gregor ///   wildcard-module-id:
7472b82c2a5SDouglas Gregor ///     identifier
7482b82c2a5SDouglas Gregor ///     '*'
7492b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
7502b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
7512b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
7522b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
7532b82c2a5SDouglas Gregor 
7542b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
7552b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
7562b82c2a5SDouglas Gregor   bool Wildcard = false;
7572b82c2a5SDouglas Gregor   do {
7582b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
7592b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
7602b82c2a5SDouglas Gregor                                               Tok.getLocation()));
7612b82c2a5SDouglas Gregor       consumeToken();
7622b82c2a5SDouglas Gregor 
7632b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
7642b82c2a5SDouglas Gregor         consumeToken();
7652b82c2a5SDouglas Gregor         continue;
7662b82c2a5SDouglas Gregor       }
7672b82c2a5SDouglas Gregor 
7682b82c2a5SDouglas Gregor       break;
7692b82c2a5SDouglas Gregor     }
7702b82c2a5SDouglas Gregor 
7712b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
7722b82c2a5SDouglas Gregor       Wildcard = true;
773*f5eedd05SDouglas Gregor       consumeToken();
7742b82c2a5SDouglas Gregor       break;
7752b82c2a5SDouglas Gregor     }
7762b82c2a5SDouglas Gregor 
7772b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
7782b82c2a5SDouglas Gregor     HadError = true;
7792b82c2a5SDouglas Gregor     return;
7802b82c2a5SDouglas Gregor   } while (true);
7812b82c2a5SDouglas Gregor 
7822b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
7832b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
7842b82c2a5SDouglas Gregor   };
7852b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
7862b82c2a5SDouglas Gregor }
7872b82c2a5SDouglas Gregor 
788718292f2SDouglas Gregor /// \brief Parse a module map file.
789718292f2SDouglas Gregor ///
790718292f2SDouglas Gregor ///   module-map-file:
791718292f2SDouglas Gregor ///     module-declaration*
792718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
793718292f2SDouglas Gregor   do {
794718292f2SDouglas Gregor     switch (Tok.Kind) {
795718292f2SDouglas Gregor     case MMToken::EndOfFile:
796718292f2SDouglas Gregor       return HadError;
797718292f2SDouglas Gregor 
798718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
799755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
800718292f2SDouglas Gregor       parseModuleDecl();
801718292f2SDouglas Gregor       break;
802718292f2SDouglas Gregor 
803718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
8042b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
805718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
806718292f2SDouglas Gregor     case MMToken::Identifier:
807718292f2SDouglas Gregor     case MMToken::LBrace:
8082b82c2a5SDouglas Gregor     case MMToken::Period:
809718292f2SDouglas Gregor     case MMToken::RBrace:
8102b82c2a5SDouglas Gregor     case MMToken::Star:
811718292f2SDouglas Gregor     case MMToken::StringLiteral:
812718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
813718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
814718292f2SDouglas Gregor       HadError = true;
815718292f2SDouglas Gregor       consumeToken();
816718292f2SDouglas Gregor       break;
817718292f2SDouglas Gregor     }
818718292f2SDouglas Gregor   } while (true);
819718292f2SDouglas Gregor 
820718292f2SDouglas Gregor   return HadError;
821718292f2SDouglas Gregor }
822718292f2SDouglas Gregor 
823718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
824718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
825718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
826718292f2SDouglas Gregor   if (!Buffer)
827718292f2SDouglas Gregor     return true;
828718292f2SDouglas Gregor 
829718292f2SDouglas Gregor   // Parse this module map file.
830718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
831718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
8325257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
833718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
834718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
835718292f2SDouglas Gregor 
836718292f2SDouglas Gregor   return Result;
837718292f2SDouglas Gregor }
838