1718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2718292f2SDouglas Gregor //
3718292f2SDouglas Gregor //                     The LLVM Compiler Infrastructure
4718292f2SDouglas Gregor //
5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6718292f2SDouglas Gregor // License. See LICENSE.TXT for details.
7718292f2SDouglas Gregor //
8718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
9718292f2SDouglas Gregor //
10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
11718292f2SDouglas Gregor // of a module as it relates to headers.
12718292f2SDouglas Gregor //
13718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
16811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h"
17718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
18718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
19718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
203a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
213a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
223a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
233a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
243a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
25718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
26e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h"
27718292f2SDouglas Gregor #include "llvm/Support/Host.h"
285257fc63SDouglas Gregor #include "llvm/Support/PathV2.h"
29718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
3007c22b78SDouglas Gregor #include <stdlib.h>
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();
160*f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
16174260502SDouglas Gregor #ifdef LLVM_ON_UNIX
16274260502SDouglas Gregor   // Note: as an egregious but useful hack we use the real path here, because
16374260502SDouglas Gregor   // frameworks moving from top-level frameworks to embedded frameworks tend
16474260502SDouglas Gregor   // to be symlinked from the top-level location to the embedded location,
16574260502SDouglas Gregor   // and we need to resolve lookups as if we had found the embedded location.
16674260502SDouglas Gregor   char RealDirName[PATH_MAX];
16774260502SDouglas Gregor   StringRef DirName;
16874260502SDouglas Gregor   if (realpath(Dir->getName(), RealDirName))
16974260502SDouglas Gregor     DirName = RealDirName;
17074260502SDouglas Gregor   else
17174260502SDouglas Gregor     DirName = Dir->getName();
17274260502SDouglas Gregor #else
173b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
17474260502SDouglas Gregor #endif
175a89c5ac4SDouglas Gregor 
176a89c5ac4SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
177a89c5ac4SDouglas Gregor   // an umbrella header.
178b65dbfffSDouglas Gregor   do {
179a89c5ac4SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
180a89c5ac4SDouglas Gregor       = UmbrellaDirs.find(Dir);
181a89c5ac4SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
182a89c5ac4SDouglas Gregor       Module *Result = KnownDir->second;
183930a85ccSDouglas Gregor 
184930a85ccSDouglas Gregor       // Search up the module stack until we find a module with an umbrella
18573141fa9SDouglas Gregor       // directory.
186930a85ccSDouglas Gregor       Module *UmbrellaModule = Result;
18773141fa9SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
188930a85ccSDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
189930a85ccSDouglas Gregor 
190930a85ccSDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
191a89c5ac4SDouglas Gregor         // Infer submodules for each of the directories we found between
192a89c5ac4SDouglas Gregor         // the directory of the umbrella header and the directory where
193a89c5ac4SDouglas Gregor         // the actual header is located.
1949458f82dSDouglas Gregor         bool Explicit = UmbrellaModule->InferExplicitSubmodules;
1959458f82dSDouglas Gregor 
1967033127bSDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
197a89c5ac4SDouglas Gregor           // Find or create the module that corresponds to this directory name.
198056396aeSDouglas Gregor           SmallString<32> NameBuf;
199056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
200056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
201056396aeSDouglas Gregor                              NameBuf);
202a89c5ac4SDouglas Gregor           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
2039458f82dSDouglas Gregor                                       Explicit).first;
204a89c5ac4SDouglas Gregor 
205a89c5ac4SDouglas Gregor           // Associate the module and the directory.
206a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I-1]] = Result;
207a89c5ac4SDouglas Gregor 
208a89c5ac4SDouglas Gregor           // If inferred submodules export everything they import, add a
209a89c5ac4SDouglas Gregor           // wildcard to the set of exports.
210930a85ccSDouglas Gregor           if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
211a89c5ac4SDouglas Gregor             Result->Exports.push_back(Module::ExportDecl(0, true));
212a89c5ac4SDouglas Gregor         }
213a89c5ac4SDouglas Gregor 
214a89c5ac4SDouglas Gregor         // Infer a submodule with the same name as this header file.
215056396aeSDouglas Gregor         SmallString<32> NameBuf;
216056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
217056396aeSDouglas Gregor                            llvm::sys::path::stem(File->getName()), NameBuf);
218a89c5ac4SDouglas Gregor         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
2199458f82dSDouglas Gregor                                     Explicit).first;
220c597c8c4SArgyrios Kyrtzidis         Result->TopHeaders.insert(File);
221a89c5ac4SDouglas Gregor 
222a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
223a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
224930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
225a89c5ac4SDouglas Gregor           Result->Exports.push_back(Module::ExportDecl(0, true));
226a89c5ac4SDouglas Gregor       } else {
227a89c5ac4SDouglas Gregor         // Record each of the directories we stepped through as being part of
228a89c5ac4SDouglas Gregor         // the module we found, since the umbrella header covers them all.
229a89c5ac4SDouglas Gregor         for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
230a89c5ac4SDouglas Gregor           UmbrellaDirs[SkippedDirs[I]] = Result;
231a89c5ac4SDouglas Gregor       }
232a89c5ac4SDouglas Gregor 
23359527666SDouglas Gregor       Headers[File] = KnownHeader(Result, /*Excluded=*/false);
2341fb5c3a6SDouglas Gregor 
2351fb5c3a6SDouglas Gregor       // If a header corresponds to an unavailable module, don't report
2361fb5c3a6SDouglas Gregor       // that it maps to anything.
2371fb5c3a6SDouglas Gregor       if (!Result->isAvailable())
2381fb5c3a6SDouglas Gregor         return 0;
2391fb5c3a6SDouglas Gregor 
240a89c5ac4SDouglas Gregor       return Result;
241a89c5ac4SDouglas Gregor     }
242a89c5ac4SDouglas Gregor 
243a89c5ac4SDouglas Gregor     SkippedDirs.push_back(Dir);
244a89c5ac4SDouglas Gregor 
245b65dbfffSDouglas Gregor     // Retrieve our parent path.
246b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
247b65dbfffSDouglas Gregor     if (DirName.empty())
248b65dbfffSDouglas Gregor       break;
249b65dbfffSDouglas Gregor 
250b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
251b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
252a89c5ac4SDouglas Gregor   } while (Dir);
253b65dbfffSDouglas Gregor 
254ab0c8a84SDouglas Gregor   return 0;
255ab0c8a84SDouglas Gregor }
256ab0c8a84SDouglas Gregor 
2571fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
25859527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(Header);
2591fb5c3a6SDouglas Gregor   if (Known != Headers.end())
26059527666SDouglas Gregor     return !Known->second.isAvailable();
2611fb5c3a6SDouglas Gregor 
2621fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
263*f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
2641fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
2651fb5c3a6SDouglas Gregor 
2661fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
2671fb5c3a6SDouglas Gregor   // an umbrella header.
2681fb5c3a6SDouglas Gregor   do {
2691fb5c3a6SDouglas Gregor     llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
2701fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
2711fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
2721fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
2731fb5c3a6SDouglas Gregor       if (!Found->isAvailable())
2741fb5c3a6SDouglas Gregor         return true;
2751fb5c3a6SDouglas Gregor 
2761fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
2771fb5c3a6SDouglas Gregor       // directory.
2781fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
2791fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
2801fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
2811fb5c3a6SDouglas Gregor 
2821fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
2831fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
2841fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
285056396aeSDouglas Gregor           SmallString<32> NameBuf;
286056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
287056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
288056396aeSDouglas Gregor                              NameBuf);
2891fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
2901fb5c3a6SDouglas Gregor           if (!Found)
2911fb5c3a6SDouglas Gregor             return false;
2921fb5c3a6SDouglas Gregor           if (!Found->isAvailable())
2931fb5c3a6SDouglas Gregor             return true;
2941fb5c3a6SDouglas Gregor         }
2951fb5c3a6SDouglas Gregor 
2961fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
297056396aeSDouglas Gregor         SmallString<32> NameBuf;
298056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
299056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
300056396aeSDouglas Gregor                            NameBuf);
3011fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
3021fb5c3a6SDouglas Gregor         if (!Found)
3031fb5c3a6SDouglas Gregor           return false;
3041fb5c3a6SDouglas Gregor       }
3051fb5c3a6SDouglas Gregor 
3061fb5c3a6SDouglas Gregor       return !Found->isAvailable();
3071fb5c3a6SDouglas Gregor     }
3081fb5c3a6SDouglas Gregor 
3091fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
3101fb5c3a6SDouglas Gregor 
3111fb5c3a6SDouglas Gregor     // Retrieve our parent path.
3121fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
3131fb5c3a6SDouglas Gregor     if (DirName.empty())
3141fb5c3a6SDouglas Gregor       break;
3151fb5c3a6SDouglas Gregor 
3161fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
3171fb5c3a6SDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
3181fb5c3a6SDouglas Gregor   } while (Dir);
3191fb5c3a6SDouglas Gregor 
3201fb5c3a6SDouglas Gregor   return false;
3211fb5c3a6SDouglas Gregor }
3221fb5c3a6SDouglas Gregor 
323de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
32488bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
32588bdfb0eSDouglas Gregor   if (Known != Modules.end())
32688bdfb0eSDouglas Gregor     return Known->getValue();
32788bdfb0eSDouglas Gregor 
32888bdfb0eSDouglas Gregor   return 0;
32988bdfb0eSDouglas Gregor }
33088bdfb0eSDouglas Gregor 
3312b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
3322b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
3332b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
3342b82c2a5SDouglas Gregor       return Sub;
3352b82c2a5SDouglas Gregor   }
3362b82c2a5SDouglas Gregor 
3372b82c2a5SDouglas Gregor   return findModule(Name);
3382b82c2a5SDouglas Gregor }
3392b82c2a5SDouglas Gregor 
3402b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
3412b82c2a5SDouglas Gregor   if (!Context)
3422b82c2a5SDouglas Gregor     return findModule(Name);
3432b82c2a5SDouglas Gregor 
344eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
3452b82c2a5SDouglas Gregor }
3462b82c2a5SDouglas Gregor 
347de3ef502SDouglas Gregor std::pair<Module *, bool>
34869021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
34969021974SDouglas Gregor                               bool IsExplicit) {
35069021974SDouglas Gregor   // Try to find an existing module with this name.
351eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
352eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
35369021974SDouglas Gregor 
35469021974SDouglas Gregor   // Create a new module with this name.
35569021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
35669021974SDouglas Gregor                               IsExplicit);
357eb90e830SDouglas Gregor   if (!Parent)
35869021974SDouglas Gregor     Modules[Name] = Result;
35969021974SDouglas Gregor   return std::make_pair(Result, true);
36069021974SDouglas Gregor }
36169021974SDouglas Gregor 
3629194a91dSDouglas Gregor bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
3639194a91dSDouglas Gregor                                         StringRef Name, bool &IsSystem) {
3649194a91dSDouglas Gregor   // Check whether we have already looked into the parent directory
3659194a91dSDouglas Gregor   // for a module map.
3669194a91dSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
3679194a91dSDouglas Gregor     inferred = InferredDirectories.find(ParentDir);
3689194a91dSDouglas Gregor   if (inferred == InferredDirectories.end())
3699194a91dSDouglas Gregor     return false;
3709194a91dSDouglas Gregor 
3719194a91dSDouglas Gregor   if (!inferred->second.InferModules)
3729194a91dSDouglas Gregor     return false;
3739194a91dSDouglas Gregor 
3749194a91dSDouglas Gregor   // We're allowed to infer for this directory, but make sure it's okay
3759194a91dSDouglas Gregor   // to infer this particular module.
3769194a91dSDouglas Gregor   bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
3779194a91dSDouglas Gregor                             inferred->second.ExcludedModules.end(),
3789194a91dSDouglas Gregor                             Name) == inferred->second.ExcludedModules.end();
3799194a91dSDouglas Gregor 
3809194a91dSDouglas Gregor   if (canInfer && inferred->second.InferSystemModules)
3819194a91dSDouglas Gregor     IsSystem = true;
3829194a91dSDouglas Gregor 
3839194a91dSDouglas Gregor   return canInfer;
3849194a91dSDouglas Gregor }
3859194a91dSDouglas Gregor 
386de3ef502SDouglas Gregor Module *
38756c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
388e89dbc1dSDouglas Gregor                                 const DirectoryEntry *FrameworkDir,
389a686e1b0SDouglas Gregor                                 bool IsSystem,
390e89dbc1dSDouglas Gregor                                 Module *Parent) {
39156c64013SDouglas Gregor   // Check whether we've already found this module.
392e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
393e89dbc1dSDouglas Gregor     return Mod;
394e89dbc1dSDouglas Gregor 
395e89dbc1dSDouglas Gregor   FileManager &FileMgr = SourceMgr->getFileManager();
39656c64013SDouglas Gregor 
3979194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
3989194a91dSDouglas Gregor   // a framework module, do so.
3999194a91dSDouglas Gregor   if (!Parent) {
4004ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
4014ddf2221SDouglas Gregor     StringRef FrameworkDirName = FrameworkDir->getName();
4024ddf2221SDouglas Gregor #ifdef LLVM_ON_UNIX
4034ddf2221SDouglas Gregor     // Note: as an egregious but useful hack we use the real path here, because
4044ddf2221SDouglas Gregor     // we might be looking at an embedded framework that symlinks out to a
4054ddf2221SDouglas Gregor     // top-level framework, and we need to infer as if we were naming the
4064ddf2221SDouglas Gregor     // top-level framework.
4074ddf2221SDouglas Gregor     char RealFrameworkDirName[PATH_MAX];
4084ddf2221SDouglas Gregor     if (realpath(FrameworkDir->getName(), RealFrameworkDirName))
4094ddf2221SDouglas Gregor       FrameworkDirName = RealFrameworkDirName;
4104ddf2221SDouglas Gregor #endif
4114ddf2221SDouglas Gregor 
4129194a91dSDouglas Gregor     bool canInfer = false;
4134ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
4149194a91dSDouglas Gregor       // Figure out the parent path.
4154ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
4169194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
4179194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
4189194a91dSDouglas Gregor         // for a module map.
4199194a91dSDouglas Gregor         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
4209194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
4219194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
4229194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
4239194a91dSDouglas Gregor           // one.
4249194a91dSDouglas Gregor           SmallString<128> ModMapPath = Parent;
4259194a91dSDouglas Gregor           llvm::sys::path::append(ModMapPath, "module.map");
4269194a91dSDouglas Gregor           if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
4279194a91dSDouglas Gregor             parseModuleMapFile(ModMapFile);
4289194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
4299194a91dSDouglas Gregor           }
4309194a91dSDouglas Gregor 
4319194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
4329194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
4339194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
4349194a91dSDouglas Gregor         }
4359194a91dSDouglas Gregor 
4369194a91dSDouglas Gregor         if (inferred->second.InferModules) {
4379194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
4389194a91dSDouglas Gregor           // to infer this particular module.
4394ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
4409194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
4419194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
4429194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
4439194a91dSDouglas Gregor 
4449194a91dSDouglas Gregor           if (inferred->second.InferSystemModules)
4459194a91dSDouglas Gregor             IsSystem = true;
4469194a91dSDouglas Gregor         }
4479194a91dSDouglas Gregor       }
4489194a91dSDouglas Gregor     }
4499194a91dSDouglas Gregor 
4509194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
4519194a91dSDouglas Gregor     if (!canInfer)
4529194a91dSDouglas Gregor       return 0;
4539194a91dSDouglas Gregor   }
4549194a91dSDouglas Gregor 
4559194a91dSDouglas Gregor 
45656c64013SDouglas Gregor   // Look for an umbrella header.
4572c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
45856c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
45956c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
460e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
46156c64013SDouglas Gregor 
46256c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
46356c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
46456c64013SDouglas Gregor   // idea.
46556c64013SDouglas Gregor   if (!UmbrellaHeader)
46656c64013SDouglas Gregor     return 0;
46756c64013SDouglas Gregor 
468e89dbc1dSDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
469e89dbc1dSDouglas Gregor                               /*IsFramework=*/true, /*IsExplicit=*/false);
470a686e1b0SDouglas Gregor   if (IsSystem)
471a686e1b0SDouglas Gregor     Result->IsSystem = IsSystem;
472a686e1b0SDouglas Gregor 
473eb90e830SDouglas Gregor   if (!Parent)
474e89dbc1dSDouglas Gregor     Modules[ModuleName] = Result;
475e89dbc1dSDouglas Gregor 
476322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
47773141fa9SDouglas Gregor   Result->Umbrella = UmbrellaHeader;
47859527666SDouglas Gregor   Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
4794dc71835SDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
480d8bd7537SDouglas Gregor 
481d8bd7537SDouglas Gregor   // export *
482d8bd7537SDouglas Gregor   Result->Exports.push_back(Module::ExportDecl(0, true));
483d8bd7537SDouglas Gregor 
484a89c5ac4SDouglas Gregor   // module * { export * }
485a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
486a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
487a89c5ac4SDouglas Gregor 
488e89dbc1dSDouglas Gregor   // Look for subframeworks.
489e89dbc1dSDouglas Gregor   llvm::error_code EC;
4902c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
491ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
492e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
4932c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirNameNative;
494ddaa69cbSDouglas Gregor   llvm::sys::path::native(SubframeworksDirName.str(),
495ddaa69cbSDouglas Gregor                           SubframeworksDirNameNative);
496ddaa69cbSDouglas Gregor   for (llvm::sys::fs::directory_iterator
497ddaa69cbSDouglas Gregor          Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
498e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
499e89dbc1dSDouglas Gregor     if (!StringRef(Dir->path()).endswith(".framework"))
500e89dbc1dSDouglas Gregor       continue;
501f2161a70SDouglas Gregor 
502e89dbc1dSDouglas Gregor     if (const DirectoryEntry *SubframeworkDir
503e89dbc1dSDouglas Gregor           = FileMgr.getDirectory(Dir->path())) {
50407c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
50507c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
50607c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
50707c22b78SDouglas Gregor       // out to a top-level framework.
50807c22b78SDouglas Gregor #ifdef LLVM_ON_UNIX
50907c22b78SDouglas Gregor       char RealSubframeworkDirName[PATH_MAX];
51007c22b78SDouglas Gregor       if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) {
51107c22b78SDouglas Gregor         StringRef SubframeworkDirName = RealSubframeworkDirName;
51207c22b78SDouglas Gregor 
51307c22b78SDouglas Gregor         bool FoundParent = false;
51407c22b78SDouglas Gregor         do {
51507c22b78SDouglas Gregor           // Get the parent directory name.
51607c22b78SDouglas Gregor           SubframeworkDirName
51707c22b78SDouglas Gregor             = llvm::sys::path::parent_path(SubframeworkDirName);
51807c22b78SDouglas Gregor           if (SubframeworkDirName.empty())
51907c22b78SDouglas Gregor             break;
52007c22b78SDouglas Gregor 
52107c22b78SDouglas Gregor           if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
52207c22b78SDouglas Gregor             FoundParent = true;
52307c22b78SDouglas Gregor             break;
52407c22b78SDouglas Gregor           }
52507c22b78SDouglas Gregor         } while (true);
52607c22b78SDouglas Gregor 
52707c22b78SDouglas Gregor         if (!FoundParent)
52807c22b78SDouglas Gregor           continue;
52907c22b78SDouglas Gregor       }
53007c22b78SDouglas Gregor #endif
53107c22b78SDouglas Gregor 
532e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
533056396aeSDouglas Gregor       SmallString<32> NameBuf;
534056396aeSDouglas Gregor       inferFrameworkModule(sanitizeFilenameAsIdentifier(
535056396aeSDouglas Gregor                              llvm::sys::path::stem(Dir->path()), NameBuf),
536056396aeSDouglas Gregor                            SubframeworkDir, IsSystem, Result);
537e89dbc1dSDouglas Gregor     }
538e89dbc1dSDouglas Gregor   }
539e89dbc1dSDouglas Gregor 
54056c64013SDouglas Gregor   return Result;
54156c64013SDouglas Gregor }
54256c64013SDouglas Gregor 
543a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
54459527666SDouglas Gregor   Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
54573141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
5467033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
547a89c5ac4SDouglas Gregor }
548a89c5ac4SDouglas Gregor 
549524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
550524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
551524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
552524e33e1SDouglas Gregor }
553524e33e1SDouglas Gregor 
55459527666SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
55559527666SDouglas Gregor                           bool Excluded) {
55659527666SDouglas Gregor   if (Excluded)
55759527666SDouglas Gregor     Mod->ExcludedHeaders.push_back(Header);
55859527666SDouglas Gregor   else
559a89c5ac4SDouglas Gregor     Mod->Headers.push_back(Header);
56059527666SDouglas Gregor   Headers[Header] = KnownHeader(Mod, Excluded);
561a89c5ac4SDouglas Gregor }
562a89c5ac4SDouglas Gregor 
563514b636aSDouglas Gregor const FileEntry *
564de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
565514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
566514b636aSDouglas Gregor     return 0;
567514b636aSDouglas Gregor 
568514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
569514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
570514b636aSDouglas Gregor }
571514b636aSDouglas Gregor 
572718292f2SDouglas Gregor void ModuleMap::dump() {
573718292f2SDouglas Gregor   llvm::errs() << "Modules:";
574718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
575718292f2SDouglas Gregor                                         MEnd = Modules.end();
576718292f2SDouglas Gregor        M != MEnd; ++M)
577d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
578718292f2SDouglas Gregor 
579718292f2SDouglas Gregor   llvm::errs() << "Headers:";
58059527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
581718292f2SDouglas Gregor        H != HEnd; ++H) {
582718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
58359527666SDouglas Gregor                  << H->second.getModule()->getFullModuleName() << "\n";
584718292f2SDouglas Gregor   }
585718292f2SDouglas Gregor }
586718292f2SDouglas Gregor 
5872b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
5882b82c2a5SDouglas Gregor   bool HadError = false;
5892b82c2a5SDouglas Gregor   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
5902b82c2a5SDouglas Gregor     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
5912b82c2a5SDouglas Gregor                                               Complain);
592f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
5932b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
5942b82c2a5SDouglas Gregor     else
5952b82c2a5SDouglas Gregor       HadError = true;
5962b82c2a5SDouglas Gregor   }
5972b82c2a5SDouglas Gregor   Mod->UnresolvedExports.clear();
5982b82c2a5SDouglas Gregor   return HadError;
5992b82c2a5SDouglas Gregor }
6002b82c2a5SDouglas Gregor 
6010093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
6020093b3c7SDouglas Gregor   if (Loc.isInvalid())
6030093b3c7SDouglas Gregor     return 0;
6040093b3c7SDouglas Gregor 
6050093b3c7SDouglas Gregor   // Use the expansion location to determine which module we're in.
6060093b3c7SDouglas Gregor   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
6070093b3c7SDouglas Gregor   if (!ExpansionLoc.isFileID())
6080093b3c7SDouglas Gregor     return 0;
6090093b3c7SDouglas Gregor 
6100093b3c7SDouglas Gregor 
6110093b3c7SDouglas Gregor   const SourceManager &SrcMgr = Loc.getManager();
6120093b3c7SDouglas Gregor   FileID ExpansionFileID = ExpansionLoc.getFileID();
613224d8a74SDouglas Gregor 
614224d8a74SDouglas Gregor   while (const FileEntry *ExpansionFile
615224d8a74SDouglas Gregor            = SrcMgr.getFileEntryForID(ExpansionFileID)) {
616224d8a74SDouglas Gregor     // Find the module that owns this header (if any).
617224d8a74SDouglas Gregor     if (Module *Mod = findModuleForHeader(ExpansionFile))
618224d8a74SDouglas Gregor       return Mod;
619224d8a74SDouglas Gregor 
620224d8a74SDouglas Gregor     // No module owns this header, so look up the inclusion chain to see if
621224d8a74SDouglas Gregor     // any included header has an associated module.
622224d8a74SDouglas Gregor     SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
623224d8a74SDouglas Gregor     if (IncludeLoc.isInvalid())
6240093b3c7SDouglas Gregor       return 0;
6250093b3c7SDouglas Gregor 
626224d8a74SDouglas Gregor     ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
627224d8a74SDouglas Gregor   }
628224d8a74SDouglas Gregor 
629224d8a74SDouglas Gregor   return 0;
6300093b3c7SDouglas Gregor }
6310093b3c7SDouglas Gregor 
632718292f2SDouglas Gregor //----------------------------------------------------------------------------//
633718292f2SDouglas Gregor // Module map file parser
634718292f2SDouglas Gregor //----------------------------------------------------------------------------//
635718292f2SDouglas Gregor 
636718292f2SDouglas Gregor namespace clang {
637718292f2SDouglas Gregor   /// \brief A token in a module map file.
638718292f2SDouglas Gregor   struct MMToken {
639718292f2SDouglas Gregor     enum TokenKind {
6401fb5c3a6SDouglas Gregor       Comma,
641718292f2SDouglas Gregor       EndOfFile,
642718292f2SDouglas Gregor       HeaderKeyword,
643718292f2SDouglas Gregor       Identifier,
64459527666SDouglas Gregor       ExcludeKeyword,
645718292f2SDouglas Gregor       ExplicitKeyword,
6462b82c2a5SDouglas Gregor       ExportKeyword,
647755b2055SDouglas Gregor       FrameworkKeyword,
648718292f2SDouglas Gregor       ModuleKeyword,
6492b82c2a5SDouglas Gregor       Period,
650718292f2SDouglas Gregor       UmbrellaKeyword,
6511fb5c3a6SDouglas Gregor       RequiresKeyword,
6522b82c2a5SDouglas Gregor       Star,
653718292f2SDouglas Gregor       StringLiteral,
654718292f2SDouglas Gregor       LBrace,
655a686e1b0SDouglas Gregor       RBrace,
656a686e1b0SDouglas Gregor       LSquare,
657a686e1b0SDouglas Gregor       RSquare
658718292f2SDouglas Gregor     } Kind;
659718292f2SDouglas Gregor 
660718292f2SDouglas Gregor     unsigned Location;
661718292f2SDouglas Gregor     unsigned StringLength;
662718292f2SDouglas Gregor     const char *StringData;
663718292f2SDouglas Gregor 
664718292f2SDouglas Gregor     void clear() {
665718292f2SDouglas Gregor       Kind = EndOfFile;
666718292f2SDouglas Gregor       Location = 0;
667718292f2SDouglas Gregor       StringLength = 0;
668718292f2SDouglas Gregor       StringData = 0;
669718292f2SDouglas Gregor     }
670718292f2SDouglas Gregor 
671718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
672718292f2SDouglas Gregor 
673718292f2SDouglas Gregor     SourceLocation getLocation() const {
674718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
675718292f2SDouglas Gregor     }
676718292f2SDouglas Gregor 
677718292f2SDouglas Gregor     StringRef getString() const {
678718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
679718292f2SDouglas Gregor     }
680718292f2SDouglas Gregor   };
681718292f2SDouglas Gregor 
6829194a91dSDouglas Gregor   /// \brief The set of attributes that can be attached to a module.
6834442605fSBill Wendling   struct Attributes {
6844442605fSBill Wendling     Attributes() : IsSystem() { }
6859194a91dSDouglas Gregor 
6869194a91dSDouglas Gregor     /// \brief Whether this is a system module.
6879194a91dSDouglas Gregor     unsigned IsSystem : 1;
6889194a91dSDouglas Gregor   };
6899194a91dSDouglas Gregor 
6909194a91dSDouglas Gregor 
691718292f2SDouglas Gregor   class ModuleMapParser {
692718292f2SDouglas Gregor     Lexer &L;
693718292f2SDouglas Gregor     SourceManager &SourceMgr;
694bc10b9fbSDouglas Gregor 
695bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
696bc10b9fbSDouglas Gregor     /// parsing.
697bc10b9fbSDouglas Gregor     const TargetInfo *Target;
698bc10b9fbSDouglas Gregor 
699718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
700718292f2SDouglas Gregor     ModuleMap &Map;
701718292f2SDouglas Gregor 
7025257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
7035257fc63SDouglas Gregor     const DirectoryEntry *Directory;
7045257fc63SDouglas Gregor 
7053ec6663bSDouglas Gregor     /// \brief The directory containing Clang-supplied headers.
7063ec6663bSDouglas Gregor     const DirectoryEntry *BuiltinIncludeDir;
7073ec6663bSDouglas Gregor 
708718292f2SDouglas Gregor     /// \brief Whether an error occurred.
709718292f2SDouglas Gregor     bool HadError;
710718292f2SDouglas Gregor 
711718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
712718292f2SDouglas Gregor     /// during parsing.
713718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
714718292f2SDouglas Gregor 
715718292f2SDouglas Gregor     /// \brief The current token.
716718292f2SDouglas Gregor     MMToken Tok;
717718292f2SDouglas Gregor 
718718292f2SDouglas Gregor     /// \brief The active module.
719de3ef502SDouglas Gregor     Module *ActiveModule;
720718292f2SDouglas Gregor 
721718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
722718292f2SDouglas Gregor     SourceLocation consumeToken();
723718292f2SDouglas Gregor 
724718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
725718292f2SDouglas Gregor     /// (or the end of the file).
726718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
727718292f2SDouglas Gregor 
728*f857950dSDmitri Gribenko     typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
729e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
730718292f2SDouglas Gregor     void parseModuleDecl();
7311fb5c3a6SDouglas Gregor     void parseRequiresDecl();
73259527666SDouglas Gregor     void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
733524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
7342b82c2a5SDouglas Gregor     void parseExportDecl();
7359194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
7364442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
737718292f2SDouglas Gregor 
7387033127bSDouglas Gregor     const DirectoryEntry *getOverriddenHeaderSearchDir();
7397033127bSDouglas Gregor 
740718292f2SDouglas Gregor   public:
741718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
742bc10b9fbSDouglas Gregor                              const TargetInfo *Target,
743718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
7445257fc63SDouglas Gregor                              ModuleMap &Map,
7453ec6663bSDouglas Gregor                              const DirectoryEntry *Directory,
7463ec6663bSDouglas Gregor                              const DirectoryEntry *BuiltinIncludeDir)
747bc10b9fbSDouglas Gregor       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
7483ec6663bSDouglas Gregor         Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
7493ec6663bSDouglas Gregor         HadError(false), ActiveModule(0)
750718292f2SDouglas Gregor     {
751718292f2SDouglas Gregor       Tok.clear();
752718292f2SDouglas Gregor       consumeToken();
753718292f2SDouglas Gregor     }
754718292f2SDouglas Gregor 
755718292f2SDouglas Gregor     bool parseModuleMapFile();
756718292f2SDouglas Gregor   };
757718292f2SDouglas Gregor }
758718292f2SDouglas Gregor 
759718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
760718292f2SDouglas Gregor retry:
761718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
762718292f2SDouglas Gregor   Tok.clear();
763718292f2SDouglas Gregor 
764718292f2SDouglas Gregor   Token LToken;
765718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
766718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
767718292f2SDouglas Gregor   switch (LToken.getKind()) {
768718292f2SDouglas Gregor   case tok::raw_identifier:
769718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
770718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
771718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
772718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
77359527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
774718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
7752b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
776755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
777718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
7781fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
779718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
780718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
781718292f2SDouglas Gregor     break;
782718292f2SDouglas Gregor 
7831fb5c3a6SDouglas Gregor   case tok::comma:
7841fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
7851fb5c3a6SDouglas Gregor     break;
7861fb5c3a6SDouglas Gregor 
787718292f2SDouglas Gregor   case tok::eof:
788718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
789718292f2SDouglas Gregor     break;
790718292f2SDouglas Gregor 
791718292f2SDouglas Gregor   case tok::l_brace:
792718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
793718292f2SDouglas Gregor     break;
794718292f2SDouglas Gregor 
795a686e1b0SDouglas Gregor   case tok::l_square:
796a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
797a686e1b0SDouglas Gregor     break;
798a686e1b0SDouglas Gregor 
7992b82c2a5SDouglas Gregor   case tok::period:
8002b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
8012b82c2a5SDouglas Gregor     break;
8022b82c2a5SDouglas Gregor 
803718292f2SDouglas Gregor   case tok::r_brace:
804718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
805718292f2SDouglas Gregor     break;
806718292f2SDouglas Gregor 
807a686e1b0SDouglas Gregor   case tok::r_square:
808a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
809a686e1b0SDouglas Gregor     break;
810a686e1b0SDouglas Gregor 
8112b82c2a5SDouglas Gregor   case tok::star:
8122b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
8132b82c2a5SDouglas Gregor     break;
8142b82c2a5SDouglas Gregor 
815718292f2SDouglas Gregor   case tok::string_literal: {
816d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
817d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
818d67aea28SRichard Smith       HadError = true;
819d67aea28SRichard Smith       goto retry;
820d67aea28SRichard Smith     }
821d67aea28SRichard Smith 
822718292f2SDouglas Gregor     // Parse the string literal.
823718292f2SDouglas Gregor     LangOptions LangOpts;
824718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
825718292f2SDouglas Gregor     if (StringLiteral.hadError)
826718292f2SDouglas Gregor       goto retry;
827718292f2SDouglas Gregor 
828718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
829718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
830718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
831718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
832718292f2SDouglas Gregor     Saved[Length] = 0;
833718292f2SDouglas Gregor 
834718292f2SDouglas Gregor     // Form the token.
835718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
836718292f2SDouglas Gregor     Tok.StringData = Saved;
837718292f2SDouglas Gregor     Tok.StringLength = Length;
838718292f2SDouglas Gregor     break;
839718292f2SDouglas Gregor   }
840718292f2SDouglas Gregor 
841718292f2SDouglas Gregor   case tok::comment:
842718292f2SDouglas Gregor     goto retry;
843718292f2SDouglas Gregor 
844718292f2SDouglas Gregor   default:
845718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
846718292f2SDouglas Gregor     HadError = true;
847718292f2SDouglas Gregor     goto retry;
848718292f2SDouglas Gregor   }
849718292f2SDouglas Gregor 
850718292f2SDouglas Gregor   return Result;
851718292f2SDouglas Gregor }
852718292f2SDouglas Gregor 
853718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
854718292f2SDouglas Gregor   unsigned braceDepth = 0;
855a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
856718292f2SDouglas Gregor   do {
857718292f2SDouglas Gregor     switch (Tok.Kind) {
858718292f2SDouglas Gregor     case MMToken::EndOfFile:
859718292f2SDouglas Gregor       return;
860718292f2SDouglas Gregor 
861718292f2SDouglas Gregor     case MMToken::LBrace:
862a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
863718292f2SDouglas Gregor         return;
864718292f2SDouglas Gregor 
865718292f2SDouglas Gregor       ++braceDepth;
866718292f2SDouglas Gregor       break;
867718292f2SDouglas Gregor 
868a686e1b0SDouglas Gregor     case MMToken::LSquare:
869a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
870a686e1b0SDouglas Gregor         return;
871a686e1b0SDouglas Gregor 
872a686e1b0SDouglas Gregor       ++squareDepth;
873a686e1b0SDouglas Gregor       break;
874a686e1b0SDouglas Gregor 
875718292f2SDouglas Gregor     case MMToken::RBrace:
876718292f2SDouglas Gregor       if (braceDepth > 0)
877718292f2SDouglas Gregor         --braceDepth;
878718292f2SDouglas Gregor       else if (Tok.is(K))
879718292f2SDouglas Gregor         return;
880718292f2SDouglas Gregor       break;
881718292f2SDouglas Gregor 
882a686e1b0SDouglas Gregor     case MMToken::RSquare:
883a686e1b0SDouglas Gregor       if (squareDepth > 0)
884a686e1b0SDouglas Gregor         --squareDepth;
885a686e1b0SDouglas Gregor       else if (Tok.is(K))
886a686e1b0SDouglas Gregor         return;
887a686e1b0SDouglas Gregor       break;
888a686e1b0SDouglas Gregor 
889718292f2SDouglas Gregor     default:
890a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
891718292f2SDouglas Gregor         return;
892718292f2SDouglas Gregor       break;
893718292f2SDouglas Gregor     }
894718292f2SDouglas Gregor 
895718292f2SDouglas Gregor    consumeToken();
896718292f2SDouglas Gregor   } while (true);
897718292f2SDouglas Gregor }
898718292f2SDouglas Gregor 
899e7ab3669SDouglas Gregor /// \brief Parse a module-id.
900e7ab3669SDouglas Gregor ///
901e7ab3669SDouglas Gregor ///   module-id:
902e7ab3669SDouglas Gregor ///     identifier
903e7ab3669SDouglas Gregor ///     identifier '.' module-id
904e7ab3669SDouglas Gregor ///
905e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
906e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
907e7ab3669SDouglas Gregor   Id.clear();
908e7ab3669SDouglas Gregor   do {
909e7ab3669SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
910e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
911e7ab3669SDouglas Gregor       consumeToken();
912e7ab3669SDouglas Gregor     } else {
913e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
914e7ab3669SDouglas Gregor       return true;
915e7ab3669SDouglas Gregor     }
916e7ab3669SDouglas Gregor 
917e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
918e7ab3669SDouglas Gregor       break;
919e7ab3669SDouglas Gregor 
920e7ab3669SDouglas Gregor     consumeToken();
921e7ab3669SDouglas Gregor   } while (true);
922e7ab3669SDouglas Gregor 
923e7ab3669SDouglas Gregor   return false;
924e7ab3669SDouglas Gregor }
925e7ab3669SDouglas Gregor 
926a686e1b0SDouglas Gregor namespace {
927a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
928a686e1b0SDouglas Gregor   enum AttributeKind {
929a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
930a686e1b0SDouglas Gregor     AT_unknown,
931a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
932a686e1b0SDouglas Gregor     AT_system
933a686e1b0SDouglas Gregor   };
934a686e1b0SDouglas Gregor }
935a686e1b0SDouglas Gregor 
936718292f2SDouglas Gregor /// \brief Parse a module declaration.
937718292f2SDouglas Gregor ///
938718292f2SDouglas Gregor ///   module-declaration:
939a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
940a686e1b0SDouglas Gregor ///       { module-member* }
941a686e1b0SDouglas Gregor ///
942718292f2SDouglas Gregor ///   module-member:
9431fb5c3a6SDouglas Gregor ///     requires-declaration
944718292f2SDouglas Gregor ///     header-declaration
945e7ab3669SDouglas Gregor ///     submodule-declaration
9462b82c2a5SDouglas Gregor ///     export-declaration
94773441091SDouglas Gregor ///
94873441091SDouglas Gregor ///   submodule-declaration:
94973441091SDouglas Gregor ///     module-declaration
95073441091SDouglas Gregor ///     inferred-submodule-declaration
951718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
952755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
953755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
954f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
955e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
956718292f2SDouglas Gregor   bool Explicit = false;
957f2161a70SDouglas Gregor   bool Framework = false;
958755b2055SDouglas Gregor 
959f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
960f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
961e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
962f2161a70SDouglas Gregor     Explicit = true;
963f2161a70SDouglas Gregor   }
964f2161a70SDouglas Gregor 
965f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
966755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
967755b2055SDouglas Gregor     consumeToken();
968755b2055SDouglas Gregor     Framework = true;
969755b2055SDouglas Gregor   }
970718292f2SDouglas Gregor 
971718292f2SDouglas Gregor   // Parse 'module' keyword.
972718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
973d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
974718292f2SDouglas Gregor     consumeToken();
975718292f2SDouglas Gregor     HadError = true;
976718292f2SDouglas Gregor     return;
977718292f2SDouglas Gregor   }
978718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
979718292f2SDouglas Gregor 
98073441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
98173441091SDouglas Gregor   // Parse it.
98273441091SDouglas Gregor   if (Tok.is(MMToken::Star))
9839194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
98473441091SDouglas Gregor 
985718292f2SDouglas Gregor   // Parse the module name.
986e7ab3669SDouglas Gregor   ModuleId Id;
987e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
988718292f2SDouglas Gregor     HadError = true;
989718292f2SDouglas Gregor     return;
990718292f2SDouglas Gregor   }
991e7ab3669SDouglas Gregor 
992e7ab3669SDouglas Gregor   if (ActiveModule) {
993e7ab3669SDouglas Gregor     if (Id.size() > 1) {
994e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
995e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
996e7ab3669SDouglas Gregor 
997e7ab3669SDouglas Gregor       HadError = true;
998e7ab3669SDouglas Gregor       return;
999e7ab3669SDouglas Gregor     }
1000e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1001e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1002e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1003e7ab3669SDouglas Gregor     Explicit = false;
1004e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1005e7ab3669SDouglas Gregor     HadError = true;
1006e7ab3669SDouglas Gregor   }
1007e7ab3669SDouglas Gregor 
1008e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1009e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1010e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1011e7ab3669SDouglas Gregor     // is a submodule.
1012e7ab3669SDouglas Gregor     ActiveModule = 0;
1013e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1014e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1015e7ab3669SDouglas Gregor         ActiveModule = Next;
1016e7ab3669SDouglas Gregor         continue;
1017e7ab3669SDouglas Gregor       }
1018e7ab3669SDouglas Gregor 
1019e7ab3669SDouglas Gregor       if (ActiveModule) {
1020e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1021e7ab3669SDouglas Gregor           << Id[I].first << ActiveModule->getTopLevelModule();
1022e7ab3669SDouglas Gregor       } else {
1023e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1024e7ab3669SDouglas Gregor       }
1025e7ab3669SDouglas Gregor       HadError = true;
1026e7ab3669SDouglas Gregor       return;
1027e7ab3669SDouglas Gregor     }
1028e7ab3669SDouglas Gregor   }
1029e7ab3669SDouglas Gregor 
1030e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1031e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1032718292f2SDouglas Gregor 
1033a686e1b0SDouglas Gregor   // Parse the optional attribute list.
10344442605fSBill Wendling   Attributes Attrs;
10359194a91dSDouglas Gregor   parseOptionalAttributes(Attrs);
1036a686e1b0SDouglas Gregor 
1037718292f2SDouglas Gregor   // Parse the opening brace.
1038718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1039718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1040718292f2SDouglas Gregor       << ModuleName;
1041718292f2SDouglas Gregor     HadError = true;
1042718292f2SDouglas Gregor     return;
1043718292f2SDouglas Gregor   }
1044718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1045718292f2SDouglas Gregor 
1046718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
1047eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1048fcc54a3bSDouglas Gregor     if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1049fcc54a3bSDouglas Gregor       // Skip the module definition.
1050fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1051fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1052fcc54a3bSDouglas Gregor         consumeToken();
1053fcc54a3bSDouglas Gregor       else {
1054fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1055fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1056fcc54a3bSDouglas Gregor         HadError = true;
1057fcc54a3bSDouglas Gregor       }
1058fcc54a3bSDouglas Gregor       return;
1059fcc54a3bSDouglas Gregor     }
1060fcc54a3bSDouglas Gregor 
1061718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1062718292f2SDouglas Gregor       << ModuleName;
1063eb90e830SDouglas Gregor     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1064718292f2SDouglas Gregor 
1065718292f2SDouglas Gregor     // Skip the module definition.
1066718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
1067718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
1068718292f2SDouglas Gregor       consumeToken();
1069718292f2SDouglas Gregor 
1070718292f2SDouglas Gregor     HadError = true;
1071718292f2SDouglas Gregor     return;
1072718292f2SDouglas Gregor   }
1073718292f2SDouglas Gregor 
1074718292f2SDouglas Gregor   // Start defining this module.
1075eb90e830SDouglas Gregor   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1076eb90e830SDouglas Gregor                                         Explicit).first;
1077eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
10789194a91dSDouglas Gregor   if (Attrs.IsSystem)
1079a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
1080718292f2SDouglas Gregor 
1081718292f2SDouglas Gregor   bool Done = false;
1082718292f2SDouglas Gregor   do {
1083718292f2SDouglas Gregor     switch (Tok.Kind) {
1084718292f2SDouglas Gregor     case MMToken::EndOfFile:
1085718292f2SDouglas Gregor     case MMToken::RBrace:
1086718292f2SDouglas Gregor       Done = true;
1087718292f2SDouglas Gregor       break;
1088718292f2SDouglas Gregor 
1089718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
1090f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1091718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1092718292f2SDouglas Gregor       parseModuleDecl();
1093718292f2SDouglas Gregor       break;
1094718292f2SDouglas Gregor 
10952b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
10962b82c2a5SDouglas Gregor       parseExportDecl();
10972b82c2a5SDouglas Gregor       break;
10982b82c2a5SDouglas Gregor 
10991fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
11001fb5c3a6SDouglas Gregor       parseRequiresDecl();
11011fb5c3a6SDouglas Gregor       break;
11021fb5c3a6SDouglas Gregor 
1103524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1104524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1105524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
110659527666SDouglas Gregor         parseHeaderDecl(UmbrellaLoc, SourceLocation());
1107524e33e1SDouglas Gregor       else
1108524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1109718292f2SDouglas Gregor       break;
1110524e33e1SDouglas Gregor     }
1111718292f2SDouglas Gregor 
111259527666SDouglas Gregor     case MMToken::ExcludeKeyword: {
111359527666SDouglas Gregor       SourceLocation ExcludeLoc = consumeToken();
111459527666SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword)) {
111559527666SDouglas Gregor         parseHeaderDecl(SourceLocation(), ExcludeLoc);
111659527666SDouglas Gregor       } else {
111759527666SDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
111859527666SDouglas Gregor           << "exclude";
111959527666SDouglas Gregor       }
112059527666SDouglas Gregor       break;
112159527666SDouglas Gregor     }
112259527666SDouglas Gregor 
1123322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
112459527666SDouglas Gregor       parseHeaderDecl(SourceLocation(), SourceLocation());
1125718292f2SDouglas Gregor       break;
1126718292f2SDouglas Gregor 
1127718292f2SDouglas Gregor     default:
1128718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1129718292f2SDouglas Gregor       consumeToken();
1130718292f2SDouglas Gregor       break;
1131718292f2SDouglas Gregor     }
1132718292f2SDouglas Gregor   } while (!Done);
1133718292f2SDouglas Gregor 
1134718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1135718292f2SDouglas Gregor     consumeToken();
1136718292f2SDouglas Gregor   else {
1137718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1138718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1139718292f2SDouglas Gregor     HadError = true;
1140718292f2SDouglas Gregor   }
1141718292f2SDouglas Gregor 
1142e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
1143e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
1144718292f2SDouglas Gregor }
1145718292f2SDouglas Gregor 
11461fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
11471fb5c3a6SDouglas Gregor ///
11481fb5c3a6SDouglas Gregor ///   requires-declaration:
11491fb5c3a6SDouglas Gregor ///     'requires' feature-list
11501fb5c3a6SDouglas Gregor ///
11511fb5c3a6SDouglas Gregor ///   feature-list:
11521fb5c3a6SDouglas Gregor ///     identifier ',' feature-list
11531fb5c3a6SDouglas Gregor ///     identifier
11541fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
11551fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
11561fb5c3a6SDouglas Gregor 
11571fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
11581fb5c3a6SDouglas Gregor   consumeToken();
11591fb5c3a6SDouglas Gregor 
11601fb5c3a6SDouglas Gregor   // Parse the feature-list.
11611fb5c3a6SDouglas Gregor   do {
11621fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
11631fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
11641fb5c3a6SDouglas Gregor       HadError = true;
11651fb5c3a6SDouglas Gregor       return;
11661fb5c3a6SDouglas Gregor     }
11671fb5c3a6SDouglas Gregor 
11681fb5c3a6SDouglas Gregor     // Consume the feature name.
11691fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
11701fb5c3a6SDouglas Gregor     consumeToken();
11711fb5c3a6SDouglas Gregor 
11721fb5c3a6SDouglas Gregor     // Add this feature.
117389929282SDouglas Gregor     ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
11741fb5c3a6SDouglas Gregor 
11751fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
11761fb5c3a6SDouglas Gregor       break;
11771fb5c3a6SDouglas Gregor 
11781fb5c3a6SDouglas Gregor     // Consume the comma.
11791fb5c3a6SDouglas Gregor     consumeToken();
11801fb5c3a6SDouglas Gregor   } while (true);
11811fb5c3a6SDouglas Gregor }
11821fb5c3a6SDouglas Gregor 
1183f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the
1184f2161a70SDouglas Gregor /// subframework in which the given module lives.
1185bf8da9d7SBenjamin Kramer static void appendSubframeworkPaths(Module *Mod,
1186*f857950dSDmitri Gribenko                                     SmallVectorImpl<char> &Path) {
1187f2161a70SDouglas Gregor   // Collect the framework names from the given module to the top-level module.
1188*f857950dSDmitri Gribenko   SmallVector<StringRef, 2> Paths;
1189f2161a70SDouglas Gregor   for (; Mod; Mod = Mod->Parent) {
1190f2161a70SDouglas Gregor     if (Mod->IsFramework)
1191f2161a70SDouglas Gregor       Paths.push_back(Mod->Name);
1192f2161a70SDouglas Gregor   }
1193f2161a70SDouglas Gregor 
1194f2161a70SDouglas Gregor   if (Paths.empty())
1195f2161a70SDouglas Gregor     return;
1196f2161a70SDouglas Gregor 
1197f2161a70SDouglas Gregor   // Add Frameworks/Name.framework for each subframework.
1198f2161a70SDouglas Gregor   for (unsigned I = Paths.size() - 1; I != 0; --I) {
1199f2161a70SDouglas Gregor     llvm::sys::path::append(Path, "Frameworks");
1200f2161a70SDouglas Gregor     llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1201f2161a70SDouglas Gregor   }
1202f2161a70SDouglas Gregor }
1203f2161a70SDouglas Gregor 
12043ec6663bSDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
12053ec6663bSDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
12063ec6663bSDouglas Gregor /// headers.
12073ec6663bSDouglas Gregor static bool isBuiltinHeader(StringRef FileName) {
12083ec6663bSDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
12093ec6663bSDouglas Gregor       .Case("float.h", true)
12103ec6663bSDouglas Gregor       .Case("iso646.h", true)
12113ec6663bSDouglas Gregor       .Case("limits.h", true)
12123ec6663bSDouglas Gregor       .Case("stdalign.h", true)
12133ec6663bSDouglas Gregor       .Case("stdarg.h", true)
12143ec6663bSDouglas Gregor       .Case("stdbool.h", true)
12153ec6663bSDouglas Gregor       .Case("stddef.h", true)
12163ec6663bSDouglas Gregor       .Case("stdint.h", true)
12173ec6663bSDouglas Gregor       .Case("tgmath.h", true)
12183ec6663bSDouglas Gregor       .Case("unwind.h", true)
12193ec6663bSDouglas Gregor       .Default(false);
12203ec6663bSDouglas Gregor }
12213ec6663bSDouglas Gregor 
1222718292f2SDouglas Gregor /// \brief Parse a header declaration.
1223718292f2SDouglas Gregor ///
1224718292f2SDouglas Gregor ///   header-declaration:
1225322f633cSDouglas Gregor ///     'umbrella'[opt] 'header' string-literal
122659527666SDouglas Gregor ///     'exclude'[opt] 'header' string-literal
122759527666SDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
122859527666SDouglas Gregor                                       SourceLocation ExcludeLoc) {
1229718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
12301871ed3dSBenjamin Kramer   consumeToken();
1231718292f2SDouglas Gregor 
1232322f633cSDouglas Gregor   bool Umbrella = UmbrellaLoc.isValid();
123359527666SDouglas Gregor   bool Exclude = ExcludeLoc.isValid();
123459527666SDouglas Gregor   assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
1235718292f2SDouglas Gregor   // Parse the header name.
1236718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1237718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1238718292f2SDouglas Gregor       << "header";
1239718292f2SDouglas Gregor     HadError = true;
1240718292f2SDouglas Gregor     return;
1241718292f2SDouglas Gregor   }
1242e7ab3669SDouglas Gregor   std::string FileName = Tok.getString();
1243718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
1244718292f2SDouglas Gregor 
1245524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1246524e33e1SDouglas Gregor   if (Umbrella && ActiveModule->Umbrella) {
1247524e33e1SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1248524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1249322f633cSDouglas Gregor     HadError = true;
1250322f633cSDouglas Gregor     return;
1251322f633cSDouglas Gregor   }
1252322f633cSDouglas Gregor 
12535257fc63SDouglas Gregor   // Look for this file.
1254e7ab3669SDouglas Gregor   const FileEntry *File = 0;
12553ec6663bSDouglas Gregor   const FileEntry *BuiltinFile = 0;
12562c1dd271SDylan Noblesmith   SmallString<128> PathName;
1257e7ab3669SDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
1258e7ab3669SDouglas Gregor     PathName = FileName;
1259e7ab3669SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
12607033127bSDouglas Gregor   } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
12617033127bSDouglas Gregor     PathName = Dir->getName();
12627033127bSDouglas Gregor     llvm::sys::path::append(PathName, FileName);
12637033127bSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
1264e7ab3669SDouglas Gregor   } else {
1265e7ab3669SDouglas Gregor     // Search for the header file within the search directory.
12667033127bSDouglas Gregor     PathName = Directory->getName();
1267e7ab3669SDouglas Gregor     unsigned PathLength = PathName.size();
1268755b2055SDouglas Gregor 
1269f2161a70SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
1270f2161a70SDouglas Gregor       appendSubframeworkPaths(ActiveModule, PathName);
1271755b2055SDouglas Gregor 
1272e7ab3669SDouglas Gregor       // Check whether this file is in the public headers.
1273e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
12745257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1275e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
1276e7ab3669SDouglas Gregor 
1277e7ab3669SDouglas Gregor       if (!File) {
1278e7ab3669SDouglas Gregor         // Check whether this file is in the private headers.
1279e7ab3669SDouglas Gregor         PathName.resize(PathLength);
1280e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
1281e7ab3669SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
1282e7ab3669SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
1283e7ab3669SDouglas Gregor       }
1284e7ab3669SDouglas Gregor     } else {
1285e7ab3669SDouglas Gregor       // Lookup for normal headers.
1286e7ab3669SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
1287e7ab3669SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
12883ec6663bSDouglas Gregor 
12893ec6663bSDouglas Gregor       // If this is a system module with a top-level header, this header
12903ec6663bSDouglas Gregor       // may have a counterpart (or replacement) in the set of headers
12913ec6663bSDouglas Gregor       // supplied by Clang. Find that builtin header.
12923ec6663bSDouglas Gregor       if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
12933ec6663bSDouglas Gregor           BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
12942c1dd271SDylan Noblesmith         SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
12953ec6663bSDouglas Gregor         llvm::sys::path::append(BuiltinPathName, FileName);
12963ec6663bSDouglas Gregor         BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
12973ec6663bSDouglas Gregor 
12983ec6663bSDouglas Gregor         // If Clang supplies this header but the underlying system does not,
12993ec6663bSDouglas Gregor         // just silently swap in our builtin version. Otherwise, we'll end
13003ec6663bSDouglas Gregor         // up adding both (later).
13013ec6663bSDouglas Gregor         if (!File && BuiltinFile) {
13023ec6663bSDouglas Gregor           File = BuiltinFile;
13033ec6663bSDouglas Gregor           BuiltinFile = 0;
13043ec6663bSDouglas Gregor         }
13053ec6663bSDouglas Gregor       }
1306e7ab3669SDouglas Gregor     }
1307e7ab3669SDouglas Gregor   }
13085257fc63SDouglas Gregor 
13095257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
13105257fc63SDouglas Gregor   // Come up with a lazy way to do this.
1311e7ab3669SDouglas Gregor   if (File) {
131259527666SDouglas Gregor     if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
13135257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
131459527666SDouglas Gregor         << FileName << OwningModule.getModule()->getFullModuleName();
13155257fc63SDouglas Gregor       HadError = true;
1316322f633cSDouglas Gregor     } else if (Umbrella) {
1317322f633cSDouglas Gregor       const DirectoryEntry *UmbrellaDir = File->getDir();
131859527666SDouglas Gregor       if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
1319322f633cSDouglas Gregor         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
132059527666SDouglas Gregor           << UmbrellaModule->getFullModuleName();
1321322f633cSDouglas Gregor         HadError = true;
13225257fc63SDouglas Gregor       } else {
1323322f633cSDouglas Gregor         // Record this umbrella header.
1324322f633cSDouglas Gregor         Map.setUmbrellaHeader(ActiveModule, File);
1325322f633cSDouglas Gregor       }
1326322f633cSDouglas Gregor     } else {
1327322f633cSDouglas Gregor       // Record this header.
132859527666SDouglas Gregor       Map.addHeader(ActiveModule, File, Exclude);
13293ec6663bSDouglas Gregor 
13303ec6663bSDouglas Gregor       // If there is a builtin counterpart to this file, add it now.
13313ec6663bSDouglas Gregor       if (BuiltinFile)
133259527666SDouglas Gregor         Map.addHeader(ActiveModule, BuiltinFile, Exclude);
13335257fc63SDouglas Gregor     }
13344b27a64bSDouglas Gregor   } else if (!Exclude) {
13354b27a64bSDouglas Gregor     // Ignore excluded header files. They're optional anyway.
13364b27a64bSDouglas Gregor 
13375257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
1338524e33e1SDouglas Gregor       << Umbrella << FileName;
13395257fc63SDouglas Gregor     HadError = true;
13405257fc63SDouglas Gregor   }
1341718292f2SDouglas Gregor }
1342718292f2SDouglas Gregor 
1343524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
1344524e33e1SDouglas Gregor ///
1345524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
1346524e33e1SDouglas Gregor ///     umbrella string-literal
1347524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1348524e33e1SDouglas Gregor   // Parse the directory name.
1349524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
1350524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1351524e33e1SDouglas Gregor       << "umbrella";
1352524e33e1SDouglas Gregor     HadError = true;
1353524e33e1SDouglas Gregor     return;
1354524e33e1SDouglas Gregor   }
1355524e33e1SDouglas Gregor 
1356524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
1357524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
1358524e33e1SDouglas Gregor 
1359524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
1360524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
1361524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1362524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
1363524e33e1SDouglas Gregor     HadError = true;
1364524e33e1SDouglas Gregor     return;
1365524e33e1SDouglas Gregor   }
1366524e33e1SDouglas Gregor 
1367524e33e1SDouglas Gregor   // Look for this file.
1368524e33e1SDouglas Gregor   const DirectoryEntry *Dir = 0;
1369524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
1370524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
1371524e33e1SDouglas Gregor   else {
13722c1dd271SDylan Noblesmith     SmallString<128> PathName;
1373524e33e1SDouglas Gregor     PathName = Directory->getName();
1374524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
1375524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
1376524e33e1SDouglas Gregor   }
1377524e33e1SDouglas Gregor 
1378524e33e1SDouglas Gregor   if (!Dir) {
1379524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1380524e33e1SDouglas Gregor       << DirName;
1381524e33e1SDouglas Gregor     HadError = true;
1382524e33e1SDouglas Gregor     return;
1383524e33e1SDouglas Gregor   }
1384524e33e1SDouglas Gregor 
1385524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1386524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1387524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
1388524e33e1SDouglas Gregor     HadError = true;
1389524e33e1SDouglas Gregor     return;
1390524e33e1SDouglas Gregor   }
1391524e33e1SDouglas Gregor 
1392524e33e1SDouglas Gregor   // Record this umbrella directory.
1393524e33e1SDouglas Gregor   Map.setUmbrellaDir(ActiveModule, Dir);
1394524e33e1SDouglas Gregor }
1395524e33e1SDouglas Gregor 
13962b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
13972b82c2a5SDouglas Gregor ///
13982b82c2a5SDouglas Gregor ///   export-declaration:
13992b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
14002b82c2a5SDouglas Gregor ///
14012b82c2a5SDouglas Gregor ///   wildcard-module-id:
14022b82c2a5SDouglas Gregor ///     identifier
14032b82c2a5SDouglas Gregor ///     '*'
14042b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
14052b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
14062b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
14072b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
14082b82c2a5SDouglas Gregor 
14092b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
14102b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
14112b82c2a5SDouglas Gregor   bool Wildcard = false;
14122b82c2a5SDouglas Gregor   do {
14132b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
14142b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
14152b82c2a5SDouglas Gregor                                               Tok.getLocation()));
14162b82c2a5SDouglas Gregor       consumeToken();
14172b82c2a5SDouglas Gregor 
14182b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
14192b82c2a5SDouglas Gregor         consumeToken();
14202b82c2a5SDouglas Gregor         continue;
14212b82c2a5SDouglas Gregor       }
14222b82c2a5SDouglas Gregor 
14232b82c2a5SDouglas Gregor       break;
14242b82c2a5SDouglas Gregor     }
14252b82c2a5SDouglas Gregor 
14262b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
14272b82c2a5SDouglas Gregor       Wildcard = true;
1428f5eedd05SDouglas Gregor       consumeToken();
14292b82c2a5SDouglas Gregor       break;
14302b82c2a5SDouglas Gregor     }
14312b82c2a5SDouglas Gregor 
14322b82c2a5SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
14332b82c2a5SDouglas Gregor     HadError = true;
14342b82c2a5SDouglas Gregor     return;
14352b82c2a5SDouglas Gregor   } while (true);
14362b82c2a5SDouglas Gregor 
14372b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
14382b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
14392b82c2a5SDouglas Gregor   };
14402b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
14412b82c2a5SDouglas Gregor }
14422b82c2a5SDouglas Gregor 
14439194a91dSDouglas Gregor /// \brief Parse an inferried module declaration (wildcard modules).
14449194a91dSDouglas Gregor ///
14459194a91dSDouglas Gregor ///   module-declaration:
14469194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
14479194a91dSDouglas Gregor ///       { inferred-module-member* }
14489194a91dSDouglas Gregor ///
14499194a91dSDouglas Gregor ///   inferred-module-member:
14509194a91dSDouglas Gregor ///     'export' '*'
14519194a91dSDouglas Gregor ///     'exclude' identifier
14529194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
145373441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
145473441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
145573441091SDouglas Gregor   bool Failed = false;
145673441091SDouglas Gregor 
145773441091SDouglas Gregor   // Inferred modules must be submodules.
14589194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
145973441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
146073441091SDouglas Gregor     Failed = true;
146173441091SDouglas Gregor   }
146273441091SDouglas Gregor 
14639194a91dSDouglas Gregor   if (ActiveModule) {
1464524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
1465524e33e1SDouglas Gregor     if (!Failed && !ActiveModule->getUmbrellaDir()) {
146673441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
146773441091SDouglas Gregor       Failed = true;
146873441091SDouglas Gregor     }
146973441091SDouglas Gregor 
147073441091SDouglas Gregor     // Check for redefinition of an inferred module.
1471dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
147273441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1473dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
1474dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
147573441091SDouglas Gregor                      diag::note_mmap_prev_definition);
147673441091SDouglas Gregor       Failed = true;
147773441091SDouglas Gregor     }
147873441091SDouglas Gregor 
14799194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
14809194a91dSDouglas Gregor     if (Framework) {
14819194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
14829194a91dSDouglas Gregor       Framework = false;
14839194a91dSDouglas Gregor     }
14849194a91dSDouglas Gregor   } else if (Explicit) {
14859194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
14869194a91dSDouglas Gregor     Explicit = false;
14879194a91dSDouglas Gregor   }
14889194a91dSDouglas Gregor 
148973441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
149073441091SDouglas Gregor   if (Failed) {
149173441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
149273441091SDouglas Gregor       consumeToken();
149373441091SDouglas Gregor       skipUntil(MMToken::RBrace);
149473441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
149573441091SDouglas Gregor         consumeToken();
149673441091SDouglas Gregor     }
149773441091SDouglas Gregor     HadError = true;
149873441091SDouglas Gregor     return;
149973441091SDouglas Gregor   }
150073441091SDouglas Gregor 
15019194a91dSDouglas Gregor   // Parse optional attributes.
15024442605fSBill Wendling   Attributes Attrs;
15039194a91dSDouglas Gregor   parseOptionalAttributes(Attrs);
15049194a91dSDouglas Gregor 
15059194a91dSDouglas Gregor   if (ActiveModule) {
150673441091SDouglas Gregor     // Note that we have an inferred submodule.
1507dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
1508dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
1509dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
15109194a91dSDouglas Gregor   } else {
15119194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
15129194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
15139194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
15149194a91dSDouglas Gregor   }
151573441091SDouglas Gregor 
151673441091SDouglas Gregor   // Parse the opening brace.
151773441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
151873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
151973441091SDouglas Gregor     HadError = true;
152073441091SDouglas Gregor     return;
152173441091SDouglas Gregor   }
152273441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
152373441091SDouglas Gregor 
152473441091SDouglas Gregor   // Parse the body of the inferred submodule.
152573441091SDouglas Gregor   bool Done = false;
152673441091SDouglas Gregor   do {
152773441091SDouglas Gregor     switch (Tok.Kind) {
152873441091SDouglas Gregor     case MMToken::EndOfFile:
152973441091SDouglas Gregor     case MMToken::RBrace:
153073441091SDouglas Gregor       Done = true;
153173441091SDouglas Gregor       break;
153273441091SDouglas Gregor 
15339194a91dSDouglas Gregor     case MMToken::ExcludeKeyword: {
15349194a91dSDouglas Gregor       if (ActiveModule) {
15359194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1536162405daSDouglas Gregor           << (ActiveModule != 0);
15379194a91dSDouglas Gregor         consumeToken();
15389194a91dSDouglas Gregor         break;
15399194a91dSDouglas Gregor       }
15409194a91dSDouglas Gregor 
15419194a91dSDouglas Gregor       consumeToken();
15429194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
15439194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
15449194a91dSDouglas Gregor         break;
15459194a91dSDouglas Gregor       }
15469194a91dSDouglas Gregor 
15479194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
15489194a91dSDouglas Gregor         .push_back(Tok.getString());
15499194a91dSDouglas Gregor       consumeToken();
15509194a91dSDouglas Gregor       break;
15519194a91dSDouglas Gregor     }
15529194a91dSDouglas Gregor 
15539194a91dSDouglas Gregor     case MMToken::ExportKeyword:
15549194a91dSDouglas Gregor       if (!ActiveModule) {
15559194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1556162405daSDouglas Gregor           << (ActiveModule != 0);
15579194a91dSDouglas Gregor         consumeToken();
15589194a91dSDouglas Gregor         break;
15599194a91dSDouglas Gregor       }
15609194a91dSDouglas Gregor 
156173441091SDouglas Gregor       consumeToken();
156273441091SDouglas Gregor       if (Tok.is(MMToken::Star))
1563dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
156473441091SDouglas Gregor       else
156573441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
156673441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
156773441091SDouglas Gregor       consumeToken();
156873441091SDouglas Gregor       break;
156973441091SDouglas Gregor 
157073441091SDouglas Gregor     case MMToken::ExplicitKeyword:
157173441091SDouglas Gregor     case MMToken::ModuleKeyword:
157273441091SDouglas Gregor     case MMToken::HeaderKeyword:
157373441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
157473441091SDouglas Gregor     default:
15759194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
1576162405daSDouglas Gregor           << (ActiveModule != 0);
157773441091SDouglas Gregor       consumeToken();
157873441091SDouglas Gregor       break;
157973441091SDouglas Gregor     }
158073441091SDouglas Gregor   } while (!Done);
158173441091SDouglas Gregor 
158273441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
158373441091SDouglas Gregor     consumeToken();
158473441091SDouglas Gregor   else {
158573441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
158673441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
158773441091SDouglas Gregor     HadError = true;
158873441091SDouglas Gregor   }
158973441091SDouglas Gregor }
159073441091SDouglas Gregor 
15919194a91dSDouglas Gregor /// \brief Parse optional attributes.
15929194a91dSDouglas Gregor ///
15939194a91dSDouglas Gregor ///   attributes:
15949194a91dSDouglas Gregor ///     attribute attributes
15959194a91dSDouglas Gregor ///     attribute
15969194a91dSDouglas Gregor ///
15979194a91dSDouglas Gregor ///   attribute:
15989194a91dSDouglas Gregor ///     [ identifier ]
15999194a91dSDouglas Gregor ///
16009194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
16019194a91dSDouglas Gregor ///
16029194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
16034442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
16049194a91dSDouglas Gregor   bool HadError = false;
16059194a91dSDouglas Gregor 
16069194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
16079194a91dSDouglas Gregor     // Consume the '['.
16089194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
16099194a91dSDouglas Gregor 
16109194a91dSDouglas Gregor     // Check whether we have an attribute name here.
16119194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
16129194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
16139194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
16149194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
16159194a91dSDouglas Gregor         consumeToken();
16169194a91dSDouglas Gregor       HadError = true;
16179194a91dSDouglas Gregor     }
16189194a91dSDouglas Gregor 
16199194a91dSDouglas Gregor     // Decode the attribute name.
16209194a91dSDouglas Gregor     AttributeKind Attribute
16219194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
16229194a91dSDouglas Gregor           .Case("system", AT_system)
16239194a91dSDouglas Gregor           .Default(AT_unknown);
16249194a91dSDouglas Gregor     switch (Attribute) {
16259194a91dSDouglas Gregor     case AT_unknown:
16269194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
16279194a91dSDouglas Gregor         << Tok.getString();
16289194a91dSDouglas Gregor       break;
16299194a91dSDouglas Gregor 
16309194a91dSDouglas Gregor     case AT_system:
16319194a91dSDouglas Gregor       Attrs.IsSystem = true;
16329194a91dSDouglas Gregor       break;
16339194a91dSDouglas Gregor     }
16349194a91dSDouglas Gregor     consumeToken();
16359194a91dSDouglas Gregor 
16369194a91dSDouglas Gregor     // Consume the ']'.
16379194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
16389194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
16399194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
16409194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
16419194a91dSDouglas Gregor       HadError = true;
16429194a91dSDouglas Gregor     }
16439194a91dSDouglas Gregor 
16449194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
16459194a91dSDouglas Gregor       consumeToken();
16469194a91dSDouglas Gregor   }
16479194a91dSDouglas Gregor 
16489194a91dSDouglas Gregor   return HadError;
16499194a91dSDouglas Gregor }
16509194a91dSDouglas Gregor 
16517033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence
16527033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null.
16537033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
16547033127bSDouglas Gregor   for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
16557033127bSDouglas Gregor     // If we have an umbrella directory, use that.
16567033127bSDouglas Gregor     if (Mod->hasUmbrellaDir())
16577033127bSDouglas Gregor       return Mod->getUmbrellaDir();
16587033127bSDouglas Gregor 
16597033127bSDouglas Gregor     // If we have a framework directory, stop looking.
16607033127bSDouglas Gregor     if (Mod->IsFramework)
16617033127bSDouglas Gregor       return 0;
16627033127bSDouglas Gregor   }
16637033127bSDouglas Gregor 
16647033127bSDouglas Gregor   return 0;
16657033127bSDouglas Gregor }
16667033127bSDouglas Gregor 
1667718292f2SDouglas Gregor /// \brief Parse a module map file.
1668718292f2SDouglas Gregor ///
1669718292f2SDouglas Gregor ///   module-map-file:
1670718292f2SDouglas Gregor ///     module-declaration*
1671718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
1672718292f2SDouglas Gregor   do {
1673718292f2SDouglas Gregor     switch (Tok.Kind) {
1674718292f2SDouglas Gregor     case MMToken::EndOfFile:
1675718292f2SDouglas Gregor       return HadError;
1676718292f2SDouglas Gregor 
1677e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
1678718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1679755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
1680718292f2SDouglas Gregor       parseModuleDecl();
1681718292f2SDouglas Gregor       break;
1682718292f2SDouglas Gregor 
16831fb5c3a6SDouglas Gregor     case MMToken::Comma:
168459527666SDouglas Gregor     case MMToken::ExcludeKeyword:
16852b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
1686718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
1687718292f2SDouglas Gregor     case MMToken::Identifier:
1688718292f2SDouglas Gregor     case MMToken::LBrace:
1689a686e1b0SDouglas Gregor     case MMToken::LSquare:
16902b82c2a5SDouglas Gregor     case MMToken::Period:
1691718292f2SDouglas Gregor     case MMToken::RBrace:
1692a686e1b0SDouglas Gregor     case MMToken::RSquare:
16931fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
16942b82c2a5SDouglas Gregor     case MMToken::Star:
1695718292f2SDouglas Gregor     case MMToken::StringLiteral:
1696718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
1697718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1698718292f2SDouglas Gregor       HadError = true;
1699718292f2SDouglas Gregor       consumeToken();
1700718292f2SDouglas Gregor       break;
1701718292f2SDouglas Gregor     }
1702718292f2SDouglas Gregor   } while (true);
1703718292f2SDouglas Gregor }
1704718292f2SDouglas Gregor 
1705718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
17064ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
17074ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
17084ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
17094ddf2221SDouglas Gregor     return Known->second;
17104ddf2221SDouglas Gregor 
171189929282SDouglas Gregor   assert(Target != 0 && "Missing target information");
1712718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1713718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1714718292f2SDouglas Gregor   if (!Buffer)
17154ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
1716718292f2SDouglas Gregor 
1717718292f2SDouglas Gregor   // Parse this module map file.
17181fb5c3a6SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
17191fb5c3a6SDouglas Gregor   Diags->getClient()->BeginSourceFile(MMapLangOpts);
1720bc10b9fbSDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
17213ec6663bSDouglas Gregor                          BuiltinIncludeDir);
1722718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
1723718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
17244ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
1725718292f2SDouglas Gregor   return Result;
1726718292f2SDouglas Gregor }
1727