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)
285fc76b4adSRichard 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.
5476bc75023SRichard Smith   // FIXME: Considering whether the module is available rather than merely
5486bc75023SRichard Smith   // importable is non-hermetic and can result in surprising behavior for
5496bc75023SRichard Smith   // prebuilt modules. Consider only checking for importability here.
5508b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5518b7c0398SSean Silva     return true;
5528b7c0398SSean Silva 
553ec87a50aSRichard Smith   // Prefer a public header over a private header.
554ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
555ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
556ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
557ec87a50aSRichard Smith 
558ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
559ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
560ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
561ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
562ec87a50aSRichard Smith 
563ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
564ec87a50aSRichard Smith   return false;
565ec87a50aSRichard Smith }
566ec87a50aSRichard Smith 
567ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
568ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
569306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
570ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
571afd1b1c9SEugene Zelenko       return {};
572306d8920SRichard Smith     return R;
573306d8920SRichard Smith   };
574306d8920SRichard Smith 
5754881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5761fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
577202210b3SRichard Smith     ModuleMap::KnownHeader Result;
57897da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5794881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5807e82e019SRichard Smith       // Prefer a header from the source module over all others.
5817e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5822f633e7cSRichard Smith         return MakeResult(H);
5834881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5844881e8b2SSean Silva         Result = H;
58597da9178SDaniel Jasper     }
586306d8920SRichard Smith     return MakeResult(Result);
5871fb5c3a6SDouglas Gregor   }
588ab0c8a84SDouglas Gregor 
589386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
590386bb073SRichard Smith }
591386bb073SRichard Smith 
592386bb073SRichard Smith ModuleMap::KnownHeader
593386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
594386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
595386bb073SRichard Smith 
596f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5974469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5984469138eSBen Langmuir   if (H) {
5994469138eSBen Langmuir     Module *Result = H.getModule();
600930a85ccSDouglas Gregor 
601930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
60273141fa9SDouglas Gregor     // directory.
603930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
60473141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
605930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
606930a85ccSDouglas Gregor 
607930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6089d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6099d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6109d6448b1SBen Langmuir 
611a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
612a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
613a89c5ac4SDouglas Gregor       // the actual header is located.
6149458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6159458f82dSDouglas Gregor 
6167033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
617a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
618056396aeSDouglas Gregor         SmallString<32> NameBuf;
619056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6204469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6219d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6229d6448b1SBen Langmuir                                     Explicit).first;
6239d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
624ffbafa2aSBen Langmuir         Result->IsInferred = true;
625a89c5ac4SDouglas Gregor 
626a89c5ac4SDouglas Gregor         // Associate the module and the directory.
627a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
628a89c5ac4SDouglas Gregor 
629a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
630a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
631930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
632d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
633a89c5ac4SDouglas Gregor       }
634a89c5ac4SDouglas Gregor 
635a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
636056396aeSDouglas Gregor       SmallString<32> NameBuf;
637056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
638056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6399d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6409d6448b1SBen Langmuir                                   Explicit).first;
6419d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
642ffbafa2aSBen Langmuir       Result->IsInferred = true;
6433c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
644a89c5ac4SDouglas Gregor 
645a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
646a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
647930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
648d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
649a89c5ac4SDouglas Gregor     } else {
650a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
651a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
652a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
653a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
654a89c5ac4SDouglas Gregor     }
655a89c5ac4SDouglas Gregor 
656386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
657386bb073SRichard Smith     Headers[File].push_back(Header);
658386bb073SRichard Smith     return Header;
659a89c5ac4SDouglas Gregor   }
660a89c5ac4SDouglas Gregor 
661afd1b1c9SEugene Zelenko   return {};
662ab0c8a84SDouglas Gregor }
663ab0c8a84SDouglas Gregor 
664386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
665*0a088eadSRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) {
666*0a088eadSRichard Smith   HeadersMap::iterator Known = findKnownHeader(File);
667*0a088eadSRichard Smith   if (Known != Headers.end())
668*0a088eadSRichard Smith     return Known->second;
669*0a088eadSRichard Smith 
670*0a088eadSRichard Smith   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
671*0a088eadSRichard Smith     return Headers.find(File)->second;
672*0a088eadSRichard Smith 
673*0a088eadSRichard Smith   return None;
674*0a088eadSRichard Smith }
675*0a088eadSRichard Smith 
676*0a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader>
677*0a088eadSRichard Smith ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
678*0a088eadSRichard Smith   // FIXME: Is this necessary?
679040e1266SRichard Smith   resolveHeaderDirectives(File);
680386bb073SRichard Smith   auto It = Headers.find(File);
681386bb073SRichard Smith   if (It == Headers.end())
682386bb073SRichard Smith     return None;
683386bb073SRichard Smith   return It->second;
684386bb073SRichard Smith }
685386bb073SRichard Smith 
686e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
687d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
68850996ce1SRichard Smith }
68950996ce1SRichard Smith 
69062bcd925SDmitri Gribenko bool
69162bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
69262bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
693040e1266SRichard Smith   resolveHeaderDirectives(Header);
694e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
69597da9178SDaniel Jasper   if (Known != Headers.end()) {
69697da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
69797da9178SDaniel Jasper              I = Known->second.begin(),
69897da9178SDaniel Jasper              E = Known->second.end();
69997da9178SDaniel Jasper          I != E; ++I) {
700052d95a6SBruno Cardoso Lopes 
701052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
702052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
703052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
704052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
705052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
706052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
707052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
708052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
709052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
710052d95a6SBruno Cardoso Lopes           continue;
71197da9178SDaniel Jasper         return false;
71297da9178SDaniel Jasper       }
713052d95a6SBruno Cardoso Lopes     }
71497da9178SDaniel Jasper     return true;
71597da9178SDaniel Jasper   }
7161fb5c3a6SDouglas Gregor 
7171fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
718f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7191fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7201fb5c3a6SDouglas Gregor 
72150996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
72250996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
72350996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
72450996ce1SRichard Smith   };
72550996ce1SRichard Smith 
7261fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7271fb5c3a6SDouglas Gregor   // an umbrella header.
7281fb5c3a6SDouglas Gregor   do {
729e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7301fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7311fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7321fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
73350996ce1SRichard Smith       if (IsUnavailable(Found))
7341fb5c3a6SDouglas Gregor         return true;
7351fb5c3a6SDouglas Gregor 
7361fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7371fb5c3a6SDouglas Gregor       // directory.
7381fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7391fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7401fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7411fb5c3a6SDouglas Gregor 
7421fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7431fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7441fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
745056396aeSDouglas Gregor           SmallString<32> NameBuf;
746056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
747056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
748056396aeSDouglas Gregor                              NameBuf);
7491fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7501fb5c3a6SDouglas Gregor           if (!Found)
7511fb5c3a6SDouglas Gregor             return false;
75250996ce1SRichard Smith           if (IsUnavailable(Found))
7531fb5c3a6SDouglas Gregor             return true;
7541fb5c3a6SDouglas Gregor         }
7551fb5c3a6SDouglas Gregor 
7561fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
757056396aeSDouglas Gregor         SmallString<32> NameBuf;
758056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
759056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
760056396aeSDouglas Gregor                            NameBuf);
7611fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7621fb5c3a6SDouglas Gregor         if (!Found)
7631fb5c3a6SDouglas Gregor           return false;
7641fb5c3a6SDouglas Gregor       }
7651fb5c3a6SDouglas Gregor 
76650996ce1SRichard Smith       return IsUnavailable(Found);
7671fb5c3a6SDouglas Gregor     }
7681fb5c3a6SDouglas Gregor 
7691fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7701fb5c3a6SDouglas Gregor 
7711fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7721fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7731fb5c3a6SDouglas Gregor     if (DirName.empty())
7741fb5c3a6SDouglas Gregor       break;
7751fb5c3a6SDouglas Gregor 
7761fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7778d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7788d323d15SHarlan Haskins       Dir = *DirEntry;
7798d323d15SHarlan Haskins     else
7808d323d15SHarlan Haskins       Dir = nullptr;
7811fb5c3a6SDouglas Gregor   } while (Dir);
7821fb5c3a6SDouglas Gregor 
7831fb5c3a6SDouglas Gregor   return false;
7841fb5c3a6SDouglas Gregor }
7851fb5c3a6SDouglas Gregor 
786e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
787e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
78888bdfb0eSDouglas Gregor   if (Known != Modules.end())
78988bdfb0eSDouglas Gregor     return Known->getValue();
79088bdfb0eSDouglas Gregor 
791d2d442caSCraig Topper   return nullptr;
79288bdfb0eSDouglas Gregor }
79388bdfb0eSDouglas Gregor 
794e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
795e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7962b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7972b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7982b82c2a5SDouglas Gregor       return Sub;
7992b82c2a5SDouglas Gregor   }
8002b82c2a5SDouglas Gregor 
8012b82c2a5SDouglas Gregor   return findModule(Name);
8022b82c2a5SDouglas Gregor }
8032b82c2a5SDouglas Gregor 
804e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8052b82c2a5SDouglas Gregor   if (!Context)
8062b82c2a5SDouglas Gregor     return findModule(Name);
8072b82c2a5SDouglas Gregor 
808eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
8092b82c2a5SDouglas Gregor }
8102b82c2a5SDouglas Gregor 
811c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
812c192d194SBruno Cardoso Lopes                                                         Module *Parent,
813c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
814c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
81569021974SDouglas Gregor   // Try to find an existing module with this name.
816eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
817eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
81869021974SDouglas Gregor 
81969021974SDouglas Gregor   // Create a new module with this name.
8209ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8219ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
8226f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8237e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8247e82e019SRichard Smith       SourceModule = Result;
82569021974SDouglas Gregor     Modules[Name] = Result;
826c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8276f722b4eSArgyrios Kyrtzidis   }
82869021974SDouglas Gregor   return std::make_pair(Result, true);
82969021974SDouglas Gregor }
83069021974SDouglas Gregor 
831a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
832d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
833056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
834056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
835d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
836d6509cf2SRichard Smith   return PendingSubmodules.back().get();
837dd8b5337SRichard Smith }
838dd8b5337SRichard Smith 
839a5bbbfefSRichard Smith Module *
840a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
841a5bbbfefSRichard Smith                                                        SourceLocation Loc) {
842a5bbbfefSRichard Smith   auto *Result =
843a5bbbfefSRichard Smith       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
844a5bbbfefSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++);
845a5bbbfefSRichard Smith   Result->Kind = Module::PrivateModuleFragment;
846a5bbbfefSRichard Smith   return Result;
847a5bbbfefSRichard Smith }
848a5bbbfefSRichard Smith 
849bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
850dd8b5337SRichard Smith                                                 StringRef Name,
851dd8b5337SRichard Smith                                                 Module *GlobalModule) {
852bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
853bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
854bbcc9f04SRichard Smith 
855bbcc9f04SRichard Smith   auto *Result =
856bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
857bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
858145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
859bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
860bbcc9f04SRichard Smith 
861dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
862d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
863d6509cf2SRichard Smith     Submodule->setParent(Result);
864d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
865d6509cf2SRichard Smith   }
866d6509cf2SRichard Smith   PendingSubmodules.clear();
867dd8b5337SRichard Smith 
868bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
869bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
870bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
871bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
872bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
873bbcc9f04SRichard Smith 
874bbcc9f04SRichard Smith   return Result;
875bbcc9f04SRichard Smith }
876bbcc9f04SRichard Smith 
877d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
878d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
879d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
880d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
881d6509cf2SRichard Smith 
882d6509cf2SRichard Smith   auto *Result =
883d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
884d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
885d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
886d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
887d6509cf2SRichard Smith 
888d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
889d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
890d6509cf2SRichard Smith                          /*IsFramework*/ false,
891d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
892d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
893d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
894d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
895d6509cf2SRichard Smith   }
896d6509cf2SRichard Smith 
897d6509cf2SRichard Smith   return Result;
898d6509cf2SRichard Smith }
899d6509cf2SRichard Smith 
9009fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
90111dfe6feSDouglas Gregor /// should link.
90211dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
90311dfe6feSDouglas Gregor                                FileManager &FileMgr) {
90411dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
90511dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
90611dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
90711dfe6feSDouglas Gregor 
90811dfe6feSDouglas Gregor   SmallString<128> LibName;
90911dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
91011dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
9118aaae5a9SJuergen Ributzka 
9128aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
9138aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
9148aaae5a9SJuergen Ributzka   // for both before we give up.
9158013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
9168aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
91711dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
91811dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
91911dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
9208aaae5a9SJuergen Ributzka       return;
9218aaae5a9SJuergen Ributzka     }
92211dfe6feSDouglas Gregor   }
92311dfe6feSDouglas Gregor }
92411dfe6feSDouglas Gregor 
925a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
926a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
927c1d88ea5SBen Langmuir   Attributes Attrs;
928c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
929a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
930c1d88ea5SBen Langmuir }
931c1d88ea5SBen Langmuir 
932a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
933c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
934a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
935a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
936a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
937a525400dSBen Langmuir   // top-level framework.
938a525400dSBen Langmuir   StringRef FrameworkDirName =
939a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
940a525400dSBen Langmuir 
941a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
942a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
943a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
944a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
945a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
946a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
947c1d88ea5SBen Langmuir 
94856c64013SDouglas Gregor   // Check whether we've already found this module.
949e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
950e89dbc1dSDouglas Gregor     return Mod;
951e89dbc1dSDouglas Gregor 
9521f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
95356c64013SDouglas Gregor 
9549194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9559194a91dSDouglas Gregor   // a framework module, do so.
956beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9579194a91dSDouglas Gregor   if (!Parent) {
9584ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9599194a91dSDouglas Gregor     bool canInfer = false;
9604ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9619194a91dSDouglas Gregor       // Figure out the parent path.
9624ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9638d323d15SHarlan Haskins       if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9649194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9659194a91dSDouglas Gregor         // for a module map.
966e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9678d323d15SHarlan Haskins           inferred = InferredDirectories.find(*ParentDir);
9689194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9699194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9709194a91dSDouglas Gregor           // one.
971984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
972984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
9738d323d15SHarlan Haskins                 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9748d323d15SHarlan Haskins             parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9758d323d15SHarlan Haskins             inferred = InferredDirectories.find(*ParentDir);
9769194a91dSDouglas Gregor           }
9779194a91dSDouglas Gregor 
9789194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9799194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9808d323d15SHarlan Haskins                          std::make_pair(*ParentDir, InferredDirectory())).first;
9819194a91dSDouglas Gregor         }
9829194a91dSDouglas Gregor 
9839194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9849194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9859194a91dSDouglas Gregor           // to infer this particular module.
9864ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9879194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9889194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9899194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9909194a91dSDouglas Gregor 
991c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
992c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
993c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
994ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
995ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
996beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9979194a91dSDouglas Gregor         }
9989194a91dSDouglas Gregor       }
9999194a91dSDouglas Gregor     }
10009194a91dSDouglas Gregor 
10019194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
10029194a91dSDouglas Gregor     if (!canInfer)
1003d2d442caSCraig Topper       return nullptr;
1004beee15e7SBen Langmuir   } else
10059d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
10069194a91dSDouglas Gregor 
10079194a91dSDouglas Gregor 
100856c64013SDouglas Gregor   // Look for an umbrella header.
10092c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
101017381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
10118d323d15SHarlan Haskins   auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
101256c64013SDouglas Gregor 
101356c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
101456c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
101556c64013SDouglas Gregor   // idea.
101656c64013SDouglas Gregor   if (!UmbrellaHeader)
1017d2d442caSCraig Topper     return nullptr;
101856c64013SDouglas Gregor 
10199d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1020a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
1021a7e2cc68SRichard Smith                               NumCreatedModules++);
10229d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
10239d6448b1SBen Langmuir   Result->IsInferred = true;
10247e82e019SRichard Smith   if (!Parent) {
10257e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
1026ba7f2f71SDaniel Jasper       SourceModule = Result;
10277e82e019SRichard Smith     Modules[ModuleName] = Result;
1028c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1029ba7f2f71SDaniel Jasper   }
1030c1d88ea5SBen Langmuir 
1031c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
1032c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1033c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1034ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10352b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1036a686e1b0SDouglas Gregor 
1037322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
10382b63d15fSRichard Smith   //
10392b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
10402b63d15fSRichard Smith   // a framework module.
10418d323d15SHarlan Haskins   setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h");
1042d8bd7537SDouglas Gregor 
1043d8bd7537SDouglas Gregor   // export *
1044d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1045d8bd7537SDouglas Gregor 
1046a89c5ac4SDouglas Gregor   // module * { export * }
1047a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1048a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1049a89c5ac4SDouglas Gregor 
1050e89dbc1dSDouglas Gregor   // Look for subframeworks.
1051c080917eSRafael Espindola   std::error_code EC;
10522c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1053ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1054e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10552d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1056db8a7422SDuncan P. N. Exon Smith   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1057fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1058fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1059b171a59bSBruno Cardoso Lopes            DirEnd;
1060e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10610ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1062e89dbc1dSDouglas Gregor       continue;
1063f2161a70SDouglas Gregor 
10648d323d15SHarlan Haskins     if (auto SubframeworkDir =
10650ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
106607c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
106707c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
106807c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
106907c22b78SDouglas Gregor       // out to a top-level framework.
10708d323d15SHarlan Haskins       StringRef SubframeworkDirName =
10718d323d15SHarlan Haskins           FileMgr.getCanonicalName(*SubframeworkDir);
107207c22b78SDouglas Gregor       bool FoundParent = false;
107307c22b78SDouglas Gregor       do {
107407c22b78SDouglas Gregor         // Get the parent directory name.
107507c22b78SDouglas Gregor         SubframeworkDirName
107607c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
107707c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
107807c22b78SDouglas Gregor           break;
107907c22b78SDouglas Gregor 
10808d323d15SHarlan Haskins         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
10818d323d15SHarlan Haskins           if (*SubDir == FrameworkDir) {
108207c22b78SDouglas Gregor             FoundParent = true;
108307c22b78SDouglas Gregor             break;
108407c22b78SDouglas Gregor           }
10858d323d15SHarlan Haskins         }
108607c22b78SDouglas Gregor       } while (true);
108707c22b78SDouglas Gregor 
108807c22b78SDouglas Gregor       if (!FoundParent)
108907c22b78SDouglas Gregor         continue;
109007c22b78SDouglas Gregor 
1091e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
10928d323d15SHarlan Haskins       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1093e89dbc1dSDouglas Gregor     }
1094e89dbc1dSDouglas Gregor   }
1095e89dbc1dSDouglas Gregor 
109611dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
109711dfe6feSDouglas Gregor   // framework.
109811dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
109911dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
110011dfe6feSDouglas Gregor   }
110111dfe6feSDouglas Gregor 
110256c64013SDouglas Gregor   return Result;
110356c64013SDouglas Gregor }
110456c64013SDouglas Gregor 
11058587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11068587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
11078587dfd9SBruno Cardoso Lopes 
11088587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
11098587dfd9SBruno Cardoso Lopes   Module *Result =
11108587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11118587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
11128587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
1113fc76b4adSRichard Smith   Result->markUnavailable(/*Unimportable*/true);
1114c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
11158587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
11168587dfd9SBruno Cardoso Lopes 
11178587dfd9SBruno Cardoso Lopes   return Result;
11188587dfd9SBruno Cardoso Lopes }
11198587dfd9SBruno Cardoso Lopes 
11202b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
11212b63d15fSRichard Smith                                   Twine NameAsWritten) {
112297da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
112373141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
1124bc883665SReid Kleckner   Mod->HasUmbrellaDir = false;
11252b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
11267033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1127b3a0fa48SBruno Cardoso Lopes 
1128b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1129b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1130b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1131a89c5ac4SDouglas Gregor }
1132a89c5ac4SDouglas Gregor 
11332b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
11342b63d15fSRichard Smith                                Twine NameAsWritten) {
1135524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
1136bc883665SReid Kleckner   Mod->HasUmbrellaDir = true;
11372b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1138524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1139524e33e1SDouglas Gregor }
1140524e33e1SDouglas Gregor 
1141040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11429f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11439f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1144040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1145040e1266SRichard Smith   // wrap the system header.
1146040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1147040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1148040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1149040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1150040e1266SRichard Smith     // case.
1151040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1152040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1153040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11543c1a41adSRichard Smith   }
1155040e1266SRichard Smith 
1156040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1157040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1158040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1159040e1266SRichard Smith   // headers.
1160040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1161040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1162040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1163040e1266SRichard Smith     // use the mtime as the key.
1164040e1266SRichard Smith     if (Header.ModTime)
1165040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1166040e1266SRichard Smith     else
1167040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1168040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1169040e1266SRichard Smith     return;
1170040e1266SRichard Smith   }
1171040e1266SRichard Smith 
1172040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1173040e1266SRichard Smith   // Perform the lookup now.
11749f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1175040e1266SRichard Smith }
1176040e1266SRichard Smith 
1177040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1178040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1179040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1180040e1266SRichard Smith     for (auto *M : BySize->second)
1181040e1266SRichard Smith       resolveHeaderDirectives(M);
1182040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1183040e1266SRichard Smith   }
1184040e1266SRichard Smith 
1185040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1186040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1187040e1266SRichard Smith     for (auto *M : ByModTime->second)
1188040e1266SRichard Smith       resolveHeaderDirectives(M);
1189040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1190040e1266SRichard Smith   }
1191040e1266SRichard Smith }
1192040e1266SRichard Smith 
1193040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11949f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1195040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1196040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1197040e1266SRichard Smith     // the header information for this file.
11989f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1199040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
12000e98d938SNAKAMURA Takumi }
1201202210b3SRichard Smith 
12023c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1203d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1204386bb073SRichard Smith   KnownHeader KH(Mod, Role);
12053c1a41adSRichard Smith 
1206386bb073SRichard Smith   // Only add each header to the headers list once.
1207386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1208386bb073SRichard Smith   // same module definition?
1209386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1210386bb073SRichard Smith   for (auto H : HeaderList)
1211386bb073SRichard Smith     if (H == KH)
1212386bb073SRichard Smith       return;
1213386bb073SRichard Smith 
1214386bb073SRichard Smith   HeaderList.push_back(KH);
12151ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1216386bb073SRichard Smith 
12177e82e019SRichard Smith   bool isCompilingModuleHeader =
1218bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1219d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1220d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1221d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1222d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1223d8879c85SRichard Smith                                     isCompilingModuleHeader);
1224d8879c85SRichard Smith   }
1225e62cfd7cSBruno Cardoso Lopes 
1226e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1227e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1228f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1229a89c5ac4SDouglas Gregor }
1230a89c5ac4SDouglas Gregor 
12313c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1232feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1233feb54b6dSRichard Smith   // umbrella directory module.
1234feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1235feb54b6dSRichard Smith   // specified module?
12363c1a41adSRichard Smith   (void) Headers[Header.Entry];
12373c1a41adSRichard Smith 
12383c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1239feb54b6dSRichard Smith }
1240feb54b6dSRichard Smith 
1241514b636aSDouglas Gregor const FileEntry *
12424b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12431f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1244d2d442caSCraig Topper     return nullptr;
1245514b636aSDouglas Gregor 
12461f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12471f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1248514b636aSDouglas Gregor }
1249514b636aSDouglas Gregor 
12504b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12519d6448b1SBen Langmuir   if (M->IsInferred) {
12529d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12539d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12549d6448b1SBen Langmuir   }
12559d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12569d6448b1SBen Langmuir }
12579d6448b1SBen Langmuir 
12589d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12599d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12609d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12619d6448b1SBen Langmuir }
12629d6448b1SBen Langmuir 
1263e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1264e08464fbSReid Kleckner                                            const FileEntry *ModuleMap) {
1265e08464fbSReid Kleckner   AdditionalModMaps[M].insert(ModuleMap);
1266e08464fbSReid Kleckner }
1267e08464fbSReid Kleckner 
1268cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1269718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1270718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1271718292f2SDouglas Gregor                                         MEnd = Modules.end();
1272718292f2SDouglas Gregor        M != MEnd; ++M)
1273d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1274718292f2SDouglas Gregor 
1275718292f2SDouglas Gregor   llvm::errs() << "Headers:";
127659527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1277718292f2SDouglas Gregor        H != HEnd; ++H) {
127897da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
127997da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
128097da9178SDaniel Jasper                                                       E = H->second.end();
128197da9178SDaniel Jasper          I != E; ++I) {
128297da9178SDaniel Jasper       if (I != H->second.begin())
128397da9178SDaniel Jasper         llvm::errs() << ",";
128497da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
128597da9178SDaniel Jasper     }
128697da9178SDaniel Jasper     llvm::errs() << "\n";
1287718292f2SDouglas Gregor   }
1288718292f2SDouglas Gregor }
1289718292f2SDouglas Gregor 
12902b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
129142413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
129242413141SRichard Smith   Mod->UnresolvedExports.clear();
129342413141SRichard Smith   for (auto &UE : Unresolved) {
129442413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1295f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12962b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12972b82c2a5SDouglas Gregor     else
129842413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12992b82c2a5SDouglas Gregor   }
130042413141SRichard Smith   return !Mod->UnresolvedExports.empty();
13012b82c2a5SDouglas Gregor }
13022b82c2a5SDouglas Gregor 
1303ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
130442413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
130542413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
130642413141SRichard Smith   for (auto &UDU : Unresolved) {
130742413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1308ba7f2f71SDaniel Jasper     if (DirectUse)
1309ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1310ba7f2f71SDaniel Jasper     else
131142413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1312ba7f2f71SDaniel Jasper   }
131342413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1314ba7f2f71SDaniel Jasper }
1315ba7f2f71SDaniel Jasper 
1316fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
131742413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
131842413141SRichard Smith   Mod->UnresolvedConflicts.clear();
131942413141SRichard Smith   for (auto &UC : Unresolved) {
132042413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1321fb912657SDouglas Gregor       Module::Conflict Conflict;
1322fb912657SDouglas Gregor       Conflict.Other = OtherMod;
132342413141SRichard Smith       Conflict.Message = UC.Message;
1324fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
132542413141SRichard Smith     } else
132642413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1327fb912657SDouglas Gregor   }
132842413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1329fb912657SDouglas Gregor }
1330fb912657SDouglas Gregor 
1331718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1332718292f2SDouglas Gregor // Module map file parser
1333718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1334718292f2SDouglas Gregor 
1335718292f2SDouglas Gregor namespace clang {
1336afd1b1c9SEugene Zelenko 
13379fc8faf9SAdrian Prantl   /// A token in a module map file.
1338718292f2SDouglas Gregor   struct MMToken {
1339718292f2SDouglas Gregor     enum TokenKind {
13401fb5c3a6SDouglas Gregor       Comma,
134135b13eceSDouglas Gregor       ConfigMacros,
1342fb912657SDouglas Gregor       Conflict,
1343718292f2SDouglas Gregor       EndOfFile,
1344718292f2SDouglas Gregor       HeaderKeyword,
1345718292f2SDouglas Gregor       Identifier,
1346a3feee2aSRichard Smith       Exclaim,
134759527666SDouglas Gregor       ExcludeKeyword,
1348718292f2SDouglas Gregor       ExplicitKeyword,
13492b82c2a5SDouglas Gregor       ExportKeyword,
1350f0b11de2SDouglas Gregor       ExportAsKeyword,
135197292843SDaniel Jasper       ExternKeyword,
1352755b2055SDouglas Gregor       FrameworkKeyword,
13536ddfca91SDouglas Gregor       LinkKeyword,
1354718292f2SDouglas Gregor       ModuleKeyword,
13552b82c2a5SDouglas Gregor       Period,
1356b53e5483SLawrence Crowl       PrivateKeyword,
1357718292f2SDouglas Gregor       UmbrellaKeyword,
1358ba7f2f71SDaniel Jasper       UseKeyword,
13591fb5c3a6SDouglas Gregor       RequiresKeyword,
13602b82c2a5SDouglas Gregor       Star,
1361718292f2SDouglas Gregor       StringLiteral,
1362040e1266SRichard Smith       IntegerLiteral,
1363306d8920SRichard Smith       TextualKeyword,
1364718292f2SDouglas Gregor       LBrace,
1365a686e1b0SDouglas Gregor       RBrace,
1366a686e1b0SDouglas Gregor       LSquare,
1367a686e1b0SDouglas Gregor       RSquare
1368718292f2SDouglas Gregor     } Kind;
1369718292f2SDouglas Gregor 
1370718292f2SDouglas Gregor     unsigned Location;
1371718292f2SDouglas Gregor     unsigned StringLength;
1372040e1266SRichard Smith     union {
1373040e1266SRichard Smith       // If Kind != IntegerLiteral.
1374718292f2SDouglas Gregor       const char *StringData;
1375afd1b1c9SEugene Zelenko 
1376040e1266SRichard Smith       // If Kind == IntegerLiteral.
1377040e1266SRichard Smith       uint64_t IntegerValue;
1378040e1266SRichard Smith     };
1379718292f2SDouglas Gregor 
1380718292f2SDouglas Gregor     void clear() {
1381718292f2SDouglas Gregor       Kind = EndOfFile;
1382718292f2SDouglas Gregor       Location = 0;
1383718292f2SDouglas Gregor       StringLength = 0;
1384d2d442caSCraig Topper       StringData = nullptr;
1385718292f2SDouglas Gregor     }
1386718292f2SDouglas Gregor 
1387718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1388718292f2SDouglas Gregor 
1389718292f2SDouglas Gregor     SourceLocation getLocation() const {
1390718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1391718292f2SDouglas Gregor     }
1392718292f2SDouglas Gregor 
1393040e1266SRichard Smith     uint64_t getInteger() const {
1394040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1395040e1266SRichard Smith     }
1396040e1266SRichard Smith 
1397718292f2SDouglas Gregor     StringRef getString() const {
1398040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1399040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1400718292f2SDouglas Gregor     }
1401718292f2SDouglas Gregor   };
1402718292f2SDouglas Gregor 
1403718292f2SDouglas Gregor   class ModuleMapParser {
1404718292f2SDouglas Gregor     Lexer &L;
1405718292f2SDouglas Gregor     SourceManager &SourceMgr;
1406bc10b9fbSDouglas Gregor 
14079fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1408bc10b9fbSDouglas Gregor     /// parsing.
1409bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1410bc10b9fbSDouglas Gregor 
1411718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1412718292f2SDouglas Gregor     ModuleMap &Map;
1413718292f2SDouglas Gregor 
14149fc8faf9SAdrian Prantl     /// The current module map file.
1415beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1416beee15e7SBen Langmuir 
14179f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
14189f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
14199f6020bcSBruno Cardoso Lopes 
14209fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
14219acb99e3SRichard Smith     /// be resolved relative to.
14225257fc63SDouglas Gregor     const DirectoryEntry *Directory;
14235257fc63SDouglas Gregor 
14249fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1425963c5535SDouglas Gregor     bool IsSystem;
1426963c5535SDouglas Gregor 
14279fc8faf9SAdrian Prantl     /// Whether an error occurred.
1428afd1b1c9SEugene Zelenko     bool HadError = false;
1429718292f2SDouglas Gregor 
14309fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1431718292f2SDouglas Gregor     /// during parsing.
1432718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1433718292f2SDouglas Gregor 
14349fc8faf9SAdrian Prantl     /// The current token.
1435718292f2SDouglas Gregor     MMToken Tok;
1436718292f2SDouglas Gregor 
14379fc8faf9SAdrian Prantl     /// The active module.
1438afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1439718292f2SDouglas Gregor 
14409fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
14417ff29148SBen Langmuir     /// contents as 'textual'.
14427ff29148SBen Langmuir     ///
14437ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14447ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14457ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14467ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14477ff29148SBen Langmuir     /// 'textual' to match the original intent.
14487ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14497ff29148SBen Langmuir 
14509fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1451718292f2SDouglas Gregor     SourceLocation consumeToken();
1452718292f2SDouglas Gregor 
14539fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1454718292f2SDouglas Gregor     /// (or the end of the file).
1455718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1456718292f2SDouglas Gregor 
1457afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1458afd1b1c9SEugene Zelenko 
1459e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1460718292f2SDouglas Gregor     void parseModuleDecl();
146197292843SDaniel Jasper     void parseExternModuleDecl();
14621fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1463afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1464524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14652b82c2a5SDouglas Gregor     void parseExportDecl();
1466f0b11de2SDouglas Gregor     void parseExportAsDecl();
1467ba7f2f71SDaniel Jasper     void parseUseDecl();
14686ddfca91SDouglas Gregor     void parseLinkDecl();
146935b13eceSDouglas Gregor     void parseConfigMacros();
1470fb912657SDouglas Gregor     void parseConflict();
14719194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1472c1d88ea5SBen Langmuir 
14735f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14745f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14755f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14765f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14775f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14785f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14795f11e128SBruno Cardoso Lopes 
1480afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1481afd1b1c9SEugene Zelenko 
14824442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1483718292f2SDouglas Gregor 
1484718292f2SDouglas Gregor   public:
1485718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14868587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14878587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1488c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1489bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1490beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1491c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1492718292f2SDouglas Gregor       Tok.clear();
1493718292f2SDouglas Gregor       consumeToken();
1494718292f2SDouglas Gregor     }
1495718292f2SDouglas Gregor 
1496718292f2SDouglas Gregor     bool parseModuleMapFile();
14978128f332SRichard Smith 
14988128f332SRichard Smith     bool terminatedByDirective() { return false; }
14998128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1500718292f2SDouglas Gregor   };
1501afd1b1c9SEugene Zelenko 
1502afd1b1c9SEugene Zelenko } // namespace clang
1503718292f2SDouglas Gregor 
1504718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1505718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1506718292f2SDouglas Gregor 
15078128f332SRichard Smith retry:
15088128f332SRichard Smith   Tok.clear();
1509718292f2SDouglas Gregor   Token LToken;
1510718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1511718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1512718292f2SDouglas Gregor   switch (LToken.getKind()) {
15132d57cea2SAlp Toker   case tok::raw_identifier: {
15142d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
15152d57cea2SAlp Toker     Tok.StringData = RI.data();
15162d57cea2SAlp Toker     Tok.StringLength = RI.size();
15172d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
151835b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1519fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
152059527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1521718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
15222b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1523f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
152497292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1525755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
152635b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
15276ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1528718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1529b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
15301fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1531306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1532718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1533ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1534718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1535718292f2SDouglas Gregor     break;
15362d57cea2SAlp Toker   }
1537718292f2SDouglas Gregor 
15381fb5c3a6SDouglas Gregor   case tok::comma:
15391fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
15401fb5c3a6SDouglas Gregor     break;
15411fb5c3a6SDouglas Gregor 
1542718292f2SDouglas Gregor   case tok::eof:
1543718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1544718292f2SDouglas Gregor     break;
1545718292f2SDouglas Gregor 
1546718292f2SDouglas Gregor   case tok::l_brace:
1547718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1548718292f2SDouglas Gregor     break;
1549718292f2SDouglas Gregor 
1550a686e1b0SDouglas Gregor   case tok::l_square:
1551a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1552a686e1b0SDouglas Gregor     break;
1553a686e1b0SDouglas Gregor 
15542b82c2a5SDouglas Gregor   case tok::period:
15552b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15562b82c2a5SDouglas Gregor     break;
15572b82c2a5SDouglas Gregor 
1558718292f2SDouglas Gregor   case tok::r_brace:
1559718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1560718292f2SDouglas Gregor     break;
1561718292f2SDouglas Gregor 
1562a686e1b0SDouglas Gregor   case tok::r_square:
1563a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1564a686e1b0SDouglas Gregor     break;
1565a686e1b0SDouglas Gregor 
15662b82c2a5SDouglas Gregor   case tok::star:
15672b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15682b82c2a5SDouglas Gregor     break;
15692b82c2a5SDouglas Gregor 
1570a3feee2aSRichard Smith   case tok::exclaim:
1571a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1572a3feee2aSRichard Smith     break;
1573a3feee2aSRichard Smith 
1574718292f2SDouglas Gregor   case tok::string_literal: {
1575d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1576d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1577d67aea28SRichard Smith       HadError = true;
1578d67aea28SRichard Smith       goto retry;
1579d67aea28SRichard Smith     }
1580d67aea28SRichard Smith 
1581718292f2SDouglas Gregor     // Parse the string literal.
1582718292f2SDouglas Gregor     LangOptions LangOpts;
15839d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1584718292f2SDouglas Gregor     if (StringLiteral.hadError)
1585718292f2SDouglas Gregor       goto retry;
1586718292f2SDouglas Gregor 
1587718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1588718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1589718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1590718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1591718292f2SDouglas Gregor     Saved[Length] = 0;
1592718292f2SDouglas Gregor 
1593718292f2SDouglas Gregor     // Form the token.
1594718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1595718292f2SDouglas Gregor     Tok.StringData = Saved;
1596718292f2SDouglas Gregor     Tok.StringLength = Length;
1597718292f2SDouglas Gregor     break;
1598718292f2SDouglas Gregor   }
1599718292f2SDouglas Gregor 
1600040e1266SRichard Smith   case tok::numeric_constant: {
1601040e1266SRichard Smith     // We don't support any suffixes or other complications.
1602040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1603040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1604040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1605040e1266SRichard Smith     unsigned Length =
1606040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1607040e1266SRichard Smith     uint64_t Value;
1608040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1609040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1610040e1266SRichard Smith       HadError = true;
1611040e1266SRichard Smith       goto retry;
1612040e1266SRichard Smith     }
1613040e1266SRichard Smith 
1614040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1615040e1266SRichard Smith     Tok.IntegerValue = Value;
1616040e1266SRichard Smith     break;
1617040e1266SRichard Smith   }
1618040e1266SRichard Smith 
1619718292f2SDouglas Gregor   case tok::comment:
1620718292f2SDouglas Gregor     goto retry;
1621718292f2SDouglas Gregor 
16228128f332SRichard Smith   case tok::hash:
16238128f332SRichard Smith     // A module map can be terminated prematurely by
16248128f332SRichard Smith     //   #pragma clang module contents
16258128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
16268128f332SRichard Smith     // contents of the module.
16278128f332SRichard Smith     {
16288128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
16298128f332SRichard Smith         L.LexFromRawLexer(LToken);
16308128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16318128f332SRichard Smith                LToken.getRawIdentifier() == Str;
16328128f332SRichard Smith       };
16338128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16348128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
16358128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
16368128f332SRichard Smith         break;
16378128f332SRichard Smith       }
16388128f332SRichard Smith     }
16398128f332SRichard Smith     LLVM_FALLTHROUGH;
16408128f332SRichard Smith 
1641718292f2SDouglas Gregor   default:
16428128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1643718292f2SDouglas Gregor     HadError = true;
1644718292f2SDouglas Gregor     goto retry;
1645718292f2SDouglas Gregor   }
1646718292f2SDouglas Gregor 
1647718292f2SDouglas Gregor   return Result;
1648718292f2SDouglas Gregor }
1649718292f2SDouglas Gregor 
1650718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1651718292f2SDouglas Gregor   unsigned braceDepth = 0;
1652a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1653718292f2SDouglas Gregor   do {
1654718292f2SDouglas Gregor     switch (Tok.Kind) {
1655718292f2SDouglas Gregor     case MMToken::EndOfFile:
1656718292f2SDouglas Gregor       return;
1657718292f2SDouglas Gregor 
1658718292f2SDouglas Gregor     case MMToken::LBrace:
1659a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1660718292f2SDouglas Gregor         return;
1661718292f2SDouglas Gregor 
1662718292f2SDouglas Gregor       ++braceDepth;
1663718292f2SDouglas Gregor       break;
1664718292f2SDouglas Gregor 
1665a686e1b0SDouglas Gregor     case MMToken::LSquare:
1666a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1667a686e1b0SDouglas Gregor         return;
1668a686e1b0SDouglas Gregor 
1669a686e1b0SDouglas Gregor       ++squareDepth;
1670a686e1b0SDouglas Gregor       break;
1671a686e1b0SDouglas Gregor 
1672718292f2SDouglas Gregor     case MMToken::RBrace:
1673718292f2SDouglas Gregor       if (braceDepth > 0)
1674718292f2SDouglas Gregor         --braceDepth;
1675718292f2SDouglas Gregor       else if (Tok.is(K))
1676718292f2SDouglas Gregor         return;
1677718292f2SDouglas Gregor       break;
1678718292f2SDouglas Gregor 
1679a686e1b0SDouglas Gregor     case MMToken::RSquare:
1680a686e1b0SDouglas Gregor       if (squareDepth > 0)
1681a686e1b0SDouglas Gregor         --squareDepth;
1682a686e1b0SDouglas Gregor       else if (Tok.is(K))
1683a686e1b0SDouglas Gregor         return;
1684a686e1b0SDouglas Gregor       break;
1685a686e1b0SDouglas Gregor 
1686718292f2SDouglas Gregor     default:
1687a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1688718292f2SDouglas Gregor         return;
1689718292f2SDouglas Gregor       break;
1690718292f2SDouglas Gregor     }
1691718292f2SDouglas Gregor 
1692718292f2SDouglas Gregor    consumeToken();
1693718292f2SDouglas Gregor   } while (true);
1694718292f2SDouglas Gregor }
1695718292f2SDouglas Gregor 
16969fc8faf9SAdrian Prantl /// Parse a module-id.
1697e7ab3669SDouglas Gregor ///
1698e7ab3669SDouglas Gregor ///   module-id:
1699e7ab3669SDouglas Gregor ///     identifier
1700e7ab3669SDouglas Gregor ///     identifier '.' module-id
1701e7ab3669SDouglas Gregor ///
1702e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1703e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1704e7ab3669SDouglas Gregor   Id.clear();
1705e7ab3669SDouglas Gregor   do {
17063cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1707adcd0268SBenjamin Kramer       Id.push_back(
1708adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1709e7ab3669SDouglas Gregor       consumeToken();
1710e7ab3669SDouglas Gregor     } else {
1711e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1712e7ab3669SDouglas Gregor       return true;
1713e7ab3669SDouglas Gregor     }
1714e7ab3669SDouglas Gregor 
1715e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1716e7ab3669SDouglas Gregor       break;
1717e7ab3669SDouglas Gregor 
1718e7ab3669SDouglas Gregor     consumeToken();
1719e7ab3669SDouglas Gregor   } while (true);
1720e7ab3669SDouglas Gregor 
1721e7ab3669SDouglas Gregor   return false;
1722e7ab3669SDouglas Gregor }
1723e7ab3669SDouglas Gregor 
1724a686e1b0SDouglas Gregor namespace {
1725afd1b1c9SEugene Zelenko 
17269fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1727a686e1b0SDouglas Gregor   enum AttributeKind {
17289fc8faf9SAdrian Prantl     /// An unknown attribute.
1729a686e1b0SDouglas Gregor     AT_unknown,
1730afd1b1c9SEugene Zelenko 
17319fc8faf9SAdrian Prantl     /// The 'system' attribute.
173235b13eceSDouglas Gregor     AT_system,
1733afd1b1c9SEugene Zelenko 
17349fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
173577944868SRichard Smith     AT_extern_c,
1736afd1b1c9SEugene Zelenko 
17379fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1738ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1739afd1b1c9SEugene Zelenko 
17409fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1741ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1742a686e1b0SDouglas Gregor   };
1743afd1b1c9SEugene Zelenko 
1744afd1b1c9SEugene Zelenko } // namespace
1745a686e1b0SDouglas Gregor 
174629729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
174729729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
174829729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
174929729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17505f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17515f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
175229729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17537d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
175429729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
175529729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
175629729919SBruno Cardoso Lopes     D << BadName << M->Name;
17577d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
175829729919SBruno Cardoso Lopes   };
175929729919SBruno Cardoso Lopes 
176029729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
176129729919SBruno Cardoso Lopes     auto const *M = E->getValue();
176229729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
176329729919SBruno Cardoso Lopes       continue;
176429729919SBruno Cardoso Lopes 
176529729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
176629729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
176729729919SBruno Cardoso Lopes       continue;
17685f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
176929729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
177029729919SBruno Cardoso Lopes     Canonical.append("_Private");
177129729919SBruno Cardoso Lopes 
177229729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
177329729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
177429729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
177529729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
177629729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
177729729919SBruno Cardoso Lopes           << FullName;
17785f11e128SBruno Cardoso Lopes 
17795f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17805f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17815f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17825f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17835f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17845f11e128SBruno Cardoso Lopes 
17855f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17865f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17875f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17885f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
17895f11e128SBruno Cardoso Lopes 
17905f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17915f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
179229729919SBruno Cardoso Lopes       continue;
179329729919SBruno Cardoso Lopes     }
179429729919SBruno Cardoso Lopes 
179529729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
179629729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
179729729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
179829729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
179929729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
180029729919SBruno Cardoso Lopes           << ActiveModule->Name;
18017d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18027d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
180329729919SBruno Cardoso Lopes     }
180429729919SBruno Cardoso Lopes   }
180529729919SBruno Cardoso Lopes }
180629729919SBruno Cardoso Lopes 
18079fc8faf9SAdrian Prantl /// Parse a module declaration.
1808718292f2SDouglas Gregor ///
1809718292f2SDouglas Gregor ///   module-declaration:
181097292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1811a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1812a686e1b0SDouglas Gregor ///       { module-member* }
1813a686e1b0SDouglas Gregor ///
1814718292f2SDouglas Gregor ///   module-member:
18151fb5c3a6SDouglas Gregor ///     requires-declaration
1816718292f2SDouglas Gregor ///     header-declaration
1817e7ab3669SDouglas Gregor ///     submodule-declaration
18182b82c2a5SDouglas Gregor ///     export-declaration
1819f0b11de2SDouglas Gregor ///     export-as-declaration
18206ddfca91SDouglas Gregor ///     link-declaration
182173441091SDouglas Gregor ///
182273441091SDouglas Gregor ///   submodule-declaration:
182373441091SDouglas Gregor ///     module-declaration
182473441091SDouglas Gregor ///     inferred-submodule-declaration
1825718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1826755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
182797292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
182897292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
182997292843SDaniel Jasper     parseExternModuleDecl();
183097292843SDaniel Jasper     return;
183197292843SDaniel Jasper   }
183297292843SDaniel Jasper 
1833f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1834e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
18355f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1836718292f2SDouglas Gregor   bool Explicit = false;
1837f2161a70SDouglas Gregor   bool Framework = false;
1838755b2055SDouglas Gregor 
1839f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1840f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1841e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1842f2161a70SDouglas Gregor     Explicit = true;
1843f2161a70SDouglas Gregor   }
1844f2161a70SDouglas Gregor 
1845f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1846755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18475f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1848755b2055SDouglas Gregor     Framework = true;
1849755b2055SDouglas Gregor   }
1850718292f2SDouglas Gregor 
1851718292f2SDouglas Gregor   // Parse 'module' keyword.
1852718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1853d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1854718292f2SDouglas Gregor     consumeToken();
1855718292f2SDouglas Gregor     HadError = true;
1856718292f2SDouglas Gregor     return;
1857718292f2SDouglas Gregor   }
18589f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1859718292f2SDouglas Gregor 
186073441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
186173441091SDouglas Gregor   // Parse it.
186273441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18639194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
186473441091SDouglas Gregor 
1865718292f2SDouglas Gregor   // Parse the module name.
1866e7ab3669SDouglas Gregor   ModuleId Id;
1867e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1868718292f2SDouglas Gregor     HadError = true;
1869718292f2SDouglas Gregor     return;
1870718292f2SDouglas Gregor   }
1871e7ab3669SDouglas Gregor 
1872e7ab3669SDouglas Gregor   if (ActiveModule) {
1873e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1874e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1875e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1876e7ab3669SDouglas Gregor 
1877e7ab3669SDouglas Gregor       HadError = true;
1878e7ab3669SDouglas Gregor       return;
1879e7ab3669SDouglas Gregor     }
1880e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1881e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1882e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1883e7ab3669SDouglas Gregor     Explicit = false;
1884e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1885e7ab3669SDouglas Gregor     HadError = true;
1886e7ab3669SDouglas Gregor   }
1887e7ab3669SDouglas Gregor 
1888e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1889e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1890e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1891e7ab3669SDouglas Gregor     // is a submodule.
1892d2d442caSCraig Topper     ActiveModule = nullptr;
18934b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1894e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1895e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
18964b8a9e95SBen Langmuir         if (I == 0)
18974b8a9e95SBen Langmuir           TopLevelModule = Next;
1898e7ab3669SDouglas Gregor         ActiveModule = Next;
1899e7ab3669SDouglas Gregor         continue;
1900e7ab3669SDouglas Gregor       }
1901e7ab3669SDouglas Gregor 
1902e7ab3669SDouglas Gregor       if (ActiveModule) {
1903e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
19045b5d21eaSRichard Smith           << Id[I].first
19055b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1906e7ab3669SDouglas Gregor       } else {
1907e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1908e7ab3669SDouglas Gregor       }
1909e7ab3669SDouglas Gregor       HadError = true;
1910e7ab3669SDouglas Gregor       return;
1911e7ab3669SDouglas Gregor     }
19124b8a9e95SBen Langmuir 
19134b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19144b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19154b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
19164b8a9e95SBen Langmuir              "top-level module");
19174b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19184b8a9e95SBen Langmuir     }
1919e7ab3669SDouglas Gregor   }
1920e7ab3669SDouglas Gregor 
1921e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1922e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1923718292f2SDouglas Gregor 
1924a686e1b0SDouglas Gregor   // Parse the optional attribute list.
19254442605fSBill Wendling   Attributes Attrs;
19265d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
19275d29dee0SDavide Italiano     return;
19285d29dee0SDavide Italiano 
1929718292f2SDouglas Gregor   // Parse the opening brace.
1930718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1931718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1932718292f2SDouglas Gregor       << ModuleName;
1933718292f2SDouglas Gregor     HadError = true;
1934718292f2SDouglas Gregor     return;
1935718292f2SDouglas Gregor   }
1936718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1937718292f2SDouglas Gregor 
1938718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
19398587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1940eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19414a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
19424a3751ffSRichard Smith     // definition for in two cases:
19434a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19444a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19454a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19464a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19474a3751ffSRichard Smith     //    module map file from which it was created.
19484a3751ffSRichard Smith     bool ParsedAsMainInput =
19494a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19504a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19514a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19524a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19534a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1954fcc54a3bSDouglas Gregor       // Skip the module definition.
1955fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1956fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1957fcc54a3bSDouglas Gregor         consumeToken();
1958fcc54a3bSDouglas Gregor       else {
1959fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1960fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1961fcc54a3bSDouglas Gregor         HadError = true;
1962fcc54a3bSDouglas Gregor       }
1963fcc54a3bSDouglas Gregor       return;
1964fcc54a3bSDouglas Gregor     }
1965fcc54a3bSDouglas Gregor 
1966c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19678587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19688587dfd9SBruno Cardoso Lopes     } else {
19698587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1970718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1971718292f2SDouglas Gregor           << ModuleName;
1972eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1973718292f2SDouglas Gregor 
1974718292f2SDouglas Gregor       // Skip the module definition.
1975718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1976718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1977718292f2SDouglas Gregor         consumeToken();
1978718292f2SDouglas Gregor 
1979718292f2SDouglas Gregor       HadError = true;
1980718292f2SDouglas Gregor       return;
1981718292f2SDouglas Gregor     }
19828587dfd9SBruno Cardoso Lopes   }
1983718292f2SDouglas Gregor 
1984718292f2SDouglas Gregor   // Start defining this module.
19858587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19868587dfd9SBruno Cardoso Lopes     ActiveModule =
19878587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19888587dfd9SBruno Cardoso Lopes   } else {
1989c192d194SBruno Cardoso Lopes     ActiveModule =
1990c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19918587dfd9SBruno Cardoso Lopes             .first;
19928587dfd9SBruno Cardoso Lopes   }
19938587dfd9SBruno Cardoso Lopes 
1994eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1995963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1996a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
199777944868SRichard Smith   if (Attrs.IsExternC)
199877944868SRichard Smith     ActiveModule->IsExternC = true;
1999ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
2000ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
2001ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
20023c1a41adSRichard Smith   ActiveModule->Directory = Directory;
2003718292f2SDouglas Gregor 
200490b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
200590b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
200690b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
200790b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
200890b0a1fcSJordan Rose   }
200929729919SBruno Cardoso Lopes 
201029729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
201129729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
201229729919SBruno Cardoso Lopes   // Foo_Private instead.
201329729919SBruno Cardoso Lopes   SourceLocation StartLoc =
201429729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
201529729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
201629729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
201729729919SBruno Cardoso Lopes                        StartLoc) &&
201829729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
201929729919SBruno Cardoso Lopes                        StartLoc) &&
202090b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
20215f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20224d867640SGraydon Hoare 
2023718292f2SDouglas Gregor   bool Done = false;
2024718292f2SDouglas Gregor   do {
2025718292f2SDouglas Gregor     switch (Tok.Kind) {
2026718292f2SDouglas Gregor     case MMToken::EndOfFile:
2027718292f2SDouglas Gregor     case MMToken::RBrace:
2028718292f2SDouglas Gregor       Done = true;
2029718292f2SDouglas Gregor       break;
2030718292f2SDouglas Gregor 
203135b13eceSDouglas Gregor     case MMToken::ConfigMacros:
203235b13eceSDouglas Gregor       parseConfigMacros();
203335b13eceSDouglas Gregor       break;
203435b13eceSDouglas Gregor 
2035fb912657SDouglas Gregor     case MMToken::Conflict:
2036fb912657SDouglas Gregor       parseConflict();
2037fb912657SDouglas Gregor       break;
2038fb912657SDouglas Gregor 
2039718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
204097292843SDaniel Jasper     case MMToken::ExternKeyword:
2041f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
2042718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2043718292f2SDouglas Gregor       parseModuleDecl();
2044718292f2SDouglas Gregor       break;
2045718292f2SDouglas Gregor 
20462b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20472b82c2a5SDouglas Gregor       parseExportDecl();
20482b82c2a5SDouglas Gregor       break;
20492b82c2a5SDouglas Gregor 
2050f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2051f0b11de2SDouglas Gregor       parseExportAsDecl();
2052f0b11de2SDouglas Gregor       break;
2053f0b11de2SDouglas Gregor 
2054ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2055ba7f2f71SDaniel Jasper       parseUseDecl();
2056ba7f2f71SDaniel Jasper       break;
2057ba7f2f71SDaniel Jasper 
20581fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20591fb5c3a6SDouglas Gregor       parseRequiresDecl();
20601fb5c3a6SDouglas Gregor       break;
20611fb5c3a6SDouglas Gregor 
2062202210b3SRichard Smith     case MMToken::TextualKeyword:
2063202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2064306d8920SRichard Smith       break;
2065306d8920SRichard Smith 
2066524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2067524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2068524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2069b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2070524e33e1SDouglas Gregor       else
2071524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2072718292f2SDouglas Gregor       break;
2073524e33e1SDouglas Gregor     }
2074718292f2SDouglas Gregor 
2075202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2076202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
207759527666SDouglas Gregor       break;
207859527666SDouglas Gregor 
2079202210b3SRichard Smith     case MMToken::PrivateKeyword:
2080202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2081b53e5483SLawrence Crowl       break;
2082b53e5483SLawrence Crowl 
2083322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2084202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2085718292f2SDouglas Gregor       break;
2086718292f2SDouglas Gregor 
20876ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20886ddfca91SDouglas Gregor       parseLinkDecl();
20896ddfca91SDouglas Gregor       break;
20906ddfca91SDouglas Gregor 
2091718292f2SDouglas Gregor     default:
2092718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2093718292f2SDouglas Gregor       consumeToken();
2094718292f2SDouglas Gregor       break;
2095718292f2SDouglas Gregor     }
2096718292f2SDouglas Gregor   } while (!Done);
2097718292f2SDouglas Gregor 
2098718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2099718292f2SDouglas Gregor     consumeToken();
2100718292f2SDouglas Gregor   else {
2101718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2102718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2103718292f2SDouglas Gregor     HadError = true;
2104718292f2SDouglas Gregor   }
2105718292f2SDouglas Gregor 
210611dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
210711dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
210811dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
210911dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
211011dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
211111dfe6feSDouglas Gregor   }
211211dfe6feSDouglas Gregor 
2113ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2114ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2115fc76b4adSRichard Smith   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2116ec8c9752SBen Langmuir       ActiveModule->Parent) {
2117fc76b4adSRichard Smith     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2118ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2119ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2120ec8c9752SBen Langmuir   }
2121ec8c9752SBen Langmuir 
2122e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2123e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2124718292f2SDouglas Gregor }
2125718292f2SDouglas Gregor 
21269fc8faf9SAdrian Prantl /// Parse an extern module declaration.
212797292843SDaniel Jasper ///
212897292843SDaniel Jasper ///   extern module-declaration:
212997292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
213097292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
213197292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2132ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
213397292843SDaniel Jasper 
213497292843SDaniel Jasper   // Parse 'module' keyword.
213597292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
213697292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
213797292843SDaniel Jasper     consumeToken();
213897292843SDaniel Jasper     HadError = true;
213997292843SDaniel Jasper     return;
214097292843SDaniel Jasper   }
214197292843SDaniel Jasper   consumeToken(); // 'module' keyword
214297292843SDaniel Jasper 
214397292843SDaniel Jasper   // Parse the module name.
214497292843SDaniel Jasper   ModuleId Id;
214597292843SDaniel Jasper   if (parseModuleId(Id)) {
214697292843SDaniel Jasper     HadError = true;
214797292843SDaniel Jasper     return;
214897292843SDaniel Jasper   }
214997292843SDaniel Jasper 
215097292843SDaniel Jasper   // Parse the referenced module map file name.
215197292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
215297292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
215397292843SDaniel Jasper     HadError = true;
215497292843SDaniel Jasper     return;
215597292843SDaniel Jasper   }
2156adcd0268SBenjamin Kramer   std::string FileName = std::string(Tok.getString());
215797292843SDaniel Jasper   consumeToken(); // filename
215897292843SDaniel Jasper 
215997292843SDaniel Jasper   StringRef FileNameRef = FileName;
216097292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
216197292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
216297292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
216397292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
216492e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
216597292843SDaniel Jasper   }
21668d323d15SHarlan Haskins   if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21679acb99e3SRichard Smith     Map.parseModuleMapFile(
21688d323d15SHarlan Haskins         *File, /*IsSystem=*/false,
21699acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21709acb99e3SRichard Smith             ? Directory
21718d323d15SHarlan Haskins             : (*File)->getDir(),
2172c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
217397292843SDaniel Jasper }
217497292843SDaniel Jasper 
21757ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21767ff29148SBen Langmuir ///
21777ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21787ff29148SBen Langmuir /// module map files:
21797ff29148SBen Langmuir ///
21807ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21817ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21827ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21837ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21847ff29148SBen Langmuir ///    module to 'textual'.
21857ff29148SBen Langmuir ///
21867ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21877ff29148SBen Langmuir ///
21887ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21897ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21907ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21917ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21928013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21938013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21948013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21957ff29148SBen Langmuir     IsRequiresExcludedHack = true;
21967ff29148SBen Langmuir     return false;
21978013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21987ff29148SBen Langmuir     return false;
21997ff29148SBen Langmuir   }
22007ff29148SBen Langmuir 
22017ff29148SBen Langmuir   return true;
22027ff29148SBen Langmuir }
22037ff29148SBen Langmuir 
22049fc8faf9SAdrian Prantl /// Parse a requires declaration.
22051fb5c3a6SDouglas Gregor ///
22061fb5c3a6SDouglas Gregor ///   requires-declaration:
22071fb5c3a6SDouglas Gregor ///     'requires' feature-list
22081fb5c3a6SDouglas Gregor ///
22091fb5c3a6SDouglas Gregor ///   feature-list:
2210a3feee2aSRichard Smith ///     feature ',' feature-list
2211a3feee2aSRichard Smith ///     feature
2212a3feee2aSRichard Smith ///
2213a3feee2aSRichard Smith ///   feature:
2214a3feee2aSRichard Smith ///     '!'[opt] identifier
22151fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
22161fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
22171fb5c3a6SDouglas Gregor 
22181fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
22191fb5c3a6SDouglas Gregor   consumeToken();
22201fb5c3a6SDouglas Gregor 
22211fb5c3a6SDouglas Gregor   // Parse the feature-list.
22221fb5c3a6SDouglas Gregor   do {
2223a3feee2aSRichard Smith     bool RequiredState = true;
2224a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2225a3feee2aSRichard Smith       RequiredState = false;
2226a3feee2aSRichard Smith       consumeToken();
2227a3feee2aSRichard Smith     }
2228a3feee2aSRichard Smith 
22291fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
22301fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22311fb5c3a6SDouglas Gregor       HadError = true;
22321fb5c3a6SDouglas Gregor       return;
22331fb5c3a6SDouglas Gregor     }
22341fb5c3a6SDouglas Gregor 
22351fb5c3a6SDouglas Gregor     // Consume the feature name.
2236adcd0268SBenjamin Kramer     std::string Feature = std::string(Tok.getString());
22371fb5c3a6SDouglas Gregor     consumeToken();
22381fb5c3a6SDouglas Gregor 
22397ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
22407ff29148SBen Langmuir     bool ShouldAddRequirement =
22417ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22427ff29148SBen Langmuir 
22437ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22447ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22457ff29148SBen Langmuir 
22467ff29148SBen Langmuir     if (ShouldAddRequirement) {
22471fb5c3a6SDouglas Gregor       // Add this feature.
22487ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22497ff29148SBen Langmuir                                    *Map.Target);
22507ff29148SBen Langmuir     }
22511fb5c3a6SDouglas Gregor 
22521fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22531fb5c3a6SDouglas Gregor       break;
22541fb5c3a6SDouglas Gregor 
22551fb5c3a6SDouglas Gregor     // Consume the comma.
22561fb5c3a6SDouglas Gregor     consumeToken();
22571fb5c3a6SDouglas Gregor   } while (true);
22581fb5c3a6SDouglas Gregor }
22591fb5c3a6SDouglas Gregor 
22609fc8faf9SAdrian Prantl /// Parse a header declaration.
2261718292f2SDouglas Gregor ///
2262718292f2SDouglas Gregor ///   header-declaration:
2263306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2264202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2265202210b3SRichard Smith ///     'exclude' 'header' string-literal
2266202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2267306d8920SRichard Smith ///
2268306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2269b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2270b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2271202210b3SRichard Smith   // We've already consumed the first token.
2272202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2273202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2274202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2275202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2276202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2277202210b3SRichard Smith       LeadingToken = Tok.Kind;
22781871ed3dSBenjamin Kramer       consumeToken();
2279202210b3SRichard Smith     }
2280202210b3SRichard Smith   }
22817ff29148SBen Langmuir 
2282202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2283202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2284202210b3SRichard Smith 
22857ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22867ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22877ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22887ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22897ff29148SBen Langmuir   }
22907ff29148SBen Langmuir 
2291202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2292202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2293202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2294202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2295202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2296202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2297202210b3SRichard Smith       return;
2298202210b3SRichard Smith     }
2299202210b3SRichard Smith     consumeToken();
2300202210b3SRichard Smith   }
2301718292f2SDouglas Gregor 
2302718292f2SDouglas Gregor   // Parse the header name.
2303718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2304718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2305718292f2SDouglas Gregor       << "header";
2306718292f2SDouglas Gregor     HadError = true;
2307718292f2SDouglas Gregor     return;
2308718292f2SDouglas Gregor   }
23093c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
2310adcd0268SBenjamin Kramer   Header.FileName = std::string(Tok.getString());
23110761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
23121d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2313040e1266SRichard Smith   Header.Kind =
2314040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2315040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2316718292f2SDouglas Gregor 
2317524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
23181d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
23190761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2320524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2321322f633cSDouglas Gregor     HadError = true;
2322322f633cSDouglas Gregor     return;
2323322f633cSDouglas Gregor   }
2324322f633cSDouglas Gregor 
2325040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2326040e1266SRichard Smith   // the file.
2327040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2328040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
23293ec6663bSDouglas Gregor 
2330040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2331040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2332040e1266SRichard Smith       StringRef Str = Tok.getString();
2333040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2334040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2335040e1266SRichard Smith                   .Case("size", Size)
2336040e1266SRichard Smith                   .Case("mtime", ModTime)
2337040e1266SRichard Smith                   .Default(Unknown)) {
2338040e1266SRichard Smith       case Size:
2339040e1266SRichard Smith         if (Header.Size)
2340040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2341040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2342040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2343040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2344040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2345040e1266SRichard Smith           break;
2346040e1266SRichard Smith         }
2347040e1266SRichard Smith         Header.Size = Tok.getInteger();
2348040e1266SRichard Smith         consumeToken();
2349040e1266SRichard Smith         break;
2350040e1266SRichard Smith 
2351040e1266SRichard Smith       case ModTime:
2352040e1266SRichard Smith         if (Header.ModTime)
2353040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2354040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2355040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2356040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2357040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2358040e1266SRichard Smith           break;
2359040e1266SRichard Smith         }
2360040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2361040e1266SRichard Smith         consumeToken();
2362040e1266SRichard Smith         break;
2363040e1266SRichard Smith 
2364040e1266SRichard Smith       case Unknown:
2365040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2366040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2367040e1266SRichard Smith         break;
2368040e1266SRichard Smith       }
23693ec6663bSDouglas Gregor     }
23705257fc63SDouglas Gregor 
2371040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2372040e1266SRichard Smith       consumeToken();
2373040e1266SRichard Smith     else {
2374040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2375040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2376322f633cSDouglas Gregor       HadError = true;
2377322f633cSDouglas Gregor     }
23780101b540SHans Wennborg   }
237925d50758SRichard Smith 
23809f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23819f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23829f6020bcSBruno Cardoso Lopes 
23839f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23849f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23859f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23869f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2387718292f2SDouglas Gregor }
2388718292f2SDouglas Gregor 
238941f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
239041f81994SBen Langmuir                                 const Module::Header *B) {
239141f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
239241f81994SBen Langmuir }
239341f81994SBen Langmuir 
23949fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2395524e33e1SDouglas Gregor ///
2396524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2397524e33e1SDouglas Gregor ///     umbrella string-literal
2398524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2399524e33e1SDouglas Gregor   // Parse the directory name.
2400524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2401524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2402524e33e1SDouglas Gregor       << "umbrella";
2403524e33e1SDouglas Gregor     HadError = true;
2404524e33e1SDouglas Gregor     return;
2405524e33e1SDouglas Gregor   }
2406524e33e1SDouglas Gregor 
2407adcd0268SBenjamin Kramer   std::string DirName = std::string(Tok.getString());
2408524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2409524e33e1SDouglas Gregor 
2410524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2411524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2412524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2413524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2414524e33e1SDouglas Gregor     HadError = true;
2415524e33e1SDouglas Gregor     return;
2416524e33e1SDouglas Gregor   }
2417524e33e1SDouglas Gregor 
2418524e33e1SDouglas Gregor   // Look for this file.
2419d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
24208d323d15SHarlan Haskins   if (llvm::sys::path::is_absolute(DirName)) {
24218d323d15SHarlan Haskins     if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24228d323d15SHarlan Haskins       Dir = *D;
24238d323d15SHarlan Haskins   } else {
24242c1dd271SDylan Noblesmith     SmallString<128> PathName;
2425524e33e1SDouglas Gregor     PathName = Directory->getName();
2426524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
24278d323d15SHarlan Haskins     if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24288d323d15SHarlan Haskins       Dir = *D;
2429524e33e1SDouglas Gregor   }
2430524e33e1SDouglas Gregor 
2431524e33e1SDouglas Gregor   if (!Dir) {
2432a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2433524e33e1SDouglas Gregor       << DirName;
2434524e33e1SDouglas Gregor     return;
2435524e33e1SDouglas Gregor   }
2436524e33e1SDouglas Gregor 
24377ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24387ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
24397ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24407ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
24417ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
24427ff29148SBen Langmuir     std::error_code EC;
24437ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2444fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2445db8a7422SDuncan P. N. Exon Smith         SourceMgr.getFileManager().getVirtualFileSystem();
2446fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24477ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
24488d323d15SHarlan Haskins       if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2449adcd0268SBenjamin Kramer         Module::Header Header = {std::string(I->path()), *FE};
24507ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24517ff29148SBen Langmuir       }
24527ff29148SBen Langmuir     }
24537ff29148SBen Langmuir 
24547ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
245541f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
245641f81994SBen Langmuir 
24577ff29148SBen Langmuir     for (auto &Header : Headers)
24587ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24597ff29148SBen Langmuir     return;
24607ff29148SBen Langmuir   }
24617ff29148SBen Langmuir 
2462524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2463524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2464524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2465524e33e1SDouglas Gregor     HadError = true;
2466524e33e1SDouglas Gregor     return;
2467524e33e1SDouglas Gregor   }
2468524e33e1SDouglas Gregor 
2469524e33e1SDouglas Gregor   // Record this umbrella directory.
24702b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2471524e33e1SDouglas Gregor }
2472524e33e1SDouglas Gregor 
24739fc8faf9SAdrian Prantl /// Parse a module export declaration.
24742b82c2a5SDouglas Gregor ///
24752b82c2a5SDouglas Gregor ///   export-declaration:
24762b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24772b82c2a5SDouglas Gregor ///
24782b82c2a5SDouglas Gregor ///   wildcard-module-id:
24792b82c2a5SDouglas Gregor ///     identifier
24802b82c2a5SDouglas Gregor ///     '*'
24812b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24822b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24832b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24842b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24852b82c2a5SDouglas Gregor 
24862b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24872b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24882b82c2a5SDouglas Gregor   bool Wildcard = false;
24892b82c2a5SDouglas Gregor   do {
2490306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24912b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
2492adcd0268SBenjamin Kramer       ParsedModuleId.push_back(
2493adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
24942b82c2a5SDouglas Gregor       consumeToken();
24952b82c2a5SDouglas Gregor 
24962b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
24972b82c2a5SDouglas Gregor         consumeToken();
24982b82c2a5SDouglas Gregor         continue;
24992b82c2a5SDouglas Gregor       }
25002b82c2a5SDouglas Gregor 
25012b82c2a5SDouglas Gregor       break;
25022b82c2a5SDouglas Gregor     }
25032b82c2a5SDouglas Gregor 
25042b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
25052b82c2a5SDouglas Gregor       Wildcard = true;
2506f5eedd05SDouglas Gregor       consumeToken();
25072b82c2a5SDouglas Gregor       break;
25082b82c2a5SDouglas Gregor     }
25092b82c2a5SDouglas Gregor 
2510ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25112b82c2a5SDouglas Gregor     HadError = true;
25122b82c2a5SDouglas Gregor     return;
25132b82c2a5SDouglas Gregor   } while (true);
25142b82c2a5SDouglas Gregor 
25152b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
25162b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
25172b82c2a5SDouglas Gregor   };
25182b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
25192b82c2a5SDouglas Gregor }
25202b82c2a5SDouglas Gregor 
25219fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2522f0b11de2SDouglas Gregor ///
2523f0b11de2SDouglas Gregor ///   export-as-declaration:
2524f0b11de2SDouglas Gregor ///     'export_as' identifier
2525f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2526f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2527f0b11de2SDouglas Gregor   consumeToken();
2528f0b11de2SDouglas Gregor 
2529f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2530f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2531f0b11de2SDouglas Gregor     HadError = true;
2532f0b11de2SDouglas Gregor     return;
2533f0b11de2SDouglas Gregor   }
2534f0b11de2SDouglas Gregor 
2535f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2536f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2537f0b11de2SDouglas Gregor     consumeToken();
2538f0b11de2SDouglas Gregor     return;
2539f0b11de2SDouglas Gregor   }
2540f0b11de2SDouglas Gregor 
2541f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2542f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2543f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2544f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2545f0b11de2SDouglas Gregor     } else {
2546f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2547f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2548f0b11de2SDouglas Gregor         << Tok.getString();
2549f0b11de2SDouglas Gregor     }
2550f0b11de2SDouglas Gregor   }
2551f0b11de2SDouglas Gregor 
2552adcd0268SBenjamin Kramer   ActiveModule->ExportAsModule = std::string(Tok.getString());
2553a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2554a3b5f71eSBruno Cardoso Lopes 
2555f0b11de2SDouglas Gregor   consumeToken();
2556f0b11de2SDouglas Gregor }
2557f0b11de2SDouglas Gregor 
25589fc8faf9SAdrian Prantl /// Parse a module use declaration.
2559ba7f2f71SDaniel Jasper ///
25608f4d3ff1SRichard Smith ///   use-declaration:
25618f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2562ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2563ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25648f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2565ba7f2f71SDaniel Jasper   // Parse the module-id.
2566ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25673cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2568ba7f2f71SDaniel Jasper 
25698f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25708f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25718f4d3ff1SRichard Smith   else
2572ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2573ba7f2f71SDaniel Jasper }
2574ba7f2f71SDaniel Jasper 
25759fc8faf9SAdrian Prantl /// Parse a link declaration.
25766ddfca91SDouglas Gregor ///
25776ddfca91SDouglas Gregor ///   module-declaration:
25786ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25796ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25806ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25816ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25826ddfca91SDouglas Gregor 
25836ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25846ddfca91SDouglas Gregor   bool IsFramework = false;
25856ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25866ddfca91SDouglas Gregor     consumeToken();
25876ddfca91SDouglas Gregor     IsFramework = true;
25886ddfca91SDouglas Gregor   }
25896ddfca91SDouglas Gregor 
25906ddfca91SDouglas Gregor   // Parse the library name
25916ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25926ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25936ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25946ddfca91SDouglas Gregor     HadError = true;
25956ddfca91SDouglas Gregor     return;
25966ddfca91SDouglas Gregor   }
25976ddfca91SDouglas Gregor 
2598adcd0268SBenjamin Kramer   std::string LibraryName = std::string(Tok.getString());
25996ddfca91SDouglas Gregor   consumeToken();
26006ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26016ddfca91SDouglas Gregor                                                             IsFramework));
26026ddfca91SDouglas Gregor }
26036ddfca91SDouglas Gregor 
26049fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
260535b13eceSDouglas Gregor ///
260635b13eceSDouglas Gregor ///   module-declaration:
260735b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
260835b13eceSDouglas Gregor ///
260935b13eceSDouglas Gregor ///   config-macro-list:
261035b13eceSDouglas Gregor ///     identifier (',' identifier)?
261135b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
261235b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
261335b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
261435b13eceSDouglas Gregor 
261535b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
261635b13eceSDouglas Gregor   if (ActiveModule->Parent) {
261735b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
261835b13eceSDouglas Gregor   }
261935b13eceSDouglas Gregor 
262035b13eceSDouglas Gregor   // Parse the optional attributes.
262135b13eceSDouglas Gregor   Attributes Attrs;
26225d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26235d29dee0SDavide Italiano     return;
26245d29dee0SDavide Italiano 
262535b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
262635b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
262735b13eceSDouglas Gregor   }
262835b13eceSDouglas Gregor 
262935b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2630306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
263135b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
263235b13eceSDouglas Gregor     return;
263335b13eceSDouglas Gregor 
263435b13eceSDouglas Gregor   // Consume the first identifier.
263535b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
263635b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
263735b13eceSDouglas Gregor   }
263835b13eceSDouglas Gregor   consumeToken();
263935b13eceSDouglas Gregor 
264035b13eceSDouglas Gregor   do {
264135b13eceSDouglas Gregor     // If there's a comma, consume it.
264235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
264335b13eceSDouglas Gregor       break;
264435b13eceSDouglas Gregor     consumeToken();
264535b13eceSDouglas Gregor 
264635b13eceSDouglas Gregor     // We expect to see a macro name here.
2647306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
264835b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
264935b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
265035b13eceSDouglas Gregor       break;
265135b13eceSDouglas Gregor     }
265235b13eceSDouglas Gregor 
265335b13eceSDouglas Gregor     // Consume the macro name.
265435b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
265535b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
265635b13eceSDouglas Gregor     }
265735b13eceSDouglas Gregor     consumeToken();
265835b13eceSDouglas Gregor   } while (true);
265935b13eceSDouglas Gregor }
266035b13eceSDouglas Gregor 
26619fc8faf9SAdrian Prantl /// Format a module-id into a string.
2662fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2663fb912657SDouglas Gregor   std::string result;
2664fb912657SDouglas Gregor   {
2665fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2666fb912657SDouglas Gregor 
2667fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2668fb912657SDouglas Gregor       if (I)
2669fb912657SDouglas Gregor         OS << ".";
2670fb912657SDouglas Gregor       OS << Id[I].first;
2671fb912657SDouglas Gregor     }
2672fb912657SDouglas Gregor   }
2673fb912657SDouglas Gregor 
2674fb912657SDouglas Gregor   return result;
2675fb912657SDouglas Gregor }
2676fb912657SDouglas Gregor 
26779fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2678fb912657SDouglas Gregor ///
2679fb912657SDouglas Gregor ///   module-declaration:
2680fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2681fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2682fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2683fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2684fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2685fb912657SDouglas Gregor 
2686fb912657SDouglas Gregor   // Parse the module-id.
2687fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2688fb912657SDouglas Gregor     return;
2689fb912657SDouglas Gregor 
2690fb912657SDouglas Gregor   // Parse the ','.
2691fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2692fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2693fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2694fb912657SDouglas Gregor     return;
2695fb912657SDouglas Gregor   }
2696fb912657SDouglas Gregor   consumeToken();
2697fb912657SDouglas Gregor 
2698fb912657SDouglas Gregor   // Parse the message.
2699fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2700fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2701fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2702fb912657SDouglas Gregor     return;
2703fb912657SDouglas Gregor   }
2704fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2705fb912657SDouglas Gregor   consumeToken();
2706fb912657SDouglas Gregor 
2707fb912657SDouglas Gregor   // Add this unresolved conflict.
2708fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2709fb912657SDouglas Gregor }
2710fb912657SDouglas Gregor 
27119fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
27129194a91dSDouglas Gregor ///
27139194a91dSDouglas Gregor ///   module-declaration:
27149194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27159194a91dSDouglas Gregor ///       { inferred-module-member* }
27169194a91dSDouglas Gregor ///
27179194a91dSDouglas Gregor ///   inferred-module-member:
27189194a91dSDouglas Gregor ///     'export' '*'
27199194a91dSDouglas Gregor ///     'exclude' identifier
27209194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
272173441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
272273441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
272373441091SDouglas Gregor   bool Failed = false;
272473441091SDouglas Gregor 
272573441091SDouglas Gregor   // Inferred modules must be submodules.
27269194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
272773441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
272873441091SDouglas Gregor     Failed = true;
272973441091SDouglas Gregor   }
273073441091SDouglas Gregor 
27319194a91dSDouglas Gregor   if (ActiveModule) {
2732524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
27334898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
27344898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
273573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
273673441091SDouglas Gregor       Failed = true;
273773441091SDouglas Gregor     }
273873441091SDouglas Gregor 
273973441091SDouglas Gregor     // Check for redefinition of an inferred module.
2740dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
274173441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2742dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2743dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
274473441091SDouglas Gregor                      diag::note_mmap_prev_definition);
274573441091SDouglas Gregor       Failed = true;
274673441091SDouglas Gregor     }
274773441091SDouglas Gregor 
27489194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27499194a91dSDouglas Gregor     if (Framework) {
27509194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27519194a91dSDouglas Gregor       Framework = false;
27529194a91dSDouglas Gregor     }
27539194a91dSDouglas Gregor   } else if (Explicit) {
27549194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27559194a91dSDouglas Gregor     Explicit = false;
27569194a91dSDouglas Gregor   }
27579194a91dSDouglas Gregor 
275873441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
275973441091SDouglas Gregor   if (Failed) {
276073441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
276173441091SDouglas Gregor       consumeToken();
276273441091SDouglas Gregor       skipUntil(MMToken::RBrace);
276373441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
276473441091SDouglas Gregor         consumeToken();
276573441091SDouglas Gregor     }
276673441091SDouglas Gregor     HadError = true;
276773441091SDouglas Gregor     return;
276873441091SDouglas Gregor   }
276973441091SDouglas Gregor 
27709194a91dSDouglas Gregor   // Parse optional attributes.
27714442605fSBill Wendling   Attributes Attrs;
27725d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27735d29dee0SDavide Italiano     return;
27749194a91dSDouglas Gregor 
27759194a91dSDouglas Gregor   if (ActiveModule) {
277673441091SDouglas Gregor     // Note that we have an inferred submodule.
2777dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2778dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2779dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27809194a91dSDouglas Gregor   } else {
27819194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27829194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2783c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2784beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2785131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27869194a91dSDouglas Gregor   }
278773441091SDouglas Gregor 
278873441091SDouglas Gregor   // Parse the opening brace.
278973441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
279073441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
279173441091SDouglas Gregor     HadError = true;
279273441091SDouglas Gregor     return;
279373441091SDouglas Gregor   }
279473441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
279573441091SDouglas Gregor 
279673441091SDouglas Gregor   // Parse the body of the inferred submodule.
279773441091SDouglas Gregor   bool Done = false;
279873441091SDouglas Gregor   do {
279973441091SDouglas Gregor     switch (Tok.Kind) {
280073441091SDouglas Gregor     case MMToken::EndOfFile:
280173441091SDouglas Gregor     case MMToken::RBrace:
280273441091SDouglas Gregor       Done = true;
280373441091SDouglas Gregor       break;
280473441091SDouglas Gregor 
2805afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
28069194a91dSDouglas Gregor       if (ActiveModule) {
28079194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2808d2d442caSCraig Topper           << (ActiveModule != nullptr);
28099194a91dSDouglas Gregor         consumeToken();
28109194a91dSDouglas Gregor         break;
28119194a91dSDouglas Gregor       }
28129194a91dSDouglas Gregor 
28139194a91dSDouglas Gregor       consumeToken();
2814306d8920SRichard Smith       // FIXME: Support string-literal module names here.
28159194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
28169194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28179194a91dSDouglas Gregor         break;
28189194a91dSDouglas Gregor       }
28199194a91dSDouglas Gregor 
2820adcd0268SBenjamin Kramer       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2821adcd0268SBenjamin Kramer           std::string(Tok.getString()));
28229194a91dSDouglas Gregor       consumeToken();
28239194a91dSDouglas Gregor       break;
28249194a91dSDouglas Gregor 
28259194a91dSDouglas Gregor     case MMToken::ExportKeyword:
28269194a91dSDouglas Gregor       if (!ActiveModule) {
28279194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2828d2d442caSCraig Topper           << (ActiveModule != nullptr);
28299194a91dSDouglas Gregor         consumeToken();
28309194a91dSDouglas Gregor         break;
28319194a91dSDouglas Gregor       }
28329194a91dSDouglas Gregor 
283373441091SDouglas Gregor       consumeToken();
283473441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2835dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
283673441091SDouglas Gregor       else
283773441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
283873441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
283973441091SDouglas Gregor       consumeToken();
284073441091SDouglas Gregor       break;
284173441091SDouglas Gregor 
284273441091SDouglas Gregor     case MMToken::ExplicitKeyword:
284373441091SDouglas Gregor     case MMToken::ModuleKeyword:
284473441091SDouglas Gregor     case MMToken::HeaderKeyword:
2845b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
284673441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
284773441091SDouglas Gregor     default:
28489194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2849d2d442caSCraig Topper           << (ActiveModule != nullptr);
285073441091SDouglas Gregor       consumeToken();
285173441091SDouglas Gregor       break;
285273441091SDouglas Gregor     }
285373441091SDouglas Gregor   } while (!Done);
285473441091SDouglas Gregor 
285573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
285673441091SDouglas Gregor     consumeToken();
285773441091SDouglas Gregor   else {
285873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
285973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
286073441091SDouglas Gregor     HadError = true;
286173441091SDouglas Gregor   }
286273441091SDouglas Gregor }
286373441091SDouglas Gregor 
28649fc8faf9SAdrian Prantl /// Parse optional attributes.
28659194a91dSDouglas Gregor ///
28669194a91dSDouglas Gregor ///   attributes:
28679194a91dSDouglas Gregor ///     attribute attributes
28689194a91dSDouglas Gregor ///     attribute
28699194a91dSDouglas Gregor ///
28709194a91dSDouglas Gregor ///   attribute:
28719194a91dSDouglas Gregor ///     [ identifier ]
28729194a91dSDouglas Gregor ///
28739194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28749194a91dSDouglas Gregor ///
28759194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28764442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28779194a91dSDouglas Gregor   bool HadError = false;
28789194a91dSDouglas Gregor 
28799194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28809194a91dSDouglas Gregor     // Consume the '['.
28819194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28829194a91dSDouglas Gregor 
28839194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28849194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28859194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28869194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28879194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28889194a91dSDouglas Gregor         consumeToken();
28899194a91dSDouglas Gregor       HadError = true;
28909194a91dSDouglas Gregor     }
28919194a91dSDouglas Gregor 
28929194a91dSDouglas Gregor     // Decode the attribute name.
28939194a91dSDouglas Gregor     AttributeKind Attribute
28949194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
289535b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
289677944868SRichard Smith           .Case("extern_c", AT_extern_c)
2897ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28989194a91dSDouglas Gregor           .Case("system", AT_system)
28999194a91dSDouglas Gregor           .Default(AT_unknown);
29009194a91dSDouglas Gregor     switch (Attribute) {
29019194a91dSDouglas Gregor     case AT_unknown:
29029194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29039194a91dSDouglas Gregor         << Tok.getString();
29049194a91dSDouglas Gregor       break;
29059194a91dSDouglas Gregor 
29069194a91dSDouglas Gregor     case AT_system:
29079194a91dSDouglas Gregor       Attrs.IsSystem = true;
29089194a91dSDouglas Gregor       break;
290935b13eceSDouglas Gregor 
291077944868SRichard Smith     case AT_extern_c:
291177944868SRichard Smith       Attrs.IsExternC = true;
291277944868SRichard Smith       break;
291377944868SRichard Smith 
291435b13eceSDouglas Gregor     case AT_exhaustive:
291535b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
291635b13eceSDouglas Gregor       break;
2917ed84df00SBruno Cardoso Lopes 
2918ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2919ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2920ed84df00SBruno Cardoso Lopes       break;
29219194a91dSDouglas Gregor     }
29229194a91dSDouglas Gregor     consumeToken();
29239194a91dSDouglas Gregor 
29249194a91dSDouglas Gregor     // Consume the ']'.
29259194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
29269194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29279194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29289194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
29299194a91dSDouglas Gregor       HadError = true;
29309194a91dSDouglas Gregor     }
29319194a91dSDouglas Gregor 
29329194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
29339194a91dSDouglas Gregor       consumeToken();
29349194a91dSDouglas Gregor   }
29359194a91dSDouglas Gregor 
29369194a91dSDouglas Gregor   return HadError;
29379194a91dSDouglas Gregor }
29389194a91dSDouglas Gregor 
29399fc8faf9SAdrian Prantl /// Parse a module map file.
2940718292f2SDouglas Gregor ///
2941718292f2SDouglas Gregor ///   module-map-file:
2942718292f2SDouglas Gregor ///     module-declaration*
2943718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2944718292f2SDouglas Gregor   do {
2945718292f2SDouglas Gregor     switch (Tok.Kind) {
2946718292f2SDouglas Gregor     case MMToken::EndOfFile:
2947718292f2SDouglas Gregor       return HadError;
2948718292f2SDouglas Gregor 
2949e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
295097292843SDaniel Jasper     case MMToken::ExternKeyword:
2951718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2952755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2953718292f2SDouglas Gregor       parseModuleDecl();
2954718292f2SDouglas Gregor       break;
2955718292f2SDouglas Gregor 
29561fb5c3a6SDouglas Gregor     case MMToken::Comma:
295735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2958fb912657SDouglas Gregor     case MMToken::Conflict:
2959a3feee2aSRichard Smith     case MMToken::Exclaim:
296059527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29612b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2962f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2963718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2964718292f2SDouglas Gregor     case MMToken::Identifier:
2965718292f2SDouglas Gregor     case MMToken::LBrace:
29666ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2967a686e1b0SDouglas Gregor     case MMToken::LSquare:
29682b82c2a5SDouglas Gregor     case MMToken::Period:
2969b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2970718292f2SDouglas Gregor     case MMToken::RBrace:
2971a686e1b0SDouglas Gregor     case MMToken::RSquare:
29721fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29732b82c2a5SDouglas Gregor     case MMToken::Star:
2974718292f2SDouglas Gregor     case MMToken::StringLiteral:
2975040e1266SRichard Smith     case MMToken::IntegerLiteral:
2976b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2977718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2978ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2979718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2980718292f2SDouglas Gregor       HadError = true;
2981718292f2SDouglas Gregor       consumeToken();
2982718292f2SDouglas Gregor       break;
2983718292f2SDouglas Gregor     }
2984718292f2SDouglas Gregor   } while (true);
2985718292f2SDouglas Gregor }
2986718292f2SDouglas Gregor 
29879acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2988c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29898128f332SRichard Smith                                    unsigned *Offset,
2990ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29918128f332SRichard Smith   assert(Target && "Missing target information");
29924ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29934ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29944ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29954ddf2221SDouglas Gregor     return Known->second;
29964ddf2221SDouglas Gregor 
29978128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
29988128f332SRichard Smith   if (ID.isInvalid()) {
2999f3f84616SRichard Smith     auto FileCharacter =
3000f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30018128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30028128f332SRichard Smith   }
30038128f332SRichard Smith 
30048128f332SRichard Smith   assert(Target && "Missing target information");
30051f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
3006718292f2SDouglas Gregor   if (!Buffer)
30074ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
30088128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30098128f332SRichard Smith          "invalid buffer offset");
3010718292f2SDouglas Gregor 
3011718292f2SDouglas Gregor   // Parse this module map file.
30128128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30138128f332SRichard Smith           Buffer->getBufferStart(),
30148128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
30158128f332SRichard Smith           Buffer->getBufferEnd());
30162a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
3017beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3018c192d194SBruno Cardoso Lopes                          IsSystem);
3019718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
30204ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
30212a6edb30SRichard Smith 
30228128f332SRichard Smith   if (Offset) {
30238128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30248128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
30258128f332SRichard Smith     *Offset = Loc.second;
30268128f332SRichard Smith   }
30278128f332SRichard Smith 
30282a6edb30SRichard Smith   // Notify callbacks that we parsed it.
30292a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
30302a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
30318587dfd9SBruno Cardoso Lopes 
3032718292f2SDouglas Gregor   return Result;
3033718292f2SDouglas Gregor }
3034