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 
39*040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
40*040e1266SRichard Smith   switch ((int)Role) {
41*040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
42*040e1266SRichard Smith   case NormalHeader:
43*040e1266SRichard Smith     return Module::HK_Normal;
44*040e1266SRichard Smith   case PrivateHeader:
45*040e1266SRichard Smith     return Module::HK_Private;
46*040e1266SRichard Smith   case TextualHeader:
47*040e1266SRichard Smith     return Module::HK_Textual;
48*040e1266SRichard Smith   case PrivateHeader | TextualHeader:
49*040e1266SRichard Smith     return Module::HK_PrivateTextual;
50*040e1266SRichard Smith   }
51*040e1266SRichard Smith }
52*040e1266SRichard Smith 
53*040e1266SRichard Smith ModuleMap::ModuleHeaderRole
54*040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
55*040e1266SRichard Smith   switch ((int)Kind) {
56*040e1266SRichard Smith   case Module::HK_Normal:
57*040e1266SRichard Smith     return NormalHeader;
58*040e1266SRichard Smith   case Module::HK_Private:
59*040e1266SRichard Smith     return PrivateHeader;
60*040e1266SRichard Smith   case Module::HK_Textual:
61*040e1266SRichard Smith     return TextualHeader;
62*040e1266SRichard Smith   case Module::HK_PrivateTextual:
63*040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
64*040e1266SRichard Smith   case Module::HK_Excluded:
65*040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
66*040e1266SRichard Smith   }
67*040e1266SRichard Smith   llvm_unreachable("unknown header kind");
68*040e1266SRichard Smith }
69*040e1266SRichard 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 *
138*040e1266SRichard Smith ModuleMap::findHeader(Module *M,
139*040e1266SRichard Smith                       const Module::UnresolvedHeaderDirective &Header,
1401d60987fSRichard Smith                       SmallVectorImpl<char> &RelativePathName) {
141*040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
142*040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
143*040e1266SRichard Smith     if (!File ||
144*040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
145*040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
146*040e1266SRichard Smith       return nullptr;
147*040e1266SRichard Smith     return File;
148*040e1266SRichard Smith   };
149*040e1266SRichard 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());
153*040e1266SRichard 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);
168*040e1266SRichard 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);
185*040e1266SRichard 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);
191*040e1266SRichard Smith   return GetFile(FullPathName);
1921d60987fSRichard Smith }
1931d60987fSRichard Smith 
194*040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
195*040e1266SRichard Smith                               const Module::UnresolvedHeaderDirective &Header) {
196*040e1266SRichard Smith   SmallString<128> RelativePathName;
197*040e1266SRichard Smith   if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
198*040e1266SRichard Smith     if (Header.IsUmbrella) {
199*040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
200*040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
201*040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
202*040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
203*040e1266SRichard Smith       else
204*040e1266SRichard Smith         // Record this umbrella header.
205*040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
206*040e1266SRichard Smith     } else {
207*040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
208*040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
209*040e1266SRichard Smith         excludeHeader(Mod, H);
210*040e1266SRichard Smith       else
211*040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
212*040e1266SRichard Smith     }
213*040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
214*040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
215*040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
216*040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
217*040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
218*040e1266SRichard Smith   } else {
219*040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
220*040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
221*040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
222*040e1266SRichard Smith     // A missing header with stat information doesn't make the module
223*040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
224*040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
225*040e1266SRichard Smith     // preprocessed source.)
226*040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
227*040e1266SRichard Smith       Mod->markUnavailable();
228*040e1266SRichard Smith   }
229*040e1266SRichard Smith }
230*040e1266SRichard Smith 
231*040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
232*040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
233*040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
234*040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
235*040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
236*040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
237*040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
238*040e1266SRichard 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.
243*040e1266SRichard Smith   SmallString<128> Path;
244*040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
245*040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
246*040e1266SRichard Smith   if (!File)
247*040e1266SRichard Smith     return false;
248*040e1266SRichard Smith 
249*040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
250*040e1266SRichard Smith   Module::Header H = {Path.str(), File};
251*040e1266SRichard Smith   addHeader(Mod, H, Role);
252*040e1266SRichard 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),
259d2d442caSCraig Topper       HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
2607e82e019SRichard Smith       SourceModule(nullptr), NumCreatedModules(0) {
2610414b857SRichard Smith   MMapLangOpts.LineComment = true;
2620414b857SRichard Smith }
263718292f2SDouglas Gregor 
264718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
26521668754SDavide Italiano   for (auto &M : Modules)
26621668754SDavide Italiano     delete M.getValue();
267718292f2SDouglas Gregor }
268718292f2SDouglas Gregor 
26989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
27089929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
27189929282SDouglas Gregor          "Improper target override");
27289929282SDouglas Gregor   this->Target = &Target;
27389929282SDouglas Gregor }
27489929282SDouglas Gregor 
275056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier.
276056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
277056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
278056396aeSDouglas Gregor   if (Name.empty())
279056396aeSDouglas Gregor     return Name;
280056396aeSDouglas Gregor 
281a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
282056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
283056396aeSDouglas Gregor     // create a buffer with the sanitized name.
284056396aeSDouglas Gregor     Buffer.clear();
285a7d03840SJordan Rose     if (isDigit(Name[0]))
286056396aeSDouglas Gregor       Buffer.push_back('_');
287056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
288056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
289a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
290056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
291056396aeSDouglas Gregor       else
292056396aeSDouglas Gregor         Buffer.push_back('_');
293056396aeSDouglas Gregor     }
294056396aeSDouglas Gregor 
295056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
296056396aeSDouglas Gregor   }
297056396aeSDouglas Gregor 
298056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
299056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
300056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
301056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
302056396aeSDouglas Gregor            .Default(false)) {
303056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
304056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
305056396aeSDouglas Gregor     Buffer.push_back('_');
306056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
307056396aeSDouglas Gregor   }
308056396aeSDouglas Gregor 
309056396aeSDouglas Gregor   return Name;
310056396aeSDouglas Gregor }
311056396aeSDouglas Gregor 
31234d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
31334d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
31434d52749SDouglas Gregor /// headers.
315ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
31634d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
31734d52749SDouglas Gregor            .Case("float.h", true)
31834d52749SDouglas Gregor            .Case("iso646.h", true)
31934d52749SDouglas Gregor            .Case("limits.h", true)
32034d52749SDouglas Gregor            .Case("stdalign.h", true)
32134d52749SDouglas Gregor            .Case("stdarg.h", true)
3223c4b1290SBen Langmuir            .Case("stdatomic.h", true)
32334d52749SDouglas Gregor            .Case("stdbool.h", true)
32434d52749SDouglas Gregor            .Case("stddef.h", true)
32534d52749SDouglas Gregor            .Case("stdint.h", true)
32634d52749SDouglas Gregor            .Case("tgmath.h", true)
32734d52749SDouglas Gregor            .Case("unwind.h", true)
32834d52749SDouglas Gregor            .Default(false);
32934d52749SDouglas Gregor }
33034d52749SDouglas Gregor 
33192669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
33292669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
333*040e1266SRichard Smith   resolveHeaderDirectives(File);
33459527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
33547972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
33647972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
337ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3384eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
33992669ee4SDaniel Jasper     return Headers.find(File);
3404eaf0a6cSDaniel Jasper   }
34192669ee4SDaniel Jasper   return Known;
34292669ee4SDaniel Jasper }
34392669ee4SDaniel Jasper 
3444469138eSBen Langmuir ModuleMap::KnownHeader
3454469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
3464469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
34747972afdSRichard Smith   if (UmbrellaDirs.empty())
34847972afdSRichard Smith     return KnownHeader();
34947972afdSRichard Smith 
3504469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
3514469138eSBen Langmuir   assert(Dir && "file in no directory");
3524469138eSBen Langmuir 
3534469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
3544469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
3554469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
3564469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
3574469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
3584469138eSBen Langmuir 
3594469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
3604469138eSBen Langmuir   // an umbrella header.
3614469138eSBen Langmuir   do {
3624469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
3634469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
3644469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
3654469138eSBen Langmuir 
3664469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
3674469138eSBen Langmuir 
3684469138eSBen Langmuir     // Retrieve our parent path.
3694469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
3704469138eSBen Langmuir     if (DirName.empty())
3714469138eSBen Langmuir       break;
3724469138eSBen Langmuir 
3734469138eSBen Langmuir     // Resolve the parent path to a directory entry.
3744469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
3754469138eSBen Langmuir   } while (Dir);
3764469138eSBen Langmuir   return KnownHeader();
3774469138eSBen Langmuir }
3784469138eSBen Langmuir 
37992669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
38092669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
3814eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
38292669ee4SDaniel Jasper #ifndef NDEBUG
3834eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
38492669ee4SDaniel Jasper     // Check for consistency between the module header role
38592669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
38692669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
3872708e520SRichard Smith     bool IsPrivate = false;
3882708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
3894eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
3904eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
3912708e520SRichard Smith     for (auto *Hs : HeaderList)
3922708e520SRichard Smith       IsPrivate |=
3932708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
3943c1a41adSRichard Smith             return H.Entry == IncFileEnt;
3952708e520SRichard Smith           }) != Hs->end();
3964eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
39700bc95ecSRichard Smith   }
39892669ee4SDaniel Jasper #endif
3994eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
40092669ee4SDaniel Jasper }
40192669ee4SDaniel Jasper 
40271e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
40371e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
40471e1a64fSBen Langmuir }
40571e1a64fSBen Langmuir 
40692669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4078d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
40892669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
40992669ee4SDaniel Jasper                                         StringRef Filename,
41092669ee4SDaniel Jasper                                         const FileEntry *File) {
41192669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
41292669ee4SDaniel Jasper   // with no source files.
41371e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
41492669ee4SDaniel Jasper     return;
41592669ee4SDaniel Jasper 
416*040e1266SRichard Smith   if (RequestingModule) {
41792669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
418*040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
419*040e1266SRichard Smith   }
42092669ee4SDaniel Jasper 
42171e1a64fSBen Langmuir   bool Excluded = false;
422d2d442caSCraig Topper   Module *Private = nullptr;
423d2d442caSCraig Topper   Module *NotUsed = nullptr;
42471e1a64fSBen Langmuir 
42571e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
42671e1a64fSBen Langmuir   if (Known != Headers.end()) {
42771e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
42892669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4294eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
43071e1a64fSBen Langmuir         Private = Header.getModule();
43192669ee4SDaniel Jasper         continue;
43292669ee4SDaniel Jasper       }
43392669ee4SDaniel Jasper 
43492669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
43592669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
43692669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4378f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
43871e1a64fSBen Langmuir         NotUsed = Header.getModule();
43992669ee4SDaniel Jasper         continue;
44092669ee4SDaniel Jasper       }
44192669ee4SDaniel Jasper 
44292669ee4SDaniel Jasper       // We have found a module that we can happily use.
44392669ee4SDaniel Jasper       return;
44492669ee4SDaniel Jasper     }
445feb54b6dSRichard Smith 
446feb54b6dSRichard Smith     Excluded = true;
44771e1a64fSBen Langmuir   }
44892669ee4SDaniel Jasper 
44992669ee4SDaniel Jasper   // We have found a header, but it is private.
450d2d442caSCraig Topper   if (Private) {
45111152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
45292669ee4SDaniel Jasper         << Filename;
45392669ee4SDaniel Jasper     return;
45492669ee4SDaniel Jasper   }
45592669ee4SDaniel Jasper 
45692669ee4SDaniel Jasper   // We have found a module, but we don't use it.
457d2d442caSCraig Topper   if (NotUsed) {
45811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
45992669ee4SDaniel Jasper         << RequestingModule->getFullModuleName() << Filename;
46092669ee4SDaniel Jasper     return;
46192669ee4SDaniel Jasper   }
46292669ee4SDaniel Jasper 
46371e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
46471e1a64fSBen Langmuir     return;
46571e1a64fSBen Langmuir 
46671e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
46771e1a64fSBen Langmuir 
46871e1a64fSBen Langmuir   if (LangOpts.ModulesStrictDeclUse) {
46911152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
47071e1a64fSBen Langmuir         << RequestingModule->getFullModuleName() << Filename;
471a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
472a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
473a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
47471e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
47571e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
47671e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
47770a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
47870a7738fSManman Ren         << File->getName();
47971e1a64fSBen Langmuir   }
48092669ee4SDaniel Jasper }
48192669ee4SDaniel Jasper 
482ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
483ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
4848b7c0398SSean Silva   // Prefer available modules.
4858b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
4868b7c0398SSean Silva     return true;
4878b7c0398SSean Silva 
488ec87a50aSRichard Smith   // Prefer a public header over a private header.
489ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
490ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
491ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
492ec87a50aSRichard Smith 
493ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
494ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
495ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
496ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
497ec87a50aSRichard Smith 
498ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
499ec87a50aSRichard Smith   return false;
500ec87a50aSRichard Smith }
501ec87a50aSRichard Smith 
502ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
503ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
504306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
505ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
506306d8920SRichard Smith       return ModuleMap::KnownHeader();
507306d8920SRichard Smith     return R;
508306d8920SRichard Smith   };
509306d8920SRichard Smith 
5104881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5111fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
512202210b3SRichard Smith     ModuleMap::KnownHeader Result;
51397da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5144881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5157e82e019SRichard Smith       // Prefer a header from the source module over all others.
5167e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5172f633e7cSRichard Smith         return MakeResult(H);
5184881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5194881e8b2SSean Silva         Result = H;
52097da9178SDaniel Jasper     }
521306d8920SRichard Smith     return MakeResult(Result);
5221fb5c3a6SDouglas Gregor   }
523ab0c8a84SDouglas Gregor 
524386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
525386bb073SRichard Smith }
526386bb073SRichard Smith 
527386bb073SRichard Smith ModuleMap::KnownHeader
528386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
529386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
530386bb073SRichard Smith 
531f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5324469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5334469138eSBen Langmuir   if (H) {
5344469138eSBen Langmuir     Module *Result = H.getModule();
535930a85ccSDouglas Gregor 
536930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
53773141fa9SDouglas Gregor     // directory.
538930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
53973141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
540930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
541930a85ccSDouglas Gregor 
542930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
5439d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
5449d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
5459d6448b1SBen Langmuir 
546a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
547a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
548a89c5ac4SDouglas Gregor       // the actual header is located.
5499458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
5509458f82dSDouglas Gregor 
5517033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
552a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
553056396aeSDouglas Gregor         SmallString<32> NameBuf;
554056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
5554469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
5569d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5579d6448b1SBen Langmuir                                     Explicit).first;
5589d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
559ffbafa2aSBen Langmuir         Result->IsInferred = true;
560a89c5ac4SDouglas Gregor 
561a89c5ac4SDouglas Gregor         // Associate the module and the directory.
562a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
563a89c5ac4SDouglas Gregor 
564a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
565a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
566930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
567d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
568a89c5ac4SDouglas Gregor       }
569a89c5ac4SDouglas Gregor 
570a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
571056396aeSDouglas Gregor       SmallString<32> NameBuf;
572056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
573056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
5749d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5759d6448b1SBen Langmuir                                   Explicit).first;
5769d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
577ffbafa2aSBen Langmuir       Result->IsInferred = true;
5783c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
579a89c5ac4SDouglas Gregor 
580a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
581a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
582930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
583d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
584a89c5ac4SDouglas Gregor     } else {
585a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
586a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
587a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
588a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
589a89c5ac4SDouglas Gregor     }
590a89c5ac4SDouglas Gregor 
591386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
592386bb073SRichard Smith     Headers[File].push_back(Header);
593386bb073SRichard Smith     return Header;
594a89c5ac4SDouglas Gregor   }
595a89c5ac4SDouglas Gregor 
596b53e5483SLawrence Crowl   return KnownHeader();
597ab0c8a84SDouglas Gregor }
598ab0c8a84SDouglas Gregor 
599386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
600386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
601*040e1266SRichard Smith   resolveHeaderDirectives(File);
602386bb073SRichard Smith   auto It = Headers.find(File);
603386bb073SRichard Smith   if (It == Headers.end())
604386bb073SRichard Smith     return None;
605386bb073SRichard Smith   return It->second;
606386bb073SRichard Smith }
607386bb073SRichard Smith 
608e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
609d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
61050996ce1SRichard Smith }
61150996ce1SRichard Smith 
61262bcd925SDmitri Gribenko bool
61362bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
61462bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
615*040e1266SRichard Smith   resolveHeaderDirectives(Header);
616e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
61797da9178SDaniel Jasper   if (Known != Headers.end()) {
61897da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
61997da9178SDaniel Jasper              I = Known->second.begin(),
62097da9178SDaniel Jasper              E = Known->second.end();
62197da9178SDaniel Jasper          I != E; ++I) {
622052d95a6SBruno Cardoso Lopes 
623052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
624052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
625052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
626052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
627052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
628052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
629052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
630052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
631052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
632052d95a6SBruno Cardoso Lopes           continue;
63397da9178SDaniel Jasper         return false;
63497da9178SDaniel Jasper       }
635052d95a6SBruno Cardoso Lopes     }
63697da9178SDaniel Jasper     return true;
63797da9178SDaniel Jasper   }
6381fb5c3a6SDouglas Gregor 
6391fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
640f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6411fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
6421fb5c3a6SDouglas Gregor 
64350996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
64450996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
64550996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
64650996ce1SRichard Smith   };
64750996ce1SRichard Smith 
6481fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
6491fb5c3a6SDouglas Gregor   // an umbrella header.
6501fb5c3a6SDouglas Gregor   do {
651e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
6521fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
6531fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
6541fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
65550996ce1SRichard Smith       if (IsUnavailable(Found))
6561fb5c3a6SDouglas Gregor         return true;
6571fb5c3a6SDouglas Gregor 
6581fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
6591fb5c3a6SDouglas Gregor       // directory.
6601fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
6611fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6621fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
6631fb5c3a6SDouglas Gregor 
6641fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
6651fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
6661fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
667056396aeSDouglas Gregor           SmallString<32> NameBuf;
668056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
669056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
670056396aeSDouglas Gregor                              NameBuf);
6711fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
6721fb5c3a6SDouglas Gregor           if (!Found)
6731fb5c3a6SDouglas Gregor             return false;
67450996ce1SRichard Smith           if (IsUnavailable(Found))
6751fb5c3a6SDouglas Gregor             return true;
6761fb5c3a6SDouglas Gregor         }
6771fb5c3a6SDouglas Gregor 
6781fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
679056396aeSDouglas Gregor         SmallString<32> NameBuf;
680056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
681056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
682056396aeSDouglas Gregor                            NameBuf);
6831fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
6841fb5c3a6SDouglas Gregor         if (!Found)
6851fb5c3a6SDouglas Gregor           return false;
6861fb5c3a6SDouglas Gregor       }
6871fb5c3a6SDouglas Gregor 
68850996ce1SRichard Smith       return IsUnavailable(Found);
6891fb5c3a6SDouglas Gregor     }
6901fb5c3a6SDouglas Gregor 
6911fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
6921fb5c3a6SDouglas Gregor 
6931fb5c3a6SDouglas Gregor     // Retrieve our parent path.
6941fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
6951fb5c3a6SDouglas Gregor     if (DirName.empty())
6961fb5c3a6SDouglas Gregor       break;
6971fb5c3a6SDouglas Gregor 
6981fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
6991f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7001fb5c3a6SDouglas Gregor   } while (Dir);
7011fb5c3a6SDouglas Gregor 
7021fb5c3a6SDouglas Gregor   return false;
7031fb5c3a6SDouglas Gregor }
7041fb5c3a6SDouglas Gregor 
705e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
706e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
70788bdfb0eSDouglas Gregor   if (Known != Modules.end())
70888bdfb0eSDouglas Gregor     return Known->getValue();
70988bdfb0eSDouglas Gregor 
710d2d442caSCraig Topper   return nullptr;
71188bdfb0eSDouglas Gregor }
71288bdfb0eSDouglas Gregor 
713e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
714e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7152b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7162b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7172b82c2a5SDouglas Gregor       return Sub;
7182b82c2a5SDouglas Gregor   }
7192b82c2a5SDouglas Gregor 
7202b82c2a5SDouglas Gregor   return findModule(Name);
7212b82c2a5SDouglas Gregor }
7222b82c2a5SDouglas Gregor 
723e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7242b82c2a5SDouglas Gregor   if (!Context)
7252b82c2a5SDouglas Gregor     return findModule(Name);
7262b82c2a5SDouglas Gregor 
727eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7282b82c2a5SDouglas Gregor }
7292b82c2a5SDouglas Gregor 
7309ffe5a35SDavid Blaikie std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
7319ffe5a35SDavid Blaikie                                                         Module *Parent,
7329ffe5a35SDavid Blaikie                                                         bool IsFramework,
73369021974SDouglas Gregor                                                         bool IsExplicit) {
73469021974SDouglas Gregor   // Try to find an existing module with this name.
735eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
736eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
73769021974SDouglas Gregor 
73869021974SDouglas Gregor   // Create a new module with this name.
7399ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7409ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
7416f722b4eSArgyrios Kyrtzidis   if (!Parent) {
7427e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
7437e82e019SRichard Smith       SourceModule = Result;
74469021974SDouglas Gregor     Modules[Name] = Result;
7456f722b4eSArgyrios Kyrtzidis   }
74669021974SDouglas Gregor   return std::make_pair(Result, true);
74769021974SDouglas Gregor }
74869021974SDouglas Gregor 
749bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
750bbcc9f04SRichard Smith                                                 StringRef Name) {
751bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
752bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
753bbcc9f04SRichard Smith 
754bbcc9f04SRichard Smith   auto *Result =
755bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
756bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
757145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
758bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
759bbcc9f04SRichard Smith 
760bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
761bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
762bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
763bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
764bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
765bbcc9f04SRichard Smith 
766bbcc9f04SRichard Smith   return Result;
767bbcc9f04SRichard Smith }
768bbcc9f04SRichard Smith 
76911dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we
77011dfe6feSDouglas Gregor /// should link.
77111dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
77211dfe6feSDouglas Gregor                                FileManager &FileMgr) {
77311dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
77411dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
77511dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
77611dfe6feSDouglas Gregor 
77711dfe6feSDouglas Gregor   SmallString<128> LibName;
77811dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
77911dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
7808aaae5a9SJuergen Ributzka 
7818aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
7828aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
7838aaae5a9SJuergen Ributzka   // for both before we give up.
7848013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
7858aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
78611dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
78711dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
78811dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
7898aaae5a9SJuergen Ributzka       return;
7908aaae5a9SJuergen Ributzka     }
79111dfe6feSDouglas Gregor   }
79211dfe6feSDouglas Gregor }
79311dfe6feSDouglas Gregor 
794a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
795a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
796c1d88ea5SBen Langmuir   Attributes Attrs;
797c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
798a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
799c1d88ea5SBen Langmuir }
800c1d88ea5SBen Langmuir 
801a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
802c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
803a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
804a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
805a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
806a525400dSBen Langmuir   // top-level framework.
807a525400dSBen Langmuir   StringRef FrameworkDirName =
808a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
809a525400dSBen Langmuir 
810a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
811a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
812a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
813a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
814a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
815a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
816c1d88ea5SBen Langmuir 
81756c64013SDouglas Gregor   // Check whether we've already found this module.
818e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
819e89dbc1dSDouglas Gregor     return Mod;
820e89dbc1dSDouglas Gregor 
8211f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
82256c64013SDouglas Gregor 
8239194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
8249194a91dSDouglas Gregor   // a framework module, do so.
825beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
8269194a91dSDouglas Gregor   if (!Parent) {
8274ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
8289194a91dSDouglas Gregor     bool canInfer = false;
8294ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
8309194a91dSDouglas Gregor       // Figure out the parent path.
8314ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
8329194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
8339194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
8349194a91dSDouglas Gregor         // for a module map.
835e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
8369194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
8379194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
8389194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
8399194a91dSDouglas Gregor           // one.
840984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
841984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
842984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
843c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
8449194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
8459194a91dSDouglas Gregor           }
8469194a91dSDouglas Gregor 
8479194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
8489194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
8499194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
8509194a91dSDouglas Gregor         }
8519194a91dSDouglas Gregor 
8529194a91dSDouglas Gregor         if (inferred->second.InferModules) {
8539194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
8549194a91dSDouglas Gregor           // to infer this particular module.
8554ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
8569194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
8579194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
8589194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
8599194a91dSDouglas Gregor 
860c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
861c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
862c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
863ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
864ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
865beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
8669194a91dSDouglas Gregor         }
8679194a91dSDouglas Gregor       }
8689194a91dSDouglas Gregor     }
8699194a91dSDouglas Gregor 
8709194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
8719194a91dSDouglas Gregor     if (!canInfer)
872d2d442caSCraig Topper       return nullptr;
873beee15e7SBen Langmuir   } else
8749d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
8759194a91dSDouglas Gregor 
8769194a91dSDouglas Gregor 
87756c64013SDouglas Gregor   // Look for an umbrella header.
8782c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
87917381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
880e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
88156c64013SDouglas Gregor 
88256c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
88356c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
88456c64013SDouglas Gregor   // idea.
88556c64013SDouglas Gregor   if (!UmbrellaHeader)
886d2d442caSCraig Topper     return nullptr;
88756c64013SDouglas Gregor 
8889d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
889a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
890a7e2cc68SRichard Smith                               NumCreatedModules++);
8919d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
8929d6448b1SBen Langmuir   Result->IsInferred = true;
8937e82e019SRichard Smith   if (!Parent) {
8947e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
895ba7f2f71SDaniel Jasper       SourceModule = Result;
8967e82e019SRichard Smith     Modules[ModuleName] = Result;
897ba7f2f71SDaniel Jasper   }
898c1d88ea5SBen Langmuir 
899c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
900c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
901c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
902ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
9032b63d15fSRichard Smith   Result->Directory = FrameworkDir;
904a686e1b0SDouglas Gregor 
905322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
9062b63d15fSRichard Smith   //
9072b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
9082b63d15fSRichard Smith   // a framework module.
9092b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
910d8bd7537SDouglas Gregor 
911d8bd7537SDouglas Gregor   // export *
912d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
913d8bd7537SDouglas Gregor 
914a89c5ac4SDouglas Gregor   // module * { export * }
915a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
916a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
917a89c5ac4SDouglas Gregor 
918e89dbc1dSDouglas Gregor   // Look for subframeworks.
919c080917eSRafael Espindola   std::error_code EC;
9202c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
921ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
922e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
9232d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
924b171a59bSBruno Cardoso Lopes   vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
925b171a59bSBruno Cardoso Lopes   for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
926b171a59bSBruno Cardoso Lopes                                DirEnd;
927e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
928b171a59bSBruno Cardoso Lopes     if (!StringRef(Dir->getName()).endswith(".framework"))
929e89dbc1dSDouglas Gregor       continue;
930f2161a70SDouglas Gregor 
931b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
932b171a59bSBruno Cardoso Lopes             FileMgr.getDirectory(Dir->getName())) {
93307c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
93407c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
93507c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
93607c22b78SDouglas Gregor       // out to a top-level framework.
937e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
93807c22b78SDouglas Gregor       bool FoundParent = false;
93907c22b78SDouglas Gregor       do {
94007c22b78SDouglas Gregor         // Get the parent directory name.
94107c22b78SDouglas Gregor         SubframeworkDirName
94207c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
94307c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
94407c22b78SDouglas Gregor           break;
94507c22b78SDouglas Gregor 
94607c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
94707c22b78SDouglas Gregor           FoundParent = true;
94807c22b78SDouglas Gregor           break;
94907c22b78SDouglas Gregor         }
95007c22b78SDouglas Gregor       } while (true);
95107c22b78SDouglas Gregor 
95207c22b78SDouglas Gregor       if (!FoundParent)
95307c22b78SDouglas Gregor         continue;
95407c22b78SDouglas Gregor 
955e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
956a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
957e89dbc1dSDouglas Gregor     }
958e89dbc1dSDouglas Gregor   }
959e89dbc1dSDouglas Gregor 
96011dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
96111dfe6feSDouglas Gregor   // framework.
96211dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
96311dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
96411dfe6feSDouglas Gregor   }
96511dfe6feSDouglas Gregor 
96656c64013SDouglas Gregor   return Result;
96756c64013SDouglas Gregor }
96856c64013SDouglas Gregor 
9692b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
9702b63d15fSRichard Smith                                   Twine NameAsWritten) {
97197da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
97273141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
9732b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
9747033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
975b3a0fa48SBruno Cardoso Lopes 
976b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
977b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
978b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
979a89c5ac4SDouglas Gregor }
980a89c5ac4SDouglas Gregor 
9812b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
9822b63d15fSRichard Smith                                Twine NameAsWritten) {
983524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
9842b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
985524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
986524e33e1SDouglas Gregor }
987524e33e1SDouglas Gregor 
988*040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
989*040e1266SRichard Smith                                     Module::UnresolvedHeaderDirective Header) {
990*040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
991*040e1266SRichard Smith   // wrap the system header.
992*040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
993*040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
994*040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
995*040e1266SRichard Smith     // force the system header to be treated as a textual header in this
996*040e1266SRichard Smith     // case.
997*040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
998*040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
999*040e1266SRichard Smith     Header.HasBuiltinHeader = true;
10003c1a41adSRichard Smith   }
1001*040e1266SRichard Smith 
1002*040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1003*040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1004*040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1005*040e1266SRichard Smith   // headers.
1006*040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1007*040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1008*040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1009*040e1266SRichard Smith     // use the mtime as the key.
1010*040e1266SRichard Smith     if (Header.ModTime)
1011*040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1012*040e1266SRichard Smith     else
1013*040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1014*040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1015*040e1266SRichard Smith     return;
1016*040e1266SRichard Smith   }
1017*040e1266SRichard Smith 
1018*040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1019*040e1266SRichard Smith   // Perform the lookup now.
1020*040e1266SRichard Smith   resolveHeader(Mod, Header);
1021*040e1266SRichard Smith }
1022*040e1266SRichard Smith 
1023*040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1024*040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1025*040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1026*040e1266SRichard Smith     for (auto *M : BySize->second)
1027*040e1266SRichard Smith       resolveHeaderDirectives(M);
1028*040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1029*040e1266SRichard Smith   }
1030*040e1266SRichard Smith 
1031*040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1032*040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1033*040e1266SRichard Smith     for (auto *M : ByModTime->second)
1034*040e1266SRichard Smith       resolveHeaderDirectives(M);
1035*040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1036*040e1266SRichard Smith   }
1037*040e1266SRichard Smith }
1038*040e1266SRichard Smith 
1039*040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
1040*040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1041*040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1042*040e1266SRichard Smith     // the header information for this file.
1043*040e1266SRichard Smith     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header);
1044*040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
10450e98d938SNAKAMURA Takumi }
1046202210b3SRichard Smith 
10473c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1048d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1049386bb073SRichard Smith   KnownHeader KH(Mod, Role);
10503c1a41adSRichard Smith 
1051386bb073SRichard Smith   // Only add each header to the headers list once.
1052386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1053386bb073SRichard Smith   // same module definition?
1054386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1055386bb073SRichard Smith   for (auto H : HeaderList)
1056386bb073SRichard Smith     if (H == KH)
1057386bb073SRichard Smith       return;
1058386bb073SRichard Smith 
1059386bb073SRichard Smith   HeaderList.push_back(KH);
10601ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1061386bb073SRichard Smith 
10627e82e019SRichard Smith   bool isCompilingModuleHeader =
1063bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1064d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1065d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1066d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1067d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1068d8879c85SRichard Smith                                     isCompilingModuleHeader);
1069d8879c85SRichard Smith   }
1070e62cfd7cSBruno Cardoso Lopes 
1071e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1072e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1073f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1074a89c5ac4SDouglas Gregor }
1075a89c5ac4SDouglas Gregor 
10763c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1077feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1078feb54b6dSRichard Smith   // umbrella directory module.
1079feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1080feb54b6dSRichard Smith   // specified module?
10813c1a41adSRichard Smith   (void) Headers[Header.Entry];
10823c1a41adSRichard Smith 
10833c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1084feb54b6dSRichard Smith }
1085feb54b6dSRichard Smith 
1086514b636aSDouglas Gregor const FileEntry *
10874b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
10881f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1089d2d442caSCraig Topper     return nullptr;
1090514b636aSDouglas Gregor 
10911f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
10921f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1093514b636aSDouglas Gregor }
1094514b636aSDouglas Gregor 
10954b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
10969d6448b1SBen Langmuir   if (M->IsInferred) {
10979d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
10989d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
10999d6448b1SBen Langmuir   }
11009d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
11019d6448b1SBen Langmuir }
11029d6448b1SBen Langmuir 
11039d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
11049d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
11059d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
11069d6448b1SBen Langmuir }
11079d6448b1SBen Langmuir 
1108cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1109718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1110718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1111718292f2SDouglas Gregor                                         MEnd = Modules.end();
1112718292f2SDouglas Gregor        M != MEnd; ++M)
1113d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1114718292f2SDouglas Gregor 
1115718292f2SDouglas Gregor   llvm::errs() << "Headers:";
111659527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1117718292f2SDouglas Gregor        H != HEnd; ++H) {
111897da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
111997da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
112097da9178SDaniel Jasper                                                       E = H->second.end();
112197da9178SDaniel Jasper          I != E; ++I) {
112297da9178SDaniel Jasper       if (I != H->second.begin())
112397da9178SDaniel Jasper         llvm::errs() << ",";
112497da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
112597da9178SDaniel Jasper     }
112697da9178SDaniel Jasper     llvm::errs() << "\n";
1127718292f2SDouglas Gregor   }
1128718292f2SDouglas Gregor }
1129718292f2SDouglas Gregor 
11302b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
113142413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
113242413141SRichard Smith   Mod->UnresolvedExports.clear();
113342413141SRichard Smith   for (auto &UE : Unresolved) {
113442413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1135f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
11362b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
11372b82c2a5SDouglas Gregor     else
113842413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
11392b82c2a5SDouglas Gregor   }
114042413141SRichard Smith   return !Mod->UnresolvedExports.empty();
11412b82c2a5SDouglas Gregor }
11422b82c2a5SDouglas Gregor 
1143ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
114442413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
114542413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
114642413141SRichard Smith   for (auto &UDU : Unresolved) {
114742413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1148ba7f2f71SDaniel Jasper     if (DirectUse)
1149ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1150ba7f2f71SDaniel Jasper     else
115142413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1152ba7f2f71SDaniel Jasper   }
115342413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1154ba7f2f71SDaniel Jasper }
1155ba7f2f71SDaniel Jasper 
1156fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
115742413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
115842413141SRichard Smith   Mod->UnresolvedConflicts.clear();
115942413141SRichard Smith   for (auto &UC : Unresolved) {
116042413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1161fb912657SDouglas Gregor       Module::Conflict Conflict;
1162fb912657SDouglas Gregor       Conflict.Other = OtherMod;
116342413141SRichard Smith       Conflict.Message = UC.Message;
1164fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
116542413141SRichard Smith     } else
116642413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1167fb912657SDouglas Gregor   }
116842413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1169fb912657SDouglas Gregor }
1170fb912657SDouglas Gregor 
1171718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1172718292f2SDouglas Gregor // Module map file parser
1173718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1174718292f2SDouglas Gregor 
1175718292f2SDouglas Gregor namespace clang {
1176718292f2SDouglas Gregor   /// \brief A token in a module map file.
1177718292f2SDouglas Gregor   struct MMToken {
1178718292f2SDouglas Gregor     enum TokenKind {
11791fb5c3a6SDouglas Gregor       Comma,
118035b13eceSDouglas Gregor       ConfigMacros,
1181fb912657SDouglas Gregor       Conflict,
1182718292f2SDouglas Gregor       EndOfFile,
1183718292f2SDouglas Gregor       HeaderKeyword,
1184718292f2SDouglas Gregor       Identifier,
1185a3feee2aSRichard Smith       Exclaim,
118659527666SDouglas Gregor       ExcludeKeyword,
1187718292f2SDouglas Gregor       ExplicitKeyword,
11882b82c2a5SDouglas Gregor       ExportKeyword,
118997292843SDaniel Jasper       ExternKeyword,
1190755b2055SDouglas Gregor       FrameworkKeyword,
11916ddfca91SDouglas Gregor       LinkKeyword,
1192718292f2SDouglas Gregor       ModuleKeyword,
11932b82c2a5SDouglas Gregor       Period,
1194b53e5483SLawrence Crowl       PrivateKeyword,
1195718292f2SDouglas Gregor       UmbrellaKeyword,
1196ba7f2f71SDaniel Jasper       UseKeyword,
11971fb5c3a6SDouglas Gregor       RequiresKeyword,
11982b82c2a5SDouglas Gregor       Star,
1199718292f2SDouglas Gregor       StringLiteral,
1200*040e1266SRichard Smith       IntegerLiteral,
1201306d8920SRichard Smith       TextualKeyword,
1202718292f2SDouglas Gregor       LBrace,
1203a686e1b0SDouglas Gregor       RBrace,
1204a686e1b0SDouglas Gregor       LSquare,
1205a686e1b0SDouglas Gregor       RSquare
1206718292f2SDouglas Gregor     } Kind;
1207718292f2SDouglas Gregor 
1208718292f2SDouglas Gregor     unsigned Location;
1209718292f2SDouglas Gregor     unsigned StringLength;
1210*040e1266SRichard Smith     union {
1211*040e1266SRichard Smith       // If Kind != IntegerLiteral.
1212718292f2SDouglas Gregor       const char *StringData;
1213*040e1266SRichard Smith       // If Kind == IntegerLiteral.
1214*040e1266SRichard Smith       uint64_t IntegerValue;
1215*040e1266SRichard Smith     };
1216718292f2SDouglas Gregor 
1217718292f2SDouglas Gregor     void clear() {
1218718292f2SDouglas Gregor       Kind = EndOfFile;
1219718292f2SDouglas Gregor       Location = 0;
1220718292f2SDouglas Gregor       StringLength = 0;
1221d2d442caSCraig Topper       StringData = nullptr;
1222718292f2SDouglas Gregor     }
1223718292f2SDouglas Gregor 
1224718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1225718292f2SDouglas Gregor 
1226718292f2SDouglas Gregor     SourceLocation getLocation() const {
1227718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1228718292f2SDouglas Gregor     }
1229718292f2SDouglas Gregor 
1230*040e1266SRichard Smith     uint64_t getInteger() const {
1231*040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1232*040e1266SRichard Smith     }
1233*040e1266SRichard Smith 
1234718292f2SDouglas Gregor     StringRef getString() const {
1235*040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1236*040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1237718292f2SDouglas Gregor     }
1238718292f2SDouglas Gregor   };
1239718292f2SDouglas Gregor 
1240718292f2SDouglas Gregor   class ModuleMapParser {
1241718292f2SDouglas Gregor     Lexer &L;
1242718292f2SDouglas Gregor     SourceManager &SourceMgr;
1243bc10b9fbSDouglas Gregor 
1244bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
1245bc10b9fbSDouglas Gregor     /// parsing.
1246bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1247bc10b9fbSDouglas Gregor 
1248718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1249718292f2SDouglas Gregor     ModuleMap &Map;
1250718292f2SDouglas Gregor 
1251beee15e7SBen Langmuir     /// \brief The current module map file.
1252beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1253beee15e7SBen Langmuir 
12549acb99e3SRichard Smith     /// \brief The directory that file names in this module map file should
12559acb99e3SRichard Smith     /// be resolved relative to.
12565257fc63SDouglas Gregor     const DirectoryEntry *Directory;
12575257fc63SDouglas Gregor 
1258963c5535SDouglas Gregor     /// \brief Whether this module map is in a system header directory.
1259963c5535SDouglas Gregor     bool IsSystem;
1260963c5535SDouglas Gregor 
1261718292f2SDouglas Gregor     /// \brief Whether an error occurred.
1262718292f2SDouglas Gregor     bool HadError;
1263718292f2SDouglas Gregor 
1264718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
1265718292f2SDouglas Gregor     /// during parsing.
1266718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1267718292f2SDouglas Gregor 
1268718292f2SDouglas Gregor     /// \brief The current token.
1269718292f2SDouglas Gregor     MMToken Tok;
1270718292f2SDouglas Gregor 
1271718292f2SDouglas Gregor     /// \brief The active module.
1272de3ef502SDouglas Gregor     Module *ActiveModule;
1273718292f2SDouglas Gregor 
12747ff29148SBen Langmuir     /// \brief Whether a module uses the 'requires excluded' hack to mark its
12757ff29148SBen Langmuir     /// contents as 'textual'.
12767ff29148SBen Langmuir     ///
12777ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
12787ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
12797ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
12807ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
12817ff29148SBen Langmuir     /// 'textual' to match the original intent.
12827ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
12837ff29148SBen Langmuir 
1284718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
1285718292f2SDouglas Gregor     SourceLocation consumeToken();
1286718292f2SDouglas Gregor 
1287718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
1288718292f2SDouglas Gregor     /// (or the end of the file).
1289718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1290718292f2SDouglas Gregor 
1291f857950dSDmitri Gribenko     typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
1292e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1293718292f2SDouglas Gregor     void parseModuleDecl();
129497292843SDaniel Jasper     void parseExternModuleDecl();
12951fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1296b53e5483SLawrence Crowl     void parseHeaderDecl(clang::MMToken::TokenKind,
1297b53e5483SLawrence Crowl                          SourceLocation LeadingLoc);
1298524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
12992b82c2a5SDouglas Gregor     void parseExportDecl();
1300ba7f2f71SDaniel Jasper     void parseUseDecl();
13016ddfca91SDouglas Gregor     void parseLinkDecl();
130235b13eceSDouglas Gregor     void parseConfigMacros();
1303fb912657SDouglas Gregor     void parseConflict();
13049194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1305c1d88ea5SBen Langmuir 
1306c1d88ea5SBen Langmuir     typedef ModuleMap::Attributes Attributes;
13074442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1308718292f2SDouglas Gregor 
1309718292f2SDouglas Gregor   public:
1310718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
1311bc10b9fbSDouglas Gregor                              const TargetInfo *Target,
1312718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
13135257fc63SDouglas Gregor                              ModuleMap &Map,
1314beee15e7SBen Langmuir                              const FileEntry *ModuleMapFile,
13153ec6663bSDouglas Gregor                              const DirectoryEntry *Directory,
1316963c5535SDouglas Gregor                              bool IsSystem)
1317bc10b9fbSDouglas Gregor       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1318beee15e7SBen Langmuir         ModuleMapFile(ModuleMapFile), Directory(Directory),
13191d60987fSRichard Smith         IsSystem(IsSystem), HadError(false), ActiveModule(nullptr)
1320718292f2SDouglas Gregor     {
1321718292f2SDouglas Gregor       Tok.clear();
1322718292f2SDouglas Gregor       consumeToken();
1323718292f2SDouglas Gregor     }
1324718292f2SDouglas Gregor 
1325718292f2SDouglas Gregor     bool parseModuleMapFile();
13268128f332SRichard Smith 
13278128f332SRichard Smith     bool terminatedByDirective() { return false; }
13288128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1329718292f2SDouglas Gregor   };
1330ab9db510SAlexander Kornienko }
1331718292f2SDouglas Gregor 
1332718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1333718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1334718292f2SDouglas Gregor 
13358128f332SRichard Smith retry:
13368128f332SRichard Smith   Tok.clear();
1337718292f2SDouglas Gregor   Token LToken;
1338718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1339718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1340718292f2SDouglas Gregor   switch (LToken.getKind()) {
13412d57cea2SAlp Toker   case tok::raw_identifier: {
13422d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
13432d57cea2SAlp Toker     Tok.StringData = RI.data();
13442d57cea2SAlp Toker     Tok.StringLength = RI.size();
13452d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
134635b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1347fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
134859527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1349718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
13502b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
135197292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1352755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
135335b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
13546ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1355718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1356b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
13571fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1358306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1359718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1360ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1361718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1362718292f2SDouglas Gregor     break;
13632d57cea2SAlp Toker   }
1364718292f2SDouglas Gregor 
13651fb5c3a6SDouglas Gregor   case tok::comma:
13661fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
13671fb5c3a6SDouglas Gregor     break;
13681fb5c3a6SDouglas Gregor 
1369718292f2SDouglas Gregor   case tok::eof:
1370718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1371718292f2SDouglas Gregor     break;
1372718292f2SDouglas Gregor 
1373718292f2SDouglas Gregor   case tok::l_brace:
1374718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1375718292f2SDouglas Gregor     break;
1376718292f2SDouglas Gregor 
1377a686e1b0SDouglas Gregor   case tok::l_square:
1378a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1379a686e1b0SDouglas Gregor     break;
1380a686e1b0SDouglas Gregor 
13812b82c2a5SDouglas Gregor   case tok::period:
13822b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
13832b82c2a5SDouglas Gregor     break;
13842b82c2a5SDouglas Gregor 
1385718292f2SDouglas Gregor   case tok::r_brace:
1386718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1387718292f2SDouglas Gregor     break;
1388718292f2SDouglas Gregor 
1389a686e1b0SDouglas Gregor   case tok::r_square:
1390a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1391a686e1b0SDouglas Gregor     break;
1392a686e1b0SDouglas Gregor 
13932b82c2a5SDouglas Gregor   case tok::star:
13942b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
13952b82c2a5SDouglas Gregor     break;
13962b82c2a5SDouglas Gregor 
1397a3feee2aSRichard Smith   case tok::exclaim:
1398a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1399a3feee2aSRichard Smith     break;
1400a3feee2aSRichard Smith 
1401718292f2SDouglas Gregor   case tok::string_literal: {
1402d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1403d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1404d67aea28SRichard Smith       HadError = true;
1405d67aea28SRichard Smith       goto retry;
1406d67aea28SRichard Smith     }
1407d67aea28SRichard Smith 
1408718292f2SDouglas Gregor     // Parse the string literal.
1409718292f2SDouglas Gregor     LangOptions LangOpts;
14109d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1411718292f2SDouglas Gregor     if (StringLiteral.hadError)
1412718292f2SDouglas Gregor       goto retry;
1413718292f2SDouglas Gregor 
1414718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1415718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1416718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1417718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1418718292f2SDouglas Gregor     Saved[Length] = 0;
1419718292f2SDouglas Gregor 
1420718292f2SDouglas Gregor     // Form the token.
1421718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1422718292f2SDouglas Gregor     Tok.StringData = Saved;
1423718292f2SDouglas Gregor     Tok.StringLength = Length;
1424718292f2SDouglas Gregor     break;
1425718292f2SDouglas Gregor   }
1426718292f2SDouglas Gregor 
1427*040e1266SRichard Smith   case tok::numeric_constant: {
1428*040e1266SRichard Smith     // We don't support any suffixes or other complications.
1429*040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1430*040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1431*040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1432*040e1266SRichard Smith     unsigned Length =
1433*040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1434*040e1266SRichard Smith     uint64_t Value;
1435*040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1436*040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1437*040e1266SRichard Smith       HadError = true;
1438*040e1266SRichard Smith       goto retry;
1439*040e1266SRichard Smith     }
1440*040e1266SRichard Smith 
1441*040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1442*040e1266SRichard Smith     Tok.IntegerValue = Value;
1443*040e1266SRichard Smith     break;
1444*040e1266SRichard Smith   }
1445*040e1266SRichard Smith 
1446718292f2SDouglas Gregor   case tok::comment:
1447718292f2SDouglas Gregor     goto retry;
1448718292f2SDouglas Gregor 
14498128f332SRichard Smith   case tok::hash:
14508128f332SRichard Smith     // A module map can be terminated prematurely by
14518128f332SRichard Smith     //   #pragma clang module contents
14528128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
14538128f332SRichard Smith     // contents of the module.
14548128f332SRichard Smith     {
14558128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
14568128f332SRichard Smith         L.LexFromRawLexer(LToken);
14578128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
14588128f332SRichard Smith                LToken.getRawIdentifier() == Str;
14598128f332SRichard Smith       };
14608128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
14618128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
14628128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
14638128f332SRichard Smith         break;
14648128f332SRichard Smith       }
14658128f332SRichard Smith     }
14668128f332SRichard Smith     LLVM_FALLTHROUGH;
14678128f332SRichard Smith 
1468718292f2SDouglas Gregor   default:
14698128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1470718292f2SDouglas Gregor     HadError = true;
1471718292f2SDouglas Gregor     goto retry;
1472718292f2SDouglas Gregor   }
1473718292f2SDouglas Gregor 
1474718292f2SDouglas Gregor   return Result;
1475718292f2SDouglas Gregor }
1476718292f2SDouglas Gregor 
1477718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1478718292f2SDouglas Gregor   unsigned braceDepth = 0;
1479a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1480718292f2SDouglas Gregor   do {
1481718292f2SDouglas Gregor     switch (Tok.Kind) {
1482718292f2SDouglas Gregor     case MMToken::EndOfFile:
1483718292f2SDouglas Gregor       return;
1484718292f2SDouglas Gregor 
1485718292f2SDouglas Gregor     case MMToken::LBrace:
1486a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1487718292f2SDouglas Gregor         return;
1488718292f2SDouglas Gregor 
1489718292f2SDouglas Gregor       ++braceDepth;
1490718292f2SDouglas Gregor       break;
1491718292f2SDouglas Gregor 
1492a686e1b0SDouglas Gregor     case MMToken::LSquare:
1493a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1494a686e1b0SDouglas Gregor         return;
1495a686e1b0SDouglas Gregor 
1496a686e1b0SDouglas Gregor       ++squareDepth;
1497a686e1b0SDouglas Gregor       break;
1498a686e1b0SDouglas Gregor 
1499718292f2SDouglas Gregor     case MMToken::RBrace:
1500718292f2SDouglas Gregor       if (braceDepth > 0)
1501718292f2SDouglas Gregor         --braceDepth;
1502718292f2SDouglas Gregor       else if (Tok.is(K))
1503718292f2SDouglas Gregor         return;
1504718292f2SDouglas Gregor       break;
1505718292f2SDouglas Gregor 
1506a686e1b0SDouglas Gregor     case MMToken::RSquare:
1507a686e1b0SDouglas Gregor       if (squareDepth > 0)
1508a686e1b0SDouglas Gregor         --squareDepth;
1509a686e1b0SDouglas Gregor       else if (Tok.is(K))
1510a686e1b0SDouglas Gregor         return;
1511a686e1b0SDouglas Gregor       break;
1512a686e1b0SDouglas Gregor 
1513718292f2SDouglas Gregor     default:
1514a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1515718292f2SDouglas Gregor         return;
1516718292f2SDouglas Gregor       break;
1517718292f2SDouglas Gregor     }
1518718292f2SDouglas Gregor 
1519718292f2SDouglas Gregor    consumeToken();
1520718292f2SDouglas Gregor   } while (true);
1521718292f2SDouglas Gregor }
1522718292f2SDouglas Gregor 
1523e7ab3669SDouglas Gregor /// \brief Parse a module-id.
1524e7ab3669SDouglas Gregor ///
1525e7ab3669SDouglas Gregor ///   module-id:
1526e7ab3669SDouglas Gregor ///     identifier
1527e7ab3669SDouglas Gregor ///     identifier '.' module-id
1528e7ab3669SDouglas Gregor ///
1529e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1530e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1531e7ab3669SDouglas Gregor   Id.clear();
1532e7ab3669SDouglas Gregor   do {
15333cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1534e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1535e7ab3669SDouglas Gregor       consumeToken();
1536e7ab3669SDouglas Gregor     } else {
1537e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1538e7ab3669SDouglas Gregor       return true;
1539e7ab3669SDouglas Gregor     }
1540e7ab3669SDouglas Gregor 
1541e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1542e7ab3669SDouglas Gregor       break;
1543e7ab3669SDouglas Gregor 
1544e7ab3669SDouglas Gregor     consumeToken();
1545e7ab3669SDouglas Gregor   } while (true);
1546e7ab3669SDouglas Gregor 
1547e7ab3669SDouglas Gregor   return false;
1548e7ab3669SDouglas Gregor }
1549e7ab3669SDouglas Gregor 
1550a686e1b0SDouglas Gregor namespace {
1551a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
1552a686e1b0SDouglas Gregor   enum AttributeKind {
1553a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
1554a686e1b0SDouglas Gregor     AT_unknown,
1555a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
155635b13eceSDouglas Gregor     AT_system,
155777944868SRichard Smith     /// \brief The 'extern_c' attribute.
155877944868SRichard Smith     AT_extern_c,
155935b13eceSDouglas Gregor     /// \brief The 'exhaustive' attribute.
1560ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1561ed84df00SBruno Cardoso Lopes     /// \brief The 'no_undeclared_includes' attribute.
1562ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1563a686e1b0SDouglas Gregor   };
1564ab9db510SAlexander Kornienko }
1565a686e1b0SDouglas Gregor 
1566718292f2SDouglas Gregor /// \brief Parse a module declaration.
1567718292f2SDouglas Gregor ///
1568718292f2SDouglas Gregor ///   module-declaration:
156997292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1570a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1571a686e1b0SDouglas Gregor ///       { module-member* }
1572a686e1b0SDouglas Gregor ///
1573718292f2SDouglas Gregor ///   module-member:
15741fb5c3a6SDouglas Gregor ///     requires-declaration
1575718292f2SDouglas Gregor ///     header-declaration
1576e7ab3669SDouglas Gregor ///     submodule-declaration
15772b82c2a5SDouglas Gregor ///     export-declaration
15786ddfca91SDouglas Gregor ///     link-declaration
157973441091SDouglas Gregor ///
158073441091SDouglas Gregor ///   submodule-declaration:
158173441091SDouglas Gregor ///     module-declaration
158273441091SDouglas Gregor ///     inferred-submodule-declaration
1583718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1584755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
158597292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
158697292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
158797292843SDaniel Jasper     parseExternModuleDecl();
158897292843SDaniel Jasper     return;
158997292843SDaniel Jasper   }
159097292843SDaniel Jasper 
1591f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1592e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
1593718292f2SDouglas Gregor   bool Explicit = false;
1594f2161a70SDouglas Gregor   bool Framework = false;
1595755b2055SDouglas Gregor 
1596f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1597f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1598e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1599f2161a70SDouglas Gregor     Explicit = true;
1600f2161a70SDouglas Gregor   }
1601f2161a70SDouglas Gregor 
1602f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1603755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
1604755b2055SDouglas Gregor     consumeToken();
1605755b2055SDouglas Gregor     Framework = true;
1606755b2055SDouglas Gregor   }
1607718292f2SDouglas Gregor 
1608718292f2SDouglas Gregor   // Parse 'module' keyword.
1609718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1610d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1611718292f2SDouglas Gregor     consumeToken();
1612718292f2SDouglas Gregor     HadError = true;
1613718292f2SDouglas Gregor     return;
1614718292f2SDouglas Gregor   }
1615718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
1616718292f2SDouglas Gregor 
161773441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
161873441091SDouglas Gregor   // Parse it.
161973441091SDouglas Gregor   if (Tok.is(MMToken::Star))
16209194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
162173441091SDouglas Gregor 
1622718292f2SDouglas Gregor   // Parse the module name.
1623e7ab3669SDouglas Gregor   ModuleId Id;
1624e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1625718292f2SDouglas Gregor     HadError = true;
1626718292f2SDouglas Gregor     return;
1627718292f2SDouglas Gregor   }
1628e7ab3669SDouglas Gregor 
1629e7ab3669SDouglas Gregor   if (ActiveModule) {
1630e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1631e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1632e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1633e7ab3669SDouglas Gregor 
1634e7ab3669SDouglas Gregor       HadError = true;
1635e7ab3669SDouglas Gregor       return;
1636e7ab3669SDouglas Gregor     }
1637e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1638e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1639e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1640e7ab3669SDouglas Gregor     Explicit = false;
1641e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1642e7ab3669SDouglas Gregor     HadError = true;
1643e7ab3669SDouglas Gregor   }
1644e7ab3669SDouglas Gregor 
1645e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1646e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1647e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1648e7ab3669SDouglas Gregor     // is a submodule.
1649d2d442caSCraig Topper     ActiveModule = nullptr;
16504b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1651e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1652e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
16534b8a9e95SBen Langmuir         if (I == 0)
16544b8a9e95SBen Langmuir           TopLevelModule = Next;
1655e7ab3669SDouglas Gregor         ActiveModule = Next;
1656e7ab3669SDouglas Gregor         continue;
1657e7ab3669SDouglas Gregor       }
1658e7ab3669SDouglas Gregor 
1659e7ab3669SDouglas Gregor       if (ActiveModule) {
1660e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
16615b5d21eaSRichard Smith           << Id[I].first
16625b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1663e7ab3669SDouglas Gregor       } else {
1664e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1665e7ab3669SDouglas Gregor       }
1666e7ab3669SDouglas Gregor       HadError = true;
1667e7ab3669SDouglas Gregor       return;
1668e7ab3669SDouglas Gregor     }
16694b8a9e95SBen Langmuir 
16704b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
16714b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
16724b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
16734b8a9e95SBen Langmuir              "top-level module");
16744b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
16754b8a9e95SBen Langmuir     }
1676e7ab3669SDouglas Gregor   }
1677e7ab3669SDouglas Gregor 
1678e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1679e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1680718292f2SDouglas Gregor 
1681a686e1b0SDouglas Gregor   // Parse the optional attribute list.
16824442605fSBill Wendling   Attributes Attrs;
16835d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
16845d29dee0SDavide Italiano     return;
16855d29dee0SDavide Italiano 
1686a686e1b0SDouglas Gregor 
1687718292f2SDouglas Gregor   // Parse the opening brace.
1688718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1689718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1690718292f2SDouglas Gregor       << ModuleName;
1691718292f2SDouglas Gregor     HadError = true;
1692718292f2SDouglas Gregor     return;
1693718292f2SDouglas Gregor   }
1694718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1695718292f2SDouglas Gregor 
1696718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
1697eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
16984a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
16994a3751ffSRichard Smith     // definition for in two cases:
17004a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
17014a3751ffSRichard Smith     //    corresponding definition in a module map file, or
17024a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
17034a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
17044a3751ffSRichard Smith     //    module map file from which it was created.
17054a3751ffSRichard Smith     bool ParsedAsMainInput =
17064a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
17074a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
17084a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
17094a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
17104a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1711fcc54a3bSDouglas Gregor       // Skip the module definition.
1712fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1713fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1714fcc54a3bSDouglas Gregor         consumeToken();
1715fcc54a3bSDouglas Gregor       else {
1716fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1717fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1718fcc54a3bSDouglas Gregor         HadError = true;
1719fcc54a3bSDouglas Gregor       }
1720fcc54a3bSDouglas Gregor       return;
1721fcc54a3bSDouglas Gregor     }
1722fcc54a3bSDouglas Gregor 
1723718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1724718292f2SDouglas Gregor       << ModuleName;
1725eb90e830SDouglas Gregor     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1726718292f2SDouglas Gregor 
1727718292f2SDouglas Gregor     // Skip the module definition.
1728718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
1729718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
1730718292f2SDouglas Gregor       consumeToken();
1731718292f2SDouglas Gregor 
1732718292f2SDouglas Gregor     HadError = true;
1733718292f2SDouglas Gregor     return;
1734718292f2SDouglas Gregor   }
1735718292f2SDouglas Gregor 
1736718292f2SDouglas Gregor   // Start defining this module.
17379d6448b1SBen Langmuir   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
17389d6448b1SBen Langmuir                                         Explicit).first;
1739eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1740963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1741a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
174277944868SRichard Smith   if (Attrs.IsExternC)
174377944868SRichard Smith     ActiveModule->IsExternC = true;
1744ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1745ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1746ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
17473c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1748718292f2SDouglas Gregor 
17494d867640SGraydon Hoare   if (!ActiveModule->Parent) {
17504d867640SGraydon Hoare     StringRef MapFileName(ModuleMapFile->getName());
17514d867640SGraydon Hoare     if (MapFileName.endswith("module.private.modulemap") ||
17524d867640SGraydon Hoare         MapFileName.endswith("module_private.map")) {
17534d867640SGraydon Hoare       // Adding a top-level module from a private modulemap is likely a
17544d867640SGraydon Hoare       // user error; we check to see if there's another top-level module
17554d867640SGraydon Hoare       // defined in the non-private map in the same dir, and if so emit a
17564d867640SGraydon Hoare       // warning.
17574d867640SGraydon Hoare       for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
17584d867640SGraydon Hoare         auto const *M = E->getValue();
17594d867640SGraydon Hoare         if (!M->Parent &&
17604d867640SGraydon Hoare             M->Directory == ActiveModule->Directory &&
17614d867640SGraydon Hoare             M->Name != ActiveModule->Name) {
17624d867640SGraydon Hoare           Diags.Report(ActiveModule->DefinitionLoc,
17634d867640SGraydon Hoare                        diag::warn_mmap_mismatched_top_level_private)
17644d867640SGraydon Hoare             << ActiveModule->Name << M->Name;
17654d867640SGraydon Hoare           // The pattern we're defending against here is typically due to
17664d867640SGraydon Hoare           // a module named FooPrivate which is supposed to be a submodule
17674d867640SGraydon Hoare           // called Foo.Private. Emit a fixit in that case.
17684d867640SGraydon Hoare           auto D =
17694d867640SGraydon Hoare             Diags.Report(ActiveModule->DefinitionLoc,
17704d867640SGraydon Hoare                          diag::note_mmap_rename_top_level_private_as_submodule);
17714d867640SGraydon Hoare           D << ActiveModule->Name << M->Name;
17724d867640SGraydon Hoare           StringRef Bad(ActiveModule->Name);
17734d867640SGraydon Hoare           if (Bad.consume_back("Private")) {
17744d867640SGraydon Hoare             SmallString<128> Fixed = Bad;
17754d867640SGraydon Hoare             Fixed.append(".Private");
17764d867640SGraydon Hoare             D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc,
17774d867640SGraydon Hoare                                               Fixed);
17784d867640SGraydon Hoare           }
17794d867640SGraydon Hoare           break;
17804d867640SGraydon Hoare         }
17814d867640SGraydon Hoare       }
17824d867640SGraydon Hoare     }
17834d867640SGraydon Hoare   }
17844d867640SGraydon Hoare 
1785718292f2SDouglas Gregor   bool Done = false;
1786718292f2SDouglas Gregor   do {
1787718292f2SDouglas Gregor     switch (Tok.Kind) {
1788718292f2SDouglas Gregor     case MMToken::EndOfFile:
1789718292f2SDouglas Gregor     case MMToken::RBrace:
1790718292f2SDouglas Gregor       Done = true;
1791718292f2SDouglas Gregor       break;
1792718292f2SDouglas Gregor 
179335b13eceSDouglas Gregor     case MMToken::ConfigMacros:
179435b13eceSDouglas Gregor       parseConfigMacros();
179535b13eceSDouglas Gregor       break;
179635b13eceSDouglas Gregor 
1797fb912657SDouglas Gregor     case MMToken::Conflict:
1798fb912657SDouglas Gregor       parseConflict();
1799fb912657SDouglas Gregor       break;
1800fb912657SDouglas Gregor 
1801718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
180297292843SDaniel Jasper     case MMToken::ExternKeyword:
1803f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1804718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1805718292f2SDouglas Gregor       parseModuleDecl();
1806718292f2SDouglas Gregor       break;
1807718292f2SDouglas Gregor 
18082b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
18092b82c2a5SDouglas Gregor       parseExportDecl();
18102b82c2a5SDouglas Gregor       break;
18112b82c2a5SDouglas Gregor 
1812ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
1813ba7f2f71SDaniel Jasper       parseUseDecl();
1814ba7f2f71SDaniel Jasper       break;
1815ba7f2f71SDaniel Jasper 
18161fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
18171fb5c3a6SDouglas Gregor       parseRequiresDecl();
18181fb5c3a6SDouglas Gregor       break;
18191fb5c3a6SDouglas Gregor 
1820202210b3SRichard Smith     case MMToken::TextualKeyword:
1821202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1822306d8920SRichard Smith       break;
1823306d8920SRichard Smith 
1824524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1825524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1826524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
1827b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1828524e33e1SDouglas Gregor       else
1829524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1830718292f2SDouglas Gregor       break;
1831524e33e1SDouglas Gregor     }
1832718292f2SDouglas Gregor 
1833202210b3SRichard Smith     case MMToken::ExcludeKeyword:
1834202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
183559527666SDouglas Gregor       break;
183659527666SDouglas Gregor 
1837202210b3SRichard Smith     case MMToken::PrivateKeyword:
1838202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1839b53e5483SLawrence Crowl       break;
1840b53e5483SLawrence Crowl 
1841322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
1842202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
1843718292f2SDouglas Gregor       break;
1844718292f2SDouglas Gregor 
18456ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
18466ddfca91SDouglas Gregor       parseLinkDecl();
18476ddfca91SDouglas Gregor       break;
18486ddfca91SDouglas Gregor 
1849718292f2SDouglas Gregor     default:
1850718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1851718292f2SDouglas Gregor       consumeToken();
1852718292f2SDouglas Gregor       break;
1853718292f2SDouglas Gregor     }
1854718292f2SDouglas Gregor   } while (!Done);
1855718292f2SDouglas Gregor 
1856718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1857718292f2SDouglas Gregor     consumeToken();
1858718292f2SDouglas Gregor   else {
1859718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1860718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1861718292f2SDouglas Gregor     HadError = true;
1862718292f2SDouglas Gregor   }
1863718292f2SDouglas Gregor 
186411dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
186511dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
186611dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
186711dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
186811dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
186911dfe6feSDouglas Gregor   }
187011dfe6feSDouglas Gregor 
1871ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
1872ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
1873ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
1874ec8c9752SBen Langmuir       ActiveModule->Parent) {
1875ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
1876ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
1877ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
1878ec8c9752SBen Langmuir   }
1879ec8c9752SBen Langmuir 
1880e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
1881e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
1882718292f2SDouglas Gregor }
1883718292f2SDouglas Gregor 
188497292843SDaniel Jasper /// \brief Parse an extern module declaration.
188597292843SDaniel Jasper ///
188697292843SDaniel Jasper ///   extern module-declaration:
188797292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
188897292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
188997292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
1890ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
189197292843SDaniel Jasper 
189297292843SDaniel Jasper   // Parse 'module' keyword.
189397292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
189497292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
189597292843SDaniel Jasper     consumeToken();
189697292843SDaniel Jasper     HadError = true;
189797292843SDaniel Jasper     return;
189897292843SDaniel Jasper   }
189997292843SDaniel Jasper   consumeToken(); // 'module' keyword
190097292843SDaniel Jasper 
190197292843SDaniel Jasper   // Parse the module name.
190297292843SDaniel Jasper   ModuleId Id;
190397292843SDaniel Jasper   if (parseModuleId(Id)) {
190497292843SDaniel Jasper     HadError = true;
190597292843SDaniel Jasper     return;
190697292843SDaniel Jasper   }
190797292843SDaniel Jasper 
190897292843SDaniel Jasper   // Parse the referenced module map file name.
190997292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
191097292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
191197292843SDaniel Jasper     HadError = true;
191297292843SDaniel Jasper     return;
191397292843SDaniel Jasper   }
191497292843SDaniel Jasper   std::string FileName = Tok.getString();
191597292843SDaniel Jasper   consumeToken(); // filename
191697292843SDaniel Jasper 
191797292843SDaniel Jasper   StringRef FileNameRef = FileName;
191897292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
191997292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
192097292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
192197292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
192292e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
192397292843SDaniel Jasper   }
192497292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
19259acb99e3SRichard Smith     Map.parseModuleMapFile(
19269acb99e3SRichard Smith         File, /*IsSystem=*/false,
19279acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
19289acb99e3SRichard Smith             ? Directory
19298128f332SRichard Smith             : File->getDir(),
19308128f332SRichard Smith         FileID(), nullptr, ExternLoc);
193197292843SDaniel Jasper }
193297292843SDaniel Jasper 
19337ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
19347ff29148SBen Langmuir ///
19357ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
19367ff29148SBen Langmuir /// module map files:
19377ff29148SBen Langmuir ///
19387ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
19397ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
19407ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
19417ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
19427ff29148SBen Langmuir ///    module to 'textual'.
19437ff29148SBen Langmuir ///
19447ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
19457ff29148SBen Langmuir ///
19467ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
19477ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
19487ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
19497ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
19508013e81dSBenjamin Kramer   if (Feature == "excluded" &&
19518013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
19528013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
19537ff29148SBen Langmuir     IsRequiresExcludedHack = true;
19547ff29148SBen Langmuir     return false;
19558013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
19567ff29148SBen Langmuir     return false;
19577ff29148SBen Langmuir   }
19587ff29148SBen Langmuir 
19597ff29148SBen Langmuir   return true;
19607ff29148SBen Langmuir }
19617ff29148SBen Langmuir 
19621fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
19631fb5c3a6SDouglas Gregor ///
19641fb5c3a6SDouglas Gregor ///   requires-declaration:
19651fb5c3a6SDouglas Gregor ///     'requires' feature-list
19661fb5c3a6SDouglas Gregor ///
19671fb5c3a6SDouglas Gregor ///   feature-list:
1968a3feee2aSRichard Smith ///     feature ',' feature-list
1969a3feee2aSRichard Smith ///     feature
1970a3feee2aSRichard Smith ///
1971a3feee2aSRichard Smith ///   feature:
1972a3feee2aSRichard Smith ///     '!'[opt] identifier
19731fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
19741fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
19751fb5c3a6SDouglas Gregor 
19761fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
19771fb5c3a6SDouglas Gregor   consumeToken();
19781fb5c3a6SDouglas Gregor 
19791fb5c3a6SDouglas Gregor   // Parse the feature-list.
19801fb5c3a6SDouglas Gregor   do {
1981a3feee2aSRichard Smith     bool RequiredState = true;
1982a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
1983a3feee2aSRichard Smith       RequiredState = false;
1984a3feee2aSRichard Smith       consumeToken();
1985a3feee2aSRichard Smith     }
1986a3feee2aSRichard Smith 
19871fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
19881fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
19891fb5c3a6SDouglas Gregor       HadError = true;
19901fb5c3a6SDouglas Gregor       return;
19911fb5c3a6SDouglas Gregor     }
19921fb5c3a6SDouglas Gregor 
19931fb5c3a6SDouglas Gregor     // Consume the feature name.
19941fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
19951fb5c3a6SDouglas Gregor     consumeToken();
19961fb5c3a6SDouglas Gregor 
19977ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
19987ff29148SBen Langmuir     bool ShouldAddRequirement =
19997ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
20007ff29148SBen Langmuir 
20017ff29148SBen Langmuir     if (IsRequiresExcludedHack)
20027ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
20037ff29148SBen Langmuir 
20047ff29148SBen Langmuir     if (ShouldAddRequirement) {
20051fb5c3a6SDouglas Gregor       // Add this feature.
20067ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
20077ff29148SBen Langmuir                                    *Map.Target);
20087ff29148SBen Langmuir     }
20091fb5c3a6SDouglas Gregor 
20101fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
20111fb5c3a6SDouglas Gregor       break;
20121fb5c3a6SDouglas Gregor 
20131fb5c3a6SDouglas Gregor     // Consume the comma.
20141fb5c3a6SDouglas Gregor     consumeToken();
20151fb5c3a6SDouglas Gregor   } while (true);
20161fb5c3a6SDouglas Gregor }
20171fb5c3a6SDouglas Gregor 
2018718292f2SDouglas Gregor /// \brief Parse a header declaration.
2019718292f2SDouglas Gregor ///
2020718292f2SDouglas Gregor ///   header-declaration:
2021306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2022202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2023202210b3SRichard Smith ///     'exclude' 'header' string-literal
2024202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2025306d8920SRichard Smith ///
2026306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2027b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2028b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2029202210b3SRichard Smith   // We've already consumed the first token.
2030202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2031202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2032202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2033202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2034202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2035202210b3SRichard Smith       LeadingToken = Tok.Kind;
20361871ed3dSBenjamin Kramer       consumeToken();
2037202210b3SRichard Smith     }
2038202210b3SRichard Smith   }
20397ff29148SBen Langmuir 
2040202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2041202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2042202210b3SRichard Smith 
20437ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
20447ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
20457ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
20467ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
20477ff29148SBen Langmuir   }
20487ff29148SBen Langmuir 
2049202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2050202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2051202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2052202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2053202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2054202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2055202210b3SRichard Smith       return;
2056202210b3SRichard Smith     }
2057202210b3SRichard Smith     consumeToken();
2058202210b3SRichard Smith   }
2059718292f2SDouglas Gregor 
2060718292f2SDouglas Gregor   // Parse the header name.
2061718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2062718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2063718292f2SDouglas Gregor       << "header";
2064718292f2SDouglas Gregor     HadError = true;
2065718292f2SDouglas Gregor     return;
2066718292f2SDouglas Gregor   }
20673c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
20680761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
20690761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
20701d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2071*040e1266SRichard Smith   Header.Kind =
2072*040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2073*040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2074718292f2SDouglas Gregor 
2075524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
20761d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
20770761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2078524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2079322f633cSDouglas Gregor     HadError = true;
2080322f633cSDouglas Gregor     return;
2081322f633cSDouglas Gregor   }
2082322f633cSDouglas Gregor 
2083*040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2084*040e1266SRichard Smith   // the file.
2085*040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2086*040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
20873ec6663bSDouglas Gregor 
2088*040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2089*040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2090*040e1266SRichard Smith       StringRef Str = Tok.getString();
2091*040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2092*040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2093*040e1266SRichard Smith                   .Case("size", Size)
2094*040e1266SRichard Smith                   .Case("mtime", ModTime)
2095*040e1266SRichard Smith                   .Default(Unknown)) {
2096*040e1266SRichard Smith       case Size:
2097*040e1266SRichard Smith         if (Header.Size)
2098*040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2099*040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2100*040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2101*040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2102*040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2103*040e1266SRichard Smith           break;
2104*040e1266SRichard Smith         }
2105*040e1266SRichard Smith         Header.Size = Tok.getInteger();
2106*040e1266SRichard Smith         consumeToken();
2107*040e1266SRichard Smith         break;
2108*040e1266SRichard Smith 
2109*040e1266SRichard Smith       case ModTime:
2110*040e1266SRichard Smith         if (Header.ModTime)
2111*040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2112*040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2113*040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2114*040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2115*040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2116*040e1266SRichard Smith           break;
2117*040e1266SRichard Smith         }
2118*040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2119*040e1266SRichard Smith         consumeToken();
2120*040e1266SRichard Smith         break;
2121*040e1266SRichard Smith 
2122*040e1266SRichard Smith       case Unknown:
2123*040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2124*040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2125*040e1266SRichard Smith         break;
2126*040e1266SRichard Smith       }
21273ec6663bSDouglas Gregor     }
21285257fc63SDouglas Gregor 
2129*040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2130*040e1266SRichard Smith       consumeToken();
2131*040e1266SRichard Smith     else {
2132*040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2133*040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2134322f633cSDouglas Gregor       HadError = true;
2135322f633cSDouglas Gregor     }
21360101b540SHans Wennborg   }
213725d50758SRichard Smith 
2138*040e1266SRichard Smith   Map.addUnresolvedHeader(ActiveModule, std::move(Header));
2139718292f2SDouglas Gregor }
2140718292f2SDouglas Gregor 
214141f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
214241f81994SBen Langmuir                                 const Module::Header *B) {
214341f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
214441f81994SBen Langmuir }
214541f81994SBen Langmuir 
2146524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
2147524e33e1SDouglas Gregor ///
2148524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2149524e33e1SDouglas Gregor ///     umbrella string-literal
2150524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2151524e33e1SDouglas Gregor   // Parse the directory name.
2152524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2153524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2154524e33e1SDouglas Gregor       << "umbrella";
2155524e33e1SDouglas Gregor     HadError = true;
2156524e33e1SDouglas Gregor     return;
2157524e33e1SDouglas Gregor   }
2158524e33e1SDouglas Gregor 
2159524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2160524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2161524e33e1SDouglas Gregor 
2162524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2163524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2164524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2165524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2166524e33e1SDouglas Gregor     HadError = true;
2167524e33e1SDouglas Gregor     return;
2168524e33e1SDouglas Gregor   }
2169524e33e1SDouglas Gregor 
2170524e33e1SDouglas Gregor   // Look for this file.
2171d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2172524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2173524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2174524e33e1SDouglas Gregor   else {
21752c1dd271SDylan Noblesmith     SmallString<128> PathName;
2176524e33e1SDouglas Gregor     PathName = Directory->getName();
2177524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2178524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2179524e33e1SDouglas Gregor   }
2180524e33e1SDouglas Gregor 
2181524e33e1SDouglas Gregor   if (!Dir) {
2182a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2183524e33e1SDouglas Gregor       << DirName;
2184524e33e1SDouglas Gregor     return;
2185524e33e1SDouglas Gregor   }
2186524e33e1SDouglas Gregor 
21877ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
21887ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
21897ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
21907ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
21917ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
21927ff29148SBen Langmuir     std::error_code EC;
21937ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2194b171a59bSBruno Cardoso Lopes     vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
2195b171a59bSBruno Cardoso Lopes     for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
21967ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
2197b171a59bSBruno Cardoso Lopes       if (const FileEntry *FE =
2198b171a59bSBruno Cardoso Lopes               SourceMgr.getFileManager().getFile(I->getName())) {
21997ff29148SBen Langmuir 
2200b171a59bSBruno Cardoso Lopes         Module::Header Header = {I->getName(), FE};
22017ff29148SBen Langmuir         Headers.push_back(std::move(Header));
22027ff29148SBen Langmuir       }
22037ff29148SBen Langmuir     }
22047ff29148SBen Langmuir 
22057ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
220641f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
220741f81994SBen Langmuir 
22087ff29148SBen Langmuir     for (auto &Header : Headers)
22097ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
22107ff29148SBen Langmuir     return;
22117ff29148SBen Langmuir   }
22127ff29148SBen Langmuir 
2213524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2214524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2215524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2216524e33e1SDouglas Gregor     HadError = true;
2217524e33e1SDouglas Gregor     return;
2218524e33e1SDouglas Gregor   }
2219524e33e1SDouglas Gregor 
2220524e33e1SDouglas Gregor   // Record this umbrella directory.
22212b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2222524e33e1SDouglas Gregor }
2223524e33e1SDouglas Gregor 
22242b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
22252b82c2a5SDouglas Gregor ///
22262b82c2a5SDouglas Gregor ///   export-declaration:
22272b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
22282b82c2a5SDouglas Gregor ///
22292b82c2a5SDouglas Gregor ///   wildcard-module-id:
22302b82c2a5SDouglas Gregor ///     identifier
22312b82c2a5SDouglas Gregor ///     '*'
22322b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
22332b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
22342b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
22352b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
22362b82c2a5SDouglas Gregor 
22372b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
22382b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
22392b82c2a5SDouglas Gregor   bool Wildcard = false;
22402b82c2a5SDouglas Gregor   do {
2241306d8920SRichard Smith     // FIXME: Support string-literal module names here.
22422b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
22432b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
22442b82c2a5SDouglas Gregor                                               Tok.getLocation()));
22452b82c2a5SDouglas Gregor       consumeToken();
22462b82c2a5SDouglas Gregor 
22472b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
22482b82c2a5SDouglas Gregor         consumeToken();
22492b82c2a5SDouglas Gregor         continue;
22502b82c2a5SDouglas Gregor       }
22512b82c2a5SDouglas Gregor 
22522b82c2a5SDouglas Gregor       break;
22532b82c2a5SDouglas Gregor     }
22542b82c2a5SDouglas Gregor 
22552b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
22562b82c2a5SDouglas Gregor       Wildcard = true;
2257f5eedd05SDouglas Gregor       consumeToken();
22582b82c2a5SDouglas Gregor       break;
22592b82c2a5SDouglas Gregor     }
22602b82c2a5SDouglas Gregor 
2261ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
22622b82c2a5SDouglas Gregor     HadError = true;
22632b82c2a5SDouglas Gregor     return;
22642b82c2a5SDouglas Gregor   } while (true);
22652b82c2a5SDouglas Gregor 
22662b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
22672b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
22682b82c2a5SDouglas Gregor   };
22692b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
22702b82c2a5SDouglas Gregor }
22712b82c2a5SDouglas Gregor 
22728f4d3ff1SRichard Smith /// \brief Parse a module use declaration.
2273ba7f2f71SDaniel Jasper ///
22748f4d3ff1SRichard Smith ///   use-declaration:
22758f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2276ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2277ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
22788f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2279ba7f2f71SDaniel Jasper   // Parse the module-id.
2280ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
22813cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2282ba7f2f71SDaniel Jasper 
22838f4d3ff1SRichard Smith   if (ActiveModule->Parent)
22848f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
22858f4d3ff1SRichard Smith   else
2286ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2287ba7f2f71SDaniel Jasper }
2288ba7f2f71SDaniel Jasper 
22896ddfca91SDouglas Gregor /// \brief Parse a link declaration.
22906ddfca91SDouglas Gregor ///
22916ddfca91SDouglas Gregor ///   module-declaration:
22926ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
22936ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
22946ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
22956ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
22966ddfca91SDouglas Gregor 
22976ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
22986ddfca91SDouglas Gregor   bool IsFramework = false;
22996ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
23006ddfca91SDouglas Gregor     consumeToken();
23016ddfca91SDouglas Gregor     IsFramework = true;
23026ddfca91SDouglas Gregor   }
23036ddfca91SDouglas Gregor 
23046ddfca91SDouglas Gregor   // Parse the library name
23056ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
23066ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
23076ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
23086ddfca91SDouglas Gregor     HadError = true;
23096ddfca91SDouglas Gregor     return;
23106ddfca91SDouglas Gregor   }
23116ddfca91SDouglas Gregor 
23126ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
23136ddfca91SDouglas Gregor   consumeToken();
23146ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
23156ddfca91SDouglas Gregor                                                             IsFramework));
23166ddfca91SDouglas Gregor }
23176ddfca91SDouglas Gregor 
231835b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration.
231935b13eceSDouglas Gregor ///
232035b13eceSDouglas Gregor ///   module-declaration:
232135b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
232235b13eceSDouglas Gregor ///
232335b13eceSDouglas Gregor ///   config-macro-list:
232435b13eceSDouglas Gregor ///     identifier (',' identifier)?
232535b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
232635b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
232735b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
232835b13eceSDouglas Gregor 
232935b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
233035b13eceSDouglas Gregor   if (ActiveModule->Parent) {
233135b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
233235b13eceSDouglas Gregor   }
233335b13eceSDouglas Gregor 
233435b13eceSDouglas Gregor   // Parse the optional attributes.
233535b13eceSDouglas Gregor   Attributes Attrs;
23365d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
23375d29dee0SDavide Italiano     return;
23385d29dee0SDavide Italiano 
233935b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
234035b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
234135b13eceSDouglas Gregor   }
234235b13eceSDouglas Gregor 
234335b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2344306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
234535b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
234635b13eceSDouglas Gregor     return;
234735b13eceSDouglas Gregor 
234835b13eceSDouglas Gregor   // Consume the first identifier.
234935b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
235035b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
235135b13eceSDouglas Gregor   }
235235b13eceSDouglas Gregor   consumeToken();
235335b13eceSDouglas Gregor 
235435b13eceSDouglas Gregor   do {
235535b13eceSDouglas Gregor     // If there's a comma, consume it.
235635b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
235735b13eceSDouglas Gregor       break;
235835b13eceSDouglas Gregor     consumeToken();
235935b13eceSDouglas Gregor 
236035b13eceSDouglas Gregor     // We expect to see a macro name here.
2361306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
236235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
236335b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
236435b13eceSDouglas Gregor       break;
236535b13eceSDouglas Gregor     }
236635b13eceSDouglas Gregor 
236735b13eceSDouglas Gregor     // Consume the macro name.
236835b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
236935b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
237035b13eceSDouglas Gregor     }
237135b13eceSDouglas Gregor     consumeToken();
237235b13eceSDouglas Gregor   } while (true);
237335b13eceSDouglas Gregor }
237435b13eceSDouglas Gregor 
2375fb912657SDouglas Gregor /// \brief Format a module-id into a string.
2376fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2377fb912657SDouglas Gregor   std::string result;
2378fb912657SDouglas Gregor   {
2379fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2380fb912657SDouglas Gregor 
2381fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2382fb912657SDouglas Gregor       if (I)
2383fb912657SDouglas Gregor         OS << ".";
2384fb912657SDouglas Gregor       OS << Id[I].first;
2385fb912657SDouglas Gregor     }
2386fb912657SDouglas Gregor   }
2387fb912657SDouglas Gregor 
2388fb912657SDouglas Gregor   return result;
2389fb912657SDouglas Gregor }
2390fb912657SDouglas Gregor 
2391fb912657SDouglas Gregor /// \brief Parse a conflict declaration.
2392fb912657SDouglas Gregor ///
2393fb912657SDouglas Gregor ///   module-declaration:
2394fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2395fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2396fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2397fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2398fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2399fb912657SDouglas Gregor 
2400fb912657SDouglas Gregor   // Parse the module-id.
2401fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2402fb912657SDouglas Gregor     return;
2403fb912657SDouglas Gregor 
2404fb912657SDouglas Gregor   // Parse the ','.
2405fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2406fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2407fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2408fb912657SDouglas Gregor     return;
2409fb912657SDouglas Gregor   }
2410fb912657SDouglas Gregor   consumeToken();
2411fb912657SDouglas Gregor 
2412fb912657SDouglas Gregor   // Parse the message.
2413fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2414fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2415fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2416fb912657SDouglas Gregor     return;
2417fb912657SDouglas Gregor   }
2418fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2419fb912657SDouglas Gregor   consumeToken();
2420fb912657SDouglas Gregor 
2421fb912657SDouglas Gregor   // Add this unresolved conflict.
2422fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2423fb912657SDouglas Gregor }
2424fb912657SDouglas Gregor 
24256ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules).
24269194a91dSDouglas Gregor ///
24279194a91dSDouglas Gregor ///   module-declaration:
24289194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
24299194a91dSDouglas Gregor ///       { inferred-module-member* }
24309194a91dSDouglas Gregor ///
24319194a91dSDouglas Gregor ///   inferred-module-member:
24329194a91dSDouglas Gregor ///     'export' '*'
24339194a91dSDouglas Gregor ///     'exclude' identifier
24349194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
243573441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
243673441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
243773441091SDouglas Gregor   bool Failed = false;
243873441091SDouglas Gregor 
243973441091SDouglas Gregor   // Inferred modules must be submodules.
24409194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
244173441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
244273441091SDouglas Gregor     Failed = true;
244373441091SDouglas Gregor   }
244473441091SDouglas Gregor 
24459194a91dSDouglas Gregor   if (ActiveModule) {
2446524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
24474898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
24484898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
244973441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
245073441091SDouglas Gregor       Failed = true;
245173441091SDouglas Gregor     }
245273441091SDouglas Gregor 
245373441091SDouglas Gregor     // Check for redefinition of an inferred module.
2454dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
245573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2456dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2457dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
245873441091SDouglas Gregor                      diag::note_mmap_prev_definition);
245973441091SDouglas Gregor       Failed = true;
246073441091SDouglas Gregor     }
246173441091SDouglas Gregor 
24629194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
24639194a91dSDouglas Gregor     if (Framework) {
24649194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
24659194a91dSDouglas Gregor       Framework = false;
24669194a91dSDouglas Gregor     }
24679194a91dSDouglas Gregor   } else if (Explicit) {
24689194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
24699194a91dSDouglas Gregor     Explicit = false;
24709194a91dSDouglas Gregor   }
24719194a91dSDouglas Gregor 
247273441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
247373441091SDouglas Gregor   if (Failed) {
247473441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
247573441091SDouglas Gregor       consumeToken();
247673441091SDouglas Gregor       skipUntil(MMToken::RBrace);
247773441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
247873441091SDouglas Gregor         consumeToken();
247973441091SDouglas Gregor     }
248073441091SDouglas Gregor     HadError = true;
248173441091SDouglas Gregor     return;
248273441091SDouglas Gregor   }
248373441091SDouglas Gregor 
24849194a91dSDouglas Gregor   // Parse optional attributes.
24854442605fSBill Wendling   Attributes Attrs;
24865d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
24875d29dee0SDavide Italiano     return;
24889194a91dSDouglas Gregor 
24899194a91dSDouglas Gregor   if (ActiveModule) {
249073441091SDouglas Gregor     // Note that we have an inferred submodule.
2491dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2492dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2493dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
24949194a91dSDouglas Gregor   } else {
24959194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
24969194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2497c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2498beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2499131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
25009194a91dSDouglas Gregor   }
250173441091SDouglas Gregor 
250273441091SDouglas Gregor   // Parse the opening brace.
250373441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
250473441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
250573441091SDouglas Gregor     HadError = true;
250673441091SDouglas Gregor     return;
250773441091SDouglas Gregor   }
250873441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
250973441091SDouglas Gregor 
251073441091SDouglas Gregor   // Parse the body of the inferred submodule.
251173441091SDouglas Gregor   bool Done = false;
251273441091SDouglas Gregor   do {
251373441091SDouglas Gregor     switch (Tok.Kind) {
251473441091SDouglas Gregor     case MMToken::EndOfFile:
251573441091SDouglas Gregor     case MMToken::RBrace:
251673441091SDouglas Gregor       Done = true;
251773441091SDouglas Gregor       break;
251873441091SDouglas Gregor 
25199194a91dSDouglas Gregor     case MMToken::ExcludeKeyword: {
25209194a91dSDouglas Gregor       if (ActiveModule) {
25219194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2522d2d442caSCraig Topper           << (ActiveModule != nullptr);
25239194a91dSDouglas Gregor         consumeToken();
25249194a91dSDouglas Gregor         break;
25259194a91dSDouglas Gregor       }
25269194a91dSDouglas Gregor 
25279194a91dSDouglas Gregor       consumeToken();
2528306d8920SRichard Smith       // FIXME: Support string-literal module names here.
25299194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
25309194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
25319194a91dSDouglas Gregor         break;
25329194a91dSDouglas Gregor       }
25339194a91dSDouglas Gregor 
25349194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
25359194a91dSDouglas Gregor         .push_back(Tok.getString());
25369194a91dSDouglas Gregor       consumeToken();
25379194a91dSDouglas Gregor       break;
25389194a91dSDouglas Gregor     }
25399194a91dSDouglas Gregor 
25409194a91dSDouglas Gregor     case MMToken::ExportKeyword:
25419194a91dSDouglas Gregor       if (!ActiveModule) {
25429194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2543d2d442caSCraig Topper           << (ActiveModule != nullptr);
25449194a91dSDouglas Gregor         consumeToken();
25459194a91dSDouglas Gregor         break;
25469194a91dSDouglas Gregor       }
25479194a91dSDouglas Gregor 
254873441091SDouglas Gregor       consumeToken();
254973441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2550dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
255173441091SDouglas Gregor       else
255273441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
255373441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
255473441091SDouglas Gregor       consumeToken();
255573441091SDouglas Gregor       break;
255673441091SDouglas Gregor 
255773441091SDouglas Gregor     case MMToken::ExplicitKeyword:
255873441091SDouglas Gregor     case MMToken::ModuleKeyword:
255973441091SDouglas Gregor     case MMToken::HeaderKeyword:
2560b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
256173441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
256273441091SDouglas Gregor     default:
25639194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2564d2d442caSCraig Topper           << (ActiveModule != nullptr);
256573441091SDouglas Gregor       consumeToken();
256673441091SDouglas Gregor       break;
256773441091SDouglas Gregor     }
256873441091SDouglas Gregor   } while (!Done);
256973441091SDouglas Gregor 
257073441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
257173441091SDouglas Gregor     consumeToken();
257273441091SDouglas Gregor   else {
257373441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
257473441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
257573441091SDouglas Gregor     HadError = true;
257673441091SDouglas Gregor   }
257773441091SDouglas Gregor }
257873441091SDouglas Gregor 
25799194a91dSDouglas Gregor /// \brief Parse optional attributes.
25809194a91dSDouglas Gregor ///
25819194a91dSDouglas Gregor ///   attributes:
25829194a91dSDouglas Gregor ///     attribute attributes
25839194a91dSDouglas Gregor ///     attribute
25849194a91dSDouglas Gregor ///
25859194a91dSDouglas Gregor ///   attribute:
25869194a91dSDouglas Gregor ///     [ identifier ]
25879194a91dSDouglas Gregor ///
25889194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
25899194a91dSDouglas Gregor ///
25909194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
25914442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
25929194a91dSDouglas Gregor   bool HadError = false;
25939194a91dSDouglas Gregor 
25949194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
25959194a91dSDouglas Gregor     // Consume the '['.
25969194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
25979194a91dSDouglas Gregor 
25989194a91dSDouglas Gregor     // Check whether we have an attribute name here.
25999194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
26009194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
26019194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
26029194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
26039194a91dSDouglas Gregor         consumeToken();
26049194a91dSDouglas Gregor       HadError = true;
26059194a91dSDouglas Gregor     }
26069194a91dSDouglas Gregor 
26079194a91dSDouglas Gregor     // Decode the attribute name.
26089194a91dSDouglas Gregor     AttributeKind Attribute
26099194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
261035b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
261177944868SRichard Smith           .Case("extern_c", AT_extern_c)
2612ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
26139194a91dSDouglas Gregor           .Case("system", AT_system)
26149194a91dSDouglas Gregor           .Default(AT_unknown);
26159194a91dSDouglas Gregor     switch (Attribute) {
26169194a91dSDouglas Gregor     case AT_unknown:
26179194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
26189194a91dSDouglas Gregor         << Tok.getString();
26199194a91dSDouglas Gregor       break;
26209194a91dSDouglas Gregor 
26219194a91dSDouglas Gregor     case AT_system:
26229194a91dSDouglas Gregor       Attrs.IsSystem = true;
26239194a91dSDouglas Gregor       break;
262435b13eceSDouglas Gregor 
262577944868SRichard Smith     case AT_extern_c:
262677944868SRichard Smith       Attrs.IsExternC = true;
262777944868SRichard Smith       break;
262877944868SRichard Smith 
262935b13eceSDouglas Gregor     case AT_exhaustive:
263035b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
263135b13eceSDouglas Gregor       break;
2632ed84df00SBruno Cardoso Lopes 
2633ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2634ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2635ed84df00SBruno Cardoso Lopes       break;
26369194a91dSDouglas Gregor     }
26379194a91dSDouglas Gregor     consumeToken();
26389194a91dSDouglas Gregor 
26399194a91dSDouglas Gregor     // Consume the ']'.
26409194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
26419194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
26429194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
26439194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
26449194a91dSDouglas Gregor       HadError = true;
26459194a91dSDouglas Gregor     }
26469194a91dSDouglas Gregor 
26479194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
26489194a91dSDouglas Gregor       consumeToken();
26499194a91dSDouglas Gregor   }
26509194a91dSDouglas Gregor 
26519194a91dSDouglas Gregor   return HadError;
26529194a91dSDouglas Gregor }
26539194a91dSDouglas Gregor 
2654718292f2SDouglas Gregor /// \brief Parse a module map file.
2655718292f2SDouglas Gregor ///
2656718292f2SDouglas Gregor ///   module-map-file:
2657718292f2SDouglas Gregor ///     module-declaration*
2658718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2659718292f2SDouglas Gregor   do {
2660718292f2SDouglas Gregor     switch (Tok.Kind) {
2661718292f2SDouglas Gregor     case MMToken::EndOfFile:
2662718292f2SDouglas Gregor       return HadError;
2663718292f2SDouglas Gregor 
2664e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
266597292843SDaniel Jasper     case MMToken::ExternKeyword:
2666718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2667755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2668718292f2SDouglas Gregor       parseModuleDecl();
2669718292f2SDouglas Gregor       break;
2670718292f2SDouglas Gregor 
26711fb5c3a6SDouglas Gregor     case MMToken::Comma:
267235b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2673fb912657SDouglas Gregor     case MMToken::Conflict:
2674a3feee2aSRichard Smith     case MMToken::Exclaim:
267559527666SDouglas Gregor     case MMToken::ExcludeKeyword:
26762b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2677718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2678718292f2SDouglas Gregor     case MMToken::Identifier:
2679718292f2SDouglas Gregor     case MMToken::LBrace:
26806ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2681a686e1b0SDouglas Gregor     case MMToken::LSquare:
26822b82c2a5SDouglas Gregor     case MMToken::Period:
2683b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2684718292f2SDouglas Gregor     case MMToken::RBrace:
2685a686e1b0SDouglas Gregor     case MMToken::RSquare:
26861fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
26872b82c2a5SDouglas Gregor     case MMToken::Star:
2688718292f2SDouglas Gregor     case MMToken::StringLiteral:
2689*040e1266SRichard Smith     case MMToken::IntegerLiteral:
2690b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2691718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2692ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2693718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2694718292f2SDouglas Gregor       HadError = true;
2695718292f2SDouglas Gregor       consumeToken();
2696718292f2SDouglas Gregor       break;
2697718292f2SDouglas Gregor     }
2698718292f2SDouglas Gregor   } while (true);
2699718292f2SDouglas Gregor }
2700718292f2SDouglas Gregor 
27019acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
27028128f332SRichard Smith                                    const DirectoryEntry *Dir, FileID ID,
27038128f332SRichard Smith                                    unsigned *Offset,
2704ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
27058128f332SRichard Smith   assert(Target && "Missing target information");
27064ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
27074ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
27084ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
27094ddf2221SDouglas Gregor     return Known->second;
27104ddf2221SDouglas Gregor 
27118128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
27128128f332SRichard Smith   if (ID.isInvalid()) {
2713cb69b57bSBen Langmuir     auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
27148128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
27158128f332SRichard Smith   }
27168128f332SRichard Smith 
27178128f332SRichard Smith   assert(Target && "Missing target information");
27181f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2719718292f2SDouglas Gregor   if (!Buffer)
27204ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
27218128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
27228128f332SRichard Smith          "invalid buffer offset");
2723718292f2SDouglas Gregor 
2724718292f2SDouglas Gregor   // Parse this module map file.
27258128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
27268128f332SRichard Smith           Buffer->getBufferStart(),
27278128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
27288128f332SRichard Smith           Buffer->getBufferEnd());
27292a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2730beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
27311d60987fSRichard Smith                          IsSystem);
2732718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
27334ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
27342a6edb30SRichard Smith 
27358128f332SRichard Smith   if (Offset) {
27368128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
27378128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
27388128f332SRichard Smith     *Offset = Loc.second;
27398128f332SRichard Smith   }
27408128f332SRichard Smith 
27412a6edb30SRichard Smith   // Notify callbacks that we parsed it.
27422a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
27432a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
2744718292f2SDouglas Gregor   return Result;
2745718292f2SDouglas Gregor }
2746