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/Basic/Diagnostic.h"
16811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h"
17718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
18718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
19718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
203a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
213a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
223a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
233a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
243a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
25718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
26e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h"
27718292f2SDouglas Gregor #include "llvm/Support/Host.h"
285257fc63SDouglas Gregor #include "llvm/Support/PathV2.h"
29718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
3007c22b78SDouglas Gregor #include <stdlib.h>
3101c7cfa2SDouglas Gregor #if defined(LLVM_ON_UNIX)
32*eadae014SDmitri Gribenko #include <limits.h>
3301c7cfa2SDouglas Gregor #endif
34718292f2SDouglas Gregor using namespace clang;
35718292f2SDouglas Gregor 
362b82c2a5SDouglas Gregor Module::ExportDecl
372b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
382b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
392b82c2a5SDouglas Gregor                          bool Complain) {
40f5eedd05SDouglas Gregor   // We may have just a wildcard.
41f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
42f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
43f5eedd05SDouglas Gregor     return Module::ExportDecl(0, true);
44f5eedd05SDouglas Gregor   }
45f5eedd05SDouglas Gregor 
462b82c2a5SDouglas Gregor   // Find the starting module.
472b82c2a5SDouglas Gregor   Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
482b82c2a5SDouglas Gregor   if (!Context) {
492b82c2a5SDouglas Gregor     if (Complain)
502b82c2a5SDouglas Gregor       Diags->Report(Unresolved.Id[0].second,
512b82c2a5SDouglas Gregor                     diag::err_mmap_missing_module_unqualified)
522b82c2a5SDouglas Gregor         << Unresolved.Id[0].first << Mod->getFullModuleName();
532b82c2a5SDouglas Gregor 
542b82c2a5SDouglas Gregor     return Module::ExportDecl();
552b82c2a5SDouglas Gregor   }
562b82c2a5SDouglas Gregor 
572b82c2a5SDouglas Gregor   // Dig into the module path.
582b82c2a5SDouglas Gregor   for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
592b82c2a5SDouglas Gregor     Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
602b82c2a5SDouglas Gregor                                         Context);
612b82c2a5SDouglas Gregor     if (!Sub) {
622b82c2a5SDouglas Gregor       if (Complain)
632b82c2a5SDouglas Gregor         Diags->Report(Unresolved.Id[I].second,
642b82c2a5SDouglas Gregor                       diag::err_mmap_missing_module_qualified)
652b82c2a5SDouglas Gregor           << Unresolved.Id[I].first << Context->getFullModuleName()
662b82c2a5SDouglas Gregor           << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
672b82c2a5SDouglas Gregor 
682b82c2a5SDouglas Gregor       return Module::ExportDecl();
692b82c2a5SDouglas Gregor     }
702b82c2a5SDouglas Gregor 
712b82c2a5SDouglas Gregor     Context = Sub;
722b82c2a5SDouglas Gregor   }
732b82c2a5SDouglas Gregor 
742b82c2a5SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
752b82c2a5SDouglas Gregor }
762b82c2a5SDouglas Gregor 
771fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
7889929282SDouglas Gregor                      const LangOptions &LangOpts, const TargetInfo *Target)
793ec6663bSDouglas Gregor   : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0)
801fb5c3a6SDouglas Gregor {
81c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
82c95d8192SDylan Noblesmith   Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
83811db4eaSDouglas Gregor             new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
84718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
85718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
86718292f2SDouglas Gregor }
87718292f2SDouglas Gregor 
88718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
895acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
905acdf59eSDouglas Gregor                                         IEnd = Modules.end();
915acdf59eSDouglas Gregor        I != IEnd; ++I) {
925acdf59eSDouglas Gregor     delete I->getValue();
935acdf59eSDouglas Gregor   }
945acdf59eSDouglas Gregor 
95718292f2SDouglas Gregor   delete SourceMgr;
96718292f2SDouglas Gregor }
97718292f2SDouglas Gregor 
9889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
9989929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
10089929282SDouglas Gregor          "Improper target override");
10189929282SDouglas Gregor   this->Target = &Target;
10289929282SDouglas Gregor }
10389929282SDouglas Gregor 
104056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier.
105056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
106056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
107056396aeSDouglas Gregor   if (Name.empty())
108056396aeSDouglas Gregor     return Name;
109056396aeSDouglas Gregor 
110056396aeSDouglas Gregor   // Check whether the filename is already an identifier; this is the common
111056396aeSDouglas Gregor   // case.
112056396aeSDouglas Gregor   bool isIdentifier = true;
113056396aeSDouglas Gregor   for (unsigned I = 0, N = Name.size(); I != N; ++I) {
114056396aeSDouglas Gregor     if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0))
115056396aeSDouglas Gregor       continue;
116056396aeSDouglas Gregor 
117056396aeSDouglas Gregor     isIdentifier = false;
118056396aeSDouglas Gregor     break;
119056396aeSDouglas Gregor   }
120056396aeSDouglas Gregor 
121056396aeSDouglas Gregor   if (!isIdentifier) {
122056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
123056396aeSDouglas Gregor     // create a buffer with the sanitized name.
124056396aeSDouglas Gregor     Buffer.clear();
125056396aeSDouglas Gregor     if (isdigit(Name[0]))
126056396aeSDouglas Gregor       Buffer.push_back('_');
127056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
128056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
129056396aeSDouglas Gregor       if (isalnum(Name[I]) || isspace(Name[I]))
130056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
131056396aeSDouglas Gregor       else
132056396aeSDouglas Gregor         Buffer.push_back('_');
133056396aeSDouglas Gregor     }
134056396aeSDouglas Gregor 
135056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
136056396aeSDouglas Gregor   }
137056396aeSDouglas Gregor 
138056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
139056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
140056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
141056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
142056396aeSDouglas Gregor            .Default(false)) {
143056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
144056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
145056396aeSDouglas Gregor     Buffer.push_back('_');
146056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
147056396aeSDouglas Gregor   }
148056396aeSDouglas Gregor 
149056396aeSDouglas Gregor   return Name;
150056396aeSDouglas Gregor }
151056396aeSDouglas Gregor 
152de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
15359527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
1541fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
15559527666SDouglas Gregor     // If a header is not available, don't report that it maps to anything.
15659527666SDouglas Gregor     if (!Known->second.isAvailable())
1571fb5c3a6SDouglas Gregor       return 0;
1581fb5c3a6SDouglas Gregor 
15959527666SDouglas Gregor     return Known->second.getModule();
1601fb5c3a6SDouglas Gregor   }
161ab0c8a84SDouglas Gregor 
162b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
163f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
164e00c8b20SDouglas Gregor 
16574260502SDouglas Gregor   // Note: as an egregious but useful hack we use the real path here, because
16674260502SDouglas Gregor   // frameworks moving from top-level frameworks to embedded frameworks tend
16774260502SDouglas Gregor   // to be symlinked from the top-level location to the embedded location,
16874260502SDouglas Gregor   // and we need to resolve lookups as if we had found the embedded location.
169e00c8b20SDouglas Gregor   StringRef DirName = SourceMgr->getFileManager().getCanonicalName(Dir);
170a89c5ac4SDouglas Gregor 
171a89c5ac4SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
172a89c5ac4SDouglas Gregor   // an umbrella header.
173b65dbfffSDouglas Gregor   do {
174a89c5ac4SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
175a89c5ac4SDouglas Gregor       = UmbrellaDirs.find(Dir);
176a89c5ac4SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
177a89c5ac4SDouglas Gregor       Module *Result = KnownDir->second;
178930a85ccSDouglas Gregor 
179930a85ccSDouglas Gregor       // Search up the module stack until we find a module with an umbrella
18073141fa9SDouglas Gregor       // directory.
181930a85ccSDouglas Gregor       Module *UmbrellaModule = Result;
18273141fa9SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
183930a85ccSDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
184930a85ccSDouglas Gregor 
185930a85ccSDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
186a89c5ac4SDouglas Gregor         // Infer submodules for each of the directories we found between
187a89c5ac4SDouglas Gregor         // the directory of the umbrella header and the directory where
188a89c5ac4SDouglas Gregor         // the actual header is located.
1899458f82dSDouglas Gregor         bool Explicit = UmbrellaModule->InferExplicitSubmodules;
1909458f82dSDouglas Gregor 
1917033127bSDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
192a89c5ac4SDouglas Gregor           // Find or create the module that corresponds to this directory name.
193056396aeSDouglas Gregor           SmallString<32> NameBuf;
194056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
195056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
196056396aeSDouglas Gregor                              NameBuf);
197a89c5ac4SDouglas Gregor           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
1989458f82dSDouglas Gregor                                       Explicit).first;
199a89c5ac4SDouglas Gregor 
200a89c5ac4SDouglas Gregor           // Associate the module and the directory.
201a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I-1]] = Result;
202a89c5ac4SDouglas Gregor 
203a89c5ac4SDouglas Gregor           // If inferred submodules export everything they import, add a
204a89c5ac4SDouglas Gregor           // wildcard to the set of exports.
205930a85ccSDouglas Gregor           if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
206a89c5ac4SDouglas Gregor             Result->Exports.push_back(Module::ExportDecl(0, true));
207a89c5ac4SDouglas Gregor         }
208a89c5ac4SDouglas Gregor 
209a89c5ac4SDouglas Gregor         // Infer a submodule with the same name as this header file.
210056396aeSDouglas Gregor         SmallString<32> NameBuf;
211056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
212056396aeSDouglas Gregor                            llvm::sys::path::stem(File->getName()), NameBuf);
213a89c5ac4SDouglas Gregor         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
2149458f82dSDouglas Gregor                                     Explicit).first;
215c597c8c4SArgyrios Kyrtzidis         Result->TopHeaders.insert(File);
216a89c5ac4SDouglas Gregor 
217a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
218a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
219930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
220a89c5ac4SDouglas Gregor           Result->Exports.push_back(Module::ExportDecl(0, true));
221a89c5ac4SDouglas Gregor       } else {
222a89c5ac4SDouglas Gregor         // Record each of the directories we stepped through as being part of
223a89c5ac4SDouglas Gregor         // the module we found, since the umbrella header covers them all.
224a89c5ac4SDouglas Gregor         for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
225a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I]] = Result;
226a89c5ac4SDouglas Gregor       }
227a89c5ac4SDouglas Gregor 
22859527666SDouglas Gregor       Headers[File] = KnownHeader(Result, /*Excluded=*/false);
2291fb5c3a6SDouglas Gregor 
2301fb5c3a6SDouglas Gregor       // If a header corresponds to an unavailable module, don't report
2311fb5c3a6SDouglas Gregor       // that it maps to anything.
2321fb5c3a6SDouglas Gregor       if (!Result->isAvailable())
2331fb5c3a6SDouglas Gregor         return 0;
2341fb5c3a6SDouglas Gregor 
235a89c5ac4SDouglas Gregor       return Result;
236a89c5ac4SDouglas Gregor     }
237a89c5ac4SDouglas Gregor 
238a89c5ac4SDouglas Gregor     SkippedDirs.push_back(Dir);
239a89c5ac4SDouglas Gregor 
240b65dbfffSDouglas Gregor     // Retrieve our parent path.
241b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
242b65dbfffSDouglas Gregor     if (DirName.empty())
243b65dbfffSDouglas Gregor       break;
244b65dbfffSDouglas Gregor 
245b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
246b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
247a89c5ac4SDouglas Gregor   } while (Dir);
248b65dbfffSDouglas Gregor 
249ab0c8a84SDouglas Gregor   return 0;
250ab0c8a84SDouglas Gregor }
251ab0c8a84SDouglas Gregor 
2521fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
25359527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(Header);
2541fb5c3a6SDouglas Gregor   if (Known != Headers.end())
25559527666SDouglas Gregor     return !Known->second.isAvailable();
2561fb5c3a6SDouglas Gregor 
2571fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
258f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
2591fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
2601fb5c3a6SDouglas Gregor 
2611fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
2621fb5c3a6SDouglas Gregor   // an umbrella header.
2631fb5c3a6SDouglas Gregor   do {
2641fb5c3a6SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
2651fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
2661fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
2671fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
2681fb5c3a6SDouglas Gregor       if (!Found->isAvailable())
2691fb5c3a6SDouglas Gregor         return true;
2701fb5c3a6SDouglas Gregor 
2711fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
2721fb5c3a6SDouglas Gregor       // directory.
2731fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
2741fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
2751fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
2761fb5c3a6SDouglas Gregor 
2771fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
2781fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
2791fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
280056396aeSDouglas Gregor           SmallString<32> NameBuf;
281056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
282056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
283056396aeSDouglas Gregor                              NameBuf);
2841fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
2851fb5c3a6SDouglas Gregor           if (!Found)
2861fb5c3a6SDouglas Gregor             return false;
2871fb5c3a6SDouglas Gregor           if (!Found->isAvailable())
2881fb5c3a6SDouglas Gregor             return true;
2891fb5c3a6SDouglas Gregor         }
2901fb5c3a6SDouglas Gregor 
2911fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
292056396aeSDouglas Gregor         SmallString<32> NameBuf;
293056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
294056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
295056396aeSDouglas Gregor                            NameBuf);
2961fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
2971fb5c3a6SDouglas Gregor         if (!Found)
2981fb5c3a6SDouglas Gregor           return false;
2991fb5c3a6SDouglas Gregor       }
3001fb5c3a6SDouglas Gregor 
3011fb5c3a6SDouglas Gregor       return !Found->isAvailable();
3021fb5c3a6SDouglas Gregor     }
3031fb5c3a6SDouglas Gregor 
3041fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
3051fb5c3a6SDouglas Gregor 
3061fb5c3a6SDouglas Gregor     // Retrieve our parent path.
3071fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
3081fb5c3a6SDouglas Gregor     if (DirName.empty())
3091fb5c3a6SDouglas Gregor       break;
3101fb5c3a6SDouglas Gregor 
3111fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
3121fb5c3a6SDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
3131fb5c3a6SDouglas Gregor   } while (Dir);
3141fb5c3a6SDouglas Gregor 
3151fb5c3a6SDouglas Gregor   return false;
3161fb5c3a6SDouglas Gregor }
3171fb5c3a6SDouglas Gregor 
318de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
31988bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
32088bdfb0eSDouglas Gregor   if (Known != Modules.end())
32188bdfb0eSDouglas Gregor     return Known->getValue();
32288bdfb0eSDouglas Gregor 
32388bdfb0eSDouglas Gregor   return 0;
32488bdfb0eSDouglas Gregor }
32588bdfb0eSDouglas Gregor 
3262b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
3272b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
3282b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
3292b82c2a5SDouglas Gregor       return Sub;
3302b82c2a5SDouglas Gregor   }
3312b82c2a5SDouglas Gregor 
3322b82c2a5SDouglas Gregor   return findModule(Name);
3332b82c2a5SDouglas Gregor }
3342b82c2a5SDouglas Gregor 
3352b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
3362b82c2a5SDouglas Gregor   if (!Context)
3372b82c2a5SDouglas Gregor     return findModule(Name);
3382b82c2a5SDouglas Gregor 
339eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
3402b82c2a5SDouglas Gregor }
3412b82c2a5SDouglas Gregor 
342de3ef502SDouglas Gregor std::pair<Module *, bool>
34369021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
34469021974SDouglas Gregor                               bool IsExplicit) {
34569021974SDouglas Gregor   // Try to find an existing module with this name.
346eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
347eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
34869021974SDouglas Gregor 
34969021974SDouglas Gregor   // Create a new module with this name.
35069021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
35169021974SDouglas Gregor                               IsExplicit);
352eb90e830SDouglas Gregor   if (!Parent)
35369021974SDouglas Gregor     Modules[Name] = Result;
35469021974SDouglas Gregor   return std::make_pair(Result, true);
35569021974SDouglas Gregor }
35669021974SDouglas Gregor 
3579194a91dSDouglas Gregor bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
3589194a91dSDouglas Gregor                                         StringRef Name, bool &IsSystem) {
3599194a91dSDouglas Gregor   // Check whether we have already looked into the parent directory
3609194a91dSDouglas Gregor   // for a module map.
3619194a91dSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
3629194a91dSDouglas Gregor     inferred = InferredDirectories.find(ParentDir);
3639194a91dSDouglas Gregor   if (inferred == InferredDirectories.end())
3649194a91dSDouglas Gregor     return false;
3659194a91dSDouglas Gregor 
3669194a91dSDouglas Gregor   if (!inferred->second.InferModules)
3679194a91dSDouglas Gregor     return false;
3689194a91dSDouglas Gregor 
3699194a91dSDouglas Gregor   // We're allowed to infer for this directory, but make sure it's okay
3709194a91dSDouglas Gregor   // to infer this particular module.
3719194a91dSDouglas Gregor   bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
3729194a91dSDouglas Gregor                             inferred->second.ExcludedModules.end(),
3739194a91dSDouglas Gregor                             Name) == inferred->second.ExcludedModules.end();
3749194a91dSDouglas Gregor 
3759194a91dSDouglas Gregor   if (canInfer && inferred->second.InferSystemModules)
3769194a91dSDouglas Gregor     IsSystem = true;
3779194a91dSDouglas Gregor 
3789194a91dSDouglas Gregor   return canInfer;
3799194a91dSDouglas Gregor }
3809194a91dSDouglas Gregor 
38111dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we
38211dfe6feSDouglas Gregor /// should link.
38311dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
38411dfe6feSDouglas Gregor                                FileManager &FileMgr) {
38511dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
38611dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
38711dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
38811dfe6feSDouglas Gregor 
38911dfe6feSDouglas Gregor   SmallString<128> LibName;
39011dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
39111dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
39211dfe6feSDouglas Gregor   if (FileMgr.getFile(LibName)) {
39311dfe6feSDouglas Gregor     Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
39411dfe6feSDouglas Gregor                                                      /*IsFramework=*/true));
39511dfe6feSDouglas Gregor   }
39611dfe6feSDouglas Gregor }
39711dfe6feSDouglas Gregor 
398de3ef502SDouglas Gregor Module *
39956c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
400e89dbc1dSDouglas Gregor                                 const DirectoryEntry *FrameworkDir,
401a686e1b0SDouglas Gregor                                 bool IsSystem,
402e89dbc1dSDouglas Gregor                                 Module *Parent) {
40356c64013SDouglas Gregor   // Check whether we've already found this module.
404e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
405e89dbc1dSDouglas Gregor     return Mod;
406e89dbc1dSDouglas Gregor 
407e89dbc1dSDouglas Gregor   FileManager &FileMgr = SourceMgr->getFileManager();
40856c64013SDouglas Gregor 
4099194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
4109194a91dSDouglas Gregor   // a framework module, do so.
4119194a91dSDouglas Gregor   if (!Parent) {
4124ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
413e00c8b20SDouglas Gregor 
4144ddf2221SDouglas Gregor     // Note: as an egregious but useful hack we use the real path here, because
4154ddf2221SDouglas Gregor     // we might be looking at an embedded framework that symlinks out to a
4164ddf2221SDouglas Gregor     // top-level framework, and we need to infer as if we were naming the
4174ddf2221SDouglas Gregor     // top-level framework.
418e00c8b20SDouglas Gregor     StringRef FrameworkDirName
419e00c8b20SDouglas Gregor       = SourceMgr->getFileManager().getCanonicalName(FrameworkDir);
4204ddf2221SDouglas Gregor 
4219194a91dSDouglas Gregor     bool canInfer = false;
4224ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
4239194a91dSDouglas Gregor       // Figure out the parent path.
4244ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
4259194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
4269194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
4279194a91dSDouglas Gregor         // for a module map.
4289194a91dSDouglas Gregor         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
4299194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
4309194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
4319194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
4329194a91dSDouglas Gregor           // one.
4339194a91dSDouglas Gregor           SmallString<128> ModMapPath = Parent;
4349194a91dSDouglas Gregor           llvm::sys::path::append(ModMapPath, "module.map");
4359194a91dSDouglas Gregor           if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
4369194a91dSDouglas Gregor             parseModuleMapFile(ModMapFile);
4379194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
4389194a91dSDouglas Gregor           }
4399194a91dSDouglas Gregor 
4409194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
4419194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
4429194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
4439194a91dSDouglas Gregor         }
4449194a91dSDouglas Gregor 
4459194a91dSDouglas Gregor         if (inferred->second.InferModules) {
4469194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
4479194a91dSDouglas Gregor           // to infer this particular module.
4484ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
4499194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
4509194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
4519194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
4529194a91dSDouglas Gregor 
4539194a91dSDouglas Gregor           if (inferred->second.InferSystemModules)
4549194a91dSDouglas Gregor             IsSystem = true;
4559194a91dSDouglas Gregor         }
4569194a91dSDouglas Gregor       }
4579194a91dSDouglas Gregor     }
4589194a91dSDouglas Gregor 
4599194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
4609194a91dSDouglas Gregor     if (!canInfer)
4619194a91dSDouglas Gregor       return 0;
4629194a91dSDouglas Gregor   }
4639194a91dSDouglas Gregor 
4649194a91dSDouglas Gregor 
46556c64013SDouglas Gregor   // Look for an umbrella header.
4662c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
46756c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
46856c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
469e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
47056c64013SDouglas Gregor 
47156c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
47256c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
47356c64013SDouglas Gregor   // idea.
47456c64013SDouglas Gregor   if (!UmbrellaHeader)
47556c64013SDouglas Gregor     return 0;
47656c64013SDouglas Gregor 
477e89dbc1dSDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
478e89dbc1dSDouglas Gregor                               /*IsFramework=*/true, /*IsExplicit=*/false);
479a686e1b0SDouglas Gregor   if (IsSystem)
480a686e1b0SDouglas Gregor     Result->IsSystem = IsSystem;
481a686e1b0SDouglas Gregor 
482eb90e830SDouglas Gregor   if (!Parent)
483e89dbc1dSDouglas Gregor     Modules[ModuleName] = Result;
484e89dbc1dSDouglas Gregor 
485322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
48673141fa9SDouglas Gregor   Result->Umbrella = UmbrellaHeader;
48759527666SDouglas Gregor   Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
4884dc71835SDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
489d8bd7537SDouglas Gregor 
490d8bd7537SDouglas Gregor   // export *
491d8bd7537SDouglas Gregor   Result->Exports.push_back(Module::ExportDecl(0, true));
492d8bd7537SDouglas Gregor 
493a89c5ac4SDouglas Gregor   // module * { export * }
494a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
495a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
496a89c5ac4SDouglas Gregor 
497e89dbc1dSDouglas Gregor   // Look for subframeworks.
498e89dbc1dSDouglas Gregor   llvm::error_code EC;
4992c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
500ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
501e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
5022c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirNameNative;
503ddaa69cbSDouglas Gregor   llvm::sys::path::native(SubframeworksDirName.str(),
504ddaa69cbSDouglas Gregor                           SubframeworksDirNameNative);
505ddaa69cbSDouglas Gregor   for (llvm::sys::fs::directory_iterator
506ddaa69cbSDouglas Gregor          Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
507e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
508e89dbc1dSDouglas Gregor     if (!StringRef(Dir->path()).endswith(".framework"))
509e89dbc1dSDouglas Gregor       continue;
510f2161a70SDouglas Gregor 
511e89dbc1dSDouglas Gregor     if (const DirectoryEntry *SubframeworkDir
512e89dbc1dSDouglas Gregor           = FileMgr.getDirectory(Dir->path())) {
51307c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
51407c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
51507c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
51607c22b78SDouglas Gregor       // out to a top-level framework.
517e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
51807c22b78SDouglas Gregor       bool FoundParent = false;
51907c22b78SDouglas Gregor       do {
52007c22b78SDouglas Gregor         // Get the parent directory name.
52107c22b78SDouglas Gregor         SubframeworkDirName
52207c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
52307c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
52407c22b78SDouglas Gregor           break;
52507c22b78SDouglas Gregor 
52607c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
52707c22b78SDouglas Gregor           FoundParent = true;
52807c22b78SDouglas Gregor           break;
52907c22b78SDouglas Gregor         }
53007c22b78SDouglas Gregor       } while (true);
53107c22b78SDouglas Gregor 
53207c22b78SDouglas Gregor       if (!FoundParent)
53307c22b78SDouglas Gregor         continue;
53407c22b78SDouglas Gregor 
535e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
536056396aeSDouglas Gregor       SmallString<32> NameBuf;
537056396aeSDouglas Gregor       inferFrameworkModule(sanitizeFilenameAsIdentifier(
538056396aeSDouglas Gregor                              llvm::sys::path::stem(Dir->path()), NameBuf),
539056396aeSDouglas Gregor                            SubframeworkDir, IsSystem, Result);
540e89dbc1dSDouglas Gregor     }
541e89dbc1dSDouglas Gregor   }
542e89dbc1dSDouglas Gregor 
54311dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
54411dfe6feSDouglas Gregor   // framework.
54511dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
54611dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
54711dfe6feSDouglas Gregor   }
54811dfe6feSDouglas Gregor 
54956c64013SDouglas Gregor   return Result;
55056c64013SDouglas Gregor }
55156c64013SDouglas Gregor 
552a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
55359527666SDouglas Gregor   Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
55473141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
5557033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
556a89c5ac4SDouglas Gregor }
557a89c5ac4SDouglas Gregor 
558524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
559524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
560524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
561524e33e1SDouglas Gregor }
562524e33e1SDouglas Gregor 
56359527666SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
56459527666SDouglas Gregor                           bool Excluded) {
56559527666SDouglas Gregor   if (Excluded)
56659527666SDouglas Gregor     Mod->ExcludedHeaders.push_back(Header);
56759527666SDouglas Gregor   else
568a89c5ac4SDouglas Gregor     Mod->Headers.push_back(Header);
56959527666SDouglas Gregor   Headers[Header] = KnownHeader(Mod, Excluded);
570a89c5ac4SDouglas Gregor }
571a89c5ac4SDouglas Gregor 
572514b636aSDouglas Gregor const FileEntry *
573de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
574514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
575514b636aSDouglas Gregor     return 0;
576514b636aSDouglas Gregor 
577514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
578514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
579514b636aSDouglas Gregor }
580514b636aSDouglas Gregor 
581718292f2SDouglas Gregor void ModuleMap::dump() {
582718292f2SDouglas Gregor   llvm::errs() << "Modules:";
583718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
584718292f2SDouglas Gregor                                         MEnd = Modules.end();
585718292f2SDouglas Gregor        M != MEnd; ++M)
586d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
587718292f2SDouglas Gregor 
588718292f2SDouglas Gregor   llvm::errs() << "Headers:";
58959527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
590718292f2SDouglas Gregor        H != HEnd; ++H) {
591718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
59259527666SDouglas Gregor                  << H->second.getModule()->getFullModuleName() << "\n";
593718292f2SDouglas Gregor   }
594718292f2SDouglas Gregor }
595718292f2SDouglas Gregor 
5962b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
5972b82c2a5SDouglas Gregor   bool HadError = false;
5982b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
5992b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
6002b82c2a5SDouglas Gregor                                               Complain);
601f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
6022b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
6032b82c2a5SDouglas Gregor     else
6042b82c2a5SDouglas Gregor       HadError = true;
6052b82c2a5SDouglas Gregor   }
6062b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
6072b82c2a5SDouglas Gregor   return HadError;
6082b82c2a5SDouglas Gregor }
6092b82c2a5SDouglas Gregor 
6100093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
6110093b3c7SDouglas Gregor   if (Loc.isInvalid())
6120093b3c7SDouglas Gregor     return 0;
6130093b3c7SDouglas Gregor 
6140093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
6150093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
6160093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
6170093b3c7SDouglas Gregor     return 0;
6180093b3c7SDouglas Gregor 
6190093b3c7SDouglas Gregor 
6200093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
6210093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
622224d8a74SDouglas Gregor 
623224d8a74SDouglas Gregor   while (const FileEntry *ExpansionFile
624224d8a74SDouglas Gregor            = SrcMgr.getFileEntryForID(ExpansionFileID)) {
625224d8a74SDouglas Gregor     // Find the module that owns this header (if any).
626224d8a74SDouglas Gregor     if (Module *Mod = findModuleForHeader(ExpansionFile))
627224d8a74SDouglas Gregor       return Mod;
628224d8a74SDouglas Gregor 
629224d8a74SDouglas Gregor     // No module owns this header, so look up the inclusion chain to see if
630224d8a74SDouglas Gregor     // any included header has an associated module.
631224d8a74SDouglas Gregor     SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
632224d8a74SDouglas Gregor     if (IncludeLoc.isInvalid())
6330093b3c7SDouglas Gregor       return 0;
6340093b3c7SDouglas Gregor 
635224d8a74SDouglas Gregor     ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
636224d8a74SDouglas Gregor   }
637224d8a74SDouglas Gregor 
638224d8a74SDouglas Gregor   return 0;
6390093b3c7SDouglas Gregor }
6400093b3c7SDouglas Gregor 
641718292f2SDouglas Gregor //----------------------------------------------------------------------------//
642718292f2SDouglas Gregor // Module map file parser
643718292f2SDouglas Gregor //----------------------------------------------------------------------------//
644718292f2SDouglas Gregor 
645718292f2SDouglas Gregor namespace clang {
646718292f2SDouglas Gregor   /// \brief A token in a module map file.
647718292f2SDouglas Gregor   struct MMToken {
648718292f2SDouglas Gregor     enum TokenKind {
6491fb5c3a6SDouglas Gregor       Comma,
650718292f2SDouglas Gregor       EndOfFile,
651718292f2SDouglas Gregor       HeaderKeyword,
652718292f2SDouglas Gregor       Identifier,
65359527666SDouglas Gregor       ExcludeKeyword,
654718292f2SDouglas Gregor       ExplicitKeyword,
6552b82c2a5SDouglas Gregor       ExportKeyword,
656755b2055SDouglas Gregor       FrameworkKeyword,
6576ddfca91SDouglas Gregor       LinkKeyword,
658718292f2SDouglas Gregor       ModuleKeyword,
6592b82c2a5SDouglas Gregor       Period,
660718292f2SDouglas Gregor       UmbrellaKeyword,
6611fb5c3a6SDouglas Gregor       RequiresKeyword,
6622b82c2a5SDouglas Gregor       Star,
663718292f2SDouglas Gregor       StringLiteral,
664718292f2SDouglas Gregor       LBrace,
665a686e1b0SDouglas Gregor       RBrace,
666a686e1b0SDouglas Gregor       LSquare,
667a686e1b0SDouglas Gregor       RSquare
668718292f2SDouglas Gregor     } Kind;
669718292f2SDouglas Gregor 
670718292f2SDouglas Gregor     unsigned Location;
671718292f2SDouglas Gregor     unsigned StringLength;
672718292f2SDouglas Gregor     const char *StringData;
673718292f2SDouglas Gregor 
674718292f2SDouglas Gregor     void clear() {
675718292f2SDouglas Gregor       Kind = EndOfFile;
676718292f2SDouglas Gregor       Location = 0;
677718292f2SDouglas Gregor       StringLength = 0;
678718292f2SDouglas Gregor       StringData = 0;
679718292f2SDouglas Gregor     }
680718292f2SDouglas Gregor 
681718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
682718292f2SDouglas Gregor 
683718292f2SDouglas Gregor     SourceLocation getLocation() const {
684718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
685718292f2SDouglas Gregor     }
686718292f2SDouglas Gregor 
687718292f2SDouglas Gregor     StringRef getString() const {
688718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
689718292f2SDouglas Gregor     }
690718292f2SDouglas Gregor   };
691718292f2SDouglas Gregor 
6929194a91dSDouglas Gregor   /// \brief The set of attributes that can be attached to a module.
6934442605fSBill Wendling   struct Attributes {
6944442605fSBill Wendling     Attributes() : IsSystem() { }
6959194a91dSDouglas Gregor 
6969194a91dSDouglas Gregor     /// \brief Whether this is a system module.
6979194a91dSDouglas Gregor     unsigned IsSystem : 1;
6989194a91dSDouglas Gregor   };
6999194a91dSDouglas Gregor 
7009194a91dSDouglas Gregor 
701718292f2SDouglas Gregor   class ModuleMapParser {
702718292f2SDouglas Gregor     Lexer &L;
703718292f2SDouglas Gregor     SourceManager &SourceMgr;
704bc10b9fbSDouglas Gregor 
705bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
706bc10b9fbSDouglas Gregor     /// parsing.
707bc10b9fbSDouglas Gregor     const TargetInfo *Target;
708bc10b9fbSDouglas Gregor 
709718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
710718292f2SDouglas Gregor     ModuleMap &Map;
711718292f2SDouglas Gregor 
7125257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
7135257fc63SDouglas Gregor     const DirectoryEntry *Directory;
7145257fc63SDouglas Gregor 
7153ec6663bSDouglas Gregor     /// \brief The directory containing Clang-supplied headers.
7163ec6663bSDouglas Gregor     const DirectoryEntry *BuiltinIncludeDir;
7173ec6663bSDouglas Gregor 
718718292f2SDouglas Gregor     /// \brief Whether an error occurred.
719718292f2SDouglas Gregor     bool HadError;
720718292f2SDouglas Gregor 
721718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
722718292f2SDouglas Gregor     /// during parsing.
723718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
724718292f2SDouglas Gregor 
725718292f2SDouglas Gregor     /// \brief The current token.
726718292f2SDouglas Gregor     MMToken Tok;
727718292f2SDouglas Gregor 
728718292f2SDouglas Gregor     /// \brief The active module.
729de3ef502SDouglas Gregor     Module *ActiveModule;
730718292f2SDouglas Gregor 
731718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
732718292f2SDouglas Gregor     SourceLocation consumeToken();
733718292f2SDouglas Gregor 
734718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
735718292f2SDouglas Gregor     /// (or the end of the file).
736718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
737718292f2SDouglas Gregor 
738f857950dSDmitri Gribenko     typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
739e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
740718292f2SDouglas Gregor     void parseModuleDecl();
7411fb5c3a6SDouglas Gregor     void parseRequiresDecl();
74259527666SDouglas Gregor     void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
743524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
7442b82c2a5SDouglas Gregor     void parseExportDecl();
7456ddfca91SDouglas Gregor     void parseLinkDecl();
7469194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
7474442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
748718292f2SDouglas Gregor 
7497033127bSDouglas Gregor     const DirectoryEntry *getOverriddenHeaderSearchDir();
7507033127bSDouglas Gregor 
751718292f2SDouglas Gregor   public:
752718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
753bc10b9fbSDouglas Gregor                              const TargetInfo *Target,
754718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
7555257fc63SDouglas Gregor                              ModuleMap &Map,
7563ec6663bSDouglas Gregor                              const DirectoryEntry *Directory,
7573ec6663bSDouglas Gregor                              const DirectoryEntry *BuiltinIncludeDir)
758bc10b9fbSDouglas Gregor       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
7593ec6663bSDouglas Gregor         Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
7603ec6663bSDouglas Gregor         HadError(false), ActiveModule(0)
761718292f2SDouglas Gregor     {
762718292f2SDouglas Gregor       Tok.clear();
763718292f2SDouglas Gregor       consumeToken();
764718292f2SDouglas Gregor     }
765718292f2SDouglas Gregor 
766718292f2SDouglas Gregor     bool parseModuleMapFile();
767718292f2SDouglas Gregor   };
768718292f2SDouglas Gregor }
769718292f2SDouglas Gregor 
770718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
771718292f2SDouglas Gregor retry:
772718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
773718292f2SDouglas Gregor   Tok.clear();
774718292f2SDouglas Gregor 
775718292f2SDouglas Gregor   Token LToken;
776718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
777718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
778718292f2SDouglas Gregor   switch (LToken.getKind()) {
779718292f2SDouglas Gregor   case tok::raw_identifier:
780718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
781718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
782718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
783718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
78459527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
785718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
7862b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
787755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
7886ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
789718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
7901fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
791718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
792718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
793718292f2SDouglas Gregor     break;
794718292f2SDouglas Gregor 
7951fb5c3a6SDouglas Gregor   case tok::comma:
7961fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
7971fb5c3a6SDouglas Gregor     break;
7981fb5c3a6SDouglas Gregor 
799718292f2SDouglas Gregor   case tok::eof:
800718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
801718292f2SDouglas Gregor     break;
802718292f2SDouglas Gregor 
803718292f2SDouglas Gregor   case tok::l_brace:
804718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
805718292f2SDouglas Gregor     break;
806718292f2SDouglas Gregor 
807a686e1b0SDouglas Gregor   case tok::l_square:
808a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
809a686e1b0SDouglas Gregor     break;
810a686e1b0SDouglas Gregor 
8112b82c2a5SDouglas Gregor   case tok::period:
8122b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
8132b82c2a5SDouglas Gregor     break;
8142b82c2a5SDouglas Gregor 
815718292f2SDouglas Gregor   case tok::r_brace:
816718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
817718292f2SDouglas Gregor     break;
818718292f2SDouglas Gregor 
819a686e1b0SDouglas Gregor   case tok::r_square:
820a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
821a686e1b0SDouglas Gregor     break;
822a686e1b0SDouglas Gregor 
8232b82c2a5SDouglas Gregor   case tok::star:
8242b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
8252b82c2a5SDouglas Gregor     break;
8262b82c2a5SDouglas Gregor 
827718292f2SDouglas Gregor   case tok::string_literal: {
828d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
829d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
830d67aea28SRichard Smith       HadError = true;
831d67aea28SRichard Smith       goto retry;
832d67aea28SRichard Smith     }
833d67aea28SRichard Smith 
834718292f2SDouglas Gregor     // Parse the string literal.
835718292f2SDouglas Gregor     LangOptions LangOpts;
836718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
837718292f2SDouglas Gregor     if (StringLiteral.hadError)
838718292f2SDouglas Gregor       goto retry;
839718292f2SDouglas Gregor 
840718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
841718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
842718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
843718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
844718292f2SDouglas Gregor     Saved[Length] = 0;
845718292f2SDouglas Gregor 
846718292f2SDouglas Gregor     // Form the token.
847718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
848718292f2SDouglas Gregor     Tok.StringData = Saved;
849718292f2SDouglas Gregor     Tok.StringLength = Length;
850718292f2SDouglas Gregor     break;
851718292f2SDouglas Gregor   }
852718292f2SDouglas Gregor 
853718292f2SDouglas Gregor   case tok::comment:
854718292f2SDouglas Gregor     goto retry;
855718292f2SDouglas Gregor 
856718292f2SDouglas Gregor   default:
857718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
858718292f2SDouglas Gregor     HadError = true;
859718292f2SDouglas Gregor     goto retry;
860718292f2SDouglas Gregor   }
861718292f2SDouglas Gregor 
862718292f2SDouglas Gregor   return Result;
863718292f2SDouglas Gregor }
864718292f2SDouglas Gregor 
865718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
866718292f2SDouglas Gregor   unsigned braceDepth = 0;
867a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
868718292f2SDouglas Gregor   do {
869718292f2SDouglas Gregor     switch (Tok.Kind) {
870718292f2SDouglas Gregor     case MMToken::EndOfFile:
871718292f2SDouglas Gregor       return;
872718292f2SDouglas Gregor 
873718292f2SDouglas Gregor     case MMToken::LBrace:
874a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
875718292f2SDouglas Gregor         return;
876718292f2SDouglas Gregor 
877718292f2SDouglas Gregor       ++braceDepth;
878718292f2SDouglas Gregor       break;
879718292f2SDouglas Gregor 
880a686e1b0SDouglas Gregor     case MMToken::LSquare:
881a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
882a686e1b0SDouglas Gregor         return;
883a686e1b0SDouglas Gregor 
884a686e1b0SDouglas Gregor       ++squareDepth;
885a686e1b0SDouglas Gregor       break;
886a686e1b0SDouglas Gregor 
887718292f2SDouglas Gregor     case MMToken::RBrace:
888718292f2SDouglas Gregor       if (braceDepth > 0)
889718292f2SDouglas Gregor         --braceDepth;
890718292f2SDouglas Gregor       else if (Tok.is(K))
891718292f2SDouglas Gregor         return;
892718292f2SDouglas Gregor       break;
893718292f2SDouglas Gregor 
894a686e1b0SDouglas Gregor     case MMToken::RSquare:
895a686e1b0SDouglas Gregor       if (squareDepth > 0)
896a686e1b0SDouglas Gregor         --squareDepth;
897a686e1b0SDouglas Gregor       else if (Tok.is(K))
898a686e1b0SDouglas Gregor         return;
899a686e1b0SDouglas Gregor       break;
900a686e1b0SDouglas Gregor 
901718292f2SDouglas Gregor     default:
902a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
903718292f2SDouglas Gregor         return;
904718292f2SDouglas Gregor       break;
905718292f2SDouglas Gregor     }
906718292f2SDouglas Gregor 
907718292f2SDouglas Gregor    consumeToken();
908718292f2SDouglas Gregor   } while (true);
909718292f2SDouglas Gregor }
910718292f2SDouglas Gregor 
911e7ab3669SDouglas Gregor /// \brief Parse a module-id.
912e7ab3669SDouglas Gregor ///
913e7ab3669SDouglas Gregor ///   module-id:
914e7ab3669SDouglas Gregor ///     identifier
915e7ab3669SDouglas Gregor ///     identifier '.' module-id
916e7ab3669SDouglas Gregor ///
917e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
918e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
919e7ab3669SDouglas Gregor   Id.clear();
920e7ab3669SDouglas Gregor   do {
921e7ab3669SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
922e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
923e7ab3669SDouglas Gregor       consumeToken();
924e7ab3669SDouglas Gregor     } else {
925e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
926e7ab3669SDouglas Gregor       return true;
927e7ab3669SDouglas Gregor     }
928e7ab3669SDouglas Gregor 
929e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
930e7ab3669SDouglas Gregor       break;
931e7ab3669SDouglas Gregor 
932e7ab3669SDouglas Gregor     consumeToken();
933e7ab3669SDouglas Gregor   } while (true);
934e7ab3669SDouglas Gregor 
935e7ab3669SDouglas Gregor   return false;
936e7ab3669SDouglas Gregor }
937e7ab3669SDouglas Gregor 
938a686e1b0SDouglas Gregor namespace {
939a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
940a686e1b0SDouglas Gregor   enum AttributeKind {
941a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
942a686e1b0SDouglas Gregor     AT_unknown,
943a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
944a686e1b0SDouglas Gregor     AT_system
945a686e1b0SDouglas Gregor   };
946a686e1b0SDouglas Gregor }
947a686e1b0SDouglas Gregor 
948718292f2SDouglas Gregor /// \brief Parse a module declaration.
949718292f2SDouglas Gregor ///
950718292f2SDouglas Gregor ///   module-declaration:
951a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
952a686e1b0SDouglas Gregor ///       { module-member* }
953a686e1b0SDouglas Gregor ///
954718292f2SDouglas Gregor ///   module-member:
9551fb5c3a6SDouglas Gregor ///     requires-declaration
956718292f2SDouglas Gregor ///     header-declaration
957e7ab3669SDouglas Gregor ///     submodule-declaration
9582b82c2a5SDouglas Gregor ///     export-declaration
9596ddfca91SDouglas Gregor ///     link-declaration
96073441091SDouglas Gregor ///
96173441091SDouglas Gregor ///   submodule-declaration:
96273441091SDouglas Gregor ///     module-declaration
96373441091SDouglas Gregor ///     inferred-submodule-declaration
964718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
965755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
966755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
967f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
968e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
969718292f2SDouglas Gregor   bool Explicit = false;
970f2161a70SDouglas Gregor   bool Framework = false;
971755b2055SDouglas Gregor 
972f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
973f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
974e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
975f2161a70SDouglas Gregor     Explicit = true;
976f2161a70SDouglas Gregor   }
977f2161a70SDouglas Gregor 
978f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
979755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
980755b2055SDouglas Gregor     consumeToken();
981755b2055SDouglas Gregor     Framework = true;
982755b2055SDouglas Gregor   }
983718292f2SDouglas Gregor 
984718292f2SDouglas Gregor   // Parse 'module' keyword.
985718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
986d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
987718292f2SDouglas Gregor     consumeToken();
988718292f2SDouglas Gregor     HadError = true;
989718292f2SDouglas Gregor     return;
990718292f2SDouglas Gregor   }
991718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
992718292f2SDouglas Gregor 
99373441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
99473441091SDouglas Gregor   // Parse it.
99573441091SDouglas Gregor   if (Tok.is(MMToken::Star))
9969194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
99773441091SDouglas Gregor 
998718292f2SDouglas Gregor   // Parse the module name.
999e7ab3669SDouglas Gregor   ModuleId Id;
1000e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1001718292f2SDouglas Gregor     HadError = true;
1002718292f2SDouglas Gregor     return;
1003718292f2SDouglas Gregor   }
1004e7ab3669SDouglas Gregor 
1005e7ab3669SDouglas Gregor   if (ActiveModule) {
1006e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1007e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1008e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1009e7ab3669SDouglas Gregor 
1010e7ab3669SDouglas Gregor       HadError = true;
1011e7ab3669SDouglas Gregor       return;
1012e7ab3669SDouglas Gregor     }
1013e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1014e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1015e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1016e7ab3669SDouglas Gregor     Explicit = false;
1017e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1018e7ab3669SDouglas Gregor     HadError = true;
1019e7ab3669SDouglas Gregor   }
1020e7ab3669SDouglas Gregor 
1021e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1022e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1023e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1024e7ab3669SDouglas Gregor     // is a submodule.
1025e7ab3669SDouglas Gregor     ActiveModule = 0;
1026e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1027e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1028e7ab3669SDouglas Gregor         ActiveModule = Next;
1029e7ab3669SDouglas Gregor         continue;
1030e7ab3669SDouglas Gregor       }
1031e7ab3669SDouglas Gregor 
1032e7ab3669SDouglas Gregor       if (ActiveModule) {
1033e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1034e7ab3669SDouglas Gregor           << Id[I].first << ActiveModule->getTopLevelModule();
1035e7ab3669SDouglas Gregor       } else {
1036e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1037e7ab3669SDouglas Gregor       }
1038e7ab3669SDouglas Gregor       HadError = true;
1039e7ab3669SDouglas Gregor       return;
1040e7ab3669SDouglas Gregor     }
1041e7ab3669SDouglas Gregor   }
1042e7ab3669SDouglas Gregor 
1043e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1044e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1045718292f2SDouglas Gregor 
1046a686e1b0SDouglas Gregor   // Parse the optional attribute list.
10474442605fSBill Wendling   Attributes Attrs;
10489194a91dSDouglas Gregor   parseOptionalAttributes(Attrs);
1049a686e1b0SDouglas Gregor 
1050718292f2SDouglas Gregor   // Parse the opening brace.
1051718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1052718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1053718292f2SDouglas Gregor       << ModuleName;
1054718292f2SDouglas Gregor     HadError = true;
1055718292f2SDouglas Gregor     return;
1056718292f2SDouglas Gregor   }
1057718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1058718292f2SDouglas Gregor 
1059718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
1060eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1061fcc54a3bSDouglas Gregor     if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1062fcc54a3bSDouglas Gregor       // Skip the module definition.
1063fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1064fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1065fcc54a3bSDouglas Gregor         consumeToken();
1066fcc54a3bSDouglas Gregor       else {
1067fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1068fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1069fcc54a3bSDouglas Gregor         HadError = true;
1070fcc54a3bSDouglas Gregor       }
1071fcc54a3bSDouglas Gregor       return;
1072fcc54a3bSDouglas Gregor     }
1073fcc54a3bSDouglas Gregor 
1074718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1075718292f2SDouglas Gregor       << ModuleName;
1076eb90e830SDouglas Gregor     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1077718292f2SDouglas Gregor 
1078718292f2SDouglas Gregor     // Skip the module definition.
1079718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
1080718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
1081718292f2SDouglas Gregor       consumeToken();
1082718292f2SDouglas Gregor 
1083718292f2SDouglas Gregor     HadError = true;
1084718292f2SDouglas Gregor     return;
1085718292f2SDouglas Gregor   }
1086718292f2SDouglas Gregor 
1087718292f2SDouglas Gregor   // Start defining this module.
1088eb90e830SDouglas Gregor   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1089eb90e830SDouglas Gregor                                         Explicit).first;
1090eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
10919194a91dSDouglas Gregor   if (Attrs.IsSystem)
1092a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
1093718292f2SDouglas Gregor 
1094718292f2SDouglas Gregor   bool Done = false;
1095718292f2SDouglas Gregor   do {
1096718292f2SDouglas Gregor     switch (Tok.Kind) {
1097718292f2SDouglas Gregor     case MMToken::EndOfFile:
1098718292f2SDouglas Gregor     case MMToken::RBrace:
1099718292f2SDouglas Gregor       Done = true;
1100718292f2SDouglas Gregor       break;
1101718292f2SDouglas Gregor 
1102718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
1103f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1104718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1105718292f2SDouglas Gregor       parseModuleDecl();
1106718292f2SDouglas Gregor       break;
1107718292f2SDouglas Gregor 
11082b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
11092b82c2a5SDouglas Gregor       parseExportDecl();
11102b82c2a5SDouglas Gregor       break;
11112b82c2a5SDouglas Gregor 
11121fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
11131fb5c3a6SDouglas Gregor       parseRequiresDecl();
11141fb5c3a6SDouglas Gregor       break;
11151fb5c3a6SDouglas Gregor 
1116524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1117524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1118524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
111959527666SDouglas Gregor         parseHeaderDecl(UmbrellaLoc, SourceLocation());
1120524e33e1SDouglas Gregor       else
1121524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1122718292f2SDouglas Gregor       break;
1123524e33e1SDouglas Gregor     }
1124718292f2SDouglas Gregor 
112559527666SDouglas Gregor     case MMToken::ExcludeKeyword: {
112659527666SDouglas Gregor       SourceLocation ExcludeLoc = consumeToken();
112759527666SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword)) {
112859527666SDouglas Gregor         parseHeaderDecl(SourceLocation(), ExcludeLoc);
112959527666SDouglas Gregor       } else {
113059527666SDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
113159527666SDouglas Gregor           << "exclude";
113259527666SDouglas Gregor       }
113359527666SDouglas Gregor       break;
113459527666SDouglas Gregor     }
113559527666SDouglas Gregor 
1136322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
113759527666SDouglas Gregor       parseHeaderDecl(SourceLocation(), SourceLocation());
1138718292f2SDouglas Gregor       break;
1139718292f2SDouglas Gregor 
11406ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
11416ddfca91SDouglas Gregor       parseLinkDecl();
11426ddfca91SDouglas Gregor       break;
11436ddfca91SDouglas Gregor 
1144718292f2SDouglas Gregor     default:
1145718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1146718292f2SDouglas Gregor       consumeToken();
1147718292f2SDouglas Gregor       break;
1148718292f2SDouglas Gregor     }
1149718292f2SDouglas Gregor   } while (!Done);
1150718292f2SDouglas Gregor 
1151718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1152718292f2SDouglas Gregor     consumeToken();
1153718292f2SDouglas Gregor   else {
1154718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1155718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1156718292f2SDouglas Gregor     HadError = true;
1157718292f2SDouglas Gregor   }
1158718292f2SDouglas Gregor 
115911dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
116011dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
116111dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
116211dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
116311dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
116411dfe6feSDouglas Gregor   }
116511dfe6feSDouglas Gregor 
1166e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
1167e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
1168718292f2SDouglas Gregor }
1169718292f2SDouglas Gregor 
11701fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
11711fb5c3a6SDouglas Gregor ///
11721fb5c3a6SDouglas Gregor ///   requires-declaration:
11731fb5c3a6SDouglas Gregor ///     'requires' feature-list
11741fb5c3a6SDouglas Gregor ///
11751fb5c3a6SDouglas Gregor ///   feature-list:
11761fb5c3a6SDouglas Gregor ///     identifier ',' feature-list
11771fb5c3a6SDouglas Gregor ///     identifier
11781fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
11791fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
11801fb5c3a6SDouglas Gregor 
11811fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
11821fb5c3a6SDouglas Gregor   consumeToken();
11831fb5c3a6SDouglas Gregor 
11841fb5c3a6SDouglas Gregor   // Parse the feature-list.
11851fb5c3a6SDouglas Gregor   do {
11861fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
11871fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
11881fb5c3a6SDouglas Gregor       HadError = true;
11891fb5c3a6SDouglas Gregor       return;
11901fb5c3a6SDouglas Gregor     }
11911fb5c3a6SDouglas Gregor 
11921fb5c3a6SDouglas Gregor     // Consume the feature name.
11931fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
11941fb5c3a6SDouglas Gregor     consumeToken();
11951fb5c3a6SDouglas Gregor 
11961fb5c3a6SDouglas Gregor     // Add this feature.
119789929282SDouglas Gregor     ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
11981fb5c3a6SDouglas Gregor 
11991fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
12001fb5c3a6SDouglas Gregor       break;
12011fb5c3a6SDouglas Gregor 
12021fb5c3a6SDouglas Gregor     // Consume the comma.
12031fb5c3a6SDouglas Gregor     consumeToken();
12041fb5c3a6SDouglas Gregor   } while (true);
12051fb5c3a6SDouglas Gregor }
12061fb5c3a6SDouglas Gregor 
1207f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the
1208f2161a70SDouglas Gregor /// subframework in which the given module lives.
1209bf8da9d7SBenjamin Kramer static void appendSubframeworkPaths(Module *Mod,
1210f857950dSDmitri Gribenko                                     SmallVectorImpl<char> &Path) {
1211f2161a70SDouglas Gregor   // Collect the framework names from the given module to the top-level module.
1212f857950dSDmitri Gribenko   SmallVector<StringRef, 2> Paths;
1213f2161a70SDouglas Gregor   for (; Mod; Mod = Mod->Parent) {
1214f2161a70SDouglas Gregor     if (Mod->IsFramework)
1215f2161a70SDouglas Gregor       Paths.push_back(Mod->Name);
1216f2161a70SDouglas Gregor   }
1217f2161a70SDouglas Gregor 
1218f2161a70SDouglas Gregor   if (Paths.empty())
1219f2161a70SDouglas Gregor     return;
1220f2161a70SDouglas Gregor 
1221f2161a70SDouglas Gregor   // Add Frameworks/Name.framework for each subframework.
1222f2161a70SDouglas Gregor   for (unsigned I = Paths.size() - 1; I != 0; --I) {
1223f2161a70SDouglas Gregor     llvm::sys::path::append(Path, "Frameworks");
1224f2161a70SDouglas Gregor     llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1225f2161a70SDouglas Gregor   }
1226f2161a70SDouglas Gregor }
1227f2161a70SDouglas Gregor 
12283ec6663bSDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
12293ec6663bSDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
12303ec6663bSDouglas Gregor /// headers.
12313ec6663bSDouglas Gregor static bool isBuiltinHeader(StringRef FileName) {
12323ec6663bSDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
12333ec6663bSDouglas Gregor       .Case("float.h", true)
12343ec6663bSDouglas Gregor       .Case("iso646.h", true)
12353ec6663bSDouglas Gregor       .Case("limits.h", true)
12363ec6663bSDouglas Gregor       .Case("stdalign.h", true)
12373ec6663bSDouglas Gregor       .Case("stdarg.h", true)
12383ec6663bSDouglas Gregor       .Case("stdbool.h", true)
12393ec6663bSDouglas Gregor       .Case("stddef.h", true)
12403ec6663bSDouglas Gregor       .Case("stdint.h", true)
12413ec6663bSDouglas Gregor       .Case("tgmath.h", true)
12423ec6663bSDouglas Gregor       .Case("unwind.h", true)
12433ec6663bSDouglas Gregor       .Default(false);
12443ec6663bSDouglas Gregor }
12453ec6663bSDouglas Gregor 
1246718292f2SDouglas Gregor /// \brief Parse a header declaration.
1247718292f2SDouglas Gregor ///
1248718292f2SDouglas Gregor ///   header-declaration:
1249322f633cSDouglas Gregor ///     'umbrella'[opt] 'header' string-literal
125059527666SDouglas Gregor ///     'exclude'[opt] 'header' string-literal
125159527666SDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
125259527666SDouglas Gregor                                       SourceLocation ExcludeLoc) {
1253718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
12541871ed3dSBenjamin Kramer   consumeToken();
1255718292f2SDouglas Gregor 
1256322f633cSDouglas Gregor   bool Umbrella = UmbrellaLoc.isValid();
125759527666SDouglas Gregor   bool Exclude = ExcludeLoc.isValid();
125859527666SDouglas Gregor   assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
1259718292f2SDouglas Gregor   // Parse the header name.
1260718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1261718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1262718292f2SDouglas Gregor       << "header";
1263718292f2SDouglas Gregor     HadError = true;
1264718292f2SDouglas Gregor     return;
1265718292f2SDouglas Gregor   }
1266e7ab3669SDouglas Gregor   std::string FileName = Tok.getString();
1267718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
1268718292f2SDouglas Gregor 
1269524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1270524e33e1SDouglas Gregor   if (Umbrella && ActiveModule->Umbrella) {
1271524e33e1SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1272524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1273322f633cSDouglas Gregor     HadError = true;
1274322f633cSDouglas Gregor     return;
1275322f633cSDouglas Gregor   }
1276322f633cSDouglas Gregor 
12775257fc63SDouglas Gregor   // Look for this file.
1278e7ab3669SDouglas Gregor   const FileEntry *File = 0;
12793ec6663bSDouglas Gregor   const FileEntry *BuiltinFile = 0;
12802c1dd271SDylan Noblesmith   SmallString<128> PathName;
1281e7ab3669SDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
1282e7ab3669SDouglas Gregor     PathName = FileName;
1283e7ab3669SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
12847033127bSDouglas Gregor   } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
12857033127bSDouglas Gregor     PathName = Dir->getName();
12867033127bSDouglas Gregor     llvm::sys::path::append(PathName, FileName);
12877033127bSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
1288e7ab3669SDouglas Gregor   } else {
1289e7ab3669SDouglas Gregor     // Search for the header file within the search directory.
12907033127bSDouglas Gregor     PathName = Directory->getName();
1291e7ab3669SDouglas Gregor     unsigned PathLength = PathName.size();
1292755b2055SDouglas Gregor 
1293f2161a70SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
1294f2161a70SDouglas Gregor       appendSubframeworkPaths(ActiveModule, PathName);
1295755b2055SDouglas Gregor 
1296e7ab3669SDouglas Gregor       // Check whether this file is in the public headers.
1297e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
12985257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1299e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
1300e7ab3669SDouglas Gregor 
1301e7ab3669SDouglas Gregor       if (!File) {
1302e7ab3669SDouglas Gregor         // Check whether this file is in the private headers.
1303e7ab3669SDouglas Gregor         PathName.resize(PathLength);
1304e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
1305e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
1306e7ab3669SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
1307e7ab3669SDouglas Gregor       }
1308e7ab3669SDouglas Gregor     } else {
1309e7ab3669SDouglas Gregor       // Lookup for normal headers.
1310e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1311e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
13123ec6663bSDouglas Gregor 
13133ec6663bSDouglas Gregor       // If this is a system module with a top-level header, this header
13143ec6663bSDouglas Gregor       // may have a counterpart (or replacement) in the set of headers
13153ec6663bSDouglas Gregor       // supplied by Clang. Find that builtin header.
13163ec6663bSDouglas Gregor       if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
13173ec6663bSDouglas Gregor           BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
13182c1dd271SDylan Noblesmith         SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
13193ec6663bSDouglas Gregor         llvm::sys::path::append(BuiltinPathName, FileName);
13203ec6663bSDouglas Gregor         BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
13213ec6663bSDouglas Gregor 
13223ec6663bSDouglas Gregor         // If Clang supplies this header but the underlying system does not,
13233ec6663bSDouglas Gregor         // just silently swap in our builtin version. Otherwise, we'll end
13243ec6663bSDouglas Gregor         // up adding both (later).
13253ec6663bSDouglas Gregor         if (!File && BuiltinFile) {
13263ec6663bSDouglas Gregor           File = BuiltinFile;
13273ec6663bSDouglas Gregor           BuiltinFile = 0;
13283ec6663bSDouglas Gregor         }
13293ec6663bSDouglas Gregor       }
1330e7ab3669SDouglas Gregor     }
1331e7ab3669SDouglas Gregor   }
13325257fc63SDouglas Gregor 
13335257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
13345257fc63SDouglas Gregor   // Come up with a lazy way to do this.
1335e7ab3669SDouglas Gregor   if (File) {
133659527666SDouglas Gregor     if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
13375257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
133859527666SDouglas Gregor         << FileName << OwningModule.getModule()->getFullModuleName();
13395257fc63SDouglas Gregor       HadError = true;
1340322f633cSDouglas Gregor     } else if (Umbrella) {
1341322f633cSDouglas Gregor       const DirectoryEntry *UmbrellaDir = File->getDir();
134259527666SDouglas Gregor       if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
1343322f633cSDouglas Gregor         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
134459527666SDouglas Gregor           << UmbrellaModule->getFullModuleName();
1345322f633cSDouglas Gregor         HadError = true;
13465257fc63SDouglas Gregor       } else {
1347322f633cSDouglas Gregor         // Record this umbrella header.
1348322f633cSDouglas Gregor         Map.setUmbrellaHeader(ActiveModule, File);
1349322f633cSDouglas Gregor       }
1350322f633cSDouglas Gregor     } else {
1351322f633cSDouglas Gregor       // Record this header.
135259527666SDouglas Gregor       Map.addHeader(ActiveModule, File, Exclude);
13533ec6663bSDouglas Gregor 
13543ec6663bSDouglas Gregor       // If there is a builtin counterpart to this file, add it now.
13553ec6663bSDouglas Gregor       if (BuiltinFile)
135659527666SDouglas Gregor         Map.addHeader(ActiveModule, BuiltinFile, Exclude);
13575257fc63SDouglas Gregor     }
13584b27a64bSDouglas Gregor   } else if (!Exclude) {
13594b27a64bSDouglas Gregor     // Ignore excluded header files. They're optional anyway.
13604b27a64bSDouglas Gregor 
13615257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
1362524e33e1SDouglas Gregor       << Umbrella << FileName;
13635257fc63SDouglas Gregor     HadError = true;
13645257fc63SDouglas Gregor   }
1365718292f2SDouglas Gregor }
1366718292f2SDouglas Gregor 
1367524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
1368524e33e1SDouglas Gregor ///
1369524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
1370524e33e1SDouglas Gregor ///     umbrella string-literal
1371524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1372524e33e1SDouglas Gregor   // Parse the directory name.
1373524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1374524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1375524e33e1SDouglas Gregor       << "umbrella";
1376524e33e1SDouglas Gregor     HadError = true;
1377524e33e1SDouglas Gregor     return;
1378524e33e1SDouglas Gregor   }
1379524e33e1SDouglas Gregor 
1380524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
1381524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
1382524e33e1SDouglas Gregor 
1383524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1384524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
1385524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1386524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1387524e33e1SDouglas Gregor     HadError = true;
1388524e33e1SDouglas Gregor     return;
1389524e33e1SDouglas Gregor   }
1390524e33e1SDouglas Gregor 
1391524e33e1SDouglas Gregor   // Look for this file.
1392524e33e1SDouglas Gregor   const DirectoryEntry *Dir = 0;
1393524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
1394524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
1395524e33e1SDouglas Gregor   else {
13962c1dd271SDylan Noblesmith     SmallString<128> PathName;
1397524e33e1SDouglas Gregor     PathName = Directory->getName();
1398524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
1399524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
1400524e33e1SDouglas Gregor   }
1401524e33e1SDouglas Gregor 
1402524e33e1SDouglas Gregor   if (!Dir) {
1403524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1404524e33e1SDouglas Gregor       << DirName;
1405524e33e1SDouglas Gregor     HadError = true;
1406524e33e1SDouglas Gregor     return;
1407524e33e1SDouglas Gregor   }
1408524e33e1SDouglas Gregor 
1409524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1410524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1411524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
1412524e33e1SDouglas Gregor     HadError = true;
1413524e33e1SDouglas Gregor     return;
1414524e33e1SDouglas Gregor   }
1415524e33e1SDouglas Gregor 
1416524e33e1SDouglas Gregor   // Record this umbrella directory.
1417524e33e1SDouglas Gregor   Map.setUmbrellaDir(ActiveModule, Dir);
1418524e33e1SDouglas Gregor }
1419524e33e1SDouglas Gregor 
14202b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
14212b82c2a5SDouglas Gregor ///
14222b82c2a5SDouglas Gregor ///   export-declaration:
14232b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
14242b82c2a5SDouglas Gregor ///
14252b82c2a5SDouglas Gregor ///   wildcard-module-id:
14262b82c2a5SDouglas Gregor ///     identifier
14272b82c2a5SDouglas Gregor ///     '*'
14282b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
14292b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
14302b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
14312b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
14322b82c2a5SDouglas Gregor 
14332b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
14342b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
14352b82c2a5SDouglas Gregor   bool Wildcard = false;
14362b82c2a5SDouglas Gregor   do {
14372b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
14382b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
14392b82c2a5SDouglas Gregor                                               Tok.getLocation()));
14402b82c2a5SDouglas Gregor       consumeToken();
14412b82c2a5SDouglas Gregor 
14422b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
14432b82c2a5SDouglas Gregor         consumeToken();
14442b82c2a5SDouglas Gregor         continue;
14452b82c2a5SDouglas Gregor       }
14462b82c2a5SDouglas Gregor 
14472b82c2a5SDouglas Gregor       break;
14482b82c2a5SDouglas Gregor     }
14492b82c2a5SDouglas Gregor 
14502b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
14512b82c2a5SDouglas Gregor       Wildcard = true;
1452f5eedd05SDouglas Gregor       consumeToken();
14532b82c2a5SDouglas Gregor       break;
14542b82c2a5SDouglas Gregor     }
14552b82c2a5SDouglas Gregor 
14562b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
14572b82c2a5SDouglas Gregor     HadError = true;
14582b82c2a5SDouglas Gregor     return;
14592b82c2a5SDouglas Gregor   } while (true);
14602b82c2a5SDouglas Gregor 
14612b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
14622b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
14632b82c2a5SDouglas Gregor   };
14642b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
14652b82c2a5SDouglas Gregor }
14662b82c2a5SDouglas Gregor 
14676ddfca91SDouglas Gregor /// \brief Parse a link declaration.
14686ddfca91SDouglas Gregor ///
14696ddfca91SDouglas Gregor ///   module-declaration:
14706ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
14716ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
14726ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
14736ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
14746ddfca91SDouglas Gregor 
14756ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
14766ddfca91SDouglas Gregor   bool IsFramework = false;
14776ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
14786ddfca91SDouglas Gregor     consumeToken();
14796ddfca91SDouglas Gregor     IsFramework = true;
14806ddfca91SDouglas Gregor   }
14816ddfca91SDouglas Gregor 
14826ddfca91SDouglas Gregor   // Parse the library name
14836ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
14846ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
14856ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
14866ddfca91SDouglas Gregor     HadError = true;
14876ddfca91SDouglas Gregor     return;
14886ddfca91SDouglas Gregor   }
14896ddfca91SDouglas Gregor 
14906ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
14916ddfca91SDouglas Gregor   consumeToken();
14926ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
14936ddfca91SDouglas Gregor                                                             IsFramework));
14946ddfca91SDouglas Gregor }
14956ddfca91SDouglas Gregor 
14966ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules).
14979194a91dSDouglas Gregor ///
14989194a91dSDouglas Gregor ///   module-declaration:
14999194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
15009194a91dSDouglas Gregor ///       { inferred-module-member* }
15019194a91dSDouglas Gregor ///
15029194a91dSDouglas Gregor ///   inferred-module-member:
15039194a91dSDouglas Gregor ///     'export' '*'
15049194a91dSDouglas Gregor ///     'exclude' identifier
15059194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
150673441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
150773441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
150873441091SDouglas Gregor   bool Failed = false;
150973441091SDouglas Gregor 
151073441091SDouglas Gregor   // Inferred modules must be submodules.
15119194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
151273441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
151373441091SDouglas Gregor     Failed = true;
151473441091SDouglas Gregor   }
151573441091SDouglas Gregor 
15169194a91dSDouglas Gregor   if (ActiveModule) {
1517524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
1518524e33e1SDouglas Gregor     if (!Failed && !ActiveModule->getUmbrellaDir()) {
151973441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
152073441091SDouglas Gregor       Failed = true;
152173441091SDouglas Gregor     }
152273441091SDouglas Gregor 
152373441091SDouglas Gregor     // Check for redefinition of an inferred module.
1524dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
152573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1526dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
1527dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
152873441091SDouglas Gregor                      diag::note_mmap_prev_definition);
152973441091SDouglas Gregor       Failed = true;
153073441091SDouglas Gregor     }
153173441091SDouglas Gregor 
15329194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
15339194a91dSDouglas Gregor     if (Framework) {
15349194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
15359194a91dSDouglas Gregor       Framework = false;
15369194a91dSDouglas Gregor     }
15379194a91dSDouglas Gregor   } else if (Explicit) {
15389194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
15399194a91dSDouglas Gregor     Explicit = false;
15409194a91dSDouglas Gregor   }
15419194a91dSDouglas Gregor 
154273441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
154373441091SDouglas Gregor   if (Failed) {
154473441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
154573441091SDouglas Gregor       consumeToken();
154673441091SDouglas Gregor       skipUntil(MMToken::RBrace);
154773441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
154873441091SDouglas Gregor         consumeToken();
154973441091SDouglas Gregor     }
155073441091SDouglas Gregor     HadError = true;
155173441091SDouglas Gregor     return;
155273441091SDouglas Gregor   }
155373441091SDouglas Gregor 
15549194a91dSDouglas Gregor   // Parse optional attributes.
15554442605fSBill Wendling   Attributes Attrs;
15569194a91dSDouglas Gregor   parseOptionalAttributes(Attrs);
15579194a91dSDouglas Gregor 
15589194a91dSDouglas Gregor   if (ActiveModule) {
155973441091SDouglas Gregor     // Note that we have an inferred submodule.
1560dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
1561dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
1562dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
15639194a91dSDouglas Gregor   } else {
15649194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
15659194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
15669194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
15679194a91dSDouglas Gregor   }
156873441091SDouglas Gregor 
156973441091SDouglas Gregor   // Parse the opening brace.
157073441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
157173441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
157273441091SDouglas Gregor     HadError = true;
157373441091SDouglas Gregor     return;
157473441091SDouglas Gregor   }
157573441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
157673441091SDouglas Gregor 
157773441091SDouglas Gregor   // Parse the body of the inferred submodule.
157873441091SDouglas Gregor   bool Done = false;
157973441091SDouglas Gregor   do {
158073441091SDouglas Gregor     switch (Tok.Kind) {
158173441091SDouglas Gregor     case MMToken::EndOfFile:
158273441091SDouglas Gregor     case MMToken::RBrace:
158373441091SDouglas Gregor       Done = true;
158473441091SDouglas Gregor       break;
158573441091SDouglas Gregor 
15869194a91dSDouglas Gregor     case MMToken::ExcludeKeyword: {
15879194a91dSDouglas Gregor       if (ActiveModule) {
15889194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1589162405daSDouglas Gregor           << (ActiveModule != 0);
15909194a91dSDouglas Gregor         consumeToken();
15919194a91dSDouglas Gregor         break;
15929194a91dSDouglas Gregor       }
15939194a91dSDouglas Gregor 
15949194a91dSDouglas Gregor       consumeToken();
15959194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
15969194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
15979194a91dSDouglas Gregor         break;
15989194a91dSDouglas Gregor       }
15999194a91dSDouglas Gregor 
16009194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
16019194a91dSDouglas Gregor         .push_back(Tok.getString());
16029194a91dSDouglas Gregor       consumeToken();
16039194a91dSDouglas Gregor       break;
16049194a91dSDouglas Gregor     }
16059194a91dSDouglas Gregor 
16069194a91dSDouglas Gregor     case MMToken::ExportKeyword:
16079194a91dSDouglas Gregor       if (!ActiveModule) {
16089194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1609162405daSDouglas Gregor           << (ActiveModule != 0);
16109194a91dSDouglas Gregor         consumeToken();
16119194a91dSDouglas Gregor         break;
16129194a91dSDouglas Gregor       }
16139194a91dSDouglas Gregor 
161473441091SDouglas Gregor       consumeToken();
161573441091SDouglas Gregor       if (Tok.is(MMToken::Star))
1616dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
161773441091SDouglas Gregor       else
161873441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
161973441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
162073441091SDouglas Gregor       consumeToken();
162173441091SDouglas Gregor       break;
162273441091SDouglas Gregor 
162373441091SDouglas Gregor     case MMToken::ExplicitKeyword:
162473441091SDouglas Gregor     case MMToken::ModuleKeyword:
162573441091SDouglas Gregor     case MMToken::HeaderKeyword:
162673441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
162773441091SDouglas Gregor     default:
16289194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1629162405daSDouglas Gregor           << (ActiveModule != 0);
163073441091SDouglas Gregor       consumeToken();
163173441091SDouglas Gregor       break;
163273441091SDouglas Gregor     }
163373441091SDouglas Gregor   } while (!Done);
163473441091SDouglas Gregor 
163573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
163673441091SDouglas Gregor     consumeToken();
163773441091SDouglas Gregor   else {
163873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
163973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
164073441091SDouglas Gregor     HadError = true;
164173441091SDouglas Gregor   }
164273441091SDouglas Gregor }
164373441091SDouglas Gregor 
16449194a91dSDouglas Gregor /// \brief Parse optional attributes.
16459194a91dSDouglas Gregor ///
16469194a91dSDouglas Gregor ///   attributes:
16479194a91dSDouglas Gregor ///     attribute attributes
16489194a91dSDouglas Gregor ///     attribute
16499194a91dSDouglas Gregor ///
16509194a91dSDouglas Gregor ///   attribute:
16519194a91dSDouglas Gregor ///     [ identifier ]
16529194a91dSDouglas Gregor ///
16539194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
16549194a91dSDouglas Gregor ///
16559194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
16564442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
16579194a91dSDouglas Gregor   bool HadError = false;
16589194a91dSDouglas Gregor 
16599194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
16609194a91dSDouglas Gregor     // Consume the '['.
16619194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
16629194a91dSDouglas Gregor 
16639194a91dSDouglas Gregor     // Check whether we have an attribute name here.
16649194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
16659194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
16669194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
16679194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
16689194a91dSDouglas Gregor         consumeToken();
16699194a91dSDouglas Gregor       HadError = true;
16709194a91dSDouglas Gregor     }
16719194a91dSDouglas Gregor 
16729194a91dSDouglas Gregor     // Decode the attribute name.
16739194a91dSDouglas Gregor     AttributeKind Attribute
16749194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
16759194a91dSDouglas Gregor           .Case("system", AT_system)
16769194a91dSDouglas Gregor           .Default(AT_unknown);
16779194a91dSDouglas Gregor     switch (Attribute) {
16789194a91dSDouglas Gregor     case AT_unknown:
16799194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
16809194a91dSDouglas Gregor         << Tok.getString();
16819194a91dSDouglas Gregor       break;
16829194a91dSDouglas Gregor 
16839194a91dSDouglas Gregor     case AT_system:
16849194a91dSDouglas Gregor       Attrs.IsSystem = true;
16859194a91dSDouglas Gregor       break;
16869194a91dSDouglas Gregor     }
16879194a91dSDouglas Gregor     consumeToken();
16889194a91dSDouglas Gregor 
16899194a91dSDouglas Gregor     // Consume the ']'.
16909194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
16919194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
16929194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
16939194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
16949194a91dSDouglas Gregor       HadError = true;
16959194a91dSDouglas Gregor     }
16969194a91dSDouglas Gregor 
16979194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
16989194a91dSDouglas Gregor       consumeToken();
16999194a91dSDouglas Gregor   }
17009194a91dSDouglas Gregor 
17019194a91dSDouglas Gregor   return HadError;
17029194a91dSDouglas Gregor }
17039194a91dSDouglas Gregor 
17047033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence
17057033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null.
17067033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
17077033127bSDouglas Gregor   for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
17087033127bSDouglas Gregor     // If we have an umbrella directory, use that.
17097033127bSDouglas Gregor     if (Mod->hasUmbrellaDir())
17107033127bSDouglas Gregor       return Mod->getUmbrellaDir();
17117033127bSDouglas Gregor 
17127033127bSDouglas Gregor     // If we have a framework directory, stop looking.
17137033127bSDouglas Gregor     if (Mod->IsFramework)
17147033127bSDouglas Gregor       return 0;
17157033127bSDouglas Gregor   }
17167033127bSDouglas Gregor 
17177033127bSDouglas Gregor   return 0;
17187033127bSDouglas Gregor }
17197033127bSDouglas Gregor 
1720718292f2SDouglas Gregor /// \brief Parse a module map file.
1721718292f2SDouglas Gregor ///
1722718292f2SDouglas Gregor ///   module-map-file:
1723718292f2SDouglas Gregor ///     module-declaration*
1724718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
1725718292f2SDouglas Gregor   do {
1726718292f2SDouglas Gregor     switch (Tok.Kind) {
1727718292f2SDouglas Gregor     case MMToken::EndOfFile:
1728718292f2SDouglas Gregor       return HadError;
1729718292f2SDouglas Gregor 
1730e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
1731718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1732755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
1733718292f2SDouglas Gregor       parseModuleDecl();
1734718292f2SDouglas Gregor       break;
1735718292f2SDouglas Gregor 
17361fb5c3a6SDouglas Gregor     case MMToken::Comma:
173759527666SDouglas Gregor     case MMToken::ExcludeKeyword:
17382b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
1739718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
1740718292f2SDouglas Gregor     case MMToken::Identifier:
1741718292f2SDouglas Gregor     case MMToken::LBrace:
17426ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
1743a686e1b0SDouglas Gregor     case MMToken::LSquare:
17442b82c2a5SDouglas Gregor     case MMToken::Period:
1745718292f2SDouglas Gregor     case MMToken::RBrace:
1746a686e1b0SDouglas Gregor     case MMToken::RSquare:
17471fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
17482b82c2a5SDouglas Gregor     case MMToken::Star:
1749718292f2SDouglas Gregor     case MMToken::StringLiteral:
1750718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
1751718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1752718292f2SDouglas Gregor       HadError = true;
1753718292f2SDouglas Gregor       consumeToken();
1754718292f2SDouglas Gregor       break;
1755718292f2SDouglas Gregor     }
1756718292f2SDouglas Gregor   } while (true);
1757718292f2SDouglas Gregor }
1758718292f2SDouglas Gregor 
1759718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
17604ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
17614ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
17624ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
17634ddf2221SDouglas Gregor     return Known->second;
17644ddf2221SDouglas Gregor 
176589929282SDouglas Gregor   assert(Target != 0 && "Missing target information");
1766718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1767718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1768718292f2SDouglas Gregor   if (!Buffer)
17694ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
1770718292f2SDouglas Gregor 
1771718292f2SDouglas Gregor   // Parse this module map file.
17721fb5c3a6SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
17731fb5c3a6SDouglas Gregor   Diags->getClient()->BeginSourceFile(MMapLangOpts);
1774bc10b9fbSDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
17753ec6663bSDouglas Gregor                          BuiltinIncludeDir);
1776718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
1777718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
17784ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
1779718292f2SDouglas Gregor   return Result;
1780718292f2SDouglas Gregor }
1781