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"
25b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
269acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
273a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
283a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
293a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
30afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h"
31afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
32afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h"
33afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h"
34afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h"
36afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
37afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h"
383a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
393a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
40718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
41afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h"
42afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
43afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
44552c169eSRafael Espindola #include "llvm/Support/Path.h"
45fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.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 
57*b3e902f4SRichard Trieu void ModuleMapCallbacks::anchor() {}
58*b3e902f4SRichard Trieu 
59a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
60a3b5f71eSBruno Cardoso Lopes   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
61a3b5f71eSBruno Cardoso Lopes   if (PendingLinkAs != PendingLinkAsModule.end()) {
62a3b5f71eSBruno Cardoso Lopes     for (auto &Name : PendingLinkAs->second) {
63a3b5f71eSBruno Cardoso Lopes       auto *M = findModule(Name.getKey());
64a3b5f71eSBruno Cardoso Lopes       if (M)
65a3b5f71eSBruno Cardoso Lopes         M->UseExportAsModuleLinkName = true;
66a3b5f71eSBruno Cardoso Lopes     }
67a3b5f71eSBruno Cardoso Lopes   }
68a3b5f71eSBruno Cardoso Lopes }
69a3b5f71eSBruno Cardoso Lopes 
70a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) {
71a3b5f71eSBruno Cardoso Lopes   if (findModule(Mod->ExportAsModule))
72a3b5f71eSBruno Cardoso Lopes     Mod->UseExportAsModuleLinkName = true;
73a3b5f71eSBruno Cardoso Lopes   else
74a3b5f71eSBruno Cardoso Lopes     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
75a3b5f71eSBruno Cardoso Lopes }
76a3b5f71eSBruno Cardoso Lopes 
77040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
78040e1266SRichard Smith   switch ((int)Role) {
79040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
80040e1266SRichard Smith   case NormalHeader:
81040e1266SRichard Smith     return Module::HK_Normal;
82040e1266SRichard Smith   case PrivateHeader:
83040e1266SRichard Smith     return Module::HK_Private;
84040e1266SRichard Smith   case TextualHeader:
85040e1266SRichard Smith     return Module::HK_Textual;
86040e1266SRichard Smith   case PrivateHeader | TextualHeader:
87040e1266SRichard Smith     return Module::HK_PrivateTextual;
88040e1266SRichard Smith   }
89040e1266SRichard Smith }
90040e1266SRichard Smith 
91040e1266SRichard Smith ModuleMap::ModuleHeaderRole
92040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
93040e1266SRichard Smith   switch ((int)Kind) {
94040e1266SRichard Smith   case Module::HK_Normal:
95040e1266SRichard Smith     return NormalHeader;
96040e1266SRichard Smith   case Module::HK_Private:
97040e1266SRichard Smith     return PrivateHeader;
98040e1266SRichard Smith   case Module::HK_Textual:
99040e1266SRichard Smith     return TextualHeader;
100040e1266SRichard Smith   case Module::HK_PrivateTextual:
101040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
102040e1266SRichard Smith   case Module::HK_Excluded:
103040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
104040e1266SRichard Smith   }
105040e1266SRichard Smith   llvm_unreachable("unknown header kind");
106040e1266SRichard Smith }
107040e1266SRichard Smith 
1082b82c2a5SDouglas Gregor Module::ExportDecl
1092b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
1102b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
111e4412640SArgyrios Kyrtzidis                          bool Complain) const {
112f5eedd05SDouglas Gregor   // We may have just a wildcard.
113f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
114f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
115d2d442caSCraig Topper     return Module::ExportDecl(nullptr, true);
116f5eedd05SDouglas Gregor   }
117f5eedd05SDouglas Gregor 
118fb912657SDouglas Gregor   // Resolve the module-id.
119fb912657SDouglas Gregor   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
120fb912657SDouglas Gregor   if (!Context)
121afd1b1c9SEugene Zelenko     return {};
122fb912657SDouglas Gregor 
123fb912657SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
124fb912657SDouglas Gregor }
125fb912657SDouglas Gregor 
126fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
127fb912657SDouglas Gregor                                    bool Complain) const {
1282b82c2a5SDouglas Gregor   // Find the starting module.
129fb912657SDouglas Gregor   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1302b82c2a5SDouglas Gregor   if (!Context) {
1312b82c2a5SDouglas Gregor     if (Complain)
1320761a8a0SDaniel Jasper       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
133fb912657SDouglas Gregor       << Id[0].first << Mod->getFullModuleName();
1342b82c2a5SDouglas Gregor 
135d2d442caSCraig Topper     return nullptr;
1362b82c2a5SDouglas Gregor   }
1372b82c2a5SDouglas Gregor 
1382b82c2a5SDouglas Gregor   // Dig into the module path.
139fb912657SDouglas Gregor   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
140fb912657SDouglas Gregor     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1412b82c2a5SDouglas Gregor     if (!Sub) {
1422b82c2a5SDouglas Gregor       if (Complain)
1430761a8a0SDaniel Jasper         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
144fb912657SDouglas Gregor         << Id[I].first << Context->getFullModuleName()
145fb912657SDouglas Gregor         << SourceRange(Id[0].second, Id[I-1].second);
1462b82c2a5SDouglas Gregor 
147d2d442caSCraig Topper       return nullptr;
1482b82c2a5SDouglas Gregor     }
1492b82c2a5SDouglas Gregor 
1502b82c2a5SDouglas Gregor     Context = Sub;
1512b82c2a5SDouglas Gregor   }
1522b82c2a5SDouglas Gregor 
153fb912657SDouglas Gregor   return Context;
1542b82c2a5SDouglas Gregor }
1552b82c2a5SDouglas Gregor 
1569fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the
1571d60987fSRichard Smith /// subframework in which the given module lives.
1581d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1591d60987fSRichard Smith                                     SmallVectorImpl<char> &Path) {
1601d60987fSRichard Smith   // Collect the framework names from the given module to the top-level module.
1611d60987fSRichard Smith   SmallVector<StringRef, 2> Paths;
1621d60987fSRichard Smith   for (; Mod; Mod = Mod->Parent) {
1631d60987fSRichard Smith     if (Mod->IsFramework)
1641d60987fSRichard Smith       Paths.push_back(Mod->Name);
1651d60987fSRichard Smith   }
1661d60987fSRichard Smith 
1671d60987fSRichard Smith   if (Paths.empty())
1681d60987fSRichard Smith     return;
1691d60987fSRichard Smith 
1701d60987fSRichard Smith   // Add Frameworks/Name.framework for each subframework.
1711d60987fSRichard Smith   for (unsigned I = Paths.size() - 1; I != 0; --I)
1721d60987fSRichard Smith     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1731d60987fSRichard Smith }
1741d60987fSRichard Smith 
1759f6020bcSBruno Cardoso Lopes const FileEntry *ModuleMap::findHeader(
1769f6020bcSBruno Cardoso Lopes     Module *M, const Module::UnresolvedHeaderDirective &Header,
1779f6020bcSBruno Cardoso Lopes     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1789f6020bcSBruno Cardoso Lopes   // Search for the header file within the module's home directory.
1799f6020bcSBruno Cardoso Lopes   auto *Directory = M->Directory;
1809f6020bcSBruno Cardoso Lopes   SmallString<128> FullPathName(Directory->getName());
1819f6020bcSBruno Cardoso Lopes 
182040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
183040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
184040e1266SRichard Smith     if (!File ||
185040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
186040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
187040e1266SRichard Smith       return nullptr;
188040e1266SRichard Smith     return File;
189040e1266SRichard Smith   };
190040e1266SRichard Smith 
1919f6020bcSBruno Cardoso Lopes   auto GetFrameworkFile = [&]() -> const FileEntry * {
1921d60987fSRichard Smith     unsigned FullPathLength = FullPathName.size();
1931d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1941d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
1951d60987fSRichard Smith 
1961d60987fSRichard Smith     // Check whether this file is in the public headers.
1971d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1981d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
199040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
2001d60987fSRichard Smith       return File;
2011d60987fSRichard Smith 
2021d60987fSRichard Smith     // Check whether this file is in the private headers.
2031d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
2041d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
2051d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2061d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
2071d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
2081d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
2091d60987fSRichard Smith       RelativePathName.clear();
2101d60987fSRichard Smith     else
2111d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
2121d60987fSRichard Smith     FullPathName.resize(FullPathLength);
2131d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2141d60987fSRichard Smith                             Header.FileName);
2151d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
216040e1266SRichard Smith     return GetFile(FullPathName);
2179f6020bcSBruno Cardoso Lopes   };
2189f6020bcSBruno Cardoso Lopes 
2199f6020bcSBruno Cardoso Lopes   if (llvm::sys::path::is_absolute(Header.FileName)) {
2209f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
2219f6020bcSBruno Cardoso Lopes     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2229f6020bcSBruno Cardoso Lopes     return GetFile(Header.FileName);
2231d60987fSRichard Smith   }
2241d60987fSRichard Smith 
2259f6020bcSBruno Cardoso Lopes   if (M->isPartOfFramework())
2269f6020bcSBruno Cardoso Lopes     return GetFrameworkFile();
2279f6020bcSBruno Cardoso Lopes 
2281d60987fSRichard Smith   // Lookup for normal headers.
2291d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
2301d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
2319f6020bcSBruno Cardoso Lopes   auto *NormalHdrFile = GetFile(FullPathName);
2329f6020bcSBruno Cardoso Lopes 
2339f6020bcSBruno Cardoso Lopes   if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
2349f6020bcSBruno Cardoso Lopes     // The lack of 'framework' keyword in a module declaration it's a simple
2359f6020bcSBruno Cardoso Lopes     // mistake we can diagnose when the header exists within the proper
2369f6020bcSBruno Cardoso Lopes     // framework style path.
2379f6020bcSBruno Cardoso Lopes     FullPathName.assign(Directory->getName());
2389f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
239d101b5d7SErich Keane     if (GetFrameworkFile()) {
2409f6020bcSBruno Cardoso Lopes       Diags.Report(Header.FileNameLoc,
2419f6020bcSBruno Cardoso Lopes                    diag::warn_mmap_incomplete_framework_module_declaration)
2429f6020bcSBruno Cardoso Lopes           << Header.FileName << M->getFullModuleName();
2439f6020bcSBruno Cardoso Lopes       NeedsFramework = true;
2449f6020bcSBruno Cardoso Lopes     }
2459f6020bcSBruno Cardoso Lopes     return nullptr;
2469f6020bcSBruno Cardoso Lopes   }
2479f6020bcSBruno Cardoso Lopes 
2489f6020bcSBruno Cardoso Lopes   return NormalHdrFile;
2491d60987fSRichard Smith }
2501d60987fSRichard Smith 
251040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
2529f6020bcSBruno Cardoso Lopes                               const Module::UnresolvedHeaderDirective &Header,
2539f6020bcSBruno Cardoso Lopes                               bool &NeedsFramework) {
254040e1266SRichard Smith   SmallString<128> RelativePathName;
2559f6020bcSBruno Cardoso Lopes   if (const FileEntry *File =
2569f6020bcSBruno Cardoso Lopes           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
257040e1266SRichard Smith     if (Header.IsUmbrella) {
258040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
259040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
260040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
261040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
262040e1266SRichard Smith       else
263040e1266SRichard Smith         // Record this umbrella header.
264040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
265040e1266SRichard Smith     } else {
266040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
267040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
268040e1266SRichard Smith         excludeHeader(Mod, H);
269040e1266SRichard Smith       else
270040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
271040e1266SRichard Smith     }
272040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
273040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
274040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
275040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
276040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
277040e1266SRichard Smith   } else {
278040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
279040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
280040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
281040e1266SRichard Smith     // A missing header with stat information doesn't make the module
282040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
283040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
284040e1266SRichard Smith     // preprocessed source.)
285040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
286040e1266SRichard Smith       Mod->markUnavailable();
287040e1266SRichard Smith   }
288040e1266SRichard Smith }
289040e1266SRichard Smith 
290040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
291040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
292040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
293040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
294040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
295040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
296040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
297040e1266SRichard Smith     return false;
2981d60987fSRichard Smith 
2991d60987fSRichard Smith   // This is a system module with a top-level header. This header
3001d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
3011d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
302040e1266SRichard Smith   SmallString<128> Path;
303040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
304040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
305040e1266SRichard Smith   if (!File)
306040e1266SRichard Smith     return false;
307040e1266SRichard Smith 
308040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
309040e1266SRichard Smith   Module::Header H = {Path.str(), File};
310040e1266SRichard Smith   addHeader(Mod, H, Role);
311040e1266SRichard Smith   return true;
3121d60987fSRichard Smith }
3131d60987fSRichard Smith 
3140761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
315b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
316b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
3170761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
318056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
3190414b857SRichard Smith   MMapLangOpts.LineComment = true;
3200414b857SRichard Smith }
321718292f2SDouglas Gregor 
322718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
32321668754SDavide Italiano   for (auto &M : Modules)
32421668754SDavide Italiano     delete M.getValue();
3258587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
3268587dfd9SBruno Cardoso Lopes     delete M;
327718292f2SDouglas Gregor }
328718292f2SDouglas Gregor 
32989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
33089929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
33189929282SDouglas Gregor          "Improper target override");
33289929282SDouglas Gregor   this->Target = &Target;
33389929282SDouglas Gregor }
33489929282SDouglas Gregor 
3359fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier.
336056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
337056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
338056396aeSDouglas Gregor   if (Name.empty())
339056396aeSDouglas Gregor     return Name;
340056396aeSDouglas Gregor 
341a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
342056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
343056396aeSDouglas Gregor     // create a buffer with the sanitized name.
344056396aeSDouglas Gregor     Buffer.clear();
345a7d03840SJordan Rose     if (isDigit(Name[0]))
346056396aeSDouglas Gregor       Buffer.push_back('_');
347056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
348056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
349a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
350056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
351056396aeSDouglas Gregor       else
352056396aeSDouglas Gregor         Buffer.push_back('_');
353056396aeSDouglas Gregor     }
354056396aeSDouglas Gregor 
355056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
356056396aeSDouglas Gregor   }
357056396aeSDouglas Gregor 
358056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
359056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
360056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
361056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
362056396aeSDouglas Gregor            .Default(false)) {
363056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
364056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
365056396aeSDouglas Gregor     Buffer.push_back('_');
366056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
367056396aeSDouglas Gregor   }
368056396aeSDouglas Gregor 
369056396aeSDouglas Gregor   return Name;
370056396aeSDouglas Gregor }
371056396aeSDouglas Gregor 
3729fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin
37334d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
37434d52749SDouglas Gregor /// headers.
375ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37634d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
37734d52749SDouglas Gregor            .Case("float.h", true)
37834d52749SDouglas Gregor            .Case("iso646.h", true)
37934d52749SDouglas Gregor            .Case("limits.h", true)
38034d52749SDouglas Gregor            .Case("stdalign.h", true)
38134d52749SDouglas Gregor            .Case("stdarg.h", true)
3823c4b1290SBen Langmuir            .Case("stdatomic.h", true)
38334d52749SDouglas Gregor            .Case("stdbool.h", true)
38434d52749SDouglas Gregor            .Case("stddef.h", true)
38534d52749SDouglas Gregor            .Case("stdint.h", true)
38634d52749SDouglas Gregor            .Case("tgmath.h", true)
38734d52749SDouglas Gregor            .Case("unwind.h", true)
38834d52749SDouglas Gregor            .Default(false);
38934d52749SDouglas Gregor }
39034d52749SDouglas Gregor 
39192669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
39292669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
393040e1266SRichard Smith   resolveHeaderDirectives(File);
39459527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
39547972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
39647972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
397ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3984eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
39992669ee4SDaniel Jasper     return Headers.find(File);
4004eaf0a6cSDaniel Jasper   }
40192669ee4SDaniel Jasper   return Known;
40292669ee4SDaniel Jasper }
40392669ee4SDaniel Jasper 
4044469138eSBen Langmuir ModuleMap::KnownHeader
4054469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4064469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
40747972afdSRichard Smith   if (UmbrellaDirs.empty())
408afd1b1c9SEugene Zelenko     return {};
40947972afdSRichard Smith 
4104469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
4114469138eSBen Langmuir   assert(Dir && "file in no directory");
4124469138eSBen Langmuir 
4134469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
4144469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
4154469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
4164469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
4174469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4184469138eSBen Langmuir 
4194469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
4204469138eSBen Langmuir   // an umbrella header.
4214469138eSBen Langmuir   do {
4224469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4234469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4244469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4254469138eSBen Langmuir 
4264469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4274469138eSBen Langmuir 
4284469138eSBen Langmuir     // Retrieve our parent path.
4294469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4304469138eSBen Langmuir     if (DirName.empty())
4314469138eSBen Langmuir       break;
4324469138eSBen Langmuir 
4334469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4344469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
4354469138eSBen Langmuir   } while (Dir);
436afd1b1c9SEugene Zelenko   return {};
4374469138eSBen Langmuir }
4384469138eSBen Langmuir 
43992669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
44092669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4414eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44292669ee4SDaniel Jasper #ifndef NDEBUG
4434eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
44492669ee4SDaniel Jasper     // Check for consistency between the module header role
44592669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
44692669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4472708e520SRichard Smith     bool IsPrivate = false;
4482708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4494eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4504eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4512708e520SRichard Smith     for (auto *Hs : HeaderList)
4522708e520SRichard Smith       IsPrivate |=
4532708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4543c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4552708e520SRichard Smith           }) != Hs->end();
4564eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
45700bc95ecSRichard Smith   }
45892669ee4SDaniel Jasper #endif
4594eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
46092669ee4SDaniel Jasper }
46192669ee4SDaniel Jasper 
46271e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46371e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
46471e1a64fSBen Langmuir }
46571e1a64fSBen Langmuir 
46692669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4678d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
46892669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
46992669ee4SDaniel Jasper                                         StringRef Filename,
47092669ee4SDaniel Jasper                                         const FileEntry *File) {
47192669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47292669ee4SDaniel Jasper   // with no source files.
47371e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47492669ee4SDaniel Jasper     return;
47592669ee4SDaniel Jasper 
476040e1266SRichard Smith   if (RequestingModule) {
47792669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
478040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
479040e1266SRichard Smith   }
48092669ee4SDaniel Jasper 
48171e1a64fSBen Langmuir   bool Excluded = false;
482d2d442caSCraig Topper   Module *Private = nullptr;
483d2d442caSCraig Topper   Module *NotUsed = nullptr;
48471e1a64fSBen Langmuir 
48571e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
48671e1a64fSBen Langmuir   if (Known != Headers.end()) {
48771e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
48892669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4894eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
49071e1a64fSBen Langmuir         Private = Header.getModule();
49192669ee4SDaniel Jasper         continue;
49292669ee4SDaniel Jasper       }
49392669ee4SDaniel Jasper 
49492669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
49592669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
49692669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4978f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
49871e1a64fSBen Langmuir         NotUsed = Header.getModule();
49992669ee4SDaniel Jasper         continue;
50092669ee4SDaniel Jasper       }
50192669ee4SDaniel Jasper 
50292669ee4SDaniel Jasper       // We have found a module that we can happily use.
50392669ee4SDaniel Jasper       return;
50492669ee4SDaniel Jasper     }
505feb54b6dSRichard Smith 
506feb54b6dSRichard Smith     Excluded = true;
50771e1a64fSBen Langmuir   }
50892669ee4SDaniel Jasper 
50992669ee4SDaniel Jasper   // We have found a header, but it is private.
510d2d442caSCraig Topper   if (Private) {
51111152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51292669ee4SDaniel Jasper         << Filename;
51392669ee4SDaniel Jasper     return;
51492669ee4SDaniel Jasper   }
51592669ee4SDaniel Jasper 
51692669ee4SDaniel Jasper   // We have found a module, but we don't use it.
517d2d442caSCraig Topper   if (NotUsed) {
51811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5194ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
52092669ee4SDaniel Jasper     return;
52192669ee4SDaniel Jasper   }
52292669ee4SDaniel Jasper 
52371e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
52471e1a64fSBen Langmuir     return;
52571e1a64fSBen Langmuir 
52671e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
52771e1a64fSBen Langmuir 
5285904c41eSBenjamin Kramer   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
52911152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5304ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
531a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
532a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
533a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
53471e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53571e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
53671e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
53770a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
53870a7738fSManman Ren         << File->getName();
53971e1a64fSBen Langmuir   }
54092669ee4SDaniel Jasper }
54192669ee4SDaniel Jasper 
542ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
543ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5448b7c0398SSean Silva   // Prefer available modules.
5458b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5468b7c0398SSean Silva     return true;
5478b7c0398SSean Silva 
548ec87a50aSRichard Smith   // Prefer a public header over a private header.
549ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
550ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
551ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
552ec87a50aSRichard Smith 
553ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
554ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
555ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
556ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
557ec87a50aSRichard Smith 
558ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
559ec87a50aSRichard Smith   return false;
560ec87a50aSRichard Smith }
561ec87a50aSRichard Smith 
562ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
563ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
564306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
565ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
566afd1b1c9SEugene Zelenko       return {};
567306d8920SRichard Smith     return R;
568306d8920SRichard Smith   };
569306d8920SRichard Smith 
5704881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5711fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
572202210b3SRichard Smith     ModuleMap::KnownHeader Result;
57397da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5744881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5757e82e019SRichard Smith       // Prefer a header from the source module over all others.
5767e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5772f633e7cSRichard Smith         return MakeResult(H);
5784881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5794881e8b2SSean Silva         Result = H;
58097da9178SDaniel Jasper     }
581306d8920SRichard Smith     return MakeResult(Result);
5821fb5c3a6SDouglas Gregor   }
583ab0c8a84SDouglas Gregor 
584386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
585386bb073SRichard Smith }
586386bb073SRichard Smith 
587386bb073SRichard Smith ModuleMap::KnownHeader
588386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
589386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
590386bb073SRichard Smith 
591f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5924469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5934469138eSBen Langmuir   if (H) {
5944469138eSBen Langmuir     Module *Result = H.getModule();
595930a85ccSDouglas Gregor 
596930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
59773141fa9SDouglas Gregor     // directory.
598930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
59973141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
600930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
601930a85ccSDouglas Gregor 
602930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6039d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6049d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6059d6448b1SBen Langmuir 
606a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
607a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
608a89c5ac4SDouglas Gregor       // the actual header is located.
6099458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6109458f82dSDouglas Gregor 
6117033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
612a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
613056396aeSDouglas Gregor         SmallString<32> NameBuf;
614056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6154469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6169d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6179d6448b1SBen Langmuir                                     Explicit).first;
6189d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
619ffbafa2aSBen Langmuir         Result->IsInferred = true;
620a89c5ac4SDouglas Gregor 
621a89c5ac4SDouglas Gregor         // Associate the module and the directory.
622a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
623a89c5ac4SDouglas Gregor 
624a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
625a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
626930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
627d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
628a89c5ac4SDouglas Gregor       }
629a89c5ac4SDouglas Gregor 
630a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
631056396aeSDouglas Gregor       SmallString<32> NameBuf;
632056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
633056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6349d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6359d6448b1SBen Langmuir                                   Explicit).first;
6369d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
637ffbafa2aSBen Langmuir       Result->IsInferred = true;
6383c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
639a89c5ac4SDouglas Gregor 
640a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
641a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
642930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
643d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
644a89c5ac4SDouglas Gregor     } else {
645a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
646a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
647a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
648a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
649a89c5ac4SDouglas Gregor     }
650a89c5ac4SDouglas Gregor 
651386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
652386bb073SRichard Smith     Headers[File].push_back(Header);
653386bb073SRichard Smith     return Header;
654a89c5ac4SDouglas Gregor   }
655a89c5ac4SDouglas Gregor 
656afd1b1c9SEugene Zelenko   return {};
657ab0c8a84SDouglas Gregor }
658ab0c8a84SDouglas Gregor 
659386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
660386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
661040e1266SRichard Smith   resolveHeaderDirectives(File);
662386bb073SRichard Smith   auto It = Headers.find(File);
663386bb073SRichard Smith   if (It == Headers.end())
664386bb073SRichard Smith     return None;
665386bb073SRichard Smith   return It->second;
666386bb073SRichard Smith }
667386bb073SRichard Smith 
668e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
669d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
67050996ce1SRichard Smith }
67150996ce1SRichard Smith 
67262bcd925SDmitri Gribenko bool
67362bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
67462bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
675040e1266SRichard Smith   resolveHeaderDirectives(Header);
676e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
67797da9178SDaniel Jasper   if (Known != Headers.end()) {
67897da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
67997da9178SDaniel Jasper              I = Known->second.begin(),
68097da9178SDaniel Jasper              E = Known->second.end();
68197da9178SDaniel Jasper          I != E; ++I) {
682052d95a6SBruno Cardoso Lopes 
683052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
684052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
685052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
686052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
687052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
688052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
689052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
690052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
691052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
692052d95a6SBruno Cardoso Lopes           continue;
69397da9178SDaniel Jasper         return false;
69497da9178SDaniel Jasper       }
695052d95a6SBruno Cardoso Lopes     }
69697da9178SDaniel Jasper     return true;
69797da9178SDaniel Jasper   }
6981fb5c3a6SDouglas Gregor 
6991fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
700f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7011fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7021fb5c3a6SDouglas Gregor 
70350996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
70450996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
70550996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
70650996ce1SRichard Smith   };
70750996ce1SRichard Smith 
7081fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7091fb5c3a6SDouglas Gregor   // an umbrella header.
7101fb5c3a6SDouglas Gregor   do {
711e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7121fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7131fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7141fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
71550996ce1SRichard Smith       if (IsUnavailable(Found))
7161fb5c3a6SDouglas Gregor         return true;
7171fb5c3a6SDouglas Gregor 
7181fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7191fb5c3a6SDouglas Gregor       // directory.
7201fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7211fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7221fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7231fb5c3a6SDouglas Gregor 
7241fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7251fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7261fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
727056396aeSDouglas Gregor           SmallString<32> NameBuf;
728056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
729056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
730056396aeSDouglas Gregor                              NameBuf);
7311fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7321fb5c3a6SDouglas Gregor           if (!Found)
7331fb5c3a6SDouglas Gregor             return false;
73450996ce1SRichard Smith           if (IsUnavailable(Found))
7351fb5c3a6SDouglas Gregor             return true;
7361fb5c3a6SDouglas Gregor         }
7371fb5c3a6SDouglas Gregor 
7381fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
739056396aeSDouglas Gregor         SmallString<32> NameBuf;
740056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
741056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
742056396aeSDouglas Gregor                            NameBuf);
7431fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7441fb5c3a6SDouglas Gregor         if (!Found)
7451fb5c3a6SDouglas Gregor           return false;
7461fb5c3a6SDouglas Gregor       }
7471fb5c3a6SDouglas Gregor 
74850996ce1SRichard Smith       return IsUnavailable(Found);
7491fb5c3a6SDouglas Gregor     }
7501fb5c3a6SDouglas Gregor 
7511fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7521fb5c3a6SDouglas Gregor 
7531fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7541fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7551fb5c3a6SDouglas Gregor     if (DirName.empty())
7561fb5c3a6SDouglas Gregor       break;
7571fb5c3a6SDouglas Gregor 
7581fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7591f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7601fb5c3a6SDouglas Gregor   } while (Dir);
7611fb5c3a6SDouglas Gregor 
7621fb5c3a6SDouglas Gregor   return false;
7631fb5c3a6SDouglas Gregor }
7641fb5c3a6SDouglas Gregor 
765e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
766e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
76788bdfb0eSDouglas Gregor   if (Known != Modules.end())
76888bdfb0eSDouglas Gregor     return Known->getValue();
76988bdfb0eSDouglas Gregor 
770d2d442caSCraig Topper   return nullptr;
77188bdfb0eSDouglas Gregor }
77288bdfb0eSDouglas Gregor 
773e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
774e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7752b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7762b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7772b82c2a5SDouglas Gregor       return Sub;
7782b82c2a5SDouglas Gregor   }
7792b82c2a5SDouglas Gregor 
7802b82c2a5SDouglas Gregor   return findModule(Name);
7812b82c2a5SDouglas Gregor }
7822b82c2a5SDouglas Gregor 
783e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7842b82c2a5SDouglas Gregor   if (!Context)
7852b82c2a5SDouglas Gregor     return findModule(Name);
7862b82c2a5SDouglas Gregor 
787eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7882b82c2a5SDouglas Gregor }
7892b82c2a5SDouglas Gregor 
790c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
791c192d194SBruno Cardoso Lopes                                                         Module *Parent,
792c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
793c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
79469021974SDouglas Gregor   // Try to find an existing module with this name.
795eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
796eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
79769021974SDouglas Gregor 
79869021974SDouglas Gregor   // Create a new module with this name.
7999ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8009ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
8016f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8027e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8037e82e019SRichard Smith       SourceModule = Result;
80469021974SDouglas Gregor     Modules[Name] = Result;
805c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8066f722b4eSArgyrios Kyrtzidis   }
80769021974SDouglas Gregor   return std::make_pair(Result, true);
80869021974SDouglas Gregor }
80969021974SDouglas Gregor 
810dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
811d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
812056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
813056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
814d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
815d6509cf2SRichard Smith   return PendingSubmodules.back().get();
816dd8b5337SRichard Smith }
817dd8b5337SRichard Smith 
818bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
819dd8b5337SRichard Smith                                                 StringRef Name,
820dd8b5337SRichard Smith                                                 Module *GlobalModule) {
821bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
822bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
823bbcc9f04SRichard Smith 
824bbcc9f04SRichard Smith   auto *Result =
825bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
826bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
827145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
828bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
829bbcc9f04SRichard Smith 
830dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
831d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
832d6509cf2SRichard Smith     Submodule->setParent(Result);
833d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
834d6509cf2SRichard Smith   }
835d6509cf2SRichard Smith   PendingSubmodules.clear();
836dd8b5337SRichard Smith 
837bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
838bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
839bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
840bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
841bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
842bbcc9f04SRichard Smith 
843bbcc9f04SRichard Smith   return Result;
844bbcc9f04SRichard Smith }
845bbcc9f04SRichard Smith 
846d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
847d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
848d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
849d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
850d6509cf2SRichard Smith 
851d6509cf2SRichard Smith   auto *Result =
852d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
853d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
854d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
855d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
856d6509cf2SRichard Smith 
857d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
858d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
859d6509cf2SRichard Smith                          /*IsFramework*/ false,
860d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
861d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
862d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
863d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
864d6509cf2SRichard Smith   }
865d6509cf2SRichard Smith 
866d6509cf2SRichard Smith   return Result;
867d6509cf2SRichard Smith }
868d6509cf2SRichard Smith 
8699fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
87011dfe6feSDouglas Gregor /// should link.
87111dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
87211dfe6feSDouglas Gregor                                FileManager &FileMgr) {
87311dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
87411dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
87511dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
87611dfe6feSDouglas Gregor 
87711dfe6feSDouglas Gregor   SmallString<128> LibName;
87811dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
87911dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8808aaae5a9SJuergen Ributzka 
8818aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8828aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8838aaae5a9SJuergen Ributzka   // for both before we give up.
8848013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8858aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
88611dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
88711dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
88811dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8898aaae5a9SJuergen Ributzka       return;
8908aaae5a9SJuergen Ributzka     }
89111dfe6feSDouglas Gregor   }
89211dfe6feSDouglas Gregor }
89311dfe6feSDouglas Gregor 
894a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
895a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
896c1d88ea5SBen Langmuir   Attributes Attrs;
897c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
898a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
899c1d88ea5SBen Langmuir }
900c1d88ea5SBen Langmuir 
901a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
902c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
903a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
904a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
905a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
906a525400dSBen Langmuir   // top-level framework.
907a525400dSBen Langmuir   StringRef FrameworkDirName =
908a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
909a525400dSBen Langmuir 
910a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
911a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
912a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
913a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
914a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
915a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
916c1d88ea5SBen Langmuir 
91756c64013SDouglas Gregor   // Check whether we've already found this module.
918e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
919e89dbc1dSDouglas Gregor     return Mod;
920e89dbc1dSDouglas Gregor 
9211f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
92256c64013SDouglas Gregor 
9239194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9249194a91dSDouglas Gregor   // a framework module, do so.
925beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9269194a91dSDouglas Gregor   if (!Parent) {
9274ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9289194a91dSDouglas Gregor     bool canInfer = false;
9294ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9309194a91dSDouglas Gregor       // Figure out the parent path.
9314ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9329194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
9339194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9349194a91dSDouglas Gregor         // for a module map.
935e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9369194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
9379194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9389194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9399194a91dSDouglas Gregor           // one.
940984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
941984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
942984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
943c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
9449194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
9459194a91dSDouglas Gregor           }
9469194a91dSDouglas Gregor 
9479194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9489194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9499194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
9509194a91dSDouglas Gregor         }
9519194a91dSDouglas Gregor 
9529194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9539194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9549194a91dSDouglas Gregor           // to infer this particular module.
9554ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9569194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9579194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9589194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9599194a91dSDouglas Gregor 
960c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
961c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
962c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
963ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
964ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
965beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9669194a91dSDouglas Gregor         }
9679194a91dSDouglas Gregor       }
9689194a91dSDouglas Gregor     }
9699194a91dSDouglas Gregor 
9709194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9719194a91dSDouglas Gregor     if (!canInfer)
972d2d442caSCraig Topper       return nullptr;
973beee15e7SBen Langmuir   } else
9749d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9759194a91dSDouglas Gregor 
9769194a91dSDouglas Gregor 
97756c64013SDouglas Gregor   // Look for an umbrella header.
9782c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
97917381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
980e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
98156c64013SDouglas Gregor 
98256c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
98356c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
98456c64013SDouglas Gregor   // idea.
98556c64013SDouglas Gregor   if (!UmbrellaHeader)
986d2d442caSCraig Topper     return nullptr;
98756c64013SDouglas Gregor 
9889d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
989a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
990a7e2cc68SRichard Smith                               NumCreatedModules++);
9919d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
9929d6448b1SBen Langmuir   Result->IsInferred = true;
9937e82e019SRichard Smith   if (!Parent) {
9947e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
995ba7f2f71SDaniel Jasper       SourceModule = Result;
9967e82e019SRichard Smith     Modules[ModuleName] = Result;
997c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
998ba7f2f71SDaniel Jasper   }
999c1d88ea5SBen Langmuir 
1000c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
1001c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1002c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1003ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10042b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1005a686e1b0SDouglas Gregor 
1006322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
10072b63d15fSRichard Smith   //
10082b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
10092b63d15fSRichard Smith   // a framework module.
10102b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
1011d8bd7537SDouglas Gregor 
1012d8bd7537SDouglas Gregor   // export *
1013d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1014d8bd7537SDouglas Gregor 
1015a89c5ac4SDouglas Gregor   // module * { export * }
1016a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1017a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1018a89c5ac4SDouglas Gregor 
1019e89dbc1dSDouglas Gregor   // Look for subframeworks.
1020c080917eSRafael Espindola   std::error_code EC;
10212c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1022ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1023e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10242d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1025fc51490bSJonas Devlieghere   llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
1026fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1027fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1028b171a59bSBruno Cardoso Lopes            DirEnd;
1029e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10300ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1031e89dbc1dSDouglas Gregor       continue;
1032f2161a70SDouglas Gregor 
1033b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
10340ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
103507c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
103607c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
103707c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
103807c22b78SDouglas Gregor       // out to a top-level framework.
1039e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
104007c22b78SDouglas Gregor       bool FoundParent = false;
104107c22b78SDouglas Gregor       do {
104207c22b78SDouglas Gregor         // Get the parent directory name.
104307c22b78SDouglas Gregor         SubframeworkDirName
104407c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
104507c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
104607c22b78SDouglas Gregor           break;
104707c22b78SDouglas Gregor 
104807c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
104907c22b78SDouglas Gregor           FoundParent = true;
105007c22b78SDouglas Gregor           break;
105107c22b78SDouglas Gregor         }
105207c22b78SDouglas Gregor       } while (true);
105307c22b78SDouglas Gregor 
105407c22b78SDouglas Gregor       if (!FoundParent)
105507c22b78SDouglas Gregor         continue;
105607c22b78SDouglas Gregor 
1057e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1058a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
1059e89dbc1dSDouglas Gregor     }
1060e89dbc1dSDouglas Gregor   }
1061e89dbc1dSDouglas Gregor 
106211dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
106311dfe6feSDouglas Gregor   // framework.
106411dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
106511dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
106611dfe6feSDouglas Gregor   }
106711dfe6feSDouglas Gregor 
106856c64013SDouglas Gregor   return Result;
106956c64013SDouglas Gregor }
107056c64013SDouglas Gregor 
10718587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10728587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10738587dfd9SBruno Cardoso Lopes 
10748587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10758587dfd9SBruno Cardoso Lopes   Module *Result =
10768587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10778587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10788587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
10798587dfd9SBruno Cardoso Lopes   Result->IsAvailable = false;
1080c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10818587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
10828587dfd9SBruno Cardoso Lopes 
10838587dfd9SBruno Cardoso Lopes   return Result;
10848587dfd9SBruno Cardoso Lopes }
10858587dfd9SBruno Cardoso Lopes 
10862b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
10872b63d15fSRichard Smith                                   Twine NameAsWritten) {
108897da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
108973141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
10902b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
10917033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1092b3a0fa48SBruno Cardoso Lopes 
1093b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1094b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1095b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1096a89c5ac4SDouglas Gregor }
1097a89c5ac4SDouglas Gregor 
10982b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
10992b63d15fSRichard Smith                                Twine NameAsWritten) {
1100524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
11012b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1102524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1103524e33e1SDouglas Gregor }
1104524e33e1SDouglas Gregor 
1105040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11069f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11079f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1108040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1109040e1266SRichard Smith   // wrap the system header.
1110040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1111040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1112040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1113040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1114040e1266SRichard Smith     // case.
1115040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1116040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1117040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11183c1a41adSRichard Smith   }
1119040e1266SRichard Smith 
1120040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1121040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1122040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1123040e1266SRichard Smith   // headers.
1124040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1125040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1126040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1127040e1266SRichard Smith     // use the mtime as the key.
1128040e1266SRichard Smith     if (Header.ModTime)
1129040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1130040e1266SRichard Smith     else
1131040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1132040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1133040e1266SRichard Smith     return;
1134040e1266SRichard Smith   }
1135040e1266SRichard Smith 
1136040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1137040e1266SRichard Smith   // Perform the lookup now.
11389f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1139040e1266SRichard Smith }
1140040e1266SRichard Smith 
1141040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1142040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1143040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1144040e1266SRichard Smith     for (auto *M : BySize->second)
1145040e1266SRichard Smith       resolveHeaderDirectives(M);
1146040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1147040e1266SRichard Smith   }
1148040e1266SRichard Smith 
1149040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1150040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1151040e1266SRichard Smith     for (auto *M : ByModTime->second)
1152040e1266SRichard Smith       resolveHeaderDirectives(M);
1153040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1154040e1266SRichard Smith   }
1155040e1266SRichard Smith }
1156040e1266SRichard Smith 
1157040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11589f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1159040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1160040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1161040e1266SRichard Smith     // the header information for this file.
11629f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1163040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
11640e98d938SNAKAMURA Takumi }
1165202210b3SRichard Smith 
11663c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1167d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1168386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11693c1a41adSRichard Smith 
1170386bb073SRichard Smith   // Only add each header to the headers list once.
1171386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1172386bb073SRichard Smith   // same module definition?
1173386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1174386bb073SRichard Smith   for (auto H : HeaderList)
1175386bb073SRichard Smith     if (H == KH)
1176386bb073SRichard Smith       return;
1177386bb073SRichard Smith 
1178386bb073SRichard Smith   HeaderList.push_back(KH);
11791ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1180386bb073SRichard Smith 
11817e82e019SRichard Smith   bool isCompilingModuleHeader =
1182bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1183d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1184d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1185d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1186d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1187d8879c85SRichard Smith                                     isCompilingModuleHeader);
1188d8879c85SRichard Smith   }
1189e62cfd7cSBruno Cardoso Lopes 
1190e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1191e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1192f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1193a89c5ac4SDouglas Gregor }
1194a89c5ac4SDouglas Gregor 
11953c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1196feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1197feb54b6dSRichard Smith   // umbrella directory module.
1198feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1199feb54b6dSRichard Smith   // specified module?
12003c1a41adSRichard Smith   (void) Headers[Header.Entry];
12013c1a41adSRichard Smith 
12023c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1203feb54b6dSRichard Smith }
1204feb54b6dSRichard Smith 
1205514b636aSDouglas Gregor const FileEntry *
12064b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12071f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1208d2d442caSCraig Topper     return nullptr;
1209514b636aSDouglas Gregor 
12101f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12111f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1212514b636aSDouglas Gregor }
1213514b636aSDouglas Gregor 
12144b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12159d6448b1SBen Langmuir   if (M->IsInferred) {
12169d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12179d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12189d6448b1SBen Langmuir   }
12199d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12209d6448b1SBen Langmuir }
12219d6448b1SBen Langmuir 
12229d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12239d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12249d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12259d6448b1SBen Langmuir }
12269d6448b1SBen Langmuir 
1227cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1228718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1229718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1230718292f2SDouglas Gregor                                         MEnd = Modules.end();
1231718292f2SDouglas Gregor        M != MEnd; ++M)
1232d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1233718292f2SDouglas Gregor 
1234718292f2SDouglas Gregor   llvm::errs() << "Headers:";
123559527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1236718292f2SDouglas Gregor        H != HEnd; ++H) {
123797da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
123897da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
123997da9178SDaniel Jasper                                                       E = H->second.end();
124097da9178SDaniel Jasper          I != E; ++I) {
124197da9178SDaniel Jasper       if (I != H->second.begin())
124297da9178SDaniel Jasper         llvm::errs() << ",";
124397da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
124497da9178SDaniel Jasper     }
124597da9178SDaniel Jasper     llvm::errs() << "\n";
1246718292f2SDouglas Gregor   }
1247718292f2SDouglas Gregor }
1248718292f2SDouglas Gregor 
12492b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
125042413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
125142413141SRichard Smith   Mod->UnresolvedExports.clear();
125242413141SRichard Smith   for (auto &UE : Unresolved) {
125342413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1254f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12552b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12562b82c2a5SDouglas Gregor     else
125742413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12582b82c2a5SDouglas Gregor   }
125942413141SRichard Smith   return !Mod->UnresolvedExports.empty();
12602b82c2a5SDouglas Gregor }
12612b82c2a5SDouglas Gregor 
1262ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
126342413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
126442413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
126542413141SRichard Smith   for (auto &UDU : Unresolved) {
126642413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1267ba7f2f71SDaniel Jasper     if (DirectUse)
1268ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1269ba7f2f71SDaniel Jasper     else
127042413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1271ba7f2f71SDaniel Jasper   }
127242413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1273ba7f2f71SDaniel Jasper }
1274ba7f2f71SDaniel Jasper 
1275fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
127642413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
127742413141SRichard Smith   Mod->UnresolvedConflicts.clear();
127842413141SRichard Smith   for (auto &UC : Unresolved) {
127942413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1280fb912657SDouglas Gregor       Module::Conflict Conflict;
1281fb912657SDouglas Gregor       Conflict.Other = OtherMod;
128242413141SRichard Smith       Conflict.Message = UC.Message;
1283fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
128442413141SRichard Smith     } else
128542413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1286fb912657SDouglas Gregor   }
128742413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1288fb912657SDouglas Gregor }
1289fb912657SDouglas Gregor 
1290718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1291718292f2SDouglas Gregor // Module map file parser
1292718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1293718292f2SDouglas Gregor 
1294718292f2SDouglas Gregor namespace clang {
1295afd1b1c9SEugene Zelenko 
12969fc8faf9SAdrian Prantl   /// A token in a module map file.
1297718292f2SDouglas Gregor   struct MMToken {
1298718292f2SDouglas Gregor     enum TokenKind {
12991fb5c3a6SDouglas Gregor       Comma,
130035b13eceSDouglas Gregor       ConfigMacros,
1301fb912657SDouglas Gregor       Conflict,
1302718292f2SDouglas Gregor       EndOfFile,
1303718292f2SDouglas Gregor       HeaderKeyword,
1304718292f2SDouglas Gregor       Identifier,
1305a3feee2aSRichard Smith       Exclaim,
130659527666SDouglas Gregor       ExcludeKeyword,
1307718292f2SDouglas Gregor       ExplicitKeyword,
13082b82c2a5SDouglas Gregor       ExportKeyword,
1309f0b11de2SDouglas Gregor       ExportAsKeyword,
131097292843SDaniel Jasper       ExternKeyword,
1311755b2055SDouglas Gregor       FrameworkKeyword,
13126ddfca91SDouglas Gregor       LinkKeyword,
1313718292f2SDouglas Gregor       ModuleKeyword,
13142b82c2a5SDouglas Gregor       Period,
1315b53e5483SLawrence Crowl       PrivateKeyword,
1316718292f2SDouglas Gregor       UmbrellaKeyword,
1317ba7f2f71SDaniel Jasper       UseKeyword,
13181fb5c3a6SDouglas Gregor       RequiresKeyword,
13192b82c2a5SDouglas Gregor       Star,
1320718292f2SDouglas Gregor       StringLiteral,
1321040e1266SRichard Smith       IntegerLiteral,
1322306d8920SRichard Smith       TextualKeyword,
1323718292f2SDouglas Gregor       LBrace,
1324a686e1b0SDouglas Gregor       RBrace,
1325a686e1b0SDouglas Gregor       LSquare,
1326a686e1b0SDouglas Gregor       RSquare
1327718292f2SDouglas Gregor     } Kind;
1328718292f2SDouglas Gregor 
1329718292f2SDouglas Gregor     unsigned Location;
1330718292f2SDouglas Gregor     unsigned StringLength;
1331040e1266SRichard Smith     union {
1332040e1266SRichard Smith       // If Kind != IntegerLiteral.
1333718292f2SDouglas Gregor       const char *StringData;
1334afd1b1c9SEugene Zelenko 
1335040e1266SRichard Smith       // If Kind == IntegerLiteral.
1336040e1266SRichard Smith       uint64_t IntegerValue;
1337040e1266SRichard Smith     };
1338718292f2SDouglas Gregor 
1339718292f2SDouglas Gregor     void clear() {
1340718292f2SDouglas Gregor       Kind = EndOfFile;
1341718292f2SDouglas Gregor       Location = 0;
1342718292f2SDouglas Gregor       StringLength = 0;
1343d2d442caSCraig Topper       StringData = nullptr;
1344718292f2SDouglas Gregor     }
1345718292f2SDouglas Gregor 
1346718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1347718292f2SDouglas Gregor 
1348718292f2SDouglas Gregor     SourceLocation getLocation() const {
1349718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1350718292f2SDouglas Gregor     }
1351718292f2SDouglas Gregor 
1352040e1266SRichard Smith     uint64_t getInteger() const {
1353040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1354040e1266SRichard Smith     }
1355040e1266SRichard Smith 
1356718292f2SDouglas Gregor     StringRef getString() const {
1357040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1358040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1359718292f2SDouglas Gregor     }
1360718292f2SDouglas Gregor   };
1361718292f2SDouglas Gregor 
1362718292f2SDouglas Gregor   class ModuleMapParser {
1363718292f2SDouglas Gregor     Lexer &L;
1364718292f2SDouglas Gregor     SourceManager &SourceMgr;
1365bc10b9fbSDouglas Gregor 
13669fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1367bc10b9fbSDouglas Gregor     /// parsing.
1368bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1369bc10b9fbSDouglas Gregor 
1370718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1371718292f2SDouglas Gregor     ModuleMap &Map;
1372718292f2SDouglas Gregor 
13739fc8faf9SAdrian Prantl     /// The current module map file.
1374beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1375beee15e7SBen Langmuir 
13769f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
13779f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
13789f6020bcSBruno Cardoso Lopes 
13799fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
13809acb99e3SRichard Smith     /// be resolved relative to.
13815257fc63SDouglas Gregor     const DirectoryEntry *Directory;
13825257fc63SDouglas Gregor 
13839fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1384963c5535SDouglas Gregor     bool IsSystem;
1385963c5535SDouglas Gregor 
13869fc8faf9SAdrian Prantl     /// Whether an error occurred.
1387afd1b1c9SEugene Zelenko     bool HadError = false;
1388718292f2SDouglas Gregor 
13899fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1390718292f2SDouglas Gregor     /// during parsing.
1391718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1392718292f2SDouglas Gregor 
13939fc8faf9SAdrian Prantl     /// The current token.
1394718292f2SDouglas Gregor     MMToken Tok;
1395718292f2SDouglas Gregor 
13969fc8faf9SAdrian Prantl     /// The active module.
1397afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1398718292f2SDouglas Gregor 
13999fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
14007ff29148SBen Langmuir     /// contents as 'textual'.
14017ff29148SBen Langmuir     ///
14027ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14037ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14047ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14057ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14067ff29148SBen Langmuir     /// 'textual' to match the original intent.
14077ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14087ff29148SBen Langmuir 
14099fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1410718292f2SDouglas Gregor     SourceLocation consumeToken();
1411718292f2SDouglas Gregor 
14129fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1413718292f2SDouglas Gregor     /// (or the end of the file).
1414718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1415718292f2SDouglas Gregor 
1416afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1417afd1b1c9SEugene Zelenko 
1418e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1419718292f2SDouglas Gregor     void parseModuleDecl();
142097292843SDaniel Jasper     void parseExternModuleDecl();
14211fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1422afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1423524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14242b82c2a5SDouglas Gregor     void parseExportDecl();
1425f0b11de2SDouglas Gregor     void parseExportAsDecl();
1426ba7f2f71SDaniel Jasper     void parseUseDecl();
14276ddfca91SDouglas Gregor     void parseLinkDecl();
142835b13eceSDouglas Gregor     void parseConfigMacros();
1429fb912657SDouglas Gregor     void parseConflict();
14309194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1431c1d88ea5SBen Langmuir 
14325f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14335f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14345f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14355f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14365f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14375f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14385f11e128SBruno Cardoso Lopes 
1439afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1440afd1b1c9SEugene Zelenko 
14414442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1442718292f2SDouglas Gregor 
1443718292f2SDouglas Gregor   public:
1444718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14458587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14468587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1447c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1448bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1449beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1450c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1451718292f2SDouglas Gregor       Tok.clear();
1452718292f2SDouglas Gregor       consumeToken();
1453718292f2SDouglas Gregor     }
1454718292f2SDouglas Gregor 
1455718292f2SDouglas Gregor     bool parseModuleMapFile();
14568128f332SRichard Smith 
14578128f332SRichard Smith     bool terminatedByDirective() { return false; }
14588128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1459718292f2SDouglas Gregor   };
1460afd1b1c9SEugene Zelenko 
1461afd1b1c9SEugene Zelenko } // namespace clang
1462718292f2SDouglas Gregor 
1463718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1464718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1465718292f2SDouglas Gregor 
14668128f332SRichard Smith retry:
14678128f332SRichard Smith   Tok.clear();
1468718292f2SDouglas Gregor   Token LToken;
1469718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1470718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1471718292f2SDouglas Gregor   switch (LToken.getKind()) {
14722d57cea2SAlp Toker   case tok::raw_identifier: {
14732d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
14742d57cea2SAlp Toker     Tok.StringData = RI.data();
14752d57cea2SAlp Toker     Tok.StringLength = RI.size();
14762d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
147735b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1478fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
147959527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1480718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
14812b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1482f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
148397292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1484755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
148535b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
14866ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1487718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1488b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
14891fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1490306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1491718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1492ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1493718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1494718292f2SDouglas Gregor     break;
14952d57cea2SAlp Toker   }
1496718292f2SDouglas Gregor 
14971fb5c3a6SDouglas Gregor   case tok::comma:
14981fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
14991fb5c3a6SDouglas Gregor     break;
15001fb5c3a6SDouglas Gregor 
1501718292f2SDouglas Gregor   case tok::eof:
1502718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1503718292f2SDouglas Gregor     break;
1504718292f2SDouglas Gregor 
1505718292f2SDouglas Gregor   case tok::l_brace:
1506718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1507718292f2SDouglas Gregor     break;
1508718292f2SDouglas Gregor 
1509a686e1b0SDouglas Gregor   case tok::l_square:
1510a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1511a686e1b0SDouglas Gregor     break;
1512a686e1b0SDouglas Gregor 
15132b82c2a5SDouglas Gregor   case tok::period:
15142b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15152b82c2a5SDouglas Gregor     break;
15162b82c2a5SDouglas Gregor 
1517718292f2SDouglas Gregor   case tok::r_brace:
1518718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1519718292f2SDouglas Gregor     break;
1520718292f2SDouglas Gregor 
1521a686e1b0SDouglas Gregor   case tok::r_square:
1522a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1523a686e1b0SDouglas Gregor     break;
1524a686e1b0SDouglas Gregor 
15252b82c2a5SDouglas Gregor   case tok::star:
15262b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15272b82c2a5SDouglas Gregor     break;
15282b82c2a5SDouglas Gregor 
1529a3feee2aSRichard Smith   case tok::exclaim:
1530a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1531a3feee2aSRichard Smith     break;
1532a3feee2aSRichard Smith 
1533718292f2SDouglas Gregor   case tok::string_literal: {
1534d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1535d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1536d67aea28SRichard Smith       HadError = true;
1537d67aea28SRichard Smith       goto retry;
1538d67aea28SRichard Smith     }
1539d67aea28SRichard Smith 
1540718292f2SDouglas Gregor     // Parse the string literal.
1541718292f2SDouglas Gregor     LangOptions LangOpts;
15429d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1543718292f2SDouglas Gregor     if (StringLiteral.hadError)
1544718292f2SDouglas Gregor       goto retry;
1545718292f2SDouglas Gregor 
1546718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1547718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1548718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1549718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1550718292f2SDouglas Gregor     Saved[Length] = 0;
1551718292f2SDouglas Gregor 
1552718292f2SDouglas Gregor     // Form the token.
1553718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1554718292f2SDouglas Gregor     Tok.StringData = Saved;
1555718292f2SDouglas Gregor     Tok.StringLength = Length;
1556718292f2SDouglas Gregor     break;
1557718292f2SDouglas Gregor   }
1558718292f2SDouglas Gregor 
1559040e1266SRichard Smith   case tok::numeric_constant: {
1560040e1266SRichard Smith     // We don't support any suffixes or other complications.
1561040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1562040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1563040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1564040e1266SRichard Smith     unsigned Length =
1565040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1566040e1266SRichard Smith     uint64_t Value;
1567040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1568040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1569040e1266SRichard Smith       HadError = true;
1570040e1266SRichard Smith       goto retry;
1571040e1266SRichard Smith     }
1572040e1266SRichard Smith 
1573040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1574040e1266SRichard Smith     Tok.IntegerValue = Value;
1575040e1266SRichard Smith     break;
1576040e1266SRichard Smith   }
1577040e1266SRichard Smith 
1578718292f2SDouglas Gregor   case tok::comment:
1579718292f2SDouglas Gregor     goto retry;
1580718292f2SDouglas Gregor 
15818128f332SRichard Smith   case tok::hash:
15828128f332SRichard Smith     // A module map can be terminated prematurely by
15838128f332SRichard Smith     //   #pragma clang module contents
15848128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
15858128f332SRichard Smith     // contents of the module.
15868128f332SRichard Smith     {
15878128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
15888128f332SRichard Smith         L.LexFromRawLexer(LToken);
15898128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15908128f332SRichard Smith                LToken.getRawIdentifier() == Str;
15918128f332SRichard Smith       };
15928128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
15938128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
15948128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
15958128f332SRichard Smith         break;
15968128f332SRichard Smith       }
15978128f332SRichard Smith     }
15988128f332SRichard Smith     LLVM_FALLTHROUGH;
15998128f332SRichard Smith 
1600718292f2SDouglas Gregor   default:
16018128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1602718292f2SDouglas Gregor     HadError = true;
1603718292f2SDouglas Gregor     goto retry;
1604718292f2SDouglas Gregor   }
1605718292f2SDouglas Gregor 
1606718292f2SDouglas Gregor   return Result;
1607718292f2SDouglas Gregor }
1608718292f2SDouglas Gregor 
1609718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1610718292f2SDouglas Gregor   unsigned braceDepth = 0;
1611a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1612718292f2SDouglas Gregor   do {
1613718292f2SDouglas Gregor     switch (Tok.Kind) {
1614718292f2SDouglas Gregor     case MMToken::EndOfFile:
1615718292f2SDouglas Gregor       return;
1616718292f2SDouglas Gregor 
1617718292f2SDouglas Gregor     case MMToken::LBrace:
1618a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1619718292f2SDouglas Gregor         return;
1620718292f2SDouglas Gregor 
1621718292f2SDouglas Gregor       ++braceDepth;
1622718292f2SDouglas Gregor       break;
1623718292f2SDouglas Gregor 
1624a686e1b0SDouglas Gregor     case MMToken::LSquare:
1625a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1626a686e1b0SDouglas Gregor         return;
1627a686e1b0SDouglas Gregor 
1628a686e1b0SDouglas Gregor       ++squareDepth;
1629a686e1b0SDouglas Gregor       break;
1630a686e1b0SDouglas Gregor 
1631718292f2SDouglas Gregor     case MMToken::RBrace:
1632718292f2SDouglas Gregor       if (braceDepth > 0)
1633718292f2SDouglas Gregor         --braceDepth;
1634718292f2SDouglas Gregor       else if (Tok.is(K))
1635718292f2SDouglas Gregor         return;
1636718292f2SDouglas Gregor       break;
1637718292f2SDouglas Gregor 
1638a686e1b0SDouglas Gregor     case MMToken::RSquare:
1639a686e1b0SDouglas Gregor       if (squareDepth > 0)
1640a686e1b0SDouglas Gregor         --squareDepth;
1641a686e1b0SDouglas Gregor       else if (Tok.is(K))
1642a686e1b0SDouglas Gregor         return;
1643a686e1b0SDouglas Gregor       break;
1644a686e1b0SDouglas Gregor 
1645718292f2SDouglas Gregor     default:
1646a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1647718292f2SDouglas Gregor         return;
1648718292f2SDouglas Gregor       break;
1649718292f2SDouglas Gregor     }
1650718292f2SDouglas Gregor 
1651718292f2SDouglas Gregor    consumeToken();
1652718292f2SDouglas Gregor   } while (true);
1653718292f2SDouglas Gregor }
1654718292f2SDouglas Gregor 
16559fc8faf9SAdrian Prantl /// Parse a module-id.
1656e7ab3669SDouglas Gregor ///
1657e7ab3669SDouglas Gregor ///   module-id:
1658e7ab3669SDouglas Gregor ///     identifier
1659e7ab3669SDouglas Gregor ///     identifier '.' module-id
1660e7ab3669SDouglas Gregor ///
1661e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1662e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1663e7ab3669SDouglas Gregor   Id.clear();
1664e7ab3669SDouglas Gregor   do {
16653cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1666e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1667e7ab3669SDouglas Gregor       consumeToken();
1668e7ab3669SDouglas Gregor     } else {
1669e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1670e7ab3669SDouglas Gregor       return true;
1671e7ab3669SDouglas Gregor     }
1672e7ab3669SDouglas Gregor 
1673e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1674e7ab3669SDouglas Gregor       break;
1675e7ab3669SDouglas Gregor 
1676e7ab3669SDouglas Gregor     consumeToken();
1677e7ab3669SDouglas Gregor   } while (true);
1678e7ab3669SDouglas Gregor 
1679e7ab3669SDouglas Gregor   return false;
1680e7ab3669SDouglas Gregor }
1681e7ab3669SDouglas Gregor 
1682a686e1b0SDouglas Gregor namespace {
1683afd1b1c9SEugene Zelenko 
16849fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1685a686e1b0SDouglas Gregor   enum AttributeKind {
16869fc8faf9SAdrian Prantl     /// An unknown attribute.
1687a686e1b0SDouglas Gregor     AT_unknown,
1688afd1b1c9SEugene Zelenko 
16899fc8faf9SAdrian Prantl     /// The 'system' attribute.
169035b13eceSDouglas Gregor     AT_system,
1691afd1b1c9SEugene Zelenko 
16929fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
169377944868SRichard Smith     AT_extern_c,
1694afd1b1c9SEugene Zelenko 
16959fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1696ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1697afd1b1c9SEugene Zelenko 
16989fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1699ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1700a686e1b0SDouglas Gregor   };
1701afd1b1c9SEugene Zelenko 
1702afd1b1c9SEugene Zelenko } // namespace
1703a686e1b0SDouglas Gregor 
170429729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
170529729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
170629729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
170729729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17085f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17095f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
171029729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17117d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
171229729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
171329729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
171429729919SBruno Cardoso Lopes     D << BadName << M->Name;
17157d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
171629729919SBruno Cardoso Lopes   };
171729729919SBruno Cardoso Lopes 
171829729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
171929729919SBruno Cardoso Lopes     auto const *M = E->getValue();
172029729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
172129729919SBruno Cardoso Lopes       continue;
172229729919SBruno Cardoso Lopes 
172329729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
172429729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
172529729919SBruno Cardoso Lopes       continue;
17265f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
172729729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
172829729919SBruno Cardoso Lopes     Canonical.append("_Private");
172929729919SBruno Cardoso Lopes 
173029729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
173129729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
173229729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
173329729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
173429729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
173529729919SBruno Cardoso Lopes           << FullName;
17365f11e128SBruno Cardoso Lopes 
17375f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17385f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17395f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17405f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17415f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17425f11e128SBruno Cardoso Lopes 
17435f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17445f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17455f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17465f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
17475f11e128SBruno Cardoso Lopes 
17485f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17495f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
175029729919SBruno Cardoso Lopes       continue;
175129729919SBruno Cardoso Lopes     }
175229729919SBruno Cardoso Lopes 
175329729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
175429729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
175529729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
175629729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
175729729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
175829729919SBruno Cardoso Lopes           << ActiveModule->Name;
17597d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
17607d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
176129729919SBruno Cardoso Lopes     }
176229729919SBruno Cardoso Lopes   }
176329729919SBruno Cardoso Lopes }
176429729919SBruno Cardoso Lopes 
17659fc8faf9SAdrian Prantl /// Parse a module declaration.
1766718292f2SDouglas Gregor ///
1767718292f2SDouglas Gregor ///   module-declaration:
176897292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1769a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1770a686e1b0SDouglas Gregor ///       { module-member* }
1771a686e1b0SDouglas Gregor ///
1772718292f2SDouglas Gregor ///   module-member:
17731fb5c3a6SDouglas Gregor ///     requires-declaration
1774718292f2SDouglas Gregor ///     header-declaration
1775e7ab3669SDouglas Gregor ///     submodule-declaration
17762b82c2a5SDouglas Gregor ///     export-declaration
1777f0b11de2SDouglas Gregor ///     export-as-declaration
17786ddfca91SDouglas Gregor ///     link-declaration
177973441091SDouglas Gregor ///
178073441091SDouglas Gregor ///   submodule-declaration:
178173441091SDouglas Gregor ///     module-declaration
178273441091SDouglas Gregor ///     inferred-submodule-declaration
1783718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1784755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
178597292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
178697292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
178797292843SDaniel Jasper     parseExternModuleDecl();
178897292843SDaniel Jasper     return;
178997292843SDaniel Jasper   }
179097292843SDaniel Jasper 
1791f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1792e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
17935f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1794718292f2SDouglas Gregor   bool Explicit = false;
1795f2161a70SDouglas Gregor   bool Framework = false;
1796755b2055SDouglas Gregor 
1797f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1798f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1799e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1800f2161a70SDouglas Gregor     Explicit = true;
1801f2161a70SDouglas Gregor   }
1802f2161a70SDouglas Gregor 
1803f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1804755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18055f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1806755b2055SDouglas Gregor     Framework = true;
1807755b2055SDouglas Gregor   }
1808718292f2SDouglas Gregor 
1809718292f2SDouglas Gregor   // Parse 'module' keyword.
1810718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1811d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1812718292f2SDouglas Gregor     consumeToken();
1813718292f2SDouglas Gregor     HadError = true;
1814718292f2SDouglas Gregor     return;
1815718292f2SDouglas Gregor   }
18169f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1817718292f2SDouglas Gregor 
181873441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
181973441091SDouglas Gregor   // Parse it.
182073441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18219194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
182273441091SDouglas Gregor 
1823718292f2SDouglas Gregor   // Parse the module name.
1824e7ab3669SDouglas Gregor   ModuleId Id;
1825e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1826718292f2SDouglas Gregor     HadError = true;
1827718292f2SDouglas Gregor     return;
1828718292f2SDouglas Gregor   }
1829e7ab3669SDouglas Gregor 
1830e7ab3669SDouglas Gregor   if (ActiveModule) {
1831e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1832e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1833e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1834e7ab3669SDouglas Gregor 
1835e7ab3669SDouglas Gregor       HadError = true;
1836e7ab3669SDouglas Gregor       return;
1837e7ab3669SDouglas Gregor     }
1838e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1839e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1840e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1841e7ab3669SDouglas Gregor     Explicit = false;
1842e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1843e7ab3669SDouglas Gregor     HadError = true;
1844e7ab3669SDouglas Gregor   }
1845e7ab3669SDouglas Gregor 
1846e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1847e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1848e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1849e7ab3669SDouglas Gregor     // is a submodule.
1850d2d442caSCraig Topper     ActiveModule = nullptr;
18514b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1852e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1853e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
18544b8a9e95SBen Langmuir         if (I == 0)
18554b8a9e95SBen Langmuir           TopLevelModule = Next;
1856e7ab3669SDouglas Gregor         ActiveModule = Next;
1857e7ab3669SDouglas Gregor         continue;
1858e7ab3669SDouglas Gregor       }
1859e7ab3669SDouglas Gregor 
1860e7ab3669SDouglas Gregor       if (ActiveModule) {
1861e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
18625b5d21eaSRichard Smith           << Id[I].first
18635b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1864e7ab3669SDouglas Gregor       } else {
1865e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1866e7ab3669SDouglas Gregor       }
1867e7ab3669SDouglas Gregor       HadError = true;
1868e7ab3669SDouglas Gregor       return;
1869e7ab3669SDouglas Gregor     }
18704b8a9e95SBen Langmuir 
18714b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
18724b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
18734b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
18744b8a9e95SBen Langmuir              "top-level module");
18754b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
18764b8a9e95SBen Langmuir     }
1877e7ab3669SDouglas Gregor   }
1878e7ab3669SDouglas Gregor 
1879e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1880e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1881718292f2SDouglas Gregor 
1882a686e1b0SDouglas Gregor   // Parse the optional attribute list.
18834442605fSBill Wendling   Attributes Attrs;
18845d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
18855d29dee0SDavide Italiano     return;
18865d29dee0SDavide Italiano 
1887718292f2SDouglas Gregor   // Parse the opening brace.
1888718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1889718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1890718292f2SDouglas Gregor       << ModuleName;
1891718292f2SDouglas Gregor     HadError = true;
1892718292f2SDouglas Gregor     return;
1893718292f2SDouglas Gregor   }
1894718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1895718292f2SDouglas Gregor 
1896718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
18978587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1898eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
18994a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
19004a3751ffSRichard Smith     // definition for in two cases:
19014a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19024a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19034a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19044a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19054a3751ffSRichard Smith     //    module map file from which it was created.
19064a3751ffSRichard Smith     bool ParsedAsMainInput =
19074a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19084a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19094a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19104a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19114a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1912fcc54a3bSDouglas Gregor       // Skip the module definition.
1913fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1914fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1915fcc54a3bSDouglas Gregor         consumeToken();
1916fcc54a3bSDouglas Gregor       else {
1917fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1918fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1919fcc54a3bSDouglas Gregor         HadError = true;
1920fcc54a3bSDouglas Gregor       }
1921fcc54a3bSDouglas Gregor       return;
1922fcc54a3bSDouglas Gregor     }
1923fcc54a3bSDouglas Gregor 
1924c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19258587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19268587dfd9SBruno Cardoso Lopes     } else {
19278587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1928718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1929718292f2SDouglas Gregor           << ModuleName;
1930eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1931718292f2SDouglas Gregor 
1932718292f2SDouglas Gregor       // Skip the module definition.
1933718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1934718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1935718292f2SDouglas Gregor         consumeToken();
1936718292f2SDouglas Gregor 
1937718292f2SDouglas Gregor       HadError = true;
1938718292f2SDouglas Gregor       return;
1939718292f2SDouglas Gregor     }
19408587dfd9SBruno Cardoso Lopes   }
1941718292f2SDouglas Gregor 
1942718292f2SDouglas Gregor   // Start defining this module.
19438587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19448587dfd9SBruno Cardoso Lopes     ActiveModule =
19458587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19468587dfd9SBruno Cardoso Lopes   } else {
1947c192d194SBruno Cardoso Lopes     ActiveModule =
1948c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19498587dfd9SBruno Cardoso Lopes             .first;
19508587dfd9SBruno Cardoso Lopes   }
19518587dfd9SBruno Cardoso Lopes 
1952eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1953963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1954a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
195577944868SRichard Smith   if (Attrs.IsExternC)
195677944868SRichard Smith     ActiveModule->IsExternC = true;
1957ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1958ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1959ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
19603c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1961718292f2SDouglas Gregor 
196290b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
196390b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
196490b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
196590b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
196690b0a1fcSJordan Rose   }
196729729919SBruno Cardoso Lopes 
196829729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
196929729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
197029729919SBruno Cardoso Lopes   // Foo_Private instead.
197129729919SBruno Cardoso Lopes   SourceLocation StartLoc =
197229729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
197329729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
197429729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
197529729919SBruno Cardoso Lopes                        StartLoc) &&
197629729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
197729729919SBruno Cardoso Lopes                        StartLoc) &&
197890b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
19795f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
19804d867640SGraydon Hoare 
1981718292f2SDouglas Gregor   bool Done = false;
1982718292f2SDouglas Gregor   do {
1983718292f2SDouglas Gregor     switch (Tok.Kind) {
1984718292f2SDouglas Gregor     case MMToken::EndOfFile:
1985718292f2SDouglas Gregor     case MMToken::RBrace:
1986718292f2SDouglas Gregor       Done = true;
1987718292f2SDouglas Gregor       break;
1988718292f2SDouglas Gregor 
198935b13eceSDouglas Gregor     case MMToken::ConfigMacros:
199035b13eceSDouglas Gregor       parseConfigMacros();
199135b13eceSDouglas Gregor       break;
199235b13eceSDouglas Gregor 
1993fb912657SDouglas Gregor     case MMToken::Conflict:
1994fb912657SDouglas Gregor       parseConflict();
1995fb912657SDouglas Gregor       break;
1996fb912657SDouglas Gregor 
1997718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
199897292843SDaniel Jasper     case MMToken::ExternKeyword:
1999f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
2000718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2001718292f2SDouglas Gregor       parseModuleDecl();
2002718292f2SDouglas Gregor       break;
2003718292f2SDouglas Gregor 
20042b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20052b82c2a5SDouglas Gregor       parseExportDecl();
20062b82c2a5SDouglas Gregor       break;
20072b82c2a5SDouglas Gregor 
2008f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2009f0b11de2SDouglas Gregor       parseExportAsDecl();
2010f0b11de2SDouglas Gregor       break;
2011f0b11de2SDouglas Gregor 
2012ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2013ba7f2f71SDaniel Jasper       parseUseDecl();
2014ba7f2f71SDaniel Jasper       break;
2015ba7f2f71SDaniel Jasper 
20161fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20171fb5c3a6SDouglas Gregor       parseRequiresDecl();
20181fb5c3a6SDouglas Gregor       break;
20191fb5c3a6SDouglas Gregor 
2020202210b3SRichard Smith     case MMToken::TextualKeyword:
2021202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2022306d8920SRichard Smith       break;
2023306d8920SRichard Smith 
2024524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2025524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2026524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2027b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2028524e33e1SDouglas Gregor       else
2029524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2030718292f2SDouglas Gregor       break;
2031524e33e1SDouglas Gregor     }
2032718292f2SDouglas Gregor 
2033202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2034202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
203559527666SDouglas Gregor       break;
203659527666SDouglas Gregor 
2037202210b3SRichard Smith     case MMToken::PrivateKeyword:
2038202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2039b53e5483SLawrence Crowl       break;
2040b53e5483SLawrence Crowl 
2041322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2042202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2043718292f2SDouglas Gregor       break;
2044718292f2SDouglas Gregor 
20456ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20466ddfca91SDouglas Gregor       parseLinkDecl();
20476ddfca91SDouglas Gregor       break;
20486ddfca91SDouglas Gregor 
2049718292f2SDouglas Gregor     default:
2050718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2051718292f2SDouglas Gregor       consumeToken();
2052718292f2SDouglas Gregor       break;
2053718292f2SDouglas Gregor     }
2054718292f2SDouglas Gregor   } while (!Done);
2055718292f2SDouglas Gregor 
2056718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2057718292f2SDouglas Gregor     consumeToken();
2058718292f2SDouglas Gregor   else {
2059718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2060718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2061718292f2SDouglas Gregor     HadError = true;
2062718292f2SDouglas Gregor   }
2063718292f2SDouglas Gregor 
206411dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
206511dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
206611dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
206711dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
206811dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
206911dfe6feSDouglas Gregor   }
207011dfe6feSDouglas Gregor 
2071ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2072ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2073ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
2074ec8c9752SBen Langmuir       ActiveModule->Parent) {
2075ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
2076ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2077ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2078ec8c9752SBen Langmuir   }
2079ec8c9752SBen Langmuir 
2080e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2081e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2082718292f2SDouglas Gregor }
2083718292f2SDouglas Gregor 
20849fc8faf9SAdrian Prantl /// Parse an extern module declaration.
208597292843SDaniel Jasper ///
208697292843SDaniel Jasper ///   extern module-declaration:
208797292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
208897292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
208997292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2090ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
209197292843SDaniel Jasper 
209297292843SDaniel Jasper   // Parse 'module' keyword.
209397292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
209497292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
209597292843SDaniel Jasper     consumeToken();
209697292843SDaniel Jasper     HadError = true;
209797292843SDaniel Jasper     return;
209897292843SDaniel Jasper   }
209997292843SDaniel Jasper   consumeToken(); // 'module' keyword
210097292843SDaniel Jasper 
210197292843SDaniel Jasper   // Parse the module name.
210297292843SDaniel Jasper   ModuleId Id;
210397292843SDaniel Jasper   if (parseModuleId(Id)) {
210497292843SDaniel Jasper     HadError = true;
210597292843SDaniel Jasper     return;
210697292843SDaniel Jasper   }
210797292843SDaniel Jasper 
210897292843SDaniel Jasper   // Parse the referenced module map file name.
210997292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
211097292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
211197292843SDaniel Jasper     HadError = true;
211297292843SDaniel Jasper     return;
211397292843SDaniel Jasper   }
211497292843SDaniel Jasper   std::string FileName = Tok.getString();
211597292843SDaniel Jasper   consumeToken(); // filename
211697292843SDaniel Jasper 
211797292843SDaniel Jasper   StringRef FileNameRef = FileName;
211897292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
211997292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
212097292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
212197292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
212292e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
212397292843SDaniel Jasper   }
212497292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
21259acb99e3SRichard Smith     Map.parseModuleMapFile(
21269acb99e3SRichard Smith         File, /*IsSystem=*/false,
21279acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21289acb99e3SRichard Smith             ? Directory
21298128f332SRichard Smith             : File->getDir(),
2130c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
213197292843SDaniel Jasper }
213297292843SDaniel Jasper 
21337ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21347ff29148SBen Langmuir ///
21357ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21367ff29148SBen Langmuir /// module map files:
21377ff29148SBen Langmuir ///
21387ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21397ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21407ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21417ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21427ff29148SBen Langmuir ///    module to 'textual'.
21437ff29148SBen Langmuir ///
21447ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21457ff29148SBen Langmuir ///
21467ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21477ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21487ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21497ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21508013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21518013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21528013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21537ff29148SBen Langmuir     IsRequiresExcludedHack = true;
21547ff29148SBen Langmuir     return false;
21558013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21567ff29148SBen Langmuir     return false;
21577ff29148SBen Langmuir   }
21587ff29148SBen Langmuir 
21597ff29148SBen Langmuir   return true;
21607ff29148SBen Langmuir }
21617ff29148SBen Langmuir 
21629fc8faf9SAdrian Prantl /// Parse a requires declaration.
21631fb5c3a6SDouglas Gregor ///
21641fb5c3a6SDouglas Gregor ///   requires-declaration:
21651fb5c3a6SDouglas Gregor ///     'requires' feature-list
21661fb5c3a6SDouglas Gregor ///
21671fb5c3a6SDouglas Gregor ///   feature-list:
2168a3feee2aSRichard Smith ///     feature ',' feature-list
2169a3feee2aSRichard Smith ///     feature
2170a3feee2aSRichard Smith ///
2171a3feee2aSRichard Smith ///   feature:
2172a3feee2aSRichard Smith ///     '!'[opt] identifier
21731fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
21741fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
21751fb5c3a6SDouglas Gregor 
21761fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
21771fb5c3a6SDouglas Gregor   consumeToken();
21781fb5c3a6SDouglas Gregor 
21791fb5c3a6SDouglas Gregor   // Parse the feature-list.
21801fb5c3a6SDouglas Gregor   do {
2181a3feee2aSRichard Smith     bool RequiredState = true;
2182a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2183a3feee2aSRichard Smith       RequiredState = false;
2184a3feee2aSRichard Smith       consumeToken();
2185a3feee2aSRichard Smith     }
2186a3feee2aSRichard Smith 
21871fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
21881fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
21891fb5c3a6SDouglas Gregor       HadError = true;
21901fb5c3a6SDouglas Gregor       return;
21911fb5c3a6SDouglas Gregor     }
21921fb5c3a6SDouglas Gregor 
21931fb5c3a6SDouglas Gregor     // Consume the feature name.
21941fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
21951fb5c3a6SDouglas Gregor     consumeToken();
21961fb5c3a6SDouglas Gregor 
21977ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
21987ff29148SBen Langmuir     bool ShouldAddRequirement =
21997ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22007ff29148SBen Langmuir 
22017ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22027ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22037ff29148SBen Langmuir 
22047ff29148SBen Langmuir     if (ShouldAddRequirement) {
22051fb5c3a6SDouglas Gregor       // Add this feature.
22067ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22077ff29148SBen Langmuir                                    *Map.Target);
22087ff29148SBen Langmuir     }
22091fb5c3a6SDouglas Gregor 
22101fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22111fb5c3a6SDouglas Gregor       break;
22121fb5c3a6SDouglas Gregor 
22131fb5c3a6SDouglas Gregor     // Consume the comma.
22141fb5c3a6SDouglas Gregor     consumeToken();
22151fb5c3a6SDouglas Gregor   } while (true);
22161fb5c3a6SDouglas Gregor }
22171fb5c3a6SDouglas Gregor 
22189fc8faf9SAdrian Prantl /// Parse a header declaration.
2219718292f2SDouglas Gregor ///
2220718292f2SDouglas Gregor ///   header-declaration:
2221306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2222202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2223202210b3SRichard Smith ///     'exclude' 'header' string-literal
2224202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2225306d8920SRichard Smith ///
2226306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2227b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2228b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2229202210b3SRichard Smith   // We've already consumed the first token.
2230202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2231202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2232202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2233202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2234202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2235202210b3SRichard Smith       LeadingToken = Tok.Kind;
22361871ed3dSBenjamin Kramer       consumeToken();
2237202210b3SRichard Smith     }
2238202210b3SRichard Smith   }
22397ff29148SBen Langmuir 
2240202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2241202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2242202210b3SRichard Smith 
22437ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22447ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22457ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22467ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22477ff29148SBen Langmuir   }
22487ff29148SBen Langmuir 
2249202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2250202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2251202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2252202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2253202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2254202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2255202210b3SRichard Smith       return;
2256202210b3SRichard Smith     }
2257202210b3SRichard Smith     consumeToken();
2258202210b3SRichard Smith   }
2259718292f2SDouglas Gregor 
2260718292f2SDouglas Gregor   // Parse the header name.
2261718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2262718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2263718292f2SDouglas Gregor       << "header";
2264718292f2SDouglas Gregor     HadError = true;
2265718292f2SDouglas Gregor     return;
2266718292f2SDouglas Gregor   }
22673c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
22680761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
22690761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
22701d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2271040e1266SRichard Smith   Header.Kind =
2272040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2273040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2274718292f2SDouglas Gregor 
2275524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
22761d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
22770761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2278524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2279322f633cSDouglas Gregor     HadError = true;
2280322f633cSDouglas Gregor     return;
2281322f633cSDouglas Gregor   }
2282322f633cSDouglas Gregor 
2283040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2284040e1266SRichard Smith   // the file.
2285040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2286040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
22873ec6663bSDouglas Gregor 
2288040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2289040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2290040e1266SRichard Smith       StringRef Str = Tok.getString();
2291040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2292040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2293040e1266SRichard Smith                   .Case("size", Size)
2294040e1266SRichard Smith                   .Case("mtime", ModTime)
2295040e1266SRichard Smith                   .Default(Unknown)) {
2296040e1266SRichard Smith       case Size:
2297040e1266SRichard Smith         if (Header.Size)
2298040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2299040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2300040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2301040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2302040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2303040e1266SRichard Smith           break;
2304040e1266SRichard Smith         }
2305040e1266SRichard Smith         Header.Size = Tok.getInteger();
2306040e1266SRichard Smith         consumeToken();
2307040e1266SRichard Smith         break;
2308040e1266SRichard Smith 
2309040e1266SRichard Smith       case ModTime:
2310040e1266SRichard Smith         if (Header.ModTime)
2311040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2312040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2313040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2314040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2315040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2316040e1266SRichard Smith           break;
2317040e1266SRichard Smith         }
2318040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2319040e1266SRichard Smith         consumeToken();
2320040e1266SRichard Smith         break;
2321040e1266SRichard Smith 
2322040e1266SRichard Smith       case Unknown:
2323040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2324040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2325040e1266SRichard Smith         break;
2326040e1266SRichard Smith       }
23273ec6663bSDouglas Gregor     }
23285257fc63SDouglas Gregor 
2329040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2330040e1266SRichard Smith       consumeToken();
2331040e1266SRichard Smith     else {
2332040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2333040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2334322f633cSDouglas Gregor       HadError = true;
2335322f633cSDouglas Gregor     }
23360101b540SHans Wennborg   }
233725d50758SRichard Smith 
23389f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23399f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23409f6020bcSBruno Cardoso Lopes 
23419f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23429f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23439f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23449f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2345718292f2SDouglas Gregor }
2346718292f2SDouglas Gregor 
234741f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
234841f81994SBen Langmuir                                 const Module::Header *B) {
234941f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
235041f81994SBen Langmuir }
235141f81994SBen Langmuir 
23529fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2353524e33e1SDouglas Gregor ///
2354524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2355524e33e1SDouglas Gregor ///     umbrella string-literal
2356524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2357524e33e1SDouglas Gregor   // Parse the directory name.
2358524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2359524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2360524e33e1SDouglas Gregor       << "umbrella";
2361524e33e1SDouglas Gregor     HadError = true;
2362524e33e1SDouglas Gregor     return;
2363524e33e1SDouglas Gregor   }
2364524e33e1SDouglas Gregor 
2365524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2366524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2367524e33e1SDouglas Gregor 
2368524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2369524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2370524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2371524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2372524e33e1SDouglas Gregor     HadError = true;
2373524e33e1SDouglas Gregor     return;
2374524e33e1SDouglas Gregor   }
2375524e33e1SDouglas Gregor 
2376524e33e1SDouglas Gregor   // Look for this file.
2377d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2378524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2379524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2380524e33e1SDouglas Gregor   else {
23812c1dd271SDylan Noblesmith     SmallString<128> PathName;
2382524e33e1SDouglas Gregor     PathName = Directory->getName();
2383524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2384524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2385524e33e1SDouglas Gregor   }
2386524e33e1SDouglas Gregor 
2387524e33e1SDouglas Gregor   if (!Dir) {
2388a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2389524e33e1SDouglas Gregor       << DirName;
2390524e33e1SDouglas Gregor     return;
2391524e33e1SDouglas Gregor   }
2392524e33e1SDouglas Gregor 
23937ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
23947ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
23957ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
23967ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
23977ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
23987ff29148SBen Langmuir     std::error_code EC;
23997ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2400fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2401fc51490bSJonas Devlieghere         *SourceMgr.getFileManager().getVirtualFileSystem();
2402fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24037ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
24040ae00567SSam McCall       if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
24057ff29148SBen Langmuir 
24060ae00567SSam McCall         Module::Header Header = {I->path(), FE};
24077ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24087ff29148SBen Langmuir       }
24097ff29148SBen Langmuir     }
24107ff29148SBen Langmuir 
24117ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
241241f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
241341f81994SBen Langmuir 
24147ff29148SBen Langmuir     for (auto &Header : Headers)
24157ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24167ff29148SBen Langmuir     return;
24177ff29148SBen Langmuir   }
24187ff29148SBen Langmuir 
2419524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2420524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2421524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2422524e33e1SDouglas Gregor     HadError = true;
2423524e33e1SDouglas Gregor     return;
2424524e33e1SDouglas Gregor   }
2425524e33e1SDouglas Gregor 
2426524e33e1SDouglas Gregor   // Record this umbrella directory.
24272b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2428524e33e1SDouglas Gregor }
2429524e33e1SDouglas Gregor 
24309fc8faf9SAdrian Prantl /// Parse a module export declaration.
24312b82c2a5SDouglas Gregor ///
24322b82c2a5SDouglas Gregor ///   export-declaration:
24332b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24342b82c2a5SDouglas Gregor ///
24352b82c2a5SDouglas Gregor ///   wildcard-module-id:
24362b82c2a5SDouglas Gregor ///     identifier
24372b82c2a5SDouglas Gregor ///     '*'
24382b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24392b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24402b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24412b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24422b82c2a5SDouglas Gregor 
24432b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24442b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24452b82c2a5SDouglas Gregor   bool Wildcard = false;
24462b82c2a5SDouglas Gregor   do {
2447306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24482b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
24492b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
24502b82c2a5SDouglas Gregor                                               Tok.getLocation()));
24512b82c2a5SDouglas Gregor       consumeToken();
24522b82c2a5SDouglas Gregor 
24532b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
24542b82c2a5SDouglas Gregor         consumeToken();
24552b82c2a5SDouglas Gregor         continue;
24562b82c2a5SDouglas Gregor       }
24572b82c2a5SDouglas Gregor 
24582b82c2a5SDouglas Gregor       break;
24592b82c2a5SDouglas Gregor     }
24602b82c2a5SDouglas Gregor 
24612b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
24622b82c2a5SDouglas Gregor       Wildcard = true;
2463f5eedd05SDouglas Gregor       consumeToken();
24642b82c2a5SDouglas Gregor       break;
24652b82c2a5SDouglas Gregor     }
24662b82c2a5SDouglas Gregor 
2467ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
24682b82c2a5SDouglas Gregor     HadError = true;
24692b82c2a5SDouglas Gregor     return;
24702b82c2a5SDouglas Gregor   } while (true);
24712b82c2a5SDouglas Gregor 
24722b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
24732b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
24742b82c2a5SDouglas Gregor   };
24752b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
24762b82c2a5SDouglas Gregor }
24772b82c2a5SDouglas Gregor 
24789fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2479f0b11de2SDouglas Gregor ///
2480f0b11de2SDouglas Gregor ///   export-as-declaration:
2481f0b11de2SDouglas Gregor ///     'export_as' identifier
2482f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2483f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2484f0b11de2SDouglas Gregor   consumeToken();
2485f0b11de2SDouglas Gregor 
2486f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2487f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2488f0b11de2SDouglas Gregor     HadError = true;
2489f0b11de2SDouglas Gregor     return;
2490f0b11de2SDouglas Gregor   }
2491f0b11de2SDouglas Gregor 
2492f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2493f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2494f0b11de2SDouglas Gregor     consumeToken();
2495f0b11de2SDouglas Gregor     return;
2496f0b11de2SDouglas Gregor   }
2497f0b11de2SDouglas Gregor 
2498f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2499f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2500f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2501f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2502f0b11de2SDouglas Gregor     } else {
2503f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2504f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2505f0b11de2SDouglas Gregor         << Tok.getString();
2506f0b11de2SDouglas Gregor     }
2507f0b11de2SDouglas Gregor   }
2508f0b11de2SDouglas Gregor 
2509f0b11de2SDouglas Gregor   ActiveModule->ExportAsModule = Tok.getString();
2510a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2511a3b5f71eSBruno Cardoso Lopes 
2512f0b11de2SDouglas Gregor   consumeToken();
2513f0b11de2SDouglas Gregor }
2514f0b11de2SDouglas Gregor 
25159fc8faf9SAdrian Prantl /// Parse a module use declaration.
2516ba7f2f71SDaniel Jasper ///
25178f4d3ff1SRichard Smith ///   use-declaration:
25188f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2519ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2520ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25218f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2522ba7f2f71SDaniel Jasper   // Parse the module-id.
2523ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25243cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2525ba7f2f71SDaniel Jasper 
25268f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25278f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25288f4d3ff1SRichard Smith   else
2529ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2530ba7f2f71SDaniel Jasper }
2531ba7f2f71SDaniel Jasper 
25329fc8faf9SAdrian Prantl /// Parse a link declaration.
25336ddfca91SDouglas Gregor ///
25346ddfca91SDouglas Gregor ///   module-declaration:
25356ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25366ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25376ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25386ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25396ddfca91SDouglas Gregor 
25406ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25416ddfca91SDouglas Gregor   bool IsFramework = false;
25426ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25436ddfca91SDouglas Gregor     consumeToken();
25446ddfca91SDouglas Gregor     IsFramework = true;
25456ddfca91SDouglas Gregor   }
25466ddfca91SDouglas Gregor 
25476ddfca91SDouglas Gregor   // Parse the library name
25486ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25496ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25506ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25516ddfca91SDouglas Gregor     HadError = true;
25526ddfca91SDouglas Gregor     return;
25536ddfca91SDouglas Gregor   }
25546ddfca91SDouglas Gregor 
25556ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
25566ddfca91SDouglas Gregor   consumeToken();
25576ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
25586ddfca91SDouglas Gregor                                                             IsFramework));
25596ddfca91SDouglas Gregor }
25606ddfca91SDouglas Gregor 
25619fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
256235b13eceSDouglas Gregor ///
256335b13eceSDouglas Gregor ///   module-declaration:
256435b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
256535b13eceSDouglas Gregor ///
256635b13eceSDouglas Gregor ///   config-macro-list:
256735b13eceSDouglas Gregor ///     identifier (',' identifier)?
256835b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
256935b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
257035b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
257135b13eceSDouglas Gregor 
257235b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
257335b13eceSDouglas Gregor   if (ActiveModule->Parent) {
257435b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
257535b13eceSDouglas Gregor   }
257635b13eceSDouglas Gregor 
257735b13eceSDouglas Gregor   // Parse the optional attributes.
257835b13eceSDouglas Gregor   Attributes Attrs;
25795d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
25805d29dee0SDavide Italiano     return;
25815d29dee0SDavide Italiano 
258235b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
258335b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
258435b13eceSDouglas Gregor   }
258535b13eceSDouglas Gregor 
258635b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2587306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
258835b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
258935b13eceSDouglas Gregor     return;
259035b13eceSDouglas Gregor 
259135b13eceSDouglas Gregor   // Consume the first identifier.
259235b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
259335b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
259435b13eceSDouglas Gregor   }
259535b13eceSDouglas Gregor   consumeToken();
259635b13eceSDouglas Gregor 
259735b13eceSDouglas Gregor   do {
259835b13eceSDouglas Gregor     // If there's a comma, consume it.
259935b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
260035b13eceSDouglas Gregor       break;
260135b13eceSDouglas Gregor     consumeToken();
260235b13eceSDouglas Gregor 
260335b13eceSDouglas Gregor     // We expect to see a macro name here.
2604306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
260535b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
260635b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
260735b13eceSDouglas Gregor       break;
260835b13eceSDouglas Gregor     }
260935b13eceSDouglas Gregor 
261035b13eceSDouglas Gregor     // Consume the macro name.
261135b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
261235b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
261335b13eceSDouglas Gregor     }
261435b13eceSDouglas Gregor     consumeToken();
261535b13eceSDouglas Gregor   } while (true);
261635b13eceSDouglas Gregor }
261735b13eceSDouglas Gregor 
26189fc8faf9SAdrian Prantl /// Format a module-id into a string.
2619fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2620fb912657SDouglas Gregor   std::string result;
2621fb912657SDouglas Gregor   {
2622fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2623fb912657SDouglas Gregor 
2624fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2625fb912657SDouglas Gregor       if (I)
2626fb912657SDouglas Gregor         OS << ".";
2627fb912657SDouglas Gregor       OS << Id[I].first;
2628fb912657SDouglas Gregor     }
2629fb912657SDouglas Gregor   }
2630fb912657SDouglas Gregor 
2631fb912657SDouglas Gregor   return result;
2632fb912657SDouglas Gregor }
2633fb912657SDouglas Gregor 
26349fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2635fb912657SDouglas Gregor ///
2636fb912657SDouglas Gregor ///   module-declaration:
2637fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2638fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2639fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2640fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2641fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2642fb912657SDouglas Gregor 
2643fb912657SDouglas Gregor   // Parse the module-id.
2644fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2645fb912657SDouglas Gregor     return;
2646fb912657SDouglas Gregor 
2647fb912657SDouglas Gregor   // Parse the ','.
2648fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2649fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2650fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2651fb912657SDouglas Gregor     return;
2652fb912657SDouglas Gregor   }
2653fb912657SDouglas Gregor   consumeToken();
2654fb912657SDouglas Gregor 
2655fb912657SDouglas Gregor   // Parse the message.
2656fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2657fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2658fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2659fb912657SDouglas Gregor     return;
2660fb912657SDouglas Gregor   }
2661fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2662fb912657SDouglas Gregor   consumeToken();
2663fb912657SDouglas Gregor 
2664fb912657SDouglas Gregor   // Add this unresolved conflict.
2665fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2666fb912657SDouglas Gregor }
2667fb912657SDouglas Gregor 
26689fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
26699194a91dSDouglas Gregor ///
26709194a91dSDouglas Gregor ///   module-declaration:
26719194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
26729194a91dSDouglas Gregor ///       { inferred-module-member* }
26739194a91dSDouglas Gregor ///
26749194a91dSDouglas Gregor ///   inferred-module-member:
26759194a91dSDouglas Gregor ///     'export' '*'
26769194a91dSDouglas Gregor ///     'exclude' identifier
26779194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
267873441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
267973441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
268073441091SDouglas Gregor   bool Failed = false;
268173441091SDouglas Gregor 
268273441091SDouglas Gregor   // Inferred modules must be submodules.
26839194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
268473441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
268573441091SDouglas Gregor     Failed = true;
268673441091SDouglas Gregor   }
268773441091SDouglas Gregor 
26889194a91dSDouglas Gregor   if (ActiveModule) {
2689524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
26904898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
26914898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
269273441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
269373441091SDouglas Gregor       Failed = true;
269473441091SDouglas Gregor     }
269573441091SDouglas Gregor 
269673441091SDouglas Gregor     // Check for redefinition of an inferred module.
2697dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
269873441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2699dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2700dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
270173441091SDouglas Gregor                      diag::note_mmap_prev_definition);
270273441091SDouglas Gregor       Failed = true;
270373441091SDouglas Gregor     }
270473441091SDouglas Gregor 
27059194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27069194a91dSDouglas Gregor     if (Framework) {
27079194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27089194a91dSDouglas Gregor       Framework = false;
27099194a91dSDouglas Gregor     }
27109194a91dSDouglas Gregor   } else if (Explicit) {
27119194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27129194a91dSDouglas Gregor     Explicit = false;
27139194a91dSDouglas Gregor   }
27149194a91dSDouglas Gregor 
271573441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
271673441091SDouglas Gregor   if (Failed) {
271773441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
271873441091SDouglas Gregor       consumeToken();
271973441091SDouglas Gregor       skipUntil(MMToken::RBrace);
272073441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
272173441091SDouglas Gregor         consumeToken();
272273441091SDouglas Gregor     }
272373441091SDouglas Gregor     HadError = true;
272473441091SDouglas Gregor     return;
272573441091SDouglas Gregor   }
272673441091SDouglas Gregor 
27279194a91dSDouglas Gregor   // Parse optional attributes.
27284442605fSBill Wendling   Attributes Attrs;
27295d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27305d29dee0SDavide Italiano     return;
27319194a91dSDouglas Gregor 
27329194a91dSDouglas Gregor   if (ActiveModule) {
273373441091SDouglas Gregor     // Note that we have an inferred submodule.
2734dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2735dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2736dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27379194a91dSDouglas Gregor   } else {
27389194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27399194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2740c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2741beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2742131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27439194a91dSDouglas Gregor   }
274473441091SDouglas Gregor 
274573441091SDouglas Gregor   // Parse the opening brace.
274673441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
274773441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
274873441091SDouglas Gregor     HadError = true;
274973441091SDouglas Gregor     return;
275073441091SDouglas Gregor   }
275173441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
275273441091SDouglas Gregor 
275373441091SDouglas Gregor   // Parse the body of the inferred submodule.
275473441091SDouglas Gregor   bool Done = false;
275573441091SDouglas Gregor   do {
275673441091SDouglas Gregor     switch (Tok.Kind) {
275773441091SDouglas Gregor     case MMToken::EndOfFile:
275873441091SDouglas Gregor     case MMToken::RBrace:
275973441091SDouglas Gregor       Done = true;
276073441091SDouglas Gregor       break;
276173441091SDouglas Gregor 
2762afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
27639194a91dSDouglas Gregor       if (ActiveModule) {
27649194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2765d2d442caSCraig Topper           << (ActiveModule != nullptr);
27669194a91dSDouglas Gregor         consumeToken();
27679194a91dSDouglas Gregor         break;
27689194a91dSDouglas Gregor       }
27699194a91dSDouglas Gregor 
27709194a91dSDouglas Gregor       consumeToken();
2771306d8920SRichard Smith       // FIXME: Support string-literal module names here.
27729194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
27739194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
27749194a91dSDouglas Gregor         break;
27759194a91dSDouglas Gregor       }
27769194a91dSDouglas Gregor 
27779194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
27789194a91dSDouglas Gregor         .push_back(Tok.getString());
27799194a91dSDouglas Gregor       consumeToken();
27809194a91dSDouglas Gregor       break;
27819194a91dSDouglas Gregor 
27829194a91dSDouglas Gregor     case MMToken::ExportKeyword:
27839194a91dSDouglas Gregor       if (!ActiveModule) {
27849194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2785d2d442caSCraig Topper           << (ActiveModule != nullptr);
27869194a91dSDouglas Gregor         consumeToken();
27879194a91dSDouglas Gregor         break;
27889194a91dSDouglas Gregor       }
27899194a91dSDouglas Gregor 
279073441091SDouglas Gregor       consumeToken();
279173441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2792dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
279373441091SDouglas Gregor       else
279473441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
279573441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
279673441091SDouglas Gregor       consumeToken();
279773441091SDouglas Gregor       break;
279873441091SDouglas Gregor 
279973441091SDouglas Gregor     case MMToken::ExplicitKeyword:
280073441091SDouglas Gregor     case MMToken::ModuleKeyword:
280173441091SDouglas Gregor     case MMToken::HeaderKeyword:
2802b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
280373441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
280473441091SDouglas Gregor     default:
28059194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2806d2d442caSCraig Topper           << (ActiveModule != nullptr);
280773441091SDouglas Gregor       consumeToken();
280873441091SDouglas Gregor       break;
280973441091SDouglas Gregor     }
281073441091SDouglas Gregor   } while (!Done);
281173441091SDouglas Gregor 
281273441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
281373441091SDouglas Gregor     consumeToken();
281473441091SDouglas Gregor   else {
281573441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
281673441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
281773441091SDouglas Gregor     HadError = true;
281873441091SDouglas Gregor   }
281973441091SDouglas Gregor }
282073441091SDouglas Gregor 
28219fc8faf9SAdrian Prantl /// Parse optional attributes.
28229194a91dSDouglas Gregor ///
28239194a91dSDouglas Gregor ///   attributes:
28249194a91dSDouglas Gregor ///     attribute attributes
28259194a91dSDouglas Gregor ///     attribute
28269194a91dSDouglas Gregor ///
28279194a91dSDouglas Gregor ///   attribute:
28289194a91dSDouglas Gregor ///     [ identifier ]
28299194a91dSDouglas Gregor ///
28309194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28319194a91dSDouglas Gregor ///
28329194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28334442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28349194a91dSDouglas Gregor   bool HadError = false;
28359194a91dSDouglas Gregor 
28369194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28379194a91dSDouglas Gregor     // Consume the '['.
28389194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28399194a91dSDouglas Gregor 
28409194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28419194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28429194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28439194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28449194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28459194a91dSDouglas Gregor         consumeToken();
28469194a91dSDouglas Gregor       HadError = true;
28479194a91dSDouglas Gregor     }
28489194a91dSDouglas Gregor 
28499194a91dSDouglas Gregor     // Decode the attribute name.
28509194a91dSDouglas Gregor     AttributeKind Attribute
28519194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
285235b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
285377944868SRichard Smith           .Case("extern_c", AT_extern_c)
2854ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28559194a91dSDouglas Gregor           .Case("system", AT_system)
28569194a91dSDouglas Gregor           .Default(AT_unknown);
28579194a91dSDouglas Gregor     switch (Attribute) {
28589194a91dSDouglas Gregor     case AT_unknown:
28599194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
28609194a91dSDouglas Gregor         << Tok.getString();
28619194a91dSDouglas Gregor       break;
28629194a91dSDouglas Gregor 
28639194a91dSDouglas Gregor     case AT_system:
28649194a91dSDouglas Gregor       Attrs.IsSystem = true;
28659194a91dSDouglas Gregor       break;
286635b13eceSDouglas Gregor 
286777944868SRichard Smith     case AT_extern_c:
286877944868SRichard Smith       Attrs.IsExternC = true;
286977944868SRichard Smith       break;
287077944868SRichard Smith 
287135b13eceSDouglas Gregor     case AT_exhaustive:
287235b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
287335b13eceSDouglas Gregor       break;
2874ed84df00SBruno Cardoso Lopes 
2875ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2876ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2877ed84df00SBruno Cardoso Lopes       break;
28789194a91dSDouglas Gregor     }
28799194a91dSDouglas Gregor     consumeToken();
28809194a91dSDouglas Gregor 
28819194a91dSDouglas Gregor     // Consume the ']'.
28829194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
28839194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
28849194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
28859194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28869194a91dSDouglas Gregor       HadError = true;
28879194a91dSDouglas Gregor     }
28889194a91dSDouglas Gregor 
28899194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
28909194a91dSDouglas Gregor       consumeToken();
28919194a91dSDouglas Gregor   }
28929194a91dSDouglas Gregor 
28939194a91dSDouglas Gregor   return HadError;
28949194a91dSDouglas Gregor }
28959194a91dSDouglas Gregor 
28969fc8faf9SAdrian Prantl /// Parse a module map file.
2897718292f2SDouglas Gregor ///
2898718292f2SDouglas Gregor ///   module-map-file:
2899718292f2SDouglas Gregor ///     module-declaration*
2900718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2901718292f2SDouglas Gregor   do {
2902718292f2SDouglas Gregor     switch (Tok.Kind) {
2903718292f2SDouglas Gregor     case MMToken::EndOfFile:
2904718292f2SDouglas Gregor       return HadError;
2905718292f2SDouglas Gregor 
2906e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
290797292843SDaniel Jasper     case MMToken::ExternKeyword:
2908718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2909755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2910718292f2SDouglas Gregor       parseModuleDecl();
2911718292f2SDouglas Gregor       break;
2912718292f2SDouglas Gregor 
29131fb5c3a6SDouglas Gregor     case MMToken::Comma:
291435b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2915fb912657SDouglas Gregor     case MMToken::Conflict:
2916a3feee2aSRichard Smith     case MMToken::Exclaim:
291759527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29182b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2919f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2920718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2921718292f2SDouglas Gregor     case MMToken::Identifier:
2922718292f2SDouglas Gregor     case MMToken::LBrace:
29236ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2924a686e1b0SDouglas Gregor     case MMToken::LSquare:
29252b82c2a5SDouglas Gregor     case MMToken::Period:
2926b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2927718292f2SDouglas Gregor     case MMToken::RBrace:
2928a686e1b0SDouglas Gregor     case MMToken::RSquare:
29291fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29302b82c2a5SDouglas Gregor     case MMToken::Star:
2931718292f2SDouglas Gregor     case MMToken::StringLiteral:
2932040e1266SRichard Smith     case MMToken::IntegerLiteral:
2933b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2934718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2935ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2936718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2937718292f2SDouglas Gregor       HadError = true;
2938718292f2SDouglas Gregor       consumeToken();
2939718292f2SDouglas Gregor       break;
2940718292f2SDouglas Gregor     }
2941718292f2SDouglas Gregor   } while (true);
2942718292f2SDouglas Gregor }
2943718292f2SDouglas Gregor 
29449acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2945c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29468128f332SRichard Smith                                    unsigned *Offset,
2947ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29488128f332SRichard Smith   assert(Target && "Missing target information");
29494ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29504ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29514ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29524ddf2221SDouglas Gregor     return Known->second;
29534ddf2221SDouglas Gregor 
29548128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
29558128f332SRichard Smith   if (ID.isInvalid()) {
2956f3f84616SRichard Smith     auto FileCharacter =
2957f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
29588128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
29598128f332SRichard Smith   }
29608128f332SRichard Smith 
29618128f332SRichard Smith   assert(Target && "Missing target information");
29621f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2963718292f2SDouglas Gregor   if (!Buffer)
29644ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
29658128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
29668128f332SRichard Smith          "invalid buffer offset");
2967718292f2SDouglas Gregor 
2968718292f2SDouglas Gregor   // Parse this module map file.
29698128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
29708128f332SRichard Smith           Buffer->getBufferStart(),
29718128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
29728128f332SRichard Smith           Buffer->getBufferEnd());
29732a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2974beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2975c192d194SBruno Cardoso Lopes                          IsSystem);
2976718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
29774ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
29782a6edb30SRichard Smith 
29798128f332SRichard Smith   if (Offset) {
29808128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
29818128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
29828128f332SRichard Smith     *Offset = Loc.second;
29838128f332SRichard Smith   }
29848128f332SRichard Smith 
29852a6edb30SRichard Smith   // Notify callbacks that we parsed it.
29862a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
29872a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
29888587dfd9SBruno Cardoso Lopes 
2989718292f2SDouglas Gregor   return Result;
2990718292f2SDouglas Gregor }
2991