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 * {
1828d323d15SHarlan Haskins     auto File = SourceMgr.getFileManager().getFile(Filename);
183040e1266SRichard Smith     if (!File ||
1848d323d15SHarlan Haskins         (Header.Size && (*File)->getSize() != *Header.Size) ||
1858d323d15SHarlan Haskins         (Header.ModTime && (*File)->getModificationTime() != *Header.ModTime))
186040e1266SRichard Smith       return nullptr;
1878d323d15SHarlan Haskins     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 
2320b4c2ee3SSimon Pilgrim   if (!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 {
265adcd0268SBenjamin Kramer       Module::Header H = {std::string(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)
285*fc76b4adSRichard Smith       Mod->markUnavailable(/*Unimportable=*/false);
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);
3038d323d15SHarlan Haskins   auto File = SourceMgr.getFileManager().getFile(Path);
304040e1266SRichard Smith   if (!File)
305040e1266SRichard Smith     return false;
306040e1266SRichard Smith 
307040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
308adcd0268SBenjamin Kramer   Module::Header H = {std::string(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.
4338d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
4348d323d15SHarlan Haskins       Dir = *DirEntry;
4358d323d15SHarlan Haskins     else
4368d323d15SHarlan Haskins       Dir = nullptr;
4374469138eSBen Langmuir   } while (Dir);
438afd1b1c9SEugene Zelenko   return {};
4394469138eSBen Langmuir }
4404469138eSBen Langmuir 
44192669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
44292669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4434eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44492669ee4SDaniel Jasper #ifndef NDEBUG
4454eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
44692669ee4SDaniel Jasper     // Check for consistency between the module header role
44792669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
44892669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4492708e520SRichard Smith     bool IsPrivate = false;
4502708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4514eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4524eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4532708e520SRichard Smith     for (auto *Hs : HeaderList)
4542708e520SRichard Smith       IsPrivate |=
4552708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4563c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4572708e520SRichard Smith           }) != Hs->end();
4584eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
45900bc95ecSRichard Smith   }
46092669ee4SDaniel Jasper #endif
4614eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
46292669ee4SDaniel Jasper }
46392669ee4SDaniel Jasper 
46471e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46571e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
46671e1a64fSBen Langmuir }
46771e1a64fSBen Langmuir 
46892669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4698d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
47092669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
47192669ee4SDaniel Jasper                                         StringRef Filename,
47292669ee4SDaniel Jasper                                         const FileEntry *File) {
47392669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47492669ee4SDaniel Jasper   // with no source files.
47571e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47692669ee4SDaniel Jasper     return;
47792669ee4SDaniel Jasper 
478040e1266SRichard Smith   if (RequestingModule) {
47992669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
480040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
481040e1266SRichard Smith   }
48292669ee4SDaniel Jasper 
48371e1a64fSBen Langmuir   bool Excluded = false;
484d2d442caSCraig Topper   Module *Private = nullptr;
485d2d442caSCraig Topper   Module *NotUsed = nullptr;
48671e1a64fSBen Langmuir 
48771e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
48871e1a64fSBen Langmuir   if (Known != Headers.end()) {
48971e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
49092669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4914eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
49271e1a64fSBen Langmuir         Private = Header.getModule();
49392669ee4SDaniel Jasper         continue;
49492669ee4SDaniel Jasper       }
49592669ee4SDaniel Jasper 
49692669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
49792669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
49892669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4998f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
50071e1a64fSBen Langmuir         NotUsed = Header.getModule();
50192669ee4SDaniel Jasper         continue;
50292669ee4SDaniel Jasper       }
50392669ee4SDaniel Jasper 
50492669ee4SDaniel Jasper       // We have found a module that we can happily use.
50592669ee4SDaniel Jasper       return;
50692669ee4SDaniel Jasper     }
507feb54b6dSRichard Smith 
508feb54b6dSRichard Smith     Excluded = true;
50971e1a64fSBen Langmuir   }
51092669ee4SDaniel Jasper 
51192669ee4SDaniel Jasper   // We have found a header, but it is private.
512d2d442caSCraig Topper   if (Private) {
51311152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51492669ee4SDaniel Jasper         << Filename;
51592669ee4SDaniel Jasper     return;
51692669ee4SDaniel Jasper   }
51792669ee4SDaniel Jasper 
51892669ee4SDaniel Jasper   // We have found a module, but we don't use it.
519d2d442caSCraig Topper   if (NotUsed) {
52011152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5214ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
52292669ee4SDaniel Jasper     return;
52392669ee4SDaniel Jasper   }
52492669ee4SDaniel Jasper 
52571e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
52671e1a64fSBen Langmuir     return;
52771e1a64fSBen Langmuir 
52871e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
52971e1a64fSBen Langmuir 
5305904c41eSBenjamin Kramer   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
53111152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5324ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
533a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
534a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
535a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
53671e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53771e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
53871e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
53970a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
54070a7738fSManman Ren         << File->getName();
54171e1a64fSBen Langmuir   }
54292669ee4SDaniel Jasper }
54392669ee4SDaniel Jasper 
544ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
545ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5468b7c0398SSean Silva   // Prefer available modules.
5478b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5488b7c0398SSean Silva     return true;
5498b7c0398SSean Silva 
550ec87a50aSRichard Smith   // Prefer a public header over a private header.
551ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
552ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
553ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
554ec87a50aSRichard Smith 
555ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
556ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
557ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
558ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
559ec87a50aSRichard Smith 
560ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
561ec87a50aSRichard Smith   return false;
562ec87a50aSRichard Smith }
563ec87a50aSRichard Smith 
564ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
565ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
566306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
567ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
568afd1b1c9SEugene Zelenko       return {};
569306d8920SRichard Smith     return R;
570306d8920SRichard Smith   };
571306d8920SRichard Smith 
5724881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5731fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
574202210b3SRichard Smith     ModuleMap::KnownHeader Result;
57597da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5764881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5777e82e019SRichard Smith       // Prefer a header from the source module over all others.
5787e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5792f633e7cSRichard Smith         return MakeResult(H);
5804881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5814881e8b2SSean Silva         Result = H;
58297da9178SDaniel Jasper     }
583306d8920SRichard Smith     return MakeResult(Result);
5841fb5c3a6SDouglas Gregor   }
585ab0c8a84SDouglas Gregor 
586386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
587386bb073SRichard Smith }
588386bb073SRichard Smith 
589386bb073SRichard Smith ModuleMap::KnownHeader
590386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
591386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
592386bb073SRichard Smith 
593f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5944469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5954469138eSBen Langmuir   if (H) {
5964469138eSBen Langmuir     Module *Result = H.getModule();
597930a85ccSDouglas Gregor 
598930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
59973141fa9SDouglas Gregor     // directory.
600930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
60173141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
602930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
603930a85ccSDouglas Gregor 
604930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6059d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6069d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6079d6448b1SBen Langmuir 
608a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
609a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
610a89c5ac4SDouglas Gregor       // the actual header is located.
6119458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6129458f82dSDouglas Gregor 
6137033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
614a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
615056396aeSDouglas Gregor         SmallString<32> NameBuf;
616056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6174469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6189d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6199d6448b1SBen Langmuir                                     Explicit).first;
6209d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
621ffbafa2aSBen Langmuir         Result->IsInferred = true;
622a89c5ac4SDouglas Gregor 
623a89c5ac4SDouglas Gregor         // Associate the module and the directory.
624a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
625a89c5ac4SDouglas Gregor 
626a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
627a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
628930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
629d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
630a89c5ac4SDouglas Gregor       }
631a89c5ac4SDouglas Gregor 
632a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
633056396aeSDouglas Gregor       SmallString<32> NameBuf;
634056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
635056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6369d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6379d6448b1SBen Langmuir                                   Explicit).first;
6389d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
639ffbafa2aSBen Langmuir       Result->IsInferred = true;
6403c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
641a89c5ac4SDouglas Gregor 
642a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
643a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
644930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
645d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
646a89c5ac4SDouglas Gregor     } else {
647a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
648a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
649a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
650a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
651a89c5ac4SDouglas Gregor     }
652a89c5ac4SDouglas Gregor 
653386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
654386bb073SRichard Smith     Headers[File].push_back(Header);
655386bb073SRichard Smith     return Header;
656a89c5ac4SDouglas Gregor   }
657a89c5ac4SDouglas Gregor 
658afd1b1c9SEugene Zelenko   return {};
659ab0c8a84SDouglas Gregor }
660ab0c8a84SDouglas Gregor 
661386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
662386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
663040e1266SRichard Smith   resolveHeaderDirectives(File);
664386bb073SRichard Smith   auto It = Headers.find(File);
665386bb073SRichard Smith   if (It == Headers.end())
666386bb073SRichard Smith     return None;
667386bb073SRichard Smith   return It->second;
668386bb073SRichard Smith }
669386bb073SRichard Smith 
670e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
671d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
67250996ce1SRichard Smith }
67350996ce1SRichard Smith 
67462bcd925SDmitri Gribenko bool
67562bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
67662bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
677040e1266SRichard Smith   resolveHeaderDirectives(Header);
678e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
67997da9178SDaniel Jasper   if (Known != Headers.end()) {
68097da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
68197da9178SDaniel Jasper              I = Known->second.begin(),
68297da9178SDaniel Jasper              E = Known->second.end();
68397da9178SDaniel Jasper          I != E; ++I) {
684052d95a6SBruno Cardoso Lopes 
685052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
686052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
687052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
688052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
689052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
690052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
691052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
692052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
693052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
694052d95a6SBruno Cardoso Lopes           continue;
69597da9178SDaniel Jasper         return false;
69697da9178SDaniel Jasper       }
697052d95a6SBruno Cardoso Lopes     }
69897da9178SDaniel Jasper     return true;
69997da9178SDaniel Jasper   }
7001fb5c3a6SDouglas Gregor 
7011fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
702f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7031fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7041fb5c3a6SDouglas Gregor 
70550996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
70650996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
70750996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
70850996ce1SRichard Smith   };
70950996ce1SRichard Smith 
7101fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7111fb5c3a6SDouglas Gregor   // an umbrella header.
7121fb5c3a6SDouglas Gregor   do {
713e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7141fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7151fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7161fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
71750996ce1SRichard Smith       if (IsUnavailable(Found))
7181fb5c3a6SDouglas Gregor         return true;
7191fb5c3a6SDouglas Gregor 
7201fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7211fb5c3a6SDouglas Gregor       // directory.
7221fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7231fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7241fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7251fb5c3a6SDouglas Gregor 
7261fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7271fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7281fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
729056396aeSDouglas Gregor           SmallString<32> NameBuf;
730056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
731056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
732056396aeSDouglas Gregor                              NameBuf);
7331fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7341fb5c3a6SDouglas Gregor           if (!Found)
7351fb5c3a6SDouglas Gregor             return false;
73650996ce1SRichard Smith           if (IsUnavailable(Found))
7371fb5c3a6SDouglas Gregor             return true;
7381fb5c3a6SDouglas Gregor         }
7391fb5c3a6SDouglas Gregor 
7401fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
741056396aeSDouglas Gregor         SmallString<32> NameBuf;
742056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
743056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
744056396aeSDouglas Gregor                            NameBuf);
7451fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7461fb5c3a6SDouglas Gregor         if (!Found)
7471fb5c3a6SDouglas Gregor           return false;
7481fb5c3a6SDouglas Gregor       }
7491fb5c3a6SDouglas Gregor 
75050996ce1SRichard Smith       return IsUnavailable(Found);
7511fb5c3a6SDouglas Gregor     }
7521fb5c3a6SDouglas Gregor 
7531fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7541fb5c3a6SDouglas Gregor 
7551fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7561fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7571fb5c3a6SDouglas Gregor     if (DirName.empty())
7581fb5c3a6SDouglas Gregor       break;
7591fb5c3a6SDouglas Gregor 
7601fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7618d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7628d323d15SHarlan Haskins       Dir = *DirEntry;
7638d323d15SHarlan Haskins     else
7648d323d15SHarlan Haskins       Dir = nullptr;
7651fb5c3a6SDouglas Gregor   } while (Dir);
7661fb5c3a6SDouglas Gregor 
7671fb5c3a6SDouglas Gregor   return false;
7681fb5c3a6SDouglas Gregor }
7691fb5c3a6SDouglas Gregor 
770e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
771e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
77288bdfb0eSDouglas Gregor   if (Known != Modules.end())
77388bdfb0eSDouglas Gregor     return Known->getValue();
77488bdfb0eSDouglas Gregor 
775d2d442caSCraig Topper   return nullptr;
77688bdfb0eSDouglas Gregor }
77788bdfb0eSDouglas Gregor 
778e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
779e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7802b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7812b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7822b82c2a5SDouglas Gregor       return Sub;
7832b82c2a5SDouglas Gregor   }
7842b82c2a5SDouglas Gregor 
7852b82c2a5SDouglas Gregor   return findModule(Name);
7862b82c2a5SDouglas Gregor }
7872b82c2a5SDouglas Gregor 
788e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7892b82c2a5SDouglas Gregor   if (!Context)
7902b82c2a5SDouglas Gregor     return findModule(Name);
7912b82c2a5SDouglas Gregor 
792eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7932b82c2a5SDouglas Gregor }
7942b82c2a5SDouglas Gregor 
795c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
796c192d194SBruno Cardoso Lopes                                                         Module *Parent,
797c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
798c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
79969021974SDouglas Gregor   // Try to find an existing module with this name.
800eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
801eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
80269021974SDouglas Gregor 
80369021974SDouglas Gregor   // Create a new module with this name.
8049ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8059ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
8066f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8077e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8087e82e019SRichard Smith       SourceModule = Result;
80969021974SDouglas Gregor     Modules[Name] = Result;
810c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8116f722b4eSArgyrios Kyrtzidis   }
81269021974SDouglas Gregor   return std::make_pair(Result, true);
81369021974SDouglas Gregor }
81469021974SDouglas Gregor 
815a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
816d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
817056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
818056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
819d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
820d6509cf2SRichard Smith   return PendingSubmodules.back().get();
821dd8b5337SRichard Smith }
822dd8b5337SRichard Smith 
823a5bbbfefSRichard Smith Module *
824a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
825a5bbbfefSRichard Smith                                                        SourceLocation Loc) {
826a5bbbfefSRichard Smith   auto *Result =
827a5bbbfefSRichard Smith       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
828a5bbbfefSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++);
829a5bbbfefSRichard Smith   Result->Kind = Module::PrivateModuleFragment;
830a5bbbfefSRichard Smith   return Result;
831a5bbbfefSRichard Smith }
832a5bbbfefSRichard Smith 
833bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
834dd8b5337SRichard Smith                                                 StringRef Name,
835dd8b5337SRichard Smith                                                 Module *GlobalModule) {
836bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
837bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
838bbcc9f04SRichard Smith 
839bbcc9f04SRichard Smith   auto *Result =
840bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
841bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
842145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
843bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
844bbcc9f04SRichard Smith 
845dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
846d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
847d6509cf2SRichard Smith     Submodule->setParent(Result);
848d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
849d6509cf2SRichard Smith   }
850d6509cf2SRichard Smith   PendingSubmodules.clear();
851dd8b5337SRichard Smith 
852bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
853bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
854bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
855bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
856bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
857bbcc9f04SRichard Smith 
858bbcc9f04SRichard Smith   return Result;
859bbcc9f04SRichard Smith }
860bbcc9f04SRichard Smith 
861d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
862d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
863d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
864d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
865d6509cf2SRichard Smith 
866d6509cf2SRichard Smith   auto *Result =
867d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
868d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
869d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
870d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
871d6509cf2SRichard Smith 
872d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
873d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
874d6509cf2SRichard Smith                          /*IsFramework*/ false,
875d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
876d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
877d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
878d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
879d6509cf2SRichard Smith   }
880d6509cf2SRichard Smith 
881d6509cf2SRichard Smith   return Result;
882d6509cf2SRichard Smith }
883d6509cf2SRichard Smith 
8849fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
88511dfe6feSDouglas Gregor /// should link.
88611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
88711dfe6feSDouglas Gregor                                FileManager &FileMgr) {
88811dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
88911dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
89011dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
89111dfe6feSDouglas Gregor 
89211dfe6feSDouglas Gregor   SmallString<128> LibName;
89311dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
89411dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8958aaae5a9SJuergen Ributzka 
8968aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8978aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8988aaae5a9SJuergen Ributzka   // for both before we give up.
8998013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
9008aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
90111dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
90211dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
90311dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
9048aaae5a9SJuergen Ributzka       return;
9058aaae5a9SJuergen Ributzka     }
90611dfe6feSDouglas Gregor   }
90711dfe6feSDouglas Gregor }
90811dfe6feSDouglas Gregor 
909a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
910a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
911c1d88ea5SBen Langmuir   Attributes Attrs;
912c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
913a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
914c1d88ea5SBen Langmuir }
915c1d88ea5SBen Langmuir 
916a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
917c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
918a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
919a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
920a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
921a525400dSBen Langmuir   // top-level framework.
922a525400dSBen Langmuir   StringRef FrameworkDirName =
923a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
924a525400dSBen Langmuir 
925a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
926a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
927a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
928a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
929a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
930a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
931c1d88ea5SBen Langmuir 
93256c64013SDouglas Gregor   // Check whether we've already found this module.
933e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
934e89dbc1dSDouglas Gregor     return Mod;
935e89dbc1dSDouglas Gregor 
9361f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
93756c64013SDouglas Gregor 
9389194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9399194a91dSDouglas Gregor   // a framework module, do so.
940beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9419194a91dSDouglas Gregor   if (!Parent) {
9424ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9439194a91dSDouglas Gregor     bool canInfer = false;
9444ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9459194a91dSDouglas Gregor       // Figure out the parent path.
9464ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9478d323d15SHarlan Haskins       if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9489194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9499194a91dSDouglas Gregor         // for a module map.
950e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9518d323d15SHarlan Haskins           inferred = InferredDirectories.find(*ParentDir);
9529194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9539194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9549194a91dSDouglas Gregor           // one.
955984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
956984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
9578d323d15SHarlan Haskins                 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9588d323d15SHarlan Haskins             parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9598d323d15SHarlan Haskins             inferred = InferredDirectories.find(*ParentDir);
9609194a91dSDouglas Gregor           }
9619194a91dSDouglas Gregor 
9629194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9639194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9648d323d15SHarlan Haskins                          std::make_pair(*ParentDir, InferredDirectory())).first;
9659194a91dSDouglas Gregor         }
9669194a91dSDouglas Gregor 
9679194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9689194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9699194a91dSDouglas Gregor           // to infer this particular module.
9704ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9719194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9729194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9739194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9749194a91dSDouglas Gregor 
975c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
976c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
977c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
978ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
979ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
980beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9819194a91dSDouglas Gregor         }
9829194a91dSDouglas Gregor       }
9839194a91dSDouglas Gregor     }
9849194a91dSDouglas Gregor 
9859194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9869194a91dSDouglas Gregor     if (!canInfer)
987d2d442caSCraig Topper       return nullptr;
988beee15e7SBen Langmuir   } else
9899d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9909194a91dSDouglas Gregor 
9919194a91dSDouglas Gregor 
99256c64013SDouglas Gregor   // Look for an umbrella header.
9932c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
99417381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
9958d323d15SHarlan Haskins   auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
99656c64013SDouglas Gregor 
99756c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
99856c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
99956c64013SDouglas Gregor   // idea.
100056c64013SDouglas Gregor   if (!UmbrellaHeader)
1001d2d442caSCraig Topper     return nullptr;
100256c64013SDouglas Gregor 
10039d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1004a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
1005a7e2cc68SRichard Smith                               NumCreatedModules++);
10069d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
10079d6448b1SBen Langmuir   Result->IsInferred = true;
10087e82e019SRichard Smith   if (!Parent) {
10097e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
1010ba7f2f71SDaniel Jasper       SourceModule = Result;
10117e82e019SRichard Smith     Modules[ModuleName] = Result;
1012c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1013ba7f2f71SDaniel Jasper   }
1014c1d88ea5SBen Langmuir 
1015c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
1016c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1017c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1018ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10192b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1020a686e1b0SDouglas Gregor 
1021322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
10222b63d15fSRichard Smith   //
10232b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
10242b63d15fSRichard Smith   // a framework module.
10258d323d15SHarlan Haskins   setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h");
1026d8bd7537SDouglas Gregor 
1027d8bd7537SDouglas Gregor   // export *
1028d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1029d8bd7537SDouglas Gregor 
1030a89c5ac4SDouglas Gregor   // module * { export * }
1031a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1032a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1033a89c5ac4SDouglas Gregor 
1034e89dbc1dSDouglas Gregor   // Look for subframeworks.
1035c080917eSRafael Espindola   std::error_code EC;
10362c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1037ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1038e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10392d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1040db8a7422SDuncan P. N. Exon Smith   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1041fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1042fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1043b171a59bSBruno Cardoso Lopes            DirEnd;
1044e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10450ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1046e89dbc1dSDouglas Gregor       continue;
1047f2161a70SDouglas Gregor 
10488d323d15SHarlan Haskins     if (auto SubframeworkDir =
10490ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
105007c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
105107c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
105207c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
105307c22b78SDouglas Gregor       // out to a top-level framework.
10548d323d15SHarlan Haskins       StringRef SubframeworkDirName =
10558d323d15SHarlan Haskins           FileMgr.getCanonicalName(*SubframeworkDir);
105607c22b78SDouglas Gregor       bool FoundParent = false;
105707c22b78SDouglas Gregor       do {
105807c22b78SDouglas Gregor         // Get the parent directory name.
105907c22b78SDouglas Gregor         SubframeworkDirName
106007c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
106107c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
106207c22b78SDouglas Gregor           break;
106307c22b78SDouglas Gregor 
10648d323d15SHarlan Haskins         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
10658d323d15SHarlan Haskins           if (*SubDir == FrameworkDir) {
106607c22b78SDouglas Gregor             FoundParent = true;
106707c22b78SDouglas Gregor             break;
106807c22b78SDouglas Gregor           }
10698d323d15SHarlan Haskins         }
107007c22b78SDouglas Gregor       } while (true);
107107c22b78SDouglas Gregor 
107207c22b78SDouglas Gregor       if (!FoundParent)
107307c22b78SDouglas Gregor         continue;
107407c22b78SDouglas Gregor 
1075e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
10768d323d15SHarlan Haskins       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1077e89dbc1dSDouglas Gregor     }
1078e89dbc1dSDouglas Gregor   }
1079e89dbc1dSDouglas Gregor 
108011dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
108111dfe6feSDouglas Gregor   // framework.
108211dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
108311dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
108411dfe6feSDouglas Gregor   }
108511dfe6feSDouglas Gregor 
108656c64013SDouglas Gregor   return Result;
108756c64013SDouglas Gregor }
108856c64013SDouglas Gregor 
10898587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10908587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10918587dfd9SBruno Cardoso Lopes 
10928587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10938587dfd9SBruno Cardoso Lopes   Module *Result =
10948587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10958587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10968587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
1097*fc76b4adSRichard Smith   Result->markUnavailable(/*Unimportable*/true);
1098c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10998587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
11008587dfd9SBruno Cardoso Lopes 
11018587dfd9SBruno Cardoso Lopes   return Result;
11028587dfd9SBruno Cardoso Lopes }
11038587dfd9SBruno Cardoso Lopes 
11042b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
11052b63d15fSRichard Smith                                   Twine NameAsWritten) {
110697da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
110773141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
1108bc883665SReid Kleckner   Mod->HasUmbrellaDir = false;
11092b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
11107033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1111b3a0fa48SBruno Cardoso Lopes 
1112b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1113b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1114b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1115a89c5ac4SDouglas Gregor }
1116a89c5ac4SDouglas Gregor 
11172b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
11182b63d15fSRichard Smith                                Twine NameAsWritten) {
1119524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
1120bc883665SReid Kleckner   Mod->HasUmbrellaDir = true;
11212b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1122524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1123524e33e1SDouglas Gregor }
1124524e33e1SDouglas Gregor 
1125040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11269f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11279f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1128040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1129040e1266SRichard Smith   // wrap the system header.
1130040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1131040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1132040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1133040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1134040e1266SRichard Smith     // case.
1135040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1136040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1137040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11383c1a41adSRichard Smith   }
1139040e1266SRichard Smith 
1140040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1141040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1142040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1143040e1266SRichard Smith   // headers.
1144040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1145040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1146040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1147040e1266SRichard Smith     // use the mtime as the key.
1148040e1266SRichard Smith     if (Header.ModTime)
1149040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1150040e1266SRichard Smith     else
1151040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1152040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1153040e1266SRichard Smith     return;
1154040e1266SRichard Smith   }
1155040e1266SRichard Smith 
1156040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1157040e1266SRichard Smith   // Perform the lookup now.
11589f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1159040e1266SRichard Smith }
1160040e1266SRichard Smith 
1161040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1162040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1163040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1164040e1266SRichard Smith     for (auto *M : BySize->second)
1165040e1266SRichard Smith       resolveHeaderDirectives(M);
1166040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1167040e1266SRichard Smith   }
1168040e1266SRichard Smith 
1169040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1170040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1171040e1266SRichard Smith     for (auto *M : ByModTime->second)
1172040e1266SRichard Smith       resolveHeaderDirectives(M);
1173040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1174040e1266SRichard Smith   }
1175040e1266SRichard Smith }
1176040e1266SRichard Smith 
1177040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11789f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1179040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1180040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1181040e1266SRichard Smith     // the header information for this file.
11829f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1183040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
11840e98d938SNAKAMURA Takumi }
1185202210b3SRichard Smith 
11863c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1187d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1188386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11893c1a41adSRichard Smith 
1190386bb073SRichard Smith   // Only add each header to the headers list once.
1191386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1192386bb073SRichard Smith   // same module definition?
1193386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1194386bb073SRichard Smith   for (auto H : HeaderList)
1195386bb073SRichard Smith     if (H == KH)
1196386bb073SRichard Smith       return;
1197386bb073SRichard Smith 
1198386bb073SRichard Smith   HeaderList.push_back(KH);
11991ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1200386bb073SRichard Smith 
12017e82e019SRichard Smith   bool isCompilingModuleHeader =
1202bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1203d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1204d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1205d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1206d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1207d8879c85SRichard Smith                                     isCompilingModuleHeader);
1208d8879c85SRichard Smith   }
1209e62cfd7cSBruno Cardoso Lopes 
1210e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1211e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1212f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1213a89c5ac4SDouglas Gregor }
1214a89c5ac4SDouglas Gregor 
12153c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1216feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1217feb54b6dSRichard Smith   // umbrella directory module.
1218feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1219feb54b6dSRichard Smith   // specified module?
12203c1a41adSRichard Smith   (void) Headers[Header.Entry];
12213c1a41adSRichard Smith 
12223c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1223feb54b6dSRichard Smith }
1224feb54b6dSRichard Smith 
1225514b636aSDouglas Gregor const FileEntry *
12264b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12271f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1228d2d442caSCraig Topper     return nullptr;
1229514b636aSDouglas Gregor 
12301f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12311f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1232514b636aSDouglas Gregor }
1233514b636aSDouglas Gregor 
12344b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12359d6448b1SBen Langmuir   if (M->IsInferred) {
12369d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12379d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12389d6448b1SBen Langmuir   }
12399d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12409d6448b1SBen Langmuir }
12419d6448b1SBen Langmuir 
12429d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12439d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12449d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12459d6448b1SBen Langmuir }
12469d6448b1SBen Langmuir 
1247e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1248e08464fbSReid Kleckner                                            const FileEntry *ModuleMap) {
1249e08464fbSReid Kleckner   AdditionalModMaps[M].insert(ModuleMap);
1250e08464fbSReid Kleckner }
1251e08464fbSReid Kleckner 
1252cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1253718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1254718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1255718292f2SDouglas Gregor                                         MEnd = Modules.end();
1256718292f2SDouglas Gregor        M != MEnd; ++M)
1257d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1258718292f2SDouglas Gregor 
1259718292f2SDouglas Gregor   llvm::errs() << "Headers:";
126059527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1261718292f2SDouglas Gregor        H != HEnd; ++H) {
126297da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
126397da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
126497da9178SDaniel Jasper                                                       E = H->second.end();
126597da9178SDaniel Jasper          I != E; ++I) {
126697da9178SDaniel Jasper       if (I != H->second.begin())
126797da9178SDaniel Jasper         llvm::errs() << ",";
126897da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
126997da9178SDaniel Jasper     }
127097da9178SDaniel Jasper     llvm::errs() << "\n";
1271718292f2SDouglas Gregor   }
1272718292f2SDouglas Gregor }
1273718292f2SDouglas Gregor 
12742b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
127542413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
127642413141SRichard Smith   Mod->UnresolvedExports.clear();
127742413141SRichard Smith   for (auto &UE : Unresolved) {
127842413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1279f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12802b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12812b82c2a5SDouglas Gregor     else
128242413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12832b82c2a5SDouglas Gregor   }
128442413141SRichard Smith   return !Mod->UnresolvedExports.empty();
12852b82c2a5SDouglas Gregor }
12862b82c2a5SDouglas Gregor 
1287ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
128842413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
128942413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
129042413141SRichard Smith   for (auto &UDU : Unresolved) {
129142413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1292ba7f2f71SDaniel Jasper     if (DirectUse)
1293ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1294ba7f2f71SDaniel Jasper     else
129542413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1296ba7f2f71SDaniel Jasper   }
129742413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1298ba7f2f71SDaniel Jasper }
1299ba7f2f71SDaniel Jasper 
1300fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
130142413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
130242413141SRichard Smith   Mod->UnresolvedConflicts.clear();
130342413141SRichard Smith   for (auto &UC : Unresolved) {
130442413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1305fb912657SDouglas Gregor       Module::Conflict Conflict;
1306fb912657SDouglas Gregor       Conflict.Other = OtherMod;
130742413141SRichard Smith       Conflict.Message = UC.Message;
1308fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
130942413141SRichard Smith     } else
131042413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1311fb912657SDouglas Gregor   }
131242413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1313fb912657SDouglas Gregor }
1314fb912657SDouglas Gregor 
1315718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1316718292f2SDouglas Gregor // Module map file parser
1317718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1318718292f2SDouglas Gregor 
1319718292f2SDouglas Gregor namespace clang {
1320afd1b1c9SEugene Zelenko 
13219fc8faf9SAdrian Prantl   /// A token in a module map file.
1322718292f2SDouglas Gregor   struct MMToken {
1323718292f2SDouglas Gregor     enum TokenKind {
13241fb5c3a6SDouglas Gregor       Comma,
132535b13eceSDouglas Gregor       ConfigMacros,
1326fb912657SDouglas Gregor       Conflict,
1327718292f2SDouglas Gregor       EndOfFile,
1328718292f2SDouglas Gregor       HeaderKeyword,
1329718292f2SDouglas Gregor       Identifier,
1330a3feee2aSRichard Smith       Exclaim,
133159527666SDouglas Gregor       ExcludeKeyword,
1332718292f2SDouglas Gregor       ExplicitKeyword,
13332b82c2a5SDouglas Gregor       ExportKeyword,
1334f0b11de2SDouglas Gregor       ExportAsKeyword,
133597292843SDaniel Jasper       ExternKeyword,
1336755b2055SDouglas Gregor       FrameworkKeyword,
13376ddfca91SDouglas Gregor       LinkKeyword,
1338718292f2SDouglas Gregor       ModuleKeyword,
13392b82c2a5SDouglas Gregor       Period,
1340b53e5483SLawrence Crowl       PrivateKeyword,
1341718292f2SDouglas Gregor       UmbrellaKeyword,
1342ba7f2f71SDaniel Jasper       UseKeyword,
13431fb5c3a6SDouglas Gregor       RequiresKeyword,
13442b82c2a5SDouglas Gregor       Star,
1345718292f2SDouglas Gregor       StringLiteral,
1346040e1266SRichard Smith       IntegerLiteral,
1347306d8920SRichard Smith       TextualKeyword,
1348718292f2SDouglas Gregor       LBrace,
1349a686e1b0SDouglas Gregor       RBrace,
1350a686e1b0SDouglas Gregor       LSquare,
1351a686e1b0SDouglas Gregor       RSquare
1352718292f2SDouglas Gregor     } Kind;
1353718292f2SDouglas Gregor 
1354718292f2SDouglas Gregor     unsigned Location;
1355718292f2SDouglas Gregor     unsigned StringLength;
1356040e1266SRichard Smith     union {
1357040e1266SRichard Smith       // If Kind != IntegerLiteral.
1358718292f2SDouglas Gregor       const char *StringData;
1359afd1b1c9SEugene Zelenko 
1360040e1266SRichard Smith       // If Kind == IntegerLiteral.
1361040e1266SRichard Smith       uint64_t IntegerValue;
1362040e1266SRichard Smith     };
1363718292f2SDouglas Gregor 
1364718292f2SDouglas Gregor     void clear() {
1365718292f2SDouglas Gregor       Kind = EndOfFile;
1366718292f2SDouglas Gregor       Location = 0;
1367718292f2SDouglas Gregor       StringLength = 0;
1368d2d442caSCraig Topper       StringData = nullptr;
1369718292f2SDouglas Gregor     }
1370718292f2SDouglas Gregor 
1371718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1372718292f2SDouglas Gregor 
1373718292f2SDouglas Gregor     SourceLocation getLocation() const {
1374718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1375718292f2SDouglas Gregor     }
1376718292f2SDouglas Gregor 
1377040e1266SRichard Smith     uint64_t getInteger() const {
1378040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1379040e1266SRichard Smith     }
1380040e1266SRichard Smith 
1381718292f2SDouglas Gregor     StringRef getString() const {
1382040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1383040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1384718292f2SDouglas Gregor     }
1385718292f2SDouglas Gregor   };
1386718292f2SDouglas Gregor 
1387718292f2SDouglas Gregor   class ModuleMapParser {
1388718292f2SDouglas Gregor     Lexer &L;
1389718292f2SDouglas Gregor     SourceManager &SourceMgr;
1390bc10b9fbSDouglas Gregor 
13919fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1392bc10b9fbSDouglas Gregor     /// parsing.
1393bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1394bc10b9fbSDouglas Gregor 
1395718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1396718292f2SDouglas Gregor     ModuleMap &Map;
1397718292f2SDouglas Gregor 
13989fc8faf9SAdrian Prantl     /// The current module map file.
1399beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1400beee15e7SBen Langmuir 
14019f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
14029f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
14039f6020bcSBruno Cardoso Lopes 
14049fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
14059acb99e3SRichard Smith     /// be resolved relative to.
14065257fc63SDouglas Gregor     const DirectoryEntry *Directory;
14075257fc63SDouglas Gregor 
14089fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1409963c5535SDouglas Gregor     bool IsSystem;
1410963c5535SDouglas Gregor 
14119fc8faf9SAdrian Prantl     /// Whether an error occurred.
1412afd1b1c9SEugene Zelenko     bool HadError = false;
1413718292f2SDouglas Gregor 
14149fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1415718292f2SDouglas Gregor     /// during parsing.
1416718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1417718292f2SDouglas Gregor 
14189fc8faf9SAdrian Prantl     /// The current token.
1419718292f2SDouglas Gregor     MMToken Tok;
1420718292f2SDouglas Gregor 
14219fc8faf9SAdrian Prantl     /// The active module.
1422afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1423718292f2SDouglas Gregor 
14249fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
14257ff29148SBen Langmuir     /// contents as 'textual'.
14267ff29148SBen Langmuir     ///
14277ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14287ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14297ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14307ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14317ff29148SBen Langmuir     /// 'textual' to match the original intent.
14327ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14337ff29148SBen Langmuir 
14349fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1435718292f2SDouglas Gregor     SourceLocation consumeToken();
1436718292f2SDouglas Gregor 
14379fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1438718292f2SDouglas Gregor     /// (or the end of the file).
1439718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1440718292f2SDouglas Gregor 
1441afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1442afd1b1c9SEugene Zelenko 
1443e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1444718292f2SDouglas Gregor     void parseModuleDecl();
144597292843SDaniel Jasper     void parseExternModuleDecl();
14461fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1447afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1448524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14492b82c2a5SDouglas Gregor     void parseExportDecl();
1450f0b11de2SDouglas Gregor     void parseExportAsDecl();
1451ba7f2f71SDaniel Jasper     void parseUseDecl();
14526ddfca91SDouglas Gregor     void parseLinkDecl();
145335b13eceSDouglas Gregor     void parseConfigMacros();
1454fb912657SDouglas Gregor     void parseConflict();
14559194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1456c1d88ea5SBen Langmuir 
14575f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14585f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14595f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14605f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14615f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14625f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14635f11e128SBruno Cardoso Lopes 
1464afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1465afd1b1c9SEugene Zelenko 
14664442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1467718292f2SDouglas Gregor 
1468718292f2SDouglas Gregor   public:
1469718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14708587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14718587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1472c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1473bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1474beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1475c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1476718292f2SDouglas Gregor       Tok.clear();
1477718292f2SDouglas Gregor       consumeToken();
1478718292f2SDouglas Gregor     }
1479718292f2SDouglas Gregor 
1480718292f2SDouglas Gregor     bool parseModuleMapFile();
14818128f332SRichard Smith 
14828128f332SRichard Smith     bool terminatedByDirective() { return false; }
14838128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1484718292f2SDouglas Gregor   };
1485afd1b1c9SEugene Zelenko 
1486afd1b1c9SEugene Zelenko } // namespace clang
1487718292f2SDouglas Gregor 
1488718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1489718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1490718292f2SDouglas Gregor 
14918128f332SRichard Smith retry:
14928128f332SRichard Smith   Tok.clear();
1493718292f2SDouglas Gregor   Token LToken;
1494718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1495718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1496718292f2SDouglas Gregor   switch (LToken.getKind()) {
14972d57cea2SAlp Toker   case tok::raw_identifier: {
14982d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
14992d57cea2SAlp Toker     Tok.StringData = RI.data();
15002d57cea2SAlp Toker     Tok.StringLength = RI.size();
15012d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
150235b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1503fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
150459527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1505718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
15062b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1507f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
150897292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1509755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
151035b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
15116ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1512718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1513b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
15141fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1515306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1516718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1517ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1518718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1519718292f2SDouglas Gregor     break;
15202d57cea2SAlp Toker   }
1521718292f2SDouglas Gregor 
15221fb5c3a6SDouglas Gregor   case tok::comma:
15231fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
15241fb5c3a6SDouglas Gregor     break;
15251fb5c3a6SDouglas Gregor 
1526718292f2SDouglas Gregor   case tok::eof:
1527718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1528718292f2SDouglas Gregor     break;
1529718292f2SDouglas Gregor 
1530718292f2SDouglas Gregor   case tok::l_brace:
1531718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1532718292f2SDouglas Gregor     break;
1533718292f2SDouglas Gregor 
1534a686e1b0SDouglas Gregor   case tok::l_square:
1535a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1536a686e1b0SDouglas Gregor     break;
1537a686e1b0SDouglas Gregor 
15382b82c2a5SDouglas Gregor   case tok::period:
15392b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15402b82c2a5SDouglas Gregor     break;
15412b82c2a5SDouglas Gregor 
1542718292f2SDouglas Gregor   case tok::r_brace:
1543718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1544718292f2SDouglas Gregor     break;
1545718292f2SDouglas Gregor 
1546a686e1b0SDouglas Gregor   case tok::r_square:
1547a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1548a686e1b0SDouglas Gregor     break;
1549a686e1b0SDouglas Gregor 
15502b82c2a5SDouglas Gregor   case tok::star:
15512b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15522b82c2a5SDouglas Gregor     break;
15532b82c2a5SDouglas Gregor 
1554a3feee2aSRichard Smith   case tok::exclaim:
1555a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1556a3feee2aSRichard Smith     break;
1557a3feee2aSRichard Smith 
1558718292f2SDouglas Gregor   case tok::string_literal: {
1559d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1560d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1561d67aea28SRichard Smith       HadError = true;
1562d67aea28SRichard Smith       goto retry;
1563d67aea28SRichard Smith     }
1564d67aea28SRichard Smith 
1565718292f2SDouglas Gregor     // Parse the string literal.
1566718292f2SDouglas Gregor     LangOptions LangOpts;
15679d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1568718292f2SDouglas Gregor     if (StringLiteral.hadError)
1569718292f2SDouglas Gregor       goto retry;
1570718292f2SDouglas Gregor 
1571718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1572718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1573718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1574718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1575718292f2SDouglas Gregor     Saved[Length] = 0;
1576718292f2SDouglas Gregor 
1577718292f2SDouglas Gregor     // Form the token.
1578718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1579718292f2SDouglas Gregor     Tok.StringData = Saved;
1580718292f2SDouglas Gregor     Tok.StringLength = Length;
1581718292f2SDouglas Gregor     break;
1582718292f2SDouglas Gregor   }
1583718292f2SDouglas Gregor 
1584040e1266SRichard Smith   case tok::numeric_constant: {
1585040e1266SRichard Smith     // We don't support any suffixes or other complications.
1586040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1587040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1588040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1589040e1266SRichard Smith     unsigned Length =
1590040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1591040e1266SRichard Smith     uint64_t Value;
1592040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1593040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1594040e1266SRichard Smith       HadError = true;
1595040e1266SRichard Smith       goto retry;
1596040e1266SRichard Smith     }
1597040e1266SRichard Smith 
1598040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1599040e1266SRichard Smith     Tok.IntegerValue = Value;
1600040e1266SRichard Smith     break;
1601040e1266SRichard Smith   }
1602040e1266SRichard Smith 
1603718292f2SDouglas Gregor   case tok::comment:
1604718292f2SDouglas Gregor     goto retry;
1605718292f2SDouglas Gregor 
16068128f332SRichard Smith   case tok::hash:
16078128f332SRichard Smith     // A module map can be terminated prematurely by
16088128f332SRichard Smith     //   #pragma clang module contents
16098128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
16108128f332SRichard Smith     // contents of the module.
16118128f332SRichard Smith     {
16128128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
16138128f332SRichard Smith         L.LexFromRawLexer(LToken);
16148128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16158128f332SRichard Smith                LToken.getRawIdentifier() == Str;
16168128f332SRichard Smith       };
16178128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16188128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
16198128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
16208128f332SRichard Smith         break;
16218128f332SRichard Smith       }
16228128f332SRichard Smith     }
16238128f332SRichard Smith     LLVM_FALLTHROUGH;
16248128f332SRichard Smith 
1625718292f2SDouglas Gregor   default:
16268128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1627718292f2SDouglas Gregor     HadError = true;
1628718292f2SDouglas Gregor     goto retry;
1629718292f2SDouglas Gregor   }
1630718292f2SDouglas Gregor 
1631718292f2SDouglas Gregor   return Result;
1632718292f2SDouglas Gregor }
1633718292f2SDouglas Gregor 
1634718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1635718292f2SDouglas Gregor   unsigned braceDepth = 0;
1636a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1637718292f2SDouglas Gregor   do {
1638718292f2SDouglas Gregor     switch (Tok.Kind) {
1639718292f2SDouglas Gregor     case MMToken::EndOfFile:
1640718292f2SDouglas Gregor       return;
1641718292f2SDouglas Gregor 
1642718292f2SDouglas Gregor     case MMToken::LBrace:
1643a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1644718292f2SDouglas Gregor         return;
1645718292f2SDouglas Gregor 
1646718292f2SDouglas Gregor       ++braceDepth;
1647718292f2SDouglas Gregor       break;
1648718292f2SDouglas Gregor 
1649a686e1b0SDouglas Gregor     case MMToken::LSquare:
1650a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1651a686e1b0SDouglas Gregor         return;
1652a686e1b0SDouglas Gregor 
1653a686e1b0SDouglas Gregor       ++squareDepth;
1654a686e1b0SDouglas Gregor       break;
1655a686e1b0SDouglas Gregor 
1656718292f2SDouglas Gregor     case MMToken::RBrace:
1657718292f2SDouglas Gregor       if (braceDepth > 0)
1658718292f2SDouglas Gregor         --braceDepth;
1659718292f2SDouglas Gregor       else if (Tok.is(K))
1660718292f2SDouglas Gregor         return;
1661718292f2SDouglas Gregor       break;
1662718292f2SDouglas Gregor 
1663a686e1b0SDouglas Gregor     case MMToken::RSquare:
1664a686e1b0SDouglas Gregor       if (squareDepth > 0)
1665a686e1b0SDouglas Gregor         --squareDepth;
1666a686e1b0SDouglas Gregor       else if (Tok.is(K))
1667a686e1b0SDouglas Gregor         return;
1668a686e1b0SDouglas Gregor       break;
1669a686e1b0SDouglas Gregor 
1670718292f2SDouglas Gregor     default:
1671a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1672718292f2SDouglas Gregor         return;
1673718292f2SDouglas Gregor       break;
1674718292f2SDouglas Gregor     }
1675718292f2SDouglas Gregor 
1676718292f2SDouglas Gregor    consumeToken();
1677718292f2SDouglas Gregor   } while (true);
1678718292f2SDouglas Gregor }
1679718292f2SDouglas Gregor 
16809fc8faf9SAdrian Prantl /// Parse a module-id.
1681e7ab3669SDouglas Gregor ///
1682e7ab3669SDouglas Gregor ///   module-id:
1683e7ab3669SDouglas Gregor ///     identifier
1684e7ab3669SDouglas Gregor ///     identifier '.' module-id
1685e7ab3669SDouglas Gregor ///
1686e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1687e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1688e7ab3669SDouglas Gregor   Id.clear();
1689e7ab3669SDouglas Gregor   do {
16903cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1691adcd0268SBenjamin Kramer       Id.push_back(
1692adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1693e7ab3669SDouglas Gregor       consumeToken();
1694e7ab3669SDouglas Gregor     } else {
1695e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1696e7ab3669SDouglas Gregor       return true;
1697e7ab3669SDouglas Gregor     }
1698e7ab3669SDouglas Gregor 
1699e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1700e7ab3669SDouglas Gregor       break;
1701e7ab3669SDouglas Gregor 
1702e7ab3669SDouglas Gregor     consumeToken();
1703e7ab3669SDouglas Gregor   } while (true);
1704e7ab3669SDouglas Gregor 
1705e7ab3669SDouglas Gregor   return false;
1706e7ab3669SDouglas Gregor }
1707e7ab3669SDouglas Gregor 
1708a686e1b0SDouglas Gregor namespace {
1709afd1b1c9SEugene Zelenko 
17109fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1711a686e1b0SDouglas Gregor   enum AttributeKind {
17129fc8faf9SAdrian Prantl     /// An unknown attribute.
1713a686e1b0SDouglas Gregor     AT_unknown,
1714afd1b1c9SEugene Zelenko 
17159fc8faf9SAdrian Prantl     /// The 'system' attribute.
171635b13eceSDouglas Gregor     AT_system,
1717afd1b1c9SEugene Zelenko 
17189fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
171977944868SRichard Smith     AT_extern_c,
1720afd1b1c9SEugene Zelenko 
17219fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1722ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1723afd1b1c9SEugene Zelenko 
17249fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1725ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1726a686e1b0SDouglas Gregor   };
1727afd1b1c9SEugene Zelenko 
1728afd1b1c9SEugene Zelenko } // namespace
1729a686e1b0SDouglas Gregor 
173029729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
173129729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
173229729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
173329729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17345f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17355f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
173629729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17377d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
173829729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
173929729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
174029729919SBruno Cardoso Lopes     D << BadName << M->Name;
17417d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
174229729919SBruno Cardoso Lopes   };
174329729919SBruno Cardoso Lopes 
174429729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
174529729919SBruno Cardoso Lopes     auto const *M = E->getValue();
174629729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
174729729919SBruno Cardoso Lopes       continue;
174829729919SBruno Cardoso Lopes 
174929729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
175029729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
175129729919SBruno Cardoso Lopes       continue;
17525f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
175329729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
175429729919SBruno Cardoso Lopes     Canonical.append("_Private");
175529729919SBruno Cardoso Lopes 
175629729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
175729729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
175829729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
175929729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
176029729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
176129729919SBruno Cardoso Lopes           << FullName;
17625f11e128SBruno Cardoso Lopes 
17635f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17645f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17655f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17665f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17675f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17685f11e128SBruno Cardoso Lopes 
17695f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17705f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17715f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17725f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
17735f11e128SBruno Cardoso Lopes 
17745f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17755f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
177629729919SBruno Cardoso Lopes       continue;
177729729919SBruno Cardoso Lopes     }
177829729919SBruno Cardoso Lopes 
177929729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
178029729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
178129729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
178229729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
178329729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
178429729919SBruno Cardoso Lopes           << ActiveModule->Name;
17857d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
17867d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
178729729919SBruno Cardoso Lopes     }
178829729919SBruno Cardoso Lopes   }
178929729919SBruno Cardoso Lopes }
179029729919SBruno Cardoso Lopes 
17919fc8faf9SAdrian Prantl /// Parse a module declaration.
1792718292f2SDouglas Gregor ///
1793718292f2SDouglas Gregor ///   module-declaration:
179497292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1795a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1796a686e1b0SDouglas Gregor ///       { module-member* }
1797a686e1b0SDouglas Gregor ///
1798718292f2SDouglas Gregor ///   module-member:
17991fb5c3a6SDouglas Gregor ///     requires-declaration
1800718292f2SDouglas Gregor ///     header-declaration
1801e7ab3669SDouglas Gregor ///     submodule-declaration
18022b82c2a5SDouglas Gregor ///     export-declaration
1803f0b11de2SDouglas Gregor ///     export-as-declaration
18046ddfca91SDouglas Gregor ///     link-declaration
180573441091SDouglas Gregor ///
180673441091SDouglas Gregor ///   submodule-declaration:
180773441091SDouglas Gregor ///     module-declaration
180873441091SDouglas Gregor ///     inferred-submodule-declaration
1809718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1810755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
181197292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
181297292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
181397292843SDaniel Jasper     parseExternModuleDecl();
181497292843SDaniel Jasper     return;
181597292843SDaniel Jasper   }
181697292843SDaniel Jasper 
1817f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1818e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
18195f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1820718292f2SDouglas Gregor   bool Explicit = false;
1821f2161a70SDouglas Gregor   bool Framework = false;
1822755b2055SDouglas Gregor 
1823f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1824f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1825e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1826f2161a70SDouglas Gregor     Explicit = true;
1827f2161a70SDouglas Gregor   }
1828f2161a70SDouglas Gregor 
1829f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1830755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18315f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1832755b2055SDouglas Gregor     Framework = true;
1833755b2055SDouglas Gregor   }
1834718292f2SDouglas Gregor 
1835718292f2SDouglas Gregor   // Parse 'module' keyword.
1836718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1837d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1838718292f2SDouglas Gregor     consumeToken();
1839718292f2SDouglas Gregor     HadError = true;
1840718292f2SDouglas Gregor     return;
1841718292f2SDouglas Gregor   }
18429f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1843718292f2SDouglas Gregor 
184473441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
184573441091SDouglas Gregor   // Parse it.
184673441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18479194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
184873441091SDouglas Gregor 
1849718292f2SDouglas Gregor   // Parse the module name.
1850e7ab3669SDouglas Gregor   ModuleId Id;
1851e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1852718292f2SDouglas Gregor     HadError = true;
1853718292f2SDouglas Gregor     return;
1854718292f2SDouglas Gregor   }
1855e7ab3669SDouglas Gregor 
1856e7ab3669SDouglas Gregor   if (ActiveModule) {
1857e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1858e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1859e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1860e7ab3669SDouglas Gregor 
1861e7ab3669SDouglas Gregor       HadError = true;
1862e7ab3669SDouglas Gregor       return;
1863e7ab3669SDouglas Gregor     }
1864e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1865e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1866e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1867e7ab3669SDouglas Gregor     Explicit = false;
1868e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1869e7ab3669SDouglas Gregor     HadError = true;
1870e7ab3669SDouglas Gregor   }
1871e7ab3669SDouglas Gregor 
1872e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1873e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1874e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1875e7ab3669SDouglas Gregor     // is a submodule.
1876d2d442caSCraig Topper     ActiveModule = nullptr;
18774b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1878e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1879e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
18804b8a9e95SBen Langmuir         if (I == 0)
18814b8a9e95SBen Langmuir           TopLevelModule = Next;
1882e7ab3669SDouglas Gregor         ActiveModule = Next;
1883e7ab3669SDouglas Gregor         continue;
1884e7ab3669SDouglas Gregor       }
1885e7ab3669SDouglas Gregor 
1886e7ab3669SDouglas Gregor       if (ActiveModule) {
1887e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
18885b5d21eaSRichard Smith           << Id[I].first
18895b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1890e7ab3669SDouglas Gregor       } else {
1891e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1892e7ab3669SDouglas Gregor       }
1893e7ab3669SDouglas Gregor       HadError = true;
1894e7ab3669SDouglas Gregor       return;
1895e7ab3669SDouglas Gregor     }
18964b8a9e95SBen Langmuir 
18974b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
18984b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
18994b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
19004b8a9e95SBen Langmuir              "top-level module");
19014b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19024b8a9e95SBen Langmuir     }
1903e7ab3669SDouglas Gregor   }
1904e7ab3669SDouglas Gregor 
1905e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1906e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1907718292f2SDouglas Gregor 
1908a686e1b0SDouglas Gregor   // Parse the optional attribute list.
19094442605fSBill Wendling   Attributes Attrs;
19105d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
19115d29dee0SDavide Italiano     return;
19125d29dee0SDavide Italiano 
1913718292f2SDouglas Gregor   // Parse the opening brace.
1914718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1915718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1916718292f2SDouglas Gregor       << ModuleName;
1917718292f2SDouglas Gregor     HadError = true;
1918718292f2SDouglas Gregor     return;
1919718292f2SDouglas Gregor   }
1920718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1921718292f2SDouglas Gregor 
1922718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
19238587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1924eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19254a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
19264a3751ffSRichard Smith     // definition for in two cases:
19274a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19284a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19294a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19304a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19314a3751ffSRichard Smith     //    module map file from which it was created.
19324a3751ffSRichard Smith     bool ParsedAsMainInput =
19334a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19344a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19354a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19364a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19374a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1938fcc54a3bSDouglas Gregor       // Skip the module definition.
1939fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1940fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1941fcc54a3bSDouglas Gregor         consumeToken();
1942fcc54a3bSDouglas Gregor       else {
1943fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1944fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1945fcc54a3bSDouglas Gregor         HadError = true;
1946fcc54a3bSDouglas Gregor       }
1947fcc54a3bSDouglas Gregor       return;
1948fcc54a3bSDouglas Gregor     }
1949fcc54a3bSDouglas Gregor 
1950c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19518587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19528587dfd9SBruno Cardoso Lopes     } else {
19538587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1954718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1955718292f2SDouglas Gregor           << ModuleName;
1956eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1957718292f2SDouglas Gregor 
1958718292f2SDouglas Gregor       // Skip the module definition.
1959718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1960718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1961718292f2SDouglas Gregor         consumeToken();
1962718292f2SDouglas Gregor 
1963718292f2SDouglas Gregor       HadError = true;
1964718292f2SDouglas Gregor       return;
1965718292f2SDouglas Gregor     }
19668587dfd9SBruno Cardoso Lopes   }
1967718292f2SDouglas Gregor 
1968718292f2SDouglas Gregor   // Start defining this module.
19698587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19708587dfd9SBruno Cardoso Lopes     ActiveModule =
19718587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19728587dfd9SBruno Cardoso Lopes   } else {
1973c192d194SBruno Cardoso Lopes     ActiveModule =
1974c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19758587dfd9SBruno Cardoso Lopes             .first;
19768587dfd9SBruno Cardoso Lopes   }
19778587dfd9SBruno Cardoso Lopes 
1978eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1979963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1980a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
198177944868SRichard Smith   if (Attrs.IsExternC)
198277944868SRichard Smith     ActiveModule->IsExternC = true;
1983ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1984ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1985ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
19863c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1987718292f2SDouglas Gregor 
198890b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
198990b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
199090b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
199190b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
199290b0a1fcSJordan Rose   }
199329729919SBruno Cardoso Lopes 
199429729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
199529729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
199629729919SBruno Cardoso Lopes   // Foo_Private instead.
199729729919SBruno Cardoso Lopes   SourceLocation StartLoc =
199829729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
199929729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
200029729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
200129729919SBruno Cardoso Lopes                        StartLoc) &&
200229729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
200329729919SBruno Cardoso Lopes                        StartLoc) &&
200490b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
20055f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20064d867640SGraydon Hoare 
2007718292f2SDouglas Gregor   bool Done = false;
2008718292f2SDouglas Gregor   do {
2009718292f2SDouglas Gregor     switch (Tok.Kind) {
2010718292f2SDouglas Gregor     case MMToken::EndOfFile:
2011718292f2SDouglas Gregor     case MMToken::RBrace:
2012718292f2SDouglas Gregor       Done = true;
2013718292f2SDouglas Gregor       break;
2014718292f2SDouglas Gregor 
201535b13eceSDouglas Gregor     case MMToken::ConfigMacros:
201635b13eceSDouglas Gregor       parseConfigMacros();
201735b13eceSDouglas Gregor       break;
201835b13eceSDouglas Gregor 
2019fb912657SDouglas Gregor     case MMToken::Conflict:
2020fb912657SDouglas Gregor       parseConflict();
2021fb912657SDouglas Gregor       break;
2022fb912657SDouglas Gregor 
2023718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
202497292843SDaniel Jasper     case MMToken::ExternKeyword:
2025f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
2026718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2027718292f2SDouglas Gregor       parseModuleDecl();
2028718292f2SDouglas Gregor       break;
2029718292f2SDouglas Gregor 
20302b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20312b82c2a5SDouglas Gregor       parseExportDecl();
20322b82c2a5SDouglas Gregor       break;
20332b82c2a5SDouglas Gregor 
2034f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2035f0b11de2SDouglas Gregor       parseExportAsDecl();
2036f0b11de2SDouglas Gregor       break;
2037f0b11de2SDouglas Gregor 
2038ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2039ba7f2f71SDaniel Jasper       parseUseDecl();
2040ba7f2f71SDaniel Jasper       break;
2041ba7f2f71SDaniel Jasper 
20421fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20431fb5c3a6SDouglas Gregor       parseRequiresDecl();
20441fb5c3a6SDouglas Gregor       break;
20451fb5c3a6SDouglas Gregor 
2046202210b3SRichard Smith     case MMToken::TextualKeyword:
2047202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2048306d8920SRichard Smith       break;
2049306d8920SRichard Smith 
2050524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2051524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2052524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2053b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2054524e33e1SDouglas Gregor       else
2055524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2056718292f2SDouglas Gregor       break;
2057524e33e1SDouglas Gregor     }
2058718292f2SDouglas Gregor 
2059202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2060202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
206159527666SDouglas Gregor       break;
206259527666SDouglas Gregor 
2063202210b3SRichard Smith     case MMToken::PrivateKeyword:
2064202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2065b53e5483SLawrence Crowl       break;
2066b53e5483SLawrence Crowl 
2067322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2068202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2069718292f2SDouglas Gregor       break;
2070718292f2SDouglas Gregor 
20716ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20726ddfca91SDouglas Gregor       parseLinkDecl();
20736ddfca91SDouglas Gregor       break;
20746ddfca91SDouglas Gregor 
2075718292f2SDouglas Gregor     default:
2076718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2077718292f2SDouglas Gregor       consumeToken();
2078718292f2SDouglas Gregor       break;
2079718292f2SDouglas Gregor     }
2080718292f2SDouglas Gregor   } while (!Done);
2081718292f2SDouglas Gregor 
2082718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2083718292f2SDouglas Gregor     consumeToken();
2084718292f2SDouglas Gregor   else {
2085718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2086718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2087718292f2SDouglas Gregor     HadError = true;
2088718292f2SDouglas Gregor   }
2089718292f2SDouglas Gregor 
209011dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
209111dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
209211dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
209311dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
209411dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
209511dfe6feSDouglas Gregor   }
209611dfe6feSDouglas Gregor 
2097ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2098ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2099*fc76b4adSRichard Smith   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2100ec8c9752SBen Langmuir       ActiveModule->Parent) {
2101*fc76b4adSRichard Smith     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2102ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2103ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2104ec8c9752SBen Langmuir   }
2105ec8c9752SBen Langmuir 
2106e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2107e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2108718292f2SDouglas Gregor }
2109718292f2SDouglas Gregor 
21109fc8faf9SAdrian Prantl /// Parse an extern module declaration.
211197292843SDaniel Jasper ///
211297292843SDaniel Jasper ///   extern module-declaration:
211397292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
211497292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
211597292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2116ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
211797292843SDaniel Jasper 
211897292843SDaniel Jasper   // Parse 'module' keyword.
211997292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
212097292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
212197292843SDaniel Jasper     consumeToken();
212297292843SDaniel Jasper     HadError = true;
212397292843SDaniel Jasper     return;
212497292843SDaniel Jasper   }
212597292843SDaniel Jasper   consumeToken(); // 'module' keyword
212697292843SDaniel Jasper 
212797292843SDaniel Jasper   // Parse the module name.
212897292843SDaniel Jasper   ModuleId Id;
212997292843SDaniel Jasper   if (parseModuleId(Id)) {
213097292843SDaniel Jasper     HadError = true;
213197292843SDaniel Jasper     return;
213297292843SDaniel Jasper   }
213397292843SDaniel Jasper 
213497292843SDaniel Jasper   // Parse the referenced module map file name.
213597292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
213697292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
213797292843SDaniel Jasper     HadError = true;
213897292843SDaniel Jasper     return;
213997292843SDaniel Jasper   }
2140adcd0268SBenjamin Kramer   std::string FileName = std::string(Tok.getString());
214197292843SDaniel Jasper   consumeToken(); // filename
214297292843SDaniel Jasper 
214397292843SDaniel Jasper   StringRef FileNameRef = FileName;
214497292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
214597292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
214697292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
214797292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
214892e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
214997292843SDaniel Jasper   }
21508d323d15SHarlan Haskins   if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21519acb99e3SRichard Smith     Map.parseModuleMapFile(
21528d323d15SHarlan Haskins         *File, /*IsSystem=*/false,
21539acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21549acb99e3SRichard Smith             ? Directory
21558d323d15SHarlan Haskins             : (*File)->getDir(),
2156c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
215797292843SDaniel Jasper }
215897292843SDaniel Jasper 
21597ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21607ff29148SBen Langmuir ///
21617ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21627ff29148SBen Langmuir /// module map files:
21637ff29148SBen Langmuir ///
21647ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21657ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21667ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21677ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21687ff29148SBen Langmuir ///    module to 'textual'.
21697ff29148SBen Langmuir ///
21707ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21717ff29148SBen Langmuir ///
21727ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21737ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21747ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21757ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21768013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21778013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21788013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21797ff29148SBen Langmuir     IsRequiresExcludedHack = true;
21807ff29148SBen Langmuir     return false;
21818013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21827ff29148SBen Langmuir     return false;
21837ff29148SBen Langmuir   }
21847ff29148SBen Langmuir 
21857ff29148SBen Langmuir   return true;
21867ff29148SBen Langmuir }
21877ff29148SBen Langmuir 
21889fc8faf9SAdrian Prantl /// Parse a requires declaration.
21891fb5c3a6SDouglas Gregor ///
21901fb5c3a6SDouglas Gregor ///   requires-declaration:
21911fb5c3a6SDouglas Gregor ///     'requires' feature-list
21921fb5c3a6SDouglas Gregor ///
21931fb5c3a6SDouglas Gregor ///   feature-list:
2194a3feee2aSRichard Smith ///     feature ',' feature-list
2195a3feee2aSRichard Smith ///     feature
2196a3feee2aSRichard Smith ///
2197a3feee2aSRichard Smith ///   feature:
2198a3feee2aSRichard Smith ///     '!'[opt] identifier
21991fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
22001fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
22011fb5c3a6SDouglas Gregor 
22021fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
22031fb5c3a6SDouglas Gregor   consumeToken();
22041fb5c3a6SDouglas Gregor 
22051fb5c3a6SDouglas Gregor   // Parse the feature-list.
22061fb5c3a6SDouglas Gregor   do {
2207a3feee2aSRichard Smith     bool RequiredState = true;
2208a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2209a3feee2aSRichard Smith       RequiredState = false;
2210a3feee2aSRichard Smith       consumeToken();
2211a3feee2aSRichard Smith     }
2212a3feee2aSRichard Smith 
22131fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
22141fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22151fb5c3a6SDouglas Gregor       HadError = true;
22161fb5c3a6SDouglas Gregor       return;
22171fb5c3a6SDouglas Gregor     }
22181fb5c3a6SDouglas Gregor 
22191fb5c3a6SDouglas Gregor     // Consume the feature name.
2220adcd0268SBenjamin Kramer     std::string Feature = std::string(Tok.getString());
22211fb5c3a6SDouglas Gregor     consumeToken();
22221fb5c3a6SDouglas Gregor 
22237ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
22247ff29148SBen Langmuir     bool ShouldAddRequirement =
22257ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22267ff29148SBen Langmuir 
22277ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22287ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22297ff29148SBen Langmuir 
22307ff29148SBen Langmuir     if (ShouldAddRequirement) {
22311fb5c3a6SDouglas Gregor       // Add this feature.
22327ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22337ff29148SBen Langmuir                                    *Map.Target);
22347ff29148SBen Langmuir     }
22351fb5c3a6SDouglas Gregor 
22361fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22371fb5c3a6SDouglas Gregor       break;
22381fb5c3a6SDouglas Gregor 
22391fb5c3a6SDouglas Gregor     // Consume the comma.
22401fb5c3a6SDouglas Gregor     consumeToken();
22411fb5c3a6SDouglas Gregor   } while (true);
22421fb5c3a6SDouglas Gregor }
22431fb5c3a6SDouglas Gregor 
22449fc8faf9SAdrian Prantl /// Parse a header declaration.
2245718292f2SDouglas Gregor ///
2246718292f2SDouglas Gregor ///   header-declaration:
2247306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2248202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2249202210b3SRichard Smith ///     'exclude' 'header' string-literal
2250202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2251306d8920SRichard Smith ///
2252306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2253b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2254b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2255202210b3SRichard Smith   // We've already consumed the first token.
2256202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2257202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2258202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2259202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2260202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2261202210b3SRichard Smith       LeadingToken = Tok.Kind;
22621871ed3dSBenjamin Kramer       consumeToken();
2263202210b3SRichard Smith     }
2264202210b3SRichard Smith   }
22657ff29148SBen Langmuir 
2266202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2267202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2268202210b3SRichard Smith 
22697ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22707ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22717ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22727ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22737ff29148SBen Langmuir   }
22747ff29148SBen Langmuir 
2275202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2276202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2277202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2278202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2279202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2280202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2281202210b3SRichard Smith       return;
2282202210b3SRichard Smith     }
2283202210b3SRichard Smith     consumeToken();
2284202210b3SRichard Smith   }
2285718292f2SDouglas Gregor 
2286718292f2SDouglas Gregor   // Parse the header name.
2287718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2288718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2289718292f2SDouglas Gregor       << "header";
2290718292f2SDouglas Gregor     HadError = true;
2291718292f2SDouglas Gregor     return;
2292718292f2SDouglas Gregor   }
22933c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
2294adcd0268SBenjamin Kramer   Header.FileName = std::string(Tok.getString());
22950761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
22961d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2297040e1266SRichard Smith   Header.Kind =
2298040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2299040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2300718292f2SDouglas Gregor 
2301524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
23021d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
23030761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2304524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2305322f633cSDouglas Gregor     HadError = true;
2306322f633cSDouglas Gregor     return;
2307322f633cSDouglas Gregor   }
2308322f633cSDouglas Gregor 
2309040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2310040e1266SRichard Smith   // the file.
2311040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2312040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
23133ec6663bSDouglas Gregor 
2314040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2315040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2316040e1266SRichard Smith       StringRef Str = Tok.getString();
2317040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2318040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2319040e1266SRichard Smith                   .Case("size", Size)
2320040e1266SRichard Smith                   .Case("mtime", ModTime)
2321040e1266SRichard Smith                   .Default(Unknown)) {
2322040e1266SRichard Smith       case Size:
2323040e1266SRichard Smith         if (Header.Size)
2324040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2325040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2326040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2327040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2328040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2329040e1266SRichard Smith           break;
2330040e1266SRichard Smith         }
2331040e1266SRichard Smith         Header.Size = Tok.getInteger();
2332040e1266SRichard Smith         consumeToken();
2333040e1266SRichard Smith         break;
2334040e1266SRichard Smith 
2335040e1266SRichard Smith       case ModTime:
2336040e1266SRichard Smith         if (Header.ModTime)
2337040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2338040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2339040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2340040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2341040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2342040e1266SRichard Smith           break;
2343040e1266SRichard Smith         }
2344040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2345040e1266SRichard Smith         consumeToken();
2346040e1266SRichard Smith         break;
2347040e1266SRichard Smith 
2348040e1266SRichard Smith       case Unknown:
2349040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2350040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2351040e1266SRichard Smith         break;
2352040e1266SRichard Smith       }
23533ec6663bSDouglas Gregor     }
23545257fc63SDouglas Gregor 
2355040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2356040e1266SRichard Smith       consumeToken();
2357040e1266SRichard Smith     else {
2358040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2359040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2360322f633cSDouglas Gregor       HadError = true;
2361322f633cSDouglas Gregor     }
23620101b540SHans Wennborg   }
236325d50758SRichard Smith 
23649f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23659f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23669f6020bcSBruno Cardoso Lopes 
23679f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23689f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23699f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23709f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2371718292f2SDouglas Gregor }
2372718292f2SDouglas Gregor 
237341f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
237441f81994SBen Langmuir                                 const Module::Header *B) {
237541f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
237641f81994SBen Langmuir }
237741f81994SBen Langmuir 
23789fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2379524e33e1SDouglas Gregor ///
2380524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2381524e33e1SDouglas Gregor ///     umbrella string-literal
2382524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2383524e33e1SDouglas Gregor   // Parse the directory name.
2384524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2385524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2386524e33e1SDouglas Gregor       << "umbrella";
2387524e33e1SDouglas Gregor     HadError = true;
2388524e33e1SDouglas Gregor     return;
2389524e33e1SDouglas Gregor   }
2390524e33e1SDouglas Gregor 
2391adcd0268SBenjamin Kramer   std::string DirName = std::string(Tok.getString());
2392524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2393524e33e1SDouglas Gregor 
2394524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2395524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2396524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2397524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2398524e33e1SDouglas Gregor     HadError = true;
2399524e33e1SDouglas Gregor     return;
2400524e33e1SDouglas Gregor   }
2401524e33e1SDouglas Gregor 
2402524e33e1SDouglas Gregor   // Look for this file.
2403d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
24048d323d15SHarlan Haskins   if (llvm::sys::path::is_absolute(DirName)) {
24058d323d15SHarlan Haskins     if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24068d323d15SHarlan Haskins       Dir = *D;
24078d323d15SHarlan Haskins   } else {
24082c1dd271SDylan Noblesmith     SmallString<128> PathName;
2409524e33e1SDouglas Gregor     PathName = Directory->getName();
2410524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
24118d323d15SHarlan Haskins     if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24128d323d15SHarlan Haskins       Dir = *D;
2413524e33e1SDouglas Gregor   }
2414524e33e1SDouglas Gregor 
2415524e33e1SDouglas Gregor   if (!Dir) {
2416a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2417524e33e1SDouglas Gregor       << DirName;
2418524e33e1SDouglas Gregor     return;
2419524e33e1SDouglas Gregor   }
2420524e33e1SDouglas Gregor 
24217ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24227ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
24237ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24247ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
24257ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
24267ff29148SBen Langmuir     std::error_code EC;
24277ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2428fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2429db8a7422SDuncan P. N. Exon Smith         SourceMgr.getFileManager().getVirtualFileSystem();
2430fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24317ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
24328d323d15SHarlan Haskins       if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2433adcd0268SBenjamin Kramer         Module::Header Header = {std::string(I->path()), *FE};
24347ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24357ff29148SBen Langmuir       }
24367ff29148SBen Langmuir     }
24377ff29148SBen Langmuir 
24387ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
243941f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
244041f81994SBen Langmuir 
24417ff29148SBen Langmuir     for (auto &Header : Headers)
24427ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24437ff29148SBen Langmuir     return;
24447ff29148SBen Langmuir   }
24457ff29148SBen Langmuir 
2446524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2447524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2448524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2449524e33e1SDouglas Gregor     HadError = true;
2450524e33e1SDouglas Gregor     return;
2451524e33e1SDouglas Gregor   }
2452524e33e1SDouglas Gregor 
2453524e33e1SDouglas Gregor   // Record this umbrella directory.
24542b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2455524e33e1SDouglas Gregor }
2456524e33e1SDouglas Gregor 
24579fc8faf9SAdrian Prantl /// Parse a module export declaration.
24582b82c2a5SDouglas Gregor ///
24592b82c2a5SDouglas Gregor ///   export-declaration:
24602b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24612b82c2a5SDouglas Gregor ///
24622b82c2a5SDouglas Gregor ///   wildcard-module-id:
24632b82c2a5SDouglas Gregor ///     identifier
24642b82c2a5SDouglas Gregor ///     '*'
24652b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24662b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24672b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24682b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24692b82c2a5SDouglas Gregor 
24702b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24712b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24722b82c2a5SDouglas Gregor   bool Wildcard = false;
24732b82c2a5SDouglas Gregor   do {
2474306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24752b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
2476adcd0268SBenjamin Kramer       ParsedModuleId.push_back(
2477adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
24782b82c2a5SDouglas Gregor       consumeToken();
24792b82c2a5SDouglas Gregor 
24802b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
24812b82c2a5SDouglas Gregor         consumeToken();
24822b82c2a5SDouglas Gregor         continue;
24832b82c2a5SDouglas Gregor       }
24842b82c2a5SDouglas Gregor 
24852b82c2a5SDouglas Gregor       break;
24862b82c2a5SDouglas Gregor     }
24872b82c2a5SDouglas Gregor 
24882b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
24892b82c2a5SDouglas Gregor       Wildcard = true;
2490f5eedd05SDouglas Gregor       consumeToken();
24912b82c2a5SDouglas Gregor       break;
24922b82c2a5SDouglas Gregor     }
24932b82c2a5SDouglas Gregor 
2494ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
24952b82c2a5SDouglas Gregor     HadError = true;
24962b82c2a5SDouglas Gregor     return;
24972b82c2a5SDouglas Gregor   } while (true);
24982b82c2a5SDouglas Gregor 
24992b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
25002b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
25012b82c2a5SDouglas Gregor   };
25022b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
25032b82c2a5SDouglas Gregor }
25042b82c2a5SDouglas Gregor 
25059fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2506f0b11de2SDouglas Gregor ///
2507f0b11de2SDouglas Gregor ///   export-as-declaration:
2508f0b11de2SDouglas Gregor ///     'export_as' identifier
2509f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2510f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2511f0b11de2SDouglas Gregor   consumeToken();
2512f0b11de2SDouglas Gregor 
2513f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2514f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2515f0b11de2SDouglas Gregor     HadError = true;
2516f0b11de2SDouglas Gregor     return;
2517f0b11de2SDouglas Gregor   }
2518f0b11de2SDouglas Gregor 
2519f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2520f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2521f0b11de2SDouglas Gregor     consumeToken();
2522f0b11de2SDouglas Gregor     return;
2523f0b11de2SDouglas Gregor   }
2524f0b11de2SDouglas Gregor 
2525f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2526f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2527f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2528f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2529f0b11de2SDouglas Gregor     } else {
2530f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2531f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2532f0b11de2SDouglas Gregor         << Tok.getString();
2533f0b11de2SDouglas Gregor     }
2534f0b11de2SDouglas Gregor   }
2535f0b11de2SDouglas Gregor 
2536adcd0268SBenjamin Kramer   ActiveModule->ExportAsModule = std::string(Tok.getString());
2537a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2538a3b5f71eSBruno Cardoso Lopes 
2539f0b11de2SDouglas Gregor   consumeToken();
2540f0b11de2SDouglas Gregor }
2541f0b11de2SDouglas Gregor 
25429fc8faf9SAdrian Prantl /// Parse a module use declaration.
2543ba7f2f71SDaniel Jasper ///
25448f4d3ff1SRichard Smith ///   use-declaration:
25458f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2546ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2547ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25488f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2549ba7f2f71SDaniel Jasper   // Parse the module-id.
2550ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25513cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2552ba7f2f71SDaniel Jasper 
25538f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25548f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25558f4d3ff1SRichard Smith   else
2556ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2557ba7f2f71SDaniel Jasper }
2558ba7f2f71SDaniel Jasper 
25599fc8faf9SAdrian Prantl /// Parse a link declaration.
25606ddfca91SDouglas Gregor ///
25616ddfca91SDouglas Gregor ///   module-declaration:
25626ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25636ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25646ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25656ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25666ddfca91SDouglas Gregor 
25676ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25686ddfca91SDouglas Gregor   bool IsFramework = false;
25696ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25706ddfca91SDouglas Gregor     consumeToken();
25716ddfca91SDouglas Gregor     IsFramework = true;
25726ddfca91SDouglas Gregor   }
25736ddfca91SDouglas Gregor 
25746ddfca91SDouglas Gregor   // Parse the library name
25756ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25766ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25776ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25786ddfca91SDouglas Gregor     HadError = true;
25796ddfca91SDouglas Gregor     return;
25806ddfca91SDouglas Gregor   }
25816ddfca91SDouglas Gregor 
2582adcd0268SBenjamin Kramer   std::string LibraryName = std::string(Tok.getString());
25836ddfca91SDouglas Gregor   consumeToken();
25846ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
25856ddfca91SDouglas Gregor                                                             IsFramework));
25866ddfca91SDouglas Gregor }
25876ddfca91SDouglas Gregor 
25889fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
258935b13eceSDouglas Gregor ///
259035b13eceSDouglas Gregor ///   module-declaration:
259135b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
259235b13eceSDouglas Gregor ///
259335b13eceSDouglas Gregor ///   config-macro-list:
259435b13eceSDouglas Gregor ///     identifier (',' identifier)?
259535b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
259635b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
259735b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
259835b13eceSDouglas Gregor 
259935b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
260035b13eceSDouglas Gregor   if (ActiveModule->Parent) {
260135b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
260235b13eceSDouglas Gregor   }
260335b13eceSDouglas Gregor 
260435b13eceSDouglas Gregor   // Parse the optional attributes.
260535b13eceSDouglas Gregor   Attributes Attrs;
26065d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26075d29dee0SDavide Italiano     return;
26085d29dee0SDavide Italiano 
260935b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
261035b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
261135b13eceSDouglas Gregor   }
261235b13eceSDouglas Gregor 
261335b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2614306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
261535b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
261635b13eceSDouglas Gregor     return;
261735b13eceSDouglas Gregor 
261835b13eceSDouglas Gregor   // Consume the first identifier.
261935b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
262035b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
262135b13eceSDouglas Gregor   }
262235b13eceSDouglas Gregor   consumeToken();
262335b13eceSDouglas Gregor 
262435b13eceSDouglas Gregor   do {
262535b13eceSDouglas Gregor     // If there's a comma, consume it.
262635b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
262735b13eceSDouglas Gregor       break;
262835b13eceSDouglas Gregor     consumeToken();
262935b13eceSDouglas Gregor 
263035b13eceSDouglas Gregor     // We expect to see a macro name here.
2631306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
263235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
263335b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
263435b13eceSDouglas Gregor       break;
263535b13eceSDouglas Gregor     }
263635b13eceSDouglas Gregor 
263735b13eceSDouglas Gregor     // Consume the macro name.
263835b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
263935b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
264035b13eceSDouglas Gregor     }
264135b13eceSDouglas Gregor     consumeToken();
264235b13eceSDouglas Gregor   } while (true);
264335b13eceSDouglas Gregor }
264435b13eceSDouglas Gregor 
26459fc8faf9SAdrian Prantl /// Format a module-id into a string.
2646fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2647fb912657SDouglas Gregor   std::string result;
2648fb912657SDouglas Gregor   {
2649fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2650fb912657SDouglas Gregor 
2651fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2652fb912657SDouglas Gregor       if (I)
2653fb912657SDouglas Gregor         OS << ".";
2654fb912657SDouglas Gregor       OS << Id[I].first;
2655fb912657SDouglas Gregor     }
2656fb912657SDouglas Gregor   }
2657fb912657SDouglas Gregor 
2658fb912657SDouglas Gregor   return result;
2659fb912657SDouglas Gregor }
2660fb912657SDouglas Gregor 
26619fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2662fb912657SDouglas Gregor ///
2663fb912657SDouglas Gregor ///   module-declaration:
2664fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2665fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2666fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2667fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2668fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2669fb912657SDouglas Gregor 
2670fb912657SDouglas Gregor   // Parse the module-id.
2671fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2672fb912657SDouglas Gregor     return;
2673fb912657SDouglas Gregor 
2674fb912657SDouglas Gregor   // Parse the ','.
2675fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2676fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2677fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2678fb912657SDouglas Gregor     return;
2679fb912657SDouglas Gregor   }
2680fb912657SDouglas Gregor   consumeToken();
2681fb912657SDouglas Gregor 
2682fb912657SDouglas Gregor   // Parse the message.
2683fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2684fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2685fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2686fb912657SDouglas Gregor     return;
2687fb912657SDouglas Gregor   }
2688fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2689fb912657SDouglas Gregor   consumeToken();
2690fb912657SDouglas Gregor 
2691fb912657SDouglas Gregor   // Add this unresolved conflict.
2692fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2693fb912657SDouglas Gregor }
2694fb912657SDouglas Gregor 
26959fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
26969194a91dSDouglas Gregor ///
26979194a91dSDouglas Gregor ///   module-declaration:
26989194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
26999194a91dSDouglas Gregor ///       { inferred-module-member* }
27009194a91dSDouglas Gregor ///
27019194a91dSDouglas Gregor ///   inferred-module-member:
27029194a91dSDouglas Gregor ///     'export' '*'
27039194a91dSDouglas Gregor ///     'exclude' identifier
27049194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
270573441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
270673441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
270773441091SDouglas Gregor   bool Failed = false;
270873441091SDouglas Gregor 
270973441091SDouglas Gregor   // Inferred modules must be submodules.
27109194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
271173441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
271273441091SDouglas Gregor     Failed = true;
271373441091SDouglas Gregor   }
271473441091SDouglas Gregor 
27159194a91dSDouglas Gregor   if (ActiveModule) {
2716524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
27174898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
27184898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
271973441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
272073441091SDouglas Gregor       Failed = true;
272173441091SDouglas Gregor     }
272273441091SDouglas Gregor 
272373441091SDouglas Gregor     // Check for redefinition of an inferred module.
2724dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
272573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2726dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2727dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
272873441091SDouglas Gregor                      diag::note_mmap_prev_definition);
272973441091SDouglas Gregor       Failed = true;
273073441091SDouglas Gregor     }
273173441091SDouglas Gregor 
27329194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27339194a91dSDouglas Gregor     if (Framework) {
27349194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27359194a91dSDouglas Gregor       Framework = false;
27369194a91dSDouglas Gregor     }
27379194a91dSDouglas Gregor   } else if (Explicit) {
27389194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27399194a91dSDouglas Gregor     Explicit = false;
27409194a91dSDouglas Gregor   }
27419194a91dSDouglas Gregor 
274273441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
274373441091SDouglas Gregor   if (Failed) {
274473441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
274573441091SDouglas Gregor       consumeToken();
274673441091SDouglas Gregor       skipUntil(MMToken::RBrace);
274773441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
274873441091SDouglas Gregor         consumeToken();
274973441091SDouglas Gregor     }
275073441091SDouglas Gregor     HadError = true;
275173441091SDouglas Gregor     return;
275273441091SDouglas Gregor   }
275373441091SDouglas Gregor 
27549194a91dSDouglas Gregor   // Parse optional attributes.
27554442605fSBill Wendling   Attributes Attrs;
27565d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27575d29dee0SDavide Italiano     return;
27589194a91dSDouglas Gregor 
27599194a91dSDouglas Gregor   if (ActiveModule) {
276073441091SDouglas Gregor     // Note that we have an inferred submodule.
2761dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2762dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2763dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27649194a91dSDouglas Gregor   } else {
27659194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27669194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2767c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2768beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2769131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27709194a91dSDouglas Gregor   }
277173441091SDouglas Gregor 
277273441091SDouglas Gregor   // Parse the opening brace.
277373441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
277473441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
277573441091SDouglas Gregor     HadError = true;
277673441091SDouglas Gregor     return;
277773441091SDouglas Gregor   }
277873441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
277973441091SDouglas Gregor 
278073441091SDouglas Gregor   // Parse the body of the inferred submodule.
278173441091SDouglas Gregor   bool Done = false;
278273441091SDouglas Gregor   do {
278373441091SDouglas Gregor     switch (Tok.Kind) {
278473441091SDouglas Gregor     case MMToken::EndOfFile:
278573441091SDouglas Gregor     case MMToken::RBrace:
278673441091SDouglas Gregor       Done = true;
278773441091SDouglas Gregor       break;
278873441091SDouglas Gregor 
2789afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
27909194a91dSDouglas Gregor       if (ActiveModule) {
27919194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2792d2d442caSCraig Topper           << (ActiveModule != nullptr);
27939194a91dSDouglas Gregor         consumeToken();
27949194a91dSDouglas Gregor         break;
27959194a91dSDouglas Gregor       }
27969194a91dSDouglas Gregor 
27979194a91dSDouglas Gregor       consumeToken();
2798306d8920SRichard Smith       // FIXME: Support string-literal module names here.
27999194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
28009194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28019194a91dSDouglas Gregor         break;
28029194a91dSDouglas Gregor       }
28039194a91dSDouglas Gregor 
2804adcd0268SBenjamin Kramer       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2805adcd0268SBenjamin Kramer           std::string(Tok.getString()));
28069194a91dSDouglas Gregor       consumeToken();
28079194a91dSDouglas Gregor       break;
28089194a91dSDouglas Gregor 
28099194a91dSDouglas Gregor     case MMToken::ExportKeyword:
28109194a91dSDouglas Gregor       if (!ActiveModule) {
28119194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2812d2d442caSCraig Topper           << (ActiveModule != nullptr);
28139194a91dSDouglas Gregor         consumeToken();
28149194a91dSDouglas Gregor         break;
28159194a91dSDouglas Gregor       }
28169194a91dSDouglas Gregor 
281773441091SDouglas Gregor       consumeToken();
281873441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2819dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
282073441091SDouglas Gregor       else
282173441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
282273441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
282373441091SDouglas Gregor       consumeToken();
282473441091SDouglas Gregor       break;
282573441091SDouglas Gregor 
282673441091SDouglas Gregor     case MMToken::ExplicitKeyword:
282773441091SDouglas Gregor     case MMToken::ModuleKeyword:
282873441091SDouglas Gregor     case MMToken::HeaderKeyword:
2829b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
283073441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
283173441091SDouglas Gregor     default:
28329194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2833d2d442caSCraig Topper           << (ActiveModule != nullptr);
283473441091SDouglas Gregor       consumeToken();
283573441091SDouglas Gregor       break;
283673441091SDouglas Gregor     }
283773441091SDouglas Gregor   } while (!Done);
283873441091SDouglas Gregor 
283973441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
284073441091SDouglas Gregor     consumeToken();
284173441091SDouglas Gregor   else {
284273441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
284373441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
284473441091SDouglas Gregor     HadError = true;
284573441091SDouglas Gregor   }
284673441091SDouglas Gregor }
284773441091SDouglas Gregor 
28489fc8faf9SAdrian Prantl /// Parse optional attributes.
28499194a91dSDouglas Gregor ///
28509194a91dSDouglas Gregor ///   attributes:
28519194a91dSDouglas Gregor ///     attribute attributes
28529194a91dSDouglas Gregor ///     attribute
28539194a91dSDouglas Gregor ///
28549194a91dSDouglas Gregor ///   attribute:
28559194a91dSDouglas Gregor ///     [ identifier ]
28569194a91dSDouglas Gregor ///
28579194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28589194a91dSDouglas Gregor ///
28599194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28604442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28619194a91dSDouglas Gregor   bool HadError = false;
28629194a91dSDouglas Gregor 
28639194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28649194a91dSDouglas Gregor     // Consume the '['.
28659194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28669194a91dSDouglas Gregor 
28679194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28689194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28699194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28709194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28719194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28729194a91dSDouglas Gregor         consumeToken();
28739194a91dSDouglas Gregor       HadError = true;
28749194a91dSDouglas Gregor     }
28759194a91dSDouglas Gregor 
28769194a91dSDouglas Gregor     // Decode the attribute name.
28779194a91dSDouglas Gregor     AttributeKind Attribute
28789194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
287935b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
288077944868SRichard Smith           .Case("extern_c", AT_extern_c)
2881ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28829194a91dSDouglas Gregor           .Case("system", AT_system)
28839194a91dSDouglas Gregor           .Default(AT_unknown);
28849194a91dSDouglas Gregor     switch (Attribute) {
28859194a91dSDouglas Gregor     case AT_unknown:
28869194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
28879194a91dSDouglas Gregor         << Tok.getString();
28889194a91dSDouglas Gregor       break;
28899194a91dSDouglas Gregor 
28909194a91dSDouglas Gregor     case AT_system:
28919194a91dSDouglas Gregor       Attrs.IsSystem = true;
28929194a91dSDouglas Gregor       break;
289335b13eceSDouglas Gregor 
289477944868SRichard Smith     case AT_extern_c:
289577944868SRichard Smith       Attrs.IsExternC = true;
289677944868SRichard Smith       break;
289777944868SRichard Smith 
289835b13eceSDouglas Gregor     case AT_exhaustive:
289935b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
290035b13eceSDouglas Gregor       break;
2901ed84df00SBruno Cardoso Lopes 
2902ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2903ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2904ed84df00SBruno Cardoso Lopes       break;
29059194a91dSDouglas Gregor     }
29069194a91dSDouglas Gregor     consumeToken();
29079194a91dSDouglas Gregor 
29089194a91dSDouglas Gregor     // Consume the ']'.
29099194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
29109194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29119194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29129194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
29139194a91dSDouglas Gregor       HadError = true;
29149194a91dSDouglas Gregor     }
29159194a91dSDouglas Gregor 
29169194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
29179194a91dSDouglas Gregor       consumeToken();
29189194a91dSDouglas Gregor   }
29199194a91dSDouglas Gregor 
29209194a91dSDouglas Gregor   return HadError;
29219194a91dSDouglas Gregor }
29229194a91dSDouglas Gregor 
29239fc8faf9SAdrian Prantl /// Parse a module map file.
2924718292f2SDouglas Gregor ///
2925718292f2SDouglas Gregor ///   module-map-file:
2926718292f2SDouglas Gregor ///     module-declaration*
2927718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2928718292f2SDouglas Gregor   do {
2929718292f2SDouglas Gregor     switch (Tok.Kind) {
2930718292f2SDouglas Gregor     case MMToken::EndOfFile:
2931718292f2SDouglas Gregor       return HadError;
2932718292f2SDouglas Gregor 
2933e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
293497292843SDaniel Jasper     case MMToken::ExternKeyword:
2935718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2936755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2937718292f2SDouglas Gregor       parseModuleDecl();
2938718292f2SDouglas Gregor       break;
2939718292f2SDouglas Gregor 
29401fb5c3a6SDouglas Gregor     case MMToken::Comma:
294135b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2942fb912657SDouglas Gregor     case MMToken::Conflict:
2943a3feee2aSRichard Smith     case MMToken::Exclaim:
294459527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29452b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2946f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2947718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2948718292f2SDouglas Gregor     case MMToken::Identifier:
2949718292f2SDouglas Gregor     case MMToken::LBrace:
29506ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2951a686e1b0SDouglas Gregor     case MMToken::LSquare:
29522b82c2a5SDouglas Gregor     case MMToken::Period:
2953b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2954718292f2SDouglas Gregor     case MMToken::RBrace:
2955a686e1b0SDouglas Gregor     case MMToken::RSquare:
29561fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29572b82c2a5SDouglas Gregor     case MMToken::Star:
2958718292f2SDouglas Gregor     case MMToken::StringLiteral:
2959040e1266SRichard Smith     case MMToken::IntegerLiteral:
2960b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2961718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2962ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2963718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2964718292f2SDouglas Gregor       HadError = true;
2965718292f2SDouglas Gregor       consumeToken();
2966718292f2SDouglas Gregor       break;
2967718292f2SDouglas Gregor     }
2968718292f2SDouglas Gregor   } while (true);
2969718292f2SDouglas Gregor }
2970718292f2SDouglas Gregor 
29719acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2972c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29738128f332SRichard Smith                                    unsigned *Offset,
2974ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29758128f332SRichard Smith   assert(Target && "Missing target information");
29764ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29774ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29784ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29794ddf2221SDouglas Gregor     return Known->second;
29804ddf2221SDouglas Gregor 
29818128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
29828128f332SRichard Smith   if (ID.isInvalid()) {
2983f3f84616SRichard Smith     auto FileCharacter =
2984f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
29858128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
29868128f332SRichard Smith   }
29878128f332SRichard Smith 
29888128f332SRichard Smith   assert(Target && "Missing target information");
29891f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2990718292f2SDouglas Gregor   if (!Buffer)
29914ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
29928128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
29938128f332SRichard Smith          "invalid buffer offset");
2994718292f2SDouglas Gregor 
2995718292f2SDouglas Gregor   // Parse this module map file.
29968128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
29978128f332SRichard Smith           Buffer->getBufferStart(),
29988128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
29998128f332SRichard Smith           Buffer->getBufferEnd());
30002a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
3001beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3002c192d194SBruno Cardoso Lopes                          IsSystem);
3003718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
30044ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
30052a6edb30SRichard Smith 
30068128f332SRichard Smith   if (Offset) {
30078128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30088128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
30098128f332SRichard Smith     *Offset = Loc.second;
30108128f332SRichard Smith   }
30118128f332SRichard Smith 
30122a6edb30SRichard Smith   // Notify callbacks that we parsed it.
30132a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
30142a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
30158587dfd9SBruno Cardoso Lopes 
3016718292f2SDouglas Gregor   return Result;
3017718292f2SDouglas Gregor }
3018