1afd1b1c9SEugene Zelenko //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
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 //===----------------------------------------------------------------------===//
14afd1b1c9SEugene Zelenko 
15718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
16a7d03840SJordan Rose #include "clang/Basic/CharInfo.h"
17718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
18718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
19afd1b1c9SEugene Zelenko #include "clang/Basic/LLVM.h"
20afd1b1c9SEugene Zelenko #include "clang/Basic/LangOptions.h"
21afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h"
22afd1b1c9SEugene Zelenko #include "clang/Basic/SourceLocation.h"
23afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h"
24718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
25afd1b1c9SEugene Zelenko #include "clang/Basic/VirtualFileSystem.h"
26b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
279acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
283a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
293a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
303a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
31afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h"
32afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
33afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h"
34afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h"
35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
36afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h"
37afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
38afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h"
393a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
403a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
41718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
42afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h"
43afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
44afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
45552c169eSRafael Espindola #include "llvm/Support/Path.h"
46718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
47afd1b1c9SEugene Zelenko #include <algorithm>
48afd1b1c9SEugene Zelenko #include <cassert>
49afd1b1c9SEugene Zelenko #include <cstdint>
50afd1b1c9SEugene Zelenko #include <cstring>
51afd1b1c9SEugene Zelenko #include <string>
52afd1b1c9SEugene Zelenko #include <system_error>
53afd1b1c9SEugene Zelenko #include <utility>
54afd1b1c9SEugene Zelenko 
55718292f2SDouglas Gregor using namespace clang;
56718292f2SDouglas Gregor 
57040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
58040e1266SRichard Smith   switch ((int)Role) {
59040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
60040e1266SRichard Smith   case NormalHeader:
61040e1266SRichard Smith     return Module::HK_Normal;
62040e1266SRichard Smith   case PrivateHeader:
63040e1266SRichard Smith     return Module::HK_Private;
64040e1266SRichard Smith   case TextualHeader:
65040e1266SRichard Smith     return Module::HK_Textual;
66040e1266SRichard Smith   case PrivateHeader | TextualHeader:
67040e1266SRichard Smith     return Module::HK_PrivateTextual;
68040e1266SRichard Smith   }
69040e1266SRichard Smith }
70040e1266SRichard Smith 
71040e1266SRichard Smith ModuleMap::ModuleHeaderRole
72040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
73040e1266SRichard Smith   switch ((int)Kind) {
74040e1266SRichard Smith   case Module::HK_Normal:
75040e1266SRichard Smith     return NormalHeader;
76040e1266SRichard Smith   case Module::HK_Private:
77040e1266SRichard Smith     return PrivateHeader;
78040e1266SRichard Smith   case Module::HK_Textual:
79040e1266SRichard Smith     return TextualHeader;
80040e1266SRichard Smith   case Module::HK_PrivateTextual:
81040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
82040e1266SRichard Smith   case Module::HK_Excluded:
83040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
84040e1266SRichard Smith   }
85040e1266SRichard Smith   llvm_unreachable("unknown header kind");
86040e1266SRichard Smith }
87040e1266SRichard Smith 
882b82c2a5SDouglas Gregor Module::ExportDecl
892b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
902b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
91e4412640SArgyrios Kyrtzidis                          bool Complain) const {
92f5eedd05SDouglas Gregor   // We may have just a wildcard.
93f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
94f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
95d2d442caSCraig Topper     return Module::ExportDecl(nullptr, true);
96f5eedd05SDouglas Gregor   }
97f5eedd05SDouglas Gregor 
98fb912657SDouglas Gregor   // Resolve the module-id.
99fb912657SDouglas Gregor   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
100fb912657SDouglas Gregor   if (!Context)
101afd1b1c9SEugene Zelenko     return {};
102fb912657SDouglas Gregor 
103fb912657SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
104fb912657SDouglas Gregor }
105fb912657SDouglas Gregor 
106fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
107fb912657SDouglas Gregor                                    bool Complain) const {
1082b82c2a5SDouglas Gregor   // Find the starting module.
109fb912657SDouglas Gregor   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1102b82c2a5SDouglas Gregor   if (!Context) {
1112b82c2a5SDouglas Gregor     if (Complain)
1120761a8a0SDaniel Jasper       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
113fb912657SDouglas Gregor       << Id[0].first << Mod->getFullModuleName();
1142b82c2a5SDouglas Gregor 
115d2d442caSCraig Topper     return nullptr;
1162b82c2a5SDouglas Gregor   }
1172b82c2a5SDouglas Gregor 
1182b82c2a5SDouglas Gregor   // Dig into the module path.
119fb912657SDouglas Gregor   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
120fb912657SDouglas Gregor     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1212b82c2a5SDouglas Gregor     if (!Sub) {
1222b82c2a5SDouglas Gregor       if (Complain)
1230761a8a0SDaniel Jasper         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
124fb912657SDouglas Gregor         << Id[I].first << Context->getFullModuleName()
125fb912657SDouglas Gregor         << SourceRange(Id[0].second, Id[I-1].second);
1262b82c2a5SDouglas Gregor 
127d2d442caSCraig Topper       return nullptr;
1282b82c2a5SDouglas Gregor     }
1292b82c2a5SDouglas Gregor 
1302b82c2a5SDouglas Gregor     Context = Sub;
1312b82c2a5SDouglas Gregor   }
1322b82c2a5SDouglas Gregor 
133fb912657SDouglas Gregor   return Context;
1342b82c2a5SDouglas Gregor }
1352b82c2a5SDouglas Gregor 
1361d60987fSRichard Smith /// \brief Append to \p Paths the set of paths needed to get to the
1371d60987fSRichard Smith /// subframework in which the given module lives.
1381d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1391d60987fSRichard Smith                                     SmallVectorImpl<char> &Path) {
1401d60987fSRichard Smith   // Collect the framework names from the given module to the top-level module.
1411d60987fSRichard Smith   SmallVector<StringRef, 2> Paths;
1421d60987fSRichard Smith   for (; Mod; Mod = Mod->Parent) {
1431d60987fSRichard Smith     if (Mod->IsFramework)
1441d60987fSRichard Smith       Paths.push_back(Mod->Name);
1451d60987fSRichard Smith   }
1461d60987fSRichard Smith 
1471d60987fSRichard Smith   if (Paths.empty())
1481d60987fSRichard Smith     return;
1491d60987fSRichard Smith 
1501d60987fSRichard Smith   // Add Frameworks/Name.framework for each subframework.
1511d60987fSRichard Smith   for (unsigned I = Paths.size() - 1; I != 0; --I)
1521d60987fSRichard Smith     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1531d60987fSRichard Smith }
1541d60987fSRichard Smith 
1551d60987fSRichard Smith const FileEntry *
156040e1266SRichard Smith ModuleMap::findHeader(Module *M,
157040e1266SRichard Smith                       const Module::UnresolvedHeaderDirective &Header,
1581d60987fSRichard Smith                       SmallVectorImpl<char> &RelativePathName) {
159040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
160040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
161040e1266SRichard Smith     if (!File ||
162040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
163040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
164040e1266SRichard Smith       return nullptr;
165040e1266SRichard Smith     return File;
166040e1266SRichard Smith   };
167040e1266SRichard Smith 
1681d60987fSRichard Smith   if (llvm::sys::path::is_absolute(Header.FileName)) {
1691d60987fSRichard Smith     RelativePathName.clear();
1701d60987fSRichard Smith     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
171040e1266SRichard Smith     return GetFile(Header.FileName);
1721d60987fSRichard Smith   }
1731d60987fSRichard Smith 
1741d60987fSRichard Smith   // Search for the header file within the module's home directory.
1751d60987fSRichard Smith   auto *Directory = M->Directory;
1761d60987fSRichard Smith   SmallString<128> FullPathName(Directory->getName());
1771d60987fSRichard Smith   unsigned FullPathLength = FullPathName.size();
1781d60987fSRichard Smith 
1791d60987fSRichard Smith   if (M->isPartOfFramework()) {
1801d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1811d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
1821d60987fSRichard Smith 
1831d60987fSRichard Smith     // Check whether this file is in the public headers.
1841d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1851d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
186040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
1871d60987fSRichard Smith       return File;
1881d60987fSRichard Smith 
1891d60987fSRichard Smith     // Check whether this file is in the private headers.
1901d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
1911d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
1921d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
1931d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
1941d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
1951d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
1961d60987fSRichard Smith       RelativePathName.clear();
1971d60987fSRichard Smith     else
1981d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
1991d60987fSRichard Smith     FullPathName.resize(FullPathLength);
2001d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2011d60987fSRichard Smith                             Header.FileName);
2021d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
203040e1266SRichard Smith     return GetFile(FullPathName);
2041d60987fSRichard Smith   }
2051d60987fSRichard Smith 
2061d60987fSRichard Smith   // Lookup for normal headers.
2071d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
2081d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
209040e1266SRichard Smith   return GetFile(FullPathName);
2101d60987fSRichard Smith }
2111d60987fSRichard Smith 
212040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
213040e1266SRichard Smith                               const Module::UnresolvedHeaderDirective &Header) {
214040e1266SRichard Smith   SmallString<128> RelativePathName;
215040e1266SRichard Smith   if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
216040e1266SRichard Smith     if (Header.IsUmbrella) {
217040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
218040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
219040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
220040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
221040e1266SRichard Smith       else
222040e1266SRichard Smith         // Record this umbrella header.
223040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
224040e1266SRichard Smith     } else {
225040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
226040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
227040e1266SRichard Smith         excludeHeader(Mod, H);
228040e1266SRichard Smith       else
229040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
230040e1266SRichard Smith     }
231040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
232040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
233040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
234040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
235040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
236040e1266SRichard Smith   } else {
237040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
238040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
239040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
240040e1266SRichard Smith     // A missing header with stat information doesn't make the module
241040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
242040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
243040e1266SRichard Smith     // preprocessed source.)
244040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
245040e1266SRichard Smith       Mod->markUnavailable();
246040e1266SRichard Smith   }
247040e1266SRichard Smith }
248040e1266SRichard Smith 
249040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
250040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
251040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
252040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
253040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
254040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
255040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
256040e1266SRichard Smith     return false;
2571d60987fSRichard Smith 
2581d60987fSRichard Smith   // This is a system module with a top-level header. This header
2591d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
2601d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
261040e1266SRichard Smith   SmallString<128> Path;
262040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
263040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
264040e1266SRichard Smith   if (!File)
265040e1266SRichard Smith     return false;
266040e1266SRichard Smith 
267040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
268040e1266SRichard Smith   Module::Header H = {Path.str(), File};
269040e1266SRichard Smith   addHeader(Mod, H, Role);
270040e1266SRichard Smith   return true;
2711d60987fSRichard Smith }
2721d60987fSRichard Smith 
2730761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
274b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
275b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
2760761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
277056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
2780414b857SRichard Smith   MMapLangOpts.LineComment = true;
2790414b857SRichard Smith }
280718292f2SDouglas Gregor 
281718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
28221668754SDavide Italiano   for (auto &M : Modules)
28321668754SDavide Italiano     delete M.getValue();
2848587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
2858587dfd9SBruno Cardoso Lopes     delete M;
286718292f2SDouglas Gregor }
287718292f2SDouglas Gregor 
28889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
28989929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
29089929282SDouglas Gregor          "Improper target override");
29189929282SDouglas Gregor   this->Target = &Target;
29289929282SDouglas Gregor }
29389929282SDouglas Gregor 
294056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier.
295056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
296056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
297056396aeSDouglas Gregor   if (Name.empty())
298056396aeSDouglas Gregor     return Name;
299056396aeSDouglas Gregor 
300a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
301056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
302056396aeSDouglas Gregor     // create a buffer with the sanitized name.
303056396aeSDouglas Gregor     Buffer.clear();
304a7d03840SJordan Rose     if (isDigit(Name[0]))
305056396aeSDouglas Gregor       Buffer.push_back('_');
306056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
307056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
308a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
309056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
310056396aeSDouglas Gregor       else
311056396aeSDouglas Gregor         Buffer.push_back('_');
312056396aeSDouglas Gregor     }
313056396aeSDouglas Gregor 
314056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
315056396aeSDouglas Gregor   }
316056396aeSDouglas Gregor 
317056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
318056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
319056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
320056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
321056396aeSDouglas Gregor            .Default(false)) {
322056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
323056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
324056396aeSDouglas Gregor     Buffer.push_back('_');
325056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
326056396aeSDouglas Gregor   }
327056396aeSDouglas Gregor 
328056396aeSDouglas Gregor   return Name;
329056396aeSDouglas Gregor }
330056396aeSDouglas Gregor 
33134d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
33234d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
33334d52749SDouglas Gregor /// headers.
334ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
33534d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
33634d52749SDouglas Gregor            .Case("float.h", true)
33734d52749SDouglas Gregor            .Case("iso646.h", true)
33834d52749SDouglas Gregor            .Case("limits.h", true)
33934d52749SDouglas Gregor            .Case("stdalign.h", true)
34034d52749SDouglas Gregor            .Case("stdarg.h", true)
3413c4b1290SBen Langmuir            .Case("stdatomic.h", true)
34234d52749SDouglas Gregor            .Case("stdbool.h", true)
34334d52749SDouglas Gregor            .Case("stddef.h", true)
34434d52749SDouglas Gregor            .Case("stdint.h", true)
34534d52749SDouglas Gregor            .Case("tgmath.h", true)
34634d52749SDouglas Gregor            .Case("unwind.h", true)
34734d52749SDouglas Gregor            .Default(false);
34834d52749SDouglas Gregor }
34934d52749SDouglas Gregor 
35092669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
35192669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
352040e1266SRichard Smith   resolveHeaderDirectives(File);
35359527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
35447972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
35547972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
356ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3574eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
35892669ee4SDaniel Jasper     return Headers.find(File);
3594eaf0a6cSDaniel Jasper   }
36092669ee4SDaniel Jasper   return Known;
36192669ee4SDaniel Jasper }
36292669ee4SDaniel Jasper 
3634469138eSBen Langmuir ModuleMap::KnownHeader
3644469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
3654469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
36647972afdSRichard Smith   if (UmbrellaDirs.empty())
367afd1b1c9SEugene Zelenko     return {};
36847972afdSRichard Smith 
3694469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
3704469138eSBen Langmuir   assert(Dir && "file in no directory");
3714469138eSBen Langmuir 
3724469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
3734469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
3744469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
3754469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
3764469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
3774469138eSBen Langmuir 
3784469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
3794469138eSBen Langmuir   // an umbrella header.
3804469138eSBen Langmuir   do {
3814469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
3824469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
3834469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
3844469138eSBen Langmuir 
3854469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
3864469138eSBen Langmuir 
3874469138eSBen Langmuir     // Retrieve our parent path.
3884469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
3894469138eSBen Langmuir     if (DirName.empty())
3904469138eSBen Langmuir       break;
3914469138eSBen Langmuir 
3924469138eSBen Langmuir     // Resolve the parent path to a directory entry.
3934469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
3944469138eSBen Langmuir   } while (Dir);
395afd1b1c9SEugene Zelenko   return {};
3964469138eSBen Langmuir }
3974469138eSBen Langmuir 
39892669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
39992669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4004eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
40192669ee4SDaniel Jasper #ifndef NDEBUG
4024eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
40392669ee4SDaniel Jasper     // Check for consistency between the module header role
40492669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
40592669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4062708e520SRichard Smith     bool IsPrivate = false;
4072708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4084eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4094eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4102708e520SRichard Smith     for (auto *Hs : HeaderList)
4112708e520SRichard Smith       IsPrivate |=
4122708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4133c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4142708e520SRichard Smith           }) != Hs->end();
4154eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
41600bc95ecSRichard Smith   }
41792669ee4SDaniel Jasper #endif
4184eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
41992669ee4SDaniel Jasper }
42092669ee4SDaniel Jasper 
42171e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
42271e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
42371e1a64fSBen Langmuir }
42471e1a64fSBen Langmuir 
42592669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4268d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
42792669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
42892669ee4SDaniel Jasper                                         StringRef Filename,
42992669ee4SDaniel Jasper                                         const FileEntry *File) {
43092669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
43192669ee4SDaniel Jasper   // with no source files.
43271e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
43392669ee4SDaniel Jasper     return;
43492669ee4SDaniel Jasper 
435040e1266SRichard Smith   if (RequestingModule) {
43692669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
437040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
438040e1266SRichard Smith   }
43992669ee4SDaniel Jasper 
44071e1a64fSBen Langmuir   bool Excluded = false;
441d2d442caSCraig Topper   Module *Private = nullptr;
442d2d442caSCraig Topper   Module *NotUsed = nullptr;
44371e1a64fSBen Langmuir 
44471e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
44571e1a64fSBen Langmuir   if (Known != Headers.end()) {
44671e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
44792669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4484eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
44971e1a64fSBen Langmuir         Private = Header.getModule();
45092669ee4SDaniel Jasper         continue;
45192669ee4SDaniel Jasper       }
45292669ee4SDaniel Jasper 
45392669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
45492669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
45592669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4568f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
45771e1a64fSBen Langmuir         NotUsed = Header.getModule();
45892669ee4SDaniel Jasper         continue;
45992669ee4SDaniel Jasper       }
46092669ee4SDaniel Jasper 
46192669ee4SDaniel Jasper       // We have found a module that we can happily use.
46292669ee4SDaniel Jasper       return;
46392669ee4SDaniel Jasper     }
464feb54b6dSRichard Smith 
465feb54b6dSRichard Smith     Excluded = true;
46671e1a64fSBen Langmuir   }
46792669ee4SDaniel Jasper 
46892669ee4SDaniel Jasper   // We have found a header, but it is private.
469d2d442caSCraig Topper   if (Private) {
47011152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
47192669ee4SDaniel Jasper         << Filename;
47292669ee4SDaniel Jasper     return;
47392669ee4SDaniel Jasper   }
47492669ee4SDaniel Jasper 
47592669ee4SDaniel Jasper   // We have found a module, but we don't use it.
476d2d442caSCraig Topper   if (NotUsed) {
47711152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
4784ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
47992669ee4SDaniel Jasper     return;
48092669ee4SDaniel Jasper   }
48192669ee4SDaniel Jasper 
48271e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
48371e1a64fSBen Langmuir     return;
48471e1a64fSBen Langmuir 
48571e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
48671e1a64fSBen Langmuir 
48771e1a64fSBen Langmuir   if (LangOpts.ModulesStrictDeclUse) {
48811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
4894ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
490a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
491a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
492a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
49371e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
49471e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
49571e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
49670a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
49770a7738fSManman Ren         << File->getName();
49871e1a64fSBen Langmuir   }
49992669ee4SDaniel Jasper }
50092669ee4SDaniel Jasper 
501ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
502ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5038b7c0398SSean Silva   // Prefer available modules.
5048b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5058b7c0398SSean Silva     return true;
5068b7c0398SSean Silva 
507ec87a50aSRichard Smith   // Prefer a public header over a private header.
508ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
509ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
510ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
511ec87a50aSRichard Smith 
512ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
513ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
514ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
515ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
516ec87a50aSRichard Smith 
517ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
518ec87a50aSRichard Smith   return false;
519ec87a50aSRichard Smith }
520ec87a50aSRichard Smith 
521ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
522ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
523306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
524ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
525afd1b1c9SEugene Zelenko       return {};
526306d8920SRichard Smith     return R;
527306d8920SRichard Smith   };
528306d8920SRichard Smith 
5294881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5301fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
531202210b3SRichard Smith     ModuleMap::KnownHeader Result;
53297da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5334881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5347e82e019SRichard Smith       // Prefer a header from the source module over all others.
5357e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5362f633e7cSRichard Smith         return MakeResult(H);
5374881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5384881e8b2SSean Silva         Result = H;
53997da9178SDaniel Jasper     }
540306d8920SRichard Smith     return MakeResult(Result);
5411fb5c3a6SDouglas Gregor   }
542ab0c8a84SDouglas Gregor 
543386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
544386bb073SRichard Smith }
545386bb073SRichard Smith 
546386bb073SRichard Smith ModuleMap::KnownHeader
547386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
548386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
549386bb073SRichard Smith 
550f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5514469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5524469138eSBen Langmuir   if (H) {
5534469138eSBen Langmuir     Module *Result = H.getModule();
554930a85ccSDouglas Gregor 
555930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
55673141fa9SDouglas Gregor     // directory.
557930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
55873141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
559930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
560930a85ccSDouglas Gregor 
561930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
5629d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
5639d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
5649d6448b1SBen Langmuir 
565a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
566a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
567a89c5ac4SDouglas Gregor       // the actual header is located.
5689458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
5699458f82dSDouglas Gregor 
5707033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
571a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
572056396aeSDouglas Gregor         SmallString<32> NameBuf;
573056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
5744469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
5759d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5769d6448b1SBen Langmuir                                     Explicit).first;
5779d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
578ffbafa2aSBen Langmuir         Result->IsInferred = true;
579a89c5ac4SDouglas Gregor 
580a89c5ac4SDouglas Gregor         // Associate the module and the directory.
581a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
582a89c5ac4SDouglas Gregor 
583a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
584a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
585930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
586d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
587a89c5ac4SDouglas Gregor       }
588a89c5ac4SDouglas Gregor 
589a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
590056396aeSDouglas Gregor       SmallString<32> NameBuf;
591056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
592056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
5939d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5949d6448b1SBen Langmuir                                   Explicit).first;
5959d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
596ffbafa2aSBen Langmuir       Result->IsInferred = true;
5973c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
598a89c5ac4SDouglas Gregor 
599a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
600a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
601930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
602d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
603a89c5ac4SDouglas Gregor     } else {
604a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
605a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
606a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
607a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
608a89c5ac4SDouglas Gregor     }
609a89c5ac4SDouglas Gregor 
610386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
611386bb073SRichard Smith     Headers[File].push_back(Header);
612386bb073SRichard Smith     return Header;
613a89c5ac4SDouglas Gregor   }
614a89c5ac4SDouglas Gregor 
615afd1b1c9SEugene Zelenko   return {};
616ab0c8a84SDouglas Gregor }
617ab0c8a84SDouglas Gregor 
618386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
619386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
620040e1266SRichard Smith   resolveHeaderDirectives(File);
621386bb073SRichard Smith   auto It = Headers.find(File);
622386bb073SRichard Smith   if (It == Headers.end())
623386bb073SRichard Smith     return None;
624386bb073SRichard Smith   return It->second;
625386bb073SRichard Smith }
626386bb073SRichard Smith 
627e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
628d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
62950996ce1SRichard Smith }
63050996ce1SRichard Smith 
63162bcd925SDmitri Gribenko bool
63262bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
63362bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
634040e1266SRichard Smith   resolveHeaderDirectives(Header);
635e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
63697da9178SDaniel Jasper   if (Known != Headers.end()) {
63797da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
63897da9178SDaniel Jasper              I = Known->second.begin(),
63997da9178SDaniel Jasper              E = Known->second.end();
64097da9178SDaniel Jasper          I != E; ++I) {
641052d95a6SBruno Cardoso Lopes 
642052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
643052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
644052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
645052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
646052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
647052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
648052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
649052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
650052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
651052d95a6SBruno Cardoso Lopes           continue;
65297da9178SDaniel Jasper         return false;
65397da9178SDaniel Jasper       }
654052d95a6SBruno Cardoso Lopes     }
65597da9178SDaniel Jasper     return true;
65697da9178SDaniel Jasper   }
6571fb5c3a6SDouglas Gregor 
6581fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
659f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6601fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
6611fb5c3a6SDouglas Gregor 
66250996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
66350996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
66450996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
66550996ce1SRichard Smith   };
66650996ce1SRichard Smith 
6671fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
6681fb5c3a6SDouglas Gregor   // an umbrella header.
6691fb5c3a6SDouglas Gregor   do {
670e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
6711fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
6721fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
6731fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
67450996ce1SRichard Smith       if (IsUnavailable(Found))
6751fb5c3a6SDouglas Gregor         return true;
6761fb5c3a6SDouglas Gregor 
6771fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
6781fb5c3a6SDouglas Gregor       // directory.
6791fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
6801fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6811fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
6821fb5c3a6SDouglas Gregor 
6831fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
6841fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
6851fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
686056396aeSDouglas Gregor           SmallString<32> NameBuf;
687056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
688056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
689056396aeSDouglas Gregor                              NameBuf);
6901fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
6911fb5c3a6SDouglas Gregor           if (!Found)
6921fb5c3a6SDouglas Gregor             return false;
69350996ce1SRichard Smith           if (IsUnavailable(Found))
6941fb5c3a6SDouglas Gregor             return true;
6951fb5c3a6SDouglas Gregor         }
6961fb5c3a6SDouglas Gregor 
6971fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
698056396aeSDouglas Gregor         SmallString<32> NameBuf;
699056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
700056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
701056396aeSDouglas Gregor                            NameBuf);
7021fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7031fb5c3a6SDouglas Gregor         if (!Found)
7041fb5c3a6SDouglas Gregor           return false;
7051fb5c3a6SDouglas Gregor       }
7061fb5c3a6SDouglas Gregor 
70750996ce1SRichard Smith       return IsUnavailable(Found);
7081fb5c3a6SDouglas Gregor     }
7091fb5c3a6SDouglas Gregor 
7101fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7111fb5c3a6SDouglas Gregor 
7121fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7131fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7141fb5c3a6SDouglas Gregor     if (DirName.empty())
7151fb5c3a6SDouglas Gregor       break;
7161fb5c3a6SDouglas Gregor 
7171fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7181f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7191fb5c3a6SDouglas Gregor   } while (Dir);
7201fb5c3a6SDouglas Gregor 
7211fb5c3a6SDouglas Gregor   return false;
7221fb5c3a6SDouglas Gregor }
7231fb5c3a6SDouglas Gregor 
724e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
725e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
72688bdfb0eSDouglas Gregor   if (Known != Modules.end())
72788bdfb0eSDouglas Gregor     return Known->getValue();
72888bdfb0eSDouglas Gregor 
729d2d442caSCraig Topper   return nullptr;
73088bdfb0eSDouglas Gregor }
73188bdfb0eSDouglas Gregor 
732e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
733e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7342b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7352b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7362b82c2a5SDouglas Gregor       return Sub;
7372b82c2a5SDouglas Gregor   }
7382b82c2a5SDouglas Gregor 
7392b82c2a5SDouglas Gregor   return findModule(Name);
7402b82c2a5SDouglas Gregor }
7412b82c2a5SDouglas Gregor 
742e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7432b82c2a5SDouglas Gregor   if (!Context)
7442b82c2a5SDouglas Gregor     return findModule(Name);
7452b82c2a5SDouglas Gregor 
746eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7472b82c2a5SDouglas Gregor }
7482b82c2a5SDouglas Gregor 
749c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
750c192d194SBruno Cardoso Lopes                                                         Module *Parent,
751c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
752c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
75369021974SDouglas Gregor   // Try to find an existing module with this name.
754eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
755eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
75669021974SDouglas Gregor 
75769021974SDouglas Gregor   // Create a new module with this name.
7589ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7599ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
7606f722b4eSArgyrios Kyrtzidis   if (!Parent) {
7617e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
7627e82e019SRichard Smith       SourceModule = Result;
76369021974SDouglas Gregor     Modules[Name] = Result;
764c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
7656f722b4eSArgyrios Kyrtzidis   }
76669021974SDouglas Gregor   return std::make_pair(Result, true);
76769021974SDouglas Gregor }
76869021974SDouglas Gregor 
769dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
770056bf77fSRichard Smith   assert(!PendingGlobalModule && "created multiple global modules");
771056bf77fSRichard Smith   PendingGlobalModule.reset(
772056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
773056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
774056bf77fSRichard Smith   PendingGlobalModule->Kind = Module::GlobalModuleFragment;
775056bf77fSRichard Smith   return PendingGlobalModule.get();
776dd8b5337SRichard Smith }
777dd8b5337SRichard Smith 
778bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
779dd8b5337SRichard Smith                                                 StringRef Name,
780dd8b5337SRichard Smith                                                 Module *GlobalModule) {
781bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
782bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
783bbcc9f04SRichard Smith 
784bbcc9f04SRichard Smith   auto *Result =
785bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
786bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
787145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
788bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
789bbcc9f04SRichard Smith 
790dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
791056bf77fSRichard Smith   assert(GlobalModule == PendingGlobalModule.get() &&
792056bf77fSRichard Smith          "unexpected global module");
793dd8b5337SRichard Smith   GlobalModule->setParent(Result);
794056bf77fSRichard Smith   PendingGlobalModule.release(); // now owned by parent
795dd8b5337SRichard Smith 
796bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
797bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
798bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
799bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
800bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
801bbcc9f04SRichard Smith 
802bbcc9f04SRichard Smith   return Result;
803bbcc9f04SRichard Smith }
804bbcc9f04SRichard Smith 
80511dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we
80611dfe6feSDouglas Gregor /// should link.
80711dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
80811dfe6feSDouglas Gregor                                FileManager &FileMgr) {
80911dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
81011dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
81111dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
81211dfe6feSDouglas Gregor 
81311dfe6feSDouglas Gregor   SmallString<128> LibName;
81411dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
81511dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8168aaae5a9SJuergen Ributzka 
8178aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8188aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8198aaae5a9SJuergen Ributzka   // for both before we give up.
8208013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8218aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
82211dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
82311dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
82411dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8258aaae5a9SJuergen Ributzka       return;
8268aaae5a9SJuergen Ributzka     }
82711dfe6feSDouglas Gregor   }
82811dfe6feSDouglas Gregor }
82911dfe6feSDouglas Gregor 
830a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
831a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
832c1d88ea5SBen Langmuir   Attributes Attrs;
833c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
834a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
835c1d88ea5SBen Langmuir }
836c1d88ea5SBen Langmuir 
837a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
838c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
839a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
840a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
841a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
842a525400dSBen Langmuir   // top-level framework.
843a525400dSBen Langmuir   StringRef FrameworkDirName =
844a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
845a525400dSBen Langmuir 
846a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
847a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
848a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
849a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
850a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
851a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
852c1d88ea5SBen Langmuir 
85356c64013SDouglas Gregor   // Check whether we've already found this module.
854e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
855e89dbc1dSDouglas Gregor     return Mod;
856e89dbc1dSDouglas Gregor 
8571f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
85856c64013SDouglas Gregor 
8599194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
8609194a91dSDouglas Gregor   // a framework module, do so.
861beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
8629194a91dSDouglas Gregor   if (!Parent) {
8634ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
8649194a91dSDouglas Gregor     bool canInfer = false;
8654ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
8669194a91dSDouglas Gregor       // Figure out the parent path.
8674ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
8689194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
8699194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
8709194a91dSDouglas Gregor         // for a module map.
871e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
8729194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
8739194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
8749194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
8759194a91dSDouglas Gregor           // one.
876984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
877984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
878984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
879c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
8809194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
8819194a91dSDouglas Gregor           }
8829194a91dSDouglas Gregor 
8839194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
8849194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
8859194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
8869194a91dSDouglas Gregor         }
8879194a91dSDouglas Gregor 
8889194a91dSDouglas Gregor         if (inferred->second.InferModules) {
8899194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
8909194a91dSDouglas Gregor           // to infer this particular module.
8914ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
8929194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
8939194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
8949194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
8959194a91dSDouglas Gregor 
896c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
897c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
898c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
899ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
900ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
901beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9029194a91dSDouglas Gregor         }
9039194a91dSDouglas Gregor       }
9049194a91dSDouglas Gregor     }
9059194a91dSDouglas Gregor 
9069194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9079194a91dSDouglas Gregor     if (!canInfer)
908d2d442caSCraig Topper       return nullptr;
909beee15e7SBen Langmuir   } else
9109d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9119194a91dSDouglas Gregor 
9129194a91dSDouglas Gregor 
91356c64013SDouglas Gregor   // Look for an umbrella header.
9142c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
91517381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
916e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
91756c64013SDouglas Gregor 
91856c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
91956c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
92056c64013SDouglas Gregor   // idea.
92156c64013SDouglas Gregor   if (!UmbrellaHeader)
922d2d442caSCraig Topper     return nullptr;
92356c64013SDouglas Gregor 
9249d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
925a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
926a7e2cc68SRichard Smith                               NumCreatedModules++);
9279d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
9289d6448b1SBen Langmuir   Result->IsInferred = true;
9297e82e019SRichard Smith   if (!Parent) {
9307e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
931ba7f2f71SDaniel Jasper       SourceModule = Result;
9327e82e019SRichard Smith     Modules[ModuleName] = Result;
933c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
934ba7f2f71SDaniel Jasper   }
935c1d88ea5SBen Langmuir 
936c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
937c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
938c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
939ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
9402b63d15fSRichard Smith   Result->Directory = FrameworkDir;
941a686e1b0SDouglas Gregor 
942322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
9432b63d15fSRichard Smith   //
9442b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
9452b63d15fSRichard Smith   // a framework module.
9462b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
947d8bd7537SDouglas Gregor 
948d8bd7537SDouglas Gregor   // export *
949d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
950d8bd7537SDouglas Gregor 
951a89c5ac4SDouglas Gregor   // module * { export * }
952a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
953a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
954a89c5ac4SDouglas Gregor 
955e89dbc1dSDouglas Gregor   // Look for subframeworks.
956c080917eSRafael Espindola   std::error_code EC;
9572c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
958ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
959e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
9602d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
961b171a59bSBruno Cardoso Lopes   vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
962b171a59bSBruno Cardoso Lopes   for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
963b171a59bSBruno Cardoso Lopes                                DirEnd;
964e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
965b171a59bSBruno Cardoso Lopes     if (!StringRef(Dir->getName()).endswith(".framework"))
966e89dbc1dSDouglas Gregor       continue;
967f2161a70SDouglas Gregor 
968b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
969b171a59bSBruno Cardoso Lopes             FileMgr.getDirectory(Dir->getName())) {
97007c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
97107c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
97207c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
97307c22b78SDouglas Gregor       // out to a top-level framework.
974e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
97507c22b78SDouglas Gregor       bool FoundParent = false;
97607c22b78SDouglas Gregor       do {
97707c22b78SDouglas Gregor         // Get the parent directory name.
97807c22b78SDouglas Gregor         SubframeworkDirName
97907c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
98007c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
98107c22b78SDouglas Gregor           break;
98207c22b78SDouglas Gregor 
98307c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
98407c22b78SDouglas Gregor           FoundParent = true;
98507c22b78SDouglas Gregor           break;
98607c22b78SDouglas Gregor         }
98707c22b78SDouglas Gregor       } while (true);
98807c22b78SDouglas Gregor 
98907c22b78SDouglas Gregor       if (!FoundParent)
99007c22b78SDouglas Gregor         continue;
99107c22b78SDouglas Gregor 
992e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
993a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
994e89dbc1dSDouglas Gregor     }
995e89dbc1dSDouglas Gregor   }
996e89dbc1dSDouglas Gregor 
99711dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
99811dfe6feSDouglas Gregor   // framework.
99911dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
100011dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
100111dfe6feSDouglas Gregor   }
100211dfe6feSDouglas Gregor 
100356c64013SDouglas Gregor   return Result;
100456c64013SDouglas Gregor }
100556c64013SDouglas Gregor 
10068587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10078587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10088587dfd9SBruno Cardoso Lopes 
10098587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10108587dfd9SBruno Cardoso Lopes   Module *Result =
10118587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10128587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10138587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
10148587dfd9SBruno Cardoso Lopes   Result->IsAvailable = false;
1015c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10168587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
10178587dfd9SBruno Cardoso Lopes 
10188587dfd9SBruno Cardoso Lopes   return Result;
10198587dfd9SBruno Cardoso Lopes }
10208587dfd9SBruno Cardoso Lopes 
10212b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
10222b63d15fSRichard Smith                                   Twine NameAsWritten) {
102397da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
102473141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
10252b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
10267033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1027b3a0fa48SBruno Cardoso Lopes 
1028b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1029b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1030b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1031a89c5ac4SDouglas Gregor }
1032a89c5ac4SDouglas Gregor 
10332b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
10342b63d15fSRichard Smith                                Twine NameAsWritten) {
1035524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
10362b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1037524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1038524e33e1SDouglas Gregor }
1039524e33e1SDouglas Gregor 
1040040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
1041040e1266SRichard Smith                                     Module::UnresolvedHeaderDirective Header) {
1042040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1043040e1266SRichard Smith   // wrap the system header.
1044040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1045040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1046040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1047040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1048040e1266SRichard Smith     // case.
1049040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1050040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1051040e1266SRichard Smith     Header.HasBuiltinHeader = true;
10523c1a41adSRichard Smith   }
1053040e1266SRichard Smith 
1054040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1055040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1056040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1057040e1266SRichard Smith   // headers.
1058040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1059040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1060040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1061040e1266SRichard Smith     // use the mtime as the key.
1062040e1266SRichard Smith     if (Header.ModTime)
1063040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1064040e1266SRichard Smith     else
1065040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1066040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1067040e1266SRichard Smith     return;
1068040e1266SRichard Smith   }
1069040e1266SRichard Smith 
1070040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1071040e1266SRichard Smith   // Perform the lookup now.
1072040e1266SRichard Smith   resolveHeader(Mod, Header);
1073040e1266SRichard Smith }
1074040e1266SRichard Smith 
1075040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1076040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1077040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1078040e1266SRichard Smith     for (auto *M : BySize->second)
1079040e1266SRichard Smith       resolveHeaderDirectives(M);
1080040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1081040e1266SRichard Smith   }
1082040e1266SRichard Smith 
1083040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1084040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1085040e1266SRichard Smith     for (auto *M : ByModTime->second)
1086040e1266SRichard Smith       resolveHeaderDirectives(M);
1087040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1088040e1266SRichard Smith   }
1089040e1266SRichard Smith }
1090040e1266SRichard Smith 
1091040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
1092040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1093040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1094040e1266SRichard Smith     // the header information for this file.
1095040e1266SRichard Smith     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header);
1096040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
10970e98d938SNAKAMURA Takumi }
1098202210b3SRichard Smith 
10993c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1100d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1101386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11023c1a41adSRichard Smith 
1103386bb073SRichard Smith   // Only add each header to the headers list once.
1104386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1105386bb073SRichard Smith   // same module definition?
1106386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1107386bb073SRichard Smith   for (auto H : HeaderList)
1108386bb073SRichard Smith     if (H == KH)
1109386bb073SRichard Smith       return;
1110386bb073SRichard Smith 
1111386bb073SRichard Smith   HeaderList.push_back(KH);
11121ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1113386bb073SRichard Smith 
11147e82e019SRichard Smith   bool isCompilingModuleHeader =
1115bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1116d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1117d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1118d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1119d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1120d8879c85SRichard Smith                                     isCompilingModuleHeader);
1121d8879c85SRichard Smith   }
1122e62cfd7cSBruno Cardoso Lopes 
1123e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1124e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1125f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1126a89c5ac4SDouglas Gregor }
1127a89c5ac4SDouglas Gregor 
11283c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1129feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1130feb54b6dSRichard Smith   // umbrella directory module.
1131feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1132feb54b6dSRichard Smith   // specified module?
11333c1a41adSRichard Smith   (void) Headers[Header.Entry];
11343c1a41adSRichard Smith 
11353c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1136feb54b6dSRichard Smith }
1137feb54b6dSRichard Smith 
1138514b636aSDouglas Gregor const FileEntry *
11394b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
11401f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1141d2d442caSCraig Topper     return nullptr;
1142514b636aSDouglas Gregor 
11431f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
11441f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1145514b636aSDouglas Gregor }
1146514b636aSDouglas Gregor 
11474b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
11489d6448b1SBen Langmuir   if (M->IsInferred) {
11499d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
11509d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
11519d6448b1SBen Langmuir   }
11529d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
11539d6448b1SBen Langmuir }
11549d6448b1SBen Langmuir 
11559d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
11569d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
11579d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
11589d6448b1SBen Langmuir }
11599d6448b1SBen Langmuir 
1160cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1161718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1162718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1163718292f2SDouglas Gregor                                         MEnd = Modules.end();
1164718292f2SDouglas Gregor        M != MEnd; ++M)
1165d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1166718292f2SDouglas Gregor 
1167718292f2SDouglas Gregor   llvm::errs() << "Headers:";
116859527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1169718292f2SDouglas Gregor        H != HEnd; ++H) {
117097da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
117197da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
117297da9178SDaniel Jasper                                                       E = H->second.end();
117397da9178SDaniel Jasper          I != E; ++I) {
117497da9178SDaniel Jasper       if (I != H->second.begin())
117597da9178SDaniel Jasper         llvm::errs() << ",";
117697da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
117797da9178SDaniel Jasper     }
117897da9178SDaniel Jasper     llvm::errs() << "\n";
1179718292f2SDouglas Gregor   }
1180718292f2SDouglas Gregor }
1181718292f2SDouglas Gregor 
11822b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
118342413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
118442413141SRichard Smith   Mod->UnresolvedExports.clear();
118542413141SRichard Smith   for (auto &UE : Unresolved) {
118642413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1187f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
11882b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
11892b82c2a5SDouglas Gregor     else
119042413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
11912b82c2a5SDouglas Gregor   }
119242413141SRichard Smith   return !Mod->UnresolvedExports.empty();
11932b82c2a5SDouglas Gregor }
11942b82c2a5SDouglas Gregor 
1195ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
119642413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
119742413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
119842413141SRichard Smith   for (auto &UDU : Unresolved) {
119942413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1200ba7f2f71SDaniel Jasper     if (DirectUse)
1201ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1202ba7f2f71SDaniel Jasper     else
120342413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1204ba7f2f71SDaniel Jasper   }
120542413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1206ba7f2f71SDaniel Jasper }
1207ba7f2f71SDaniel Jasper 
1208fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
120942413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
121042413141SRichard Smith   Mod->UnresolvedConflicts.clear();
121142413141SRichard Smith   for (auto &UC : Unresolved) {
121242413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1213fb912657SDouglas Gregor       Module::Conflict Conflict;
1214fb912657SDouglas Gregor       Conflict.Other = OtherMod;
121542413141SRichard Smith       Conflict.Message = UC.Message;
1216fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
121742413141SRichard Smith     } else
121842413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1219fb912657SDouglas Gregor   }
122042413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1221fb912657SDouglas Gregor }
1222fb912657SDouglas Gregor 
1223718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1224718292f2SDouglas Gregor // Module map file parser
1225718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1226718292f2SDouglas Gregor 
1227718292f2SDouglas Gregor namespace clang {
1228afd1b1c9SEugene Zelenko 
1229718292f2SDouglas Gregor   /// \brief A token in a module map file.
1230718292f2SDouglas Gregor   struct MMToken {
1231718292f2SDouglas Gregor     enum TokenKind {
12321fb5c3a6SDouglas Gregor       Comma,
123335b13eceSDouglas Gregor       ConfigMacros,
1234fb912657SDouglas Gregor       Conflict,
1235718292f2SDouglas Gregor       EndOfFile,
1236718292f2SDouglas Gregor       HeaderKeyword,
1237718292f2SDouglas Gregor       Identifier,
1238a3feee2aSRichard Smith       Exclaim,
123959527666SDouglas Gregor       ExcludeKeyword,
1240718292f2SDouglas Gregor       ExplicitKeyword,
12412b82c2a5SDouglas Gregor       ExportKeyword,
1242f0b11de2SDouglas Gregor       ExportAsKeyword,
124397292843SDaniel Jasper       ExternKeyword,
1244755b2055SDouglas Gregor       FrameworkKeyword,
12456ddfca91SDouglas Gregor       LinkKeyword,
1246718292f2SDouglas Gregor       ModuleKeyword,
12472b82c2a5SDouglas Gregor       Period,
1248b53e5483SLawrence Crowl       PrivateKeyword,
1249718292f2SDouglas Gregor       UmbrellaKeyword,
1250ba7f2f71SDaniel Jasper       UseKeyword,
12511fb5c3a6SDouglas Gregor       RequiresKeyword,
12522b82c2a5SDouglas Gregor       Star,
1253718292f2SDouglas Gregor       StringLiteral,
1254040e1266SRichard Smith       IntegerLiteral,
1255306d8920SRichard Smith       TextualKeyword,
1256718292f2SDouglas Gregor       LBrace,
1257a686e1b0SDouglas Gregor       RBrace,
1258a686e1b0SDouglas Gregor       LSquare,
1259a686e1b0SDouglas Gregor       RSquare
1260718292f2SDouglas Gregor     } Kind;
1261718292f2SDouglas Gregor 
1262718292f2SDouglas Gregor     unsigned Location;
1263718292f2SDouglas Gregor     unsigned StringLength;
1264040e1266SRichard Smith     union {
1265040e1266SRichard Smith       // If Kind != IntegerLiteral.
1266718292f2SDouglas Gregor       const char *StringData;
1267afd1b1c9SEugene Zelenko 
1268040e1266SRichard Smith       // If Kind == IntegerLiteral.
1269040e1266SRichard Smith       uint64_t IntegerValue;
1270040e1266SRichard Smith     };
1271718292f2SDouglas Gregor 
1272718292f2SDouglas Gregor     void clear() {
1273718292f2SDouglas Gregor       Kind = EndOfFile;
1274718292f2SDouglas Gregor       Location = 0;
1275718292f2SDouglas Gregor       StringLength = 0;
1276d2d442caSCraig Topper       StringData = nullptr;
1277718292f2SDouglas Gregor     }
1278718292f2SDouglas Gregor 
1279718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1280718292f2SDouglas Gregor 
1281718292f2SDouglas Gregor     SourceLocation getLocation() const {
1282718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1283718292f2SDouglas Gregor     }
1284718292f2SDouglas Gregor 
1285040e1266SRichard Smith     uint64_t getInteger() const {
1286040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1287040e1266SRichard Smith     }
1288040e1266SRichard Smith 
1289718292f2SDouglas Gregor     StringRef getString() const {
1290040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1291040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1292718292f2SDouglas Gregor     }
1293718292f2SDouglas Gregor   };
1294718292f2SDouglas Gregor 
1295718292f2SDouglas Gregor   class ModuleMapParser {
1296718292f2SDouglas Gregor     Lexer &L;
1297718292f2SDouglas Gregor     SourceManager &SourceMgr;
1298bc10b9fbSDouglas Gregor 
1299bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
1300bc10b9fbSDouglas Gregor     /// parsing.
1301bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1302bc10b9fbSDouglas Gregor 
1303718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1304718292f2SDouglas Gregor     ModuleMap &Map;
1305718292f2SDouglas Gregor 
1306beee15e7SBen Langmuir     /// \brief The current module map file.
1307beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1308beee15e7SBen Langmuir 
13099acb99e3SRichard Smith     /// \brief The directory that file names in this module map file should
13109acb99e3SRichard Smith     /// be resolved relative to.
13115257fc63SDouglas Gregor     const DirectoryEntry *Directory;
13125257fc63SDouglas Gregor 
1313963c5535SDouglas Gregor     /// \brief Whether this module map is in a system header directory.
1314963c5535SDouglas Gregor     bool IsSystem;
1315963c5535SDouglas Gregor 
1316718292f2SDouglas Gregor     /// \brief Whether an error occurred.
1317afd1b1c9SEugene Zelenko     bool HadError = false;
1318718292f2SDouglas Gregor 
1319718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
1320718292f2SDouglas Gregor     /// during parsing.
1321718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1322718292f2SDouglas Gregor 
1323718292f2SDouglas Gregor     /// \brief The current token.
1324718292f2SDouglas Gregor     MMToken Tok;
1325718292f2SDouglas Gregor 
1326718292f2SDouglas Gregor     /// \brief The active module.
1327afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1328718292f2SDouglas Gregor 
13297ff29148SBen Langmuir     /// \brief Whether a module uses the 'requires excluded' hack to mark its
13307ff29148SBen Langmuir     /// contents as 'textual'.
13317ff29148SBen Langmuir     ///
13327ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
13337ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
13347ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
13357ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
13367ff29148SBen Langmuir     /// 'textual' to match the original intent.
13377ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
13387ff29148SBen Langmuir 
1339718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
1340718292f2SDouglas Gregor     SourceLocation consumeToken();
1341718292f2SDouglas Gregor 
1342718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
1343718292f2SDouglas Gregor     /// (or the end of the file).
1344718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1345718292f2SDouglas Gregor 
1346afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1347afd1b1c9SEugene Zelenko 
1348e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1349718292f2SDouglas Gregor     void parseModuleDecl();
135097292843SDaniel Jasper     void parseExternModuleDecl();
13511fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1352afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1353524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
13542b82c2a5SDouglas Gregor     void parseExportDecl();
1355f0b11de2SDouglas Gregor     void parseExportAsDecl();
1356ba7f2f71SDaniel Jasper     void parseUseDecl();
13576ddfca91SDouglas Gregor     void parseLinkDecl();
135835b13eceSDouglas Gregor     void parseConfigMacros();
1359fb912657SDouglas Gregor     void parseConflict();
13609194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1361c1d88ea5SBen Langmuir 
1362afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1363afd1b1c9SEugene Zelenko 
13644442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1365718292f2SDouglas Gregor 
1366718292f2SDouglas Gregor   public:
1367718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
13688587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
13698587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1370c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1371bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1372beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1373c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1374718292f2SDouglas Gregor       Tok.clear();
1375718292f2SDouglas Gregor       consumeToken();
1376718292f2SDouglas Gregor     }
1377718292f2SDouglas Gregor 
1378718292f2SDouglas Gregor     bool parseModuleMapFile();
13798128f332SRichard Smith 
13808128f332SRichard Smith     bool terminatedByDirective() { return false; }
13818128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1382718292f2SDouglas Gregor   };
1383afd1b1c9SEugene Zelenko 
1384afd1b1c9SEugene Zelenko } // namespace clang
1385718292f2SDouglas Gregor 
1386718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1387718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1388718292f2SDouglas Gregor 
13898128f332SRichard Smith retry:
13908128f332SRichard Smith   Tok.clear();
1391718292f2SDouglas Gregor   Token LToken;
1392718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1393718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1394718292f2SDouglas Gregor   switch (LToken.getKind()) {
13952d57cea2SAlp Toker   case tok::raw_identifier: {
13962d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
13972d57cea2SAlp Toker     Tok.StringData = RI.data();
13982d57cea2SAlp Toker     Tok.StringLength = RI.size();
13992d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
140035b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1401fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
140259527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1403718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
14042b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1405f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
140697292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1407755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
140835b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
14096ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1410718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1411b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
14121fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1413306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1414718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1415ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1416718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1417718292f2SDouglas Gregor     break;
14182d57cea2SAlp Toker   }
1419718292f2SDouglas Gregor 
14201fb5c3a6SDouglas Gregor   case tok::comma:
14211fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
14221fb5c3a6SDouglas Gregor     break;
14231fb5c3a6SDouglas Gregor 
1424718292f2SDouglas Gregor   case tok::eof:
1425718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1426718292f2SDouglas Gregor     break;
1427718292f2SDouglas Gregor 
1428718292f2SDouglas Gregor   case tok::l_brace:
1429718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1430718292f2SDouglas Gregor     break;
1431718292f2SDouglas Gregor 
1432a686e1b0SDouglas Gregor   case tok::l_square:
1433a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1434a686e1b0SDouglas Gregor     break;
1435a686e1b0SDouglas Gregor 
14362b82c2a5SDouglas Gregor   case tok::period:
14372b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
14382b82c2a5SDouglas Gregor     break;
14392b82c2a5SDouglas Gregor 
1440718292f2SDouglas Gregor   case tok::r_brace:
1441718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1442718292f2SDouglas Gregor     break;
1443718292f2SDouglas Gregor 
1444a686e1b0SDouglas Gregor   case tok::r_square:
1445a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1446a686e1b0SDouglas Gregor     break;
1447a686e1b0SDouglas Gregor 
14482b82c2a5SDouglas Gregor   case tok::star:
14492b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
14502b82c2a5SDouglas Gregor     break;
14512b82c2a5SDouglas Gregor 
1452a3feee2aSRichard Smith   case tok::exclaim:
1453a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1454a3feee2aSRichard Smith     break;
1455a3feee2aSRichard Smith 
1456718292f2SDouglas Gregor   case tok::string_literal: {
1457d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1458d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1459d67aea28SRichard Smith       HadError = true;
1460d67aea28SRichard Smith       goto retry;
1461d67aea28SRichard Smith     }
1462d67aea28SRichard Smith 
1463718292f2SDouglas Gregor     // Parse the string literal.
1464718292f2SDouglas Gregor     LangOptions LangOpts;
14659d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1466718292f2SDouglas Gregor     if (StringLiteral.hadError)
1467718292f2SDouglas Gregor       goto retry;
1468718292f2SDouglas Gregor 
1469718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1470718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1471718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1472718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1473718292f2SDouglas Gregor     Saved[Length] = 0;
1474718292f2SDouglas Gregor 
1475718292f2SDouglas Gregor     // Form the token.
1476718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1477718292f2SDouglas Gregor     Tok.StringData = Saved;
1478718292f2SDouglas Gregor     Tok.StringLength = Length;
1479718292f2SDouglas Gregor     break;
1480718292f2SDouglas Gregor   }
1481718292f2SDouglas Gregor 
1482040e1266SRichard Smith   case tok::numeric_constant: {
1483040e1266SRichard Smith     // We don't support any suffixes or other complications.
1484040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1485040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1486040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1487040e1266SRichard Smith     unsigned Length =
1488040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1489040e1266SRichard Smith     uint64_t Value;
1490040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1491040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1492040e1266SRichard Smith       HadError = true;
1493040e1266SRichard Smith       goto retry;
1494040e1266SRichard Smith     }
1495040e1266SRichard Smith 
1496040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1497040e1266SRichard Smith     Tok.IntegerValue = Value;
1498040e1266SRichard Smith     break;
1499040e1266SRichard Smith   }
1500040e1266SRichard Smith 
1501718292f2SDouglas Gregor   case tok::comment:
1502718292f2SDouglas Gregor     goto retry;
1503718292f2SDouglas Gregor 
15048128f332SRichard Smith   case tok::hash:
15058128f332SRichard Smith     // A module map can be terminated prematurely by
15068128f332SRichard Smith     //   #pragma clang module contents
15078128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
15088128f332SRichard Smith     // contents of the module.
15098128f332SRichard Smith     {
15108128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
15118128f332SRichard Smith         L.LexFromRawLexer(LToken);
15128128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15138128f332SRichard Smith                LToken.getRawIdentifier() == Str;
15148128f332SRichard Smith       };
15158128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
15168128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
15178128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
15188128f332SRichard Smith         break;
15198128f332SRichard Smith       }
15208128f332SRichard Smith     }
15218128f332SRichard Smith     LLVM_FALLTHROUGH;
15228128f332SRichard Smith 
1523718292f2SDouglas Gregor   default:
15248128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1525718292f2SDouglas Gregor     HadError = true;
1526718292f2SDouglas Gregor     goto retry;
1527718292f2SDouglas Gregor   }
1528718292f2SDouglas Gregor 
1529718292f2SDouglas Gregor   return Result;
1530718292f2SDouglas Gregor }
1531718292f2SDouglas Gregor 
1532718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1533718292f2SDouglas Gregor   unsigned braceDepth = 0;
1534a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1535718292f2SDouglas Gregor   do {
1536718292f2SDouglas Gregor     switch (Tok.Kind) {
1537718292f2SDouglas Gregor     case MMToken::EndOfFile:
1538718292f2SDouglas Gregor       return;
1539718292f2SDouglas Gregor 
1540718292f2SDouglas Gregor     case MMToken::LBrace:
1541a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1542718292f2SDouglas Gregor         return;
1543718292f2SDouglas Gregor 
1544718292f2SDouglas Gregor       ++braceDepth;
1545718292f2SDouglas Gregor       break;
1546718292f2SDouglas Gregor 
1547a686e1b0SDouglas Gregor     case MMToken::LSquare:
1548a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1549a686e1b0SDouglas Gregor         return;
1550a686e1b0SDouglas Gregor 
1551a686e1b0SDouglas Gregor       ++squareDepth;
1552a686e1b0SDouglas Gregor       break;
1553a686e1b0SDouglas Gregor 
1554718292f2SDouglas Gregor     case MMToken::RBrace:
1555718292f2SDouglas Gregor       if (braceDepth > 0)
1556718292f2SDouglas Gregor         --braceDepth;
1557718292f2SDouglas Gregor       else if (Tok.is(K))
1558718292f2SDouglas Gregor         return;
1559718292f2SDouglas Gregor       break;
1560718292f2SDouglas Gregor 
1561a686e1b0SDouglas Gregor     case MMToken::RSquare:
1562a686e1b0SDouglas Gregor       if (squareDepth > 0)
1563a686e1b0SDouglas Gregor         --squareDepth;
1564a686e1b0SDouglas Gregor       else if (Tok.is(K))
1565a686e1b0SDouglas Gregor         return;
1566a686e1b0SDouglas Gregor       break;
1567a686e1b0SDouglas Gregor 
1568718292f2SDouglas Gregor     default:
1569a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1570718292f2SDouglas Gregor         return;
1571718292f2SDouglas Gregor       break;
1572718292f2SDouglas Gregor     }
1573718292f2SDouglas Gregor 
1574718292f2SDouglas Gregor    consumeToken();
1575718292f2SDouglas Gregor   } while (true);
1576718292f2SDouglas Gregor }
1577718292f2SDouglas Gregor 
1578e7ab3669SDouglas Gregor /// \brief Parse a module-id.
1579e7ab3669SDouglas Gregor ///
1580e7ab3669SDouglas Gregor ///   module-id:
1581e7ab3669SDouglas Gregor ///     identifier
1582e7ab3669SDouglas Gregor ///     identifier '.' module-id
1583e7ab3669SDouglas Gregor ///
1584e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1585e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1586e7ab3669SDouglas Gregor   Id.clear();
1587e7ab3669SDouglas Gregor   do {
15883cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1589e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1590e7ab3669SDouglas Gregor       consumeToken();
1591e7ab3669SDouglas Gregor     } else {
1592e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1593e7ab3669SDouglas Gregor       return true;
1594e7ab3669SDouglas Gregor     }
1595e7ab3669SDouglas Gregor 
1596e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1597e7ab3669SDouglas Gregor       break;
1598e7ab3669SDouglas Gregor 
1599e7ab3669SDouglas Gregor     consumeToken();
1600e7ab3669SDouglas Gregor   } while (true);
1601e7ab3669SDouglas Gregor 
1602e7ab3669SDouglas Gregor   return false;
1603e7ab3669SDouglas Gregor }
1604e7ab3669SDouglas Gregor 
1605a686e1b0SDouglas Gregor namespace {
1606afd1b1c9SEugene Zelenko 
1607a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
1608a686e1b0SDouglas Gregor   enum AttributeKind {
1609a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
1610a686e1b0SDouglas Gregor     AT_unknown,
1611afd1b1c9SEugene Zelenko 
1612a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
161335b13eceSDouglas Gregor     AT_system,
1614afd1b1c9SEugene Zelenko 
161577944868SRichard Smith     /// \brief The 'extern_c' attribute.
161677944868SRichard Smith     AT_extern_c,
1617afd1b1c9SEugene Zelenko 
161835b13eceSDouglas Gregor     /// \brief The 'exhaustive' attribute.
1619ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1620afd1b1c9SEugene Zelenko 
1621ed84df00SBruno Cardoso Lopes     /// \brief The 'no_undeclared_includes' attribute.
1622ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1623a686e1b0SDouglas Gregor   };
1624afd1b1c9SEugene Zelenko 
1625afd1b1c9SEugene Zelenko } // namespace
1626a686e1b0SDouglas Gregor 
162729729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
162829729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
162929729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
163029729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
163129729919SBruno Cardoso Lopes static void diagnosePrivateModules(const ModuleMap &Map,
163229729919SBruno Cardoso Lopes                                    DiagnosticsEngine &Diags,
1633*7d29486dSBruno Cardoso Lopes                                    const Module *ActiveModule,
1634*7d29486dSBruno Cardoso Lopes                                    SourceLocation InlineParent) {
163529729919SBruno Cardoso Lopes 
163629729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1637*7d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
163829729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
163929729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
164029729919SBruno Cardoso Lopes     D << BadName << M->Name;
1641*7d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
164229729919SBruno Cardoso Lopes   };
164329729919SBruno Cardoso Lopes 
164429729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
164529729919SBruno Cardoso Lopes     auto const *M = E->getValue();
164629729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
164729729919SBruno Cardoso Lopes       continue;
164829729919SBruno Cardoso Lopes 
164929729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
165029729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
165129729919SBruno Cardoso Lopes       continue;
165229729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
165329729919SBruno Cardoso Lopes     Canonical.append("_Private");
165429729919SBruno Cardoso Lopes 
165529729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
165629729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
165729729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
165829729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
165929729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
166029729919SBruno Cardoso Lopes           << FullName;
1661*7d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(FullName, Canonical, M,
1662*7d29486dSBruno Cardoso Lopes                       SourceRange(InlineParent, ActiveModule->DefinitionLoc));
166329729919SBruno Cardoso Lopes       continue;
166429729919SBruno Cardoso Lopes     }
166529729919SBruno Cardoso Lopes 
166629729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
166729729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
166829729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
166929729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
167029729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
167129729919SBruno Cardoso Lopes           << ActiveModule->Name;
1672*7d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1673*7d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
167429729919SBruno Cardoso Lopes     }
167529729919SBruno Cardoso Lopes   }
167629729919SBruno Cardoso Lopes }
167729729919SBruno Cardoso Lopes 
1678718292f2SDouglas Gregor /// \brief Parse a module declaration.
1679718292f2SDouglas Gregor ///
1680718292f2SDouglas Gregor ///   module-declaration:
168197292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1682a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1683a686e1b0SDouglas Gregor ///       { module-member* }
1684a686e1b0SDouglas Gregor ///
1685718292f2SDouglas Gregor ///   module-member:
16861fb5c3a6SDouglas Gregor ///     requires-declaration
1687718292f2SDouglas Gregor ///     header-declaration
1688e7ab3669SDouglas Gregor ///     submodule-declaration
16892b82c2a5SDouglas Gregor ///     export-declaration
1690f0b11de2SDouglas Gregor ///     export-as-declaration
16916ddfca91SDouglas Gregor ///     link-declaration
169273441091SDouglas Gregor ///
169373441091SDouglas Gregor ///   submodule-declaration:
169473441091SDouglas Gregor ///     module-declaration
169573441091SDouglas Gregor ///     inferred-submodule-declaration
1696718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1697755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
169897292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
169997292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
170097292843SDaniel Jasper     parseExternModuleDecl();
170197292843SDaniel Jasper     return;
170297292843SDaniel Jasper   }
170397292843SDaniel Jasper 
1704f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1705e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
1706718292f2SDouglas Gregor   bool Explicit = false;
1707f2161a70SDouglas Gregor   bool Framework = false;
1708755b2055SDouglas Gregor 
1709f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1710f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1711e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1712f2161a70SDouglas Gregor     Explicit = true;
1713f2161a70SDouglas Gregor   }
1714f2161a70SDouglas Gregor 
1715f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1716755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
1717755b2055SDouglas Gregor     consumeToken();
1718755b2055SDouglas Gregor     Framework = true;
1719755b2055SDouglas Gregor   }
1720718292f2SDouglas Gregor 
1721718292f2SDouglas Gregor   // Parse 'module' keyword.
1722718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1723d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1724718292f2SDouglas Gregor     consumeToken();
1725718292f2SDouglas Gregor     HadError = true;
1726718292f2SDouglas Gregor     return;
1727718292f2SDouglas Gregor   }
1728718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
1729718292f2SDouglas Gregor 
173073441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
173173441091SDouglas Gregor   // Parse it.
173273441091SDouglas Gregor   if (Tok.is(MMToken::Star))
17339194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
173473441091SDouglas Gregor 
1735718292f2SDouglas Gregor   // Parse the module name.
1736e7ab3669SDouglas Gregor   ModuleId Id;
1737e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1738718292f2SDouglas Gregor     HadError = true;
1739718292f2SDouglas Gregor     return;
1740718292f2SDouglas Gregor   }
1741e7ab3669SDouglas Gregor 
1742e7ab3669SDouglas Gregor   if (ActiveModule) {
1743e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1744e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1745e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1746e7ab3669SDouglas Gregor 
1747e7ab3669SDouglas Gregor       HadError = true;
1748e7ab3669SDouglas Gregor       return;
1749e7ab3669SDouglas Gregor     }
1750e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1751e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1752e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1753e7ab3669SDouglas Gregor     Explicit = false;
1754e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1755e7ab3669SDouglas Gregor     HadError = true;
1756e7ab3669SDouglas Gregor   }
1757e7ab3669SDouglas Gregor 
1758e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1759*7d29486dSBruno Cardoso Lopes   SourceLocation LastInlineParentLoc = SourceLocation();
1760e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1761e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1762e7ab3669SDouglas Gregor     // is a submodule.
1763d2d442caSCraig Topper     ActiveModule = nullptr;
17644b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1765e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1766e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
17674b8a9e95SBen Langmuir         if (I == 0)
17684b8a9e95SBen Langmuir           TopLevelModule = Next;
1769e7ab3669SDouglas Gregor         ActiveModule = Next;
1770*7d29486dSBruno Cardoso Lopes         LastInlineParentLoc = Id[I].second;
1771e7ab3669SDouglas Gregor         continue;
1772e7ab3669SDouglas Gregor       }
1773e7ab3669SDouglas Gregor 
1774e7ab3669SDouglas Gregor       if (ActiveModule) {
1775e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
17765b5d21eaSRichard Smith           << Id[I].first
17775b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1778e7ab3669SDouglas Gregor       } else {
1779e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1780e7ab3669SDouglas Gregor       }
1781e7ab3669SDouglas Gregor       HadError = true;
1782e7ab3669SDouglas Gregor       return;
1783e7ab3669SDouglas Gregor     }
17844b8a9e95SBen Langmuir 
17854b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
17864b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
17874b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
17884b8a9e95SBen Langmuir              "top-level module");
17894b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
17904b8a9e95SBen Langmuir     }
1791e7ab3669SDouglas Gregor   }
1792e7ab3669SDouglas Gregor 
1793e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1794e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1795718292f2SDouglas Gregor 
1796a686e1b0SDouglas Gregor   // Parse the optional attribute list.
17974442605fSBill Wendling   Attributes Attrs;
17985d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
17995d29dee0SDavide Italiano     return;
18005d29dee0SDavide Italiano 
1801718292f2SDouglas Gregor   // Parse the opening brace.
1802718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1803718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1804718292f2SDouglas Gregor       << ModuleName;
1805718292f2SDouglas Gregor     HadError = true;
1806718292f2SDouglas Gregor     return;
1807718292f2SDouglas Gregor   }
1808718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1809718292f2SDouglas Gregor 
1810718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
18118587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1812eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
18134a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
18144a3751ffSRichard Smith     // definition for in two cases:
18154a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
18164a3751ffSRichard Smith     //    corresponding definition in a module map file, or
18174a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
18184a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
18194a3751ffSRichard Smith     //    module map file from which it was created.
18204a3751ffSRichard Smith     bool ParsedAsMainInput =
18214a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
18224a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
18234a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
18244a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
18254a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1826fcc54a3bSDouglas Gregor       // Skip the module definition.
1827fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1828fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1829fcc54a3bSDouglas Gregor         consumeToken();
1830fcc54a3bSDouglas Gregor       else {
1831fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1832fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1833fcc54a3bSDouglas Gregor         HadError = true;
1834fcc54a3bSDouglas Gregor       }
1835fcc54a3bSDouglas Gregor       return;
1836fcc54a3bSDouglas Gregor     }
1837fcc54a3bSDouglas Gregor 
1838c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
18398587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
18408587dfd9SBruno Cardoso Lopes     } else {
18418587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1842718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1843718292f2SDouglas Gregor           << ModuleName;
1844eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1845718292f2SDouglas Gregor 
1846718292f2SDouglas Gregor       // Skip the module definition.
1847718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1848718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1849718292f2SDouglas Gregor         consumeToken();
1850718292f2SDouglas Gregor 
1851718292f2SDouglas Gregor       HadError = true;
1852718292f2SDouglas Gregor       return;
1853718292f2SDouglas Gregor     }
18548587dfd9SBruno Cardoso Lopes   }
1855718292f2SDouglas Gregor 
1856718292f2SDouglas Gregor   // Start defining this module.
18578587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
18588587dfd9SBruno Cardoso Lopes     ActiveModule =
18598587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
18608587dfd9SBruno Cardoso Lopes   } else {
1861c192d194SBruno Cardoso Lopes     ActiveModule =
1862c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
18638587dfd9SBruno Cardoso Lopes             .first;
18648587dfd9SBruno Cardoso Lopes   }
18658587dfd9SBruno Cardoso Lopes 
1866eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1867963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1868a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
186977944868SRichard Smith   if (Attrs.IsExternC)
187077944868SRichard Smith     ActiveModule->IsExternC = true;
1871ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1872ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1873ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
18743c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1875718292f2SDouglas Gregor 
187629729919SBruno Cardoso Lopes 
187729729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
187829729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
187929729919SBruno Cardoso Lopes   // Foo_Private instead.
188029729919SBruno Cardoso Lopes   SourceLocation StartLoc =
188129729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
18824d867640SGraydon Hoare   StringRef MapFileName(ModuleMapFile->getName());
188329729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
188429729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
188529729919SBruno Cardoso Lopes                        StartLoc) &&
188629729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
188729729919SBruno Cardoso Lopes                        StartLoc) &&
188829729919SBruno Cardoso Lopes       (MapFileName.endswith("module.private.modulemap") ||
188929729919SBruno Cardoso Lopes        MapFileName.endswith("module_private.map")))
1890*7d29486dSBruno Cardoso Lopes     diagnosePrivateModules(Map, Diags, ActiveModule, LastInlineParentLoc);
18914d867640SGraydon Hoare 
1892718292f2SDouglas Gregor   bool Done = false;
1893718292f2SDouglas Gregor   do {
1894718292f2SDouglas Gregor     switch (Tok.Kind) {
1895718292f2SDouglas Gregor     case MMToken::EndOfFile:
1896718292f2SDouglas Gregor     case MMToken::RBrace:
1897718292f2SDouglas Gregor       Done = true;
1898718292f2SDouglas Gregor       break;
1899718292f2SDouglas Gregor 
190035b13eceSDouglas Gregor     case MMToken::ConfigMacros:
190135b13eceSDouglas Gregor       parseConfigMacros();
190235b13eceSDouglas Gregor       break;
190335b13eceSDouglas Gregor 
1904fb912657SDouglas Gregor     case MMToken::Conflict:
1905fb912657SDouglas Gregor       parseConflict();
1906fb912657SDouglas Gregor       break;
1907fb912657SDouglas Gregor 
1908718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
190997292843SDaniel Jasper     case MMToken::ExternKeyword:
1910f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1911718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1912718292f2SDouglas Gregor       parseModuleDecl();
1913718292f2SDouglas Gregor       break;
1914718292f2SDouglas Gregor 
19152b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
19162b82c2a5SDouglas Gregor       parseExportDecl();
19172b82c2a5SDouglas Gregor       break;
19182b82c2a5SDouglas Gregor 
1919f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
1920f0b11de2SDouglas Gregor       parseExportAsDecl();
1921f0b11de2SDouglas Gregor       break;
1922f0b11de2SDouglas Gregor 
1923ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
1924ba7f2f71SDaniel Jasper       parseUseDecl();
1925ba7f2f71SDaniel Jasper       break;
1926ba7f2f71SDaniel Jasper 
19271fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
19281fb5c3a6SDouglas Gregor       parseRequiresDecl();
19291fb5c3a6SDouglas Gregor       break;
19301fb5c3a6SDouglas Gregor 
1931202210b3SRichard Smith     case MMToken::TextualKeyword:
1932202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1933306d8920SRichard Smith       break;
1934306d8920SRichard Smith 
1935524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1936524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1937524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
1938b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1939524e33e1SDouglas Gregor       else
1940524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1941718292f2SDouglas Gregor       break;
1942524e33e1SDouglas Gregor     }
1943718292f2SDouglas Gregor 
1944202210b3SRichard Smith     case MMToken::ExcludeKeyword:
1945202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
194659527666SDouglas Gregor       break;
194759527666SDouglas Gregor 
1948202210b3SRichard Smith     case MMToken::PrivateKeyword:
1949202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1950b53e5483SLawrence Crowl       break;
1951b53e5483SLawrence Crowl 
1952322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
1953202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
1954718292f2SDouglas Gregor       break;
1955718292f2SDouglas Gregor 
19566ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
19576ddfca91SDouglas Gregor       parseLinkDecl();
19586ddfca91SDouglas Gregor       break;
19596ddfca91SDouglas Gregor 
1960718292f2SDouglas Gregor     default:
1961718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1962718292f2SDouglas Gregor       consumeToken();
1963718292f2SDouglas Gregor       break;
1964718292f2SDouglas Gregor     }
1965718292f2SDouglas Gregor   } while (!Done);
1966718292f2SDouglas Gregor 
1967718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1968718292f2SDouglas Gregor     consumeToken();
1969718292f2SDouglas Gregor   else {
1970718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1971718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1972718292f2SDouglas Gregor     HadError = true;
1973718292f2SDouglas Gregor   }
1974718292f2SDouglas Gregor 
197511dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
197611dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
197711dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
197811dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
197911dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
198011dfe6feSDouglas Gregor   }
198111dfe6feSDouglas Gregor 
1982ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
1983ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
1984ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
1985ec8c9752SBen Langmuir       ActiveModule->Parent) {
1986ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
1987ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
1988ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
1989ec8c9752SBen Langmuir   }
1990ec8c9752SBen Langmuir 
1991e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
1992e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
1993718292f2SDouglas Gregor }
1994718292f2SDouglas Gregor 
199597292843SDaniel Jasper /// \brief Parse an extern module declaration.
199697292843SDaniel Jasper ///
199797292843SDaniel Jasper ///   extern module-declaration:
199897292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
199997292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
200097292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2001ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
200297292843SDaniel Jasper 
200397292843SDaniel Jasper   // Parse 'module' keyword.
200497292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
200597292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
200697292843SDaniel Jasper     consumeToken();
200797292843SDaniel Jasper     HadError = true;
200897292843SDaniel Jasper     return;
200997292843SDaniel Jasper   }
201097292843SDaniel Jasper   consumeToken(); // 'module' keyword
201197292843SDaniel Jasper 
201297292843SDaniel Jasper   // Parse the module name.
201397292843SDaniel Jasper   ModuleId Id;
201497292843SDaniel Jasper   if (parseModuleId(Id)) {
201597292843SDaniel Jasper     HadError = true;
201697292843SDaniel Jasper     return;
201797292843SDaniel Jasper   }
201897292843SDaniel Jasper 
201997292843SDaniel Jasper   // Parse the referenced module map file name.
202097292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
202197292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
202297292843SDaniel Jasper     HadError = true;
202397292843SDaniel Jasper     return;
202497292843SDaniel Jasper   }
202597292843SDaniel Jasper   std::string FileName = Tok.getString();
202697292843SDaniel Jasper   consumeToken(); // filename
202797292843SDaniel Jasper 
202897292843SDaniel Jasper   StringRef FileNameRef = FileName;
202997292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
203097292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
203197292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
203297292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
203392e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
203497292843SDaniel Jasper   }
203597292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
20369acb99e3SRichard Smith     Map.parseModuleMapFile(
20379acb99e3SRichard Smith         File, /*IsSystem=*/false,
20389acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
20399acb99e3SRichard Smith             ? Directory
20408128f332SRichard Smith             : File->getDir(),
2041c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
204297292843SDaniel Jasper }
204397292843SDaniel Jasper 
20447ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
20457ff29148SBen Langmuir ///
20467ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
20477ff29148SBen Langmuir /// module map files:
20487ff29148SBen Langmuir ///
20497ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
20507ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
20517ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
20527ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
20537ff29148SBen Langmuir ///    module to 'textual'.
20547ff29148SBen Langmuir ///
20557ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
20567ff29148SBen Langmuir ///
20577ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
20587ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
20597ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
20607ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
20618013e81dSBenjamin Kramer   if (Feature == "excluded" &&
20628013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
20638013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
20647ff29148SBen Langmuir     IsRequiresExcludedHack = true;
20657ff29148SBen Langmuir     return false;
20668013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
20677ff29148SBen Langmuir     return false;
20687ff29148SBen Langmuir   }
20697ff29148SBen Langmuir 
20707ff29148SBen Langmuir   return true;
20717ff29148SBen Langmuir }
20727ff29148SBen Langmuir 
20731fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
20741fb5c3a6SDouglas Gregor ///
20751fb5c3a6SDouglas Gregor ///   requires-declaration:
20761fb5c3a6SDouglas Gregor ///     'requires' feature-list
20771fb5c3a6SDouglas Gregor ///
20781fb5c3a6SDouglas Gregor ///   feature-list:
2079a3feee2aSRichard Smith ///     feature ',' feature-list
2080a3feee2aSRichard Smith ///     feature
2081a3feee2aSRichard Smith ///
2082a3feee2aSRichard Smith ///   feature:
2083a3feee2aSRichard Smith ///     '!'[opt] identifier
20841fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
20851fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
20861fb5c3a6SDouglas Gregor 
20871fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
20881fb5c3a6SDouglas Gregor   consumeToken();
20891fb5c3a6SDouglas Gregor 
20901fb5c3a6SDouglas Gregor   // Parse the feature-list.
20911fb5c3a6SDouglas Gregor   do {
2092a3feee2aSRichard Smith     bool RequiredState = true;
2093a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2094a3feee2aSRichard Smith       RequiredState = false;
2095a3feee2aSRichard Smith       consumeToken();
2096a3feee2aSRichard Smith     }
2097a3feee2aSRichard Smith 
20981fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
20991fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
21001fb5c3a6SDouglas Gregor       HadError = true;
21011fb5c3a6SDouglas Gregor       return;
21021fb5c3a6SDouglas Gregor     }
21031fb5c3a6SDouglas Gregor 
21041fb5c3a6SDouglas Gregor     // Consume the feature name.
21051fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
21061fb5c3a6SDouglas Gregor     consumeToken();
21071fb5c3a6SDouglas Gregor 
21087ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
21097ff29148SBen Langmuir     bool ShouldAddRequirement =
21107ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
21117ff29148SBen Langmuir 
21127ff29148SBen Langmuir     if (IsRequiresExcludedHack)
21137ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
21147ff29148SBen Langmuir 
21157ff29148SBen Langmuir     if (ShouldAddRequirement) {
21161fb5c3a6SDouglas Gregor       // Add this feature.
21177ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
21187ff29148SBen Langmuir                                    *Map.Target);
21197ff29148SBen Langmuir     }
21201fb5c3a6SDouglas Gregor 
21211fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
21221fb5c3a6SDouglas Gregor       break;
21231fb5c3a6SDouglas Gregor 
21241fb5c3a6SDouglas Gregor     // Consume the comma.
21251fb5c3a6SDouglas Gregor     consumeToken();
21261fb5c3a6SDouglas Gregor   } while (true);
21271fb5c3a6SDouglas Gregor }
21281fb5c3a6SDouglas Gregor 
2129718292f2SDouglas Gregor /// \brief Parse a header declaration.
2130718292f2SDouglas Gregor ///
2131718292f2SDouglas Gregor ///   header-declaration:
2132306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2133202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2134202210b3SRichard Smith ///     'exclude' 'header' string-literal
2135202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2136306d8920SRichard Smith ///
2137306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2138b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2139b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2140202210b3SRichard Smith   // We've already consumed the first token.
2141202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2142202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2143202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2144202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2145202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2146202210b3SRichard Smith       LeadingToken = Tok.Kind;
21471871ed3dSBenjamin Kramer       consumeToken();
2148202210b3SRichard Smith     }
2149202210b3SRichard Smith   }
21507ff29148SBen Langmuir 
2151202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2152202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2153202210b3SRichard Smith 
21547ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
21557ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
21567ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
21577ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
21587ff29148SBen Langmuir   }
21597ff29148SBen Langmuir 
2160202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2161202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2162202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2163202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2164202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2165202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2166202210b3SRichard Smith       return;
2167202210b3SRichard Smith     }
2168202210b3SRichard Smith     consumeToken();
2169202210b3SRichard Smith   }
2170718292f2SDouglas Gregor 
2171718292f2SDouglas Gregor   // Parse the header name.
2172718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2173718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2174718292f2SDouglas Gregor       << "header";
2175718292f2SDouglas Gregor     HadError = true;
2176718292f2SDouglas Gregor     return;
2177718292f2SDouglas Gregor   }
21783c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
21790761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
21800761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
21811d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2182040e1266SRichard Smith   Header.Kind =
2183040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2184040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2185718292f2SDouglas Gregor 
2186524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
21871d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
21880761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2189524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2190322f633cSDouglas Gregor     HadError = true;
2191322f633cSDouglas Gregor     return;
2192322f633cSDouglas Gregor   }
2193322f633cSDouglas Gregor 
2194040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2195040e1266SRichard Smith   // the file.
2196040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2197040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
21983ec6663bSDouglas Gregor 
2199040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2200040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2201040e1266SRichard Smith       StringRef Str = Tok.getString();
2202040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2203040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2204040e1266SRichard Smith                   .Case("size", Size)
2205040e1266SRichard Smith                   .Case("mtime", ModTime)
2206040e1266SRichard Smith                   .Default(Unknown)) {
2207040e1266SRichard Smith       case Size:
2208040e1266SRichard Smith         if (Header.Size)
2209040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2210040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2211040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2212040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2213040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2214040e1266SRichard Smith           break;
2215040e1266SRichard Smith         }
2216040e1266SRichard Smith         Header.Size = Tok.getInteger();
2217040e1266SRichard Smith         consumeToken();
2218040e1266SRichard Smith         break;
2219040e1266SRichard Smith 
2220040e1266SRichard Smith       case ModTime:
2221040e1266SRichard Smith         if (Header.ModTime)
2222040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2223040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2224040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2225040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2226040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2227040e1266SRichard Smith           break;
2228040e1266SRichard Smith         }
2229040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2230040e1266SRichard Smith         consumeToken();
2231040e1266SRichard Smith         break;
2232040e1266SRichard Smith 
2233040e1266SRichard Smith       case Unknown:
2234040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2235040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2236040e1266SRichard Smith         break;
2237040e1266SRichard Smith       }
22383ec6663bSDouglas Gregor     }
22395257fc63SDouglas Gregor 
2240040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2241040e1266SRichard Smith       consumeToken();
2242040e1266SRichard Smith     else {
2243040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2244040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2245322f633cSDouglas Gregor       HadError = true;
2246322f633cSDouglas Gregor     }
22470101b540SHans Wennborg   }
224825d50758SRichard Smith 
2249040e1266SRichard Smith   Map.addUnresolvedHeader(ActiveModule, std::move(Header));
2250718292f2SDouglas Gregor }
2251718292f2SDouglas Gregor 
225241f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
225341f81994SBen Langmuir                                 const Module::Header *B) {
225441f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
225541f81994SBen Langmuir }
225641f81994SBen Langmuir 
2257524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
2258524e33e1SDouglas Gregor ///
2259524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2260524e33e1SDouglas Gregor ///     umbrella string-literal
2261524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2262524e33e1SDouglas Gregor   // Parse the directory name.
2263524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2264524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2265524e33e1SDouglas Gregor       << "umbrella";
2266524e33e1SDouglas Gregor     HadError = true;
2267524e33e1SDouglas Gregor     return;
2268524e33e1SDouglas Gregor   }
2269524e33e1SDouglas Gregor 
2270524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2271524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2272524e33e1SDouglas Gregor 
2273524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2274524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2275524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2276524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2277524e33e1SDouglas Gregor     HadError = true;
2278524e33e1SDouglas Gregor     return;
2279524e33e1SDouglas Gregor   }
2280524e33e1SDouglas Gregor 
2281524e33e1SDouglas Gregor   // Look for this file.
2282d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2283524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2284524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2285524e33e1SDouglas Gregor   else {
22862c1dd271SDylan Noblesmith     SmallString<128> PathName;
2287524e33e1SDouglas Gregor     PathName = Directory->getName();
2288524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2289524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2290524e33e1SDouglas Gregor   }
2291524e33e1SDouglas Gregor 
2292524e33e1SDouglas Gregor   if (!Dir) {
2293a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2294524e33e1SDouglas Gregor       << DirName;
2295524e33e1SDouglas Gregor     return;
2296524e33e1SDouglas Gregor   }
2297524e33e1SDouglas Gregor 
22987ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22997ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
23007ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
23017ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
23027ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
23037ff29148SBen Langmuir     std::error_code EC;
23047ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2305b171a59bSBruno Cardoso Lopes     vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
2306b171a59bSBruno Cardoso Lopes     for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
23077ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
2308b171a59bSBruno Cardoso Lopes       if (const FileEntry *FE =
2309b171a59bSBruno Cardoso Lopes               SourceMgr.getFileManager().getFile(I->getName())) {
23107ff29148SBen Langmuir 
2311b171a59bSBruno Cardoso Lopes         Module::Header Header = {I->getName(), FE};
23127ff29148SBen Langmuir         Headers.push_back(std::move(Header));
23137ff29148SBen Langmuir       }
23147ff29148SBen Langmuir     }
23157ff29148SBen Langmuir 
23167ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
231741f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
231841f81994SBen Langmuir 
23197ff29148SBen Langmuir     for (auto &Header : Headers)
23207ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
23217ff29148SBen Langmuir     return;
23227ff29148SBen Langmuir   }
23237ff29148SBen Langmuir 
2324524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2325524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2326524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2327524e33e1SDouglas Gregor     HadError = true;
2328524e33e1SDouglas Gregor     return;
2329524e33e1SDouglas Gregor   }
2330524e33e1SDouglas Gregor 
2331524e33e1SDouglas Gregor   // Record this umbrella directory.
23322b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2333524e33e1SDouglas Gregor }
2334524e33e1SDouglas Gregor 
23352b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
23362b82c2a5SDouglas Gregor ///
23372b82c2a5SDouglas Gregor ///   export-declaration:
23382b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
23392b82c2a5SDouglas Gregor ///
23402b82c2a5SDouglas Gregor ///   wildcard-module-id:
23412b82c2a5SDouglas Gregor ///     identifier
23422b82c2a5SDouglas Gregor ///     '*'
23432b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
23442b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
23452b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
23462b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
23472b82c2a5SDouglas Gregor 
23482b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
23492b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
23502b82c2a5SDouglas Gregor   bool Wildcard = false;
23512b82c2a5SDouglas Gregor   do {
2352306d8920SRichard Smith     // FIXME: Support string-literal module names here.
23532b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
23542b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
23552b82c2a5SDouglas Gregor                                               Tok.getLocation()));
23562b82c2a5SDouglas Gregor       consumeToken();
23572b82c2a5SDouglas Gregor 
23582b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
23592b82c2a5SDouglas Gregor         consumeToken();
23602b82c2a5SDouglas Gregor         continue;
23612b82c2a5SDouglas Gregor       }
23622b82c2a5SDouglas Gregor 
23632b82c2a5SDouglas Gregor       break;
23642b82c2a5SDouglas Gregor     }
23652b82c2a5SDouglas Gregor 
23662b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
23672b82c2a5SDouglas Gregor       Wildcard = true;
2368f5eedd05SDouglas Gregor       consumeToken();
23692b82c2a5SDouglas Gregor       break;
23702b82c2a5SDouglas Gregor     }
23712b82c2a5SDouglas Gregor 
2372ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
23732b82c2a5SDouglas Gregor     HadError = true;
23742b82c2a5SDouglas Gregor     return;
23752b82c2a5SDouglas Gregor   } while (true);
23762b82c2a5SDouglas Gregor 
23772b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
23782b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
23792b82c2a5SDouglas Gregor   };
23802b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
23812b82c2a5SDouglas Gregor }
23822b82c2a5SDouglas Gregor 
2383f0b11de2SDouglas Gregor /// \brief Parse a module export_as declaration.
2384f0b11de2SDouglas Gregor ///
2385f0b11de2SDouglas Gregor ///   export-as-declaration:
2386f0b11de2SDouglas Gregor ///     'export_as' identifier
2387f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2388f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2389f0b11de2SDouglas Gregor   consumeToken();
2390f0b11de2SDouglas Gregor 
2391f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2392f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2393f0b11de2SDouglas Gregor     HadError = true;
2394f0b11de2SDouglas Gregor     return;
2395f0b11de2SDouglas Gregor   }
2396f0b11de2SDouglas Gregor 
2397f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2398f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2399f0b11de2SDouglas Gregor     consumeToken();
2400f0b11de2SDouglas Gregor     return;
2401f0b11de2SDouglas Gregor   }
2402f0b11de2SDouglas Gregor 
2403f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2404f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2405f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2406f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2407f0b11de2SDouglas Gregor     } else {
2408f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2409f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2410f0b11de2SDouglas Gregor         << Tok.getString();
2411f0b11de2SDouglas Gregor     }
2412f0b11de2SDouglas Gregor   }
2413f0b11de2SDouglas Gregor 
2414f0b11de2SDouglas Gregor   ActiveModule->ExportAsModule = Tok.getString();
2415f0b11de2SDouglas Gregor   consumeToken();
2416f0b11de2SDouglas Gregor }
2417f0b11de2SDouglas Gregor 
24188f4d3ff1SRichard Smith /// \brief Parse a module use declaration.
2419ba7f2f71SDaniel Jasper ///
24208f4d3ff1SRichard Smith ///   use-declaration:
24218f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2422ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2423ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
24248f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2425ba7f2f71SDaniel Jasper   // Parse the module-id.
2426ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
24273cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2428ba7f2f71SDaniel Jasper 
24298f4d3ff1SRichard Smith   if (ActiveModule->Parent)
24308f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
24318f4d3ff1SRichard Smith   else
2432ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2433ba7f2f71SDaniel Jasper }
2434ba7f2f71SDaniel Jasper 
24356ddfca91SDouglas Gregor /// \brief Parse a link declaration.
24366ddfca91SDouglas Gregor ///
24376ddfca91SDouglas Gregor ///   module-declaration:
24386ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
24396ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
24406ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
24416ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
24426ddfca91SDouglas Gregor 
24436ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
24446ddfca91SDouglas Gregor   bool IsFramework = false;
24456ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
24466ddfca91SDouglas Gregor     consumeToken();
24476ddfca91SDouglas Gregor     IsFramework = true;
24486ddfca91SDouglas Gregor   }
24496ddfca91SDouglas Gregor 
24506ddfca91SDouglas Gregor   // Parse the library name
24516ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
24526ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
24536ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
24546ddfca91SDouglas Gregor     HadError = true;
24556ddfca91SDouglas Gregor     return;
24566ddfca91SDouglas Gregor   }
24576ddfca91SDouglas Gregor 
24586ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
24596ddfca91SDouglas Gregor   consumeToken();
24606ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
24616ddfca91SDouglas Gregor                                                             IsFramework));
24626ddfca91SDouglas Gregor }
24636ddfca91SDouglas Gregor 
246435b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration.
246535b13eceSDouglas Gregor ///
246635b13eceSDouglas Gregor ///   module-declaration:
246735b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
246835b13eceSDouglas Gregor ///
246935b13eceSDouglas Gregor ///   config-macro-list:
247035b13eceSDouglas Gregor ///     identifier (',' identifier)?
247135b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
247235b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
247335b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
247435b13eceSDouglas Gregor 
247535b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
247635b13eceSDouglas Gregor   if (ActiveModule->Parent) {
247735b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
247835b13eceSDouglas Gregor   }
247935b13eceSDouglas Gregor 
248035b13eceSDouglas Gregor   // Parse the optional attributes.
248135b13eceSDouglas Gregor   Attributes Attrs;
24825d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
24835d29dee0SDavide Italiano     return;
24845d29dee0SDavide Italiano 
248535b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
248635b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
248735b13eceSDouglas Gregor   }
248835b13eceSDouglas Gregor 
248935b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2490306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
249135b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
249235b13eceSDouglas Gregor     return;
249335b13eceSDouglas Gregor 
249435b13eceSDouglas Gregor   // Consume the first identifier.
249535b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
249635b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
249735b13eceSDouglas Gregor   }
249835b13eceSDouglas Gregor   consumeToken();
249935b13eceSDouglas Gregor 
250035b13eceSDouglas Gregor   do {
250135b13eceSDouglas Gregor     // If there's a comma, consume it.
250235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
250335b13eceSDouglas Gregor       break;
250435b13eceSDouglas Gregor     consumeToken();
250535b13eceSDouglas Gregor 
250635b13eceSDouglas Gregor     // We expect to see a macro name here.
2507306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
250835b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
250935b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
251035b13eceSDouglas Gregor       break;
251135b13eceSDouglas Gregor     }
251235b13eceSDouglas Gregor 
251335b13eceSDouglas Gregor     // Consume the macro name.
251435b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
251535b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
251635b13eceSDouglas Gregor     }
251735b13eceSDouglas Gregor     consumeToken();
251835b13eceSDouglas Gregor   } while (true);
251935b13eceSDouglas Gregor }
252035b13eceSDouglas Gregor 
2521fb912657SDouglas Gregor /// \brief Format a module-id into a string.
2522fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2523fb912657SDouglas Gregor   std::string result;
2524fb912657SDouglas Gregor   {
2525fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2526fb912657SDouglas Gregor 
2527fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2528fb912657SDouglas Gregor       if (I)
2529fb912657SDouglas Gregor         OS << ".";
2530fb912657SDouglas Gregor       OS << Id[I].first;
2531fb912657SDouglas Gregor     }
2532fb912657SDouglas Gregor   }
2533fb912657SDouglas Gregor 
2534fb912657SDouglas Gregor   return result;
2535fb912657SDouglas Gregor }
2536fb912657SDouglas Gregor 
2537fb912657SDouglas Gregor /// \brief Parse a conflict declaration.
2538fb912657SDouglas Gregor ///
2539fb912657SDouglas Gregor ///   module-declaration:
2540fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2541fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2542fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2543fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2544fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2545fb912657SDouglas Gregor 
2546fb912657SDouglas Gregor   // Parse the module-id.
2547fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2548fb912657SDouglas Gregor     return;
2549fb912657SDouglas Gregor 
2550fb912657SDouglas Gregor   // Parse the ','.
2551fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2552fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2553fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2554fb912657SDouglas Gregor     return;
2555fb912657SDouglas Gregor   }
2556fb912657SDouglas Gregor   consumeToken();
2557fb912657SDouglas Gregor 
2558fb912657SDouglas Gregor   // Parse the message.
2559fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2560fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2561fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2562fb912657SDouglas Gregor     return;
2563fb912657SDouglas Gregor   }
2564fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2565fb912657SDouglas Gregor   consumeToken();
2566fb912657SDouglas Gregor 
2567fb912657SDouglas Gregor   // Add this unresolved conflict.
2568fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2569fb912657SDouglas Gregor }
2570fb912657SDouglas Gregor 
25716ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules).
25729194a91dSDouglas Gregor ///
25739194a91dSDouglas Gregor ///   module-declaration:
25749194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
25759194a91dSDouglas Gregor ///       { inferred-module-member* }
25769194a91dSDouglas Gregor ///
25779194a91dSDouglas Gregor ///   inferred-module-member:
25789194a91dSDouglas Gregor ///     'export' '*'
25799194a91dSDouglas Gregor ///     'exclude' identifier
25809194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
258173441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
258273441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
258373441091SDouglas Gregor   bool Failed = false;
258473441091SDouglas Gregor 
258573441091SDouglas Gregor   // Inferred modules must be submodules.
25869194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
258773441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
258873441091SDouglas Gregor     Failed = true;
258973441091SDouglas Gregor   }
259073441091SDouglas Gregor 
25919194a91dSDouglas Gregor   if (ActiveModule) {
2592524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
25934898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
25944898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
259573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
259673441091SDouglas Gregor       Failed = true;
259773441091SDouglas Gregor     }
259873441091SDouglas Gregor 
259973441091SDouglas Gregor     // Check for redefinition of an inferred module.
2600dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
260173441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2602dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2603dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
260473441091SDouglas Gregor                      diag::note_mmap_prev_definition);
260573441091SDouglas Gregor       Failed = true;
260673441091SDouglas Gregor     }
260773441091SDouglas Gregor 
26089194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
26099194a91dSDouglas Gregor     if (Framework) {
26109194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
26119194a91dSDouglas Gregor       Framework = false;
26129194a91dSDouglas Gregor     }
26139194a91dSDouglas Gregor   } else if (Explicit) {
26149194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
26159194a91dSDouglas Gregor     Explicit = false;
26169194a91dSDouglas Gregor   }
26179194a91dSDouglas Gregor 
261873441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
261973441091SDouglas Gregor   if (Failed) {
262073441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
262173441091SDouglas Gregor       consumeToken();
262273441091SDouglas Gregor       skipUntil(MMToken::RBrace);
262373441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
262473441091SDouglas Gregor         consumeToken();
262573441091SDouglas Gregor     }
262673441091SDouglas Gregor     HadError = true;
262773441091SDouglas Gregor     return;
262873441091SDouglas Gregor   }
262973441091SDouglas Gregor 
26309194a91dSDouglas Gregor   // Parse optional attributes.
26314442605fSBill Wendling   Attributes Attrs;
26325d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26335d29dee0SDavide Italiano     return;
26349194a91dSDouglas Gregor 
26359194a91dSDouglas Gregor   if (ActiveModule) {
263673441091SDouglas Gregor     // Note that we have an inferred submodule.
2637dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2638dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2639dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
26409194a91dSDouglas Gregor   } else {
26419194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
26429194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2643c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2644beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2645131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
26469194a91dSDouglas Gregor   }
264773441091SDouglas Gregor 
264873441091SDouglas Gregor   // Parse the opening brace.
264973441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
265073441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
265173441091SDouglas Gregor     HadError = true;
265273441091SDouglas Gregor     return;
265373441091SDouglas Gregor   }
265473441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
265573441091SDouglas Gregor 
265673441091SDouglas Gregor   // Parse the body of the inferred submodule.
265773441091SDouglas Gregor   bool Done = false;
265873441091SDouglas Gregor   do {
265973441091SDouglas Gregor     switch (Tok.Kind) {
266073441091SDouglas Gregor     case MMToken::EndOfFile:
266173441091SDouglas Gregor     case MMToken::RBrace:
266273441091SDouglas Gregor       Done = true;
266373441091SDouglas Gregor       break;
266473441091SDouglas Gregor 
2665afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
26669194a91dSDouglas Gregor       if (ActiveModule) {
26679194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2668d2d442caSCraig Topper           << (ActiveModule != nullptr);
26699194a91dSDouglas Gregor         consumeToken();
26709194a91dSDouglas Gregor         break;
26719194a91dSDouglas Gregor       }
26729194a91dSDouglas Gregor 
26739194a91dSDouglas Gregor       consumeToken();
2674306d8920SRichard Smith       // FIXME: Support string-literal module names here.
26759194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
26769194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
26779194a91dSDouglas Gregor         break;
26789194a91dSDouglas Gregor       }
26799194a91dSDouglas Gregor 
26809194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
26819194a91dSDouglas Gregor         .push_back(Tok.getString());
26829194a91dSDouglas Gregor       consumeToken();
26839194a91dSDouglas Gregor       break;
26849194a91dSDouglas Gregor 
26859194a91dSDouglas Gregor     case MMToken::ExportKeyword:
26869194a91dSDouglas Gregor       if (!ActiveModule) {
26879194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2688d2d442caSCraig Topper           << (ActiveModule != nullptr);
26899194a91dSDouglas Gregor         consumeToken();
26909194a91dSDouglas Gregor         break;
26919194a91dSDouglas Gregor       }
26929194a91dSDouglas Gregor 
269373441091SDouglas Gregor       consumeToken();
269473441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2695dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
269673441091SDouglas Gregor       else
269773441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
269873441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
269973441091SDouglas Gregor       consumeToken();
270073441091SDouglas Gregor       break;
270173441091SDouglas Gregor 
270273441091SDouglas Gregor     case MMToken::ExplicitKeyword:
270373441091SDouglas Gregor     case MMToken::ModuleKeyword:
270473441091SDouglas Gregor     case MMToken::HeaderKeyword:
2705b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
270673441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
270773441091SDouglas Gregor     default:
27089194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2709d2d442caSCraig Topper           << (ActiveModule != nullptr);
271073441091SDouglas Gregor       consumeToken();
271173441091SDouglas Gregor       break;
271273441091SDouglas Gregor     }
271373441091SDouglas Gregor   } while (!Done);
271473441091SDouglas Gregor 
271573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
271673441091SDouglas Gregor     consumeToken();
271773441091SDouglas Gregor   else {
271873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
271973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
272073441091SDouglas Gregor     HadError = true;
272173441091SDouglas Gregor   }
272273441091SDouglas Gregor }
272373441091SDouglas Gregor 
27249194a91dSDouglas Gregor /// \brief Parse optional attributes.
27259194a91dSDouglas Gregor ///
27269194a91dSDouglas Gregor ///   attributes:
27279194a91dSDouglas Gregor ///     attribute attributes
27289194a91dSDouglas Gregor ///     attribute
27299194a91dSDouglas Gregor ///
27309194a91dSDouglas Gregor ///   attribute:
27319194a91dSDouglas Gregor ///     [ identifier ]
27329194a91dSDouglas Gregor ///
27339194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
27349194a91dSDouglas Gregor ///
27359194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
27364442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
27379194a91dSDouglas Gregor   bool HadError = false;
27389194a91dSDouglas Gregor 
27399194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
27409194a91dSDouglas Gregor     // Consume the '['.
27419194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
27429194a91dSDouglas Gregor 
27439194a91dSDouglas Gregor     // Check whether we have an attribute name here.
27449194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
27459194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
27469194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
27479194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
27489194a91dSDouglas Gregor         consumeToken();
27499194a91dSDouglas Gregor       HadError = true;
27509194a91dSDouglas Gregor     }
27519194a91dSDouglas Gregor 
27529194a91dSDouglas Gregor     // Decode the attribute name.
27539194a91dSDouglas Gregor     AttributeKind Attribute
27549194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
275535b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
275677944868SRichard Smith           .Case("extern_c", AT_extern_c)
2757ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
27589194a91dSDouglas Gregor           .Case("system", AT_system)
27599194a91dSDouglas Gregor           .Default(AT_unknown);
27609194a91dSDouglas Gregor     switch (Attribute) {
27619194a91dSDouglas Gregor     case AT_unknown:
27629194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
27639194a91dSDouglas Gregor         << Tok.getString();
27649194a91dSDouglas Gregor       break;
27659194a91dSDouglas Gregor 
27669194a91dSDouglas Gregor     case AT_system:
27679194a91dSDouglas Gregor       Attrs.IsSystem = true;
27689194a91dSDouglas Gregor       break;
276935b13eceSDouglas Gregor 
277077944868SRichard Smith     case AT_extern_c:
277177944868SRichard Smith       Attrs.IsExternC = true;
277277944868SRichard Smith       break;
277377944868SRichard Smith 
277435b13eceSDouglas Gregor     case AT_exhaustive:
277535b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
277635b13eceSDouglas Gregor       break;
2777ed84df00SBruno Cardoso Lopes 
2778ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2779ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2780ed84df00SBruno Cardoso Lopes       break;
27819194a91dSDouglas Gregor     }
27829194a91dSDouglas Gregor     consumeToken();
27839194a91dSDouglas Gregor 
27849194a91dSDouglas Gregor     // Consume the ']'.
27859194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
27869194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
27879194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
27889194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
27899194a91dSDouglas Gregor       HadError = true;
27909194a91dSDouglas Gregor     }
27919194a91dSDouglas Gregor 
27929194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
27939194a91dSDouglas Gregor       consumeToken();
27949194a91dSDouglas Gregor   }
27959194a91dSDouglas Gregor 
27969194a91dSDouglas Gregor   return HadError;
27979194a91dSDouglas Gregor }
27989194a91dSDouglas Gregor 
2799718292f2SDouglas Gregor /// \brief Parse a module map file.
2800718292f2SDouglas Gregor ///
2801718292f2SDouglas Gregor ///   module-map-file:
2802718292f2SDouglas Gregor ///     module-declaration*
2803718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2804718292f2SDouglas Gregor   do {
2805718292f2SDouglas Gregor     switch (Tok.Kind) {
2806718292f2SDouglas Gregor     case MMToken::EndOfFile:
2807718292f2SDouglas Gregor       return HadError;
2808718292f2SDouglas Gregor 
2809e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
281097292843SDaniel Jasper     case MMToken::ExternKeyword:
2811718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2812755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2813718292f2SDouglas Gregor       parseModuleDecl();
2814718292f2SDouglas Gregor       break;
2815718292f2SDouglas Gregor 
28161fb5c3a6SDouglas Gregor     case MMToken::Comma:
281735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2818fb912657SDouglas Gregor     case MMToken::Conflict:
2819a3feee2aSRichard Smith     case MMToken::Exclaim:
282059527666SDouglas Gregor     case MMToken::ExcludeKeyword:
28212b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2822f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2823718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2824718292f2SDouglas Gregor     case MMToken::Identifier:
2825718292f2SDouglas Gregor     case MMToken::LBrace:
28266ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2827a686e1b0SDouglas Gregor     case MMToken::LSquare:
28282b82c2a5SDouglas Gregor     case MMToken::Period:
2829b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2830718292f2SDouglas Gregor     case MMToken::RBrace:
2831a686e1b0SDouglas Gregor     case MMToken::RSquare:
28321fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
28332b82c2a5SDouglas Gregor     case MMToken::Star:
2834718292f2SDouglas Gregor     case MMToken::StringLiteral:
2835040e1266SRichard Smith     case MMToken::IntegerLiteral:
2836b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2837718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2838ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2839718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2840718292f2SDouglas Gregor       HadError = true;
2841718292f2SDouglas Gregor       consumeToken();
2842718292f2SDouglas Gregor       break;
2843718292f2SDouglas Gregor     }
2844718292f2SDouglas Gregor   } while (true);
2845718292f2SDouglas Gregor }
2846718292f2SDouglas Gregor 
28479acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2848c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
28498128f332SRichard Smith                                    unsigned *Offset,
2850ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
28518128f332SRichard Smith   assert(Target && "Missing target information");
28524ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
28534ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
28544ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
28554ddf2221SDouglas Gregor     return Known->second;
28564ddf2221SDouglas Gregor 
28578128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
28588128f332SRichard Smith   if (ID.isInvalid()) {
2859f3f84616SRichard Smith     auto FileCharacter =
2860f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
28618128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
28628128f332SRichard Smith   }
28638128f332SRichard Smith 
28648128f332SRichard Smith   assert(Target && "Missing target information");
28651f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2866718292f2SDouglas Gregor   if (!Buffer)
28674ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
28688128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
28698128f332SRichard Smith          "invalid buffer offset");
2870718292f2SDouglas Gregor 
2871718292f2SDouglas Gregor   // Parse this module map file.
28728128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
28738128f332SRichard Smith           Buffer->getBufferStart(),
28748128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
28758128f332SRichard Smith           Buffer->getBufferEnd());
28762a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2877beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2878c192d194SBruno Cardoso Lopes                          IsSystem);
2879718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
28804ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
28812a6edb30SRichard Smith 
28828128f332SRichard Smith   if (Offset) {
28838128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
28848128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
28858128f332SRichard Smith     *Offset = Loc.second;
28868128f332SRichard Smith   }
28878128f332SRichard Smith 
28882a6edb30SRichard Smith   // Notify callbacks that we parsed it.
28892a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
28902a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
28918587dfd9SBruno Cardoso Lopes 
2892718292f2SDouglas Gregor   return Result;
2893718292f2SDouglas Gregor }
2894