1afd1b1c9SEugene Zelenko //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2718292f2SDouglas Gregor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6718292f2SDouglas Gregor //
7718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
8718292f2SDouglas Gregor //
9718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
10718292f2SDouglas Gregor // of a module as it relates to headers.
11718292f2SDouglas Gregor //
12718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
13afd1b1c9SEugene Zelenko 
14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15a7d03840SJordan Rose #include "clang/Basic/CharInfo.h"
16718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
17718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
18afd1b1c9SEugene Zelenko #include "clang/Basic/LLVM.h"
19afd1b1c9SEugene Zelenko #include "clang/Basic/LangOptions.h"
20afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h"
21afd1b1c9SEugene Zelenko #include "clang/Basic/SourceLocation.h"
22afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h"
23718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
24b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
259acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
263a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
273a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
283a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
29afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h"
30afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
31afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h"
32afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h"
33afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
34afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h"
35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
36afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h"
373a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
383a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
39718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
40afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h"
41afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
42afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
43552c169eSRafael Espindola #include "llvm/Support/Path.h"
44fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h"
45718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
46afd1b1c9SEugene Zelenko #include <algorithm>
47afd1b1c9SEugene Zelenko #include <cassert>
48afd1b1c9SEugene Zelenko #include <cstdint>
49afd1b1c9SEugene Zelenko #include <cstring>
50afd1b1c9SEugene Zelenko #include <string>
51afd1b1c9SEugene Zelenko #include <system_error>
52afd1b1c9SEugene Zelenko #include <utility>
53afd1b1c9SEugene Zelenko 
54718292f2SDouglas Gregor using namespace clang;
55718292f2SDouglas Gregor 
56b3e902f4SRichard Trieu void ModuleMapCallbacks::anchor() {}
57b3e902f4SRichard Trieu 
58a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
59a3b5f71eSBruno Cardoso Lopes   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
60a3b5f71eSBruno Cardoso Lopes   if (PendingLinkAs != PendingLinkAsModule.end()) {
61a3b5f71eSBruno Cardoso Lopes     for (auto &Name : PendingLinkAs->second) {
62a3b5f71eSBruno Cardoso Lopes       auto *M = findModule(Name.getKey());
63a3b5f71eSBruno Cardoso Lopes       if (M)
64a3b5f71eSBruno Cardoso Lopes         M->UseExportAsModuleLinkName = true;
65a3b5f71eSBruno Cardoso Lopes     }
66a3b5f71eSBruno Cardoso Lopes   }
67a3b5f71eSBruno Cardoso Lopes }
68a3b5f71eSBruno Cardoso Lopes 
69a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) {
70a3b5f71eSBruno Cardoso Lopes   if (findModule(Mod->ExportAsModule))
71a3b5f71eSBruno Cardoso Lopes     Mod->UseExportAsModuleLinkName = true;
72a3b5f71eSBruno Cardoso Lopes   else
73a3b5f71eSBruno Cardoso Lopes     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
74a3b5f71eSBruno Cardoso Lopes }
75a3b5f71eSBruno Cardoso Lopes 
76040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
77040e1266SRichard Smith   switch ((int)Role) {
78040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
79040e1266SRichard Smith   case NormalHeader:
80040e1266SRichard Smith     return Module::HK_Normal;
81040e1266SRichard Smith   case PrivateHeader:
82040e1266SRichard Smith     return Module::HK_Private;
83040e1266SRichard Smith   case TextualHeader:
84040e1266SRichard Smith     return Module::HK_Textual;
85040e1266SRichard Smith   case PrivateHeader | TextualHeader:
86040e1266SRichard Smith     return Module::HK_PrivateTextual;
87040e1266SRichard Smith   }
88040e1266SRichard Smith }
89040e1266SRichard Smith 
90040e1266SRichard Smith ModuleMap::ModuleHeaderRole
91040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
92040e1266SRichard Smith   switch ((int)Kind) {
93040e1266SRichard Smith   case Module::HK_Normal:
94040e1266SRichard Smith     return NormalHeader;
95040e1266SRichard Smith   case Module::HK_Private:
96040e1266SRichard Smith     return PrivateHeader;
97040e1266SRichard Smith   case Module::HK_Textual:
98040e1266SRichard Smith     return TextualHeader;
99040e1266SRichard Smith   case Module::HK_PrivateTextual:
100040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
101040e1266SRichard Smith   case Module::HK_Excluded:
102040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
103040e1266SRichard Smith   }
104040e1266SRichard Smith   llvm_unreachable("unknown header kind");
105040e1266SRichard Smith }
106040e1266SRichard Smith 
1072b82c2a5SDouglas Gregor Module::ExportDecl
1082b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
1092b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
110e4412640SArgyrios Kyrtzidis                          bool Complain) const {
111f5eedd05SDouglas Gregor   // We may have just a wildcard.
112f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
113f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
114d2d442caSCraig Topper     return Module::ExportDecl(nullptr, true);
115f5eedd05SDouglas Gregor   }
116f5eedd05SDouglas Gregor 
117fb912657SDouglas Gregor   // Resolve the module-id.
118fb912657SDouglas Gregor   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
119fb912657SDouglas Gregor   if (!Context)
120afd1b1c9SEugene Zelenko     return {};
121fb912657SDouglas Gregor 
122fb912657SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
123fb912657SDouglas Gregor }
124fb912657SDouglas Gregor 
125fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
126fb912657SDouglas Gregor                                    bool Complain) const {
1272b82c2a5SDouglas Gregor   // Find the starting module.
128fb912657SDouglas Gregor   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1292b82c2a5SDouglas Gregor   if (!Context) {
1302b82c2a5SDouglas Gregor     if (Complain)
1310761a8a0SDaniel Jasper       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
132fb912657SDouglas Gregor       << Id[0].first << Mod->getFullModuleName();
1332b82c2a5SDouglas Gregor 
134d2d442caSCraig Topper     return nullptr;
1352b82c2a5SDouglas Gregor   }
1362b82c2a5SDouglas Gregor 
1372b82c2a5SDouglas Gregor   // Dig into the module path.
138fb912657SDouglas Gregor   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
139fb912657SDouglas Gregor     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1402b82c2a5SDouglas Gregor     if (!Sub) {
1412b82c2a5SDouglas Gregor       if (Complain)
1420761a8a0SDaniel Jasper         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
143fb912657SDouglas Gregor         << Id[I].first << Context->getFullModuleName()
144fb912657SDouglas Gregor         << SourceRange(Id[0].second, Id[I-1].second);
1452b82c2a5SDouglas Gregor 
146d2d442caSCraig Topper       return nullptr;
1472b82c2a5SDouglas Gregor     }
1482b82c2a5SDouglas Gregor 
1492b82c2a5SDouglas Gregor     Context = Sub;
1502b82c2a5SDouglas Gregor   }
1512b82c2a5SDouglas Gregor 
152fb912657SDouglas Gregor   return Context;
1532b82c2a5SDouglas Gregor }
1542b82c2a5SDouglas Gregor 
1559fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the
1561d60987fSRichard Smith /// subframework in which the given module lives.
1571d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1581d60987fSRichard Smith                                     SmallVectorImpl<char> &Path) {
1591d60987fSRichard Smith   // Collect the framework names from the given module to the top-level module.
1601d60987fSRichard Smith   SmallVector<StringRef, 2> Paths;
1611d60987fSRichard Smith   for (; Mod; Mod = Mod->Parent) {
1621d60987fSRichard Smith     if (Mod->IsFramework)
1631d60987fSRichard Smith       Paths.push_back(Mod->Name);
1641d60987fSRichard Smith   }
1651d60987fSRichard Smith 
1661d60987fSRichard Smith   if (Paths.empty())
1671d60987fSRichard Smith     return;
1681d60987fSRichard Smith 
1691d60987fSRichard Smith   // Add Frameworks/Name.framework for each subframework.
1701d60987fSRichard Smith   for (unsigned I = Paths.size() - 1; I != 0; --I)
1711d60987fSRichard Smith     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1721d60987fSRichard Smith }
1731d60987fSRichard Smith 
1749f6020bcSBruno Cardoso Lopes const FileEntry *ModuleMap::findHeader(
1759f6020bcSBruno Cardoso Lopes     Module *M, const Module::UnresolvedHeaderDirective &Header,
1769f6020bcSBruno Cardoso Lopes     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1779f6020bcSBruno Cardoso Lopes   // Search for the header file within the module's home directory.
1789f6020bcSBruno Cardoso Lopes   auto *Directory = M->Directory;
1799f6020bcSBruno Cardoso Lopes   SmallString<128> FullPathName(Directory->getName());
1809f6020bcSBruno Cardoso Lopes 
181040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
182040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
183040e1266SRichard Smith     if (!File ||
184040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
185040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186040e1266SRichard Smith       return nullptr;
187040e1266SRichard Smith     return File;
188040e1266SRichard Smith   };
189040e1266SRichard Smith 
1909f6020bcSBruno Cardoso Lopes   auto GetFrameworkFile = [&]() -> const FileEntry * {
1911d60987fSRichard Smith     unsigned FullPathLength = FullPathName.size();
1921d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1931d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
1941d60987fSRichard Smith 
1951d60987fSRichard Smith     // Check whether this file is in the public headers.
1961d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1971d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
198040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
1991d60987fSRichard Smith       return File;
2001d60987fSRichard Smith 
2011d60987fSRichard Smith     // Check whether this file is in the private headers.
2021d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
2031d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
2041d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2051d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
2061d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
2071d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
2081d60987fSRichard Smith       RelativePathName.clear();
2091d60987fSRichard Smith     else
2101d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
2111d60987fSRichard Smith     FullPathName.resize(FullPathLength);
2121d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2131d60987fSRichard Smith                             Header.FileName);
2141d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
215040e1266SRichard Smith     return GetFile(FullPathName);
2169f6020bcSBruno Cardoso Lopes   };
2179f6020bcSBruno Cardoso Lopes 
2189f6020bcSBruno Cardoso Lopes   if (llvm::sys::path::is_absolute(Header.FileName)) {
2199f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
2209f6020bcSBruno Cardoso Lopes     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2219f6020bcSBruno Cardoso Lopes     return GetFile(Header.FileName);
2221d60987fSRichard Smith   }
2231d60987fSRichard Smith 
2249f6020bcSBruno Cardoso Lopes   if (M->isPartOfFramework())
2259f6020bcSBruno Cardoso Lopes     return GetFrameworkFile();
2269f6020bcSBruno Cardoso Lopes 
2271d60987fSRichard Smith   // Lookup for normal headers.
2281d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
2291d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
2309f6020bcSBruno Cardoso Lopes   auto *NormalHdrFile = GetFile(FullPathName);
2319f6020bcSBruno Cardoso Lopes 
2329f6020bcSBruno Cardoso Lopes   if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
2339f6020bcSBruno Cardoso Lopes     // The lack of 'framework' keyword in a module declaration it's a simple
2349f6020bcSBruno Cardoso Lopes     // mistake we can diagnose when the header exists within the proper
2359f6020bcSBruno Cardoso Lopes     // framework style path.
2369f6020bcSBruno Cardoso Lopes     FullPathName.assign(Directory->getName());
2379f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
238d101b5d7SErich Keane     if (GetFrameworkFile()) {
2399f6020bcSBruno Cardoso Lopes       Diags.Report(Header.FileNameLoc,
2409f6020bcSBruno Cardoso Lopes                    diag::warn_mmap_incomplete_framework_module_declaration)
2419f6020bcSBruno Cardoso Lopes           << Header.FileName << M->getFullModuleName();
2429f6020bcSBruno Cardoso Lopes       NeedsFramework = true;
2439f6020bcSBruno Cardoso Lopes     }
2449f6020bcSBruno Cardoso Lopes     return nullptr;
2459f6020bcSBruno Cardoso Lopes   }
2469f6020bcSBruno Cardoso Lopes 
2479f6020bcSBruno Cardoso Lopes   return NormalHdrFile;
2481d60987fSRichard Smith }
2491d60987fSRichard Smith 
250040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
2519f6020bcSBruno Cardoso Lopes                               const Module::UnresolvedHeaderDirective &Header,
2529f6020bcSBruno Cardoso Lopes                               bool &NeedsFramework) {
253040e1266SRichard Smith   SmallString<128> RelativePathName;
2549f6020bcSBruno Cardoso Lopes   if (const FileEntry *File =
2559f6020bcSBruno Cardoso Lopes           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
256040e1266SRichard Smith     if (Header.IsUmbrella) {
257040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
258040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
259040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
260040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
261040e1266SRichard Smith       else
262040e1266SRichard Smith         // Record this umbrella header.
263040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
264040e1266SRichard Smith     } else {
265040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
266040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
267040e1266SRichard Smith         excludeHeader(Mod, H);
268040e1266SRichard Smith       else
269040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
270040e1266SRichard Smith     }
271040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
272040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
273040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
274040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
275040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
276040e1266SRichard Smith   } else {
277040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
278040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
279040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
280040e1266SRichard Smith     // A missing header with stat information doesn't make the module
281040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
282040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
283040e1266SRichard Smith     // preprocessed source.)
284040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
285040e1266SRichard Smith       Mod->markUnavailable();
286040e1266SRichard Smith   }
287040e1266SRichard Smith }
288040e1266SRichard Smith 
289040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
290040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
291040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
292040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
293040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
294040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
295040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
296040e1266SRichard Smith     return false;
2971d60987fSRichard Smith 
2981d60987fSRichard Smith   // This is a system module with a top-level header. This header
2991d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
3001d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
301040e1266SRichard Smith   SmallString<128> Path;
302040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
303040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
304040e1266SRichard Smith   if (!File)
305040e1266SRichard Smith     return false;
306040e1266SRichard Smith 
307040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
308040e1266SRichard Smith   Module::Header H = {Path.str(), File};
309040e1266SRichard Smith   addHeader(Mod, H, Role);
310040e1266SRichard Smith   return true;
3111d60987fSRichard Smith }
3121d60987fSRichard Smith 
3130761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
314b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
315b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
3160761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
317056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
3180414b857SRichard Smith   MMapLangOpts.LineComment = true;
3190414b857SRichard Smith }
320718292f2SDouglas Gregor 
321718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
32221668754SDavide Italiano   for (auto &M : Modules)
32321668754SDavide Italiano     delete M.getValue();
3248587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
3258587dfd9SBruno Cardoso Lopes     delete M;
326718292f2SDouglas Gregor }
327718292f2SDouglas Gregor 
32889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
32989929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
33089929282SDouglas Gregor          "Improper target override");
33189929282SDouglas Gregor   this->Target = &Target;
33289929282SDouglas Gregor }
33389929282SDouglas Gregor 
3349fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier.
335056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
336056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
337056396aeSDouglas Gregor   if (Name.empty())
338056396aeSDouglas Gregor     return Name;
339056396aeSDouglas Gregor 
340a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
341056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
342056396aeSDouglas Gregor     // create a buffer with the sanitized name.
343056396aeSDouglas Gregor     Buffer.clear();
344a7d03840SJordan Rose     if (isDigit(Name[0]))
345056396aeSDouglas Gregor       Buffer.push_back('_');
346056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
347056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
348a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
349056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
350056396aeSDouglas Gregor       else
351056396aeSDouglas Gregor         Buffer.push_back('_');
352056396aeSDouglas Gregor     }
353056396aeSDouglas Gregor 
354056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
355056396aeSDouglas Gregor   }
356056396aeSDouglas Gregor 
357056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
358056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
359056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
360056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
361056396aeSDouglas Gregor            .Default(false)) {
362056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
363056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
364056396aeSDouglas Gregor     Buffer.push_back('_');
365056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
366056396aeSDouglas Gregor   }
367056396aeSDouglas Gregor 
368056396aeSDouglas Gregor   return Name;
369056396aeSDouglas Gregor }
370056396aeSDouglas Gregor 
3719fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin
37234d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
37334d52749SDouglas Gregor /// headers.
374ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37534d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
37634d52749SDouglas Gregor            .Case("float.h", true)
37734d52749SDouglas Gregor            .Case("iso646.h", true)
37834d52749SDouglas Gregor            .Case("limits.h", true)
37934d52749SDouglas Gregor            .Case("stdalign.h", true)
38034d52749SDouglas Gregor            .Case("stdarg.h", true)
3813c4b1290SBen Langmuir            .Case("stdatomic.h", true)
38234d52749SDouglas Gregor            .Case("stdbool.h", true)
38334d52749SDouglas Gregor            .Case("stddef.h", true)
38434d52749SDouglas Gregor            .Case("stdint.h", true)
38534d52749SDouglas Gregor            .Case("tgmath.h", true)
38634d52749SDouglas Gregor            .Case("unwind.h", true)
38734d52749SDouglas Gregor            .Default(false);
38834d52749SDouglas Gregor }
38934d52749SDouglas Gregor 
39092669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
39192669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
392040e1266SRichard Smith   resolveHeaderDirectives(File);
39359527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
39447972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
39547972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
396ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3974eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
39892669ee4SDaniel Jasper     return Headers.find(File);
3994eaf0a6cSDaniel Jasper   }
40092669ee4SDaniel Jasper   return Known;
40192669ee4SDaniel Jasper }
40292669ee4SDaniel Jasper 
4034469138eSBen Langmuir ModuleMap::KnownHeader
4044469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4054469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
40647972afdSRichard Smith   if (UmbrellaDirs.empty())
407afd1b1c9SEugene Zelenko     return {};
40847972afdSRichard Smith 
4094469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
4104469138eSBen Langmuir   assert(Dir && "file in no directory");
4114469138eSBen Langmuir 
4124469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
4134469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
4144469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
4154469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
4164469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4174469138eSBen Langmuir 
4184469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
4194469138eSBen Langmuir   // an umbrella header.
4204469138eSBen Langmuir   do {
4214469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4224469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4234469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4244469138eSBen Langmuir 
4254469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4264469138eSBen Langmuir 
4274469138eSBen Langmuir     // Retrieve our parent path.
4284469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4294469138eSBen Langmuir     if (DirName.empty())
4304469138eSBen Langmuir       break;
4314469138eSBen Langmuir 
4324469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4334469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
4344469138eSBen Langmuir   } while (Dir);
435afd1b1c9SEugene Zelenko   return {};
4364469138eSBen Langmuir }
4374469138eSBen Langmuir 
43892669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
43992669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4404eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44192669ee4SDaniel Jasper #ifndef NDEBUG
4424eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
44392669ee4SDaniel Jasper     // Check for consistency between the module header role
44492669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
44592669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4462708e520SRichard Smith     bool IsPrivate = false;
4472708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4484eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4494eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4502708e520SRichard Smith     for (auto *Hs : HeaderList)
4512708e520SRichard Smith       IsPrivate |=
4522708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4533c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4542708e520SRichard Smith           }) != Hs->end();
4554eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
45600bc95ecSRichard Smith   }
45792669ee4SDaniel Jasper #endif
4584eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
45992669ee4SDaniel Jasper }
46092669ee4SDaniel Jasper 
46171e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46271e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
46371e1a64fSBen Langmuir }
46471e1a64fSBen Langmuir 
46592669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4668d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
46792669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
46892669ee4SDaniel Jasper                                         StringRef Filename,
46992669ee4SDaniel Jasper                                         const FileEntry *File) {
47092669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47192669ee4SDaniel Jasper   // with no source files.
47271e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47392669ee4SDaniel Jasper     return;
47492669ee4SDaniel Jasper 
475040e1266SRichard Smith   if (RequestingModule) {
47692669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
477040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
478040e1266SRichard Smith   }
47992669ee4SDaniel Jasper 
48071e1a64fSBen Langmuir   bool Excluded = false;
481d2d442caSCraig Topper   Module *Private = nullptr;
482d2d442caSCraig Topper   Module *NotUsed = nullptr;
48371e1a64fSBen Langmuir 
48471e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
48571e1a64fSBen Langmuir   if (Known != Headers.end()) {
48671e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
48792669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4884eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
48971e1a64fSBen Langmuir         Private = Header.getModule();
49092669ee4SDaniel Jasper         continue;
49192669ee4SDaniel Jasper       }
49292669ee4SDaniel Jasper 
49392669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
49492669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
49592669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4968f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
49771e1a64fSBen Langmuir         NotUsed = Header.getModule();
49892669ee4SDaniel Jasper         continue;
49992669ee4SDaniel Jasper       }
50092669ee4SDaniel Jasper 
50192669ee4SDaniel Jasper       // We have found a module that we can happily use.
50292669ee4SDaniel Jasper       return;
50392669ee4SDaniel Jasper     }
504feb54b6dSRichard Smith 
505feb54b6dSRichard Smith     Excluded = true;
50671e1a64fSBen Langmuir   }
50792669ee4SDaniel Jasper 
50892669ee4SDaniel Jasper   // We have found a header, but it is private.
509d2d442caSCraig Topper   if (Private) {
51011152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51192669ee4SDaniel Jasper         << Filename;
51292669ee4SDaniel Jasper     return;
51392669ee4SDaniel Jasper   }
51492669ee4SDaniel Jasper 
51592669ee4SDaniel Jasper   // We have found a module, but we don't use it.
516d2d442caSCraig Topper   if (NotUsed) {
51711152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5184ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
51992669ee4SDaniel Jasper     return;
52092669ee4SDaniel Jasper   }
52192669ee4SDaniel Jasper 
52271e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
52371e1a64fSBen Langmuir     return;
52471e1a64fSBen Langmuir 
52571e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
52671e1a64fSBen Langmuir 
5275904c41eSBenjamin Kramer   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
52811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5294ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
530a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
531a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
532a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
53371e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53471e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
53571e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
53670a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
53770a7738fSManman Ren         << File->getName();
53871e1a64fSBen Langmuir   }
53992669ee4SDaniel Jasper }
54092669ee4SDaniel Jasper 
541ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
542ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5438b7c0398SSean Silva   // Prefer available modules.
5448b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5458b7c0398SSean Silva     return true;
5468b7c0398SSean Silva 
547ec87a50aSRichard Smith   // Prefer a public header over a private header.
548ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
549ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
550ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
551ec87a50aSRichard Smith 
552ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
553ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
554ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
555ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
556ec87a50aSRichard Smith 
557ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
558ec87a50aSRichard Smith   return false;
559ec87a50aSRichard Smith }
560ec87a50aSRichard Smith 
561ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
562ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
563306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
564ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
565afd1b1c9SEugene Zelenko       return {};
566306d8920SRichard Smith     return R;
567306d8920SRichard Smith   };
568306d8920SRichard Smith 
5694881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5701fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
571202210b3SRichard Smith     ModuleMap::KnownHeader Result;
57297da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5734881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5747e82e019SRichard Smith       // Prefer a header from the source module over all others.
5757e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5762f633e7cSRichard Smith         return MakeResult(H);
5774881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5784881e8b2SSean Silva         Result = H;
57997da9178SDaniel Jasper     }
580306d8920SRichard Smith     return MakeResult(Result);
5811fb5c3a6SDouglas Gregor   }
582ab0c8a84SDouglas Gregor 
583386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
584386bb073SRichard Smith }
585386bb073SRichard Smith 
586386bb073SRichard Smith ModuleMap::KnownHeader
587386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
588386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
589386bb073SRichard Smith 
590f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5914469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5924469138eSBen Langmuir   if (H) {
5934469138eSBen Langmuir     Module *Result = H.getModule();
594930a85ccSDouglas Gregor 
595930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
59673141fa9SDouglas Gregor     // directory.
597930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
59873141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
599930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
600930a85ccSDouglas Gregor 
601930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6029d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6039d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6049d6448b1SBen Langmuir 
605a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
606a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
607a89c5ac4SDouglas Gregor       // the actual header is located.
6089458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6099458f82dSDouglas Gregor 
6107033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
611a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
612056396aeSDouglas Gregor         SmallString<32> NameBuf;
613056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6144469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6159d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6169d6448b1SBen Langmuir                                     Explicit).first;
6179d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
618ffbafa2aSBen Langmuir         Result->IsInferred = true;
619a89c5ac4SDouglas Gregor 
620a89c5ac4SDouglas Gregor         // Associate the module and the directory.
621a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
622a89c5ac4SDouglas Gregor 
623a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
624a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
625930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
626d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
627a89c5ac4SDouglas Gregor       }
628a89c5ac4SDouglas Gregor 
629a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
630056396aeSDouglas Gregor       SmallString<32> NameBuf;
631056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
632056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6339d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6349d6448b1SBen Langmuir                                   Explicit).first;
6359d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
636ffbafa2aSBen Langmuir       Result->IsInferred = true;
6373c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
638a89c5ac4SDouglas Gregor 
639a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
640a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
641930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
642d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
643a89c5ac4SDouglas Gregor     } else {
644a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
645a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
646a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
647a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
648a89c5ac4SDouglas Gregor     }
649a89c5ac4SDouglas Gregor 
650386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
651386bb073SRichard Smith     Headers[File].push_back(Header);
652386bb073SRichard Smith     return Header;
653a89c5ac4SDouglas Gregor   }
654a89c5ac4SDouglas Gregor 
655afd1b1c9SEugene Zelenko   return {};
656ab0c8a84SDouglas Gregor }
657ab0c8a84SDouglas Gregor 
658386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
659386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
660040e1266SRichard Smith   resolveHeaderDirectives(File);
661386bb073SRichard Smith   auto It = Headers.find(File);
662386bb073SRichard Smith   if (It == Headers.end())
663386bb073SRichard Smith     return None;
664386bb073SRichard Smith   return It->second;
665386bb073SRichard Smith }
666386bb073SRichard Smith 
667e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
668d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
66950996ce1SRichard Smith }
67050996ce1SRichard Smith 
67162bcd925SDmitri Gribenko bool
67262bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
67362bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
674040e1266SRichard Smith   resolveHeaderDirectives(Header);
675e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
67697da9178SDaniel Jasper   if (Known != Headers.end()) {
67797da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
67897da9178SDaniel Jasper              I = Known->second.begin(),
67997da9178SDaniel Jasper              E = Known->second.end();
68097da9178SDaniel Jasper          I != E; ++I) {
681052d95a6SBruno Cardoso Lopes 
682052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
683052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
684052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
685052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
686052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
687052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
688052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
689052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
690052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
691052d95a6SBruno Cardoso Lopes           continue;
69297da9178SDaniel Jasper         return false;
69397da9178SDaniel Jasper       }
694052d95a6SBruno Cardoso Lopes     }
69597da9178SDaniel Jasper     return true;
69697da9178SDaniel Jasper   }
6971fb5c3a6SDouglas Gregor 
6981fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
699f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7001fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7011fb5c3a6SDouglas Gregor 
70250996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
70350996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
70450996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
70550996ce1SRichard Smith   };
70650996ce1SRichard Smith 
7071fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7081fb5c3a6SDouglas Gregor   // an umbrella header.
7091fb5c3a6SDouglas Gregor   do {
710e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7111fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7121fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7131fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
71450996ce1SRichard Smith       if (IsUnavailable(Found))
7151fb5c3a6SDouglas Gregor         return true;
7161fb5c3a6SDouglas Gregor 
7171fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7181fb5c3a6SDouglas Gregor       // directory.
7191fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7201fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7211fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7221fb5c3a6SDouglas Gregor 
7231fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7241fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7251fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
726056396aeSDouglas Gregor           SmallString<32> NameBuf;
727056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
728056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
729056396aeSDouglas Gregor                              NameBuf);
7301fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7311fb5c3a6SDouglas Gregor           if (!Found)
7321fb5c3a6SDouglas Gregor             return false;
73350996ce1SRichard Smith           if (IsUnavailable(Found))
7341fb5c3a6SDouglas Gregor             return true;
7351fb5c3a6SDouglas Gregor         }
7361fb5c3a6SDouglas Gregor 
7371fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
738056396aeSDouglas Gregor         SmallString<32> NameBuf;
739056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
740056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
741056396aeSDouglas Gregor                            NameBuf);
7421fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7431fb5c3a6SDouglas Gregor         if (!Found)
7441fb5c3a6SDouglas Gregor           return false;
7451fb5c3a6SDouglas Gregor       }
7461fb5c3a6SDouglas Gregor 
74750996ce1SRichard Smith       return IsUnavailable(Found);
7481fb5c3a6SDouglas Gregor     }
7491fb5c3a6SDouglas Gregor 
7501fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7511fb5c3a6SDouglas Gregor 
7521fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7531fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7541fb5c3a6SDouglas Gregor     if (DirName.empty())
7551fb5c3a6SDouglas Gregor       break;
7561fb5c3a6SDouglas Gregor 
7571fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7581f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7591fb5c3a6SDouglas Gregor   } while (Dir);
7601fb5c3a6SDouglas Gregor 
7611fb5c3a6SDouglas Gregor   return false;
7621fb5c3a6SDouglas Gregor }
7631fb5c3a6SDouglas Gregor 
764e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
765e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
76688bdfb0eSDouglas Gregor   if (Known != Modules.end())
76788bdfb0eSDouglas Gregor     return Known->getValue();
76888bdfb0eSDouglas Gregor 
769d2d442caSCraig Topper   return nullptr;
77088bdfb0eSDouglas Gregor }
77188bdfb0eSDouglas Gregor 
772e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
773e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7742b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7752b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7762b82c2a5SDouglas Gregor       return Sub;
7772b82c2a5SDouglas Gregor   }
7782b82c2a5SDouglas Gregor 
7792b82c2a5SDouglas Gregor   return findModule(Name);
7802b82c2a5SDouglas Gregor }
7812b82c2a5SDouglas Gregor 
782e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7832b82c2a5SDouglas Gregor   if (!Context)
7842b82c2a5SDouglas Gregor     return findModule(Name);
7852b82c2a5SDouglas Gregor 
786eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7872b82c2a5SDouglas Gregor }
7882b82c2a5SDouglas Gregor 
789c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
790c192d194SBruno Cardoso Lopes                                                         Module *Parent,
791c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
792c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
79369021974SDouglas Gregor   // Try to find an existing module with this name.
794eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
795eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
79669021974SDouglas Gregor 
79769021974SDouglas Gregor   // Create a new module with this name.
7989ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7999ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
8006f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8017e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8027e82e019SRichard Smith       SourceModule = Result;
80369021974SDouglas Gregor     Modules[Name] = Result;
804c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8056f722b4eSArgyrios Kyrtzidis   }
80669021974SDouglas Gregor   return std::make_pair(Result, true);
80769021974SDouglas Gregor }
80869021974SDouglas Gregor 
809*a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
810d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
811056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
812056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
813d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
814d6509cf2SRichard Smith   return PendingSubmodules.back().get();
815dd8b5337SRichard Smith }
816dd8b5337SRichard Smith 
817*a5bbbfefSRichard Smith Module *
818*a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
819*a5bbbfefSRichard Smith                                                        SourceLocation Loc) {
820*a5bbbfefSRichard Smith   auto *Result =
821*a5bbbfefSRichard Smith       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
822*a5bbbfefSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++);
823*a5bbbfefSRichard Smith   Result->Kind = Module::PrivateModuleFragment;
824*a5bbbfefSRichard Smith   return Result;
825*a5bbbfefSRichard Smith }
826*a5bbbfefSRichard Smith 
827bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
828dd8b5337SRichard Smith                                                 StringRef Name,
829dd8b5337SRichard Smith                                                 Module *GlobalModule) {
830bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
831bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
832bbcc9f04SRichard Smith 
833bbcc9f04SRichard Smith   auto *Result =
834bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
835bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
836145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
837bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
838bbcc9f04SRichard Smith 
839dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
840d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
841d6509cf2SRichard Smith     Submodule->setParent(Result);
842d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
843d6509cf2SRichard Smith   }
844d6509cf2SRichard Smith   PendingSubmodules.clear();
845dd8b5337SRichard Smith 
846bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
847bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
848bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
849bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
850bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
851bbcc9f04SRichard Smith 
852bbcc9f04SRichard Smith   return Result;
853bbcc9f04SRichard Smith }
854bbcc9f04SRichard Smith 
855d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
856d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
857d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
858d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
859d6509cf2SRichard Smith 
860d6509cf2SRichard Smith   auto *Result =
861d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
862d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
863d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
864d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
865d6509cf2SRichard Smith 
866d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
867d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
868d6509cf2SRichard Smith                          /*IsFramework*/ false,
869d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
870d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
871d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
872d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
873d6509cf2SRichard Smith   }
874d6509cf2SRichard Smith 
875d6509cf2SRichard Smith   return Result;
876d6509cf2SRichard Smith }
877d6509cf2SRichard Smith 
8789fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
87911dfe6feSDouglas Gregor /// should link.
88011dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
88111dfe6feSDouglas Gregor                                FileManager &FileMgr) {
88211dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
88311dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
88411dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
88511dfe6feSDouglas Gregor 
88611dfe6feSDouglas Gregor   SmallString<128> LibName;
88711dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
88811dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8898aaae5a9SJuergen Ributzka 
8908aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8918aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8928aaae5a9SJuergen Ributzka   // for both before we give up.
8938013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8948aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
89511dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
89611dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
89711dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8988aaae5a9SJuergen Ributzka       return;
8998aaae5a9SJuergen Ributzka     }
90011dfe6feSDouglas Gregor   }
90111dfe6feSDouglas Gregor }
90211dfe6feSDouglas Gregor 
903a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
904a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
905c1d88ea5SBen Langmuir   Attributes Attrs;
906c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
907a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
908c1d88ea5SBen Langmuir }
909c1d88ea5SBen Langmuir 
910a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
911c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
912a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
913a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
914a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
915a525400dSBen Langmuir   // top-level framework.
916a525400dSBen Langmuir   StringRef FrameworkDirName =
917a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
918a525400dSBen Langmuir 
919a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
920a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
921a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
922a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
923a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
924a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
925c1d88ea5SBen Langmuir 
92656c64013SDouglas Gregor   // Check whether we've already found this module.
927e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
928e89dbc1dSDouglas Gregor     return Mod;
929e89dbc1dSDouglas Gregor 
9301f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
93156c64013SDouglas Gregor 
9329194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9339194a91dSDouglas Gregor   // a framework module, do so.
934beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9359194a91dSDouglas Gregor   if (!Parent) {
9364ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9379194a91dSDouglas Gregor     bool canInfer = false;
9384ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9399194a91dSDouglas Gregor       // Figure out the parent path.
9404ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9419194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
9429194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9439194a91dSDouglas Gregor         // for a module map.
944e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9459194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
9469194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9479194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9489194a91dSDouglas Gregor           // one.
949984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
950984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
951984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
952c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
9539194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
9549194a91dSDouglas Gregor           }
9559194a91dSDouglas Gregor 
9569194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9579194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9589194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
9599194a91dSDouglas Gregor         }
9609194a91dSDouglas Gregor 
9619194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9629194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9639194a91dSDouglas Gregor           // to infer this particular module.
9644ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9659194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9669194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9679194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9689194a91dSDouglas Gregor 
969c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
970c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
971c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
972ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
973ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
974beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9759194a91dSDouglas Gregor         }
9769194a91dSDouglas Gregor       }
9779194a91dSDouglas Gregor     }
9789194a91dSDouglas Gregor 
9799194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9809194a91dSDouglas Gregor     if (!canInfer)
981d2d442caSCraig Topper       return nullptr;
982beee15e7SBen Langmuir   } else
9839d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9849194a91dSDouglas Gregor 
9859194a91dSDouglas Gregor 
98656c64013SDouglas Gregor   // Look for an umbrella header.
9872c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
98817381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
989e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
99056c64013SDouglas Gregor 
99156c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
99256c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
99356c64013SDouglas Gregor   // idea.
99456c64013SDouglas Gregor   if (!UmbrellaHeader)
995d2d442caSCraig Topper     return nullptr;
99656c64013SDouglas Gregor 
9979d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
998a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
999a7e2cc68SRichard Smith                               NumCreatedModules++);
10009d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
10019d6448b1SBen Langmuir   Result->IsInferred = true;
10027e82e019SRichard Smith   if (!Parent) {
10037e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
1004ba7f2f71SDaniel Jasper       SourceModule = Result;
10057e82e019SRichard Smith     Modules[ModuleName] = Result;
1006c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1007ba7f2f71SDaniel Jasper   }
1008c1d88ea5SBen Langmuir 
1009c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
1010c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1011c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1012ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10132b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1014a686e1b0SDouglas Gregor 
1015322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
10162b63d15fSRichard Smith   //
10172b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
10182b63d15fSRichard Smith   // a framework module.
10192b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
1020d8bd7537SDouglas Gregor 
1021d8bd7537SDouglas Gregor   // export *
1022d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1023d8bd7537SDouglas Gregor 
1024a89c5ac4SDouglas Gregor   // module * { export * }
1025a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1026a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1027a89c5ac4SDouglas Gregor 
1028e89dbc1dSDouglas Gregor   // Look for subframeworks.
1029c080917eSRafael Espindola   std::error_code EC;
10302c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1031ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1032e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10332d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1034db8a7422SDuncan P. N. Exon Smith   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1035fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1036fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1037b171a59bSBruno Cardoso Lopes            DirEnd;
1038e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10390ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1040e89dbc1dSDouglas Gregor       continue;
1041f2161a70SDouglas Gregor 
1042b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
10430ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
104407c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
104507c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
104607c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
104707c22b78SDouglas Gregor       // out to a top-level framework.
1048e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
104907c22b78SDouglas Gregor       bool FoundParent = false;
105007c22b78SDouglas Gregor       do {
105107c22b78SDouglas Gregor         // Get the parent directory name.
105207c22b78SDouglas Gregor         SubframeworkDirName
105307c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
105407c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
105507c22b78SDouglas Gregor           break;
105607c22b78SDouglas Gregor 
105707c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
105807c22b78SDouglas Gregor           FoundParent = true;
105907c22b78SDouglas Gregor           break;
106007c22b78SDouglas Gregor         }
106107c22b78SDouglas Gregor       } while (true);
106207c22b78SDouglas Gregor 
106307c22b78SDouglas Gregor       if (!FoundParent)
106407c22b78SDouglas Gregor         continue;
106507c22b78SDouglas Gregor 
1066e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1067a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
1068e89dbc1dSDouglas Gregor     }
1069e89dbc1dSDouglas Gregor   }
1070e89dbc1dSDouglas Gregor 
107111dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
107211dfe6feSDouglas Gregor   // framework.
107311dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
107411dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
107511dfe6feSDouglas Gregor   }
107611dfe6feSDouglas Gregor 
107756c64013SDouglas Gregor   return Result;
107856c64013SDouglas Gregor }
107956c64013SDouglas Gregor 
10808587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10818587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10828587dfd9SBruno Cardoso Lopes 
10838587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10848587dfd9SBruno Cardoso Lopes   Module *Result =
10858587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10868587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10878587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
10888587dfd9SBruno Cardoso Lopes   Result->IsAvailable = false;
1089c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10908587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
10918587dfd9SBruno Cardoso Lopes 
10928587dfd9SBruno Cardoso Lopes   return Result;
10938587dfd9SBruno Cardoso Lopes }
10948587dfd9SBruno Cardoso Lopes 
10952b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
10962b63d15fSRichard Smith                                   Twine NameAsWritten) {
109797da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
109873141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
10992b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
11007033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1101b3a0fa48SBruno Cardoso Lopes 
1102b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1103b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1104b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1105a89c5ac4SDouglas Gregor }
1106a89c5ac4SDouglas Gregor 
11072b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
11082b63d15fSRichard Smith                                Twine NameAsWritten) {
1109524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
11102b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1111524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1112524e33e1SDouglas Gregor }
1113524e33e1SDouglas Gregor 
1114040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11159f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11169f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1117040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1118040e1266SRichard Smith   // wrap the system header.
1119040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1120040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1121040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1122040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1123040e1266SRichard Smith     // case.
1124040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1125040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1126040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11273c1a41adSRichard Smith   }
1128040e1266SRichard Smith 
1129040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1130040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1131040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1132040e1266SRichard Smith   // headers.
1133040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1134040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1135040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1136040e1266SRichard Smith     // use the mtime as the key.
1137040e1266SRichard Smith     if (Header.ModTime)
1138040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1139040e1266SRichard Smith     else
1140040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1141040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1142040e1266SRichard Smith     return;
1143040e1266SRichard Smith   }
1144040e1266SRichard Smith 
1145040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1146040e1266SRichard Smith   // Perform the lookup now.
11479f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1148040e1266SRichard Smith }
1149040e1266SRichard Smith 
1150040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1151040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1152040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1153040e1266SRichard Smith     for (auto *M : BySize->second)
1154040e1266SRichard Smith       resolveHeaderDirectives(M);
1155040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1156040e1266SRichard Smith   }
1157040e1266SRichard Smith 
1158040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1159040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1160040e1266SRichard Smith     for (auto *M : ByModTime->second)
1161040e1266SRichard Smith       resolveHeaderDirectives(M);
1162040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1163040e1266SRichard Smith   }
1164040e1266SRichard Smith }
1165040e1266SRichard Smith 
1166040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11679f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1168040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1169040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1170040e1266SRichard Smith     // the header information for this file.
11719f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1172040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
11730e98d938SNAKAMURA Takumi }
1174202210b3SRichard Smith 
11753c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1176d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1177386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11783c1a41adSRichard Smith 
1179386bb073SRichard Smith   // Only add each header to the headers list once.
1180386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1181386bb073SRichard Smith   // same module definition?
1182386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1183386bb073SRichard Smith   for (auto H : HeaderList)
1184386bb073SRichard Smith     if (H == KH)
1185386bb073SRichard Smith       return;
1186386bb073SRichard Smith 
1187386bb073SRichard Smith   HeaderList.push_back(KH);
11881ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1189386bb073SRichard Smith 
11907e82e019SRichard Smith   bool isCompilingModuleHeader =
1191bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1192d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1193d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1194d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1195d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1196d8879c85SRichard Smith                                     isCompilingModuleHeader);
1197d8879c85SRichard Smith   }
1198e62cfd7cSBruno Cardoso Lopes 
1199e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1200e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1201f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1202a89c5ac4SDouglas Gregor }
1203a89c5ac4SDouglas Gregor 
12043c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1205feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1206feb54b6dSRichard Smith   // umbrella directory module.
1207feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1208feb54b6dSRichard Smith   // specified module?
12093c1a41adSRichard Smith   (void) Headers[Header.Entry];
12103c1a41adSRichard Smith 
12113c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1212feb54b6dSRichard Smith }
1213feb54b6dSRichard Smith 
1214514b636aSDouglas Gregor const FileEntry *
12154b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12161f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1217d2d442caSCraig Topper     return nullptr;
1218514b636aSDouglas Gregor 
12191f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12201f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1221514b636aSDouglas Gregor }
1222514b636aSDouglas Gregor 
12234b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12249d6448b1SBen Langmuir   if (M->IsInferred) {
12259d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12269d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12279d6448b1SBen Langmuir   }
12289d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12299d6448b1SBen Langmuir }
12309d6448b1SBen Langmuir 
12319d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12329d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12339d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12349d6448b1SBen Langmuir }
12359d6448b1SBen Langmuir 
1236cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1237718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1238718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1239718292f2SDouglas Gregor                                         MEnd = Modules.end();
1240718292f2SDouglas Gregor        M != MEnd; ++M)
1241d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1242718292f2SDouglas Gregor 
1243718292f2SDouglas Gregor   llvm::errs() << "Headers:";
124459527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1245718292f2SDouglas Gregor        H != HEnd; ++H) {
124697da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
124797da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
124897da9178SDaniel Jasper                                                       E = H->second.end();
124997da9178SDaniel Jasper          I != E; ++I) {
125097da9178SDaniel Jasper       if (I != H->second.begin())
125197da9178SDaniel Jasper         llvm::errs() << ",";
125297da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
125397da9178SDaniel Jasper     }
125497da9178SDaniel Jasper     llvm::errs() << "\n";
1255718292f2SDouglas Gregor   }
1256718292f2SDouglas Gregor }
1257718292f2SDouglas Gregor 
12582b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
125942413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
126042413141SRichard Smith   Mod->UnresolvedExports.clear();
126142413141SRichard Smith   for (auto &UE : Unresolved) {
126242413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1263f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12642b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12652b82c2a5SDouglas Gregor     else
126642413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12672b82c2a5SDouglas Gregor   }
126842413141SRichard Smith   return !Mod->UnresolvedExports.empty();
12692b82c2a5SDouglas Gregor }
12702b82c2a5SDouglas Gregor 
1271ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
127242413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
127342413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
127442413141SRichard Smith   for (auto &UDU : Unresolved) {
127542413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1276ba7f2f71SDaniel Jasper     if (DirectUse)
1277ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1278ba7f2f71SDaniel Jasper     else
127942413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1280ba7f2f71SDaniel Jasper   }
128142413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1282ba7f2f71SDaniel Jasper }
1283ba7f2f71SDaniel Jasper 
1284fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
128542413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
128642413141SRichard Smith   Mod->UnresolvedConflicts.clear();
128742413141SRichard Smith   for (auto &UC : Unresolved) {
128842413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1289fb912657SDouglas Gregor       Module::Conflict Conflict;
1290fb912657SDouglas Gregor       Conflict.Other = OtherMod;
129142413141SRichard Smith       Conflict.Message = UC.Message;
1292fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
129342413141SRichard Smith     } else
129442413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1295fb912657SDouglas Gregor   }
129642413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1297fb912657SDouglas Gregor }
1298fb912657SDouglas Gregor 
1299718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1300718292f2SDouglas Gregor // Module map file parser
1301718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1302718292f2SDouglas Gregor 
1303718292f2SDouglas Gregor namespace clang {
1304afd1b1c9SEugene Zelenko 
13059fc8faf9SAdrian Prantl   /// A token in a module map file.
1306718292f2SDouglas Gregor   struct MMToken {
1307718292f2SDouglas Gregor     enum TokenKind {
13081fb5c3a6SDouglas Gregor       Comma,
130935b13eceSDouglas Gregor       ConfigMacros,
1310fb912657SDouglas Gregor       Conflict,
1311718292f2SDouglas Gregor       EndOfFile,
1312718292f2SDouglas Gregor       HeaderKeyword,
1313718292f2SDouglas Gregor       Identifier,
1314a3feee2aSRichard Smith       Exclaim,
131559527666SDouglas Gregor       ExcludeKeyword,
1316718292f2SDouglas Gregor       ExplicitKeyword,
13172b82c2a5SDouglas Gregor       ExportKeyword,
1318f0b11de2SDouglas Gregor       ExportAsKeyword,
131997292843SDaniel Jasper       ExternKeyword,
1320755b2055SDouglas Gregor       FrameworkKeyword,
13216ddfca91SDouglas Gregor       LinkKeyword,
1322718292f2SDouglas Gregor       ModuleKeyword,
13232b82c2a5SDouglas Gregor       Period,
1324b53e5483SLawrence Crowl       PrivateKeyword,
1325718292f2SDouglas Gregor       UmbrellaKeyword,
1326ba7f2f71SDaniel Jasper       UseKeyword,
13271fb5c3a6SDouglas Gregor       RequiresKeyword,
13282b82c2a5SDouglas Gregor       Star,
1329718292f2SDouglas Gregor       StringLiteral,
1330040e1266SRichard Smith       IntegerLiteral,
1331306d8920SRichard Smith       TextualKeyword,
1332718292f2SDouglas Gregor       LBrace,
1333a686e1b0SDouglas Gregor       RBrace,
1334a686e1b0SDouglas Gregor       LSquare,
1335a686e1b0SDouglas Gregor       RSquare
1336718292f2SDouglas Gregor     } Kind;
1337718292f2SDouglas Gregor 
1338718292f2SDouglas Gregor     unsigned Location;
1339718292f2SDouglas Gregor     unsigned StringLength;
1340040e1266SRichard Smith     union {
1341040e1266SRichard Smith       // If Kind != IntegerLiteral.
1342718292f2SDouglas Gregor       const char *StringData;
1343afd1b1c9SEugene Zelenko 
1344040e1266SRichard Smith       // If Kind == IntegerLiteral.
1345040e1266SRichard Smith       uint64_t IntegerValue;
1346040e1266SRichard Smith     };
1347718292f2SDouglas Gregor 
1348718292f2SDouglas Gregor     void clear() {
1349718292f2SDouglas Gregor       Kind = EndOfFile;
1350718292f2SDouglas Gregor       Location = 0;
1351718292f2SDouglas Gregor       StringLength = 0;
1352d2d442caSCraig Topper       StringData = nullptr;
1353718292f2SDouglas Gregor     }
1354718292f2SDouglas Gregor 
1355718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1356718292f2SDouglas Gregor 
1357718292f2SDouglas Gregor     SourceLocation getLocation() const {
1358718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1359718292f2SDouglas Gregor     }
1360718292f2SDouglas Gregor 
1361040e1266SRichard Smith     uint64_t getInteger() const {
1362040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1363040e1266SRichard Smith     }
1364040e1266SRichard Smith 
1365718292f2SDouglas Gregor     StringRef getString() const {
1366040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1367040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1368718292f2SDouglas Gregor     }
1369718292f2SDouglas Gregor   };
1370718292f2SDouglas Gregor 
1371718292f2SDouglas Gregor   class ModuleMapParser {
1372718292f2SDouglas Gregor     Lexer &L;
1373718292f2SDouglas Gregor     SourceManager &SourceMgr;
1374bc10b9fbSDouglas Gregor 
13759fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1376bc10b9fbSDouglas Gregor     /// parsing.
1377bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1378bc10b9fbSDouglas Gregor 
1379718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1380718292f2SDouglas Gregor     ModuleMap &Map;
1381718292f2SDouglas Gregor 
13829fc8faf9SAdrian Prantl     /// The current module map file.
1383beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1384beee15e7SBen Langmuir 
13859f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
13869f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
13879f6020bcSBruno Cardoso Lopes 
13889fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
13899acb99e3SRichard Smith     /// be resolved relative to.
13905257fc63SDouglas Gregor     const DirectoryEntry *Directory;
13915257fc63SDouglas Gregor 
13929fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1393963c5535SDouglas Gregor     bool IsSystem;
1394963c5535SDouglas Gregor 
13959fc8faf9SAdrian Prantl     /// Whether an error occurred.
1396afd1b1c9SEugene Zelenko     bool HadError = false;
1397718292f2SDouglas Gregor 
13989fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1399718292f2SDouglas Gregor     /// during parsing.
1400718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1401718292f2SDouglas Gregor 
14029fc8faf9SAdrian Prantl     /// The current token.
1403718292f2SDouglas Gregor     MMToken Tok;
1404718292f2SDouglas Gregor 
14059fc8faf9SAdrian Prantl     /// The active module.
1406afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1407718292f2SDouglas Gregor 
14089fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
14097ff29148SBen Langmuir     /// contents as 'textual'.
14107ff29148SBen Langmuir     ///
14117ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14127ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14137ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14147ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14157ff29148SBen Langmuir     /// 'textual' to match the original intent.
14167ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14177ff29148SBen Langmuir 
14189fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1419718292f2SDouglas Gregor     SourceLocation consumeToken();
1420718292f2SDouglas Gregor 
14219fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1422718292f2SDouglas Gregor     /// (or the end of the file).
1423718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1424718292f2SDouglas Gregor 
1425afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1426afd1b1c9SEugene Zelenko 
1427e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1428718292f2SDouglas Gregor     void parseModuleDecl();
142997292843SDaniel Jasper     void parseExternModuleDecl();
14301fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1431afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1432524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14332b82c2a5SDouglas Gregor     void parseExportDecl();
1434f0b11de2SDouglas Gregor     void parseExportAsDecl();
1435ba7f2f71SDaniel Jasper     void parseUseDecl();
14366ddfca91SDouglas Gregor     void parseLinkDecl();
143735b13eceSDouglas Gregor     void parseConfigMacros();
1438fb912657SDouglas Gregor     void parseConflict();
14399194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1440c1d88ea5SBen Langmuir 
14415f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14425f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14435f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14445f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14455f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14465f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14475f11e128SBruno Cardoso Lopes 
1448afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1449afd1b1c9SEugene Zelenko 
14504442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1451718292f2SDouglas Gregor 
1452718292f2SDouglas Gregor   public:
1453718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14548587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14558587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1456c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1457bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1458beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1459c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1460718292f2SDouglas Gregor       Tok.clear();
1461718292f2SDouglas Gregor       consumeToken();
1462718292f2SDouglas Gregor     }
1463718292f2SDouglas Gregor 
1464718292f2SDouglas Gregor     bool parseModuleMapFile();
14658128f332SRichard Smith 
14668128f332SRichard Smith     bool terminatedByDirective() { return false; }
14678128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1468718292f2SDouglas Gregor   };
1469afd1b1c9SEugene Zelenko 
1470afd1b1c9SEugene Zelenko } // namespace clang
1471718292f2SDouglas Gregor 
1472718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1473718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1474718292f2SDouglas Gregor 
14758128f332SRichard Smith retry:
14768128f332SRichard Smith   Tok.clear();
1477718292f2SDouglas Gregor   Token LToken;
1478718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1479718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1480718292f2SDouglas Gregor   switch (LToken.getKind()) {
14812d57cea2SAlp Toker   case tok::raw_identifier: {
14822d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
14832d57cea2SAlp Toker     Tok.StringData = RI.data();
14842d57cea2SAlp Toker     Tok.StringLength = RI.size();
14852d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
148635b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1487fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
148859527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1489718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
14902b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1491f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
149297292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1493755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
149435b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
14956ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1496718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1497b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
14981fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1499306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1500718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1501ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1502718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1503718292f2SDouglas Gregor     break;
15042d57cea2SAlp Toker   }
1505718292f2SDouglas Gregor 
15061fb5c3a6SDouglas Gregor   case tok::comma:
15071fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
15081fb5c3a6SDouglas Gregor     break;
15091fb5c3a6SDouglas Gregor 
1510718292f2SDouglas Gregor   case tok::eof:
1511718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1512718292f2SDouglas Gregor     break;
1513718292f2SDouglas Gregor 
1514718292f2SDouglas Gregor   case tok::l_brace:
1515718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1516718292f2SDouglas Gregor     break;
1517718292f2SDouglas Gregor 
1518a686e1b0SDouglas Gregor   case tok::l_square:
1519a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1520a686e1b0SDouglas Gregor     break;
1521a686e1b0SDouglas Gregor 
15222b82c2a5SDouglas Gregor   case tok::period:
15232b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15242b82c2a5SDouglas Gregor     break;
15252b82c2a5SDouglas Gregor 
1526718292f2SDouglas Gregor   case tok::r_brace:
1527718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1528718292f2SDouglas Gregor     break;
1529718292f2SDouglas Gregor 
1530a686e1b0SDouglas Gregor   case tok::r_square:
1531a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1532a686e1b0SDouglas Gregor     break;
1533a686e1b0SDouglas Gregor 
15342b82c2a5SDouglas Gregor   case tok::star:
15352b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15362b82c2a5SDouglas Gregor     break;
15372b82c2a5SDouglas Gregor 
1538a3feee2aSRichard Smith   case tok::exclaim:
1539a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1540a3feee2aSRichard Smith     break;
1541a3feee2aSRichard Smith 
1542718292f2SDouglas Gregor   case tok::string_literal: {
1543d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1544d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1545d67aea28SRichard Smith       HadError = true;
1546d67aea28SRichard Smith       goto retry;
1547d67aea28SRichard Smith     }
1548d67aea28SRichard Smith 
1549718292f2SDouglas Gregor     // Parse the string literal.
1550718292f2SDouglas Gregor     LangOptions LangOpts;
15519d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1552718292f2SDouglas Gregor     if (StringLiteral.hadError)
1553718292f2SDouglas Gregor       goto retry;
1554718292f2SDouglas Gregor 
1555718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1556718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1557718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1558718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1559718292f2SDouglas Gregor     Saved[Length] = 0;
1560718292f2SDouglas Gregor 
1561718292f2SDouglas Gregor     // Form the token.
1562718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1563718292f2SDouglas Gregor     Tok.StringData = Saved;
1564718292f2SDouglas Gregor     Tok.StringLength = Length;
1565718292f2SDouglas Gregor     break;
1566718292f2SDouglas Gregor   }
1567718292f2SDouglas Gregor 
1568040e1266SRichard Smith   case tok::numeric_constant: {
1569040e1266SRichard Smith     // We don't support any suffixes or other complications.
1570040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1571040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1572040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1573040e1266SRichard Smith     unsigned Length =
1574040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1575040e1266SRichard Smith     uint64_t Value;
1576040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1577040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1578040e1266SRichard Smith       HadError = true;
1579040e1266SRichard Smith       goto retry;
1580040e1266SRichard Smith     }
1581040e1266SRichard Smith 
1582040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1583040e1266SRichard Smith     Tok.IntegerValue = Value;
1584040e1266SRichard Smith     break;
1585040e1266SRichard Smith   }
1586040e1266SRichard Smith 
1587718292f2SDouglas Gregor   case tok::comment:
1588718292f2SDouglas Gregor     goto retry;
1589718292f2SDouglas Gregor 
15908128f332SRichard Smith   case tok::hash:
15918128f332SRichard Smith     // A module map can be terminated prematurely by
15928128f332SRichard Smith     //   #pragma clang module contents
15938128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
15948128f332SRichard Smith     // contents of the module.
15958128f332SRichard Smith     {
15968128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
15978128f332SRichard Smith         L.LexFromRawLexer(LToken);
15988128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15998128f332SRichard Smith                LToken.getRawIdentifier() == Str;
16008128f332SRichard Smith       };
16018128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16028128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
16038128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
16048128f332SRichard Smith         break;
16058128f332SRichard Smith       }
16068128f332SRichard Smith     }
16078128f332SRichard Smith     LLVM_FALLTHROUGH;
16088128f332SRichard Smith 
1609718292f2SDouglas Gregor   default:
16108128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1611718292f2SDouglas Gregor     HadError = true;
1612718292f2SDouglas Gregor     goto retry;
1613718292f2SDouglas Gregor   }
1614718292f2SDouglas Gregor 
1615718292f2SDouglas Gregor   return Result;
1616718292f2SDouglas Gregor }
1617718292f2SDouglas Gregor 
1618718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1619718292f2SDouglas Gregor   unsigned braceDepth = 0;
1620a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1621718292f2SDouglas Gregor   do {
1622718292f2SDouglas Gregor     switch (Tok.Kind) {
1623718292f2SDouglas Gregor     case MMToken::EndOfFile:
1624718292f2SDouglas Gregor       return;
1625718292f2SDouglas Gregor 
1626718292f2SDouglas Gregor     case MMToken::LBrace:
1627a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1628718292f2SDouglas Gregor         return;
1629718292f2SDouglas Gregor 
1630718292f2SDouglas Gregor       ++braceDepth;
1631718292f2SDouglas Gregor       break;
1632718292f2SDouglas Gregor 
1633a686e1b0SDouglas Gregor     case MMToken::LSquare:
1634a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1635a686e1b0SDouglas Gregor         return;
1636a686e1b0SDouglas Gregor 
1637a686e1b0SDouglas Gregor       ++squareDepth;
1638a686e1b0SDouglas Gregor       break;
1639a686e1b0SDouglas Gregor 
1640718292f2SDouglas Gregor     case MMToken::RBrace:
1641718292f2SDouglas Gregor       if (braceDepth > 0)
1642718292f2SDouglas Gregor         --braceDepth;
1643718292f2SDouglas Gregor       else if (Tok.is(K))
1644718292f2SDouglas Gregor         return;
1645718292f2SDouglas Gregor       break;
1646718292f2SDouglas Gregor 
1647a686e1b0SDouglas Gregor     case MMToken::RSquare:
1648a686e1b0SDouglas Gregor       if (squareDepth > 0)
1649a686e1b0SDouglas Gregor         --squareDepth;
1650a686e1b0SDouglas Gregor       else if (Tok.is(K))
1651a686e1b0SDouglas Gregor         return;
1652a686e1b0SDouglas Gregor       break;
1653a686e1b0SDouglas Gregor 
1654718292f2SDouglas Gregor     default:
1655a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1656718292f2SDouglas Gregor         return;
1657718292f2SDouglas Gregor       break;
1658718292f2SDouglas Gregor     }
1659718292f2SDouglas Gregor 
1660718292f2SDouglas Gregor    consumeToken();
1661718292f2SDouglas Gregor   } while (true);
1662718292f2SDouglas Gregor }
1663718292f2SDouglas Gregor 
16649fc8faf9SAdrian Prantl /// Parse a module-id.
1665e7ab3669SDouglas Gregor ///
1666e7ab3669SDouglas Gregor ///   module-id:
1667e7ab3669SDouglas Gregor ///     identifier
1668e7ab3669SDouglas Gregor ///     identifier '.' module-id
1669e7ab3669SDouglas Gregor ///
1670e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1671e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1672e7ab3669SDouglas Gregor   Id.clear();
1673e7ab3669SDouglas Gregor   do {
16743cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1675e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1676e7ab3669SDouglas Gregor       consumeToken();
1677e7ab3669SDouglas Gregor     } else {
1678e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1679e7ab3669SDouglas Gregor       return true;
1680e7ab3669SDouglas Gregor     }
1681e7ab3669SDouglas Gregor 
1682e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1683e7ab3669SDouglas Gregor       break;
1684e7ab3669SDouglas Gregor 
1685e7ab3669SDouglas Gregor     consumeToken();
1686e7ab3669SDouglas Gregor   } while (true);
1687e7ab3669SDouglas Gregor 
1688e7ab3669SDouglas Gregor   return false;
1689e7ab3669SDouglas Gregor }
1690e7ab3669SDouglas Gregor 
1691a686e1b0SDouglas Gregor namespace {
1692afd1b1c9SEugene Zelenko 
16939fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1694a686e1b0SDouglas Gregor   enum AttributeKind {
16959fc8faf9SAdrian Prantl     /// An unknown attribute.
1696a686e1b0SDouglas Gregor     AT_unknown,
1697afd1b1c9SEugene Zelenko 
16989fc8faf9SAdrian Prantl     /// The 'system' attribute.
169935b13eceSDouglas Gregor     AT_system,
1700afd1b1c9SEugene Zelenko 
17019fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
170277944868SRichard Smith     AT_extern_c,
1703afd1b1c9SEugene Zelenko 
17049fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1705ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1706afd1b1c9SEugene Zelenko 
17079fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1708ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1709a686e1b0SDouglas Gregor   };
1710afd1b1c9SEugene Zelenko 
1711afd1b1c9SEugene Zelenko } // namespace
1712a686e1b0SDouglas Gregor 
171329729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
171429729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
171529729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
171629729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17175f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17185f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
171929729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17207d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
172129729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
172229729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
172329729919SBruno Cardoso Lopes     D << BadName << M->Name;
17247d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
172529729919SBruno Cardoso Lopes   };
172629729919SBruno Cardoso Lopes 
172729729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
172829729919SBruno Cardoso Lopes     auto const *M = E->getValue();
172929729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
173029729919SBruno Cardoso Lopes       continue;
173129729919SBruno Cardoso Lopes 
173229729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
173329729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
173429729919SBruno Cardoso Lopes       continue;
17355f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
173629729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
173729729919SBruno Cardoso Lopes     Canonical.append("_Private");
173829729919SBruno Cardoso Lopes 
173929729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
174029729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
174129729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
174229729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
174329729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
174429729919SBruno Cardoso Lopes           << FullName;
17455f11e128SBruno Cardoso Lopes 
17465f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17475f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17485f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17495f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17505f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17515f11e128SBruno Cardoso Lopes 
17525f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17535f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17545f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17555f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
17565f11e128SBruno Cardoso Lopes 
17575f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17585f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
175929729919SBruno Cardoso Lopes       continue;
176029729919SBruno Cardoso Lopes     }
176129729919SBruno Cardoso Lopes 
176229729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
176329729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
176429729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
176529729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
176629729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
176729729919SBruno Cardoso Lopes           << ActiveModule->Name;
17687d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
17697d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
177029729919SBruno Cardoso Lopes     }
177129729919SBruno Cardoso Lopes   }
177229729919SBruno Cardoso Lopes }
177329729919SBruno Cardoso Lopes 
17749fc8faf9SAdrian Prantl /// Parse a module declaration.
1775718292f2SDouglas Gregor ///
1776718292f2SDouglas Gregor ///   module-declaration:
177797292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1778a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1779a686e1b0SDouglas Gregor ///       { module-member* }
1780a686e1b0SDouglas Gregor ///
1781718292f2SDouglas Gregor ///   module-member:
17821fb5c3a6SDouglas Gregor ///     requires-declaration
1783718292f2SDouglas Gregor ///     header-declaration
1784e7ab3669SDouglas Gregor ///     submodule-declaration
17852b82c2a5SDouglas Gregor ///     export-declaration
1786f0b11de2SDouglas Gregor ///     export-as-declaration
17876ddfca91SDouglas Gregor ///     link-declaration
178873441091SDouglas Gregor ///
178973441091SDouglas Gregor ///   submodule-declaration:
179073441091SDouglas Gregor ///     module-declaration
179173441091SDouglas Gregor ///     inferred-submodule-declaration
1792718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1793755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
179497292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
179597292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
179697292843SDaniel Jasper     parseExternModuleDecl();
179797292843SDaniel Jasper     return;
179897292843SDaniel Jasper   }
179997292843SDaniel Jasper 
1800f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1801e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
18025f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1803718292f2SDouglas Gregor   bool Explicit = false;
1804f2161a70SDouglas Gregor   bool Framework = false;
1805755b2055SDouglas Gregor 
1806f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1807f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1808e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1809f2161a70SDouglas Gregor     Explicit = true;
1810f2161a70SDouglas Gregor   }
1811f2161a70SDouglas Gregor 
1812f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1813755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18145f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1815755b2055SDouglas Gregor     Framework = true;
1816755b2055SDouglas Gregor   }
1817718292f2SDouglas Gregor 
1818718292f2SDouglas Gregor   // Parse 'module' keyword.
1819718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1820d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1821718292f2SDouglas Gregor     consumeToken();
1822718292f2SDouglas Gregor     HadError = true;
1823718292f2SDouglas Gregor     return;
1824718292f2SDouglas Gregor   }
18259f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1826718292f2SDouglas Gregor 
182773441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
182873441091SDouglas Gregor   // Parse it.
182973441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18309194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
183173441091SDouglas Gregor 
1832718292f2SDouglas Gregor   // Parse the module name.
1833e7ab3669SDouglas Gregor   ModuleId Id;
1834e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1835718292f2SDouglas Gregor     HadError = true;
1836718292f2SDouglas Gregor     return;
1837718292f2SDouglas Gregor   }
1838e7ab3669SDouglas Gregor 
1839e7ab3669SDouglas Gregor   if (ActiveModule) {
1840e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1841e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1842e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1843e7ab3669SDouglas Gregor 
1844e7ab3669SDouglas Gregor       HadError = true;
1845e7ab3669SDouglas Gregor       return;
1846e7ab3669SDouglas Gregor     }
1847e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1848e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1849e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1850e7ab3669SDouglas Gregor     Explicit = false;
1851e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1852e7ab3669SDouglas Gregor     HadError = true;
1853e7ab3669SDouglas Gregor   }
1854e7ab3669SDouglas Gregor 
1855e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1856e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1857e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1858e7ab3669SDouglas Gregor     // is a submodule.
1859d2d442caSCraig Topper     ActiveModule = nullptr;
18604b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1861e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1862e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
18634b8a9e95SBen Langmuir         if (I == 0)
18644b8a9e95SBen Langmuir           TopLevelModule = Next;
1865e7ab3669SDouglas Gregor         ActiveModule = Next;
1866e7ab3669SDouglas Gregor         continue;
1867e7ab3669SDouglas Gregor       }
1868e7ab3669SDouglas Gregor 
1869e7ab3669SDouglas Gregor       if (ActiveModule) {
1870e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
18715b5d21eaSRichard Smith           << Id[I].first
18725b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1873e7ab3669SDouglas Gregor       } else {
1874e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1875e7ab3669SDouglas Gregor       }
1876e7ab3669SDouglas Gregor       HadError = true;
1877e7ab3669SDouglas Gregor       return;
1878e7ab3669SDouglas Gregor     }
18794b8a9e95SBen Langmuir 
18804b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
18814b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
18824b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
18834b8a9e95SBen Langmuir              "top-level module");
18844b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
18854b8a9e95SBen Langmuir     }
1886e7ab3669SDouglas Gregor   }
1887e7ab3669SDouglas Gregor 
1888e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1889e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1890718292f2SDouglas Gregor 
1891a686e1b0SDouglas Gregor   // Parse the optional attribute list.
18924442605fSBill Wendling   Attributes Attrs;
18935d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
18945d29dee0SDavide Italiano     return;
18955d29dee0SDavide Italiano 
1896718292f2SDouglas Gregor   // Parse the opening brace.
1897718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1898718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1899718292f2SDouglas Gregor       << ModuleName;
1900718292f2SDouglas Gregor     HadError = true;
1901718292f2SDouglas Gregor     return;
1902718292f2SDouglas Gregor   }
1903718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1904718292f2SDouglas Gregor 
1905718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
19068587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1907eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19084a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
19094a3751ffSRichard Smith     // definition for in two cases:
19104a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19114a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19124a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19134a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19144a3751ffSRichard Smith     //    module map file from which it was created.
19154a3751ffSRichard Smith     bool ParsedAsMainInput =
19164a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19174a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19184a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19194a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19204a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1921fcc54a3bSDouglas Gregor       // Skip the module definition.
1922fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1923fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1924fcc54a3bSDouglas Gregor         consumeToken();
1925fcc54a3bSDouglas Gregor       else {
1926fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1927fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1928fcc54a3bSDouglas Gregor         HadError = true;
1929fcc54a3bSDouglas Gregor       }
1930fcc54a3bSDouglas Gregor       return;
1931fcc54a3bSDouglas Gregor     }
1932fcc54a3bSDouglas Gregor 
1933c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19348587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19358587dfd9SBruno Cardoso Lopes     } else {
19368587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1937718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1938718292f2SDouglas Gregor           << ModuleName;
1939eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1940718292f2SDouglas Gregor 
1941718292f2SDouglas Gregor       // Skip the module definition.
1942718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1943718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1944718292f2SDouglas Gregor         consumeToken();
1945718292f2SDouglas Gregor 
1946718292f2SDouglas Gregor       HadError = true;
1947718292f2SDouglas Gregor       return;
1948718292f2SDouglas Gregor     }
19498587dfd9SBruno Cardoso Lopes   }
1950718292f2SDouglas Gregor 
1951718292f2SDouglas Gregor   // Start defining this module.
19528587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19538587dfd9SBruno Cardoso Lopes     ActiveModule =
19548587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19558587dfd9SBruno Cardoso Lopes   } else {
1956c192d194SBruno Cardoso Lopes     ActiveModule =
1957c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19588587dfd9SBruno Cardoso Lopes             .first;
19598587dfd9SBruno Cardoso Lopes   }
19608587dfd9SBruno Cardoso Lopes 
1961eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1962963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1963a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
196477944868SRichard Smith   if (Attrs.IsExternC)
196577944868SRichard Smith     ActiveModule->IsExternC = true;
1966ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1967ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1968ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
19693c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1970718292f2SDouglas Gregor 
197190b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
197290b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
197390b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
197490b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
197590b0a1fcSJordan Rose   }
197629729919SBruno Cardoso Lopes 
197729729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
197829729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
197929729919SBruno Cardoso Lopes   // Foo_Private instead.
198029729919SBruno Cardoso Lopes   SourceLocation StartLoc =
198129729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
198229729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
198329729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
198429729919SBruno Cardoso Lopes                        StartLoc) &&
198529729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
198629729919SBruno Cardoso Lopes                        StartLoc) &&
198790b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
19885f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
19894d867640SGraydon Hoare 
1990718292f2SDouglas Gregor   bool Done = false;
1991718292f2SDouglas Gregor   do {
1992718292f2SDouglas Gregor     switch (Tok.Kind) {
1993718292f2SDouglas Gregor     case MMToken::EndOfFile:
1994718292f2SDouglas Gregor     case MMToken::RBrace:
1995718292f2SDouglas Gregor       Done = true;
1996718292f2SDouglas Gregor       break;
1997718292f2SDouglas Gregor 
199835b13eceSDouglas Gregor     case MMToken::ConfigMacros:
199935b13eceSDouglas Gregor       parseConfigMacros();
200035b13eceSDouglas Gregor       break;
200135b13eceSDouglas Gregor 
2002fb912657SDouglas Gregor     case MMToken::Conflict:
2003fb912657SDouglas Gregor       parseConflict();
2004fb912657SDouglas Gregor       break;
2005fb912657SDouglas Gregor 
2006718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
200797292843SDaniel Jasper     case MMToken::ExternKeyword:
2008f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
2009718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2010718292f2SDouglas Gregor       parseModuleDecl();
2011718292f2SDouglas Gregor       break;
2012718292f2SDouglas Gregor 
20132b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20142b82c2a5SDouglas Gregor       parseExportDecl();
20152b82c2a5SDouglas Gregor       break;
20162b82c2a5SDouglas Gregor 
2017f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2018f0b11de2SDouglas Gregor       parseExportAsDecl();
2019f0b11de2SDouglas Gregor       break;
2020f0b11de2SDouglas Gregor 
2021ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2022ba7f2f71SDaniel Jasper       parseUseDecl();
2023ba7f2f71SDaniel Jasper       break;
2024ba7f2f71SDaniel Jasper 
20251fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20261fb5c3a6SDouglas Gregor       parseRequiresDecl();
20271fb5c3a6SDouglas Gregor       break;
20281fb5c3a6SDouglas Gregor 
2029202210b3SRichard Smith     case MMToken::TextualKeyword:
2030202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2031306d8920SRichard Smith       break;
2032306d8920SRichard Smith 
2033524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2034524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2035524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2036b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2037524e33e1SDouglas Gregor       else
2038524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2039718292f2SDouglas Gregor       break;
2040524e33e1SDouglas Gregor     }
2041718292f2SDouglas Gregor 
2042202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2043202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
204459527666SDouglas Gregor       break;
204559527666SDouglas Gregor 
2046202210b3SRichard Smith     case MMToken::PrivateKeyword:
2047202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2048b53e5483SLawrence Crowl       break;
2049b53e5483SLawrence Crowl 
2050322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2051202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2052718292f2SDouglas Gregor       break;
2053718292f2SDouglas Gregor 
20546ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20556ddfca91SDouglas Gregor       parseLinkDecl();
20566ddfca91SDouglas Gregor       break;
20576ddfca91SDouglas Gregor 
2058718292f2SDouglas Gregor     default:
2059718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2060718292f2SDouglas Gregor       consumeToken();
2061718292f2SDouglas Gregor       break;
2062718292f2SDouglas Gregor     }
2063718292f2SDouglas Gregor   } while (!Done);
2064718292f2SDouglas Gregor 
2065718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2066718292f2SDouglas Gregor     consumeToken();
2067718292f2SDouglas Gregor   else {
2068718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2069718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2070718292f2SDouglas Gregor     HadError = true;
2071718292f2SDouglas Gregor   }
2072718292f2SDouglas Gregor 
207311dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
207411dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
207511dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
207611dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
207711dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
207811dfe6feSDouglas Gregor   }
207911dfe6feSDouglas Gregor 
2080ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2081ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2082ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
2083ec8c9752SBen Langmuir       ActiveModule->Parent) {
2084ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
2085ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2086ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2087ec8c9752SBen Langmuir   }
2088ec8c9752SBen Langmuir 
2089e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2090e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2091718292f2SDouglas Gregor }
2092718292f2SDouglas Gregor 
20939fc8faf9SAdrian Prantl /// Parse an extern module declaration.
209497292843SDaniel Jasper ///
209597292843SDaniel Jasper ///   extern module-declaration:
209697292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
209797292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
209897292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2099ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
210097292843SDaniel Jasper 
210197292843SDaniel Jasper   // Parse 'module' keyword.
210297292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
210397292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
210497292843SDaniel Jasper     consumeToken();
210597292843SDaniel Jasper     HadError = true;
210697292843SDaniel Jasper     return;
210797292843SDaniel Jasper   }
210897292843SDaniel Jasper   consumeToken(); // 'module' keyword
210997292843SDaniel Jasper 
211097292843SDaniel Jasper   // Parse the module name.
211197292843SDaniel Jasper   ModuleId Id;
211297292843SDaniel Jasper   if (parseModuleId(Id)) {
211397292843SDaniel Jasper     HadError = true;
211497292843SDaniel Jasper     return;
211597292843SDaniel Jasper   }
211697292843SDaniel Jasper 
211797292843SDaniel Jasper   // Parse the referenced module map file name.
211897292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
211997292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
212097292843SDaniel Jasper     HadError = true;
212197292843SDaniel Jasper     return;
212297292843SDaniel Jasper   }
212397292843SDaniel Jasper   std::string FileName = Tok.getString();
212497292843SDaniel Jasper   consumeToken(); // filename
212597292843SDaniel Jasper 
212697292843SDaniel Jasper   StringRef FileNameRef = FileName;
212797292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
212897292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
212997292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
213097292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
213192e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
213297292843SDaniel Jasper   }
213397292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
21349acb99e3SRichard Smith     Map.parseModuleMapFile(
21359acb99e3SRichard Smith         File, /*IsSystem=*/false,
21369acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21379acb99e3SRichard Smith             ? Directory
21388128f332SRichard Smith             : File->getDir(),
2139c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
214097292843SDaniel Jasper }
214197292843SDaniel Jasper 
21427ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21437ff29148SBen Langmuir ///
21447ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21457ff29148SBen Langmuir /// module map files:
21467ff29148SBen Langmuir ///
21477ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21487ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21497ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21507ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21517ff29148SBen Langmuir ///    module to 'textual'.
21527ff29148SBen Langmuir ///
21537ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21547ff29148SBen Langmuir ///
21557ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21567ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21577ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21587ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21598013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21608013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21618013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21627ff29148SBen Langmuir     IsRequiresExcludedHack = true;
21637ff29148SBen Langmuir     return false;
21648013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21657ff29148SBen Langmuir     return false;
21667ff29148SBen Langmuir   }
21677ff29148SBen Langmuir 
21687ff29148SBen Langmuir   return true;
21697ff29148SBen Langmuir }
21707ff29148SBen Langmuir 
21719fc8faf9SAdrian Prantl /// Parse a requires declaration.
21721fb5c3a6SDouglas Gregor ///
21731fb5c3a6SDouglas Gregor ///   requires-declaration:
21741fb5c3a6SDouglas Gregor ///     'requires' feature-list
21751fb5c3a6SDouglas Gregor ///
21761fb5c3a6SDouglas Gregor ///   feature-list:
2177a3feee2aSRichard Smith ///     feature ',' feature-list
2178a3feee2aSRichard Smith ///     feature
2179a3feee2aSRichard Smith ///
2180a3feee2aSRichard Smith ///   feature:
2181a3feee2aSRichard Smith ///     '!'[opt] identifier
21821fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
21831fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
21841fb5c3a6SDouglas Gregor 
21851fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
21861fb5c3a6SDouglas Gregor   consumeToken();
21871fb5c3a6SDouglas Gregor 
21881fb5c3a6SDouglas Gregor   // Parse the feature-list.
21891fb5c3a6SDouglas Gregor   do {
2190a3feee2aSRichard Smith     bool RequiredState = true;
2191a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2192a3feee2aSRichard Smith       RequiredState = false;
2193a3feee2aSRichard Smith       consumeToken();
2194a3feee2aSRichard Smith     }
2195a3feee2aSRichard Smith 
21961fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
21971fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
21981fb5c3a6SDouglas Gregor       HadError = true;
21991fb5c3a6SDouglas Gregor       return;
22001fb5c3a6SDouglas Gregor     }
22011fb5c3a6SDouglas Gregor 
22021fb5c3a6SDouglas Gregor     // Consume the feature name.
22031fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
22041fb5c3a6SDouglas Gregor     consumeToken();
22051fb5c3a6SDouglas Gregor 
22067ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
22077ff29148SBen Langmuir     bool ShouldAddRequirement =
22087ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22097ff29148SBen Langmuir 
22107ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22117ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22127ff29148SBen Langmuir 
22137ff29148SBen Langmuir     if (ShouldAddRequirement) {
22141fb5c3a6SDouglas Gregor       // Add this feature.
22157ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22167ff29148SBen Langmuir                                    *Map.Target);
22177ff29148SBen Langmuir     }
22181fb5c3a6SDouglas Gregor 
22191fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22201fb5c3a6SDouglas Gregor       break;
22211fb5c3a6SDouglas Gregor 
22221fb5c3a6SDouglas Gregor     // Consume the comma.
22231fb5c3a6SDouglas Gregor     consumeToken();
22241fb5c3a6SDouglas Gregor   } while (true);
22251fb5c3a6SDouglas Gregor }
22261fb5c3a6SDouglas Gregor 
22279fc8faf9SAdrian Prantl /// Parse a header declaration.
2228718292f2SDouglas Gregor ///
2229718292f2SDouglas Gregor ///   header-declaration:
2230306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2231202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2232202210b3SRichard Smith ///     'exclude' 'header' string-literal
2233202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2234306d8920SRichard Smith ///
2235306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2236b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2237b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2238202210b3SRichard Smith   // We've already consumed the first token.
2239202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2240202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2241202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2242202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2243202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2244202210b3SRichard Smith       LeadingToken = Tok.Kind;
22451871ed3dSBenjamin Kramer       consumeToken();
2246202210b3SRichard Smith     }
2247202210b3SRichard Smith   }
22487ff29148SBen Langmuir 
2249202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2250202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2251202210b3SRichard Smith 
22527ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22537ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22547ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22557ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22567ff29148SBen Langmuir   }
22577ff29148SBen Langmuir 
2258202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2259202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2260202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2261202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2262202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2263202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2264202210b3SRichard Smith       return;
2265202210b3SRichard Smith     }
2266202210b3SRichard Smith     consumeToken();
2267202210b3SRichard Smith   }
2268718292f2SDouglas Gregor 
2269718292f2SDouglas Gregor   // Parse the header name.
2270718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2271718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2272718292f2SDouglas Gregor       << "header";
2273718292f2SDouglas Gregor     HadError = true;
2274718292f2SDouglas Gregor     return;
2275718292f2SDouglas Gregor   }
22763c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
22770761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
22780761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
22791d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2280040e1266SRichard Smith   Header.Kind =
2281040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2282040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2283718292f2SDouglas Gregor 
2284524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
22851d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
22860761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2287524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2288322f633cSDouglas Gregor     HadError = true;
2289322f633cSDouglas Gregor     return;
2290322f633cSDouglas Gregor   }
2291322f633cSDouglas Gregor 
2292040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2293040e1266SRichard Smith   // the file.
2294040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2295040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
22963ec6663bSDouglas Gregor 
2297040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2298040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2299040e1266SRichard Smith       StringRef Str = Tok.getString();
2300040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2301040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2302040e1266SRichard Smith                   .Case("size", Size)
2303040e1266SRichard Smith                   .Case("mtime", ModTime)
2304040e1266SRichard Smith                   .Default(Unknown)) {
2305040e1266SRichard Smith       case Size:
2306040e1266SRichard Smith         if (Header.Size)
2307040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2308040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2309040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2310040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2311040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2312040e1266SRichard Smith           break;
2313040e1266SRichard Smith         }
2314040e1266SRichard Smith         Header.Size = Tok.getInteger();
2315040e1266SRichard Smith         consumeToken();
2316040e1266SRichard Smith         break;
2317040e1266SRichard Smith 
2318040e1266SRichard Smith       case ModTime:
2319040e1266SRichard Smith         if (Header.ModTime)
2320040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2321040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2322040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2323040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2324040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2325040e1266SRichard Smith           break;
2326040e1266SRichard Smith         }
2327040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2328040e1266SRichard Smith         consumeToken();
2329040e1266SRichard Smith         break;
2330040e1266SRichard Smith 
2331040e1266SRichard Smith       case Unknown:
2332040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2333040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2334040e1266SRichard Smith         break;
2335040e1266SRichard Smith       }
23363ec6663bSDouglas Gregor     }
23375257fc63SDouglas Gregor 
2338040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2339040e1266SRichard Smith       consumeToken();
2340040e1266SRichard Smith     else {
2341040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2342040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2343322f633cSDouglas Gregor       HadError = true;
2344322f633cSDouglas Gregor     }
23450101b540SHans Wennborg   }
234625d50758SRichard Smith 
23479f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23489f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23499f6020bcSBruno Cardoso Lopes 
23509f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23519f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23529f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23539f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2354718292f2SDouglas Gregor }
2355718292f2SDouglas Gregor 
235641f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
235741f81994SBen Langmuir                                 const Module::Header *B) {
235841f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
235941f81994SBen Langmuir }
236041f81994SBen Langmuir 
23619fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2362524e33e1SDouglas Gregor ///
2363524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2364524e33e1SDouglas Gregor ///     umbrella string-literal
2365524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2366524e33e1SDouglas Gregor   // Parse the directory name.
2367524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2368524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2369524e33e1SDouglas Gregor       << "umbrella";
2370524e33e1SDouglas Gregor     HadError = true;
2371524e33e1SDouglas Gregor     return;
2372524e33e1SDouglas Gregor   }
2373524e33e1SDouglas Gregor 
2374524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2375524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2376524e33e1SDouglas Gregor 
2377524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2378524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2379524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2380524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2381524e33e1SDouglas Gregor     HadError = true;
2382524e33e1SDouglas Gregor     return;
2383524e33e1SDouglas Gregor   }
2384524e33e1SDouglas Gregor 
2385524e33e1SDouglas Gregor   // Look for this file.
2386d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2387524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2388524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2389524e33e1SDouglas Gregor   else {
23902c1dd271SDylan Noblesmith     SmallString<128> PathName;
2391524e33e1SDouglas Gregor     PathName = Directory->getName();
2392524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2393524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2394524e33e1SDouglas Gregor   }
2395524e33e1SDouglas Gregor 
2396524e33e1SDouglas Gregor   if (!Dir) {
2397a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2398524e33e1SDouglas Gregor       << DirName;
2399524e33e1SDouglas Gregor     return;
2400524e33e1SDouglas Gregor   }
2401524e33e1SDouglas Gregor 
24027ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24037ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
24047ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24057ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
24067ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
24077ff29148SBen Langmuir     std::error_code EC;
24087ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2409fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2410db8a7422SDuncan P. N. Exon Smith         SourceMgr.getFileManager().getVirtualFileSystem();
2411fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24127ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
24130ae00567SSam McCall       if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
24147ff29148SBen Langmuir 
24150ae00567SSam McCall         Module::Header Header = {I->path(), FE};
24167ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24177ff29148SBen Langmuir       }
24187ff29148SBen Langmuir     }
24197ff29148SBen Langmuir 
24207ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
242141f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
242241f81994SBen Langmuir 
24237ff29148SBen Langmuir     for (auto &Header : Headers)
24247ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24257ff29148SBen Langmuir     return;
24267ff29148SBen Langmuir   }
24277ff29148SBen Langmuir 
2428524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2429524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2430524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2431524e33e1SDouglas Gregor     HadError = true;
2432524e33e1SDouglas Gregor     return;
2433524e33e1SDouglas Gregor   }
2434524e33e1SDouglas Gregor 
2435524e33e1SDouglas Gregor   // Record this umbrella directory.
24362b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2437524e33e1SDouglas Gregor }
2438524e33e1SDouglas Gregor 
24399fc8faf9SAdrian Prantl /// Parse a module export declaration.
24402b82c2a5SDouglas Gregor ///
24412b82c2a5SDouglas Gregor ///   export-declaration:
24422b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24432b82c2a5SDouglas Gregor ///
24442b82c2a5SDouglas Gregor ///   wildcard-module-id:
24452b82c2a5SDouglas Gregor ///     identifier
24462b82c2a5SDouglas Gregor ///     '*'
24472b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24482b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24492b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24502b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24512b82c2a5SDouglas Gregor 
24522b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24532b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24542b82c2a5SDouglas Gregor   bool Wildcard = false;
24552b82c2a5SDouglas Gregor   do {
2456306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24572b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
24582b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
24592b82c2a5SDouglas Gregor                                               Tok.getLocation()));
24602b82c2a5SDouglas Gregor       consumeToken();
24612b82c2a5SDouglas Gregor 
24622b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
24632b82c2a5SDouglas Gregor         consumeToken();
24642b82c2a5SDouglas Gregor         continue;
24652b82c2a5SDouglas Gregor       }
24662b82c2a5SDouglas Gregor 
24672b82c2a5SDouglas Gregor       break;
24682b82c2a5SDouglas Gregor     }
24692b82c2a5SDouglas Gregor 
24702b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
24712b82c2a5SDouglas Gregor       Wildcard = true;
2472f5eedd05SDouglas Gregor       consumeToken();
24732b82c2a5SDouglas Gregor       break;
24742b82c2a5SDouglas Gregor     }
24752b82c2a5SDouglas Gregor 
2476ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
24772b82c2a5SDouglas Gregor     HadError = true;
24782b82c2a5SDouglas Gregor     return;
24792b82c2a5SDouglas Gregor   } while (true);
24802b82c2a5SDouglas Gregor 
24812b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
24822b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
24832b82c2a5SDouglas Gregor   };
24842b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
24852b82c2a5SDouglas Gregor }
24862b82c2a5SDouglas Gregor 
24879fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2488f0b11de2SDouglas Gregor ///
2489f0b11de2SDouglas Gregor ///   export-as-declaration:
2490f0b11de2SDouglas Gregor ///     'export_as' identifier
2491f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2492f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2493f0b11de2SDouglas Gregor   consumeToken();
2494f0b11de2SDouglas Gregor 
2495f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2496f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2497f0b11de2SDouglas Gregor     HadError = true;
2498f0b11de2SDouglas Gregor     return;
2499f0b11de2SDouglas Gregor   }
2500f0b11de2SDouglas Gregor 
2501f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2502f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2503f0b11de2SDouglas Gregor     consumeToken();
2504f0b11de2SDouglas Gregor     return;
2505f0b11de2SDouglas Gregor   }
2506f0b11de2SDouglas Gregor 
2507f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2508f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2509f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2510f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2511f0b11de2SDouglas Gregor     } else {
2512f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2513f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2514f0b11de2SDouglas Gregor         << Tok.getString();
2515f0b11de2SDouglas Gregor     }
2516f0b11de2SDouglas Gregor   }
2517f0b11de2SDouglas Gregor 
2518f0b11de2SDouglas Gregor   ActiveModule->ExportAsModule = Tok.getString();
2519a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2520a3b5f71eSBruno Cardoso Lopes 
2521f0b11de2SDouglas Gregor   consumeToken();
2522f0b11de2SDouglas Gregor }
2523f0b11de2SDouglas Gregor 
25249fc8faf9SAdrian Prantl /// Parse a module use declaration.
2525ba7f2f71SDaniel Jasper ///
25268f4d3ff1SRichard Smith ///   use-declaration:
25278f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2528ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2529ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25308f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2531ba7f2f71SDaniel Jasper   // Parse the module-id.
2532ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25333cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2534ba7f2f71SDaniel Jasper 
25358f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25368f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25378f4d3ff1SRichard Smith   else
2538ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2539ba7f2f71SDaniel Jasper }
2540ba7f2f71SDaniel Jasper 
25419fc8faf9SAdrian Prantl /// Parse a link declaration.
25426ddfca91SDouglas Gregor ///
25436ddfca91SDouglas Gregor ///   module-declaration:
25446ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25456ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25466ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25476ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25486ddfca91SDouglas Gregor 
25496ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25506ddfca91SDouglas Gregor   bool IsFramework = false;
25516ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25526ddfca91SDouglas Gregor     consumeToken();
25536ddfca91SDouglas Gregor     IsFramework = true;
25546ddfca91SDouglas Gregor   }
25556ddfca91SDouglas Gregor 
25566ddfca91SDouglas Gregor   // Parse the library name
25576ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25586ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25596ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25606ddfca91SDouglas Gregor     HadError = true;
25616ddfca91SDouglas Gregor     return;
25626ddfca91SDouglas Gregor   }
25636ddfca91SDouglas Gregor 
25646ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
25656ddfca91SDouglas Gregor   consumeToken();
25666ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
25676ddfca91SDouglas Gregor                                                             IsFramework));
25686ddfca91SDouglas Gregor }
25696ddfca91SDouglas Gregor 
25709fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
257135b13eceSDouglas Gregor ///
257235b13eceSDouglas Gregor ///   module-declaration:
257335b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
257435b13eceSDouglas Gregor ///
257535b13eceSDouglas Gregor ///   config-macro-list:
257635b13eceSDouglas Gregor ///     identifier (',' identifier)?
257735b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
257835b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
257935b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
258035b13eceSDouglas Gregor 
258135b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
258235b13eceSDouglas Gregor   if (ActiveModule->Parent) {
258335b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
258435b13eceSDouglas Gregor   }
258535b13eceSDouglas Gregor 
258635b13eceSDouglas Gregor   // Parse the optional attributes.
258735b13eceSDouglas Gregor   Attributes Attrs;
25885d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
25895d29dee0SDavide Italiano     return;
25905d29dee0SDavide Italiano 
259135b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
259235b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
259335b13eceSDouglas Gregor   }
259435b13eceSDouglas Gregor 
259535b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2596306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
259735b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
259835b13eceSDouglas Gregor     return;
259935b13eceSDouglas Gregor 
260035b13eceSDouglas Gregor   // Consume the first identifier.
260135b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
260235b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
260335b13eceSDouglas Gregor   }
260435b13eceSDouglas Gregor   consumeToken();
260535b13eceSDouglas Gregor 
260635b13eceSDouglas Gregor   do {
260735b13eceSDouglas Gregor     // If there's a comma, consume it.
260835b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
260935b13eceSDouglas Gregor       break;
261035b13eceSDouglas Gregor     consumeToken();
261135b13eceSDouglas Gregor 
261235b13eceSDouglas Gregor     // We expect to see a macro name here.
2613306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
261435b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
261535b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
261635b13eceSDouglas Gregor       break;
261735b13eceSDouglas Gregor     }
261835b13eceSDouglas Gregor 
261935b13eceSDouglas Gregor     // Consume the macro name.
262035b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
262135b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
262235b13eceSDouglas Gregor     }
262335b13eceSDouglas Gregor     consumeToken();
262435b13eceSDouglas Gregor   } while (true);
262535b13eceSDouglas Gregor }
262635b13eceSDouglas Gregor 
26279fc8faf9SAdrian Prantl /// Format a module-id into a string.
2628fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2629fb912657SDouglas Gregor   std::string result;
2630fb912657SDouglas Gregor   {
2631fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2632fb912657SDouglas Gregor 
2633fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2634fb912657SDouglas Gregor       if (I)
2635fb912657SDouglas Gregor         OS << ".";
2636fb912657SDouglas Gregor       OS << Id[I].first;
2637fb912657SDouglas Gregor     }
2638fb912657SDouglas Gregor   }
2639fb912657SDouglas Gregor 
2640fb912657SDouglas Gregor   return result;
2641fb912657SDouglas Gregor }
2642fb912657SDouglas Gregor 
26439fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2644fb912657SDouglas Gregor ///
2645fb912657SDouglas Gregor ///   module-declaration:
2646fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2647fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2648fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2649fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2650fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2651fb912657SDouglas Gregor 
2652fb912657SDouglas Gregor   // Parse the module-id.
2653fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2654fb912657SDouglas Gregor     return;
2655fb912657SDouglas Gregor 
2656fb912657SDouglas Gregor   // Parse the ','.
2657fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2658fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2659fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2660fb912657SDouglas Gregor     return;
2661fb912657SDouglas Gregor   }
2662fb912657SDouglas Gregor   consumeToken();
2663fb912657SDouglas Gregor 
2664fb912657SDouglas Gregor   // Parse the message.
2665fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2666fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2667fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2668fb912657SDouglas Gregor     return;
2669fb912657SDouglas Gregor   }
2670fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2671fb912657SDouglas Gregor   consumeToken();
2672fb912657SDouglas Gregor 
2673fb912657SDouglas Gregor   // Add this unresolved conflict.
2674fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2675fb912657SDouglas Gregor }
2676fb912657SDouglas Gregor 
26779fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
26789194a91dSDouglas Gregor ///
26799194a91dSDouglas Gregor ///   module-declaration:
26809194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
26819194a91dSDouglas Gregor ///       { inferred-module-member* }
26829194a91dSDouglas Gregor ///
26839194a91dSDouglas Gregor ///   inferred-module-member:
26849194a91dSDouglas Gregor ///     'export' '*'
26859194a91dSDouglas Gregor ///     'exclude' identifier
26869194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
268773441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
268873441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
268973441091SDouglas Gregor   bool Failed = false;
269073441091SDouglas Gregor 
269173441091SDouglas Gregor   // Inferred modules must be submodules.
26929194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
269373441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
269473441091SDouglas Gregor     Failed = true;
269573441091SDouglas Gregor   }
269673441091SDouglas Gregor 
26979194a91dSDouglas Gregor   if (ActiveModule) {
2698524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
26994898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
27004898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
270173441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
270273441091SDouglas Gregor       Failed = true;
270373441091SDouglas Gregor     }
270473441091SDouglas Gregor 
270573441091SDouglas Gregor     // Check for redefinition of an inferred module.
2706dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
270773441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2708dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2709dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
271073441091SDouglas Gregor                      diag::note_mmap_prev_definition);
271173441091SDouglas Gregor       Failed = true;
271273441091SDouglas Gregor     }
271373441091SDouglas Gregor 
27149194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27159194a91dSDouglas Gregor     if (Framework) {
27169194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27179194a91dSDouglas Gregor       Framework = false;
27189194a91dSDouglas Gregor     }
27199194a91dSDouglas Gregor   } else if (Explicit) {
27209194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27219194a91dSDouglas Gregor     Explicit = false;
27229194a91dSDouglas Gregor   }
27239194a91dSDouglas Gregor 
272473441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
272573441091SDouglas Gregor   if (Failed) {
272673441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
272773441091SDouglas Gregor       consumeToken();
272873441091SDouglas Gregor       skipUntil(MMToken::RBrace);
272973441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
273073441091SDouglas Gregor         consumeToken();
273173441091SDouglas Gregor     }
273273441091SDouglas Gregor     HadError = true;
273373441091SDouglas Gregor     return;
273473441091SDouglas Gregor   }
273573441091SDouglas Gregor 
27369194a91dSDouglas Gregor   // Parse optional attributes.
27374442605fSBill Wendling   Attributes Attrs;
27385d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27395d29dee0SDavide Italiano     return;
27409194a91dSDouglas Gregor 
27419194a91dSDouglas Gregor   if (ActiveModule) {
274273441091SDouglas Gregor     // Note that we have an inferred submodule.
2743dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2744dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2745dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27469194a91dSDouglas Gregor   } else {
27479194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27489194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2749c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2750beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2751131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27529194a91dSDouglas Gregor   }
275373441091SDouglas Gregor 
275473441091SDouglas Gregor   // Parse the opening brace.
275573441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
275673441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
275773441091SDouglas Gregor     HadError = true;
275873441091SDouglas Gregor     return;
275973441091SDouglas Gregor   }
276073441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
276173441091SDouglas Gregor 
276273441091SDouglas Gregor   // Parse the body of the inferred submodule.
276373441091SDouglas Gregor   bool Done = false;
276473441091SDouglas Gregor   do {
276573441091SDouglas Gregor     switch (Tok.Kind) {
276673441091SDouglas Gregor     case MMToken::EndOfFile:
276773441091SDouglas Gregor     case MMToken::RBrace:
276873441091SDouglas Gregor       Done = true;
276973441091SDouglas Gregor       break;
277073441091SDouglas Gregor 
2771afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
27729194a91dSDouglas Gregor       if (ActiveModule) {
27739194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2774d2d442caSCraig Topper           << (ActiveModule != nullptr);
27759194a91dSDouglas Gregor         consumeToken();
27769194a91dSDouglas Gregor         break;
27779194a91dSDouglas Gregor       }
27789194a91dSDouglas Gregor 
27799194a91dSDouglas Gregor       consumeToken();
2780306d8920SRichard Smith       // FIXME: Support string-literal module names here.
27819194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
27829194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
27839194a91dSDouglas Gregor         break;
27849194a91dSDouglas Gregor       }
27859194a91dSDouglas Gregor 
27869194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
27879194a91dSDouglas Gregor         .push_back(Tok.getString());
27889194a91dSDouglas Gregor       consumeToken();
27899194a91dSDouglas Gregor       break;
27909194a91dSDouglas Gregor 
27919194a91dSDouglas Gregor     case MMToken::ExportKeyword:
27929194a91dSDouglas Gregor       if (!ActiveModule) {
27939194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2794d2d442caSCraig Topper           << (ActiveModule != nullptr);
27959194a91dSDouglas Gregor         consumeToken();
27969194a91dSDouglas Gregor         break;
27979194a91dSDouglas Gregor       }
27989194a91dSDouglas Gregor 
279973441091SDouglas Gregor       consumeToken();
280073441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2801dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
280273441091SDouglas Gregor       else
280373441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
280473441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
280573441091SDouglas Gregor       consumeToken();
280673441091SDouglas Gregor       break;
280773441091SDouglas Gregor 
280873441091SDouglas Gregor     case MMToken::ExplicitKeyword:
280973441091SDouglas Gregor     case MMToken::ModuleKeyword:
281073441091SDouglas Gregor     case MMToken::HeaderKeyword:
2811b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
281273441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
281373441091SDouglas Gregor     default:
28149194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2815d2d442caSCraig Topper           << (ActiveModule != nullptr);
281673441091SDouglas Gregor       consumeToken();
281773441091SDouglas Gregor       break;
281873441091SDouglas Gregor     }
281973441091SDouglas Gregor   } while (!Done);
282073441091SDouglas Gregor 
282173441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
282273441091SDouglas Gregor     consumeToken();
282373441091SDouglas Gregor   else {
282473441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
282573441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
282673441091SDouglas Gregor     HadError = true;
282773441091SDouglas Gregor   }
282873441091SDouglas Gregor }
282973441091SDouglas Gregor 
28309fc8faf9SAdrian Prantl /// Parse optional attributes.
28319194a91dSDouglas Gregor ///
28329194a91dSDouglas Gregor ///   attributes:
28339194a91dSDouglas Gregor ///     attribute attributes
28349194a91dSDouglas Gregor ///     attribute
28359194a91dSDouglas Gregor ///
28369194a91dSDouglas Gregor ///   attribute:
28379194a91dSDouglas Gregor ///     [ identifier ]
28389194a91dSDouglas Gregor ///
28399194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28409194a91dSDouglas Gregor ///
28419194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28424442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28439194a91dSDouglas Gregor   bool HadError = false;
28449194a91dSDouglas Gregor 
28459194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28469194a91dSDouglas Gregor     // Consume the '['.
28479194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28489194a91dSDouglas Gregor 
28499194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28509194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28519194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28529194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28539194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28549194a91dSDouglas Gregor         consumeToken();
28559194a91dSDouglas Gregor       HadError = true;
28569194a91dSDouglas Gregor     }
28579194a91dSDouglas Gregor 
28589194a91dSDouglas Gregor     // Decode the attribute name.
28599194a91dSDouglas Gregor     AttributeKind Attribute
28609194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
286135b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
286277944868SRichard Smith           .Case("extern_c", AT_extern_c)
2863ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28649194a91dSDouglas Gregor           .Case("system", AT_system)
28659194a91dSDouglas Gregor           .Default(AT_unknown);
28669194a91dSDouglas Gregor     switch (Attribute) {
28679194a91dSDouglas Gregor     case AT_unknown:
28689194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
28699194a91dSDouglas Gregor         << Tok.getString();
28709194a91dSDouglas Gregor       break;
28719194a91dSDouglas Gregor 
28729194a91dSDouglas Gregor     case AT_system:
28739194a91dSDouglas Gregor       Attrs.IsSystem = true;
28749194a91dSDouglas Gregor       break;
287535b13eceSDouglas Gregor 
287677944868SRichard Smith     case AT_extern_c:
287777944868SRichard Smith       Attrs.IsExternC = true;
287877944868SRichard Smith       break;
287977944868SRichard Smith 
288035b13eceSDouglas Gregor     case AT_exhaustive:
288135b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
288235b13eceSDouglas Gregor       break;
2883ed84df00SBruno Cardoso Lopes 
2884ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2885ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2886ed84df00SBruno Cardoso Lopes       break;
28879194a91dSDouglas Gregor     }
28889194a91dSDouglas Gregor     consumeToken();
28899194a91dSDouglas Gregor 
28909194a91dSDouglas Gregor     // Consume the ']'.
28919194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
28929194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
28939194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
28949194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28959194a91dSDouglas Gregor       HadError = true;
28969194a91dSDouglas Gregor     }
28979194a91dSDouglas Gregor 
28989194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
28999194a91dSDouglas Gregor       consumeToken();
29009194a91dSDouglas Gregor   }
29019194a91dSDouglas Gregor 
29029194a91dSDouglas Gregor   return HadError;
29039194a91dSDouglas Gregor }
29049194a91dSDouglas Gregor 
29059fc8faf9SAdrian Prantl /// Parse a module map file.
2906718292f2SDouglas Gregor ///
2907718292f2SDouglas Gregor ///   module-map-file:
2908718292f2SDouglas Gregor ///     module-declaration*
2909718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2910718292f2SDouglas Gregor   do {
2911718292f2SDouglas Gregor     switch (Tok.Kind) {
2912718292f2SDouglas Gregor     case MMToken::EndOfFile:
2913718292f2SDouglas Gregor       return HadError;
2914718292f2SDouglas Gregor 
2915e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
291697292843SDaniel Jasper     case MMToken::ExternKeyword:
2917718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2918755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2919718292f2SDouglas Gregor       parseModuleDecl();
2920718292f2SDouglas Gregor       break;
2921718292f2SDouglas Gregor 
29221fb5c3a6SDouglas Gregor     case MMToken::Comma:
292335b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2924fb912657SDouglas Gregor     case MMToken::Conflict:
2925a3feee2aSRichard Smith     case MMToken::Exclaim:
292659527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29272b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2928f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2929718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2930718292f2SDouglas Gregor     case MMToken::Identifier:
2931718292f2SDouglas Gregor     case MMToken::LBrace:
29326ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2933a686e1b0SDouglas Gregor     case MMToken::LSquare:
29342b82c2a5SDouglas Gregor     case MMToken::Period:
2935b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2936718292f2SDouglas Gregor     case MMToken::RBrace:
2937a686e1b0SDouglas Gregor     case MMToken::RSquare:
29381fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29392b82c2a5SDouglas Gregor     case MMToken::Star:
2940718292f2SDouglas Gregor     case MMToken::StringLiteral:
2941040e1266SRichard Smith     case MMToken::IntegerLiteral:
2942b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2943718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2944ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2945718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2946718292f2SDouglas Gregor       HadError = true;
2947718292f2SDouglas Gregor       consumeToken();
2948718292f2SDouglas Gregor       break;
2949718292f2SDouglas Gregor     }
2950718292f2SDouglas Gregor   } while (true);
2951718292f2SDouglas Gregor }
2952718292f2SDouglas Gregor 
29539acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2954c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29558128f332SRichard Smith                                    unsigned *Offset,
2956ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29578128f332SRichard Smith   assert(Target && "Missing target information");
29584ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29594ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29604ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29614ddf2221SDouglas Gregor     return Known->second;
29624ddf2221SDouglas Gregor 
29638128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
29648128f332SRichard Smith   if (ID.isInvalid()) {
2965f3f84616SRichard Smith     auto FileCharacter =
2966f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
29678128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
29688128f332SRichard Smith   }
29698128f332SRichard Smith 
29708128f332SRichard Smith   assert(Target && "Missing target information");
29711f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2972718292f2SDouglas Gregor   if (!Buffer)
29734ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
29748128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
29758128f332SRichard Smith          "invalid buffer offset");
2976718292f2SDouglas Gregor 
2977718292f2SDouglas Gregor   // Parse this module map file.
29788128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
29798128f332SRichard Smith           Buffer->getBufferStart(),
29808128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
29818128f332SRichard Smith           Buffer->getBufferEnd());
29822a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2983beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2984c192d194SBruno Cardoso Lopes                          IsSystem);
2985718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
29864ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
29872a6edb30SRichard Smith 
29888128f332SRichard Smith   if (Offset) {
29898128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
29908128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
29918128f332SRichard Smith     *Offset = Loc.second;
29928128f332SRichard Smith   }
29938128f332SRichard Smith 
29942a6edb30SRichard Smith   // Notify callbacks that we parsed it.
29952a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
29962a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
29978587dfd9SBruno Cardoso Lopes 
2998718292f2SDouglas Gregor   return Result;
2999718292f2SDouglas Gregor }
3000