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 
721fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
731fb5c3a6SDouglas Gregor                      const LangOptions &LangOpts)
741fb5c3a6SDouglas Gregor   : LangOpts(LangOpts)
751fb5c3a6SDouglas Gregor {
76718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
77718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
78718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
79718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
80718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
81718292f2SDouglas Gregor }
82718292f2SDouglas Gregor 
83718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
845acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
855acdf59eSDouglas Gregor                                         IEnd = Modules.end();
865acdf59eSDouglas Gregor        I != IEnd; ++I) {
875acdf59eSDouglas Gregor     delete I->getValue();
885acdf59eSDouglas Gregor   }
895acdf59eSDouglas Gregor 
90718292f2SDouglas Gregor   delete SourceMgr;
91718292f2SDouglas Gregor }
92718292f2SDouglas Gregor 
93de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
94ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
95ab0c8a84SDouglas Gregor     = Headers.find(File);
961fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
971fb5c3a6SDouglas Gregor     // If a header corresponds to an unavailable module, don't report
981fb5c3a6SDouglas Gregor     // that it maps to anything.
991fb5c3a6SDouglas Gregor     if (!Known->second->isAvailable())
1001fb5c3a6SDouglas Gregor       return 0;
1011fb5c3a6SDouglas Gregor 
102ab0c8a84SDouglas Gregor     return Known->second;
1031fb5c3a6SDouglas Gregor   }
104ab0c8a84SDouglas Gregor 
105b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
106b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
107b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
108a89c5ac4SDouglas Gregor 
109a89c5ac4SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
110a89c5ac4SDouglas Gregor   // an umbrella header.
111b65dbfffSDouglas Gregor   do {
112a89c5ac4SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
113a89c5ac4SDouglas Gregor       = UmbrellaDirs.find(Dir);
114a89c5ac4SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
115a89c5ac4SDouglas Gregor       Module *Result = KnownDir->second;
116930a85ccSDouglas Gregor 
117930a85ccSDouglas Gregor       // Search up the module stack until we find a module with an umbrella
11873141fa9SDouglas Gregor       // directory.
119930a85ccSDouglas Gregor       Module *UmbrellaModule = Result;
12073141fa9SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
121930a85ccSDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
122930a85ccSDouglas Gregor 
123930a85ccSDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
124a89c5ac4SDouglas Gregor         // Infer submodules for each of the directories we found between
125a89c5ac4SDouglas Gregor         // the directory of the umbrella header and the directory where
126a89c5ac4SDouglas Gregor         // the actual header is located.
1279458f82dSDouglas Gregor         bool Explicit = UmbrellaModule->InferExplicitSubmodules;
1289458f82dSDouglas Gregor 
1297033127bSDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
130a89c5ac4SDouglas Gregor           // Find or create the module that corresponds to this directory name.
131a89c5ac4SDouglas Gregor           StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
132a89c5ac4SDouglas Gregor           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
1339458f82dSDouglas Gregor                                       Explicit).first;
134a89c5ac4SDouglas Gregor 
135a89c5ac4SDouglas Gregor           // Associate the module and the directory.
136a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I-1]] = Result;
137a89c5ac4SDouglas Gregor 
138a89c5ac4SDouglas Gregor           // If inferred submodules export everything they import, add a
139a89c5ac4SDouglas Gregor           // wildcard to the set of exports.
140930a85ccSDouglas Gregor           if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
141a89c5ac4SDouglas Gregor             Result->Exports.push_back(Module::ExportDecl(0, true));
142a89c5ac4SDouglas Gregor         }
143a89c5ac4SDouglas Gregor 
144a89c5ac4SDouglas Gregor         // Infer a submodule with the same name as this header file.
145a89c5ac4SDouglas Gregor         StringRef Name = llvm::sys::path::stem(File->getName());
146a89c5ac4SDouglas Gregor         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
1479458f82dSDouglas Gregor                                     Explicit).first;
148a89c5ac4SDouglas Gregor 
149a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
150a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
151930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
152a89c5ac4SDouglas Gregor           Result->Exports.push_back(Module::ExportDecl(0, true));
153a89c5ac4SDouglas Gregor       } else {
154a89c5ac4SDouglas Gregor         // Record each of the directories we stepped through as being part of
155a89c5ac4SDouglas Gregor         // the module we found, since the umbrella header covers them all.
156a89c5ac4SDouglas Gregor         for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
157a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I]] = Result;
158a89c5ac4SDouglas Gregor       }
159a89c5ac4SDouglas Gregor 
160a89c5ac4SDouglas Gregor       Headers[File] = Result;
1611fb5c3a6SDouglas Gregor 
1621fb5c3a6SDouglas Gregor       // If a header corresponds to an unavailable module, don't report
1631fb5c3a6SDouglas Gregor       // that it maps to anything.
1641fb5c3a6SDouglas Gregor       if (!Result->isAvailable())
1651fb5c3a6SDouglas Gregor         return 0;
1661fb5c3a6SDouglas Gregor 
167a89c5ac4SDouglas Gregor       return Result;
168a89c5ac4SDouglas Gregor     }
169a89c5ac4SDouglas Gregor 
170a89c5ac4SDouglas Gregor     SkippedDirs.push_back(Dir);
171a89c5ac4SDouglas Gregor 
172b65dbfffSDouglas Gregor     // Retrieve our parent path.
173b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
174b65dbfffSDouglas Gregor     if (DirName.empty())
175b65dbfffSDouglas Gregor       break;
176b65dbfffSDouglas Gregor 
177b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
178b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
179a89c5ac4SDouglas Gregor   } while (Dir);
180b65dbfffSDouglas Gregor 
181ab0c8a84SDouglas Gregor   return 0;
182ab0c8a84SDouglas Gregor }
183ab0c8a84SDouglas Gregor 
1841fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
1851fb5c3a6SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
1861fb5c3a6SDouglas Gregor     = Headers.find(Header);
1871fb5c3a6SDouglas Gregor   if (Known != Headers.end())
1881fb5c3a6SDouglas Gregor     return !Known->second->isAvailable();
1891fb5c3a6SDouglas Gregor 
1901fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
1911fb5c3a6SDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
1921fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
1931fb5c3a6SDouglas Gregor 
1941fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
1951fb5c3a6SDouglas Gregor   // an umbrella header.
1961fb5c3a6SDouglas Gregor   do {
1971fb5c3a6SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
1981fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
1991fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
2001fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
2011fb5c3a6SDouglas Gregor       if (!Found->isAvailable())
2021fb5c3a6SDouglas Gregor         return true;
2031fb5c3a6SDouglas Gregor 
2041fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
2051fb5c3a6SDouglas Gregor       // directory.
2061fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
2071fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
2081fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
2091fb5c3a6SDouglas Gregor 
2101fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
2111fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
2121fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
2131fb5c3a6SDouglas Gregor           StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
2141fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
2151fb5c3a6SDouglas Gregor           if (!Found)
2161fb5c3a6SDouglas Gregor             return false;
2171fb5c3a6SDouglas Gregor           if (!Found->isAvailable())
2181fb5c3a6SDouglas Gregor             return true;
2191fb5c3a6SDouglas Gregor         }
2201fb5c3a6SDouglas Gregor 
2211fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
2221fb5c3a6SDouglas Gregor         StringRef Name = llvm::sys::path::stem(Header->getName());
2231fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
2241fb5c3a6SDouglas Gregor         if (!Found)
2251fb5c3a6SDouglas Gregor           return false;
2261fb5c3a6SDouglas Gregor       }
2271fb5c3a6SDouglas Gregor 
2281fb5c3a6SDouglas Gregor       return !Found->isAvailable();
2291fb5c3a6SDouglas Gregor     }
2301fb5c3a6SDouglas Gregor 
2311fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
2321fb5c3a6SDouglas Gregor 
2331fb5c3a6SDouglas Gregor     // Retrieve our parent path.
2341fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
2351fb5c3a6SDouglas Gregor     if (DirName.empty())
2361fb5c3a6SDouglas Gregor       break;
2371fb5c3a6SDouglas Gregor 
2381fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
2391fb5c3a6SDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
2401fb5c3a6SDouglas Gregor   } while (Dir);
2411fb5c3a6SDouglas Gregor 
2421fb5c3a6SDouglas Gregor   return false;
2431fb5c3a6SDouglas Gregor }
2441fb5c3a6SDouglas Gregor 
245de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
24688bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
24788bdfb0eSDouglas Gregor   if (Known != Modules.end())
24888bdfb0eSDouglas Gregor     return Known->getValue();
24988bdfb0eSDouglas Gregor 
25088bdfb0eSDouglas Gregor   return 0;
25188bdfb0eSDouglas Gregor }
25288bdfb0eSDouglas Gregor 
2532b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
2542b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
2552b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
2562b82c2a5SDouglas Gregor       return Sub;
2572b82c2a5SDouglas Gregor   }
2582b82c2a5SDouglas Gregor 
2592b82c2a5SDouglas Gregor   return findModule(Name);
2602b82c2a5SDouglas Gregor }
2612b82c2a5SDouglas Gregor 
2622b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
2632b82c2a5SDouglas Gregor   if (!Context)
2642b82c2a5SDouglas Gregor     return findModule(Name);
2652b82c2a5SDouglas Gregor 
266eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
2672b82c2a5SDouglas Gregor }
2682b82c2a5SDouglas Gregor 
269de3ef502SDouglas Gregor std::pair<Module *, bool>
27069021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
27169021974SDouglas Gregor                               bool IsExplicit) {
27269021974SDouglas Gregor   // Try to find an existing module with this name.
273eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
274eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
27569021974SDouglas Gregor 
27669021974SDouglas Gregor   // Create a new module with this name.
27769021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
27869021974SDouglas Gregor                               IsExplicit);
279eb90e830SDouglas Gregor   if (!Parent)
28069021974SDouglas Gregor     Modules[Name] = Result;
28169021974SDouglas Gregor   return std::make_pair(Result, true);
28269021974SDouglas Gregor }
28369021974SDouglas Gregor 
284de3ef502SDouglas Gregor Module *
28556c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
286e89dbc1dSDouglas Gregor                                 const DirectoryEntry *FrameworkDir,
287*a686e1b0SDouglas Gregor                                 bool IsSystem,
288e89dbc1dSDouglas Gregor                                 Module *Parent) {
28956c64013SDouglas Gregor   // Check whether we've already found this module.
290e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
291e89dbc1dSDouglas Gregor     return Mod;
292e89dbc1dSDouglas Gregor 
293e89dbc1dSDouglas Gregor   FileManager &FileMgr = SourceMgr->getFileManager();
29456c64013SDouglas Gregor 
29556c64013SDouglas Gregor   // Look for an umbrella header.
29656c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
29756c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
29856c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
299e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
30056c64013SDouglas Gregor 
30156c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
30256c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
30356c64013SDouglas Gregor   // idea.
30456c64013SDouglas Gregor   if (!UmbrellaHeader)
30556c64013SDouglas Gregor     return 0;
30656c64013SDouglas Gregor 
307e89dbc1dSDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
308e89dbc1dSDouglas Gregor                               /*IsFramework=*/true, /*IsExplicit=*/false);
309*a686e1b0SDouglas Gregor   if (IsSystem)
310*a686e1b0SDouglas Gregor     Result->IsSystem = IsSystem;
311*a686e1b0SDouglas Gregor 
312eb90e830SDouglas Gregor   if (!Parent)
313e89dbc1dSDouglas Gregor     Modules[ModuleName] = Result;
314e89dbc1dSDouglas Gregor 
315322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
31673141fa9SDouglas Gregor   Result->Umbrella = UmbrellaHeader;
31756c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
3184dc71835SDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
319d8bd7537SDouglas Gregor 
320d8bd7537SDouglas Gregor   // export *
321d8bd7537SDouglas Gregor   Result->Exports.push_back(Module::ExportDecl(0, true));
322d8bd7537SDouglas Gregor 
323a89c5ac4SDouglas Gregor   // module * { export * }
324a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
325a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
326a89c5ac4SDouglas Gregor 
327e89dbc1dSDouglas Gregor   // Look for subframeworks.
328e89dbc1dSDouglas Gregor   llvm::error_code EC;
329ddaa69cbSDouglas Gregor   llvm::SmallString<128> SubframeworksDirName
330ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
331e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
332ddaa69cbSDouglas Gregor   llvm::SmallString<128> SubframeworksDirNameNative;
333ddaa69cbSDouglas Gregor   llvm::sys::path::native(SubframeworksDirName.str(),
334ddaa69cbSDouglas Gregor                           SubframeworksDirNameNative);
335ddaa69cbSDouglas Gregor   for (llvm::sys::fs::directory_iterator
336ddaa69cbSDouglas Gregor          Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
337e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
338e89dbc1dSDouglas Gregor     if (!StringRef(Dir->path()).endswith(".framework"))
339e89dbc1dSDouglas Gregor       continue;
340f2161a70SDouglas Gregor 
341e89dbc1dSDouglas Gregor     if (const DirectoryEntry *SubframeworkDir
342e89dbc1dSDouglas Gregor           = FileMgr.getDirectory(Dir->path())) {
343e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
344e89dbc1dSDouglas Gregor       inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
345*a686e1b0SDouglas Gregor                            IsSystem, Result);
346e89dbc1dSDouglas Gregor     }
347e89dbc1dSDouglas Gregor   }
348e89dbc1dSDouglas Gregor 
34956c64013SDouglas Gregor   return Result;
35056c64013SDouglas Gregor }
35156c64013SDouglas Gregor 
352a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
353a89c5ac4SDouglas Gregor   Headers[UmbrellaHeader] = Mod;
35473141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
3557033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
356a89c5ac4SDouglas Gregor }
357a89c5ac4SDouglas Gregor 
358524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
359524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
360524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
361524e33e1SDouglas Gregor }
362524e33e1SDouglas Gregor 
363a89c5ac4SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
364a89c5ac4SDouglas Gregor   Mod->Headers.push_back(Header);
365a89c5ac4SDouglas Gregor   Headers[Header] = Mod;
366a89c5ac4SDouglas Gregor }
367a89c5ac4SDouglas Gregor 
368514b636aSDouglas Gregor const FileEntry *
369de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
370514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
371514b636aSDouglas Gregor     return 0;
372514b636aSDouglas Gregor 
373514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
374514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
375514b636aSDouglas Gregor }
376514b636aSDouglas Gregor 
377718292f2SDouglas Gregor void ModuleMap::dump() {
378718292f2SDouglas Gregor   llvm::errs() << "Modules:";
379718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
380718292f2SDouglas Gregor                                         MEnd = Modules.end();
381718292f2SDouglas Gregor        M != MEnd; ++M)
382d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
383718292f2SDouglas Gregor 
384718292f2SDouglas Gregor   llvm::errs() << "Headers:";
385718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
386718292f2SDouglas Gregor             H = Headers.begin(),
387718292f2SDouglas Gregor          HEnd = Headers.end();
388718292f2SDouglas Gregor        H != HEnd; ++H) {
389718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
390718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
391718292f2SDouglas Gregor   }
392718292f2SDouglas Gregor }
393718292f2SDouglas Gregor 
3942b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
3952b82c2a5SDouglas Gregor   bool HadError = false;
3962b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
3972b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
3982b82c2a5SDouglas Gregor                                               Complain);
399f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
4002b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
4012b82c2a5SDouglas Gregor     else
4022b82c2a5SDouglas Gregor       HadError = true;
4032b82c2a5SDouglas Gregor   }
4042b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
4052b82c2a5SDouglas Gregor   return HadError;
4062b82c2a5SDouglas Gregor }
4072b82c2a5SDouglas Gregor 
4080093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
4090093b3c7SDouglas Gregor   if (Loc.isInvalid())
4100093b3c7SDouglas Gregor     return 0;
4110093b3c7SDouglas Gregor 
4120093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
4130093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
4140093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
4150093b3c7SDouglas Gregor     return 0;
4160093b3c7SDouglas Gregor 
4170093b3c7SDouglas Gregor 
4180093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
4190093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
420224d8a74SDouglas Gregor 
421224d8a74SDouglas Gregor   while (const FileEntry *ExpansionFile
422224d8a74SDouglas Gregor            = SrcMgr.getFileEntryForID(ExpansionFileID)) {
423224d8a74SDouglas Gregor     // Find the module that owns this header (if any).
424224d8a74SDouglas Gregor     if (Module *Mod = findModuleForHeader(ExpansionFile))
425224d8a74SDouglas Gregor       return Mod;
426224d8a74SDouglas Gregor 
427224d8a74SDouglas Gregor     // No module owns this header, so look up the inclusion chain to see if
428224d8a74SDouglas Gregor     // any included header has an associated module.
429224d8a74SDouglas Gregor     SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
430224d8a74SDouglas Gregor     if (IncludeLoc.isInvalid())
4310093b3c7SDouglas Gregor       return 0;
4320093b3c7SDouglas Gregor 
433224d8a74SDouglas Gregor     ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
434224d8a74SDouglas Gregor   }
435224d8a74SDouglas Gregor 
436224d8a74SDouglas Gregor   return 0;
4370093b3c7SDouglas Gregor }
4380093b3c7SDouglas Gregor 
439718292f2SDouglas Gregor //----------------------------------------------------------------------------//
440718292f2SDouglas Gregor // Module map file parser
441718292f2SDouglas Gregor //----------------------------------------------------------------------------//
442718292f2SDouglas Gregor 
443718292f2SDouglas Gregor namespace clang {
444718292f2SDouglas Gregor   /// \brief A token in a module map file.
445718292f2SDouglas Gregor   struct MMToken {
446718292f2SDouglas Gregor     enum TokenKind {
4471fb5c3a6SDouglas Gregor       Comma,
448718292f2SDouglas Gregor       EndOfFile,
449718292f2SDouglas Gregor       HeaderKeyword,
450718292f2SDouglas Gregor       Identifier,
451718292f2SDouglas Gregor       ExplicitKeyword,
4522b82c2a5SDouglas Gregor       ExportKeyword,
453755b2055SDouglas Gregor       FrameworkKeyword,
454718292f2SDouglas Gregor       ModuleKeyword,
4552b82c2a5SDouglas Gregor       Period,
456718292f2SDouglas Gregor       UmbrellaKeyword,
4571fb5c3a6SDouglas Gregor       RequiresKeyword,
4582b82c2a5SDouglas Gregor       Star,
459718292f2SDouglas Gregor       StringLiteral,
460718292f2SDouglas Gregor       LBrace,
461*a686e1b0SDouglas Gregor       RBrace,
462*a686e1b0SDouglas Gregor       LSquare,
463*a686e1b0SDouglas Gregor       RSquare
464718292f2SDouglas Gregor     } Kind;
465718292f2SDouglas Gregor 
466718292f2SDouglas Gregor     unsigned Location;
467718292f2SDouglas Gregor     unsigned StringLength;
468718292f2SDouglas Gregor     const char *StringData;
469718292f2SDouglas Gregor 
470718292f2SDouglas Gregor     void clear() {
471718292f2SDouglas Gregor       Kind = EndOfFile;
472718292f2SDouglas Gregor       Location = 0;
473718292f2SDouglas Gregor       StringLength = 0;
474718292f2SDouglas Gregor       StringData = 0;
475718292f2SDouglas Gregor     }
476718292f2SDouglas Gregor 
477718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
478718292f2SDouglas Gregor 
479718292f2SDouglas Gregor     SourceLocation getLocation() const {
480718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
481718292f2SDouglas Gregor     }
482718292f2SDouglas Gregor 
483718292f2SDouglas Gregor     StringRef getString() const {
484718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
485718292f2SDouglas Gregor     }
486718292f2SDouglas Gregor   };
487718292f2SDouglas Gregor 
488718292f2SDouglas Gregor   class ModuleMapParser {
489718292f2SDouglas Gregor     Lexer &L;
490718292f2SDouglas Gregor     SourceManager &SourceMgr;
491718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
492718292f2SDouglas Gregor     ModuleMap &Map;
493718292f2SDouglas Gregor 
4945257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
4955257fc63SDouglas Gregor     const DirectoryEntry *Directory;
4965257fc63SDouglas Gregor 
497718292f2SDouglas Gregor     /// \brief Whether an error occurred.
498718292f2SDouglas Gregor     bool HadError;
499718292f2SDouglas Gregor 
500718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
501718292f2SDouglas Gregor     /// parsing.
502718292f2SDouglas Gregor     TargetInfo *Target;
503718292f2SDouglas Gregor 
504718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
505718292f2SDouglas Gregor     /// during parsing.
506718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
507718292f2SDouglas Gregor 
508718292f2SDouglas Gregor     /// \brief The current token.
509718292f2SDouglas Gregor     MMToken Tok;
510718292f2SDouglas Gregor 
511718292f2SDouglas Gregor     /// \brief The active module.
512de3ef502SDouglas Gregor     Module *ActiveModule;
513718292f2SDouglas Gregor 
514718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
515718292f2SDouglas Gregor     SourceLocation consumeToken();
516718292f2SDouglas Gregor 
517718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
518718292f2SDouglas Gregor     /// (or the end of the file).
519718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
520718292f2SDouglas Gregor 
521e7ab3669SDouglas Gregor     typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
522e7ab3669SDouglas Gregor       ModuleId;
523e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
524718292f2SDouglas Gregor     void parseModuleDecl();
5251fb5c3a6SDouglas Gregor     void parseRequiresDecl();
526322f633cSDouglas Gregor     void parseHeaderDecl(SourceLocation UmbrellaLoc);
527524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
5282b82c2a5SDouglas Gregor     void parseExportDecl();
52973441091SDouglas Gregor     void parseInferredSubmoduleDecl(bool Explicit);
530718292f2SDouglas Gregor 
5317033127bSDouglas Gregor     const DirectoryEntry *getOverriddenHeaderSearchDir();
5327033127bSDouglas Gregor 
533718292f2SDouglas Gregor   public:
534718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
535718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
5365257fc63SDouglas Gregor                              ModuleMap &Map,
5375257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
5385257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
5395257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
540718292f2SDouglas Gregor     {
541718292f2SDouglas Gregor       TargetOptions TargetOpts;
542718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
543718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
544718292f2SDouglas Gregor 
545718292f2SDouglas Gregor       Tok.clear();
546718292f2SDouglas Gregor       consumeToken();
547718292f2SDouglas Gregor     }
548718292f2SDouglas Gregor 
549718292f2SDouglas Gregor     bool parseModuleMapFile();
550718292f2SDouglas Gregor   };
551718292f2SDouglas Gregor }
552718292f2SDouglas Gregor 
553718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
554718292f2SDouglas Gregor retry:
555718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
556718292f2SDouglas Gregor   Tok.clear();
557718292f2SDouglas Gregor 
558718292f2SDouglas Gregor   Token LToken;
559718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
560718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
561718292f2SDouglas Gregor   switch (LToken.getKind()) {
562718292f2SDouglas Gregor   case tok::raw_identifier:
563718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
564718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
565718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
566718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
567718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
5682b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
569755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
570718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
5711fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
572718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
573718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
574718292f2SDouglas Gregor     break;
575718292f2SDouglas Gregor 
5761fb5c3a6SDouglas Gregor   case tok::comma:
5771fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
5781fb5c3a6SDouglas Gregor     break;
5791fb5c3a6SDouglas Gregor 
580718292f2SDouglas Gregor   case tok::eof:
581718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
582718292f2SDouglas Gregor     break;
583718292f2SDouglas Gregor 
584718292f2SDouglas Gregor   case tok::l_brace:
585718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
586718292f2SDouglas Gregor     break;
587718292f2SDouglas Gregor 
588*a686e1b0SDouglas Gregor   case tok::l_square:
589*a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
590*a686e1b0SDouglas Gregor     break;
591*a686e1b0SDouglas Gregor 
5922b82c2a5SDouglas Gregor   case tok::period:
5932b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
5942b82c2a5SDouglas Gregor     break;
5952b82c2a5SDouglas Gregor 
596718292f2SDouglas Gregor   case tok::r_brace:
597718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
598718292f2SDouglas Gregor     break;
599718292f2SDouglas Gregor 
600*a686e1b0SDouglas Gregor   case tok::r_square:
601*a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
602*a686e1b0SDouglas Gregor     break;
603*a686e1b0SDouglas Gregor 
6042b82c2a5SDouglas Gregor   case tok::star:
6052b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
6062b82c2a5SDouglas Gregor     break;
6072b82c2a5SDouglas Gregor 
608718292f2SDouglas Gregor   case tok::string_literal: {
609718292f2SDouglas Gregor     // Parse the string literal.
610718292f2SDouglas Gregor     LangOptions LangOpts;
611718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
612718292f2SDouglas Gregor     if (StringLiteral.hadError)
613718292f2SDouglas Gregor       goto retry;
614718292f2SDouglas Gregor 
615718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
616718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
617718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
618718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
619718292f2SDouglas Gregor     Saved[Length] = 0;
620718292f2SDouglas Gregor 
621718292f2SDouglas Gregor     // Form the token.
622718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
623718292f2SDouglas Gregor     Tok.StringData = Saved;
624718292f2SDouglas Gregor     Tok.StringLength = Length;
625718292f2SDouglas Gregor     break;
626718292f2SDouglas Gregor   }
627718292f2SDouglas Gregor 
628718292f2SDouglas Gregor   case tok::comment:
629718292f2SDouglas Gregor     goto retry;
630718292f2SDouglas Gregor 
631718292f2SDouglas Gregor   default:
632718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
633718292f2SDouglas Gregor     HadError = true;
634718292f2SDouglas Gregor     goto retry;
635718292f2SDouglas Gregor   }
636718292f2SDouglas Gregor 
637718292f2SDouglas Gregor   return Result;
638718292f2SDouglas Gregor }
639718292f2SDouglas Gregor 
640718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
641718292f2SDouglas Gregor   unsigned braceDepth = 0;
642*a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
643718292f2SDouglas Gregor   do {
644718292f2SDouglas Gregor     switch (Tok.Kind) {
645718292f2SDouglas Gregor     case MMToken::EndOfFile:
646718292f2SDouglas Gregor       return;
647718292f2SDouglas Gregor 
648718292f2SDouglas Gregor     case MMToken::LBrace:
649*a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
650718292f2SDouglas Gregor         return;
651718292f2SDouglas Gregor 
652718292f2SDouglas Gregor       ++braceDepth;
653718292f2SDouglas Gregor       break;
654718292f2SDouglas Gregor 
655*a686e1b0SDouglas Gregor     case MMToken::LSquare:
656*a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
657*a686e1b0SDouglas Gregor         return;
658*a686e1b0SDouglas Gregor 
659*a686e1b0SDouglas Gregor       ++squareDepth;
660*a686e1b0SDouglas Gregor       break;
661*a686e1b0SDouglas Gregor 
662718292f2SDouglas Gregor     case MMToken::RBrace:
663718292f2SDouglas Gregor       if (braceDepth > 0)
664718292f2SDouglas Gregor         --braceDepth;
665718292f2SDouglas Gregor       else if (Tok.is(K))
666718292f2SDouglas Gregor         return;
667718292f2SDouglas Gregor       break;
668718292f2SDouglas Gregor 
669*a686e1b0SDouglas Gregor     case MMToken::RSquare:
670*a686e1b0SDouglas Gregor       if (squareDepth > 0)
671*a686e1b0SDouglas Gregor         --squareDepth;
672*a686e1b0SDouglas Gregor       else if (Tok.is(K))
673*a686e1b0SDouglas Gregor         return;
674*a686e1b0SDouglas Gregor       break;
675*a686e1b0SDouglas Gregor 
676718292f2SDouglas Gregor     default:
677*a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
678718292f2SDouglas Gregor         return;
679718292f2SDouglas Gregor       break;
680718292f2SDouglas Gregor     }
681718292f2SDouglas Gregor 
682718292f2SDouglas Gregor    consumeToken();
683718292f2SDouglas Gregor   } while (true);
684718292f2SDouglas Gregor }
685718292f2SDouglas Gregor 
686e7ab3669SDouglas Gregor /// \brief Parse a module-id.
687e7ab3669SDouglas Gregor ///
688e7ab3669SDouglas Gregor ///   module-id:
689e7ab3669SDouglas Gregor ///     identifier
690e7ab3669SDouglas Gregor ///     identifier '.' module-id
691e7ab3669SDouglas Gregor ///
692e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
693e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
694e7ab3669SDouglas Gregor   Id.clear();
695e7ab3669SDouglas Gregor   do {
696e7ab3669SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
697e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
698e7ab3669SDouglas Gregor       consumeToken();
699e7ab3669SDouglas Gregor     } else {
700e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
701e7ab3669SDouglas Gregor       return true;
702e7ab3669SDouglas Gregor     }
703e7ab3669SDouglas Gregor 
704e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
705e7ab3669SDouglas Gregor       break;
706e7ab3669SDouglas Gregor 
707e7ab3669SDouglas Gregor     consumeToken();
708e7ab3669SDouglas Gregor   } while (true);
709e7ab3669SDouglas Gregor 
710e7ab3669SDouglas Gregor   return false;
711e7ab3669SDouglas Gregor }
712e7ab3669SDouglas Gregor 
713*a686e1b0SDouglas Gregor namespace {
714*a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
715*a686e1b0SDouglas Gregor   enum AttributeKind {
716*a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
717*a686e1b0SDouglas Gregor     AT_unknown,
718*a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
719*a686e1b0SDouglas Gregor     AT_system
720*a686e1b0SDouglas Gregor   };
721*a686e1b0SDouglas Gregor }
722*a686e1b0SDouglas Gregor 
723718292f2SDouglas Gregor /// \brief Parse a module declaration.
724718292f2SDouglas Gregor ///
725718292f2SDouglas Gregor ///   module-declaration:
726*a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
727*a686e1b0SDouglas Gregor ///       { module-member* }
728*a686e1b0SDouglas Gregor ///
729*a686e1b0SDouglas Gregor ///   attributes:
730*a686e1b0SDouglas Gregor ///     attribute attributes
731*a686e1b0SDouglas Gregor ///     attribute
732*a686e1b0SDouglas Gregor ///
733*a686e1b0SDouglas Gregor ///   attribute:
734*a686e1b0SDouglas Gregor ///     [ identifier ]
735718292f2SDouglas Gregor ///
736718292f2SDouglas Gregor ///   module-member:
7371fb5c3a6SDouglas Gregor ///     requires-declaration
738718292f2SDouglas Gregor ///     header-declaration
739e7ab3669SDouglas Gregor ///     submodule-declaration
7402b82c2a5SDouglas Gregor ///     export-declaration
74173441091SDouglas Gregor ///
74273441091SDouglas Gregor ///   submodule-declaration:
74373441091SDouglas Gregor ///     module-declaration
74473441091SDouglas Gregor ///     inferred-submodule-declaration
745718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
746755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
747755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
748f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
749e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
750718292f2SDouglas Gregor   bool Explicit = false;
751f2161a70SDouglas Gregor   bool Framework = false;
752755b2055SDouglas Gregor 
753f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
754f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
755e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
756f2161a70SDouglas Gregor     Explicit = true;
757f2161a70SDouglas Gregor   }
758f2161a70SDouglas Gregor 
759f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
760755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
761755b2055SDouglas Gregor     consumeToken();
762755b2055SDouglas Gregor     Framework = true;
763755b2055SDouglas Gregor   }
764718292f2SDouglas Gregor 
765718292f2SDouglas Gregor   // Parse 'module' keyword.
766718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
767d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
768718292f2SDouglas Gregor     consumeToken();
769718292f2SDouglas Gregor     HadError = true;
770718292f2SDouglas Gregor     return;
771718292f2SDouglas Gregor   }
772718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
773718292f2SDouglas Gregor 
77473441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
77573441091SDouglas Gregor   // Parse it.
77673441091SDouglas Gregor   if (Tok.is(MMToken::Star))
77773441091SDouglas Gregor     return parseInferredSubmoduleDecl(Explicit);
77873441091SDouglas Gregor 
779718292f2SDouglas Gregor   // Parse the module name.
780e7ab3669SDouglas Gregor   ModuleId Id;
781e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
782718292f2SDouglas Gregor     HadError = true;
783718292f2SDouglas Gregor     return;
784718292f2SDouglas Gregor   }
785e7ab3669SDouglas Gregor 
786e7ab3669SDouglas Gregor   if (ActiveModule) {
787e7ab3669SDouglas Gregor     if (Id.size() > 1) {
788e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
789e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
790e7ab3669SDouglas Gregor 
791e7ab3669SDouglas Gregor       HadError = true;
792e7ab3669SDouglas Gregor       return;
793e7ab3669SDouglas Gregor     }
794e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
795e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
796e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
797e7ab3669SDouglas Gregor     Explicit = false;
798e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
799e7ab3669SDouglas Gregor     HadError = true;
800e7ab3669SDouglas Gregor   }
801e7ab3669SDouglas Gregor 
802e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
803e7ab3669SDouglas Gregor   if (Id.size() > 1) {
804e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
805e7ab3669SDouglas Gregor     // is a submodule.
806e7ab3669SDouglas Gregor     ActiveModule = 0;
807e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
808e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
809e7ab3669SDouglas Gregor         ActiveModule = Next;
810e7ab3669SDouglas Gregor         continue;
811e7ab3669SDouglas Gregor       }
812e7ab3669SDouglas Gregor 
813e7ab3669SDouglas Gregor       if (ActiveModule) {
814e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
815e7ab3669SDouglas Gregor           << Id[I].first << ActiveModule->getTopLevelModule();
816e7ab3669SDouglas Gregor       } else {
817e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
818e7ab3669SDouglas Gregor       }
819e7ab3669SDouglas Gregor       HadError = true;
820e7ab3669SDouglas Gregor       return;
821e7ab3669SDouglas Gregor     }
822e7ab3669SDouglas Gregor   }
823e7ab3669SDouglas Gregor 
824e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
825e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
826718292f2SDouglas Gregor 
827*a686e1b0SDouglas Gregor   // Parse the optional attribute list.
828*a686e1b0SDouglas Gregor   bool IsSystem = false;
829*a686e1b0SDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
830*a686e1b0SDouglas Gregor     // Consume the '['.
831*a686e1b0SDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
832*a686e1b0SDouglas Gregor 
833*a686e1b0SDouglas Gregor     // Check whether we have an attribute name here.
834*a686e1b0SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
835*a686e1b0SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
836*a686e1b0SDouglas Gregor       skipUntil(MMToken::RSquare);
837*a686e1b0SDouglas Gregor       if (Tok.is(MMToken::RSquare))
838*a686e1b0SDouglas Gregor         consumeToken();
839*a686e1b0SDouglas Gregor       continue;
840*a686e1b0SDouglas Gregor     }
841*a686e1b0SDouglas Gregor 
842*a686e1b0SDouglas Gregor     // Decode the attribute name.
843*a686e1b0SDouglas Gregor     AttributeKind Attribute
844*a686e1b0SDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
845*a686e1b0SDouglas Gregor         .Case("system", AT_system)
846*a686e1b0SDouglas Gregor         .Default(AT_unknown);
847*a686e1b0SDouglas Gregor     switch (Attribute) {
848*a686e1b0SDouglas Gregor     case AT_unknown:
849*a686e1b0SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
850*a686e1b0SDouglas Gregor         << Tok.getString();
851*a686e1b0SDouglas Gregor       break;
852*a686e1b0SDouglas Gregor 
853*a686e1b0SDouglas Gregor     case AT_system:
854*a686e1b0SDouglas Gregor       IsSystem = true;
855*a686e1b0SDouglas Gregor       break;
856*a686e1b0SDouglas Gregor     }
857*a686e1b0SDouglas Gregor     consumeToken();
858*a686e1b0SDouglas Gregor 
859*a686e1b0SDouglas Gregor     // Consume the ']'.
860*a686e1b0SDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
861*a686e1b0SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
862*a686e1b0SDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
863*a686e1b0SDouglas Gregor       skipUntil(MMToken::RSquare);
864*a686e1b0SDouglas Gregor     }
865*a686e1b0SDouglas Gregor 
866*a686e1b0SDouglas Gregor     if (Tok.is(MMToken::RSquare))
867*a686e1b0SDouglas Gregor       consumeToken();
868*a686e1b0SDouglas Gregor   }
869*a686e1b0SDouglas Gregor 
870718292f2SDouglas Gregor   // Parse the opening brace.
871718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
872718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
873718292f2SDouglas Gregor       << ModuleName;
874718292f2SDouglas Gregor     HadError = true;
875718292f2SDouglas Gregor     return;
876718292f2SDouglas Gregor   }
877718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
878718292f2SDouglas Gregor 
879718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
880eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
881fcc54a3bSDouglas Gregor     if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
882fcc54a3bSDouglas Gregor       // Skip the module definition.
883fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
884fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
885fcc54a3bSDouglas Gregor         consumeToken();
886fcc54a3bSDouglas Gregor       else {
887fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
888fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
889fcc54a3bSDouglas Gregor         HadError = true;
890fcc54a3bSDouglas Gregor       }
891fcc54a3bSDouglas Gregor       return;
892fcc54a3bSDouglas Gregor     }
893fcc54a3bSDouglas Gregor 
894718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
895718292f2SDouglas Gregor       << ModuleName;
896eb90e830SDouglas Gregor     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
897718292f2SDouglas Gregor 
898718292f2SDouglas Gregor     // Skip the module definition.
899718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
900718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
901718292f2SDouglas Gregor       consumeToken();
902718292f2SDouglas Gregor 
903718292f2SDouglas Gregor     HadError = true;
904718292f2SDouglas Gregor     return;
905718292f2SDouglas Gregor   }
906718292f2SDouglas Gregor 
907718292f2SDouglas Gregor   // Start defining this module.
908eb90e830SDouglas Gregor   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
909eb90e830SDouglas Gregor                                         Explicit).first;
910eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
911*a686e1b0SDouglas Gregor   if (IsSystem)
912*a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
913718292f2SDouglas Gregor 
914718292f2SDouglas Gregor   bool Done = false;
915718292f2SDouglas Gregor   do {
916718292f2SDouglas Gregor     switch (Tok.Kind) {
917718292f2SDouglas Gregor     case MMToken::EndOfFile:
918718292f2SDouglas Gregor     case MMToken::RBrace:
919718292f2SDouglas Gregor       Done = true;
920718292f2SDouglas Gregor       break;
921718292f2SDouglas Gregor 
922718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
923f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
924718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
925718292f2SDouglas Gregor       parseModuleDecl();
926718292f2SDouglas Gregor       break;
927718292f2SDouglas Gregor 
9282b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
9292b82c2a5SDouglas Gregor       parseExportDecl();
9302b82c2a5SDouglas Gregor       break;
9312b82c2a5SDouglas Gregor 
9321fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
9331fb5c3a6SDouglas Gregor       parseRequiresDecl();
9341fb5c3a6SDouglas Gregor       break;
9351fb5c3a6SDouglas Gregor 
936524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
937524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
938524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
939524e33e1SDouglas Gregor         parseHeaderDecl(UmbrellaLoc);
940524e33e1SDouglas Gregor       else
941524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
942718292f2SDouglas Gregor       break;
943524e33e1SDouglas Gregor     }
944718292f2SDouglas Gregor 
945322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
946322f633cSDouglas Gregor       parseHeaderDecl(SourceLocation());
947718292f2SDouglas Gregor       break;
948718292f2SDouglas Gregor 
949718292f2SDouglas Gregor     default:
950718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
951718292f2SDouglas Gregor       consumeToken();
952718292f2SDouglas Gregor       break;
953718292f2SDouglas Gregor     }
954718292f2SDouglas Gregor   } while (!Done);
955718292f2SDouglas Gregor 
956718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
957718292f2SDouglas Gregor     consumeToken();
958718292f2SDouglas Gregor   else {
959718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
960718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
961718292f2SDouglas Gregor     HadError = true;
962718292f2SDouglas Gregor   }
963718292f2SDouglas Gregor 
964e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
965e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
966718292f2SDouglas Gregor }
967718292f2SDouglas Gregor 
9681fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
9691fb5c3a6SDouglas Gregor ///
9701fb5c3a6SDouglas Gregor ///   requires-declaration:
9711fb5c3a6SDouglas Gregor ///     'requires' feature-list
9721fb5c3a6SDouglas Gregor ///
9731fb5c3a6SDouglas Gregor ///   feature-list:
9741fb5c3a6SDouglas Gregor ///     identifier ',' feature-list
9751fb5c3a6SDouglas Gregor ///     identifier
9761fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
9771fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
9781fb5c3a6SDouglas Gregor 
9791fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
9801fb5c3a6SDouglas Gregor   consumeToken();
9811fb5c3a6SDouglas Gregor 
9821fb5c3a6SDouglas Gregor   // Parse the feature-list.
9831fb5c3a6SDouglas Gregor   do {
9841fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
9851fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
9861fb5c3a6SDouglas Gregor       HadError = true;
9871fb5c3a6SDouglas Gregor       return;
9881fb5c3a6SDouglas Gregor     }
9891fb5c3a6SDouglas Gregor 
9901fb5c3a6SDouglas Gregor     // Consume the feature name.
9911fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
9921fb5c3a6SDouglas Gregor     consumeToken();
9931fb5c3a6SDouglas Gregor 
9941fb5c3a6SDouglas Gregor     // Add this feature.
9951fb5c3a6SDouglas Gregor     ActiveModule->addRequirement(Feature, Map.LangOpts);
9961fb5c3a6SDouglas Gregor 
9971fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
9981fb5c3a6SDouglas Gregor       break;
9991fb5c3a6SDouglas Gregor 
10001fb5c3a6SDouglas Gregor     // Consume the comma.
10011fb5c3a6SDouglas Gregor     consumeToken();
10021fb5c3a6SDouglas Gregor   } while (true);
10031fb5c3a6SDouglas Gregor }
10041fb5c3a6SDouglas Gregor 
1005f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the
1006f2161a70SDouglas Gregor /// subframework in which the given module lives.
1007f2161a70SDouglas Gregor void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
1008f2161a70SDouglas Gregor   // Collect the framework names from the given module to the top-level module.
1009f2161a70SDouglas Gregor   llvm::SmallVector<StringRef, 2> Paths;
1010f2161a70SDouglas Gregor   for (; Mod; Mod = Mod->Parent) {
1011f2161a70SDouglas Gregor     if (Mod->IsFramework)
1012f2161a70SDouglas Gregor       Paths.push_back(Mod->Name);
1013f2161a70SDouglas Gregor   }
1014f2161a70SDouglas Gregor 
1015f2161a70SDouglas Gregor   if (Paths.empty())
1016f2161a70SDouglas Gregor     return;
1017f2161a70SDouglas Gregor 
1018f2161a70SDouglas Gregor   // Add Frameworks/Name.framework for each subframework.
1019f2161a70SDouglas Gregor   for (unsigned I = Paths.size() - 1; I != 0; --I) {
1020f2161a70SDouglas Gregor     llvm::sys::path::append(Path, "Frameworks");
1021f2161a70SDouglas Gregor     llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1022f2161a70SDouglas Gregor   }
1023f2161a70SDouglas Gregor }
1024f2161a70SDouglas Gregor 
1025718292f2SDouglas Gregor /// \brief Parse a header declaration.
1026718292f2SDouglas Gregor ///
1027718292f2SDouglas Gregor ///   header-declaration:
1028322f633cSDouglas Gregor ///     'umbrella'[opt] 'header' string-literal
1029322f633cSDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
1030718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
10311871ed3dSBenjamin Kramer   consumeToken();
1032718292f2SDouglas Gregor 
1033322f633cSDouglas Gregor   bool Umbrella = UmbrellaLoc.isValid();
1034322f633cSDouglas Gregor 
1035718292f2SDouglas Gregor   // Parse the header name.
1036718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1037718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1038718292f2SDouglas Gregor       << "header";
1039718292f2SDouglas Gregor     HadError = true;
1040718292f2SDouglas Gregor     return;
1041718292f2SDouglas Gregor   }
1042e7ab3669SDouglas Gregor   std::string FileName = Tok.getString();
1043718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
1044718292f2SDouglas Gregor 
1045524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1046524e33e1SDouglas Gregor   if (Umbrella && ActiveModule->Umbrella) {
1047524e33e1SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1048524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1049322f633cSDouglas Gregor     HadError = true;
1050322f633cSDouglas Gregor     return;
1051322f633cSDouglas Gregor   }
1052322f633cSDouglas Gregor 
10535257fc63SDouglas Gregor   // Look for this file.
1054e7ab3669SDouglas Gregor   const FileEntry *File = 0;
10555257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
1056e7ab3669SDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
1057e7ab3669SDouglas Gregor     PathName = FileName;
1058e7ab3669SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
10597033127bSDouglas Gregor   } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
10607033127bSDouglas Gregor     PathName = Dir->getName();
10617033127bSDouglas Gregor     llvm::sys::path::append(PathName, FileName);
10627033127bSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
1063e7ab3669SDouglas Gregor   } else {
1064e7ab3669SDouglas Gregor     // Search for the header file within the search directory.
10657033127bSDouglas Gregor     PathName = Directory->getName();
1066e7ab3669SDouglas Gregor     unsigned PathLength = PathName.size();
1067755b2055SDouglas Gregor 
1068f2161a70SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
1069f2161a70SDouglas Gregor       appendSubframeworkPaths(ActiveModule, PathName);
1070755b2055SDouglas Gregor 
1071e7ab3669SDouglas Gregor       // Check whether this file is in the public headers.
1072e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
10735257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1074e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
1075e7ab3669SDouglas Gregor 
1076e7ab3669SDouglas Gregor       if (!File) {
1077e7ab3669SDouglas Gregor         // Check whether this file is in the private headers.
1078e7ab3669SDouglas Gregor         PathName.resize(PathLength);
1079e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
1080e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
1081e7ab3669SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
1082e7ab3669SDouglas Gregor       }
1083e7ab3669SDouglas Gregor     } else {
1084e7ab3669SDouglas Gregor       // Lookup for normal headers.
1085e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1086e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
1087e7ab3669SDouglas Gregor     }
1088e7ab3669SDouglas Gregor   }
10895257fc63SDouglas Gregor 
10905257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
10915257fc63SDouglas Gregor   // Come up with a lazy way to do this.
1092e7ab3669SDouglas Gregor   if (File) {
10935257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
10945257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
10955257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
10965257fc63SDouglas Gregor       HadError = true;
1097322f633cSDouglas Gregor     } else if (Umbrella) {
1098322f633cSDouglas Gregor       const DirectoryEntry *UmbrellaDir = File->getDir();
1099322f633cSDouglas Gregor       if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1100322f633cSDouglas Gregor         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1101322f633cSDouglas Gregor           << OwningModule->getFullModuleName();
1102322f633cSDouglas Gregor         HadError = true;
11035257fc63SDouglas Gregor       } else {
1104322f633cSDouglas Gregor         // Record this umbrella header.
1105322f633cSDouglas Gregor         Map.setUmbrellaHeader(ActiveModule, File);
1106322f633cSDouglas Gregor       }
1107322f633cSDouglas Gregor     } else {
1108322f633cSDouglas Gregor       // Record this header.
1109a89c5ac4SDouglas Gregor       Map.addHeader(ActiveModule, File);
11105257fc63SDouglas Gregor     }
11115257fc63SDouglas Gregor   } else {
11125257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
1113524e33e1SDouglas Gregor       << Umbrella << FileName;
11145257fc63SDouglas Gregor     HadError = true;
11155257fc63SDouglas Gregor   }
1116718292f2SDouglas Gregor }
1117718292f2SDouglas Gregor 
1118524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
1119524e33e1SDouglas Gregor ///
1120524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
1121524e33e1SDouglas Gregor ///     umbrella string-literal
1122524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1123524e33e1SDouglas Gregor   // Parse the directory name.
1124524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1125524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1126524e33e1SDouglas Gregor       << "umbrella";
1127524e33e1SDouglas Gregor     HadError = true;
1128524e33e1SDouglas Gregor     return;
1129524e33e1SDouglas Gregor   }
1130524e33e1SDouglas Gregor 
1131524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
1132524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
1133524e33e1SDouglas Gregor 
1134524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1135524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
1136524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1137524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1138524e33e1SDouglas Gregor     HadError = true;
1139524e33e1SDouglas Gregor     return;
1140524e33e1SDouglas Gregor   }
1141524e33e1SDouglas Gregor 
1142524e33e1SDouglas Gregor   // Look for this file.
1143524e33e1SDouglas Gregor   const DirectoryEntry *Dir = 0;
1144524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
1145524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
1146524e33e1SDouglas Gregor   else {
1147524e33e1SDouglas Gregor     llvm::SmallString<128> PathName;
1148524e33e1SDouglas Gregor     PathName = Directory->getName();
1149524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
1150524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
1151524e33e1SDouglas Gregor   }
1152524e33e1SDouglas Gregor 
1153524e33e1SDouglas Gregor   if (!Dir) {
1154524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1155524e33e1SDouglas Gregor       << DirName;
1156524e33e1SDouglas Gregor     HadError = true;
1157524e33e1SDouglas Gregor     return;
1158524e33e1SDouglas Gregor   }
1159524e33e1SDouglas Gregor 
1160524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1161524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1162524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
1163524e33e1SDouglas Gregor     HadError = true;
1164524e33e1SDouglas Gregor     return;
1165524e33e1SDouglas Gregor   }
1166524e33e1SDouglas Gregor 
1167524e33e1SDouglas Gregor   // Record this umbrella directory.
1168524e33e1SDouglas Gregor   Map.setUmbrellaDir(ActiveModule, Dir);
1169524e33e1SDouglas Gregor }
1170524e33e1SDouglas Gregor 
11712b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
11722b82c2a5SDouglas Gregor ///
11732b82c2a5SDouglas Gregor ///   export-declaration:
11742b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
11752b82c2a5SDouglas Gregor ///
11762b82c2a5SDouglas Gregor ///   wildcard-module-id:
11772b82c2a5SDouglas Gregor ///     identifier
11782b82c2a5SDouglas Gregor ///     '*'
11792b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
11802b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
11812b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
11822b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
11832b82c2a5SDouglas Gregor 
11842b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
11852b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
11862b82c2a5SDouglas Gregor   bool Wildcard = false;
11872b82c2a5SDouglas Gregor   do {
11882b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
11892b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
11902b82c2a5SDouglas Gregor                                               Tok.getLocation()));
11912b82c2a5SDouglas Gregor       consumeToken();
11922b82c2a5SDouglas Gregor 
11932b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
11942b82c2a5SDouglas Gregor         consumeToken();
11952b82c2a5SDouglas Gregor         continue;
11962b82c2a5SDouglas Gregor       }
11972b82c2a5SDouglas Gregor 
11982b82c2a5SDouglas Gregor       break;
11992b82c2a5SDouglas Gregor     }
12002b82c2a5SDouglas Gregor 
12012b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
12022b82c2a5SDouglas Gregor       Wildcard = true;
1203f5eedd05SDouglas Gregor       consumeToken();
12042b82c2a5SDouglas Gregor       break;
12052b82c2a5SDouglas Gregor     }
12062b82c2a5SDouglas Gregor 
12072b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
12082b82c2a5SDouglas Gregor     HadError = true;
12092b82c2a5SDouglas Gregor     return;
12102b82c2a5SDouglas Gregor   } while (true);
12112b82c2a5SDouglas Gregor 
12122b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
12132b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
12142b82c2a5SDouglas Gregor   };
12152b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
12162b82c2a5SDouglas Gregor }
12172b82c2a5SDouglas Gregor 
121873441091SDouglas Gregor void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
121973441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
122073441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
122173441091SDouglas Gregor   bool Failed = false;
122273441091SDouglas Gregor 
122373441091SDouglas Gregor   // Inferred modules must be submodules.
122473441091SDouglas Gregor   if (!ActiveModule) {
122573441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
122673441091SDouglas Gregor     Failed = true;
122773441091SDouglas Gregor   }
122873441091SDouglas Gregor 
1229524e33e1SDouglas Gregor   // Inferred modules must have umbrella directories.
1230524e33e1SDouglas Gregor   if (!Failed && !ActiveModule->getUmbrellaDir()) {
123173441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
123273441091SDouglas Gregor     Failed = true;
123373441091SDouglas Gregor   }
123473441091SDouglas Gregor 
123573441091SDouglas Gregor   // Check for redefinition of an inferred module.
1236dd005f69SDouglas Gregor   if (!Failed && ActiveModule->InferSubmodules) {
123773441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1238dd005f69SDouglas Gregor     if (ActiveModule->InferredSubmoduleLoc.isValid())
1239dd005f69SDouglas Gregor       Diags.Report(ActiveModule->InferredSubmoduleLoc,
124073441091SDouglas Gregor                    diag::note_mmap_prev_definition);
124173441091SDouglas Gregor     Failed = true;
124273441091SDouglas Gregor   }
124373441091SDouglas Gregor 
124473441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
124573441091SDouglas Gregor   if (Failed) {
124673441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
124773441091SDouglas Gregor       consumeToken();
124873441091SDouglas Gregor       skipUntil(MMToken::RBrace);
124973441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
125073441091SDouglas Gregor         consumeToken();
125173441091SDouglas Gregor     }
125273441091SDouglas Gregor     HadError = true;
125373441091SDouglas Gregor     return;
125473441091SDouglas Gregor   }
125573441091SDouglas Gregor 
125673441091SDouglas Gregor   // Note that we have an inferred submodule.
1257dd005f69SDouglas Gregor   ActiveModule->InferSubmodules = true;
1258dd005f69SDouglas Gregor   ActiveModule->InferredSubmoduleLoc = StarLoc;
1259dd005f69SDouglas Gregor   ActiveModule->InferExplicitSubmodules = Explicit;
126073441091SDouglas Gregor 
126173441091SDouglas Gregor   // Parse the opening brace.
126273441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
126373441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
126473441091SDouglas Gregor     HadError = true;
126573441091SDouglas Gregor     return;
126673441091SDouglas Gregor   }
126773441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
126873441091SDouglas Gregor 
126973441091SDouglas Gregor   // Parse the body of the inferred submodule.
127073441091SDouglas Gregor   bool Done = false;
127173441091SDouglas Gregor   do {
127273441091SDouglas Gregor     switch (Tok.Kind) {
127373441091SDouglas Gregor     case MMToken::EndOfFile:
127473441091SDouglas Gregor     case MMToken::RBrace:
127573441091SDouglas Gregor       Done = true;
127673441091SDouglas Gregor       break;
127773441091SDouglas Gregor 
127873441091SDouglas Gregor     case MMToken::ExportKeyword: {
127973441091SDouglas Gregor       consumeToken();
128073441091SDouglas Gregor       if (Tok.is(MMToken::Star))
1281dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
128273441091SDouglas Gregor       else
128373441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
128473441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
128573441091SDouglas Gregor       consumeToken();
128673441091SDouglas Gregor       break;
128773441091SDouglas Gregor     }
128873441091SDouglas Gregor 
128973441091SDouglas Gregor     case MMToken::ExplicitKeyword:
129073441091SDouglas Gregor     case MMToken::ModuleKeyword:
129173441091SDouglas Gregor     case MMToken::HeaderKeyword:
129273441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
129373441091SDouglas Gregor     default:
129473441091SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
129573441091SDouglas Gregor       consumeToken();
129673441091SDouglas Gregor       break;
129773441091SDouglas Gregor     }
129873441091SDouglas Gregor   } while (!Done);
129973441091SDouglas Gregor 
130073441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
130173441091SDouglas Gregor     consumeToken();
130273441091SDouglas Gregor   else {
130373441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
130473441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
130573441091SDouglas Gregor     HadError = true;
130673441091SDouglas Gregor   }
130773441091SDouglas Gregor }
130873441091SDouglas Gregor 
13097033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence
13107033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null.
13117033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
13127033127bSDouglas Gregor   for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
13137033127bSDouglas Gregor     // If we have an umbrella directory, use that.
13147033127bSDouglas Gregor     if (Mod->hasUmbrellaDir())
13157033127bSDouglas Gregor       return Mod->getUmbrellaDir();
13167033127bSDouglas Gregor 
13177033127bSDouglas Gregor     // If we have a framework directory, stop looking.
13187033127bSDouglas Gregor     if (Mod->IsFramework)
13197033127bSDouglas Gregor       return 0;
13207033127bSDouglas Gregor   }
13217033127bSDouglas Gregor 
13227033127bSDouglas Gregor   return 0;
13237033127bSDouglas Gregor }
13247033127bSDouglas Gregor 
1325718292f2SDouglas Gregor /// \brief Parse a module map file.
1326718292f2SDouglas Gregor ///
1327718292f2SDouglas Gregor ///   module-map-file:
1328718292f2SDouglas Gregor ///     module-declaration*
1329718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
1330718292f2SDouglas Gregor   do {
1331718292f2SDouglas Gregor     switch (Tok.Kind) {
1332718292f2SDouglas Gregor     case MMToken::EndOfFile:
1333718292f2SDouglas Gregor       return HadError;
1334718292f2SDouglas Gregor 
1335e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
1336718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1337755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
1338718292f2SDouglas Gregor       parseModuleDecl();
1339718292f2SDouglas Gregor       break;
1340718292f2SDouglas Gregor 
13411fb5c3a6SDouglas Gregor     case MMToken::Comma:
13422b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
1343718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
1344718292f2SDouglas Gregor     case MMToken::Identifier:
1345718292f2SDouglas Gregor     case MMToken::LBrace:
1346*a686e1b0SDouglas Gregor     case MMToken::LSquare:
13472b82c2a5SDouglas Gregor     case MMToken::Period:
1348718292f2SDouglas Gregor     case MMToken::RBrace:
1349*a686e1b0SDouglas Gregor     case MMToken::RSquare:
13501fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
13512b82c2a5SDouglas Gregor     case MMToken::Star:
1352718292f2SDouglas Gregor     case MMToken::StringLiteral:
1353718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
1354718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1355718292f2SDouglas Gregor       HadError = true;
1356718292f2SDouglas Gregor       consumeToken();
1357718292f2SDouglas Gregor       break;
1358718292f2SDouglas Gregor     }
1359718292f2SDouglas Gregor   } while (true);
1360718292f2SDouglas Gregor }
1361718292f2SDouglas Gregor 
1362718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1363718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1364718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1365718292f2SDouglas Gregor   if (!Buffer)
1366718292f2SDouglas Gregor     return true;
1367718292f2SDouglas Gregor 
1368718292f2SDouglas Gregor   // Parse this module map file.
13691fb5c3a6SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
13701fb5c3a6SDouglas Gregor   Diags->getClient()->BeginSourceFile(MMapLangOpts);
13715257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
1372718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
1373718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
1374718292f2SDouglas Gregor 
1375718292f2SDouglas Gregor   return Result;
1376718292f2SDouglas Gregor }
1377