1718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2718292f2SDouglas Gregor //
3718292f2SDouglas Gregor //                     The LLVM Compiler Infrastructure
4718292f2SDouglas Gregor //
5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6718292f2SDouglas Gregor // License. See LICENSE.TXT for details.
7718292f2SDouglas Gregor //
8718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
9718292f2SDouglas Gregor //
10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
11718292f2SDouglas Gregor // of a module as it relates to headers.
12718292f2SDouglas Gregor //
13718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15718292f2SDouglas Gregor #include "clang/Lex/Lexer.h"
16718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h"
17718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h"
18718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
19811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h"
20718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
21718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
22718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
23718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
24e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h"
25718292f2SDouglas Gregor #include "llvm/Support/Host.h"
265257fc63SDouglas Gregor #include "llvm/Support/PathV2.h"
27718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
28718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h"
29718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h"
3007c22b78SDouglas Gregor #include <stdlib.h>
31718292f2SDouglas Gregor using namespace clang;
32718292f2SDouglas Gregor 
332b82c2a5SDouglas Gregor Module::ExportDecl
342b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
352b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
362b82c2a5SDouglas Gregor                          bool Complain) {
37f5eedd05SDouglas Gregor   // We may have just a wildcard.
38f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
39f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
40f5eedd05SDouglas Gregor     return Module::ExportDecl(0, true);
41f5eedd05SDouglas Gregor   }
42f5eedd05SDouglas Gregor 
432b82c2a5SDouglas Gregor   // Find the starting module.
442b82c2a5SDouglas Gregor   Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
452b82c2a5SDouglas Gregor   if (!Context) {
462b82c2a5SDouglas Gregor     if (Complain)
472b82c2a5SDouglas Gregor       Diags->Report(Unresolved.Id[0].second,
482b82c2a5SDouglas Gregor                     diag::err_mmap_missing_module_unqualified)
492b82c2a5SDouglas Gregor         << Unresolved.Id[0].first << Mod->getFullModuleName();
502b82c2a5SDouglas Gregor 
512b82c2a5SDouglas Gregor     return Module::ExportDecl();
522b82c2a5SDouglas Gregor   }
532b82c2a5SDouglas Gregor 
542b82c2a5SDouglas Gregor   // Dig into the module path.
552b82c2a5SDouglas Gregor   for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
562b82c2a5SDouglas Gregor     Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
572b82c2a5SDouglas Gregor                                         Context);
582b82c2a5SDouglas Gregor     if (!Sub) {
592b82c2a5SDouglas Gregor       if (Complain)
602b82c2a5SDouglas Gregor         Diags->Report(Unresolved.Id[I].second,
612b82c2a5SDouglas Gregor                       diag::err_mmap_missing_module_qualified)
622b82c2a5SDouglas Gregor           << Unresolved.Id[I].first << Context->getFullModuleName()
632b82c2a5SDouglas Gregor           << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
642b82c2a5SDouglas Gregor 
652b82c2a5SDouglas Gregor       return Module::ExportDecl();
662b82c2a5SDouglas Gregor     }
672b82c2a5SDouglas Gregor 
682b82c2a5SDouglas Gregor     Context = Sub;
692b82c2a5SDouglas Gregor   }
702b82c2a5SDouglas Gregor 
712b82c2a5SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
722b82c2a5SDouglas Gregor }
732b82c2a5SDouglas Gregor 
741fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
7589929282SDouglas Gregor                      const LangOptions &LangOpts, const TargetInfo *Target)
763ec6663bSDouglas Gregor   : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0)
771fb5c3a6SDouglas Gregor {
78c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
79c95d8192SDylan Noblesmith   Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
80811db4eaSDouglas Gregor             new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
81718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
82718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
83718292f2SDouglas Gregor }
84718292f2SDouglas Gregor 
85718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
865acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
875acdf59eSDouglas Gregor                                         IEnd = Modules.end();
885acdf59eSDouglas Gregor        I != IEnd; ++I) {
895acdf59eSDouglas Gregor     delete I->getValue();
905acdf59eSDouglas Gregor   }
915acdf59eSDouglas Gregor 
92718292f2SDouglas Gregor   delete SourceMgr;
93718292f2SDouglas Gregor }
94718292f2SDouglas Gregor 
9589929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
9689929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
9789929282SDouglas Gregor          "Improper target override");
9889929282SDouglas Gregor   this->Target = &Target;
9989929282SDouglas Gregor }
10089929282SDouglas Gregor 
101056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier.
102056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
103056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
104056396aeSDouglas Gregor   if (Name.empty())
105056396aeSDouglas Gregor     return Name;
106056396aeSDouglas Gregor 
107056396aeSDouglas Gregor   // Check whether the filename is already an identifier; this is the common
108056396aeSDouglas Gregor   // case.
109056396aeSDouglas Gregor   bool isIdentifier = true;
110056396aeSDouglas Gregor   for (unsigned I = 0, N = Name.size(); I != N; ++I) {
111056396aeSDouglas Gregor     if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0))
112056396aeSDouglas Gregor       continue;
113056396aeSDouglas Gregor 
114056396aeSDouglas Gregor     isIdentifier = false;
115056396aeSDouglas Gregor     break;
116056396aeSDouglas Gregor   }
117056396aeSDouglas Gregor 
118056396aeSDouglas Gregor   if (!isIdentifier) {
119056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
120056396aeSDouglas Gregor     // create a buffer with the sanitized name.
121056396aeSDouglas Gregor     Buffer.clear();
122056396aeSDouglas Gregor     if (isdigit(Name[0]))
123056396aeSDouglas Gregor       Buffer.push_back('_');
124056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
125056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
126056396aeSDouglas Gregor       if (isalnum(Name[I]) || isspace(Name[I]))
127056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
128056396aeSDouglas Gregor       else
129056396aeSDouglas Gregor         Buffer.push_back('_');
130056396aeSDouglas Gregor     }
131056396aeSDouglas Gregor 
132056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
133056396aeSDouglas Gregor   }
134056396aeSDouglas Gregor 
135056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
136056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
137056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
138056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
139056396aeSDouglas Gregor            .Default(false)) {
140056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
141056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
142056396aeSDouglas Gregor     Buffer.push_back('_');
143056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
144056396aeSDouglas Gregor   }
145056396aeSDouglas Gregor 
146056396aeSDouglas Gregor   return Name;
147056396aeSDouglas Gregor }
148056396aeSDouglas Gregor 
149de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
15059527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
1511fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
15259527666SDouglas Gregor     // If a header is not available, don't report that it maps to anything.
15359527666SDouglas Gregor     if (!Known->second.isAvailable())
1541fb5c3a6SDouglas Gregor       return 0;
1551fb5c3a6SDouglas Gregor 
15659527666SDouglas Gregor     return Known->second.getModule();
1571fb5c3a6SDouglas Gregor   }
158ab0c8a84SDouglas Gregor 
159b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
160b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
161b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
162a89c5ac4SDouglas Gregor 
163a89c5ac4SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
164a89c5ac4SDouglas Gregor   // an umbrella header.
165b65dbfffSDouglas Gregor   do {
166a89c5ac4SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
167a89c5ac4SDouglas Gregor       = UmbrellaDirs.find(Dir);
168a89c5ac4SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
169a89c5ac4SDouglas Gregor       Module *Result = KnownDir->second;
170930a85ccSDouglas Gregor 
171930a85ccSDouglas Gregor       // Search up the module stack until we find a module with an umbrella
17273141fa9SDouglas Gregor       // directory.
173930a85ccSDouglas Gregor       Module *UmbrellaModule = Result;
17473141fa9SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
175930a85ccSDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
176930a85ccSDouglas Gregor 
177930a85ccSDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
178a89c5ac4SDouglas Gregor         // Infer submodules for each of the directories we found between
179a89c5ac4SDouglas Gregor         // the directory of the umbrella header and the directory where
180a89c5ac4SDouglas Gregor         // the actual header is located.
1819458f82dSDouglas Gregor         bool Explicit = UmbrellaModule->InferExplicitSubmodules;
1829458f82dSDouglas Gregor 
1837033127bSDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
184a89c5ac4SDouglas Gregor           // Find or create the module that corresponds to this directory name.
185056396aeSDouglas Gregor           SmallString<32> NameBuf;
186056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
187056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
188056396aeSDouglas Gregor                              NameBuf);
189a89c5ac4SDouglas Gregor           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
1909458f82dSDouglas Gregor                                       Explicit).first;
191a89c5ac4SDouglas Gregor 
192a89c5ac4SDouglas Gregor           // Associate the module and the directory.
193a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I-1]] = Result;
194a89c5ac4SDouglas Gregor 
195a89c5ac4SDouglas Gregor           // If inferred submodules export everything they import, add a
196a89c5ac4SDouglas Gregor           // wildcard to the set of exports.
197930a85ccSDouglas Gregor           if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
198a89c5ac4SDouglas Gregor             Result->Exports.push_back(Module::ExportDecl(0, true));
199a89c5ac4SDouglas Gregor         }
200a89c5ac4SDouglas Gregor 
201a89c5ac4SDouglas Gregor         // Infer a submodule with the same name as this header file.
202056396aeSDouglas Gregor         SmallString<32> NameBuf;
203056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
204056396aeSDouglas Gregor                            llvm::sys::path::stem(File->getName()), NameBuf);
205a89c5ac4SDouglas Gregor         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
2069458f82dSDouglas Gregor                                     Explicit).first;
207c597c8c4SArgyrios Kyrtzidis         Result->TopHeaders.insert(File);
208a89c5ac4SDouglas Gregor 
209a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
210a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
211930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
212a89c5ac4SDouglas Gregor           Result->Exports.push_back(Module::ExportDecl(0, true));
213a89c5ac4SDouglas Gregor       } else {
214a89c5ac4SDouglas Gregor         // Record each of the directories we stepped through as being part of
215a89c5ac4SDouglas Gregor         // the module we found, since the umbrella header covers them all.
216a89c5ac4SDouglas Gregor         for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
217a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I]] = Result;
218a89c5ac4SDouglas Gregor       }
219a89c5ac4SDouglas Gregor 
22059527666SDouglas Gregor       Headers[File] = KnownHeader(Result, /*Excluded=*/false);
2211fb5c3a6SDouglas Gregor 
2221fb5c3a6SDouglas Gregor       // If a header corresponds to an unavailable module, don't report
2231fb5c3a6SDouglas Gregor       // that it maps to anything.
2241fb5c3a6SDouglas Gregor       if (!Result->isAvailable())
2251fb5c3a6SDouglas Gregor         return 0;
2261fb5c3a6SDouglas Gregor 
227a89c5ac4SDouglas Gregor       return Result;
228a89c5ac4SDouglas Gregor     }
229a89c5ac4SDouglas Gregor 
230a89c5ac4SDouglas Gregor     SkippedDirs.push_back(Dir);
231a89c5ac4SDouglas Gregor 
232b65dbfffSDouglas Gregor     // Retrieve our parent path.
233b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
234b65dbfffSDouglas Gregor     if (DirName.empty())
235b65dbfffSDouglas Gregor       break;
236b65dbfffSDouglas Gregor 
237b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
238b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
239a89c5ac4SDouglas Gregor   } while (Dir);
240b65dbfffSDouglas Gregor 
241ab0c8a84SDouglas Gregor   return 0;
242ab0c8a84SDouglas Gregor }
243ab0c8a84SDouglas Gregor 
2441fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
24559527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(Header);
2461fb5c3a6SDouglas Gregor   if (Known != Headers.end())
24759527666SDouglas Gregor     return !Known->second.isAvailable();
2481fb5c3a6SDouglas Gregor 
2491fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
2501fb5c3a6SDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
2511fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
2521fb5c3a6SDouglas Gregor 
2531fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
2541fb5c3a6SDouglas Gregor   // an umbrella header.
2551fb5c3a6SDouglas Gregor   do {
2561fb5c3a6SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
2571fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
2581fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
2591fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
2601fb5c3a6SDouglas Gregor       if (!Found->isAvailable())
2611fb5c3a6SDouglas Gregor         return true;
2621fb5c3a6SDouglas Gregor 
2631fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
2641fb5c3a6SDouglas Gregor       // directory.
2651fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
2661fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
2671fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
2681fb5c3a6SDouglas Gregor 
2691fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
2701fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
2711fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
272056396aeSDouglas Gregor           SmallString<32> NameBuf;
273056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
274056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
275056396aeSDouglas Gregor                              NameBuf);
2761fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
2771fb5c3a6SDouglas Gregor           if (!Found)
2781fb5c3a6SDouglas Gregor             return false;
2791fb5c3a6SDouglas Gregor           if (!Found->isAvailable())
2801fb5c3a6SDouglas Gregor             return true;
2811fb5c3a6SDouglas Gregor         }
2821fb5c3a6SDouglas Gregor 
2831fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
284056396aeSDouglas Gregor         SmallString<32> NameBuf;
285056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
286056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
287056396aeSDouglas Gregor                            NameBuf);
2881fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
2891fb5c3a6SDouglas Gregor         if (!Found)
2901fb5c3a6SDouglas Gregor           return false;
2911fb5c3a6SDouglas Gregor       }
2921fb5c3a6SDouglas Gregor 
2931fb5c3a6SDouglas Gregor       return !Found->isAvailable();
2941fb5c3a6SDouglas Gregor     }
2951fb5c3a6SDouglas Gregor 
2961fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
2971fb5c3a6SDouglas Gregor 
2981fb5c3a6SDouglas Gregor     // Retrieve our parent path.
2991fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
3001fb5c3a6SDouglas Gregor     if (DirName.empty())
3011fb5c3a6SDouglas Gregor       break;
3021fb5c3a6SDouglas Gregor 
3031fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
3041fb5c3a6SDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
3051fb5c3a6SDouglas Gregor   } while (Dir);
3061fb5c3a6SDouglas Gregor 
3071fb5c3a6SDouglas Gregor   return false;
3081fb5c3a6SDouglas Gregor }
3091fb5c3a6SDouglas Gregor 
310de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
31188bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
31288bdfb0eSDouglas Gregor   if (Known != Modules.end())
31388bdfb0eSDouglas Gregor     return Known->getValue();
31488bdfb0eSDouglas Gregor 
31588bdfb0eSDouglas Gregor   return 0;
31688bdfb0eSDouglas Gregor }
31788bdfb0eSDouglas Gregor 
3182b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
3192b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
3202b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
3212b82c2a5SDouglas Gregor       return Sub;
3222b82c2a5SDouglas Gregor   }
3232b82c2a5SDouglas Gregor 
3242b82c2a5SDouglas Gregor   return findModule(Name);
3252b82c2a5SDouglas Gregor }
3262b82c2a5SDouglas Gregor 
3272b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
3282b82c2a5SDouglas Gregor   if (!Context)
3292b82c2a5SDouglas Gregor     return findModule(Name);
3302b82c2a5SDouglas Gregor 
331eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
3322b82c2a5SDouglas Gregor }
3332b82c2a5SDouglas Gregor 
334de3ef502SDouglas Gregor std::pair<Module *, bool>
33569021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
33669021974SDouglas Gregor                               bool IsExplicit) {
33769021974SDouglas Gregor   // Try to find an existing module with this name.
338eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
339eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
34069021974SDouglas Gregor 
34169021974SDouglas Gregor   // Create a new module with this name.
34269021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
34369021974SDouglas Gregor                               IsExplicit);
344eb90e830SDouglas Gregor   if (!Parent)
34569021974SDouglas Gregor     Modules[Name] = Result;
34669021974SDouglas Gregor   return std::make_pair(Result, true);
34769021974SDouglas Gregor }
34869021974SDouglas Gregor 
3499194a91dSDouglas Gregor bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
3509194a91dSDouglas Gregor                                         StringRef Name, bool &IsSystem) {
3519194a91dSDouglas Gregor   // Check whether we have already looked into the parent directory
3529194a91dSDouglas Gregor   // for a module map.
3539194a91dSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
3549194a91dSDouglas Gregor     inferred = InferredDirectories.find(ParentDir);
3559194a91dSDouglas Gregor   if (inferred == InferredDirectories.end())
3569194a91dSDouglas Gregor     return false;
3579194a91dSDouglas Gregor 
3589194a91dSDouglas Gregor   if (!inferred->second.InferModules)
3599194a91dSDouglas Gregor     return false;
3609194a91dSDouglas Gregor 
3619194a91dSDouglas Gregor   // We're allowed to infer for this directory, but make sure it's okay
3629194a91dSDouglas Gregor   // to infer this particular module.
3639194a91dSDouglas Gregor   bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
3649194a91dSDouglas Gregor                             inferred->second.ExcludedModules.end(),
3659194a91dSDouglas Gregor                             Name) == inferred->second.ExcludedModules.end();
3669194a91dSDouglas Gregor 
3679194a91dSDouglas Gregor   if (canInfer && inferred->second.InferSystemModules)
3689194a91dSDouglas Gregor     IsSystem = true;
3699194a91dSDouglas Gregor 
3709194a91dSDouglas Gregor   return canInfer;
3719194a91dSDouglas Gregor }
3729194a91dSDouglas Gregor 
373de3ef502SDouglas Gregor Module *
37456c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
375e89dbc1dSDouglas Gregor                                 const DirectoryEntry *FrameworkDir,
376a686e1b0SDouglas Gregor                                 bool IsSystem,
377e89dbc1dSDouglas Gregor                                 Module *Parent) {
37856c64013SDouglas Gregor   // Check whether we've already found this module.
379e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
380e89dbc1dSDouglas Gregor     return Mod;
381e89dbc1dSDouglas Gregor 
382e89dbc1dSDouglas Gregor   FileManager &FileMgr = SourceMgr->getFileManager();
38356c64013SDouglas Gregor 
3849194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
3859194a91dSDouglas Gregor   // a framework module, do so.
3869194a91dSDouglas Gregor   if (!Parent) {
3879194a91dSDouglas Gregor     bool canInfer = false;
3889194a91dSDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDir->getName())) {
3899194a91dSDouglas Gregor       // Figure out the parent path.
3909194a91dSDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDir->getName());
3919194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
3929194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
3939194a91dSDouglas Gregor         // for a module map.
3949194a91dSDouglas Gregor         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
3959194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
3969194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
3979194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
3989194a91dSDouglas Gregor           // one.
3999194a91dSDouglas Gregor           SmallString<128> ModMapPath = Parent;
4009194a91dSDouglas Gregor           llvm::sys::path::append(ModMapPath, "module.map");
4019194a91dSDouglas Gregor           if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
4029194a91dSDouglas Gregor             parseModuleMapFile(ModMapFile);
4039194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
4049194a91dSDouglas Gregor           }
4059194a91dSDouglas Gregor 
4069194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
4079194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
4089194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
4099194a91dSDouglas Gregor         }
4109194a91dSDouglas Gregor 
4119194a91dSDouglas Gregor         if (inferred->second.InferModules) {
4129194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
4139194a91dSDouglas Gregor           // to infer this particular module.
4149194a91dSDouglas Gregor           StringRef Name = llvm::sys::path::filename(FrameworkDir->getName());
4159194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
4169194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
4179194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
4189194a91dSDouglas Gregor 
4199194a91dSDouglas Gregor           if (inferred->second.InferSystemModules)
4209194a91dSDouglas Gregor             IsSystem = true;
4219194a91dSDouglas Gregor         }
4229194a91dSDouglas Gregor       }
4239194a91dSDouglas Gregor     }
4249194a91dSDouglas Gregor 
4259194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
4269194a91dSDouglas Gregor     if (!canInfer)
4279194a91dSDouglas Gregor       return 0;
4289194a91dSDouglas Gregor   }
4299194a91dSDouglas Gregor 
4309194a91dSDouglas Gregor 
43156c64013SDouglas Gregor   // Look for an umbrella header.
4322c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
43356c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
43456c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
435e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
43656c64013SDouglas Gregor 
43756c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
43856c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
43956c64013SDouglas Gregor   // idea.
44056c64013SDouglas Gregor   if (!UmbrellaHeader)
44156c64013SDouglas Gregor     return 0;
44256c64013SDouglas Gregor 
443e89dbc1dSDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
444e89dbc1dSDouglas Gregor                               /*IsFramework=*/true, /*IsExplicit=*/false);
445a686e1b0SDouglas Gregor   if (IsSystem)
446a686e1b0SDouglas Gregor     Result->IsSystem = IsSystem;
447a686e1b0SDouglas Gregor 
448eb90e830SDouglas Gregor   if (!Parent)
449e89dbc1dSDouglas Gregor     Modules[ModuleName] = Result;
450e89dbc1dSDouglas Gregor 
451322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
45273141fa9SDouglas Gregor   Result->Umbrella = UmbrellaHeader;
45359527666SDouglas Gregor   Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
4544dc71835SDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
455d8bd7537SDouglas Gregor 
456d8bd7537SDouglas Gregor   // export *
457d8bd7537SDouglas Gregor   Result->Exports.push_back(Module::ExportDecl(0, true));
458d8bd7537SDouglas Gregor 
459a89c5ac4SDouglas Gregor   // module * { export * }
460a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
461a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
462a89c5ac4SDouglas Gregor 
463e89dbc1dSDouglas Gregor   // Look for subframeworks.
464e89dbc1dSDouglas Gregor   llvm::error_code EC;
4652c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
466ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
467e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
4682c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirNameNative;
469ddaa69cbSDouglas Gregor   llvm::sys::path::native(SubframeworksDirName.str(),
470ddaa69cbSDouglas Gregor                           SubframeworksDirNameNative);
471ddaa69cbSDouglas Gregor   for (llvm::sys::fs::directory_iterator
472ddaa69cbSDouglas Gregor          Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
473e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
474e89dbc1dSDouglas Gregor     if (!StringRef(Dir->path()).endswith(".framework"))
475e89dbc1dSDouglas Gregor       continue;
476f2161a70SDouglas Gregor 
477e89dbc1dSDouglas Gregor     if (const DirectoryEntry *SubframeworkDir
478e89dbc1dSDouglas Gregor           = FileMgr.getDirectory(Dir->path())) {
47907c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
48007c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
48107c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
48207c22b78SDouglas Gregor       // out to a top-level framework.
48307c22b78SDouglas Gregor #ifdef LLVM_ON_UNIX
48407c22b78SDouglas Gregor       char RealSubframeworkDirName[PATH_MAX];
48507c22b78SDouglas Gregor       if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) {
48607c22b78SDouglas Gregor         StringRef SubframeworkDirName = RealSubframeworkDirName;
48707c22b78SDouglas Gregor 
48807c22b78SDouglas Gregor         bool FoundParent = false;
48907c22b78SDouglas Gregor         do {
49007c22b78SDouglas Gregor           // Get the parent directory name.
49107c22b78SDouglas Gregor           SubframeworkDirName
49207c22b78SDouglas Gregor             = llvm::sys::path::parent_path(SubframeworkDirName);
49307c22b78SDouglas Gregor           if (SubframeworkDirName.empty())
49407c22b78SDouglas Gregor             break;
49507c22b78SDouglas Gregor 
49607c22b78SDouglas Gregor           if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
49707c22b78SDouglas Gregor             FoundParent = true;
49807c22b78SDouglas Gregor             break;
49907c22b78SDouglas Gregor           }
50007c22b78SDouglas Gregor         } while (true);
50107c22b78SDouglas Gregor 
50207c22b78SDouglas Gregor         if (!FoundParent)
50307c22b78SDouglas Gregor           continue;
50407c22b78SDouglas Gregor       }
50507c22b78SDouglas Gregor #endif
50607c22b78SDouglas Gregor 
507e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
508056396aeSDouglas Gregor       SmallString<32> NameBuf;
509056396aeSDouglas Gregor       inferFrameworkModule(sanitizeFilenameAsIdentifier(
510056396aeSDouglas Gregor                              llvm::sys::path::stem(Dir->path()), NameBuf),
511056396aeSDouglas Gregor                            SubframeworkDir, IsSystem, Result);
512e89dbc1dSDouglas Gregor     }
513e89dbc1dSDouglas Gregor   }
514e89dbc1dSDouglas Gregor 
51556c64013SDouglas Gregor   return Result;
51656c64013SDouglas Gregor }
51756c64013SDouglas Gregor 
518a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
51959527666SDouglas Gregor   Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
52073141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
5217033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
522a89c5ac4SDouglas Gregor }
523a89c5ac4SDouglas Gregor 
524524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
525524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
526524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
527524e33e1SDouglas Gregor }
528524e33e1SDouglas Gregor 
52959527666SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
53059527666SDouglas Gregor                           bool Excluded) {
53159527666SDouglas Gregor   if (Excluded)
53259527666SDouglas Gregor     Mod->ExcludedHeaders.push_back(Header);
53359527666SDouglas Gregor   else
534a89c5ac4SDouglas Gregor     Mod->Headers.push_back(Header);
53559527666SDouglas Gregor   Headers[Header] = KnownHeader(Mod, Excluded);
536a89c5ac4SDouglas Gregor }
537a89c5ac4SDouglas Gregor 
538514b636aSDouglas Gregor const FileEntry *
539de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
540514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
541514b636aSDouglas Gregor     return 0;
542514b636aSDouglas Gregor 
543514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
544514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
545514b636aSDouglas Gregor }
546514b636aSDouglas Gregor 
547718292f2SDouglas Gregor void ModuleMap::dump() {
548718292f2SDouglas Gregor   llvm::errs() << "Modules:";
549718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
550718292f2SDouglas Gregor                                         MEnd = Modules.end();
551718292f2SDouglas Gregor        M != MEnd; ++M)
552d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
553718292f2SDouglas Gregor 
554718292f2SDouglas Gregor   llvm::errs() << "Headers:";
55559527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
556718292f2SDouglas Gregor        H != HEnd; ++H) {
557718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
55859527666SDouglas Gregor                  << H->second.getModule()->getFullModuleName() << "\n";
559718292f2SDouglas Gregor   }
560718292f2SDouglas Gregor }
561718292f2SDouglas Gregor 
5622b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
5632b82c2a5SDouglas Gregor   bool HadError = false;
5642b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
5652b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
5662b82c2a5SDouglas Gregor                                               Complain);
567f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
5682b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
5692b82c2a5SDouglas Gregor     else
5702b82c2a5SDouglas Gregor       HadError = true;
5712b82c2a5SDouglas Gregor   }
5722b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
5732b82c2a5SDouglas Gregor   return HadError;
5742b82c2a5SDouglas Gregor }
5752b82c2a5SDouglas Gregor 
5760093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
5770093b3c7SDouglas Gregor   if (Loc.isInvalid())
5780093b3c7SDouglas Gregor     return 0;
5790093b3c7SDouglas Gregor 
5800093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
5810093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
5820093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
5830093b3c7SDouglas Gregor     return 0;
5840093b3c7SDouglas Gregor 
5850093b3c7SDouglas Gregor 
5860093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
5870093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
588224d8a74SDouglas Gregor 
589224d8a74SDouglas Gregor   while (const FileEntry *ExpansionFile
590224d8a74SDouglas Gregor            = SrcMgr.getFileEntryForID(ExpansionFileID)) {
591224d8a74SDouglas Gregor     // Find the module that owns this header (if any).
592224d8a74SDouglas Gregor     if (Module *Mod = findModuleForHeader(ExpansionFile))
593224d8a74SDouglas Gregor       return Mod;
594224d8a74SDouglas Gregor 
595224d8a74SDouglas Gregor     // No module owns this header, so look up the inclusion chain to see if
596224d8a74SDouglas Gregor     // any included header has an associated module.
597224d8a74SDouglas Gregor     SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
598224d8a74SDouglas Gregor     if (IncludeLoc.isInvalid())
5990093b3c7SDouglas Gregor       return 0;
6000093b3c7SDouglas Gregor 
601224d8a74SDouglas Gregor     ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
602224d8a74SDouglas Gregor   }
603224d8a74SDouglas Gregor 
604224d8a74SDouglas Gregor   return 0;
6050093b3c7SDouglas Gregor }
6060093b3c7SDouglas Gregor 
607718292f2SDouglas Gregor //----------------------------------------------------------------------------//
608718292f2SDouglas Gregor // Module map file parser
609718292f2SDouglas Gregor //----------------------------------------------------------------------------//
610718292f2SDouglas Gregor 
611718292f2SDouglas Gregor namespace clang {
612718292f2SDouglas Gregor   /// \brief A token in a module map file.
613718292f2SDouglas Gregor   struct MMToken {
614718292f2SDouglas Gregor     enum TokenKind {
6151fb5c3a6SDouglas Gregor       Comma,
616718292f2SDouglas Gregor       EndOfFile,
617718292f2SDouglas Gregor       HeaderKeyword,
618718292f2SDouglas Gregor       Identifier,
61959527666SDouglas Gregor       ExcludeKeyword,
620718292f2SDouglas Gregor       ExplicitKeyword,
6212b82c2a5SDouglas Gregor       ExportKeyword,
622755b2055SDouglas Gregor       FrameworkKeyword,
623718292f2SDouglas Gregor       ModuleKeyword,
6242b82c2a5SDouglas Gregor       Period,
625718292f2SDouglas Gregor       UmbrellaKeyword,
6261fb5c3a6SDouglas Gregor       RequiresKeyword,
6272b82c2a5SDouglas Gregor       Star,
628718292f2SDouglas Gregor       StringLiteral,
629718292f2SDouglas Gregor       LBrace,
630a686e1b0SDouglas Gregor       RBrace,
631a686e1b0SDouglas Gregor       LSquare,
632a686e1b0SDouglas Gregor       RSquare
633718292f2SDouglas Gregor     } Kind;
634718292f2SDouglas Gregor 
635718292f2SDouglas Gregor     unsigned Location;
636718292f2SDouglas Gregor     unsigned StringLength;
637718292f2SDouglas Gregor     const char *StringData;
638718292f2SDouglas Gregor 
639718292f2SDouglas Gregor     void clear() {
640718292f2SDouglas Gregor       Kind = EndOfFile;
641718292f2SDouglas Gregor       Location = 0;
642718292f2SDouglas Gregor       StringLength = 0;
643718292f2SDouglas Gregor       StringData = 0;
644718292f2SDouglas Gregor     }
645718292f2SDouglas Gregor 
646718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
647718292f2SDouglas Gregor 
648718292f2SDouglas Gregor     SourceLocation getLocation() const {
649718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
650718292f2SDouglas Gregor     }
651718292f2SDouglas Gregor 
652718292f2SDouglas Gregor     StringRef getString() const {
653718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
654718292f2SDouglas Gregor     }
655718292f2SDouglas Gregor   };
656718292f2SDouglas Gregor 
6579194a91dSDouglas Gregor   /// \brief The set of attributes that can be attached to a module.
6589194a91dSDouglas Gregor   struct Attributes {
6599194a91dSDouglas Gregor     Attributes() : IsSystem() { }
6609194a91dSDouglas Gregor 
6619194a91dSDouglas Gregor     /// \brief Whether this is a system module.
6629194a91dSDouglas Gregor     unsigned IsSystem : 1;
6639194a91dSDouglas Gregor   };
6649194a91dSDouglas Gregor 
6659194a91dSDouglas Gregor 
666718292f2SDouglas Gregor   class ModuleMapParser {
667718292f2SDouglas Gregor     Lexer &L;
668718292f2SDouglas Gregor     SourceManager &SourceMgr;
669bc10b9fbSDouglas Gregor 
670bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
671bc10b9fbSDouglas Gregor     /// parsing.
672bc10b9fbSDouglas Gregor     const TargetInfo *Target;
673bc10b9fbSDouglas Gregor 
674718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
675718292f2SDouglas Gregor     ModuleMap &Map;
676718292f2SDouglas Gregor 
6775257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
6785257fc63SDouglas Gregor     const DirectoryEntry *Directory;
6795257fc63SDouglas Gregor 
6803ec6663bSDouglas Gregor     /// \brief The directory containing Clang-supplied headers.
6813ec6663bSDouglas Gregor     const DirectoryEntry *BuiltinIncludeDir;
6823ec6663bSDouglas Gregor 
683718292f2SDouglas Gregor     /// \brief Whether an error occurred.
684718292f2SDouglas Gregor     bool HadError;
685718292f2SDouglas Gregor 
686718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
687718292f2SDouglas Gregor     /// during parsing.
688718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
689718292f2SDouglas Gregor 
690718292f2SDouglas Gregor     /// \brief The current token.
691718292f2SDouglas Gregor     MMToken Tok;
692718292f2SDouglas Gregor 
693718292f2SDouglas Gregor     /// \brief The active module.
694de3ef502SDouglas Gregor     Module *ActiveModule;
695718292f2SDouglas Gregor 
696718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
697718292f2SDouglas Gregor     SourceLocation consumeToken();
698718292f2SDouglas Gregor 
699718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
700718292f2SDouglas Gregor     /// (or the end of the file).
701718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
702718292f2SDouglas Gregor 
703e7ab3669SDouglas Gregor     typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
704e7ab3669SDouglas Gregor       ModuleId;
705e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
706718292f2SDouglas Gregor     void parseModuleDecl();
7071fb5c3a6SDouglas Gregor     void parseRequiresDecl();
70859527666SDouglas Gregor     void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
709524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
7102b82c2a5SDouglas Gregor     void parseExportDecl();
7119194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
7129194a91dSDouglas Gregor     bool parseOptionalAttributes(Attributes &Attrs);
713718292f2SDouglas Gregor 
7147033127bSDouglas Gregor     const DirectoryEntry *getOverriddenHeaderSearchDir();
7157033127bSDouglas Gregor 
716718292f2SDouglas Gregor   public:
717718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
718bc10b9fbSDouglas Gregor                              const TargetInfo *Target,
719718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
7205257fc63SDouglas Gregor                              ModuleMap &Map,
7213ec6663bSDouglas Gregor                              const DirectoryEntry *Directory,
7223ec6663bSDouglas Gregor                              const DirectoryEntry *BuiltinIncludeDir)
723bc10b9fbSDouglas Gregor       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
7243ec6663bSDouglas Gregor         Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
7253ec6663bSDouglas Gregor         HadError(false), ActiveModule(0)
726718292f2SDouglas Gregor     {
727718292f2SDouglas Gregor       Tok.clear();
728718292f2SDouglas Gregor       consumeToken();
729718292f2SDouglas Gregor     }
730718292f2SDouglas Gregor 
731718292f2SDouglas Gregor     bool parseModuleMapFile();
732718292f2SDouglas Gregor   };
733718292f2SDouglas Gregor }
734718292f2SDouglas Gregor 
735718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
736718292f2SDouglas Gregor retry:
737718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
738718292f2SDouglas Gregor   Tok.clear();
739718292f2SDouglas Gregor 
740718292f2SDouglas Gregor   Token LToken;
741718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
742718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
743718292f2SDouglas Gregor   switch (LToken.getKind()) {
744718292f2SDouglas Gregor   case tok::raw_identifier:
745718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
746718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
747718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
748718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
74959527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
750718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
7512b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
752755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
753718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
7541fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
755718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
756718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
757718292f2SDouglas Gregor     break;
758718292f2SDouglas Gregor 
7591fb5c3a6SDouglas Gregor   case tok::comma:
7601fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
7611fb5c3a6SDouglas Gregor     break;
7621fb5c3a6SDouglas Gregor 
763718292f2SDouglas Gregor   case tok::eof:
764718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
765718292f2SDouglas Gregor     break;
766718292f2SDouglas Gregor 
767718292f2SDouglas Gregor   case tok::l_brace:
768718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
769718292f2SDouglas Gregor     break;
770718292f2SDouglas Gregor 
771a686e1b0SDouglas Gregor   case tok::l_square:
772a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
773a686e1b0SDouglas Gregor     break;
774a686e1b0SDouglas Gregor 
7752b82c2a5SDouglas Gregor   case tok::period:
7762b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
7772b82c2a5SDouglas Gregor     break;
7782b82c2a5SDouglas Gregor 
779718292f2SDouglas Gregor   case tok::r_brace:
780718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
781718292f2SDouglas Gregor     break;
782718292f2SDouglas Gregor 
783a686e1b0SDouglas Gregor   case tok::r_square:
784a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
785a686e1b0SDouglas Gregor     break;
786a686e1b0SDouglas Gregor 
7872b82c2a5SDouglas Gregor   case tok::star:
7882b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
7892b82c2a5SDouglas Gregor     break;
7902b82c2a5SDouglas Gregor 
791718292f2SDouglas Gregor   case tok::string_literal: {
792d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
793d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
794d67aea28SRichard Smith       HadError = true;
795d67aea28SRichard Smith       goto retry;
796d67aea28SRichard Smith     }
797d67aea28SRichard Smith 
798718292f2SDouglas Gregor     // Parse the string literal.
799718292f2SDouglas Gregor     LangOptions LangOpts;
800718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
801718292f2SDouglas Gregor     if (StringLiteral.hadError)
802718292f2SDouglas Gregor       goto retry;
803718292f2SDouglas Gregor 
804718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
805718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
806718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
807718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
808718292f2SDouglas Gregor     Saved[Length] = 0;
809718292f2SDouglas Gregor 
810718292f2SDouglas Gregor     // Form the token.
811718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
812718292f2SDouglas Gregor     Tok.StringData = Saved;
813718292f2SDouglas Gregor     Tok.StringLength = Length;
814718292f2SDouglas Gregor     break;
815718292f2SDouglas Gregor   }
816718292f2SDouglas Gregor 
817718292f2SDouglas Gregor   case tok::comment:
818718292f2SDouglas Gregor     goto retry;
819718292f2SDouglas Gregor 
820718292f2SDouglas Gregor   default:
821718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
822718292f2SDouglas Gregor     HadError = true;
823718292f2SDouglas Gregor     goto retry;
824718292f2SDouglas Gregor   }
825718292f2SDouglas Gregor 
826718292f2SDouglas Gregor   return Result;
827718292f2SDouglas Gregor }
828718292f2SDouglas Gregor 
829718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
830718292f2SDouglas Gregor   unsigned braceDepth = 0;
831a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
832718292f2SDouglas Gregor   do {
833718292f2SDouglas Gregor     switch (Tok.Kind) {
834718292f2SDouglas Gregor     case MMToken::EndOfFile:
835718292f2SDouglas Gregor       return;
836718292f2SDouglas Gregor 
837718292f2SDouglas Gregor     case MMToken::LBrace:
838a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
839718292f2SDouglas Gregor         return;
840718292f2SDouglas Gregor 
841718292f2SDouglas Gregor       ++braceDepth;
842718292f2SDouglas Gregor       break;
843718292f2SDouglas Gregor 
844a686e1b0SDouglas Gregor     case MMToken::LSquare:
845a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
846a686e1b0SDouglas Gregor         return;
847a686e1b0SDouglas Gregor 
848a686e1b0SDouglas Gregor       ++squareDepth;
849a686e1b0SDouglas Gregor       break;
850a686e1b0SDouglas Gregor 
851718292f2SDouglas Gregor     case MMToken::RBrace:
852718292f2SDouglas Gregor       if (braceDepth > 0)
853718292f2SDouglas Gregor         --braceDepth;
854718292f2SDouglas Gregor       else if (Tok.is(K))
855718292f2SDouglas Gregor         return;
856718292f2SDouglas Gregor       break;
857718292f2SDouglas Gregor 
858a686e1b0SDouglas Gregor     case MMToken::RSquare:
859a686e1b0SDouglas Gregor       if (squareDepth > 0)
860a686e1b0SDouglas Gregor         --squareDepth;
861a686e1b0SDouglas Gregor       else if (Tok.is(K))
862a686e1b0SDouglas Gregor         return;
863a686e1b0SDouglas Gregor       break;
864a686e1b0SDouglas Gregor 
865718292f2SDouglas Gregor     default:
866a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
867718292f2SDouglas Gregor         return;
868718292f2SDouglas Gregor       break;
869718292f2SDouglas Gregor     }
870718292f2SDouglas Gregor 
871718292f2SDouglas Gregor    consumeToken();
872718292f2SDouglas Gregor   } while (true);
873718292f2SDouglas Gregor }
874718292f2SDouglas Gregor 
875e7ab3669SDouglas Gregor /// \brief Parse a module-id.
876e7ab3669SDouglas Gregor ///
877e7ab3669SDouglas Gregor ///   module-id:
878e7ab3669SDouglas Gregor ///     identifier
879e7ab3669SDouglas Gregor ///     identifier '.' module-id
880e7ab3669SDouglas Gregor ///
881e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
882e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
883e7ab3669SDouglas Gregor   Id.clear();
884e7ab3669SDouglas Gregor   do {
885e7ab3669SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
886e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
887e7ab3669SDouglas Gregor       consumeToken();
888e7ab3669SDouglas Gregor     } else {
889e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
890e7ab3669SDouglas Gregor       return true;
891e7ab3669SDouglas Gregor     }
892e7ab3669SDouglas Gregor 
893e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
894e7ab3669SDouglas Gregor       break;
895e7ab3669SDouglas Gregor 
896e7ab3669SDouglas Gregor     consumeToken();
897e7ab3669SDouglas Gregor   } while (true);
898e7ab3669SDouglas Gregor 
899e7ab3669SDouglas Gregor   return false;
900e7ab3669SDouglas Gregor }
901e7ab3669SDouglas Gregor 
902a686e1b0SDouglas Gregor namespace {
903a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
904a686e1b0SDouglas Gregor   enum AttributeKind {
905a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
906a686e1b0SDouglas Gregor     AT_unknown,
907a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
908a686e1b0SDouglas Gregor     AT_system
909a686e1b0SDouglas Gregor   };
910a686e1b0SDouglas Gregor }
911a686e1b0SDouglas Gregor 
912718292f2SDouglas Gregor /// \brief Parse a module declaration.
913718292f2SDouglas Gregor ///
914718292f2SDouglas Gregor ///   module-declaration:
915a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
916a686e1b0SDouglas Gregor ///       { module-member* }
917a686e1b0SDouglas Gregor ///
918718292f2SDouglas Gregor ///   module-member:
9191fb5c3a6SDouglas Gregor ///     requires-declaration
920718292f2SDouglas Gregor ///     header-declaration
921e7ab3669SDouglas Gregor ///     submodule-declaration
9222b82c2a5SDouglas Gregor ///     export-declaration
92373441091SDouglas Gregor ///
92473441091SDouglas Gregor ///   submodule-declaration:
92573441091SDouglas Gregor ///     module-declaration
92673441091SDouglas Gregor ///     inferred-submodule-declaration
927718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
928755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
929755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
930f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
931e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
932718292f2SDouglas Gregor   bool Explicit = false;
933f2161a70SDouglas Gregor   bool Framework = false;
934755b2055SDouglas Gregor 
935f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
936f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
937e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
938f2161a70SDouglas Gregor     Explicit = true;
939f2161a70SDouglas Gregor   }
940f2161a70SDouglas Gregor 
941f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
942755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
943755b2055SDouglas Gregor     consumeToken();
944755b2055SDouglas Gregor     Framework = true;
945755b2055SDouglas Gregor   }
946718292f2SDouglas Gregor 
947718292f2SDouglas Gregor   // Parse 'module' keyword.
948718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
949d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
950718292f2SDouglas Gregor     consumeToken();
951718292f2SDouglas Gregor     HadError = true;
952718292f2SDouglas Gregor     return;
953718292f2SDouglas Gregor   }
954718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
955718292f2SDouglas Gregor 
95673441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
95773441091SDouglas Gregor   // Parse it.
95873441091SDouglas Gregor   if (Tok.is(MMToken::Star))
9599194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
96073441091SDouglas Gregor 
961718292f2SDouglas Gregor   // Parse the module name.
962e7ab3669SDouglas Gregor   ModuleId Id;
963e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
964718292f2SDouglas Gregor     HadError = true;
965718292f2SDouglas Gregor     return;
966718292f2SDouglas Gregor   }
967e7ab3669SDouglas Gregor 
968e7ab3669SDouglas Gregor   if (ActiveModule) {
969e7ab3669SDouglas Gregor     if (Id.size() > 1) {
970e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
971e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
972e7ab3669SDouglas Gregor 
973e7ab3669SDouglas Gregor       HadError = true;
974e7ab3669SDouglas Gregor       return;
975e7ab3669SDouglas Gregor     }
976e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
977e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
978e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
979e7ab3669SDouglas Gregor     Explicit = false;
980e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
981e7ab3669SDouglas Gregor     HadError = true;
982e7ab3669SDouglas Gregor   }
983e7ab3669SDouglas Gregor 
984e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
985e7ab3669SDouglas Gregor   if (Id.size() > 1) {
986e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
987e7ab3669SDouglas Gregor     // is a submodule.
988e7ab3669SDouglas Gregor     ActiveModule = 0;
989e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
990e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
991e7ab3669SDouglas Gregor         ActiveModule = Next;
992e7ab3669SDouglas Gregor         continue;
993e7ab3669SDouglas Gregor       }
994e7ab3669SDouglas Gregor 
995e7ab3669SDouglas Gregor       if (ActiveModule) {
996e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
997e7ab3669SDouglas Gregor           << Id[I].first << ActiveModule->getTopLevelModule();
998e7ab3669SDouglas Gregor       } else {
999e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1000e7ab3669SDouglas Gregor       }
1001e7ab3669SDouglas Gregor       HadError = true;
1002e7ab3669SDouglas Gregor       return;
1003e7ab3669SDouglas Gregor     }
1004e7ab3669SDouglas Gregor   }
1005e7ab3669SDouglas Gregor 
1006e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1007e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1008718292f2SDouglas Gregor 
1009a686e1b0SDouglas Gregor   // Parse the optional attribute list.
10109194a91dSDouglas Gregor   Attributes Attrs;
10119194a91dSDouglas Gregor   parseOptionalAttributes(Attrs);
1012a686e1b0SDouglas Gregor 
1013718292f2SDouglas Gregor   // Parse the opening brace.
1014718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1015718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1016718292f2SDouglas Gregor       << ModuleName;
1017718292f2SDouglas Gregor     HadError = true;
1018718292f2SDouglas Gregor     return;
1019718292f2SDouglas Gregor   }
1020718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1021718292f2SDouglas Gregor 
1022718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
1023eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1024fcc54a3bSDouglas Gregor     if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1025fcc54a3bSDouglas Gregor       // Skip the module definition.
1026fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1027fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1028fcc54a3bSDouglas Gregor         consumeToken();
1029fcc54a3bSDouglas Gregor       else {
1030fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1031fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1032fcc54a3bSDouglas Gregor         HadError = true;
1033fcc54a3bSDouglas Gregor       }
1034fcc54a3bSDouglas Gregor       return;
1035fcc54a3bSDouglas Gregor     }
1036fcc54a3bSDouglas Gregor 
1037718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1038718292f2SDouglas Gregor       << ModuleName;
1039eb90e830SDouglas Gregor     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1040718292f2SDouglas Gregor 
1041718292f2SDouglas Gregor     // Skip the module definition.
1042718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
1043718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
1044718292f2SDouglas Gregor       consumeToken();
1045718292f2SDouglas Gregor 
1046718292f2SDouglas Gregor     HadError = true;
1047718292f2SDouglas Gregor     return;
1048718292f2SDouglas Gregor   }
1049718292f2SDouglas Gregor 
1050718292f2SDouglas Gregor   // Start defining this module.
1051eb90e830SDouglas Gregor   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1052eb90e830SDouglas Gregor                                         Explicit).first;
1053eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
10549194a91dSDouglas Gregor   if (Attrs.IsSystem)
1055a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
1056718292f2SDouglas Gregor 
1057718292f2SDouglas Gregor   bool Done = false;
1058718292f2SDouglas Gregor   do {
1059718292f2SDouglas Gregor     switch (Tok.Kind) {
1060718292f2SDouglas Gregor     case MMToken::EndOfFile:
1061718292f2SDouglas Gregor     case MMToken::RBrace:
1062718292f2SDouglas Gregor       Done = true;
1063718292f2SDouglas Gregor       break;
1064718292f2SDouglas Gregor 
1065718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
1066f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1067718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1068718292f2SDouglas Gregor       parseModuleDecl();
1069718292f2SDouglas Gregor       break;
1070718292f2SDouglas Gregor 
10712b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
10722b82c2a5SDouglas Gregor       parseExportDecl();
10732b82c2a5SDouglas Gregor       break;
10742b82c2a5SDouglas Gregor 
10751fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
10761fb5c3a6SDouglas Gregor       parseRequiresDecl();
10771fb5c3a6SDouglas Gregor       break;
10781fb5c3a6SDouglas Gregor 
1079524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1080524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1081524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
108259527666SDouglas Gregor         parseHeaderDecl(UmbrellaLoc, SourceLocation());
1083524e33e1SDouglas Gregor       else
1084524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1085718292f2SDouglas Gregor       break;
1086524e33e1SDouglas Gregor     }
1087718292f2SDouglas Gregor 
108859527666SDouglas Gregor     case MMToken::ExcludeKeyword: {
108959527666SDouglas Gregor       SourceLocation ExcludeLoc = consumeToken();
109059527666SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword)) {
109159527666SDouglas Gregor         parseHeaderDecl(SourceLocation(), ExcludeLoc);
109259527666SDouglas Gregor       } else {
109359527666SDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
109459527666SDouglas Gregor           << "exclude";
109559527666SDouglas Gregor       }
109659527666SDouglas Gregor       break;
109759527666SDouglas Gregor     }
109859527666SDouglas Gregor 
1099322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
110059527666SDouglas Gregor       parseHeaderDecl(SourceLocation(), SourceLocation());
1101718292f2SDouglas Gregor       break;
1102718292f2SDouglas Gregor 
1103718292f2SDouglas Gregor     default:
1104718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1105718292f2SDouglas Gregor       consumeToken();
1106718292f2SDouglas Gregor       break;
1107718292f2SDouglas Gregor     }
1108718292f2SDouglas Gregor   } while (!Done);
1109718292f2SDouglas Gregor 
1110718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1111718292f2SDouglas Gregor     consumeToken();
1112718292f2SDouglas Gregor   else {
1113718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1114718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1115718292f2SDouglas Gregor     HadError = true;
1116718292f2SDouglas Gregor   }
1117718292f2SDouglas Gregor 
1118e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
1119e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
1120718292f2SDouglas Gregor }
1121718292f2SDouglas Gregor 
11221fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
11231fb5c3a6SDouglas Gregor ///
11241fb5c3a6SDouglas Gregor ///   requires-declaration:
11251fb5c3a6SDouglas Gregor ///     'requires' feature-list
11261fb5c3a6SDouglas Gregor ///
11271fb5c3a6SDouglas Gregor ///   feature-list:
11281fb5c3a6SDouglas Gregor ///     identifier ',' feature-list
11291fb5c3a6SDouglas Gregor ///     identifier
11301fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
11311fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
11321fb5c3a6SDouglas Gregor 
11331fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
11341fb5c3a6SDouglas Gregor   consumeToken();
11351fb5c3a6SDouglas Gregor 
11361fb5c3a6SDouglas Gregor   // Parse the feature-list.
11371fb5c3a6SDouglas Gregor   do {
11381fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
11391fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
11401fb5c3a6SDouglas Gregor       HadError = true;
11411fb5c3a6SDouglas Gregor       return;
11421fb5c3a6SDouglas Gregor     }
11431fb5c3a6SDouglas Gregor 
11441fb5c3a6SDouglas Gregor     // Consume the feature name.
11451fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
11461fb5c3a6SDouglas Gregor     consumeToken();
11471fb5c3a6SDouglas Gregor 
11481fb5c3a6SDouglas Gregor     // Add this feature.
114989929282SDouglas Gregor     ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
11501fb5c3a6SDouglas Gregor 
11511fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
11521fb5c3a6SDouglas Gregor       break;
11531fb5c3a6SDouglas Gregor 
11541fb5c3a6SDouglas Gregor     // Consume the comma.
11551fb5c3a6SDouglas Gregor     consumeToken();
11561fb5c3a6SDouglas Gregor   } while (true);
11571fb5c3a6SDouglas Gregor }
11581fb5c3a6SDouglas Gregor 
1159f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the
1160f2161a70SDouglas Gregor /// subframework in which the given module lives.
1161bf8da9d7SBenjamin Kramer static void appendSubframeworkPaths(Module *Mod,
1162bf8da9d7SBenjamin Kramer                                     llvm::SmallVectorImpl<char> &Path) {
1163f2161a70SDouglas Gregor   // Collect the framework names from the given module to the top-level module.
1164f2161a70SDouglas Gregor   llvm::SmallVector<StringRef, 2> Paths;
1165f2161a70SDouglas Gregor   for (; Mod; Mod = Mod->Parent) {
1166f2161a70SDouglas Gregor     if (Mod->IsFramework)
1167f2161a70SDouglas Gregor       Paths.push_back(Mod->Name);
1168f2161a70SDouglas Gregor   }
1169f2161a70SDouglas Gregor 
1170f2161a70SDouglas Gregor   if (Paths.empty())
1171f2161a70SDouglas Gregor     return;
1172f2161a70SDouglas Gregor 
1173f2161a70SDouglas Gregor   // Add Frameworks/Name.framework for each subframework.
1174f2161a70SDouglas Gregor   for (unsigned I = Paths.size() - 1; I != 0; --I) {
1175f2161a70SDouglas Gregor     llvm::sys::path::append(Path, "Frameworks");
1176f2161a70SDouglas Gregor     llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1177f2161a70SDouglas Gregor   }
1178f2161a70SDouglas Gregor }
1179f2161a70SDouglas Gregor 
11803ec6663bSDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
11813ec6663bSDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
11823ec6663bSDouglas Gregor /// headers.
11833ec6663bSDouglas Gregor static bool isBuiltinHeader(StringRef FileName) {
11843ec6663bSDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
11853ec6663bSDouglas Gregor       .Case("float.h", true)
11863ec6663bSDouglas Gregor       .Case("iso646.h", true)
11873ec6663bSDouglas Gregor       .Case("limits.h", true)
11883ec6663bSDouglas Gregor       .Case("stdalign.h", true)
11893ec6663bSDouglas Gregor       .Case("stdarg.h", true)
11903ec6663bSDouglas Gregor       .Case("stdbool.h", true)
11913ec6663bSDouglas Gregor       .Case("stddef.h", true)
11923ec6663bSDouglas Gregor       .Case("stdint.h", true)
11933ec6663bSDouglas Gregor       .Case("tgmath.h", true)
11943ec6663bSDouglas Gregor       .Case("unwind.h", true)
11953ec6663bSDouglas Gregor       .Default(false);
11963ec6663bSDouglas Gregor }
11973ec6663bSDouglas Gregor 
1198718292f2SDouglas Gregor /// \brief Parse a header declaration.
1199718292f2SDouglas Gregor ///
1200718292f2SDouglas Gregor ///   header-declaration:
1201322f633cSDouglas Gregor ///     'umbrella'[opt] 'header' string-literal
120259527666SDouglas Gregor ///     'exclude'[opt] 'header' string-literal
120359527666SDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
120459527666SDouglas Gregor                                       SourceLocation ExcludeLoc) {
1205718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
12061871ed3dSBenjamin Kramer   consumeToken();
1207718292f2SDouglas Gregor 
1208322f633cSDouglas Gregor   bool Umbrella = UmbrellaLoc.isValid();
120959527666SDouglas Gregor   bool Exclude = ExcludeLoc.isValid();
121059527666SDouglas Gregor   assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
1211718292f2SDouglas Gregor   // Parse the header name.
1212718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1213718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1214718292f2SDouglas Gregor       << "header";
1215718292f2SDouglas Gregor     HadError = true;
1216718292f2SDouglas Gregor     return;
1217718292f2SDouglas Gregor   }
1218e7ab3669SDouglas Gregor   std::string FileName = Tok.getString();
1219718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
1220718292f2SDouglas Gregor 
1221524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1222524e33e1SDouglas Gregor   if (Umbrella && ActiveModule->Umbrella) {
1223524e33e1SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1224524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1225322f633cSDouglas Gregor     HadError = true;
1226322f633cSDouglas Gregor     return;
1227322f633cSDouglas Gregor   }
1228322f633cSDouglas Gregor 
12295257fc63SDouglas Gregor   // Look for this file.
1230e7ab3669SDouglas Gregor   const FileEntry *File = 0;
12313ec6663bSDouglas Gregor   const FileEntry *BuiltinFile = 0;
12322c1dd271SDylan Noblesmith   SmallString<128> PathName;
1233e7ab3669SDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
1234e7ab3669SDouglas Gregor     PathName = FileName;
1235e7ab3669SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
12367033127bSDouglas Gregor   } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
12377033127bSDouglas Gregor     PathName = Dir->getName();
12387033127bSDouglas Gregor     llvm::sys::path::append(PathName, FileName);
12397033127bSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
1240e7ab3669SDouglas Gregor   } else {
1241e7ab3669SDouglas Gregor     // Search for the header file within the search directory.
12427033127bSDouglas Gregor     PathName = Directory->getName();
1243e7ab3669SDouglas Gregor     unsigned PathLength = PathName.size();
1244755b2055SDouglas Gregor 
1245f2161a70SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
1246f2161a70SDouglas Gregor       appendSubframeworkPaths(ActiveModule, PathName);
1247755b2055SDouglas Gregor 
1248e7ab3669SDouglas Gregor       // Check whether this file is in the public headers.
1249e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
12505257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1251e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
1252e7ab3669SDouglas Gregor 
1253e7ab3669SDouglas Gregor       if (!File) {
1254e7ab3669SDouglas Gregor         // Check whether this file is in the private headers.
1255e7ab3669SDouglas Gregor         PathName.resize(PathLength);
1256e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
1257e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
1258e7ab3669SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
1259e7ab3669SDouglas Gregor       }
1260e7ab3669SDouglas Gregor     } else {
1261e7ab3669SDouglas Gregor       // Lookup for normal headers.
1262e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1263e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
12643ec6663bSDouglas Gregor 
12653ec6663bSDouglas Gregor       // If this is a system module with a top-level header, this header
12663ec6663bSDouglas Gregor       // may have a counterpart (or replacement) in the set of headers
12673ec6663bSDouglas Gregor       // supplied by Clang. Find that builtin header.
12683ec6663bSDouglas Gregor       if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
12693ec6663bSDouglas Gregor           BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
12702c1dd271SDylan Noblesmith         SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
12713ec6663bSDouglas Gregor         llvm::sys::path::append(BuiltinPathName, FileName);
12723ec6663bSDouglas Gregor         BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
12733ec6663bSDouglas Gregor 
12743ec6663bSDouglas Gregor         // If Clang supplies this header but the underlying system does not,
12753ec6663bSDouglas Gregor         // just silently swap in our builtin version. Otherwise, we'll end
12763ec6663bSDouglas Gregor         // up adding both (later).
12773ec6663bSDouglas Gregor         if (!File && BuiltinFile) {
12783ec6663bSDouglas Gregor           File = BuiltinFile;
12793ec6663bSDouglas Gregor           BuiltinFile = 0;
12803ec6663bSDouglas Gregor         }
12813ec6663bSDouglas Gregor       }
1282e7ab3669SDouglas Gregor     }
1283e7ab3669SDouglas Gregor   }
12845257fc63SDouglas Gregor 
12855257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
12865257fc63SDouglas Gregor   // Come up with a lazy way to do this.
1287e7ab3669SDouglas Gregor   if (File) {
128859527666SDouglas Gregor     if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
12895257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
129059527666SDouglas Gregor         << FileName << OwningModule.getModule()->getFullModuleName();
12915257fc63SDouglas Gregor       HadError = true;
1292322f633cSDouglas Gregor     } else if (Umbrella) {
1293322f633cSDouglas Gregor       const DirectoryEntry *UmbrellaDir = File->getDir();
129459527666SDouglas Gregor       if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
1295322f633cSDouglas Gregor         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
129659527666SDouglas Gregor           << UmbrellaModule->getFullModuleName();
1297322f633cSDouglas Gregor         HadError = true;
12985257fc63SDouglas Gregor       } else {
1299322f633cSDouglas Gregor         // Record this umbrella header.
1300322f633cSDouglas Gregor         Map.setUmbrellaHeader(ActiveModule, File);
1301322f633cSDouglas Gregor       }
1302322f633cSDouglas Gregor     } else {
1303322f633cSDouglas Gregor       // Record this header.
130459527666SDouglas Gregor       Map.addHeader(ActiveModule, File, Exclude);
13053ec6663bSDouglas Gregor 
13063ec6663bSDouglas Gregor       // If there is a builtin counterpart to this file, add it now.
13073ec6663bSDouglas Gregor       if (BuiltinFile)
130859527666SDouglas Gregor         Map.addHeader(ActiveModule, BuiltinFile, Exclude);
13095257fc63SDouglas Gregor     }
13105257fc63SDouglas Gregor   } else {
13115257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
1312524e33e1SDouglas Gregor       << Umbrella << FileName;
13135257fc63SDouglas Gregor     HadError = true;
13145257fc63SDouglas Gregor   }
1315718292f2SDouglas Gregor }
1316718292f2SDouglas Gregor 
1317524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
1318524e33e1SDouglas Gregor ///
1319524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
1320524e33e1SDouglas Gregor ///     umbrella string-literal
1321524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1322524e33e1SDouglas Gregor   // Parse the directory name.
1323524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1324524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1325524e33e1SDouglas Gregor       << "umbrella";
1326524e33e1SDouglas Gregor     HadError = true;
1327524e33e1SDouglas Gregor     return;
1328524e33e1SDouglas Gregor   }
1329524e33e1SDouglas Gregor 
1330524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
1331524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
1332524e33e1SDouglas Gregor 
1333524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1334524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
1335524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1336524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1337524e33e1SDouglas Gregor     HadError = true;
1338524e33e1SDouglas Gregor     return;
1339524e33e1SDouglas Gregor   }
1340524e33e1SDouglas Gregor 
1341524e33e1SDouglas Gregor   // Look for this file.
1342524e33e1SDouglas Gregor   const DirectoryEntry *Dir = 0;
1343524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
1344524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
1345524e33e1SDouglas Gregor   else {
13462c1dd271SDylan Noblesmith     SmallString<128> PathName;
1347524e33e1SDouglas Gregor     PathName = Directory->getName();
1348524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
1349524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
1350524e33e1SDouglas Gregor   }
1351524e33e1SDouglas Gregor 
1352524e33e1SDouglas Gregor   if (!Dir) {
1353524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1354524e33e1SDouglas Gregor       << DirName;
1355524e33e1SDouglas Gregor     HadError = true;
1356524e33e1SDouglas Gregor     return;
1357524e33e1SDouglas Gregor   }
1358524e33e1SDouglas Gregor 
1359524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1360524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1361524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
1362524e33e1SDouglas Gregor     HadError = true;
1363524e33e1SDouglas Gregor     return;
1364524e33e1SDouglas Gregor   }
1365524e33e1SDouglas Gregor 
1366524e33e1SDouglas Gregor   // Record this umbrella directory.
1367524e33e1SDouglas Gregor   Map.setUmbrellaDir(ActiveModule, Dir);
1368524e33e1SDouglas Gregor }
1369524e33e1SDouglas Gregor 
13702b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
13712b82c2a5SDouglas Gregor ///
13722b82c2a5SDouglas Gregor ///   export-declaration:
13732b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
13742b82c2a5SDouglas Gregor ///
13752b82c2a5SDouglas Gregor ///   wildcard-module-id:
13762b82c2a5SDouglas Gregor ///     identifier
13772b82c2a5SDouglas Gregor ///     '*'
13782b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
13792b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
13802b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
13812b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
13822b82c2a5SDouglas Gregor 
13832b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
13842b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
13852b82c2a5SDouglas Gregor   bool Wildcard = false;
13862b82c2a5SDouglas Gregor   do {
13872b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
13882b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
13892b82c2a5SDouglas Gregor                                               Tok.getLocation()));
13902b82c2a5SDouglas Gregor       consumeToken();
13912b82c2a5SDouglas Gregor 
13922b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
13932b82c2a5SDouglas Gregor         consumeToken();
13942b82c2a5SDouglas Gregor         continue;
13952b82c2a5SDouglas Gregor       }
13962b82c2a5SDouglas Gregor 
13972b82c2a5SDouglas Gregor       break;
13982b82c2a5SDouglas Gregor     }
13992b82c2a5SDouglas Gregor 
14002b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
14012b82c2a5SDouglas Gregor       Wildcard = true;
1402f5eedd05SDouglas Gregor       consumeToken();
14032b82c2a5SDouglas Gregor       break;
14042b82c2a5SDouglas Gregor     }
14052b82c2a5SDouglas Gregor 
14062b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
14072b82c2a5SDouglas Gregor     HadError = true;
14082b82c2a5SDouglas Gregor     return;
14092b82c2a5SDouglas Gregor   } while (true);
14102b82c2a5SDouglas Gregor 
14112b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
14122b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
14132b82c2a5SDouglas Gregor   };
14142b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
14152b82c2a5SDouglas Gregor }
14162b82c2a5SDouglas Gregor 
14179194a91dSDouglas Gregor /// \brief Parse an inferried module declaration (wildcard modules).
14189194a91dSDouglas Gregor ///
14199194a91dSDouglas Gregor ///   module-declaration:
14209194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
14219194a91dSDouglas Gregor ///       { inferred-module-member* }
14229194a91dSDouglas Gregor ///
14239194a91dSDouglas Gregor ///   inferred-module-member:
14249194a91dSDouglas Gregor ///     'export' '*'
14259194a91dSDouglas Gregor ///     'exclude' identifier
14269194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
142773441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
142873441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
142973441091SDouglas Gregor   bool Failed = false;
143073441091SDouglas Gregor 
143173441091SDouglas Gregor   // Inferred modules must be submodules.
14329194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
143373441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
143473441091SDouglas Gregor     Failed = true;
143573441091SDouglas Gregor   }
143673441091SDouglas Gregor 
14379194a91dSDouglas Gregor   if (ActiveModule) {
1438524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
1439524e33e1SDouglas Gregor     if (!Failed && !ActiveModule->getUmbrellaDir()) {
144073441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
144173441091SDouglas Gregor       Failed = true;
144273441091SDouglas Gregor     }
144373441091SDouglas Gregor 
144473441091SDouglas Gregor     // Check for redefinition of an inferred module.
1445dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
144673441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1447dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
1448dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
144973441091SDouglas Gregor                      diag::note_mmap_prev_definition);
145073441091SDouglas Gregor       Failed = true;
145173441091SDouglas Gregor     }
145273441091SDouglas Gregor 
14539194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
14549194a91dSDouglas Gregor     if (Framework) {
14559194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
14569194a91dSDouglas Gregor       Framework = false;
14579194a91dSDouglas Gregor     }
14589194a91dSDouglas Gregor   } else if (Explicit) {
14599194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
14609194a91dSDouglas Gregor     Explicit = false;
14619194a91dSDouglas Gregor   }
14629194a91dSDouglas Gregor 
146373441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
146473441091SDouglas Gregor   if (Failed) {
146573441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
146673441091SDouglas Gregor       consumeToken();
146773441091SDouglas Gregor       skipUntil(MMToken::RBrace);
146873441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
146973441091SDouglas Gregor         consumeToken();
147073441091SDouglas Gregor     }
147173441091SDouglas Gregor     HadError = true;
147273441091SDouglas Gregor     return;
147373441091SDouglas Gregor   }
147473441091SDouglas Gregor 
14759194a91dSDouglas Gregor   // Parse optional attributes.
14769194a91dSDouglas Gregor   Attributes Attrs;
14779194a91dSDouglas Gregor   parseOptionalAttributes(Attrs);
14789194a91dSDouglas Gregor 
14799194a91dSDouglas Gregor   if (ActiveModule) {
148073441091SDouglas Gregor     // Note that we have an inferred submodule.
1481dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
1482dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
1483dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
14849194a91dSDouglas Gregor   } else {
14859194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
14869194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
14879194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
14889194a91dSDouglas Gregor   }
148973441091SDouglas Gregor 
149073441091SDouglas Gregor   // Parse the opening brace.
149173441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
149273441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
149373441091SDouglas Gregor     HadError = true;
149473441091SDouglas Gregor     return;
149573441091SDouglas Gregor   }
149673441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
149773441091SDouglas Gregor 
149873441091SDouglas Gregor   // Parse the body of the inferred submodule.
149973441091SDouglas Gregor   bool Done = false;
150073441091SDouglas Gregor   do {
150173441091SDouglas Gregor     switch (Tok.Kind) {
150273441091SDouglas Gregor     case MMToken::EndOfFile:
150373441091SDouglas Gregor     case MMToken::RBrace:
150473441091SDouglas Gregor       Done = true;
150573441091SDouglas Gregor       break;
150673441091SDouglas Gregor 
15079194a91dSDouglas Gregor     case MMToken::ExcludeKeyword: {
15089194a91dSDouglas Gregor       if (ActiveModule) {
15099194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1510*162405daSDouglas Gregor           << (ActiveModule != 0);
15119194a91dSDouglas Gregor         consumeToken();
15129194a91dSDouglas Gregor         break;
15139194a91dSDouglas Gregor       }
15149194a91dSDouglas Gregor 
15159194a91dSDouglas Gregor       consumeToken();
15169194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
15179194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
15189194a91dSDouglas Gregor         break;
15199194a91dSDouglas Gregor       }
15209194a91dSDouglas Gregor 
15219194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
15229194a91dSDouglas Gregor         .push_back(Tok.getString());
15239194a91dSDouglas Gregor       consumeToken();
15249194a91dSDouglas Gregor       break;
15259194a91dSDouglas Gregor     }
15269194a91dSDouglas Gregor 
15279194a91dSDouglas Gregor     case MMToken::ExportKeyword:
15289194a91dSDouglas Gregor       if (!ActiveModule) {
15299194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1530*162405daSDouglas Gregor           << (ActiveModule != 0);
15319194a91dSDouglas Gregor         consumeToken();
15329194a91dSDouglas Gregor         break;
15339194a91dSDouglas Gregor       }
15349194a91dSDouglas Gregor 
153573441091SDouglas Gregor       consumeToken();
153673441091SDouglas Gregor       if (Tok.is(MMToken::Star))
1537dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
153873441091SDouglas Gregor       else
153973441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
154073441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
154173441091SDouglas Gregor       consumeToken();
154273441091SDouglas Gregor       break;
154373441091SDouglas Gregor 
154473441091SDouglas Gregor     case MMToken::ExplicitKeyword:
154573441091SDouglas Gregor     case MMToken::ModuleKeyword:
154673441091SDouglas Gregor     case MMToken::HeaderKeyword:
154773441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
154873441091SDouglas Gregor     default:
15499194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1550*162405daSDouglas Gregor           << (ActiveModule != 0);
155173441091SDouglas Gregor       consumeToken();
155273441091SDouglas Gregor       break;
155373441091SDouglas Gregor     }
155473441091SDouglas Gregor   } while (!Done);
155573441091SDouglas Gregor 
155673441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
155773441091SDouglas Gregor     consumeToken();
155873441091SDouglas Gregor   else {
155973441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
156073441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
156173441091SDouglas Gregor     HadError = true;
156273441091SDouglas Gregor   }
156373441091SDouglas Gregor }
156473441091SDouglas Gregor 
15659194a91dSDouglas Gregor /// \brief Parse optional attributes.
15669194a91dSDouglas Gregor ///
15679194a91dSDouglas Gregor ///   attributes:
15689194a91dSDouglas Gregor ///     attribute attributes
15699194a91dSDouglas Gregor ///     attribute
15709194a91dSDouglas Gregor ///
15719194a91dSDouglas Gregor ///   attribute:
15729194a91dSDouglas Gregor ///     [ identifier ]
15739194a91dSDouglas Gregor ///
15749194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
15759194a91dSDouglas Gregor ///
15769194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
15779194a91dSDouglas Gregor bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
15789194a91dSDouglas Gregor   bool HadError = false;
15799194a91dSDouglas Gregor 
15809194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
15819194a91dSDouglas Gregor     // Consume the '['.
15829194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
15839194a91dSDouglas Gregor 
15849194a91dSDouglas Gregor     // Check whether we have an attribute name here.
15859194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
15869194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
15879194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
15889194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
15899194a91dSDouglas Gregor         consumeToken();
15909194a91dSDouglas Gregor       HadError = true;
15919194a91dSDouglas Gregor     }
15929194a91dSDouglas Gregor 
15939194a91dSDouglas Gregor     // Decode the attribute name.
15949194a91dSDouglas Gregor     AttributeKind Attribute
15959194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
15969194a91dSDouglas Gregor           .Case("system", AT_system)
15979194a91dSDouglas Gregor           .Default(AT_unknown);
15989194a91dSDouglas Gregor     switch (Attribute) {
15999194a91dSDouglas Gregor     case AT_unknown:
16009194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
16019194a91dSDouglas Gregor         << Tok.getString();
16029194a91dSDouglas Gregor       break;
16039194a91dSDouglas Gregor 
16049194a91dSDouglas Gregor     case AT_system:
16059194a91dSDouglas Gregor       Attrs.IsSystem = true;
16069194a91dSDouglas Gregor       break;
16079194a91dSDouglas Gregor     }
16089194a91dSDouglas Gregor     consumeToken();
16099194a91dSDouglas Gregor 
16109194a91dSDouglas Gregor     // Consume the ']'.
16119194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
16129194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
16139194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
16149194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
16159194a91dSDouglas Gregor       HadError = true;
16169194a91dSDouglas Gregor     }
16179194a91dSDouglas Gregor 
16189194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
16199194a91dSDouglas Gregor       consumeToken();
16209194a91dSDouglas Gregor   }
16219194a91dSDouglas Gregor 
16229194a91dSDouglas Gregor   return HadError;
16239194a91dSDouglas Gregor }
16249194a91dSDouglas Gregor 
16257033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence
16267033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null.
16277033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
16287033127bSDouglas Gregor   for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
16297033127bSDouglas Gregor     // If we have an umbrella directory, use that.
16307033127bSDouglas Gregor     if (Mod->hasUmbrellaDir())
16317033127bSDouglas Gregor       return Mod->getUmbrellaDir();
16327033127bSDouglas Gregor 
16337033127bSDouglas Gregor     // If we have a framework directory, stop looking.
16347033127bSDouglas Gregor     if (Mod->IsFramework)
16357033127bSDouglas Gregor       return 0;
16367033127bSDouglas Gregor   }
16377033127bSDouglas Gregor 
16387033127bSDouglas Gregor   return 0;
16397033127bSDouglas Gregor }
16407033127bSDouglas Gregor 
1641718292f2SDouglas Gregor /// \brief Parse a module map file.
1642718292f2SDouglas Gregor ///
1643718292f2SDouglas Gregor ///   module-map-file:
1644718292f2SDouglas Gregor ///     module-declaration*
1645718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
1646718292f2SDouglas Gregor   do {
1647718292f2SDouglas Gregor     switch (Tok.Kind) {
1648718292f2SDouglas Gregor     case MMToken::EndOfFile:
1649718292f2SDouglas Gregor       return HadError;
1650718292f2SDouglas Gregor 
1651e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
1652718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1653755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
1654718292f2SDouglas Gregor       parseModuleDecl();
1655718292f2SDouglas Gregor       break;
1656718292f2SDouglas Gregor 
16571fb5c3a6SDouglas Gregor     case MMToken::Comma:
165859527666SDouglas Gregor     case MMToken::ExcludeKeyword:
16592b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
1660718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
1661718292f2SDouglas Gregor     case MMToken::Identifier:
1662718292f2SDouglas Gregor     case MMToken::LBrace:
1663a686e1b0SDouglas Gregor     case MMToken::LSquare:
16642b82c2a5SDouglas Gregor     case MMToken::Period:
1665718292f2SDouglas Gregor     case MMToken::RBrace:
1666a686e1b0SDouglas Gregor     case MMToken::RSquare:
16671fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
16682b82c2a5SDouglas Gregor     case MMToken::Star:
1669718292f2SDouglas Gregor     case MMToken::StringLiteral:
1670718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
1671718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1672718292f2SDouglas Gregor       HadError = true;
1673718292f2SDouglas Gregor       consumeToken();
1674718292f2SDouglas Gregor       break;
1675718292f2SDouglas Gregor     }
1676718292f2SDouglas Gregor   } while (true);
1677718292f2SDouglas Gregor }
1678718292f2SDouglas Gregor 
1679718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
168089929282SDouglas Gregor   assert(Target != 0 && "Missing target information");
1681718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1682718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1683718292f2SDouglas Gregor   if (!Buffer)
1684718292f2SDouglas Gregor     return true;
1685718292f2SDouglas Gregor 
1686718292f2SDouglas Gregor   // Parse this module map file.
16871fb5c3a6SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
16881fb5c3a6SDouglas Gregor   Diags->getClient()->BeginSourceFile(MMapLangOpts);
1689bc10b9fbSDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
16903ec6663bSDouglas Gregor                          BuiltinIncludeDir);
1691718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
1692718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
1693718292f2SDouglas Gregor 
1694718292f2SDouglas Gregor   return Result;
1695718292f2SDouglas Gregor }
1696