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"
15a7d03840SJordan Rose #include "clang/Basic/CharInfo.h"
16718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
17811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h"
18718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
19718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
20718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
21b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
229acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
233a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
243a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
253a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
263a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
273a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
28718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
29e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h"
30718292f2SDouglas Gregor #include "llvm/Support/Host.h"
31552c169eSRafael Espindola #include "llvm/Support/Path.h"
32718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
3307c22b78SDouglas Gregor #include <stdlib.h>
3401c7cfa2SDouglas Gregor #if defined(LLVM_ON_UNIX)
35eadae014SDmitri Gribenko #include <limits.h>
3601c7cfa2SDouglas Gregor #endif
37718292f2SDouglas Gregor using namespace clang;
38718292f2SDouglas Gregor 
39040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
40040e1266SRichard Smith   switch ((int)Role) {
41040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
42040e1266SRichard Smith   case NormalHeader:
43040e1266SRichard Smith     return Module::HK_Normal;
44040e1266SRichard Smith   case PrivateHeader:
45040e1266SRichard Smith     return Module::HK_Private;
46040e1266SRichard Smith   case TextualHeader:
47040e1266SRichard Smith     return Module::HK_Textual;
48040e1266SRichard Smith   case PrivateHeader | TextualHeader:
49040e1266SRichard Smith     return Module::HK_PrivateTextual;
50040e1266SRichard Smith   }
51040e1266SRichard Smith }
52040e1266SRichard Smith 
53040e1266SRichard Smith ModuleMap::ModuleHeaderRole
54040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
55040e1266SRichard Smith   switch ((int)Kind) {
56040e1266SRichard Smith   case Module::HK_Normal:
57040e1266SRichard Smith     return NormalHeader;
58040e1266SRichard Smith   case Module::HK_Private:
59040e1266SRichard Smith     return PrivateHeader;
60040e1266SRichard Smith   case Module::HK_Textual:
61040e1266SRichard Smith     return TextualHeader;
62040e1266SRichard Smith   case Module::HK_PrivateTextual:
63040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
64040e1266SRichard Smith   case Module::HK_Excluded:
65040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
66040e1266SRichard Smith   }
67040e1266SRichard Smith   llvm_unreachable("unknown header kind");
68040e1266SRichard Smith }
69040e1266SRichard Smith 
702b82c2a5SDouglas Gregor Module::ExportDecl
712b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
722b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
73e4412640SArgyrios Kyrtzidis                          bool Complain) const {
74f5eedd05SDouglas Gregor   // We may have just a wildcard.
75f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
76f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
77d2d442caSCraig Topper     return Module::ExportDecl(nullptr, true);
78f5eedd05SDouglas Gregor   }
79f5eedd05SDouglas Gregor 
80fb912657SDouglas Gregor   // Resolve the module-id.
81fb912657SDouglas Gregor   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
82fb912657SDouglas Gregor   if (!Context)
83fb912657SDouglas Gregor     return Module::ExportDecl();
84fb912657SDouglas Gregor 
85fb912657SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
86fb912657SDouglas Gregor }
87fb912657SDouglas Gregor 
88fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
89fb912657SDouglas Gregor                                    bool Complain) const {
902b82c2a5SDouglas Gregor   // Find the starting module.
91fb912657SDouglas Gregor   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
922b82c2a5SDouglas Gregor   if (!Context) {
932b82c2a5SDouglas Gregor     if (Complain)
940761a8a0SDaniel Jasper       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
95fb912657SDouglas Gregor       << Id[0].first << Mod->getFullModuleName();
962b82c2a5SDouglas Gregor 
97d2d442caSCraig Topper     return nullptr;
982b82c2a5SDouglas Gregor   }
992b82c2a5SDouglas Gregor 
1002b82c2a5SDouglas Gregor   // Dig into the module path.
101fb912657SDouglas Gregor   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
102fb912657SDouglas Gregor     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1032b82c2a5SDouglas Gregor     if (!Sub) {
1042b82c2a5SDouglas Gregor       if (Complain)
1050761a8a0SDaniel Jasper         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
106fb912657SDouglas Gregor         << Id[I].first << Context->getFullModuleName()
107fb912657SDouglas Gregor         << SourceRange(Id[0].second, Id[I-1].second);
1082b82c2a5SDouglas Gregor 
109d2d442caSCraig Topper       return nullptr;
1102b82c2a5SDouglas Gregor     }
1112b82c2a5SDouglas Gregor 
1122b82c2a5SDouglas Gregor     Context = Sub;
1132b82c2a5SDouglas Gregor   }
1142b82c2a5SDouglas Gregor 
115fb912657SDouglas Gregor   return Context;
1162b82c2a5SDouglas Gregor }
1172b82c2a5SDouglas Gregor 
1181d60987fSRichard Smith /// \brief Append to \p Paths the set of paths needed to get to the
1191d60987fSRichard Smith /// subframework in which the given module lives.
1201d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1211d60987fSRichard Smith                                     SmallVectorImpl<char> &Path) {
1221d60987fSRichard Smith   // Collect the framework names from the given module to the top-level module.
1231d60987fSRichard Smith   SmallVector<StringRef, 2> Paths;
1241d60987fSRichard Smith   for (; Mod; Mod = Mod->Parent) {
1251d60987fSRichard Smith     if (Mod->IsFramework)
1261d60987fSRichard Smith       Paths.push_back(Mod->Name);
1271d60987fSRichard Smith   }
1281d60987fSRichard Smith 
1291d60987fSRichard Smith   if (Paths.empty())
1301d60987fSRichard Smith     return;
1311d60987fSRichard Smith 
1321d60987fSRichard Smith   // Add Frameworks/Name.framework for each subframework.
1331d60987fSRichard Smith   for (unsigned I = Paths.size() - 1; I != 0; --I)
1341d60987fSRichard Smith     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1351d60987fSRichard Smith }
1361d60987fSRichard Smith 
1371d60987fSRichard Smith const FileEntry *
138040e1266SRichard Smith ModuleMap::findHeader(Module *M,
139040e1266SRichard Smith                       const Module::UnresolvedHeaderDirective &Header,
1401d60987fSRichard Smith                       SmallVectorImpl<char> &RelativePathName) {
141040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
142040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
143040e1266SRichard Smith     if (!File ||
144040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
145040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
146040e1266SRichard Smith       return nullptr;
147040e1266SRichard Smith     return File;
148040e1266SRichard Smith   };
149040e1266SRichard Smith 
1501d60987fSRichard Smith   if (llvm::sys::path::is_absolute(Header.FileName)) {
1511d60987fSRichard Smith     RelativePathName.clear();
1521d60987fSRichard Smith     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
153040e1266SRichard Smith     return GetFile(Header.FileName);
1541d60987fSRichard Smith   }
1551d60987fSRichard Smith 
1561d60987fSRichard Smith   // Search for the header file within the module's home directory.
1571d60987fSRichard Smith   auto *Directory = M->Directory;
1581d60987fSRichard Smith   SmallString<128> FullPathName(Directory->getName());
1591d60987fSRichard Smith   unsigned FullPathLength = FullPathName.size();
1601d60987fSRichard Smith 
1611d60987fSRichard Smith   if (M->isPartOfFramework()) {
1621d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1631d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
1641d60987fSRichard Smith 
1651d60987fSRichard Smith     // Check whether this file is in the public headers.
1661d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1671d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
168040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
1691d60987fSRichard Smith       return File;
1701d60987fSRichard Smith 
1711d60987fSRichard Smith     // Check whether this file is in the private headers.
1721d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
1731d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
1741d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
1751d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
1761d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
1771d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
1781d60987fSRichard Smith       RelativePathName.clear();
1791d60987fSRichard Smith     else
1801d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
1811d60987fSRichard Smith     FullPathName.resize(FullPathLength);
1821d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
1831d60987fSRichard Smith                             Header.FileName);
1841d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
185040e1266SRichard Smith     return GetFile(FullPathName);
1861d60987fSRichard Smith   }
1871d60987fSRichard Smith 
1881d60987fSRichard Smith   // Lookup for normal headers.
1891d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
1901d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
191040e1266SRichard Smith   return GetFile(FullPathName);
1921d60987fSRichard Smith }
1931d60987fSRichard Smith 
194040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
195040e1266SRichard Smith                               const Module::UnresolvedHeaderDirective &Header) {
196040e1266SRichard Smith   SmallString<128> RelativePathName;
197040e1266SRichard Smith   if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
198040e1266SRichard Smith     if (Header.IsUmbrella) {
199040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
200040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
201040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
202040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
203040e1266SRichard Smith       else
204040e1266SRichard Smith         // Record this umbrella header.
205040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
206040e1266SRichard Smith     } else {
207040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
208040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
209040e1266SRichard Smith         excludeHeader(Mod, H);
210040e1266SRichard Smith       else
211040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
212040e1266SRichard Smith     }
213040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
214040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
215040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
216040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
217040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
218040e1266SRichard Smith   } else {
219040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
220040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
221040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
222040e1266SRichard Smith     // A missing header with stat information doesn't make the module
223040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
224040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
225040e1266SRichard Smith     // preprocessed source.)
226040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
227040e1266SRichard Smith       Mod->markUnavailable();
228040e1266SRichard Smith   }
229040e1266SRichard Smith }
230040e1266SRichard Smith 
231040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
232040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
233040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
234040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
235040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
236040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
237040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
238040e1266SRichard Smith     return false;
2391d60987fSRichard Smith 
2401d60987fSRichard Smith   // This is a system module with a top-level header. This header
2411d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
2421d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
243040e1266SRichard Smith   SmallString<128> Path;
244040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
245040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
246040e1266SRichard Smith   if (!File)
247040e1266SRichard Smith     return false;
248040e1266SRichard Smith 
249040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
250040e1266SRichard Smith   Module::Header H = {Path.str(), File};
251040e1266SRichard Smith   addHeader(Mod, H, Role);
252040e1266SRichard Smith   return true;
2531d60987fSRichard Smith }
2541d60987fSRichard Smith 
2550761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
256b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
257b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
2580761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
259*056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
2600414b857SRichard Smith   MMapLangOpts.LineComment = true;
2610414b857SRichard Smith }
262718292f2SDouglas Gregor 
263718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
26421668754SDavide Italiano   for (auto &M : Modules)
26521668754SDavide Italiano     delete M.getValue();
266718292f2SDouglas Gregor }
267718292f2SDouglas Gregor 
26889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
26989929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
27089929282SDouglas Gregor          "Improper target override");
27189929282SDouglas Gregor   this->Target = &Target;
27289929282SDouglas Gregor }
27389929282SDouglas Gregor 
274056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier.
275056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
276056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
277056396aeSDouglas Gregor   if (Name.empty())
278056396aeSDouglas Gregor     return Name;
279056396aeSDouglas Gregor 
280a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
281056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
282056396aeSDouglas Gregor     // create a buffer with the sanitized name.
283056396aeSDouglas Gregor     Buffer.clear();
284a7d03840SJordan Rose     if (isDigit(Name[0]))
285056396aeSDouglas Gregor       Buffer.push_back('_');
286056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
287056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
288a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
289056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
290056396aeSDouglas Gregor       else
291056396aeSDouglas Gregor         Buffer.push_back('_');
292056396aeSDouglas Gregor     }
293056396aeSDouglas Gregor 
294056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
295056396aeSDouglas Gregor   }
296056396aeSDouglas Gregor 
297056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
298056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
299056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
300056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
301056396aeSDouglas Gregor            .Default(false)) {
302056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
303056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
304056396aeSDouglas Gregor     Buffer.push_back('_');
305056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
306056396aeSDouglas Gregor   }
307056396aeSDouglas Gregor 
308056396aeSDouglas Gregor   return Name;
309056396aeSDouglas Gregor }
310056396aeSDouglas Gregor 
31134d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
31234d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
31334d52749SDouglas Gregor /// headers.
314ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
31534d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
31634d52749SDouglas Gregor            .Case("float.h", true)
31734d52749SDouglas Gregor            .Case("iso646.h", true)
31834d52749SDouglas Gregor            .Case("limits.h", true)
31934d52749SDouglas Gregor            .Case("stdalign.h", true)
32034d52749SDouglas Gregor            .Case("stdarg.h", true)
3213c4b1290SBen Langmuir            .Case("stdatomic.h", true)
32234d52749SDouglas Gregor            .Case("stdbool.h", true)
32334d52749SDouglas Gregor            .Case("stddef.h", true)
32434d52749SDouglas Gregor            .Case("stdint.h", true)
32534d52749SDouglas Gregor            .Case("tgmath.h", true)
32634d52749SDouglas Gregor            .Case("unwind.h", true)
32734d52749SDouglas Gregor            .Default(false);
32834d52749SDouglas Gregor }
32934d52749SDouglas Gregor 
33092669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
33192669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
332040e1266SRichard Smith   resolveHeaderDirectives(File);
33359527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
33447972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
33547972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
336ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3374eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
33892669ee4SDaniel Jasper     return Headers.find(File);
3394eaf0a6cSDaniel Jasper   }
34092669ee4SDaniel Jasper   return Known;
34192669ee4SDaniel Jasper }
34292669ee4SDaniel Jasper 
3434469138eSBen Langmuir ModuleMap::KnownHeader
3444469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
3454469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
34647972afdSRichard Smith   if (UmbrellaDirs.empty())
34747972afdSRichard Smith     return KnownHeader();
34847972afdSRichard Smith 
3494469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
3504469138eSBen Langmuir   assert(Dir && "file in no directory");
3514469138eSBen Langmuir 
3524469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
3534469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
3544469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
3554469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
3564469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
3574469138eSBen Langmuir 
3584469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
3594469138eSBen Langmuir   // an umbrella header.
3604469138eSBen Langmuir   do {
3614469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
3624469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
3634469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
3644469138eSBen Langmuir 
3654469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
3664469138eSBen Langmuir 
3674469138eSBen Langmuir     // Retrieve our parent path.
3684469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
3694469138eSBen Langmuir     if (DirName.empty())
3704469138eSBen Langmuir       break;
3714469138eSBen Langmuir 
3724469138eSBen Langmuir     // Resolve the parent path to a directory entry.
3734469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
3744469138eSBen Langmuir   } while (Dir);
3754469138eSBen Langmuir   return KnownHeader();
3764469138eSBen Langmuir }
3774469138eSBen Langmuir 
37892669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
37992669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
3804eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
38192669ee4SDaniel Jasper #ifndef NDEBUG
3824eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
38392669ee4SDaniel Jasper     // Check for consistency between the module header role
38492669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
38592669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
3862708e520SRichard Smith     bool IsPrivate = false;
3872708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
3884eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
3894eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
3902708e520SRichard Smith     for (auto *Hs : HeaderList)
3912708e520SRichard Smith       IsPrivate |=
3922708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
3933c1a41adSRichard Smith             return H.Entry == IncFileEnt;
3942708e520SRichard Smith           }) != Hs->end();
3954eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
39600bc95ecSRichard Smith   }
39792669ee4SDaniel Jasper #endif
3984eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
39992669ee4SDaniel Jasper }
40092669ee4SDaniel Jasper 
40171e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
40271e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
40371e1a64fSBen Langmuir }
40471e1a64fSBen Langmuir 
40592669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4068d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
40792669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
40892669ee4SDaniel Jasper                                         StringRef Filename,
40992669ee4SDaniel Jasper                                         const FileEntry *File) {
41092669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
41192669ee4SDaniel Jasper   // with no source files.
41271e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
41392669ee4SDaniel Jasper     return;
41492669ee4SDaniel Jasper 
415040e1266SRichard Smith   if (RequestingModule) {
41692669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
417040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
418040e1266SRichard Smith   }
41992669ee4SDaniel Jasper 
42071e1a64fSBen Langmuir   bool Excluded = false;
421d2d442caSCraig Topper   Module *Private = nullptr;
422d2d442caSCraig Topper   Module *NotUsed = nullptr;
42371e1a64fSBen Langmuir 
42471e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
42571e1a64fSBen Langmuir   if (Known != Headers.end()) {
42671e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
42792669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4284eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
42971e1a64fSBen Langmuir         Private = Header.getModule();
43092669ee4SDaniel Jasper         continue;
43192669ee4SDaniel Jasper       }
43292669ee4SDaniel Jasper 
43392669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
43492669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
43592669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4368f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
43771e1a64fSBen Langmuir         NotUsed = Header.getModule();
43892669ee4SDaniel Jasper         continue;
43992669ee4SDaniel Jasper       }
44092669ee4SDaniel Jasper 
44192669ee4SDaniel Jasper       // We have found a module that we can happily use.
44292669ee4SDaniel Jasper       return;
44392669ee4SDaniel Jasper     }
444feb54b6dSRichard Smith 
445feb54b6dSRichard Smith     Excluded = true;
44671e1a64fSBen Langmuir   }
44792669ee4SDaniel Jasper 
44892669ee4SDaniel Jasper   // We have found a header, but it is private.
449d2d442caSCraig Topper   if (Private) {
45011152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
45192669ee4SDaniel Jasper         << Filename;
45292669ee4SDaniel Jasper     return;
45392669ee4SDaniel Jasper   }
45492669ee4SDaniel Jasper 
45592669ee4SDaniel Jasper   // We have found a module, but we don't use it.
456d2d442caSCraig Topper   if (NotUsed) {
45711152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
45892669ee4SDaniel Jasper         << RequestingModule->getFullModuleName() << Filename;
45992669ee4SDaniel Jasper     return;
46092669ee4SDaniel Jasper   }
46192669ee4SDaniel Jasper 
46271e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
46371e1a64fSBen Langmuir     return;
46471e1a64fSBen Langmuir 
46571e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
46671e1a64fSBen Langmuir 
46771e1a64fSBen Langmuir   if (LangOpts.ModulesStrictDeclUse) {
46811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
46971e1a64fSBen Langmuir         << RequestingModule->getFullModuleName() << Filename;
470a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
471a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
472a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
47371e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
47471e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
47571e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
47670a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
47770a7738fSManman Ren         << File->getName();
47871e1a64fSBen Langmuir   }
47992669ee4SDaniel Jasper }
48092669ee4SDaniel Jasper 
481ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
482ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
4838b7c0398SSean Silva   // Prefer available modules.
4848b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
4858b7c0398SSean Silva     return true;
4868b7c0398SSean Silva 
487ec87a50aSRichard Smith   // Prefer a public header over a private header.
488ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
489ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
490ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
491ec87a50aSRichard Smith 
492ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
493ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
494ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
495ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
496ec87a50aSRichard Smith 
497ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
498ec87a50aSRichard Smith   return false;
499ec87a50aSRichard Smith }
500ec87a50aSRichard Smith 
501ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
502ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
503306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
504ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
505306d8920SRichard Smith       return ModuleMap::KnownHeader();
506306d8920SRichard Smith     return R;
507306d8920SRichard Smith   };
508306d8920SRichard Smith 
5094881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5101fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
511202210b3SRichard Smith     ModuleMap::KnownHeader Result;
51297da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5134881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5147e82e019SRichard Smith       // Prefer a header from the source module over all others.
5157e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5162f633e7cSRichard Smith         return MakeResult(H);
5174881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5184881e8b2SSean Silva         Result = H;
51997da9178SDaniel Jasper     }
520306d8920SRichard Smith     return MakeResult(Result);
5211fb5c3a6SDouglas Gregor   }
522ab0c8a84SDouglas Gregor 
523386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
524386bb073SRichard Smith }
525386bb073SRichard Smith 
526386bb073SRichard Smith ModuleMap::KnownHeader
527386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
528386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
529386bb073SRichard Smith 
530f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5314469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5324469138eSBen Langmuir   if (H) {
5334469138eSBen Langmuir     Module *Result = H.getModule();
534930a85ccSDouglas Gregor 
535930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
53673141fa9SDouglas Gregor     // directory.
537930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
53873141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
539930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
540930a85ccSDouglas Gregor 
541930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
5429d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
5439d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
5449d6448b1SBen Langmuir 
545a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
546a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
547a89c5ac4SDouglas Gregor       // the actual header is located.
5489458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
5499458f82dSDouglas Gregor 
5507033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
551a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
552056396aeSDouglas Gregor         SmallString<32> NameBuf;
553056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
5544469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
5559d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5569d6448b1SBen Langmuir                                     Explicit).first;
5579d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
558ffbafa2aSBen Langmuir         Result->IsInferred = true;
559a89c5ac4SDouglas Gregor 
560a89c5ac4SDouglas Gregor         // Associate the module and the directory.
561a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
562a89c5ac4SDouglas Gregor 
563a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
564a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
565930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
566d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
567a89c5ac4SDouglas Gregor       }
568a89c5ac4SDouglas Gregor 
569a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
570056396aeSDouglas Gregor       SmallString<32> NameBuf;
571056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
572056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
5739d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5749d6448b1SBen Langmuir                                   Explicit).first;
5759d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
576ffbafa2aSBen Langmuir       Result->IsInferred = true;
5773c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
578a89c5ac4SDouglas Gregor 
579a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
580a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
581930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
582d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
583a89c5ac4SDouglas Gregor     } else {
584a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
585a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
586a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
587a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
588a89c5ac4SDouglas Gregor     }
589a89c5ac4SDouglas Gregor 
590386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
591386bb073SRichard Smith     Headers[File].push_back(Header);
592386bb073SRichard Smith     return Header;
593a89c5ac4SDouglas Gregor   }
594a89c5ac4SDouglas Gregor 
595b53e5483SLawrence Crowl   return KnownHeader();
596ab0c8a84SDouglas Gregor }
597ab0c8a84SDouglas Gregor 
598386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
599386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
600040e1266SRichard Smith   resolveHeaderDirectives(File);
601386bb073SRichard Smith   auto It = Headers.find(File);
602386bb073SRichard Smith   if (It == Headers.end())
603386bb073SRichard Smith     return None;
604386bb073SRichard Smith   return It->second;
605386bb073SRichard Smith }
606386bb073SRichard Smith 
607e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
608d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
60950996ce1SRichard Smith }
61050996ce1SRichard Smith 
61162bcd925SDmitri Gribenko bool
61262bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
61362bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
614040e1266SRichard Smith   resolveHeaderDirectives(Header);
615e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
61697da9178SDaniel Jasper   if (Known != Headers.end()) {
61797da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
61897da9178SDaniel Jasper              I = Known->second.begin(),
61997da9178SDaniel Jasper              E = Known->second.end();
62097da9178SDaniel Jasper          I != E; ++I) {
621052d95a6SBruno Cardoso Lopes 
622052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
623052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
624052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
625052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
626052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
627052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
628052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
629052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
630052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
631052d95a6SBruno Cardoso Lopes           continue;
63297da9178SDaniel Jasper         return false;
63397da9178SDaniel Jasper       }
634052d95a6SBruno Cardoso Lopes     }
63597da9178SDaniel Jasper     return true;
63697da9178SDaniel Jasper   }
6371fb5c3a6SDouglas Gregor 
6381fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
639f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6401fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
6411fb5c3a6SDouglas Gregor 
64250996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
64350996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
64450996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
64550996ce1SRichard Smith   };
64650996ce1SRichard Smith 
6471fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
6481fb5c3a6SDouglas Gregor   // an umbrella header.
6491fb5c3a6SDouglas Gregor   do {
650e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
6511fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
6521fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
6531fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
65450996ce1SRichard Smith       if (IsUnavailable(Found))
6551fb5c3a6SDouglas Gregor         return true;
6561fb5c3a6SDouglas Gregor 
6571fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
6581fb5c3a6SDouglas Gregor       // directory.
6591fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
6601fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6611fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
6621fb5c3a6SDouglas Gregor 
6631fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
6641fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
6651fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
666056396aeSDouglas Gregor           SmallString<32> NameBuf;
667056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
668056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
669056396aeSDouglas Gregor                              NameBuf);
6701fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
6711fb5c3a6SDouglas Gregor           if (!Found)
6721fb5c3a6SDouglas Gregor             return false;
67350996ce1SRichard Smith           if (IsUnavailable(Found))
6741fb5c3a6SDouglas Gregor             return true;
6751fb5c3a6SDouglas Gregor         }
6761fb5c3a6SDouglas Gregor 
6771fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
678056396aeSDouglas Gregor         SmallString<32> NameBuf;
679056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
680056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
681056396aeSDouglas Gregor                            NameBuf);
6821fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
6831fb5c3a6SDouglas Gregor         if (!Found)
6841fb5c3a6SDouglas Gregor           return false;
6851fb5c3a6SDouglas Gregor       }
6861fb5c3a6SDouglas Gregor 
68750996ce1SRichard Smith       return IsUnavailable(Found);
6881fb5c3a6SDouglas Gregor     }
6891fb5c3a6SDouglas Gregor 
6901fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
6911fb5c3a6SDouglas Gregor 
6921fb5c3a6SDouglas Gregor     // Retrieve our parent path.
6931fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
6941fb5c3a6SDouglas Gregor     if (DirName.empty())
6951fb5c3a6SDouglas Gregor       break;
6961fb5c3a6SDouglas Gregor 
6971fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
6981f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
6991fb5c3a6SDouglas Gregor   } while (Dir);
7001fb5c3a6SDouglas Gregor 
7011fb5c3a6SDouglas Gregor   return false;
7021fb5c3a6SDouglas Gregor }
7031fb5c3a6SDouglas Gregor 
704e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
705e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
70688bdfb0eSDouglas Gregor   if (Known != Modules.end())
70788bdfb0eSDouglas Gregor     return Known->getValue();
70888bdfb0eSDouglas Gregor 
709d2d442caSCraig Topper   return nullptr;
71088bdfb0eSDouglas Gregor }
71188bdfb0eSDouglas Gregor 
712e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
713e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7142b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7152b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7162b82c2a5SDouglas Gregor       return Sub;
7172b82c2a5SDouglas Gregor   }
7182b82c2a5SDouglas Gregor 
7192b82c2a5SDouglas Gregor   return findModule(Name);
7202b82c2a5SDouglas Gregor }
7212b82c2a5SDouglas Gregor 
722e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7232b82c2a5SDouglas Gregor   if (!Context)
7242b82c2a5SDouglas Gregor     return findModule(Name);
7252b82c2a5SDouglas Gregor 
726eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7272b82c2a5SDouglas Gregor }
7282b82c2a5SDouglas Gregor 
7299ffe5a35SDavid Blaikie std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
7309ffe5a35SDavid Blaikie                                                         Module *Parent,
7319ffe5a35SDavid Blaikie                                                         bool IsFramework,
73269021974SDouglas Gregor                                                         bool IsExplicit) {
73369021974SDouglas Gregor   // Try to find an existing module with this name.
734eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
735eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
73669021974SDouglas Gregor 
73769021974SDouglas Gregor   // Create a new module with this name.
7389ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7399ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
7406f722b4eSArgyrios Kyrtzidis   if (!Parent) {
7417e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
7427e82e019SRichard Smith       SourceModule = Result;
74369021974SDouglas Gregor     Modules[Name] = Result;
7446f722b4eSArgyrios Kyrtzidis   }
74569021974SDouglas Gregor   return std::make_pair(Result, true);
74669021974SDouglas Gregor }
74769021974SDouglas Gregor 
748dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
749*056bf77fSRichard Smith   assert(!PendingGlobalModule && "created multiple global modules");
750*056bf77fSRichard Smith   PendingGlobalModule.reset(
751*056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
752*056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
753*056bf77fSRichard Smith   PendingGlobalModule->Kind = Module::GlobalModuleFragment;
754*056bf77fSRichard Smith   return PendingGlobalModule.get();
755dd8b5337SRichard Smith }
756dd8b5337SRichard Smith 
757bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
758dd8b5337SRichard Smith                                                 StringRef Name,
759dd8b5337SRichard Smith                                                 Module *GlobalModule) {
760bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
761bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
762bbcc9f04SRichard Smith 
763bbcc9f04SRichard Smith   auto *Result =
764bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
765bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
766145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
767bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
768bbcc9f04SRichard Smith 
769dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
770*056bf77fSRichard Smith   assert(GlobalModule == PendingGlobalModule.get() &&
771*056bf77fSRichard Smith          "unexpected global module");
772dd8b5337SRichard Smith   GlobalModule->setParent(Result);
773*056bf77fSRichard Smith   PendingGlobalModule.release(); // now owned by parent
774dd8b5337SRichard Smith 
775bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
776bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
777bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
778bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
779bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
780bbcc9f04SRichard Smith 
781bbcc9f04SRichard Smith   return Result;
782bbcc9f04SRichard Smith }
783bbcc9f04SRichard Smith 
78411dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we
78511dfe6feSDouglas Gregor /// should link.
78611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
78711dfe6feSDouglas Gregor                                FileManager &FileMgr) {
78811dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
78911dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
79011dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
79111dfe6feSDouglas Gregor 
79211dfe6feSDouglas Gregor   SmallString<128> LibName;
79311dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
79411dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
7958aaae5a9SJuergen Ributzka 
7968aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
7978aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
7988aaae5a9SJuergen Ributzka   // for both before we give up.
7998013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8008aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
80111dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
80211dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
80311dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8048aaae5a9SJuergen Ributzka       return;
8058aaae5a9SJuergen Ributzka     }
80611dfe6feSDouglas Gregor   }
80711dfe6feSDouglas Gregor }
80811dfe6feSDouglas Gregor 
809a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
810a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
811c1d88ea5SBen Langmuir   Attributes Attrs;
812c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
813a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
814c1d88ea5SBen Langmuir }
815c1d88ea5SBen Langmuir 
816a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
817c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
818a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
819a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
820a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
821a525400dSBen Langmuir   // top-level framework.
822a525400dSBen Langmuir   StringRef FrameworkDirName =
823a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
824a525400dSBen Langmuir 
825a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
826a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
827a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
828a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
829a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
830a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
831c1d88ea5SBen Langmuir 
83256c64013SDouglas Gregor   // Check whether we've already found this module.
833e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
834e89dbc1dSDouglas Gregor     return Mod;
835e89dbc1dSDouglas Gregor 
8361f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
83756c64013SDouglas Gregor 
8389194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
8399194a91dSDouglas Gregor   // a framework module, do so.
840beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
8419194a91dSDouglas Gregor   if (!Parent) {
8424ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
8439194a91dSDouglas Gregor     bool canInfer = false;
8444ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
8459194a91dSDouglas Gregor       // Figure out the parent path.
8464ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
8479194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
8489194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
8499194a91dSDouglas Gregor         // for a module map.
850e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
8519194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
8529194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
8539194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
8549194a91dSDouglas Gregor           // one.
855984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
856984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
857984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
858c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
8599194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
8609194a91dSDouglas Gregor           }
8619194a91dSDouglas Gregor 
8629194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
8639194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
8649194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
8659194a91dSDouglas Gregor         }
8669194a91dSDouglas Gregor 
8679194a91dSDouglas Gregor         if (inferred->second.InferModules) {
8689194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
8699194a91dSDouglas Gregor           // to infer this particular module.
8704ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
8719194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
8729194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
8739194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
8749194a91dSDouglas Gregor 
875c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
876c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
877c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
878ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
879ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
880beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
8819194a91dSDouglas Gregor         }
8829194a91dSDouglas Gregor       }
8839194a91dSDouglas Gregor     }
8849194a91dSDouglas Gregor 
8859194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
8869194a91dSDouglas Gregor     if (!canInfer)
887d2d442caSCraig Topper       return nullptr;
888beee15e7SBen Langmuir   } else
8899d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
8909194a91dSDouglas Gregor 
8919194a91dSDouglas Gregor 
89256c64013SDouglas Gregor   // Look for an umbrella header.
8932c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
89417381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
895e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
89656c64013SDouglas Gregor 
89756c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
89856c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
89956c64013SDouglas Gregor   // idea.
90056c64013SDouglas Gregor   if (!UmbrellaHeader)
901d2d442caSCraig Topper     return nullptr;
90256c64013SDouglas Gregor 
9039d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
904a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
905a7e2cc68SRichard Smith                               NumCreatedModules++);
9069d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
9079d6448b1SBen Langmuir   Result->IsInferred = true;
9087e82e019SRichard Smith   if (!Parent) {
9097e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
910ba7f2f71SDaniel Jasper       SourceModule = Result;
9117e82e019SRichard Smith     Modules[ModuleName] = Result;
912ba7f2f71SDaniel Jasper   }
913c1d88ea5SBen Langmuir 
914c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
915c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
916c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
917ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
9182b63d15fSRichard Smith   Result->Directory = FrameworkDir;
919a686e1b0SDouglas Gregor 
920322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
9212b63d15fSRichard Smith   //
9222b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
9232b63d15fSRichard Smith   // a framework module.
9242b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
925d8bd7537SDouglas Gregor 
926d8bd7537SDouglas Gregor   // export *
927d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
928d8bd7537SDouglas Gregor 
929a89c5ac4SDouglas Gregor   // module * { export * }
930a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
931a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
932a89c5ac4SDouglas Gregor 
933e89dbc1dSDouglas Gregor   // Look for subframeworks.
934c080917eSRafael Espindola   std::error_code EC;
9352c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
936ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
937e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
9382d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
939b171a59bSBruno Cardoso Lopes   vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
940b171a59bSBruno Cardoso Lopes   for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
941b171a59bSBruno Cardoso Lopes                                DirEnd;
942e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
943b171a59bSBruno Cardoso Lopes     if (!StringRef(Dir->getName()).endswith(".framework"))
944e89dbc1dSDouglas Gregor       continue;
945f2161a70SDouglas Gregor 
946b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
947b171a59bSBruno Cardoso Lopes             FileMgr.getDirectory(Dir->getName())) {
94807c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
94907c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
95007c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
95107c22b78SDouglas Gregor       // out to a top-level framework.
952e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
95307c22b78SDouglas Gregor       bool FoundParent = false;
95407c22b78SDouglas Gregor       do {
95507c22b78SDouglas Gregor         // Get the parent directory name.
95607c22b78SDouglas Gregor         SubframeworkDirName
95707c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
95807c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
95907c22b78SDouglas Gregor           break;
96007c22b78SDouglas Gregor 
96107c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
96207c22b78SDouglas Gregor           FoundParent = true;
96307c22b78SDouglas Gregor           break;
96407c22b78SDouglas Gregor         }
96507c22b78SDouglas Gregor       } while (true);
96607c22b78SDouglas Gregor 
96707c22b78SDouglas Gregor       if (!FoundParent)
96807c22b78SDouglas Gregor         continue;
96907c22b78SDouglas Gregor 
970e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
971a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
972e89dbc1dSDouglas Gregor     }
973e89dbc1dSDouglas Gregor   }
974e89dbc1dSDouglas Gregor 
97511dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
97611dfe6feSDouglas Gregor   // framework.
97711dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
97811dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
97911dfe6feSDouglas Gregor   }
98011dfe6feSDouglas Gregor 
98156c64013SDouglas Gregor   return Result;
98256c64013SDouglas Gregor }
98356c64013SDouglas Gregor 
9842b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
9852b63d15fSRichard Smith                                   Twine NameAsWritten) {
98697da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
98773141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
9882b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
9897033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
990b3a0fa48SBruno Cardoso Lopes 
991b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
992b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
993b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
994a89c5ac4SDouglas Gregor }
995a89c5ac4SDouglas Gregor 
9962b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
9972b63d15fSRichard Smith                                Twine NameAsWritten) {
998524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
9992b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1000524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1001524e33e1SDouglas Gregor }
1002524e33e1SDouglas Gregor 
1003040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
1004040e1266SRichard Smith                                     Module::UnresolvedHeaderDirective Header) {
1005040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1006040e1266SRichard Smith   // wrap the system header.
1007040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1008040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1009040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1010040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1011040e1266SRichard Smith     // case.
1012040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1013040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1014040e1266SRichard Smith     Header.HasBuiltinHeader = true;
10153c1a41adSRichard Smith   }
1016040e1266SRichard Smith 
1017040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1018040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1019040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1020040e1266SRichard Smith   // headers.
1021040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1022040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1023040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1024040e1266SRichard Smith     // use the mtime as the key.
1025040e1266SRichard Smith     if (Header.ModTime)
1026040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1027040e1266SRichard Smith     else
1028040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1029040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1030040e1266SRichard Smith     return;
1031040e1266SRichard Smith   }
1032040e1266SRichard Smith 
1033040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1034040e1266SRichard Smith   // Perform the lookup now.
1035040e1266SRichard Smith   resolveHeader(Mod, Header);
1036040e1266SRichard Smith }
1037040e1266SRichard Smith 
1038040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1039040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1040040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1041040e1266SRichard Smith     for (auto *M : BySize->second)
1042040e1266SRichard Smith       resolveHeaderDirectives(M);
1043040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1044040e1266SRichard Smith   }
1045040e1266SRichard Smith 
1046040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1047040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1048040e1266SRichard Smith     for (auto *M : ByModTime->second)
1049040e1266SRichard Smith       resolveHeaderDirectives(M);
1050040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1051040e1266SRichard Smith   }
1052040e1266SRichard Smith }
1053040e1266SRichard Smith 
1054040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
1055040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1056040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1057040e1266SRichard Smith     // the header information for this file.
1058040e1266SRichard Smith     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header);
1059040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
10600e98d938SNAKAMURA Takumi }
1061202210b3SRichard Smith 
10623c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1063d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1064386bb073SRichard Smith   KnownHeader KH(Mod, Role);
10653c1a41adSRichard Smith 
1066386bb073SRichard Smith   // Only add each header to the headers list once.
1067386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1068386bb073SRichard Smith   // same module definition?
1069386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1070386bb073SRichard Smith   for (auto H : HeaderList)
1071386bb073SRichard Smith     if (H == KH)
1072386bb073SRichard Smith       return;
1073386bb073SRichard Smith 
1074386bb073SRichard Smith   HeaderList.push_back(KH);
10751ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1076386bb073SRichard Smith 
10777e82e019SRichard Smith   bool isCompilingModuleHeader =
1078bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1079d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1080d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1081d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1082d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1083d8879c85SRichard Smith                                     isCompilingModuleHeader);
1084d8879c85SRichard Smith   }
1085e62cfd7cSBruno Cardoso Lopes 
1086e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1087e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1088f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1089a89c5ac4SDouglas Gregor }
1090a89c5ac4SDouglas Gregor 
10913c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1092feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1093feb54b6dSRichard Smith   // umbrella directory module.
1094feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1095feb54b6dSRichard Smith   // specified module?
10963c1a41adSRichard Smith   (void) Headers[Header.Entry];
10973c1a41adSRichard Smith 
10983c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1099feb54b6dSRichard Smith }
1100feb54b6dSRichard Smith 
1101514b636aSDouglas Gregor const FileEntry *
11024b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
11031f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1104d2d442caSCraig Topper     return nullptr;
1105514b636aSDouglas Gregor 
11061f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
11071f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1108514b636aSDouglas Gregor }
1109514b636aSDouglas Gregor 
11104b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
11119d6448b1SBen Langmuir   if (M->IsInferred) {
11129d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
11139d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
11149d6448b1SBen Langmuir   }
11159d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
11169d6448b1SBen Langmuir }
11179d6448b1SBen Langmuir 
11189d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
11199d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
11209d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
11219d6448b1SBen Langmuir }
11229d6448b1SBen Langmuir 
1123cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1124718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1125718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1126718292f2SDouglas Gregor                                         MEnd = Modules.end();
1127718292f2SDouglas Gregor        M != MEnd; ++M)
1128d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1129718292f2SDouglas Gregor 
1130718292f2SDouglas Gregor   llvm::errs() << "Headers:";
113159527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1132718292f2SDouglas Gregor        H != HEnd; ++H) {
113397da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
113497da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
113597da9178SDaniel Jasper                                                       E = H->second.end();
113697da9178SDaniel Jasper          I != E; ++I) {
113797da9178SDaniel Jasper       if (I != H->second.begin())
113897da9178SDaniel Jasper         llvm::errs() << ",";
113997da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
114097da9178SDaniel Jasper     }
114197da9178SDaniel Jasper     llvm::errs() << "\n";
1142718292f2SDouglas Gregor   }
1143718292f2SDouglas Gregor }
1144718292f2SDouglas Gregor 
11452b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
114642413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
114742413141SRichard Smith   Mod->UnresolvedExports.clear();
114842413141SRichard Smith   for (auto &UE : Unresolved) {
114942413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1150f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
11512b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
11522b82c2a5SDouglas Gregor     else
115342413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
11542b82c2a5SDouglas Gregor   }
115542413141SRichard Smith   return !Mod->UnresolvedExports.empty();
11562b82c2a5SDouglas Gregor }
11572b82c2a5SDouglas Gregor 
1158ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
115942413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
116042413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
116142413141SRichard Smith   for (auto &UDU : Unresolved) {
116242413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1163ba7f2f71SDaniel Jasper     if (DirectUse)
1164ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1165ba7f2f71SDaniel Jasper     else
116642413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1167ba7f2f71SDaniel Jasper   }
116842413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1169ba7f2f71SDaniel Jasper }
1170ba7f2f71SDaniel Jasper 
1171fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
117242413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
117342413141SRichard Smith   Mod->UnresolvedConflicts.clear();
117442413141SRichard Smith   for (auto &UC : Unresolved) {
117542413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1176fb912657SDouglas Gregor       Module::Conflict Conflict;
1177fb912657SDouglas Gregor       Conflict.Other = OtherMod;
117842413141SRichard Smith       Conflict.Message = UC.Message;
1179fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
118042413141SRichard Smith     } else
118142413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1182fb912657SDouglas Gregor   }
118342413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1184fb912657SDouglas Gregor }
1185fb912657SDouglas Gregor 
1186718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1187718292f2SDouglas Gregor // Module map file parser
1188718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1189718292f2SDouglas Gregor 
1190718292f2SDouglas Gregor namespace clang {
1191718292f2SDouglas Gregor   /// \brief A token in a module map file.
1192718292f2SDouglas Gregor   struct MMToken {
1193718292f2SDouglas Gregor     enum TokenKind {
11941fb5c3a6SDouglas Gregor       Comma,
119535b13eceSDouglas Gregor       ConfigMacros,
1196fb912657SDouglas Gregor       Conflict,
1197718292f2SDouglas Gregor       EndOfFile,
1198718292f2SDouglas Gregor       HeaderKeyword,
1199718292f2SDouglas Gregor       Identifier,
1200a3feee2aSRichard Smith       Exclaim,
120159527666SDouglas Gregor       ExcludeKeyword,
1202718292f2SDouglas Gregor       ExplicitKeyword,
12032b82c2a5SDouglas Gregor       ExportKeyword,
120497292843SDaniel Jasper       ExternKeyword,
1205755b2055SDouglas Gregor       FrameworkKeyword,
12066ddfca91SDouglas Gregor       LinkKeyword,
1207718292f2SDouglas Gregor       ModuleKeyword,
12082b82c2a5SDouglas Gregor       Period,
1209b53e5483SLawrence Crowl       PrivateKeyword,
1210718292f2SDouglas Gregor       UmbrellaKeyword,
1211ba7f2f71SDaniel Jasper       UseKeyword,
12121fb5c3a6SDouglas Gregor       RequiresKeyword,
12132b82c2a5SDouglas Gregor       Star,
1214718292f2SDouglas Gregor       StringLiteral,
1215040e1266SRichard Smith       IntegerLiteral,
1216306d8920SRichard Smith       TextualKeyword,
1217718292f2SDouglas Gregor       LBrace,
1218a686e1b0SDouglas Gregor       RBrace,
1219a686e1b0SDouglas Gregor       LSquare,
1220a686e1b0SDouglas Gregor       RSquare
1221718292f2SDouglas Gregor     } Kind;
1222718292f2SDouglas Gregor 
1223718292f2SDouglas Gregor     unsigned Location;
1224718292f2SDouglas Gregor     unsigned StringLength;
1225040e1266SRichard Smith     union {
1226040e1266SRichard Smith       // If Kind != IntegerLiteral.
1227718292f2SDouglas Gregor       const char *StringData;
1228040e1266SRichard Smith       // If Kind == IntegerLiteral.
1229040e1266SRichard Smith       uint64_t IntegerValue;
1230040e1266SRichard Smith     };
1231718292f2SDouglas Gregor 
1232718292f2SDouglas Gregor     void clear() {
1233718292f2SDouglas Gregor       Kind = EndOfFile;
1234718292f2SDouglas Gregor       Location = 0;
1235718292f2SDouglas Gregor       StringLength = 0;
1236d2d442caSCraig Topper       StringData = nullptr;
1237718292f2SDouglas Gregor     }
1238718292f2SDouglas Gregor 
1239718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1240718292f2SDouglas Gregor 
1241718292f2SDouglas Gregor     SourceLocation getLocation() const {
1242718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1243718292f2SDouglas Gregor     }
1244718292f2SDouglas Gregor 
1245040e1266SRichard Smith     uint64_t getInteger() const {
1246040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1247040e1266SRichard Smith     }
1248040e1266SRichard Smith 
1249718292f2SDouglas Gregor     StringRef getString() const {
1250040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1251040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1252718292f2SDouglas Gregor     }
1253718292f2SDouglas Gregor   };
1254718292f2SDouglas Gregor 
1255718292f2SDouglas Gregor   class ModuleMapParser {
1256718292f2SDouglas Gregor     Lexer &L;
1257718292f2SDouglas Gregor     SourceManager &SourceMgr;
1258bc10b9fbSDouglas Gregor 
1259bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
1260bc10b9fbSDouglas Gregor     /// parsing.
1261bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1262bc10b9fbSDouglas Gregor 
1263718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1264718292f2SDouglas Gregor     ModuleMap &Map;
1265718292f2SDouglas Gregor 
1266beee15e7SBen Langmuir     /// \brief The current module map file.
1267beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1268beee15e7SBen Langmuir 
12699acb99e3SRichard Smith     /// \brief The directory that file names in this module map file should
12709acb99e3SRichard Smith     /// be resolved relative to.
12715257fc63SDouglas Gregor     const DirectoryEntry *Directory;
12725257fc63SDouglas Gregor 
1273963c5535SDouglas Gregor     /// \brief Whether this module map is in a system header directory.
1274963c5535SDouglas Gregor     bool IsSystem;
1275963c5535SDouglas Gregor 
1276718292f2SDouglas Gregor     /// \brief Whether an error occurred.
1277718292f2SDouglas Gregor     bool HadError;
1278718292f2SDouglas Gregor 
1279718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
1280718292f2SDouglas Gregor     /// during parsing.
1281718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1282718292f2SDouglas Gregor 
1283718292f2SDouglas Gregor     /// \brief The current token.
1284718292f2SDouglas Gregor     MMToken Tok;
1285718292f2SDouglas Gregor 
1286718292f2SDouglas Gregor     /// \brief The active module.
1287de3ef502SDouglas Gregor     Module *ActiveModule;
1288718292f2SDouglas Gregor 
12897ff29148SBen Langmuir     /// \brief Whether a module uses the 'requires excluded' hack to mark its
12907ff29148SBen Langmuir     /// contents as 'textual'.
12917ff29148SBen Langmuir     ///
12927ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
12937ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
12947ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
12957ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
12967ff29148SBen Langmuir     /// 'textual' to match the original intent.
12977ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
12987ff29148SBen Langmuir 
1299718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
1300718292f2SDouglas Gregor     SourceLocation consumeToken();
1301718292f2SDouglas Gregor 
1302718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
1303718292f2SDouglas Gregor     /// (or the end of the file).
1304718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1305718292f2SDouglas Gregor 
1306f857950dSDmitri Gribenko     typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
1307e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1308718292f2SDouglas Gregor     void parseModuleDecl();
130997292843SDaniel Jasper     void parseExternModuleDecl();
13101fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1311b53e5483SLawrence Crowl     void parseHeaderDecl(clang::MMToken::TokenKind,
1312b53e5483SLawrence Crowl                          SourceLocation LeadingLoc);
1313524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
13142b82c2a5SDouglas Gregor     void parseExportDecl();
1315ba7f2f71SDaniel Jasper     void parseUseDecl();
13166ddfca91SDouglas Gregor     void parseLinkDecl();
131735b13eceSDouglas Gregor     void parseConfigMacros();
1318fb912657SDouglas Gregor     void parseConflict();
13199194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1320c1d88ea5SBen Langmuir 
1321c1d88ea5SBen Langmuir     typedef ModuleMap::Attributes Attributes;
13224442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1323718292f2SDouglas Gregor 
1324718292f2SDouglas Gregor   public:
1325718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
1326bc10b9fbSDouglas Gregor                              const TargetInfo *Target,
1327718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
13285257fc63SDouglas Gregor                              ModuleMap &Map,
1329beee15e7SBen Langmuir                              const FileEntry *ModuleMapFile,
13303ec6663bSDouglas Gregor                              const DirectoryEntry *Directory,
1331963c5535SDouglas Gregor                              bool IsSystem)
1332bc10b9fbSDouglas Gregor       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1333beee15e7SBen Langmuir         ModuleMapFile(ModuleMapFile), Directory(Directory),
13341d60987fSRichard Smith         IsSystem(IsSystem), HadError(false), ActiveModule(nullptr)
1335718292f2SDouglas Gregor     {
1336718292f2SDouglas Gregor       Tok.clear();
1337718292f2SDouglas Gregor       consumeToken();
1338718292f2SDouglas Gregor     }
1339718292f2SDouglas Gregor 
1340718292f2SDouglas Gregor     bool parseModuleMapFile();
13418128f332SRichard Smith 
13428128f332SRichard Smith     bool terminatedByDirective() { return false; }
13438128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1344718292f2SDouglas Gregor   };
1345ab9db510SAlexander Kornienko }
1346718292f2SDouglas Gregor 
1347718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1348718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1349718292f2SDouglas Gregor 
13508128f332SRichard Smith retry:
13518128f332SRichard Smith   Tok.clear();
1352718292f2SDouglas Gregor   Token LToken;
1353718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1354718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1355718292f2SDouglas Gregor   switch (LToken.getKind()) {
13562d57cea2SAlp Toker   case tok::raw_identifier: {
13572d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
13582d57cea2SAlp Toker     Tok.StringData = RI.data();
13592d57cea2SAlp Toker     Tok.StringLength = RI.size();
13602d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
136135b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1362fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
136359527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1364718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
13652b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
136697292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1367755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
136835b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
13696ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1370718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1371b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
13721fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1373306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1374718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1375ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1376718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1377718292f2SDouglas Gregor     break;
13782d57cea2SAlp Toker   }
1379718292f2SDouglas Gregor 
13801fb5c3a6SDouglas Gregor   case tok::comma:
13811fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
13821fb5c3a6SDouglas Gregor     break;
13831fb5c3a6SDouglas Gregor 
1384718292f2SDouglas Gregor   case tok::eof:
1385718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1386718292f2SDouglas Gregor     break;
1387718292f2SDouglas Gregor 
1388718292f2SDouglas Gregor   case tok::l_brace:
1389718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1390718292f2SDouglas Gregor     break;
1391718292f2SDouglas Gregor 
1392a686e1b0SDouglas Gregor   case tok::l_square:
1393a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1394a686e1b0SDouglas Gregor     break;
1395a686e1b0SDouglas Gregor 
13962b82c2a5SDouglas Gregor   case tok::period:
13972b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
13982b82c2a5SDouglas Gregor     break;
13992b82c2a5SDouglas Gregor 
1400718292f2SDouglas Gregor   case tok::r_brace:
1401718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1402718292f2SDouglas Gregor     break;
1403718292f2SDouglas Gregor 
1404a686e1b0SDouglas Gregor   case tok::r_square:
1405a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1406a686e1b0SDouglas Gregor     break;
1407a686e1b0SDouglas Gregor 
14082b82c2a5SDouglas Gregor   case tok::star:
14092b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
14102b82c2a5SDouglas Gregor     break;
14112b82c2a5SDouglas Gregor 
1412a3feee2aSRichard Smith   case tok::exclaim:
1413a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1414a3feee2aSRichard Smith     break;
1415a3feee2aSRichard Smith 
1416718292f2SDouglas Gregor   case tok::string_literal: {
1417d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1418d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1419d67aea28SRichard Smith       HadError = true;
1420d67aea28SRichard Smith       goto retry;
1421d67aea28SRichard Smith     }
1422d67aea28SRichard Smith 
1423718292f2SDouglas Gregor     // Parse the string literal.
1424718292f2SDouglas Gregor     LangOptions LangOpts;
14259d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1426718292f2SDouglas Gregor     if (StringLiteral.hadError)
1427718292f2SDouglas Gregor       goto retry;
1428718292f2SDouglas Gregor 
1429718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1430718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1431718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1432718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1433718292f2SDouglas Gregor     Saved[Length] = 0;
1434718292f2SDouglas Gregor 
1435718292f2SDouglas Gregor     // Form the token.
1436718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1437718292f2SDouglas Gregor     Tok.StringData = Saved;
1438718292f2SDouglas Gregor     Tok.StringLength = Length;
1439718292f2SDouglas Gregor     break;
1440718292f2SDouglas Gregor   }
1441718292f2SDouglas Gregor 
1442040e1266SRichard Smith   case tok::numeric_constant: {
1443040e1266SRichard Smith     // We don't support any suffixes or other complications.
1444040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1445040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1446040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1447040e1266SRichard Smith     unsigned Length =
1448040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1449040e1266SRichard Smith     uint64_t Value;
1450040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1451040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1452040e1266SRichard Smith       HadError = true;
1453040e1266SRichard Smith       goto retry;
1454040e1266SRichard Smith     }
1455040e1266SRichard Smith 
1456040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1457040e1266SRichard Smith     Tok.IntegerValue = Value;
1458040e1266SRichard Smith     break;
1459040e1266SRichard Smith   }
1460040e1266SRichard Smith 
1461718292f2SDouglas Gregor   case tok::comment:
1462718292f2SDouglas Gregor     goto retry;
1463718292f2SDouglas Gregor 
14648128f332SRichard Smith   case tok::hash:
14658128f332SRichard Smith     // A module map can be terminated prematurely by
14668128f332SRichard Smith     //   #pragma clang module contents
14678128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
14688128f332SRichard Smith     // contents of the module.
14698128f332SRichard Smith     {
14708128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
14718128f332SRichard Smith         L.LexFromRawLexer(LToken);
14728128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
14738128f332SRichard Smith                LToken.getRawIdentifier() == Str;
14748128f332SRichard Smith       };
14758128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
14768128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
14778128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
14788128f332SRichard Smith         break;
14798128f332SRichard Smith       }
14808128f332SRichard Smith     }
14818128f332SRichard Smith     LLVM_FALLTHROUGH;
14828128f332SRichard Smith 
1483718292f2SDouglas Gregor   default:
14848128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1485718292f2SDouglas Gregor     HadError = true;
1486718292f2SDouglas Gregor     goto retry;
1487718292f2SDouglas Gregor   }
1488718292f2SDouglas Gregor 
1489718292f2SDouglas Gregor   return Result;
1490718292f2SDouglas Gregor }
1491718292f2SDouglas Gregor 
1492718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1493718292f2SDouglas Gregor   unsigned braceDepth = 0;
1494a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1495718292f2SDouglas Gregor   do {
1496718292f2SDouglas Gregor     switch (Tok.Kind) {
1497718292f2SDouglas Gregor     case MMToken::EndOfFile:
1498718292f2SDouglas Gregor       return;
1499718292f2SDouglas Gregor 
1500718292f2SDouglas Gregor     case MMToken::LBrace:
1501a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1502718292f2SDouglas Gregor         return;
1503718292f2SDouglas Gregor 
1504718292f2SDouglas Gregor       ++braceDepth;
1505718292f2SDouglas Gregor       break;
1506718292f2SDouglas Gregor 
1507a686e1b0SDouglas Gregor     case MMToken::LSquare:
1508a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1509a686e1b0SDouglas Gregor         return;
1510a686e1b0SDouglas Gregor 
1511a686e1b0SDouglas Gregor       ++squareDepth;
1512a686e1b0SDouglas Gregor       break;
1513a686e1b0SDouglas Gregor 
1514718292f2SDouglas Gregor     case MMToken::RBrace:
1515718292f2SDouglas Gregor       if (braceDepth > 0)
1516718292f2SDouglas Gregor         --braceDepth;
1517718292f2SDouglas Gregor       else if (Tok.is(K))
1518718292f2SDouglas Gregor         return;
1519718292f2SDouglas Gregor       break;
1520718292f2SDouglas Gregor 
1521a686e1b0SDouglas Gregor     case MMToken::RSquare:
1522a686e1b0SDouglas Gregor       if (squareDepth > 0)
1523a686e1b0SDouglas Gregor         --squareDepth;
1524a686e1b0SDouglas Gregor       else if (Tok.is(K))
1525a686e1b0SDouglas Gregor         return;
1526a686e1b0SDouglas Gregor       break;
1527a686e1b0SDouglas Gregor 
1528718292f2SDouglas Gregor     default:
1529a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1530718292f2SDouglas Gregor         return;
1531718292f2SDouglas Gregor       break;
1532718292f2SDouglas Gregor     }
1533718292f2SDouglas Gregor 
1534718292f2SDouglas Gregor    consumeToken();
1535718292f2SDouglas Gregor   } while (true);
1536718292f2SDouglas Gregor }
1537718292f2SDouglas Gregor 
1538e7ab3669SDouglas Gregor /// \brief Parse a module-id.
1539e7ab3669SDouglas Gregor ///
1540e7ab3669SDouglas Gregor ///   module-id:
1541e7ab3669SDouglas Gregor ///     identifier
1542e7ab3669SDouglas Gregor ///     identifier '.' module-id
1543e7ab3669SDouglas Gregor ///
1544e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1545e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1546e7ab3669SDouglas Gregor   Id.clear();
1547e7ab3669SDouglas Gregor   do {
15483cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1549e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1550e7ab3669SDouglas Gregor       consumeToken();
1551e7ab3669SDouglas Gregor     } else {
1552e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1553e7ab3669SDouglas Gregor       return true;
1554e7ab3669SDouglas Gregor     }
1555e7ab3669SDouglas Gregor 
1556e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1557e7ab3669SDouglas Gregor       break;
1558e7ab3669SDouglas Gregor 
1559e7ab3669SDouglas Gregor     consumeToken();
1560e7ab3669SDouglas Gregor   } while (true);
1561e7ab3669SDouglas Gregor 
1562e7ab3669SDouglas Gregor   return false;
1563e7ab3669SDouglas Gregor }
1564e7ab3669SDouglas Gregor 
1565a686e1b0SDouglas Gregor namespace {
1566a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
1567a686e1b0SDouglas Gregor   enum AttributeKind {
1568a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
1569a686e1b0SDouglas Gregor     AT_unknown,
1570a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
157135b13eceSDouglas Gregor     AT_system,
157277944868SRichard Smith     /// \brief The 'extern_c' attribute.
157377944868SRichard Smith     AT_extern_c,
157435b13eceSDouglas Gregor     /// \brief The 'exhaustive' attribute.
1575ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1576ed84df00SBruno Cardoso Lopes     /// \brief The 'no_undeclared_includes' attribute.
1577ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1578a686e1b0SDouglas Gregor   };
1579ab9db510SAlexander Kornienko }
1580a686e1b0SDouglas Gregor 
1581718292f2SDouglas Gregor /// \brief Parse a module declaration.
1582718292f2SDouglas Gregor ///
1583718292f2SDouglas Gregor ///   module-declaration:
158497292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1585a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1586a686e1b0SDouglas Gregor ///       { module-member* }
1587a686e1b0SDouglas Gregor ///
1588718292f2SDouglas Gregor ///   module-member:
15891fb5c3a6SDouglas Gregor ///     requires-declaration
1590718292f2SDouglas Gregor ///     header-declaration
1591e7ab3669SDouglas Gregor ///     submodule-declaration
15922b82c2a5SDouglas Gregor ///     export-declaration
15936ddfca91SDouglas Gregor ///     link-declaration
159473441091SDouglas Gregor ///
159573441091SDouglas Gregor ///   submodule-declaration:
159673441091SDouglas Gregor ///     module-declaration
159773441091SDouglas Gregor ///     inferred-submodule-declaration
1598718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1599755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
160097292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
160197292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
160297292843SDaniel Jasper     parseExternModuleDecl();
160397292843SDaniel Jasper     return;
160497292843SDaniel Jasper   }
160597292843SDaniel Jasper 
1606f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1607e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
1608718292f2SDouglas Gregor   bool Explicit = false;
1609f2161a70SDouglas Gregor   bool Framework = false;
1610755b2055SDouglas Gregor 
1611f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1612f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1613e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1614f2161a70SDouglas Gregor     Explicit = true;
1615f2161a70SDouglas Gregor   }
1616f2161a70SDouglas Gregor 
1617f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1618755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
1619755b2055SDouglas Gregor     consumeToken();
1620755b2055SDouglas Gregor     Framework = true;
1621755b2055SDouglas Gregor   }
1622718292f2SDouglas Gregor 
1623718292f2SDouglas Gregor   // Parse 'module' keyword.
1624718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1625d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1626718292f2SDouglas Gregor     consumeToken();
1627718292f2SDouglas Gregor     HadError = true;
1628718292f2SDouglas Gregor     return;
1629718292f2SDouglas Gregor   }
1630718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
1631718292f2SDouglas Gregor 
163273441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
163373441091SDouglas Gregor   // Parse it.
163473441091SDouglas Gregor   if (Tok.is(MMToken::Star))
16359194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
163673441091SDouglas Gregor 
1637718292f2SDouglas Gregor   // Parse the module name.
1638e7ab3669SDouglas Gregor   ModuleId Id;
1639e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1640718292f2SDouglas Gregor     HadError = true;
1641718292f2SDouglas Gregor     return;
1642718292f2SDouglas Gregor   }
1643e7ab3669SDouglas Gregor 
1644e7ab3669SDouglas Gregor   if (ActiveModule) {
1645e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1646e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1647e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1648e7ab3669SDouglas Gregor 
1649e7ab3669SDouglas Gregor       HadError = true;
1650e7ab3669SDouglas Gregor       return;
1651e7ab3669SDouglas Gregor     }
1652e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1653e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1654e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1655e7ab3669SDouglas Gregor     Explicit = false;
1656e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1657e7ab3669SDouglas Gregor     HadError = true;
1658e7ab3669SDouglas Gregor   }
1659e7ab3669SDouglas Gregor 
1660e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1661e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1662e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1663e7ab3669SDouglas Gregor     // is a submodule.
1664d2d442caSCraig Topper     ActiveModule = nullptr;
16654b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1666e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1667e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
16684b8a9e95SBen Langmuir         if (I == 0)
16694b8a9e95SBen Langmuir           TopLevelModule = Next;
1670e7ab3669SDouglas Gregor         ActiveModule = Next;
1671e7ab3669SDouglas Gregor         continue;
1672e7ab3669SDouglas Gregor       }
1673e7ab3669SDouglas Gregor 
1674e7ab3669SDouglas Gregor       if (ActiveModule) {
1675e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
16765b5d21eaSRichard Smith           << Id[I].first
16775b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1678e7ab3669SDouglas Gregor       } else {
1679e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1680e7ab3669SDouglas Gregor       }
1681e7ab3669SDouglas Gregor       HadError = true;
1682e7ab3669SDouglas Gregor       return;
1683e7ab3669SDouglas Gregor     }
16844b8a9e95SBen Langmuir 
16854b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
16864b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
16874b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
16884b8a9e95SBen Langmuir              "top-level module");
16894b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
16904b8a9e95SBen Langmuir     }
1691e7ab3669SDouglas Gregor   }
1692e7ab3669SDouglas Gregor 
1693e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1694e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1695718292f2SDouglas Gregor 
1696a686e1b0SDouglas Gregor   // Parse the optional attribute list.
16974442605fSBill Wendling   Attributes Attrs;
16985d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
16995d29dee0SDavide Italiano     return;
17005d29dee0SDavide Italiano 
1701a686e1b0SDouglas Gregor 
1702718292f2SDouglas Gregor   // Parse the opening brace.
1703718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1704718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1705718292f2SDouglas Gregor       << ModuleName;
1706718292f2SDouglas Gregor     HadError = true;
1707718292f2SDouglas Gregor     return;
1708718292f2SDouglas Gregor   }
1709718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1710718292f2SDouglas Gregor 
1711718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
1712eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
17134a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
17144a3751ffSRichard Smith     // definition for in two cases:
17154a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
17164a3751ffSRichard Smith     //    corresponding definition in a module map file, or
17174a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
17184a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
17194a3751ffSRichard Smith     //    module map file from which it was created.
17204a3751ffSRichard Smith     bool ParsedAsMainInput =
17214a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
17224a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
17234a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
17244a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
17254a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1726fcc54a3bSDouglas Gregor       // Skip the module definition.
1727fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1728fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1729fcc54a3bSDouglas Gregor         consumeToken();
1730fcc54a3bSDouglas Gregor       else {
1731fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1732fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1733fcc54a3bSDouglas Gregor         HadError = true;
1734fcc54a3bSDouglas Gregor       }
1735fcc54a3bSDouglas Gregor       return;
1736fcc54a3bSDouglas Gregor     }
1737fcc54a3bSDouglas Gregor 
1738718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1739718292f2SDouglas Gregor       << ModuleName;
1740eb90e830SDouglas Gregor     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1741718292f2SDouglas Gregor 
1742718292f2SDouglas Gregor     // Skip the module definition.
1743718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
1744718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
1745718292f2SDouglas Gregor       consumeToken();
1746718292f2SDouglas Gregor 
1747718292f2SDouglas Gregor     HadError = true;
1748718292f2SDouglas Gregor     return;
1749718292f2SDouglas Gregor   }
1750718292f2SDouglas Gregor 
1751718292f2SDouglas Gregor   // Start defining this module.
17529d6448b1SBen Langmuir   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
17539d6448b1SBen Langmuir                                         Explicit).first;
1754eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1755963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1756a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
175777944868SRichard Smith   if (Attrs.IsExternC)
175877944868SRichard Smith     ActiveModule->IsExternC = true;
1759ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1760ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1761ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
17623c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1763718292f2SDouglas Gregor 
17644d867640SGraydon Hoare   if (!ActiveModule->Parent) {
17654d867640SGraydon Hoare     StringRef MapFileName(ModuleMapFile->getName());
17664d867640SGraydon Hoare     if (MapFileName.endswith("module.private.modulemap") ||
17674d867640SGraydon Hoare         MapFileName.endswith("module_private.map")) {
17684d867640SGraydon Hoare       // Adding a top-level module from a private modulemap is likely a
17694d867640SGraydon Hoare       // user error; we check to see if there's another top-level module
17704d867640SGraydon Hoare       // defined in the non-private map in the same dir, and if so emit a
17714d867640SGraydon Hoare       // warning.
17724d867640SGraydon Hoare       for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
17734d867640SGraydon Hoare         auto const *M = E->getValue();
17744d867640SGraydon Hoare         if (!M->Parent &&
17754d867640SGraydon Hoare             M->Directory == ActiveModule->Directory &&
17764d867640SGraydon Hoare             M->Name != ActiveModule->Name) {
17774d867640SGraydon Hoare           Diags.Report(ActiveModule->DefinitionLoc,
17784d867640SGraydon Hoare                        diag::warn_mmap_mismatched_top_level_private)
17794d867640SGraydon Hoare             << ActiveModule->Name << M->Name;
17804d867640SGraydon Hoare           // The pattern we're defending against here is typically due to
17814d867640SGraydon Hoare           // a module named FooPrivate which is supposed to be a submodule
17824d867640SGraydon Hoare           // called Foo.Private. Emit a fixit in that case.
17834d867640SGraydon Hoare           auto D =
17844d867640SGraydon Hoare             Diags.Report(ActiveModule->DefinitionLoc,
17854d867640SGraydon Hoare                          diag::note_mmap_rename_top_level_private_as_submodule);
17864d867640SGraydon Hoare           D << ActiveModule->Name << M->Name;
17874d867640SGraydon Hoare           StringRef Bad(ActiveModule->Name);
17884d867640SGraydon Hoare           if (Bad.consume_back("Private")) {
17894d867640SGraydon Hoare             SmallString<128> Fixed = Bad;
17904d867640SGraydon Hoare             Fixed.append(".Private");
17914d867640SGraydon Hoare             D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc,
17924d867640SGraydon Hoare                                               Fixed);
17934d867640SGraydon Hoare           }
17944d867640SGraydon Hoare           break;
17954d867640SGraydon Hoare         }
17964d867640SGraydon Hoare       }
17974d867640SGraydon Hoare     }
17984d867640SGraydon Hoare   }
17994d867640SGraydon Hoare 
1800718292f2SDouglas Gregor   bool Done = false;
1801718292f2SDouglas Gregor   do {
1802718292f2SDouglas Gregor     switch (Tok.Kind) {
1803718292f2SDouglas Gregor     case MMToken::EndOfFile:
1804718292f2SDouglas Gregor     case MMToken::RBrace:
1805718292f2SDouglas Gregor       Done = true;
1806718292f2SDouglas Gregor       break;
1807718292f2SDouglas Gregor 
180835b13eceSDouglas Gregor     case MMToken::ConfigMacros:
180935b13eceSDouglas Gregor       parseConfigMacros();
181035b13eceSDouglas Gregor       break;
181135b13eceSDouglas Gregor 
1812fb912657SDouglas Gregor     case MMToken::Conflict:
1813fb912657SDouglas Gregor       parseConflict();
1814fb912657SDouglas Gregor       break;
1815fb912657SDouglas Gregor 
1816718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
181797292843SDaniel Jasper     case MMToken::ExternKeyword:
1818f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1819718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1820718292f2SDouglas Gregor       parseModuleDecl();
1821718292f2SDouglas Gregor       break;
1822718292f2SDouglas Gregor 
18232b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
18242b82c2a5SDouglas Gregor       parseExportDecl();
18252b82c2a5SDouglas Gregor       break;
18262b82c2a5SDouglas Gregor 
1827ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
1828ba7f2f71SDaniel Jasper       parseUseDecl();
1829ba7f2f71SDaniel Jasper       break;
1830ba7f2f71SDaniel Jasper 
18311fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
18321fb5c3a6SDouglas Gregor       parseRequiresDecl();
18331fb5c3a6SDouglas Gregor       break;
18341fb5c3a6SDouglas Gregor 
1835202210b3SRichard Smith     case MMToken::TextualKeyword:
1836202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1837306d8920SRichard Smith       break;
1838306d8920SRichard Smith 
1839524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1840524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1841524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
1842b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1843524e33e1SDouglas Gregor       else
1844524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1845718292f2SDouglas Gregor       break;
1846524e33e1SDouglas Gregor     }
1847718292f2SDouglas Gregor 
1848202210b3SRichard Smith     case MMToken::ExcludeKeyword:
1849202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
185059527666SDouglas Gregor       break;
185159527666SDouglas Gregor 
1852202210b3SRichard Smith     case MMToken::PrivateKeyword:
1853202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1854b53e5483SLawrence Crowl       break;
1855b53e5483SLawrence Crowl 
1856322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
1857202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
1858718292f2SDouglas Gregor       break;
1859718292f2SDouglas Gregor 
18606ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
18616ddfca91SDouglas Gregor       parseLinkDecl();
18626ddfca91SDouglas Gregor       break;
18636ddfca91SDouglas Gregor 
1864718292f2SDouglas Gregor     default:
1865718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1866718292f2SDouglas Gregor       consumeToken();
1867718292f2SDouglas Gregor       break;
1868718292f2SDouglas Gregor     }
1869718292f2SDouglas Gregor   } while (!Done);
1870718292f2SDouglas Gregor 
1871718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1872718292f2SDouglas Gregor     consumeToken();
1873718292f2SDouglas Gregor   else {
1874718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1875718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1876718292f2SDouglas Gregor     HadError = true;
1877718292f2SDouglas Gregor   }
1878718292f2SDouglas Gregor 
187911dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
188011dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
188111dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
188211dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
188311dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
188411dfe6feSDouglas Gregor   }
188511dfe6feSDouglas Gregor 
1886ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
1887ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
1888ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
1889ec8c9752SBen Langmuir       ActiveModule->Parent) {
1890ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
1891ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
1892ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
1893ec8c9752SBen Langmuir   }
1894ec8c9752SBen Langmuir 
1895e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
1896e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
1897718292f2SDouglas Gregor }
1898718292f2SDouglas Gregor 
189997292843SDaniel Jasper /// \brief Parse an extern module declaration.
190097292843SDaniel Jasper ///
190197292843SDaniel Jasper ///   extern module-declaration:
190297292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
190397292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
190497292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
1905ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
190697292843SDaniel Jasper 
190797292843SDaniel Jasper   // Parse 'module' keyword.
190897292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
190997292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
191097292843SDaniel Jasper     consumeToken();
191197292843SDaniel Jasper     HadError = true;
191297292843SDaniel Jasper     return;
191397292843SDaniel Jasper   }
191497292843SDaniel Jasper   consumeToken(); // 'module' keyword
191597292843SDaniel Jasper 
191697292843SDaniel Jasper   // Parse the module name.
191797292843SDaniel Jasper   ModuleId Id;
191897292843SDaniel Jasper   if (parseModuleId(Id)) {
191997292843SDaniel Jasper     HadError = true;
192097292843SDaniel Jasper     return;
192197292843SDaniel Jasper   }
192297292843SDaniel Jasper 
192397292843SDaniel Jasper   // Parse the referenced module map file name.
192497292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
192597292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
192697292843SDaniel Jasper     HadError = true;
192797292843SDaniel Jasper     return;
192897292843SDaniel Jasper   }
192997292843SDaniel Jasper   std::string FileName = Tok.getString();
193097292843SDaniel Jasper   consumeToken(); // filename
193197292843SDaniel Jasper 
193297292843SDaniel Jasper   StringRef FileNameRef = FileName;
193397292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
193497292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
193597292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
193697292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
193792e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
193897292843SDaniel Jasper   }
193997292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
19409acb99e3SRichard Smith     Map.parseModuleMapFile(
19419acb99e3SRichard Smith         File, /*IsSystem=*/false,
19429acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
19439acb99e3SRichard Smith             ? Directory
19448128f332SRichard Smith             : File->getDir(),
19458128f332SRichard Smith         FileID(), nullptr, ExternLoc);
194697292843SDaniel Jasper }
194797292843SDaniel Jasper 
19487ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
19497ff29148SBen Langmuir ///
19507ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
19517ff29148SBen Langmuir /// module map files:
19527ff29148SBen Langmuir ///
19537ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
19547ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
19557ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
19567ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
19577ff29148SBen Langmuir ///    module to 'textual'.
19587ff29148SBen Langmuir ///
19597ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
19607ff29148SBen Langmuir ///
19617ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
19627ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
19637ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
19647ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
19658013e81dSBenjamin Kramer   if (Feature == "excluded" &&
19668013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
19678013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
19687ff29148SBen Langmuir     IsRequiresExcludedHack = true;
19697ff29148SBen Langmuir     return false;
19708013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
19717ff29148SBen Langmuir     return false;
19727ff29148SBen Langmuir   }
19737ff29148SBen Langmuir 
19747ff29148SBen Langmuir   return true;
19757ff29148SBen Langmuir }
19767ff29148SBen Langmuir 
19771fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
19781fb5c3a6SDouglas Gregor ///
19791fb5c3a6SDouglas Gregor ///   requires-declaration:
19801fb5c3a6SDouglas Gregor ///     'requires' feature-list
19811fb5c3a6SDouglas Gregor ///
19821fb5c3a6SDouglas Gregor ///   feature-list:
1983a3feee2aSRichard Smith ///     feature ',' feature-list
1984a3feee2aSRichard Smith ///     feature
1985a3feee2aSRichard Smith ///
1986a3feee2aSRichard Smith ///   feature:
1987a3feee2aSRichard Smith ///     '!'[opt] identifier
19881fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
19891fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
19901fb5c3a6SDouglas Gregor 
19911fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
19921fb5c3a6SDouglas Gregor   consumeToken();
19931fb5c3a6SDouglas Gregor 
19941fb5c3a6SDouglas Gregor   // Parse the feature-list.
19951fb5c3a6SDouglas Gregor   do {
1996a3feee2aSRichard Smith     bool RequiredState = true;
1997a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
1998a3feee2aSRichard Smith       RequiredState = false;
1999a3feee2aSRichard Smith       consumeToken();
2000a3feee2aSRichard Smith     }
2001a3feee2aSRichard Smith 
20021fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
20031fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
20041fb5c3a6SDouglas Gregor       HadError = true;
20051fb5c3a6SDouglas Gregor       return;
20061fb5c3a6SDouglas Gregor     }
20071fb5c3a6SDouglas Gregor 
20081fb5c3a6SDouglas Gregor     // Consume the feature name.
20091fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
20101fb5c3a6SDouglas Gregor     consumeToken();
20111fb5c3a6SDouglas Gregor 
20127ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
20137ff29148SBen Langmuir     bool ShouldAddRequirement =
20147ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
20157ff29148SBen Langmuir 
20167ff29148SBen Langmuir     if (IsRequiresExcludedHack)
20177ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
20187ff29148SBen Langmuir 
20197ff29148SBen Langmuir     if (ShouldAddRequirement) {
20201fb5c3a6SDouglas Gregor       // Add this feature.
20217ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
20227ff29148SBen Langmuir                                    *Map.Target);
20237ff29148SBen Langmuir     }
20241fb5c3a6SDouglas Gregor 
20251fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
20261fb5c3a6SDouglas Gregor       break;
20271fb5c3a6SDouglas Gregor 
20281fb5c3a6SDouglas Gregor     // Consume the comma.
20291fb5c3a6SDouglas Gregor     consumeToken();
20301fb5c3a6SDouglas Gregor   } while (true);
20311fb5c3a6SDouglas Gregor }
20321fb5c3a6SDouglas Gregor 
2033718292f2SDouglas Gregor /// \brief Parse a header declaration.
2034718292f2SDouglas Gregor ///
2035718292f2SDouglas Gregor ///   header-declaration:
2036306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2037202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2038202210b3SRichard Smith ///     'exclude' 'header' string-literal
2039202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2040306d8920SRichard Smith ///
2041306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2042b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2043b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2044202210b3SRichard Smith   // We've already consumed the first token.
2045202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2046202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2047202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2048202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2049202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2050202210b3SRichard Smith       LeadingToken = Tok.Kind;
20511871ed3dSBenjamin Kramer       consumeToken();
2052202210b3SRichard Smith     }
2053202210b3SRichard Smith   }
20547ff29148SBen Langmuir 
2055202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2056202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2057202210b3SRichard Smith 
20587ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
20597ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
20607ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
20617ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
20627ff29148SBen Langmuir   }
20637ff29148SBen Langmuir 
2064202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2065202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2066202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2067202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2068202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2069202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2070202210b3SRichard Smith       return;
2071202210b3SRichard Smith     }
2072202210b3SRichard Smith     consumeToken();
2073202210b3SRichard Smith   }
2074718292f2SDouglas Gregor 
2075718292f2SDouglas Gregor   // Parse the header name.
2076718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2077718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2078718292f2SDouglas Gregor       << "header";
2079718292f2SDouglas Gregor     HadError = true;
2080718292f2SDouglas Gregor     return;
2081718292f2SDouglas Gregor   }
20823c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
20830761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
20840761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
20851d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2086040e1266SRichard Smith   Header.Kind =
2087040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2088040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2089718292f2SDouglas Gregor 
2090524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
20911d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
20920761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2093524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2094322f633cSDouglas Gregor     HadError = true;
2095322f633cSDouglas Gregor     return;
2096322f633cSDouglas Gregor   }
2097322f633cSDouglas Gregor 
2098040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2099040e1266SRichard Smith   // the file.
2100040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2101040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
21023ec6663bSDouglas Gregor 
2103040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2104040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2105040e1266SRichard Smith       StringRef Str = Tok.getString();
2106040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2107040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2108040e1266SRichard Smith                   .Case("size", Size)
2109040e1266SRichard Smith                   .Case("mtime", ModTime)
2110040e1266SRichard Smith                   .Default(Unknown)) {
2111040e1266SRichard Smith       case Size:
2112040e1266SRichard Smith         if (Header.Size)
2113040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2114040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2115040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2116040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2117040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2118040e1266SRichard Smith           break;
2119040e1266SRichard Smith         }
2120040e1266SRichard Smith         Header.Size = Tok.getInteger();
2121040e1266SRichard Smith         consumeToken();
2122040e1266SRichard Smith         break;
2123040e1266SRichard Smith 
2124040e1266SRichard Smith       case ModTime:
2125040e1266SRichard Smith         if (Header.ModTime)
2126040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2127040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2128040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2129040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2130040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2131040e1266SRichard Smith           break;
2132040e1266SRichard Smith         }
2133040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2134040e1266SRichard Smith         consumeToken();
2135040e1266SRichard Smith         break;
2136040e1266SRichard Smith 
2137040e1266SRichard Smith       case Unknown:
2138040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2139040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2140040e1266SRichard Smith         break;
2141040e1266SRichard Smith       }
21423ec6663bSDouglas Gregor     }
21435257fc63SDouglas Gregor 
2144040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2145040e1266SRichard Smith       consumeToken();
2146040e1266SRichard Smith     else {
2147040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2148040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2149322f633cSDouglas Gregor       HadError = true;
2150322f633cSDouglas Gregor     }
21510101b540SHans Wennborg   }
215225d50758SRichard Smith 
2153040e1266SRichard Smith   Map.addUnresolvedHeader(ActiveModule, std::move(Header));
2154718292f2SDouglas Gregor }
2155718292f2SDouglas Gregor 
215641f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
215741f81994SBen Langmuir                                 const Module::Header *B) {
215841f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
215941f81994SBen Langmuir }
216041f81994SBen Langmuir 
2161524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
2162524e33e1SDouglas Gregor ///
2163524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2164524e33e1SDouglas Gregor ///     umbrella string-literal
2165524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2166524e33e1SDouglas Gregor   // Parse the directory name.
2167524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2168524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2169524e33e1SDouglas Gregor       << "umbrella";
2170524e33e1SDouglas Gregor     HadError = true;
2171524e33e1SDouglas Gregor     return;
2172524e33e1SDouglas Gregor   }
2173524e33e1SDouglas Gregor 
2174524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2175524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2176524e33e1SDouglas Gregor 
2177524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2178524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2179524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2180524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2181524e33e1SDouglas Gregor     HadError = true;
2182524e33e1SDouglas Gregor     return;
2183524e33e1SDouglas Gregor   }
2184524e33e1SDouglas Gregor 
2185524e33e1SDouglas Gregor   // Look for this file.
2186d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2187524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2188524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2189524e33e1SDouglas Gregor   else {
21902c1dd271SDylan Noblesmith     SmallString<128> PathName;
2191524e33e1SDouglas Gregor     PathName = Directory->getName();
2192524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2193524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2194524e33e1SDouglas Gregor   }
2195524e33e1SDouglas Gregor 
2196524e33e1SDouglas Gregor   if (!Dir) {
2197a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2198524e33e1SDouglas Gregor       << DirName;
2199524e33e1SDouglas Gregor     return;
2200524e33e1SDouglas Gregor   }
2201524e33e1SDouglas Gregor 
22027ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22037ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22047ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
22057ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
22067ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
22077ff29148SBen Langmuir     std::error_code EC;
22087ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2209b171a59bSBruno Cardoso Lopes     vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
2210b171a59bSBruno Cardoso Lopes     for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
22117ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
2212b171a59bSBruno Cardoso Lopes       if (const FileEntry *FE =
2213b171a59bSBruno Cardoso Lopes               SourceMgr.getFileManager().getFile(I->getName())) {
22147ff29148SBen Langmuir 
2215b171a59bSBruno Cardoso Lopes         Module::Header Header = {I->getName(), FE};
22167ff29148SBen Langmuir         Headers.push_back(std::move(Header));
22177ff29148SBen Langmuir       }
22187ff29148SBen Langmuir     }
22197ff29148SBen Langmuir 
22207ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
222141f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
222241f81994SBen Langmuir 
22237ff29148SBen Langmuir     for (auto &Header : Headers)
22247ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
22257ff29148SBen Langmuir     return;
22267ff29148SBen Langmuir   }
22277ff29148SBen Langmuir 
2228524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2229524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2230524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2231524e33e1SDouglas Gregor     HadError = true;
2232524e33e1SDouglas Gregor     return;
2233524e33e1SDouglas Gregor   }
2234524e33e1SDouglas Gregor 
2235524e33e1SDouglas Gregor   // Record this umbrella directory.
22362b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2237524e33e1SDouglas Gregor }
2238524e33e1SDouglas Gregor 
22392b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
22402b82c2a5SDouglas Gregor ///
22412b82c2a5SDouglas Gregor ///   export-declaration:
22422b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
22432b82c2a5SDouglas Gregor ///
22442b82c2a5SDouglas Gregor ///   wildcard-module-id:
22452b82c2a5SDouglas Gregor ///     identifier
22462b82c2a5SDouglas Gregor ///     '*'
22472b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
22482b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
22492b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
22502b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
22512b82c2a5SDouglas Gregor 
22522b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
22532b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
22542b82c2a5SDouglas Gregor   bool Wildcard = false;
22552b82c2a5SDouglas Gregor   do {
2256306d8920SRichard Smith     // FIXME: Support string-literal module names here.
22572b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
22582b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
22592b82c2a5SDouglas Gregor                                               Tok.getLocation()));
22602b82c2a5SDouglas Gregor       consumeToken();
22612b82c2a5SDouglas Gregor 
22622b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
22632b82c2a5SDouglas Gregor         consumeToken();
22642b82c2a5SDouglas Gregor         continue;
22652b82c2a5SDouglas Gregor       }
22662b82c2a5SDouglas Gregor 
22672b82c2a5SDouglas Gregor       break;
22682b82c2a5SDouglas Gregor     }
22692b82c2a5SDouglas Gregor 
22702b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
22712b82c2a5SDouglas Gregor       Wildcard = true;
2272f5eedd05SDouglas Gregor       consumeToken();
22732b82c2a5SDouglas Gregor       break;
22742b82c2a5SDouglas Gregor     }
22752b82c2a5SDouglas Gregor 
2276ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
22772b82c2a5SDouglas Gregor     HadError = true;
22782b82c2a5SDouglas Gregor     return;
22792b82c2a5SDouglas Gregor   } while (true);
22802b82c2a5SDouglas Gregor 
22812b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
22822b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
22832b82c2a5SDouglas Gregor   };
22842b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
22852b82c2a5SDouglas Gregor }
22862b82c2a5SDouglas Gregor 
22878f4d3ff1SRichard Smith /// \brief Parse a module use declaration.
2288ba7f2f71SDaniel Jasper ///
22898f4d3ff1SRichard Smith ///   use-declaration:
22908f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2291ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2292ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
22938f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2294ba7f2f71SDaniel Jasper   // Parse the module-id.
2295ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
22963cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2297ba7f2f71SDaniel Jasper 
22988f4d3ff1SRichard Smith   if (ActiveModule->Parent)
22998f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
23008f4d3ff1SRichard Smith   else
2301ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2302ba7f2f71SDaniel Jasper }
2303ba7f2f71SDaniel Jasper 
23046ddfca91SDouglas Gregor /// \brief Parse a link declaration.
23056ddfca91SDouglas Gregor ///
23066ddfca91SDouglas Gregor ///   module-declaration:
23076ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
23086ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
23096ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
23106ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
23116ddfca91SDouglas Gregor 
23126ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
23136ddfca91SDouglas Gregor   bool IsFramework = false;
23146ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
23156ddfca91SDouglas Gregor     consumeToken();
23166ddfca91SDouglas Gregor     IsFramework = true;
23176ddfca91SDouglas Gregor   }
23186ddfca91SDouglas Gregor 
23196ddfca91SDouglas Gregor   // Parse the library name
23206ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
23216ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
23226ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
23236ddfca91SDouglas Gregor     HadError = true;
23246ddfca91SDouglas Gregor     return;
23256ddfca91SDouglas Gregor   }
23266ddfca91SDouglas Gregor 
23276ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
23286ddfca91SDouglas Gregor   consumeToken();
23296ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
23306ddfca91SDouglas Gregor                                                             IsFramework));
23316ddfca91SDouglas Gregor }
23326ddfca91SDouglas Gregor 
233335b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration.
233435b13eceSDouglas Gregor ///
233535b13eceSDouglas Gregor ///   module-declaration:
233635b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
233735b13eceSDouglas Gregor ///
233835b13eceSDouglas Gregor ///   config-macro-list:
233935b13eceSDouglas Gregor ///     identifier (',' identifier)?
234035b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
234135b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
234235b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
234335b13eceSDouglas Gregor 
234435b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
234535b13eceSDouglas Gregor   if (ActiveModule->Parent) {
234635b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
234735b13eceSDouglas Gregor   }
234835b13eceSDouglas Gregor 
234935b13eceSDouglas Gregor   // Parse the optional attributes.
235035b13eceSDouglas Gregor   Attributes Attrs;
23515d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
23525d29dee0SDavide Italiano     return;
23535d29dee0SDavide Italiano 
235435b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
235535b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
235635b13eceSDouglas Gregor   }
235735b13eceSDouglas Gregor 
235835b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2359306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
236035b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
236135b13eceSDouglas Gregor     return;
236235b13eceSDouglas Gregor 
236335b13eceSDouglas Gregor   // Consume the first identifier.
236435b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
236535b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
236635b13eceSDouglas Gregor   }
236735b13eceSDouglas Gregor   consumeToken();
236835b13eceSDouglas Gregor 
236935b13eceSDouglas Gregor   do {
237035b13eceSDouglas Gregor     // If there's a comma, consume it.
237135b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
237235b13eceSDouglas Gregor       break;
237335b13eceSDouglas Gregor     consumeToken();
237435b13eceSDouglas Gregor 
237535b13eceSDouglas Gregor     // We expect to see a macro name here.
2376306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
237735b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
237835b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
237935b13eceSDouglas Gregor       break;
238035b13eceSDouglas Gregor     }
238135b13eceSDouglas Gregor 
238235b13eceSDouglas Gregor     // Consume the macro name.
238335b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
238435b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
238535b13eceSDouglas Gregor     }
238635b13eceSDouglas Gregor     consumeToken();
238735b13eceSDouglas Gregor   } while (true);
238835b13eceSDouglas Gregor }
238935b13eceSDouglas Gregor 
2390fb912657SDouglas Gregor /// \brief Format a module-id into a string.
2391fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2392fb912657SDouglas Gregor   std::string result;
2393fb912657SDouglas Gregor   {
2394fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2395fb912657SDouglas Gregor 
2396fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2397fb912657SDouglas Gregor       if (I)
2398fb912657SDouglas Gregor         OS << ".";
2399fb912657SDouglas Gregor       OS << Id[I].first;
2400fb912657SDouglas Gregor     }
2401fb912657SDouglas Gregor   }
2402fb912657SDouglas Gregor 
2403fb912657SDouglas Gregor   return result;
2404fb912657SDouglas Gregor }
2405fb912657SDouglas Gregor 
2406fb912657SDouglas Gregor /// \brief Parse a conflict declaration.
2407fb912657SDouglas Gregor ///
2408fb912657SDouglas Gregor ///   module-declaration:
2409fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2410fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2411fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2412fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2413fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2414fb912657SDouglas Gregor 
2415fb912657SDouglas Gregor   // Parse the module-id.
2416fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2417fb912657SDouglas Gregor     return;
2418fb912657SDouglas Gregor 
2419fb912657SDouglas Gregor   // Parse the ','.
2420fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2421fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2422fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2423fb912657SDouglas Gregor     return;
2424fb912657SDouglas Gregor   }
2425fb912657SDouglas Gregor   consumeToken();
2426fb912657SDouglas Gregor 
2427fb912657SDouglas Gregor   // Parse the message.
2428fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2429fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2430fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2431fb912657SDouglas Gregor     return;
2432fb912657SDouglas Gregor   }
2433fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2434fb912657SDouglas Gregor   consumeToken();
2435fb912657SDouglas Gregor 
2436fb912657SDouglas Gregor   // Add this unresolved conflict.
2437fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2438fb912657SDouglas Gregor }
2439fb912657SDouglas Gregor 
24406ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules).
24419194a91dSDouglas Gregor ///
24429194a91dSDouglas Gregor ///   module-declaration:
24439194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
24449194a91dSDouglas Gregor ///       { inferred-module-member* }
24459194a91dSDouglas Gregor ///
24469194a91dSDouglas Gregor ///   inferred-module-member:
24479194a91dSDouglas Gregor ///     'export' '*'
24489194a91dSDouglas Gregor ///     'exclude' identifier
24499194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
245073441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
245173441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
245273441091SDouglas Gregor   bool Failed = false;
245373441091SDouglas Gregor 
245473441091SDouglas Gregor   // Inferred modules must be submodules.
24559194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
245673441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
245773441091SDouglas Gregor     Failed = true;
245873441091SDouglas Gregor   }
245973441091SDouglas Gregor 
24609194a91dSDouglas Gregor   if (ActiveModule) {
2461524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
24624898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
24634898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
246473441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
246573441091SDouglas Gregor       Failed = true;
246673441091SDouglas Gregor     }
246773441091SDouglas Gregor 
246873441091SDouglas Gregor     // Check for redefinition of an inferred module.
2469dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
247073441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2471dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2472dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
247373441091SDouglas Gregor                      diag::note_mmap_prev_definition);
247473441091SDouglas Gregor       Failed = true;
247573441091SDouglas Gregor     }
247673441091SDouglas Gregor 
24779194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
24789194a91dSDouglas Gregor     if (Framework) {
24799194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
24809194a91dSDouglas Gregor       Framework = false;
24819194a91dSDouglas Gregor     }
24829194a91dSDouglas Gregor   } else if (Explicit) {
24839194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
24849194a91dSDouglas Gregor     Explicit = false;
24859194a91dSDouglas Gregor   }
24869194a91dSDouglas Gregor 
248773441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
248873441091SDouglas Gregor   if (Failed) {
248973441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
249073441091SDouglas Gregor       consumeToken();
249173441091SDouglas Gregor       skipUntil(MMToken::RBrace);
249273441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
249373441091SDouglas Gregor         consumeToken();
249473441091SDouglas Gregor     }
249573441091SDouglas Gregor     HadError = true;
249673441091SDouglas Gregor     return;
249773441091SDouglas Gregor   }
249873441091SDouglas Gregor 
24999194a91dSDouglas Gregor   // Parse optional attributes.
25004442605fSBill Wendling   Attributes Attrs;
25015d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
25025d29dee0SDavide Italiano     return;
25039194a91dSDouglas Gregor 
25049194a91dSDouglas Gregor   if (ActiveModule) {
250573441091SDouglas Gregor     // Note that we have an inferred submodule.
2506dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2507dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2508dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
25099194a91dSDouglas Gregor   } else {
25109194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
25119194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2512c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2513beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2514131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
25159194a91dSDouglas Gregor   }
251673441091SDouglas Gregor 
251773441091SDouglas Gregor   // Parse the opening brace.
251873441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
251973441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
252073441091SDouglas Gregor     HadError = true;
252173441091SDouglas Gregor     return;
252273441091SDouglas Gregor   }
252373441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
252473441091SDouglas Gregor 
252573441091SDouglas Gregor   // Parse the body of the inferred submodule.
252673441091SDouglas Gregor   bool Done = false;
252773441091SDouglas Gregor   do {
252873441091SDouglas Gregor     switch (Tok.Kind) {
252973441091SDouglas Gregor     case MMToken::EndOfFile:
253073441091SDouglas Gregor     case MMToken::RBrace:
253173441091SDouglas Gregor       Done = true;
253273441091SDouglas Gregor       break;
253373441091SDouglas Gregor 
25349194a91dSDouglas Gregor     case MMToken::ExcludeKeyword: {
25359194a91dSDouglas Gregor       if (ActiveModule) {
25369194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2537d2d442caSCraig Topper           << (ActiveModule != nullptr);
25389194a91dSDouglas Gregor         consumeToken();
25399194a91dSDouglas Gregor         break;
25409194a91dSDouglas Gregor       }
25419194a91dSDouglas Gregor 
25429194a91dSDouglas Gregor       consumeToken();
2543306d8920SRichard Smith       // FIXME: Support string-literal module names here.
25449194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
25459194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
25469194a91dSDouglas Gregor         break;
25479194a91dSDouglas Gregor       }
25489194a91dSDouglas Gregor 
25499194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
25509194a91dSDouglas Gregor         .push_back(Tok.getString());
25519194a91dSDouglas Gregor       consumeToken();
25529194a91dSDouglas Gregor       break;
25539194a91dSDouglas Gregor     }
25549194a91dSDouglas Gregor 
25559194a91dSDouglas Gregor     case MMToken::ExportKeyword:
25569194a91dSDouglas Gregor       if (!ActiveModule) {
25579194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2558d2d442caSCraig Topper           << (ActiveModule != nullptr);
25599194a91dSDouglas Gregor         consumeToken();
25609194a91dSDouglas Gregor         break;
25619194a91dSDouglas Gregor       }
25629194a91dSDouglas Gregor 
256373441091SDouglas Gregor       consumeToken();
256473441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2565dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
256673441091SDouglas Gregor       else
256773441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
256873441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
256973441091SDouglas Gregor       consumeToken();
257073441091SDouglas Gregor       break;
257173441091SDouglas Gregor 
257273441091SDouglas Gregor     case MMToken::ExplicitKeyword:
257373441091SDouglas Gregor     case MMToken::ModuleKeyword:
257473441091SDouglas Gregor     case MMToken::HeaderKeyword:
2575b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
257673441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
257773441091SDouglas Gregor     default:
25789194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2579d2d442caSCraig Topper           << (ActiveModule != nullptr);
258073441091SDouglas Gregor       consumeToken();
258173441091SDouglas Gregor       break;
258273441091SDouglas Gregor     }
258373441091SDouglas Gregor   } while (!Done);
258473441091SDouglas Gregor 
258573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
258673441091SDouglas Gregor     consumeToken();
258773441091SDouglas Gregor   else {
258873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
258973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
259073441091SDouglas Gregor     HadError = true;
259173441091SDouglas Gregor   }
259273441091SDouglas Gregor }
259373441091SDouglas Gregor 
25949194a91dSDouglas Gregor /// \brief Parse optional attributes.
25959194a91dSDouglas Gregor ///
25969194a91dSDouglas Gregor ///   attributes:
25979194a91dSDouglas Gregor ///     attribute attributes
25989194a91dSDouglas Gregor ///     attribute
25999194a91dSDouglas Gregor ///
26009194a91dSDouglas Gregor ///   attribute:
26019194a91dSDouglas Gregor ///     [ identifier ]
26029194a91dSDouglas Gregor ///
26039194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
26049194a91dSDouglas Gregor ///
26059194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
26064442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
26079194a91dSDouglas Gregor   bool HadError = false;
26089194a91dSDouglas Gregor 
26099194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
26109194a91dSDouglas Gregor     // Consume the '['.
26119194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
26129194a91dSDouglas Gregor 
26139194a91dSDouglas Gregor     // Check whether we have an attribute name here.
26149194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
26159194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
26169194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
26179194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
26189194a91dSDouglas Gregor         consumeToken();
26199194a91dSDouglas Gregor       HadError = true;
26209194a91dSDouglas Gregor     }
26219194a91dSDouglas Gregor 
26229194a91dSDouglas Gregor     // Decode the attribute name.
26239194a91dSDouglas Gregor     AttributeKind Attribute
26249194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
262535b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
262677944868SRichard Smith           .Case("extern_c", AT_extern_c)
2627ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
26289194a91dSDouglas Gregor           .Case("system", AT_system)
26299194a91dSDouglas Gregor           .Default(AT_unknown);
26309194a91dSDouglas Gregor     switch (Attribute) {
26319194a91dSDouglas Gregor     case AT_unknown:
26329194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
26339194a91dSDouglas Gregor         << Tok.getString();
26349194a91dSDouglas Gregor       break;
26359194a91dSDouglas Gregor 
26369194a91dSDouglas Gregor     case AT_system:
26379194a91dSDouglas Gregor       Attrs.IsSystem = true;
26389194a91dSDouglas Gregor       break;
263935b13eceSDouglas Gregor 
264077944868SRichard Smith     case AT_extern_c:
264177944868SRichard Smith       Attrs.IsExternC = true;
264277944868SRichard Smith       break;
264377944868SRichard Smith 
264435b13eceSDouglas Gregor     case AT_exhaustive:
264535b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
264635b13eceSDouglas Gregor       break;
2647ed84df00SBruno Cardoso Lopes 
2648ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2649ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2650ed84df00SBruno Cardoso Lopes       break;
26519194a91dSDouglas Gregor     }
26529194a91dSDouglas Gregor     consumeToken();
26539194a91dSDouglas Gregor 
26549194a91dSDouglas Gregor     // Consume the ']'.
26559194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
26569194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
26579194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
26589194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
26599194a91dSDouglas Gregor       HadError = true;
26609194a91dSDouglas Gregor     }
26619194a91dSDouglas Gregor 
26629194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
26639194a91dSDouglas Gregor       consumeToken();
26649194a91dSDouglas Gregor   }
26659194a91dSDouglas Gregor 
26669194a91dSDouglas Gregor   return HadError;
26679194a91dSDouglas Gregor }
26689194a91dSDouglas Gregor 
2669718292f2SDouglas Gregor /// \brief Parse a module map file.
2670718292f2SDouglas Gregor ///
2671718292f2SDouglas Gregor ///   module-map-file:
2672718292f2SDouglas Gregor ///     module-declaration*
2673718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2674718292f2SDouglas Gregor   do {
2675718292f2SDouglas Gregor     switch (Tok.Kind) {
2676718292f2SDouglas Gregor     case MMToken::EndOfFile:
2677718292f2SDouglas Gregor       return HadError;
2678718292f2SDouglas Gregor 
2679e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
268097292843SDaniel Jasper     case MMToken::ExternKeyword:
2681718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2682755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2683718292f2SDouglas Gregor       parseModuleDecl();
2684718292f2SDouglas Gregor       break;
2685718292f2SDouglas Gregor 
26861fb5c3a6SDouglas Gregor     case MMToken::Comma:
268735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2688fb912657SDouglas Gregor     case MMToken::Conflict:
2689a3feee2aSRichard Smith     case MMToken::Exclaim:
269059527666SDouglas Gregor     case MMToken::ExcludeKeyword:
26912b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2692718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2693718292f2SDouglas Gregor     case MMToken::Identifier:
2694718292f2SDouglas Gregor     case MMToken::LBrace:
26956ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2696a686e1b0SDouglas Gregor     case MMToken::LSquare:
26972b82c2a5SDouglas Gregor     case MMToken::Period:
2698b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2699718292f2SDouglas Gregor     case MMToken::RBrace:
2700a686e1b0SDouglas Gregor     case MMToken::RSquare:
27011fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
27022b82c2a5SDouglas Gregor     case MMToken::Star:
2703718292f2SDouglas Gregor     case MMToken::StringLiteral:
2704040e1266SRichard Smith     case MMToken::IntegerLiteral:
2705b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2706718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2707ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2708718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2709718292f2SDouglas Gregor       HadError = true;
2710718292f2SDouglas Gregor       consumeToken();
2711718292f2SDouglas Gregor       break;
2712718292f2SDouglas Gregor     }
2713718292f2SDouglas Gregor   } while (true);
2714718292f2SDouglas Gregor }
2715718292f2SDouglas Gregor 
27169acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
27178128f332SRichard Smith                                    const DirectoryEntry *Dir, FileID ID,
27188128f332SRichard Smith                                    unsigned *Offset,
2719ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
27208128f332SRichard Smith   assert(Target && "Missing target information");
27214ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
27224ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
27234ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
27244ddf2221SDouglas Gregor     return Known->second;
27254ddf2221SDouglas Gregor 
27268128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
27278128f332SRichard Smith   if (ID.isInvalid()) {
2728f3f84616SRichard Smith     auto FileCharacter =
2729f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
27308128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
27318128f332SRichard Smith   }
27328128f332SRichard Smith 
27338128f332SRichard Smith   assert(Target && "Missing target information");
27341f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2735718292f2SDouglas Gregor   if (!Buffer)
27364ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
27378128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
27388128f332SRichard Smith          "invalid buffer offset");
2739718292f2SDouglas Gregor 
2740718292f2SDouglas Gregor   // Parse this module map file.
27418128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
27428128f332SRichard Smith           Buffer->getBufferStart(),
27438128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
27448128f332SRichard Smith           Buffer->getBufferEnd());
27452a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2746beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
27471d60987fSRichard Smith                          IsSystem);
2748718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
27494ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
27502a6edb30SRichard Smith 
27518128f332SRichard Smith   if (Offset) {
27528128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
27538128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
27548128f332SRichard Smith     *Offset = Loc.second;
27558128f332SRichard Smith   }
27568128f332SRichard Smith 
27572a6edb30SRichard Smith   // Notify callbacks that we parsed it.
27582a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
27592a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
2760718292f2SDouglas Gregor   return Result;
2761718292f2SDouglas Gregor }
2762