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"
23e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h"
24718292f2SDouglas Gregor #include "llvm/Support/Host.h"
255257fc63SDouglas Gregor #include "llvm/Support/PathV2.h"
26718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
27718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h"
28718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h"
29718292f2SDouglas Gregor using namespace clang;
30718292f2SDouglas Gregor 
312b82c2a5SDouglas Gregor Module::ExportDecl
322b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
332b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
342b82c2a5SDouglas Gregor                          bool Complain) {
35f5eedd05SDouglas Gregor   // We may have just a wildcard.
36f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
37f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
38f5eedd05SDouglas Gregor     return Module::ExportDecl(0, true);
39f5eedd05SDouglas Gregor   }
40f5eedd05SDouglas Gregor 
412b82c2a5SDouglas Gregor   // Find the starting module.
422b82c2a5SDouglas Gregor   Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
432b82c2a5SDouglas Gregor   if (!Context) {
442b82c2a5SDouglas Gregor     if (Complain)
452b82c2a5SDouglas Gregor       Diags->Report(Unresolved.Id[0].second,
462b82c2a5SDouglas Gregor                     diag::err_mmap_missing_module_unqualified)
472b82c2a5SDouglas Gregor         << Unresolved.Id[0].first << Mod->getFullModuleName();
482b82c2a5SDouglas Gregor 
492b82c2a5SDouglas Gregor     return Module::ExportDecl();
502b82c2a5SDouglas Gregor   }
512b82c2a5SDouglas Gregor 
522b82c2a5SDouglas Gregor   // Dig into the module path.
532b82c2a5SDouglas Gregor   for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
542b82c2a5SDouglas Gregor     Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
552b82c2a5SDouglas Gregor                                         Context);
562b82c2a5SDouglas Gregor     if (!Sub) {
572b82c2a5SDouglas Gregor       if (Complain)
582b82c2a5SDouglas Gregor         Diags->Report(Unresolved.Id[I].second,
592b82c2a5SDouglas Gregor                       diag::err_mmap_missing_module_qualified)
602b82c2a5SDouglas Gregor           << Unresolved.Id[I].first << Context->getFullModuleName()
612b82c2a5SDouglas Gregor           << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
622b82c2a5SDouglas Gregor 
632b82c2a5SDouglas Gregor       return Module::ExportDecl();
642b82c2a5SDouglas Gregor     }
652b82c2a5SDouglas Gregor 
662b82c2a5SDouglas Gregor     Context = Sub;
672b82c2a5SDouglas Gregor   }
682b82c2a5SDouglas Gregor 
692b82c2a5SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
702b82c2a5SDouglas Gregor }
712b82c2a5SDouglas Gregor 
72718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
73718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
74718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
75718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
76718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
77718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
78718292f2SDouglas Gregor }
79718292f2SDouglas Gregor 
80718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
815acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
825acdf59eSDouglas Gregor                                         IEnd = Modules.end();
835acdf59eSDouglas Gregor        I != IEnd; ++I) {
845acdf59eSDouglas Gregor     delete I->getValue();
855acdf59eSDouglas Gregor   }
865acdf59eSDouglas Gregor 
87718292f2SDouglas Gregor   delete SourceMgr;
88718292f2SDouglas Gregor }
89718292f2SDouglas Gregor 
90de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
91ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
92ab0c8a84SDouglas Gregor     = Headers.find(File);
93ab0c8a84SDouglas Gregor   if (Known != Headers.end())
94ab0c8a84SDouglas Gregor     return Known->second;
95ab0c8a84SDouglas Gregor 
96b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
97b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
98b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
99a89c5ac4SDouglas Gregor 
100a89c5ac4SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
101a89c5ac4SDouglas Gregor   // an umbrella header.
102b65dbfffSDouglas Gregor   do {
103a89c5ac4SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
104a89c5ac4SDouglas Gregor       = UmbrellaDirs.find(Dir);
105a89c5ac4SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
106a89c5ac4SDouglas Gregor       Module *Result = KnownDir->second;
107930a85ccSDouglas Gregor 
108930a85ccSDouglas Gregor       // Search up the module stack until we find a module with an umbrella
10973141fa9SDouglas Gregor       // directory.
110930a85ccSDouglas Gregor       Module *UmbrellaModule = Result;
11173141fa9SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
112930a85ccSDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
113930a85ccSDouglas Gregor 
114930a85ccSDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
115a89c5ac4SDouglas Gregor         // Infer submodules for each of the directories we found between
116a89c5ac4SDouglas Gregor         // the directory of the umbrella header and the directory where
117a89c5ac4SDouglas Gregor         // the actual header is located.
1189458f82dSDouglas Gregor         bool Explicit = UmbrellaModule->InferExplicitSubmodules;
1199458f82dSDouglas Gregor 
1207033127bSDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
121a89c5ac4SDouglas Gregor           // Find or create the module that corresponds to this directory name.
122a89c5ac4SDouglas Gregor           StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
123a89c5ac4SDouglas Gregor           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
1249458f82dSDouglas Gregor                                       Explicit).first;
125a89c5ac4SDouglas Gregor 
126a89c5ac4SDouglas Gregor           // Associate the module and the directory.
127a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I-1]] = Result;
128a89c5ac4SDouglas Gregor 
129a89c5ac4SDouglas Gregor           // If inferred submodules export everything they import, add a
130a89c5ac4SDouglas Gregor           // wildcard to the set of exports.
131930a85ccSDouglas Gregor           if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
132a89c5ac4SDouglas Gregor             Result->Exports.push_back(Module::ExportDecl(0, true));
133a89c5ac4SDouglas Gregor         }
134a89c5ac4SDouglas Gregor 
135a89c5ac4SDouglas Gregor         // Infer a submodule with the same name as this header file.
136a89c5ac4SDouglas Gregor         StringRef Name = llvm::sys::path::stem(File->getName());
137a89c5ac4SDouglas Gregor         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
1389458f82dSDouglas Gregor                                     Explicit).first;
139a89c5ac4SDouglas Gregor 
140a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
141a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
142930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
143a89c5ac4SDouglas Gregor           Result->Exports.push_back(Module::ExportDecl(0, true));
144a89c5ac4SDouglas Gregor       } else {
145a89c5ac4SDouglas Gregor         // Record each of the directories we stepped through as being part of
146a89c5ac4SDouglas Gregor         // the module we found, since the umbrella header covers them all.
147a89c5ac4SDouglas Gregor         for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
148a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I]] = Result;
149a89c5ac4SDouglas Gregor       }
150a89c5ac4SDouglas Gregor 
151a89c5ac4SDouglas Gregor       Headers[File] = Result;
152a89c5ac4SDouglas Gregor       return Result;
153a89c5ac4SDouglas Gregor     }
154a89c5ac4SDouglas Gregor 
155a89c5ac4SDouglas Gregor     SkippedDirs.push_back(Dir);
156a89c5ac4SDouglas Gregor 
157b65dbfffSDouglas Gregor     // Retrieve our parent path.
158b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
159b65dbfffSDouglas Gregor     if (DirName.empty())
160b65dbfffSDouglas Gregor       break;
161b65dbfffSDouglas Gregor 
162b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
163b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
164a89c5ac4SDouglas Gregor   } while (Dir);
165b65dbfffSDouglas Gregor 
166ab0c8a84SDouglas Gregor   return 0;
167ab0c8a84SDouglas Gregor }
168ab0c8a84SDouglas Gregor 
169de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
17088bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
17188bdfb0eSDouglas Gregor   if (Known != Modules.end())
17288bdfb0eSDouglas Gregor     return Known->getValue();
17388bdfb0eSDouglas Gregor 
17488bdfb0eSDouglas Gregor   return 0;
17588bdfb0eSDouglas Gregor }
17688bdfb0eSDouglas Gregor 
1772b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
1782b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
1792b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
1802b82c2a5SDouglas Gregor       return Sub;
1812b82c2a5SDouglas Gregor   }
1822b82c2a5SDouglas Gregor 
1832b82c2a5SDouglas Gregor   return findModule(Name);
1842b82c2a5SDouglas Gregor }
1852b82c2a5SDouglas Gregor 
1862b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
1872b82c2a5SDouglas Gregor   if (!Context)
1882b82c2a5SDouglas Gregor     return findModule(Name);
1892b82c2a5SDouglas Gregor 
1902b82c2a5SDouglas Gregor   llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
1912b82c2a5SDouglas Gregor   if (Sub != Context->SubModules.end())
1922b82c2a5SDouglas Gregor     return Sub->getValue();
1932b82c2a5SDouglas Gregor 
1942b82c2a5SDouglas Gregor   return 0;
1952b82c2a5SDouglas Gregor }
1962b82c2a5SDouglas Gregor 
197de3ef502SDouglas Gregor std::pair<Module *, bool>
19869021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
19969021974SDouglas Gregor                               bool IsExplicit) {
20069021974SDouglas Gregor   // Try to find an existing module with this name.
20169021974SDouglas Gregor   if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
20269021974SDouglas Gregor     return std::make_pair(Found, false);
20369021974SDouglas Gregor 
20469021974SDouglas Gregor   // Create a new module with this name.
20569021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
20669021974SDouglas Gregor                               IsExplicit);
20769021974SDouglas Gregor   if (Parent)
20869021974SDouglas Gregor     Parent->SubModules[Name] = Result;
20969021974SDouglas Gregor   else
21069021974SDouglas Gregor     Modules[Name] = Result;
21169021974SDouglas Gregor   return std::make_pair(Result, true);
21269021974SDouglas Gregor }
21369021974SDouglas Gregor 
214de3ef502SDouglas Gregor Module *
21556c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
216e89dbc1dSDouglas Gregor                                 const DirectoryEntry *FrameworkDir,
217e89dbc1dSDouglas Gregor                                 Module *Parent) {
21856c64013SDouglas Gregor   // Check whether we've already found this module.
219e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
220e89dbc1dSDouglas Gregor     return Mod;
221e89dbc1dSDouglas Gregor 
222e89dbc1dSDouglas Gregor   FileManager &FileMgr = SourceMgr->getFileManager();
22356c64013SDouglas Gregor 
22456c64013SDouglas Gregor   // Look for an umbrella header.
22556c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
22656c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
22756c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
228e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
22956c64013SDouglas Gregor 
23056c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
23156c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
23256c64013SDouglas Gregor   // idea.
23356c64013SDouglas Gregor   if (!UmbrellaHeader)
23456c64013SDouglas Gregor     return 0;
23556c64013SDouglas Gregor 
236e89dbc1dSDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
237e89dbc1dSDouglas Gregor                               /*IsFramework=*/true, /*IsExplicit=*/false);
238e89dbc1dSDouglas Gregor 
239e89dbc1dSDouglas Gregor   if (Parent)
240e89dbc1dSDouglas Gregor     Parent->SubModules[ModuleName] = Result;
241e89dbc1dSDouglas Gregor   else
242e89dbc1dSDouglas Gregor     Modules[ModuleName] = Result;
243e89dbc1dSDouglas Gregor 
244322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
24573141fa9SDouglas Gregor   Result->Umbrella = UmbrellaHeader;
24656c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
247*4dc71835SDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
248d8bd7537SDouglas Gregor 
249d8bd7537SDouglas Gregor   // export *
250d8bd7537SDouglas Gregor   Result->Exports.push_back(Module::ExportDecl(0, true));
251d8bd7537SDouglas Gregor 
252a89c5ac4SDouglas Gregor   // module * { export * }
253a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
254a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
255a89c5ac4SDouglas Gregor 
256e89dbc1dSDouglas Gregor   // Look for subframeworks.
257e89dbc1dSDouglas Gregor   llvm::error_code EC;
258ddaa69cbSDouglas Gregor   llvm::SmallString<128> SubframeworksDirName
259ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
260e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
261ddaa69cbSDouglas Gregor   llvm::SmallString<128> SubframeworksDirNameNative;
262ddaa69cbSDouglas Gregor   llvm::sys::path::native(SubframeworksDirName.str(),
263ddaa69cbSDouglas Gregor                           SubframeworksDirNameNative);
264ddaa69cbSDouglas Gregor   for (llvm::sys::fs::directory_iterator
265ddaa69cbSDouglas Gregor          Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
266e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
267e89dbc1dSDouglas Gregor     if (!StringRef(Dir->path()).endswith(".framework"))
268e89dbc1dSDouglas Gregor       continue;
269f2161a70SDouglas Gregor 
270e89dbc1dSDouglas Gregor     if (const DirectoryEntry *SubframeworkDir
271e89dbc1dSDouglas Gregor           = FileMgr.getDirectory(Dir->path())) {
272e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
273e89dbc1dSDouglas Gregor       inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
274e89dbc1dSDouglas Gregor                            Result);
275e89dbc1dSDouglas Gregor     }
276e89dbc1dSDouglas Gregor   }
277e89dbc1dSDouglas Gregor 
2789458f82dSDouglas Gregor   // Look for private headers.
2799458f82dSDouglas Gregor   llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName());
2809458f82dSDouglas Gregor   llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders");
2817033127bSDouglas Gregor   if (const DirectoryEntry *Dir = FileMgr.getDirectory(PrivateHeadersDirName)) {
2827033127bSDouglas Gregor     Module *Private = findOrCreateModule("Private", Result,
2839458f82dSDouglas Gregor                                          /*IsFramework=*/false,
2849458f82dSDouglas Gregor                                          /*IsExplicit=*/true).first;
2857033127bSDouglas Gregor     setUmbrellaDir(Private, Dir);
2867033127bSDouglas Gregor     Private->InferSubmodules = true;
2877033127bSDouglas Gregor     Private->InferExplicitSubmodules = true;
2887033127bSDouglas Gregor     Private->InferExportWildcard = true;
2899458f82dSDouglas Gregor   }
2909458f82dSDouglas Gregor 
29156c64013SDouglas Gregor   return Result;
29256c64013SDouglas Gregor }
29356c64013SDouglas Gregor 
294a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
295a89c5ac4SDouglas Gregor   Headers[UmbrellaHeader] = Mod;
29673141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
2977033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
298a89c5ac4SDouglas Gregor }
299a89c5ac4SDouglas Gregor 
300524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
301524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
302524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
303524e33e1SDouglas Gregor }
304524e33e1SDouglas Gregor 
305a89c5ac4SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
306a89c5ac4SDouglas Gregor   Mod->Headers.push_back(Header);
307a89c5ac4SDouglas Gregor   Headers[Header] = Mod;
308a89c5ac4SDouglas Gregor }
309a89c5ac4SDouglas Gregor 
310514b636aSDouglas Gregor const FileEntry *
311de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
312514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
313514b636aSDouglas Gregor     return 0;
314514b636aSDouglas Gregor 
315514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
316514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
317514b636aSDouglas Gregor }
318514b636aSDouglas Gregor 
319718292f2SDouglas Gregor void ModuleMap::dump() {
320718292f2SDouglas Gregor   llvm::errs() << "Modules:";
321718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
322718292f2SDouglas Gregor                                         MEnd = Modules.end();
323718292f2SDouglas Gregor        M != MEnd; ++M)
324d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
325718292f2SDouglas Gregor 
326718292f2SDouglas Gregor   llvm::errs() << "Headers:";
327718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
328718292f2SDouglas Gregor             H = Headers.begin(),
329718292f2SDouglas Gregor          HEnd = Headers.end();
330718292f2SDouglas Gregor        H != HEnd; ++H) {
331718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
332718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
333718292f2SDouglas Gregor   }
334718292f2SDouglas Gregor }
335718292f2SDouglas Gregor 
3362b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
3372b82c2a5SDouglas Gregor   bool HadError = false;
3382b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
3392b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
3402b82c2a5SDouglas Gregor                                               Complain);
341f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
3422b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
3432b82c2a5SDouglas Gregor     else
3442b82c2a5SDouglas Gregor       HadError = true;
3452b82c2a5SDouglas Gregor   }
3462b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
3472b82c2a5SDouglas Gregor   return HadError;
3482b82c2a5SDouglas Gregor }
3492b82c2a5SDouglas Gregor 
3500093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
3510093b3c7SDouglas Gregor   if (Loc.isInvalid())
3520093b3c7SDouglas Gregor     return 0;
3530093b3c7SDouglas Gregor 
3540093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
3550093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
3560093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
3570093b3c7SDouglas Gregor     return 0;
3580093b3c7SDouglas Gregor 
3590093b3c7SDouglas Gregor 
3600093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
3610093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
3620093b3c7SDouglas Gregor   const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
3630093b3c7SDouglas Gregor   if (!ExpansionFile)
3640093b3c7SDouglas Gregor     return 0;
3650093b3c7SDouglas Gregor 
3660093b3c7SDouglas Gregor   // Find the module that owns this header.
3670093b3c7SDouglas Gregor   return findModuleForHeader(ExpansionFile);
3680093b3c7SDouglas Gregor }
3690093b3c7SDouglas Gregor 
370718292f2SDouglas Gregor //----------------------------------------------------------------------------//
371718292f2SDouglas Gregor // Module map file parser
372718292f2SDouglas Gregor //----------------------------------------------------------------------------//
373718292f2SDouglas Gregor 
374718292f2SDouglas Gregor namespace clang {
375718292f2SDouglas Gregor   /// \brief A token in a module map file.
376718292f2SDouglas Gregor   struct MMToken {
377718292f2SDouglas Gregor     enum TokenKind {
378718292f2SDouglas Gregor       EndOfFile,
379718292f2SDouglas Gregor       HeaderKeyword,
380718292f2SDouglas Gregor       Identifier,
381718292f2SDouglas Gregor       ExplicitKeyword,
3822b82c2a5SDouglas Gregor       ExportKeyword,
383755b2055SDouglas Gregor       FrameworkKeyword,
384718292f2SDouglas Gregor       ModuleKeyword,
3852b82c2a5SDouglas Gregor       Period,
386718292f2SDouglas Gregor       UmbrellaKeyword,
3872b82c2a5SDouglas Gregor       Star,
388718292f2SDouglas Gregor       StringLiteral,
389718292f2SDouglas Gregor       LBrace,
390718292f2SDouglas Gregor       RBrace
391718292f2SDouglas Gregor     } Kind;
392718292f2SDouglas Gregor 
393718292f2SDouglas Gregor     unsigned Location;
394718292f2SDouglas Gregor     unsigned StringLength;
395718292f2SDouglas Gregor     const char *StringData;
396718292f2SDouglas Gregor 
397718292f2SDouglas Gregor     void clear() {
398718292f2SDouglas Gregor       Kind = EndOfFile;
399718292f2SDouglas Gregor       Location = 0;
400718292f2SDouglas Gregor       StringLength = 0;
401718292f2SDouglas Gregor       StringData = 0;
402718292f2SDouglas Gregor     }
403718292f2SDouglas Gregor 
404718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
405718292f2SDouglas Gregor 
406718292f2SDouglas Gregor     SourceLocation getLocation() const {
407718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
408718292f2SDouglas Gregor     }
409718292f2SDouglas Gregor 
410718292f2SDouglas Gregor     StringRef getString() const {
411718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
412718292f2SDouglas Gregor     }
413718292f2SDouglas Gregor   };
414718292f2SDouglas Gregor 
415718292f2SDouglas Gregor   class ModuleMapParser {
416718292f2SDouglas Gregor     Lexer &L;
417718292f2SDouglas Gregor     SourceManager &SourceMgr;
418718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
419718292f2SDouglas Gregor     ModuleMap &Map;
420718292f2SDouglas Gregor 
4215257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
4225257fc63SDouglas Gregor     const DirectoryEntry *Directory;
4235257fc63SDouglas Gregor 
424718292f2SDouglas Gregor     /// \brief Whether an error occurred.
425718292f2SDouglas Gregor     bool HadError;
426718292f2SDouglas Gregor 
427718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
428718292f2SDouglas Gregor     /// parsing.
429718292f2SDouglas Gregor     TargetInfo *Target;
430718292f2SDouglas Gregor 
431718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
432718292f2SDouglas Gregor     /// during parsing.
433718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
434718292f2SDouglas Gregor 
435718292f2SDouglas Gregor     /// \brief The current token.
436718292f2SDouglas Gregor     MMToken Tok;
437718292f2SDouglas Gregor 
438718292f2SDouglas Gregor     /// \brief The active module.
439de3ef502SDouglas Gregor     Module *ActiveModule;
440718292f2SDouglas Gregor 
441718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
442718292f2SDouglas Gregor     SourceLocation consumeToken();
443718292f2SDouglas Gregor 
444718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
445718292f2SDouglas Gregor     /// (or the end of the file).
446718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
447718292f2SDouglas Gregor 
448e7ab3669SDouglas Gregor     typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
449e7ab3669SDouglas Gregor       ModuleId;
450e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
451718292f2SDouglas Gregor     void parseModuleDecl();
452322f633cSDouglas Gregor     void parseHeaderDecl(SourceLocation UmbrellaLoc);
453524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
4542b82c2a5SDouglas Gregor     void parseExportDecl();
45573441091SDouglas Gregor     void parseInferredSubmoduleDecl(bool Explicit);
456718292f2SDouglas Gregor 
4577033127bSDouglas Gregor     const DirectoryEntry *getOverriddenHeaderSearchDir();
4587033127bSDouglas Gregor 
459718292f2SDouglas Gregor   public:
460718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
461718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
4625257fc63SDouglas Gregor                              ModuleMap &Map,
4635257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
4645257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
4655257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
466718292f2SDouglas Gregor     {
467718292f2SDouglas Gregor       TargetOptions TargetOpts;
468718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
469718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
470718292f2SDouglas Gregor 
471718292f2SDouglas Gregor       Tok.clear();
472718292f2SDouglas Gregor       consumeToken();
473718292f2SDouglas Gregor     }
474718292f2SDouglas Gregor 
475718292f2SDouglas Gregor     bool parseModuleMapFile();
476718292f2SDouglas Gregor   };
477718292f2SDouglas Gregor }
478718292f2SDouglas Gregor 
479718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
480718292f2SDouglas Gregor retry:
481718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
482718292f2SDouglas Gregor   Tok.clear();
483718292f2SDouglas Gregor 
484718292f2SDouglas Gregor   Token LToken;
485718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
486718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
487718292f2SDouglas Gregor   switch (LToken.getKind()) {
488718292f2SDouglas Gregor   case tok::raw_identifier:
489718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
490718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
491718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
492718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
493718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
4942b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
495755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
496718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
497718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
498718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
499718292f2SDouglas Gregor     break;
500718292f2SDouglas Gregor 
501718292f2SDouglas Gregor   case tok::eof:
502718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
503718292f2SDouglas Gregor     break;
504718292f2SDouglas Gregor 
505718292f2SDouglas Gregor   case tok::l_brace:
506718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
507718292f2SDouglas Gregor     break;
508718292f2SDouglas Gregor 
5092b82c2a5SDouglas Gregor   case tok::period:
5102b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
5112b82c2a5SDouglas Gregor     break;
5122b82c2a5SDouglas Gregor 
513718292f2SDouglas Gregor   case tok::r_brace:
514718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
515718292f2SDouglas Gregor     break;
516718292f2SDouglas Gregor 
5172b82c2a5SDouglas Gregor   case tok::star:
5182b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
5192b82c2a5SDouglas Gregor     break;
5202b82c2a5SDouglas Gregor 
521718292f2SDouglas Gregor   case tok::string_literal: {
522718292f2SDouglas Gregor     // Parse the string literal.
523718292f2SDouglas Gregor     LangOptions LangOpts;
524718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
525718292f2SDouglas Gregor     if (StringLiteral.hadError)
526718292f2SDouglas Gregor       goto retry;
527718292f2SDouglas Gregor 
528718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
529718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
530718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
531718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
532718292f2SDouglas Gregor     Saved[Length] = 0;
533718292f2SDouglas Gregor 
534718292f2SDouglas Gregor     // Form the token.
535718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
536718292f2SDouglas Gregor     Tok.StringData = Saved;
537718292f2SDouglas Gregor     Tok.StringLength = Length;
538718292f2SDouglas Gregor     break;
539718292f2SDouglas Gregor   }
540718292f2SDouglas Gregor 
541718292f2SDouglas Gregor   case tok::comment:
542718292f2SDouglas Gregor     goto retry;
543718292f2SDouglas Gregor 
544718292f2SDouglas Gregor   default:
545718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
546718292f2SDouglas Gregor     HadError = true;
547718292f2SDouglas Gregor     goto retry;
548718292f2SDouglas Gregor   }
549718292f2SDouglas Gregor 
550718292f2SDouglas Gregor   return Result;
551718292f2SDouglas Gregor }
552718292f2SDouglas Gregor 
553718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
554718292f2SDouglas Gregor   unsigned braceDepth = 0;
555718292f2SDouglas Gregor   do {
556718292f2SDouglas Gregor     switch (Tok.Kind) {
557718292f2SDouglas Gregor     case MMToken::EndOfFile:
558718292f2SDouglas Gregor       return;
559718292f2SDouglas Gregor 
560718292f2SDouglas Gregor     case MMToken::LBrace:
561718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
562718292f2SDouglas Gregor         return;
563718292f2SDouglas Gregor 
564718292f2SDouglas Gregor       ++braceDepth;
565718292f2SDouglas Gregor       break;
566718292f2SDouglas Gregor 
567718292f2SDouglas Gregor     case MMToken::RBrace:
568718292f2SDouglas Gregor       if (braceDepth > 0)
569718292f2SDouglas Gregor         --braceDepth;
570718292f2SDouglas Gregor       else if (Tok.is(K))
571718292f2SDouglas Gregor         return;
572718292f2SDouglas Gregor       break;
573718292f2SDouglas Gregor 
574718292f2SDouglas Gregor     default:
575718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
576718292f2SDouglas Gregor         return;
577718292f2SDouglas Gregor       break;
578718292f2SDouglas Gregor     }
579718292f2SDouglas Gregor 
580718292f2SDouglas Gregor    consumeToken();
581718292f2SDouglas Gregor   } while (true);
582718292f2SDouglas Gregor }
583718292f2SDouglas Gregor 
584e7ab3669SDouglas Gregor /// \brief Parse a module-id.
585e7ab3669SDouglas Gregor ///
586e7ab3669SDouglas Gregor ///   module-id:
587e7ab3669SDouglas Gregor ///     identifier
588e7ab3669SDouglas Gregor ///     identifier '.' module-id
589e7ab3669SDouglas Gregor ///
590e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
591e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
592e7ab3669SDouglas Gregor   Id.clear();
593e7ab3669SDouglas Gregor   do {
594e7ab3669SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
595e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
596e7ab3669SDouglas Gregor       consumeToken();
597e7ab3669SDouglas Gregor     } else {
598e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
599e7ab3669SDouglas Gregor       return true;
600e7ab3669SDouglas Gregor     }
601e7ab3669SDouglas Gregor 
602e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
603e7ab3669SDouglas Gregor       break;
604e7ab3669SDouglas Gregor 
605e7ab3669SDouglas Gregor     consumeToken();
606e7ab3669SDouglas Gregor   } while (true);
607e7ab3669SDouglas Gregor 
608e7ab3669SDouglas Gregor   return false;
609e7ab3669SDouglas Gregor }
610e7ab3669SDouglas Gregor 
611718292f2SDouglas Gregor /// \brief Parse a module declaration.
612718292f2SDouglas Gregor ///
613718292f2SDouglas Gregor ///   module-declaration:
614e7ab3669SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
615718292f2SDouglas Gregor ///
616718292f2SDouglas Gregor ///   module-member:
617718292f2SDouglas Gregor ///     header-declaration
618e7ab3669SDouglas Gregor ///     submodule-declaration
6192b82c2a5SDouglas Gregor ///     export-declaration
62073441091SDouglas Gregor ///
62173441091SDouglas Gregor ///   submodule-declaration:
62273441091SDouglas Gregor ///     module-declaration
62373441091SDouglas Gregor ///     inferred-submodule-declaration
624718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
625755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
626755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
627f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
628e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
629718292f2SDouglas Gregor   bool Explicit = false;
630f2161a70SDouglas Gregor   bool Framework = false;
631755b2055SDouglas Gregor 
632f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
633f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
634e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
635f2161a70SDouglas Gregor     Explicit = true;
636f2161a70SDouglas Gregor   }
637f2161a70SDouglas Gregor 
638f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
639755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
640755b2055SDouglas Gregor     consumeToken();
641755b2055SDouglas Gregor     Framework = true;
642755b2055SDouglas Gregor   }
643718292f2SDouglas Gregor 
644718292f2SDouglas Gregor   // Parse 'module' keyword.
645718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
646d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
647718292f2SDouglas Gregor     consumeToken();
648718292f2SDouglas Gregor     HadError = true;
649718292f2SDouglas Gregor     return;
650718292f2SDouglas Gregor   }
651718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
652718292f2SDouglas Gregor 
65373441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
65473441091SDouglas Gregor   // Parse it.
65573441091SDouglas Gregor   if (Tok.is(MMToken::Star))
65673441091SDouglas Gregor     return parseInferredSubmoduleDecl(Explicit);
65773441091SDouglas Gregor 
658718292f2SDouglas Gregor   // Parse the module name.
659e7ab3669SDouglas Gregor   ModuleId Id;
660e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
661718292f2SDouglas Gregor     HadError = true;
662718292f2SDouglas Gregor     return;
663718292f2SDouglas Gregor   }
664e7ab3669SDouglas Gregor 
665e7ab3669SDouglas Gregor   if (ActiveModule) {
666e7ab3669SDouglas Gregor     if (Id.size() > 1) {
667e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
668e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
669e7ab3669SDouglas Gregor 
670e7ab3669SDouglas Gregor       HadError = true;
671e7ab3669SDouglas Gregor       return;
672e7ab3669SDouglas Gregor     }
673e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
674e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
675e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
676e7ab3669SDouglas Gregor     Explicit = false;
677e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
678e7ab3669SDouglas Gregor     HadError = true;
679e7ab3669SDouglas Gregor   }
680e7ab3669SDouglas Gregor 
681e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
682e7ab3669SDouglas Gregor   if (Id.size() > 1) {
683e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
684e7ab3669SDouglas Gregor     // is a submodule.
685e7ab3669SDouglas Gregor     ActiveModule = 0;
686e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
687e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
688e7ab3669SDouglas Gregor         ActiveModule = Next;
689e7ab3669SDouglas Gregor         continue;
690e7ab3669SDouglas Gregor       }
691e7ab3669SDouglas Gregor 
692e7ab3669SDouglas Gregor       if (ActiveModule) {
693e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
694e7ab3669SDouglas Gregor           << Id[I].first << ActiveModule->getTopLevelModule();
695e7ab3669SDouglas Gregor       } else {
696e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
697e7ab3669SDouglas Gregor       }
698e7ab3669SDouglas Gregor       HadError = true;
699e7ab3669SDouglas Gregor       return;
700e7ab3669SDouglas Gregor     }
701e7ab3669SDouglas Gregor   }
702e7ab3669SDouglas Gregor 
703e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
704e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
705718292f2SDouglas Gregor 
706718292f2SDouglas Gregor   // Parse the opening brace.
707718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
708718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
709718292f2SDouglas Gregor       << ModuleName;
710718292f2SDouglas Gregor     HadError = true;
711718292f2SDouglas Gregor     return;
712718292f2SDouglas Gregor   }
713718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
714718292f2SDouglas Gregor 
715718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
716718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
717718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
718718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
719718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
720718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
721718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
722718292f2SDouglas Gregor       << ModuleName;
723718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
724718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
725718292f2SDouglas Gregor 
726718292f2SDouglas Gregor     // Skip the module definition.
727718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
728718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
729718292f2SDouglas Gregor       consumeToken();
730718292f2SDouglas Gregor 
731718292f2SDouglas Gregor     HadError = true;
732718292f2SDouglas Gregor     return;
733718292f2SDouglas Gregor   }
734718292f2SDouglas Gregor 
735718292f2SDouglas Gregor   // Start defining this module.
736755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
737755b2055SDouglas Gregor                             Explicit);
738718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
739718292f2SDouglas Gregor 
740718292f2SDouglas Gregor   bool Done = false;
741718292f2SDouglas Gregor   do {
742718292f2SDouglas Gregor     switch (Tok.Kind) {
743718292f2SDouglas Gregor     case MMToken::EndOfFile:
744718292f2SDouglas Gregor     case MMToken::RBrace:
745718292f2SDouglas Gregor       Done = true;
746718292f2SDouglas Gregor       break;
747718292f2SDouglas Gregor 
748718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
749f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
750718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
751718292f2SDouglas Gregor       parseModuleDecl();
752718292f2SDouglas Gregor       break;
753718292f2SDouglas Gregor 
7542b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
7552b82c2a5SDouglas Gregor       parseExportDecl();
7562b82c2a5SDouglas Gregor       break;
7572b82c2a5SDouglas Gregor 
758524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
759524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
760524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
761524e33e1SDouglas Gregor         parseHeaderDecl(UmbrellaLoc);
762524e33e1SDouglas Gregor       else
763524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
764718292f2SDouglas Gregor       break;
765524e33e1SDouglas Gregor     }
766718292f2SDouglas Gregor 
767322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
768322f633cSDouglas Gregor       parseHeaderDecl(SourceLocation());
769718292f2SDouglas Gregor       break;
770718292f2SDouglas Gregor 
771718292f2SDouglas Gregor     default:
772718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
773718292f2SDouglas Gregor       consumeToken();
774718292f2SDouglas Gregor       break;
775718292f2SDouglas Gregor     }
776718292f2SDouglas Gregor   } while (!Done);
777718292f2SDouglas Gregor 
778718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
779718292f2SDouglas Gregor     consumeToken();
780718292f2SDouglas Gregor   else {
781718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
782718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
783718292f2SDouglas Gregor     HadError = true;
784718292f2SDouglas Gregor   }
785718292f2SDouglas Gregor 
786e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
787e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
788718292f2SDouglas Gregor }
789718292f2SDouglas Gregor 
790f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the
791f2161a70SDouglas Gregor /// subframework in which the given module lives.
792f2161a70SDouglas Gregor void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
793f2161a70SDouglas Gregor   // Collect the framework names from the given module to the top-level module.
794f2161a70SDouglas Gregor   llvm::SmallVector<StringRef, 2> Paths;
795f2161a70SDouglas Gregor   for (; Mod; Mod = Mod->Parent) {
796f2161a70SDouglas Gregor     if (Mod->IsFramework)
797f2161a70SDouglas Gregor       Paths.push_back(Mod->Name);
798f2161a70SDouglas Gregor   }
799f2161a70SDouglas Gregor 
800f2161a70SDouglas Gregor   if (Paths.empty())
801f2161a70SDouglas Gregor     return;
802f2161a70SDouglas Gregor 
803f2161a70SDouglas Gregor   // Add Frameworks/Name.framework for each subframework.
804f2161a70SDouglas Gregor   for (unsigned I = Paths.size() - 1; I != 0; --I) {
805f2161a70SDouglas Gregor     llvm::sys::path::append(Path, "Frameworks");
806f2161a70SDouglas Gregor     llvm::sys::path::append(Path, Paths[I-1] + ".framework");
807f2161a70SDouglas Gregor   }
808f2161a70SDouglas Gregor }
809f2161a70SDouglas Gregor 
810718292f2SDouglas Gregor /// \brief Parse a header declaration.
811718292f2SDouglas Gregor ///
812718292f2SDouglas Gregor ///   header-declaration:
813322f633cSDouglas Gregor ///     'umbrella'[opt] 'header' string-literal
814322f633cSDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
815718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
8161871ed3dSBenjamin Kramer   consumeToken();
817718292f2SDouglas Gregor 
818322f633cSDouglas Gregor   bool Umbrella = UmbrellaLoc.isValid();
819322f633cSDouglas Gregor 
820718292f2SDouglas Gregor   // Parse the header name.
821718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
822718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
823718292f2SDouglas Gregor       << "header";
824718292f2SDouglas Gregor     HadError = true;
825718292f2SDouglas Gregor     return;
826718292f2SDouglas Gregor   }
827e7ab3669SDouglas Gregor   std::string FileName = Tok.getString();
828718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
829718292f2SDouglas Gregor 
830524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
831524e33e1SDouglas Gregor   if (Umbrella && ActiveModule->Umbrella) {
832524e33e1SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
833524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
834322f633cSDouglas Gregor     HadError = true;
835322f633cSDouglas Gregor     return;
836322f633cSDouglas Gregor   }
837322f633cSDouglas Gregor 
8385257fc63SDouglas Gregor   // Look for this file.
839e7ab3669SDouglas Gregor   const FileEntry *File = 0;
8405257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
841e7ab3669SDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
842e7ab3669SDouglas Gregor     PathName = FileName;
843e7ab3669SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
8447033127bSDouglas Gregor   } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
8457033127bSDouglas Gregor     PathName = Dir->getName();
8467033127bSDouglas Gregor     llvm::sys::path::append(PathName, FileName);
8477033127bSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
848e7ab3669SDouglas Gregor   } else {
849e7ab3669SDouglas Gregor     // Search for the header file within the search directory.
8507033127bSDouglas Gregor     PathName = Directory->getName();
851e7ab3669SDouglas Gregor     unsigned PathLength = PathName.size();
852755b2055SDouglas Gregor 
853f2161a70SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
854f2161a70SDouglas Gregor       appendSubframeworkPaths(ActiveModule, PathName);
855755b2055SDouglas Gregor 
856e7ab3669SDouglas Gregor       // Check whether this file is in the public headers.
857e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
8585257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
859e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
860e7ab3669SDouglas Gregor 
861e7ab3669SDouglas Gregor       if (!File) {
862e7ab3669SDouglas Gregor         // Check whether this file is in the private headers.
863e7ab3669SDouglas Gregor         PathName.resize(PathLength);
864e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
865e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
866e7ab3669SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
867e7ab3669SDouglas Gregor       }
868e7ab3669SDouglas Gregor     } else {
869e7ab3669SDouglas Gregor       // Lookup for normal headers.
870e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
871e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
872e7ab3669SDouglas Gregor     }
873e7ab3669SDouglas Gregor   }
8745257fc63SDouglas Gregor 
8755257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
8765257fc63SDouglas Gregor   // Come up with a lazy way to do this.
877e7ab3669SDouglas Gregor   if (File) {
8785257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
8795257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
8805257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
8815257fc63SDouglas Gregor       HadError = true;
882322f633cSDouglas Gregor     } else if (Umbrella) {
883322f633cSDouglas Gregor       const DirectoryEntry *UmbrellaDir = File->getDir();
884322f633cSDouglas Gregor       if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
885322f633cSDouglas Gregor         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
886322f633cSDouglas Gregor           << OwningModule->getFullModuleName();
887322f633cSDouglas Gregor         HadError = true;
8885257fc63SDouglas Gregor       } else {
889322f633cSDouglas Gregor         // Record this umbrella header.
890322f633cSDouglas Gregor         Map.setUmbrellaHeader(ActiveModule, File);
891322f633cSDouglas Gregor       }
892322f633cSDouglas Gregor     } else {
893322f633cSDouglas Gregor       // Record this header.
894a89c5ac4SDouglas Gregor       Map.addHeader(ActiveModule, File);
8955257fc63SDouglas Gregor     }
8965257fc63SDouglas Gregor   } else {
8975257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
898524e33e1SDouglas Gregor       << Umbrella << FileName;
8995257fc63SDouglas Gregor     HadError = true;
9005257fc63SDouglas Gregor   }
901718292f2SDouglas Gregor }
902718292f2SDouglas Gregor 
903524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
904524e33e1SDouglas Gregor ///
905524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
906524e33e1SDouglas Gregor ///     umbrella string-literal
907524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
908524e33e1SDouglas Gregor   // Parse the directory name.
909524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
910524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
911524e33e1SDouglas Gregor       << "umbrella";
912524e33e1SDouglas Gregor     HadError = true;
913524e33e1SDouglas Gregor     return;
914524e33e1SDouglas Gregor   }
915524e33e1SDouglas Gregor 
916524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
917524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
918524e33e1SDouglas Gregor 
919524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
920524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
921524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
922524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
923524e33e1SDouglas Gregor     HadError = true;
924524e33e1SDouglas Gregor     return;
925524e33e1SDouglas Gregor   }
926524e33e1SDouglas Gregor 
927524e33e1SDouglas Gregor   // Look for this file.
928524e33e1SDouglas Gregor   const DirectoryEntry *Dir = 0;
929524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
930524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
931524e33e1SDouglas Gregor   else {
932524e33e1SDouglas Gregor     llvm::SmallString<128> PathName;
933524e33e1SDouglas Gregor     PathName = Directory->getName();
934524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
935524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
936524e33e1SDouglas Gregor   }
937524e33e1SDouglas Gregor 
938524e33e1SDouglas Gregor   if (!Dir) {
939524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
940524e33e1SDouglas Gregor       << DirName;
941524e33e1SDouglas Gregor     HadError = true;
942524e33e1SDouglas Gregor     return;
943524e33e1SDouglas Gregor   }
944524e33e1SDouglas Gregor 
945524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
946524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
947524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
948524e33e1SDouglas Gregor     HadError = true;
949524e33e1SDouglas Gregor     return;
950524e33e1SDouglas Gregor   }
951524e33e1SDouglas Gregor 
952524e33e1SDouglas Gregor   // Record this umbrella directory.
953524e33e1SDouglas Gregor   Map.setUmbrellaDir(ActiveModule, Dir);
954524e33e1SDouglas Gregor }
955524e33e1SDouglas Gregor 
9562b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
9572b82c2a5SDouglas Gregor ///
9582b82c2a5SDouglas Gregor ///   export-declaration:
9592b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
9602b82c2a5SDouglas Gregor ///
9612b82c2a5SDouglas Gregor ///   wildcard-module-id:
9622b82c2a5SDouglas Gregor ///     identifier
9632b82c2a5SDouglas Gregor ///     '*'
9642b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
9652b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
9662b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
9672b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
9682b82c2a5SDouglas Gregor 
9692b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
9702b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
9712b82c2a5SDouglas Gregor   bool Wildcard = false;
9722b82c2a5SDouglas Gregor   do {
9732b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
9742b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
9752b82c2a5SDouglas Gregor                                               Tok.getLocation()));
9762b82c2a5SDouglas Gregor       consumeToken();
9772b82c2a5SDouglas Gregor 
9782b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
9792b82c2a5SDouglas Gregor         consumeToken();
9802b82c2a5SDouglas Gregor         continue;
9812b82c2a5SDouglas Gregor       }
9822b82c2a5SDouglas Gregor 
9832b82c2a5SDouglas Gregor       break;
9842b82c2a5SDouglas Gregor     }
9852b82c2a5SDouglas Gregor 
9862b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
9872b82c2a5SDouglas Gregor       Wildcard = true;
988f5eedd05SDouglas Gregor       consumeToken();
9892b82c2a5SDouglas Gregor       break;
9902b82c2a5SDouglas Gregor     }
9912b82c2a5SDouglas Gregor 
9922b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
9932b82c2a5SDouglas Gregor     HadError = true;
9942b82c2a5SDouglas Gregor     return;
9952b82c2a5SDouglas Gregor   } while (true);
9962b82c2a5SDouglas Gregor 
9972b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
9982b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
9992b82c2a5SDouglas Gregor   };
10002b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
10012b82c2a5SDouglas Gregor }
10022b82c2a5SDouglas Gregor 
100373441091SDouglas Gregor void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
100473441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
100573441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
100673441091SDouglas Gregor   bool Failed = false;
100773441091SDouglas Gregor 
100873441091SDouglas Gregor   // Inferred modules must be submodules.
100973441091SDouglas Gregor   if (!ActiveModule) {
101073441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
101173441091SDouglas Gregor     Failed = true;
101273441091SDouglas Gregor   }
101373441091SDouglas Gregor 
1014524e33e1SDouglas Gregor   // Inferred modules must have umbrella directories.
1015524e33e1SDouglas Gregor   if (!Failed && !ActiveModule->getUmbrellaDir()) {
101673441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
101773441091SDouglas Gregor     Failed = true;
101873441091SDouglas Gregor   }
101973441091SDouglas Gregor 
102073441091SDouglas Gregor   // Check for redefinition of an inferred module.
1021dd005f69SDouglas Gregor   if (!Failed && ActiveModule->InferSubmodules) {
102273441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1023dd005f69SDouglas Gregor     if (ActiveModule->InferredSubmoduleLoc.isValid())
1024dd005f69SDouglas Gregor       Diags.Report(ActiveModule->InferredSubmoduleLoc,
102573441091SDouglas Gregor                    diag::note_mmap_prev_definition);
102673441091SDouglas Gregor     Failed = true;
102773441091SDouglas Gregor   }
102873441091SDouglas Gregor 
102973441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
103073441091SDouglas Gregor   if (Failed) {
103173441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
103273441091SDouglas Gregor       consumeToken();
103373441091SDouglas Gregor       skipUntil(MMToken::RBrace);
103473441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
103573441091SDouglas Gregor         consumeToken();
103673441091SDouglas Gregor     }
103773441091SDouglas Gregor     HadError = true;
103873441091SDouglas Gregor     return;
103973441091SDouglas Gregor   }
104073441091SDouglas Gregor 
104173441091SDouglas Gregor   // Note that we have an inferred submodule.
1042dd005f69SDouglas Gregor   ActiveModule->InferSubmodules = true;
1043dd005f69SDouglas Gregor   ActiveModule->InferredSubmoduleLoc = StarLoc;
1044dd005f69SDouglas Gregor   ActiveModule->InferExplicitSubmodules = Explicit;
104573441091SDouglas Gregor 
104673441091SDouglas Gregor   // Parse the opening brace.
104773441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
104873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
104973441091SDouglas Gregor     HadError = true;
105073441091SDouglas Gregor     return;
105173441091SDouglas Gregor   }
105273441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
105373441091SDouglas Gregor 
105473441091SDouglas Gregor   // Parse the body of the inferred submodule.
105573441091SDouglas Gregor   bool Done = false;
105673441091SDouglas Gregor   do {
105773441091SDouglas Gregor     switch (Tok.Kind) {
105873441091SDouglas Gregor     case MMToken::EndOfFile:
105973441091SDouglas Gregor     case MMToken::RBrace:
106073441091SDouglas Gregor       Done = true;
106173441091SDouglas Gregor       break;
106273441091SDouglas Gregor 
106373441091SDouglas Gregor     case MMToken::ExportKeyword: {
106473441091SDouglas Gregor       consumeToken();
106573441091SDouglas Gregor       if (Tok.is(MMToken::Star))
1066dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
106773441091SDouglas Gregor       else
106873441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
106973441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
107073441091SDouglas Gregor       consumeToken();
107173441091SDouglas Gregor       break;
107273441091SDouglas Gregor     }
107373441091SDouglas Gregor 
107473441091SDouglas Gregor     case MMToken::ExplicitKeyword:
107573441091SDouglas Gregor     case MMToken::ModuleKeyword:
107673441091SDouglas Gregor     case MMToken::HeaderKeyword:
107773441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
107873441091SDouglas Gregor     default:
107973441091SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
108073441091SDouglas Gregor       consumeToken();
108173441091SDouglas Gregor       break;
108273441091SDouglas Gregor     }
108373441091SDouglas Gregor   } while (!Done);
108473441091SDouglas Gregor 
108573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
108673441091SDouglas Gregor     consumeToken();
108773441091SDouglas Gregor   else {
108873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
108973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
109073441091SDouglas Gregor     HadError = true;
109173441091SDouglas Gregor   }
109273441091SDouglas Gregor }
109373441091SDouglas Gregor 
10947033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence
10957033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null.
10967033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
10977033127bSDouglas Gregor   for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
10987033127bSDouglas Gregor     // If we have an umbrella directory, use that.
10997033127bSDouglas Gregor     if (Mod->hasUmbrellaDir())
11007033127bSDouglas Gregor       return Mod->getUmbrellaDir();
11017033127bSDouglas Gregor 
11027033127bSDouglas Gregor     // If we have a framework directory, stop looking.
11037033127bSDouglas Gregor     if (Mod->IsFramework)
11047033127bSDouglas Gregor       return 0;
11057033127bSDouglas Gregor   }
11067033127bSDouglas Gregor 
11077033127bSDouglas Gregor   return 0;
11087033127bSDouglas Gregor }
11097033127bSDouglas Gregor 
1110718292f2SDouglas Gregor /// \brief Parse a module map file.
1111718292f2SDouglas Gregor ///
1112718292f2SDouglas Gregor ///   module-map-file:
1113718292f2SDouglas Gregor ///     module-declaration*
1114718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
1115718292f2SDouglas Gregor   do {
1116718292f2SDouglas Gregor     switch (Tok.Kind) {
1117718292f2SDouglas Gregor     case MMToken::EndOfFile:
1118718292f2SDouglas Gregor       return HadError;
1119718292f2SDouglas Gregor 
1120e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
1121718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1122755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
1123718292f2SDouglas Gregor       parseModuleDecl();
1124718292f2SDouglas Gregor       break;
1125718292f2SDouglas Gregor 
11262b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
1127718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
1128718292f2SDouglas Gregor     case MMToken::Identifier:
1129718292f2SDouglas Gregor     case MMToken::LBrace:
11302b82c2a5SDouglas Gregor     case MMToken::Period:
1131718292f2SDouglas Gregor     case MMToken::RBrace:
11322b82c2a5SDouglas Gregor     case MMToken::Star:
1133718292f2SDouglas Gregor     case MMToken::StringLiteral:
1134718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
1135718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1136718292f2SDouglas Gregor       HadError = true;
1137718292f2SDouglas Gregor       consumeToken();
1138718292f2SDouglas Gregor       break;
1139718292f2SDouglas Gregor     }
1140718292f2SDouglas Gregor   } while (true);
1141718292f2SDouglas Gregor 
1142718292f2SDouglas Gregor   return HadError;
1143718292f2SDouglas Gregor }
1144718292f2SDouglas Gregor 
1145718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1146718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1147718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1148718292f2SDouglas Gregor   if (!Buffer)
1149718292f2SDouglas Gregor     return true;
1150718292f2SDouglas Gregor 
1151718292f2SDouglas Gregor   // Parse this module map file.
1152718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
1153718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
11545257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
1155718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
1156718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
1157718292f2SDouglas Gregor 
1158718292f2SDouglas Gregor   return Result;
1159718292f2SDouglas Gregor }
1160