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 
390*8d74de9dSMartin Boehme bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
391*8d74de9dSMartin Boehme   return File->getDir() == BuiltinIncludeDir &&
392*8d74de9dSMartin Boehme          ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
393*8d74de9dSMartin Boehme }
394*8d74de9dSMartin Boehme 
39592669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
39692669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
397040e1266SRichard Smith   resolveHeaderDirectives(File);
39859527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
39947972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
400*8d74de9dSMartin Boehme       Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4014eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
40292669ee4SDaniel Jasper     return Headers.find(File);
4034eaf0a6cSDaniel Jasper   }
40492669ee4SDaniel Jasper   return Known;
40592669ee4SDaniel Jasper }
40692669ee4SDaniel Jasper 
4074469138eSBen Langmuir ModuleMap::KnownHeader
4084469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4094469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
41047972afdSRichard Smith   if (UmbrellaDirs.empty())
411afd1b1c9SEugene Zelenko     return {};
41247972afdSRichard Smith 
4134469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
4144469138eSBen Langmuir   assert(Dir && "file in no directory");
4154469138eSBen Langmuir 
4164469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
4174469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
4184469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
4194469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
4204469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4214469138eSBen Langmuir 
4224469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
4234469138eSBen Langmuir   // an umbrella header.
4244469138eSBen Langmuir   do {
4254469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4264469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4274469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4284469138eSBen Langmuir 
4294469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4304469138eSBen Langmuir 
4314469138eSBen Langmuir     // Retrieve our parent path.
4324469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4334469138eSBen Langmuir     if (DirName.empty())
4344469138eSBen Langmuir       break;
4354469138eSBen Langmuir 
4364469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4378d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
4388d323d15SHarlan Haskins       Dir = *DirEntry;
4398d323d15SHarlan Haskins     else
4408d323d15SHarlan Haskins       Dir = nullptr;
4414469138eSBen Langmuir   } while (Dir);
442afd1b1c9SEugene Zelenko   return {};
4434469138eSBen Langmuir }
4444469138eSBen Langmuir 
44592669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
44692669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4474eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44892669ee4SDaniel Jasper #ifndef NDEBUG
4494eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
45092669ee4SDaniel Jasper     // Check for consistency between the module header role
45192669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
45292669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4532708e520SRichard Smith     bool IsPrivate = false;
4542708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4554eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4564eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4572708e520SRichard Smith     for (auto *Hs : HeaderList)
4582708e520SRichard Smith       IsPrivate |=
4592708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4603c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4612708e520SRichard Smith           }) != Hs->end();
4624eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
46300bc95ecSRichard Smith   }
46492669ee4SDaniel Jasper #endif
4654eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
46692669ee4SDaniel Jasper }
46792669ee4SDaniel Jasper 
46871e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46971e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
47071e1a64fSBen Langmuir }
47171e1a64fSBen Langmuir 
47292669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4738d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
47492669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
47592669ee4SDaniel Jasper                                         StringRef Filename,
47692669ee4SDaniel Jasper                                         const FileEntry *File) {
47792669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47892669ee4SDaniel Jasper   // with no source files.
47971e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
48092669ee4SDaniel Jasper     return;
48192669ee4SDaniel Jasper 
482040e1266SRichard Smith   if (RequestingModule) {
48392669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
484040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
485040e1266SRichard Smith   }
48692669ee4SDaniel Jasper 
48771e1a64fSBen Langmuir   bool Excluded = false;
488d2d442caSCraig Topper   Module *Private = nullptr;
489d2d442caSCraig Topper   Module *NotUsed = nullptr;
49071e1a64fSBen Langmuir 
49171e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
49271e1a64fSBen Langmuir   if (Known != Headers.end()) {
49371e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
49492669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4954eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
49671e1a64fSBen Langmuir         Private = Header.getModule();
49792669ee4SDaniel Jasper         continue;
49892669ee4SDaniel Jasper       }
49992669ee4SDaniel Jasper 
50092669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
50192669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
50292669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
5038f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
50471e1a64fSBen Langmuir         NotUsed = Header.getModule();
50592669ee4SDaniel Jasper         continue;
50692669ee4SDaniel Jasper       }
50792669ee4SDaniel Jasper 
50892669ee4SDaniel Jasper       // We have found a module that we can happily use.
50992669ee4SDaniel Jasper       return;
51092669ee4SDaniel Jasper     }
511feb54b6dSRichard Smith 
512feb54b6dSRichard Smith     Excluded = true;
51371e1a64fSBen Langmuir   }
51492669ee4SDaniel Jasper 
51592669ee4SDaniel Jasper   // We have found a header, but it is private.
516d2d442caSCraig Topper   if (Private) {
51711152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51892669ee4SDaniel Jasper         << Filename;
51992669ee4SDaniel Jasper     return;
52092669ee4SDaniel Jasper   }
52192669ee4SDaniel Jasper 
52292669ee4SDaniel Jasper   // We have found a module, but we don't use it.
523d2d442caSCraig Topper   if (NotUsed) {
52411152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5254ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
52692669ee4SDaniel Jasper     return;
52792669ee4SDaniel Jasper   }
52892669ee4SDaniel Jasper 
52971e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
53071e1a64fSBen Langmuir     return;
53171e1a64fSBen Langmuir 
53271e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
53371e1a64fSBen Langmuir 
5345904c41eSBenjamin Kramer   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
53511152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5364ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
537a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
538a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
539a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
54071e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
54171e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
54271e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
54370a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
54470a7738fSManman Ren         << File->getName();
54571e1a64fSBen Langmuir   }
54692669ee4SDaniel Jasper }
54792669ee4SDaniel Jasper 
548ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
549ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5508b7c0398SSean Silva   // Prefer available modules.
5516bc75023SRichard Smith   // FIXME: Considering whether the module is available rather than merely
5526bc75023SRichard Smith   // importable is non-hermetic and can result in surprising behavior for
5536bc75023SRichard Smith   // prebuilt modules. Consider only checking for importability here.
5548b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5558b7c0398SSean Silva     return true;
5568b7c0398SSean Silva 
557ec87a50aSRichard Smith   // Prefer a public header over a private header.
558ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
559ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
560ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
561ec87a50aSRichard Smith 
562ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
563ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
564ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
565ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
566ec87a50aSRichard Smith 
567ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
568ec87a50aSRichard Smith   return false;
569ec87a50aSRichard Smith }
570ec87a50aSRichard Smith 
571ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
572ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
573306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
574ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
575afd1b1c9SEugene Zelenko       return {};
576306d8920SRichard Smith     return R;
577306d8920SRichard Smith   };
578306d8920SRichard Smith 
5794881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5801fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
581202210b3SRichard Smith     ModuleMap::KnownHeader Result;
58297da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5834881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5847e82e019SRichard Smith       // Prefer a header from the source module over all others.
5857e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5862f633e7cSRichard Smith         return MakeResult(H);
5874881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5884881e8b2SSean Silva         Result = H;
58997da9178SDaniel Jasper     }
590306d8920SRichard Smith     return MakeResult(Result);
5911fb5c3a6SDouglas Gregor   }
592ab0c8a84SDouglas Gregor 
593386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
594386bb073SRichard Smith }
595386bb073SRichard Smith 
596386bb073SRichard Smith ModuleMap::KnownHeader
597386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
598386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
599386bb073SRichard Smith 
600f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6014469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6024469138eSBen Langmuir   if (H) {
6034469138eSBen Langmuir     Module *Result = H.getModule();
604930a85ccSDouglas Gregor 
605930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
60673141fa9SDouglas Gregor     // directory.
607930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
60873141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
609930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
610930a85ccSDouglas Gregor 
611930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6129d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6139d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6149d6448b1SBen Langmuir 
615a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
616a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
617a89c5ac4SDouglas Gregor       // the actual header is located.
6189458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6199458f82dSDouglas Gregor 
6207033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
621a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
622056396aeSDouglas Gregor         SmallString<32> NameBuf;
623056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6244469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6259d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6269d6448b1SBen Langmuir                                     Explicit).first;
6279d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
628ffbafa2aSBen Langmuir         Result->IsInferred = true;
629a89c5ac4SDouglas Gregor 
630a89c5ac4SDouglas Gregor         // Associate the module and the directory.
631a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
632a89c5ac4SDouglas Gregor 
633a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
634a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
635930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
636d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
637a89c5ac4SDouglas Gregor       }
638a89c5ac4SDouglas Gregor 
639a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
640056396aeSDouglas Gregor       SmallString<32> NameBuf;
641056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
642056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6439d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6449d6448b1SBen Langmuir                                   Explicit).first;
6459d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
646ffbafa2aSBen Langmuir       Result->IsInferred = true;
6473c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
648a89c5ac4SDouglas Gregor 
649a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
650a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
651930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
652d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
653a89c5ac4SDouglas Gregor     } else {
654a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
655a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
656a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
657a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
658a89c5ac4SDouglas Gregor     }
659a89c5ac4SDouglas Gregor 
660386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
661386bb073SRichard Smith     Headers[File].push_back(Header);
662386bb073SRichard Smith     return Header;
663a89c5ac4SDouglas Gregor   }
664a89c5ac4SDouglas Gregor 
665afd1b1c9SEugene Zelenko   return {};
666ab0c8a84SDouglas Gregor }
667ab0c8a84SDouglas Gregor 
668386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
6690a088eadSRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) {
6700a088eadSRichard Smith   HeadersMap::iterator Known = findKnownHeader(File);
6710a088eadSRichard Smith   if (Known != Headers.end())
6720a088eadSRichard Smith     return Known->second;
6730a088eadSRichard Smith 
6740a088eadSRichard Smith   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
6750a088eadSRichard Smith     return Headers.find(File)->second;
6760a088eadSRichard Smith 
6770a088eadSRichard Smith   return None;
6780a088eadSRichard Smith }
6790a088eadSRichard Smith 
6800a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader>
6810a088eadSRichard Smith ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
6820a088eadSRichard Smith   // FIXME: Is this necessary?
683040e1266SRichard Smith   resolveHeaderDirectives(File);
684386bb073SRichard Smith   auto It = Headers.find(File);
685386bb073SRichard Smith   if (It == Headers.end())
686386bb073SRichard Smith     return None;
687386bb073SRichard Smith   return It->second;
688386bb073SRichard Smith }
689386bb073SRichard Smith 
690e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
691d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
69250996ce1SRichard Smith }
69350996ce1SRichard Smith 
69462bcd925SDmitri Gribenko bool
69562bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
69662bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
697040e1266SRichard Smith   resolveHeaderDirectives(Header);
698e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
69997da9178SDaniel Jasper   if (Known != Headers.end()) {
70097da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
70197da9178SDaniel Jasper              I = Known->second.begin(),
70297da9178SDaniel Jasper              E = Known->second.end();
70397da9178SDaniel Jasper          I != E; ++I) {
704052d95a6SBruno Cardoso Lopes 
705052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
706052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
707052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
708052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
709052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
710052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
711052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
712052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
713052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
714052d95a6SBruno Cardoso Lopes           continue;
71597da9178SDaniel Jasper         return false;
71697da9178SDaniel Jasper       }
717052d95a6SBruno Cardoso Lopes     }
71897da9178SDaniel Jasper     return true;
71997da9178SDaniel Jasper   }
7201fb5c3a6SDouglas Gregor 
7211fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
722f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7231fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7241fb5c3a6SDouglas Gregor 
72550996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
72650996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
72750996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
72850996ce1SRichard Smith   };
72950996ce1SRichard Smith 
7301fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7311fb5c3a6SDouglas Gregor   // an umbrella header.
7321fb5c3a6SDouglas Gregor   do {
733e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7341fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7351fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7361fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
73750996ce1SRichard Smith       if (IsUnavailable(Found))
7381fb5c3a6SDouglas Gregor         return true;
7391fb5c3a6SDouglas Gregor 
7401fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7411fb5c3a6SDouglas Gregor       // directory.
7421fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7431fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7441fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7451fb5c3a6SDouglas Gregor 
7461fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7471fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7481fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
749056396aeSDouglas Gregor           SmallString<32> NameBuf;
750056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
751056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
752056396aeSDouglas Gregor                              NameBuf);
7531fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7541fb5c3a6SDouglas Gregor           if (!Found)
7551fb5c3a6SDouglas Gregor             return false;
75650996ce1SRichard Smith           if (IsUnavailable(Found))
7571fb5c3a6SDouglas Gregor             return true;
7581fb5c3a6SDouglas Gregor         }
7591fb5c3a6SDouglas Gregor 
7601fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
761056396aeSDouglas Gregor         SmallString<32> NameBuf;
762056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
763056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
764056396aeSDouglas Gregor                            NameBuf);
7651fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7661fb5c3a6SDouglas Gregor         if (!Found)
7671fb5c3a6SDouglas Gregor           return false;
7681fb5c3a6SDouglas Gregor       }
7691fb5c3a6SDouglas Gregor 
77050996ce1SRichard Smith       return IsUnavailable(Found);
7711fb5c3a6SDouglas Gregor     }
7721fb5c3a6SDouglas Gregor 
7731fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7741fb5c3a6SDouglas Gregor 
7751fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7761fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7771fb5c3a6SDouglas Gregor     if (DirName.empty())
7781fb5c3a6SDouglas Gregor       break;
7791fb5c3a6SDouglas Gregor 
7801fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7818d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7828d323d15SHarlan Haskins       Dir = *DirEntry;
7838d323d15SHarlan Haskins     else
7848d323d15SHarlan Haskins       Dir = nullptr;
7851fb5c3a6SDouglas Gregor   } while (Dir);
7861fb5c3a6SDouglas Gregor 
7871fb5c3a6SDouglas Gregor   return false;
7881fb5c3a6SDouglas Gregor }
7891fb5c3a6SDouglas Gregor 
790e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
791e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
79288bdfb0eSDouglas Gregor   if (Known != Modules.end())
79388bdfb0eSDouglas Gregor     return Known->getValue();
79488bdfb0eSDouglas Gregor 
795d2d442caSCraig Topper   return nullptr;
79688bdfb0eSDouglas Gregor }
79788bdfb0eSDouglas Gregor 
798e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
799e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
8002b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
8012b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
8022b82c2a5SDouglas Gregor       return Sub;
8032b82c2a5SDouglas Gregor   }
8042b82c2a5SDouglas Gregor 
8052b82c2a5SDouglas Gregor   return findModule(Name);
8062b82c2a5SDouglas Gregor }
8072b82c2a5SDouglas Gregor 
808e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8092b82c2a5SDouglas Gregor   if (!Context)
8102b82c2a5SDouglas Gregor     return findModule(Name);
8112b82c2a5SDouglas Gregor 
812eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
8132b82c2a5SDouglas Gregor }
8142b82c2a5SDouglas Gregor 
815c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
816c192d194SBruno Cardoso Lopes                                                         Module *Parent,
817c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
818c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
81969021974SDouglas Gregor   // Try to find an existing module with this name.
820eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
821eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
82269021974SDouglas Gregor 
82369021974SDouglas Gregor   // Create a new module with this name.
8249ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8259ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
8266f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8277e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8287e82e019SRichard Smith       SourceModule = Result;
82969021974SDouglas Gregor     Modules[Name] = Result;
830c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8316f722b4eSArgyrios Kyrtzidis   }
83269021974SDouglas Gregor   return std::make_pair(Result, true);
83369021974SDouglas Gregor }
83469021974SDouglas Gregor 
835a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
836d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
837056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
838056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
839d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
840d6509cf2SRichard Smith   return PendingSubmodules.back().get();
841dd8b5337SRichard Smith }
842dd8b5337SRichard Smith 
843a5bbbfefSRichard Smith Module *
844a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
845a5bbbfefSRichard Smith                                                        SourceLocation Loc) {
846a5bbbfefSRichard Smith   auto *Result =
847a5bbbfefSRichard Smith       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
848a5bbbfefSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++);
849a5bbbfefSRichard Smith   Result->Kind = Module::PrivateModuleFragment;
850a5bbbfefSRichard Smith   return Result;
851a5bbbfefSRichard Smith }
852a5bbbfefSRichard Smith 
853bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
854dd8b5337SRichard Smith                                                 StringRef Name,
855dd8b5337SRichard Smith                                                 Module *GlobalModule) {
856bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
857bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
858bbcc9f04SRichard Smith 
859bbcc9f04SRichard Smith   auto *Result =
860bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
861bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
862145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
863bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
864bbcc9f04SRichard Smith 
865dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
866d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
867d6509cf2SRichard Smith     Submodule->setParent(Result);
868d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
869d6509cf2SRichard Smith   }
870d6509cf2SRichard Smith   PendingSubmodules.clear();
871dd8b5337SRichard Smith 
872bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
873bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
874bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
875bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
876bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
877bbcc9f04SRichard Smith 
878bbcc9f04SRichard Smith   return Result;
879bbcc9f04SRichard Smith }
880bbcc9f04SRichard Smith 
881d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
882d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
883d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
884d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
885d6509cf2SRichard Smith 
886d6509cf2SRichard Smith   auto *Result =
887d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
888d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
889d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
890d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
891d6509cf2SRichard Smith 
892d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
893d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
894d6509cf2SRichard Smith                          /*IsFramework*/ false,
895d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
896d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
897d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
898d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
899d6509cf2SRichard Smith   }
900d6509cf2SRichard Smith 
901d6509cf2SRichard Smith   return Result;
902d6509cf2SRichard Smith }
903d6509cf2SRichard Smith 
9049fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
90511dfe6feSDouglas Gregor /// should link.
90611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
90711dfe6feSDouglas Gregor                                FileManager &FileMgr) {
90811dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
90911dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
91011dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
91111dfe6feSDouglas Gregor 
91211dfe6feSDouglas Gregor   SmallString<128> LibName;
91311dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
91411dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
9158aaae5a9SJuergen Ributzka 
9168aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
9178aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
9188aaae5a9SJuergen Ributzka   // for both before we give up.
9198013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
9208aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
92111dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
92211dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
92311dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
9248aaae5a9SJuergen Ributzka       return;
9258aaae5a9SJuergen Ributzka     }
92611dfe6feSDouglas Gregor   }
92711dfe6feSDouglas Gregor }
92811dfe6feSDouglas Gregor 
929a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
930a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
931c1d88ea5SBen Langmuir   Attributes Attrs;
932c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
933a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
934c1d88ea5SBen Langmuir }
935c1d88ea5SBen Langmuir 
936a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
937c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
938a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
939a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
940a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
941a525400dSBen Langmuir   // top-level framework.
942a525400dSBen Langmuir   StringRef FrameworkDirName =
943a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
944a525400dSBen Langmuir 
945a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
946a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
947a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
948a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
949a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
950a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
951c1d88ea5SBen Langmuir 
95256c64013SDouglas Gregor   // Check whether we've already found this module.
953e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
954e89dbc1dSDouglas Gregor     return Mod;
955e89dbc1dSDouglas Gregor 
9561f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
95756c64013SDouglas Gregor 
9589194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9599194a91dSDouglas Gregor   // a framework module, do so.
960beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9619194a91dSDouglas Gregor   if (!Parent) {
9624ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9639194a91dSDouglas Gregor     bool canInfer = false;
9644ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9659194a91dSDouglas Gregor       // Figure out the parent path.
9664ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9678d323d15SHarlan Haskins       if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9689194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9699194a91dSDouglas Gregor         // for a module map.
970e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9718d323d15SHarlan Haskins           inferred = InferredDirectories.find(*ParentDir);
9729194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9739194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9749194a91dSDouglas Gregor           // one.
975984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
976984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
9778d323d15SHarlan Haskins                 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9788d323d15SHarlan Haskins             parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9798d323d15SHarlan Haskins             inferred = InferredDirectories.find(*ParentDir);
9809194a91dSDouglas Gregor           }
9819194a91dSDouglas Gregor 
9829194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9839194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9848d323d15SHarlan Haskins                          std::make_pair(*ParentDir, InferredDirectory())).first;
9859194a91dSDouglas Gregor         }
9869194a91dSDouglas Gregor 
9879194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9889194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9899194a91dSDouglas Gregor           // to infer this particular module.
9904ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9919194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9929194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9939194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9949194a91dSDouglas Gregor 
995c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
996c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
997c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
998ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
999ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
1000beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
10019194a91dSDouglas Gregor         }
10029194a91dSDouglas Gregor       }
10039194a91dSDouglas Gregor     }
10049194a91dSDouglas Gregor 
10059194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
10069194a91dSDouglas Gregor     if (!canInfer)
1007d2d442caSCraig Topper       return nullptr;
1008beee15e7SBen Langmuir   } else
10099d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
10109194a91dSDouglas Gregor 
10119194a91dSDouglas Gregor 
101256c64013SDouglas Gregor   // Look for an umbrella header.
10132c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
101417381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
10158d323d15SHarlan Haskins   auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
101656c64013SDouglas Gregor 
101756c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
101856c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
101956c64013SDouglas Gregor   // idea.
102056c64013SDouglas Gregor   if (!UmbrellaHeader)
1021d2d442caSCraig Topper     return nullptr;
102256c64013SDouglas Gregor 
10239d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1024a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
1025a7e2cc68SRichard Smith                               NumCreatedModules++);
10269d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
10279d6448b1SBen Langmuir   Result->IsInferred = true;
10287e82e019SRichard Smith   if (!Parent) {
10297e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
1030ba7f2f71SDaniel Jasper       SourceModule = Result;
10317e82e019SRichard Smith     Modules[ModuleName] = Result;
1032c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1033ba7f2f71SDaniel Jasper   }
1034c1d88ea5SBen Langmuir 
1035c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
1036c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1037c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1038ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10392b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1040a686e1b0SDouglas Gregor 
1041322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
10422b63d15fSRichard Smith   //
10432b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
10442b63d15fSRichard Smith   // a framework module.
10458d323d15SHarlan Haskins   setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h");
1046d8bd7537SDouglas Gregor 
1047d8bd7537SDouglas Gregor   // export *
1048d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1049d8bd7537SDouglas Gregor 
1050a89c5ac4SDouglas Gregor   // module * { export * }
1051a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1052a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1053a89c5ac4SDouglas Gregor 
1054e89dbc1dSDouglas Gregor   // Look for subframeworks.
1055c080917eSRafael Espindola   std::error_code EC;
10562c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1057ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1058e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10592d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1060db8a7422SDuncan P. N. Exon Smith   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1061fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1062fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1063b171a59bSBruno Cardoso Lopes            DirEnd;
1064e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10650ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1066e89dbc1dSDouglas Gregor       continue;
1067f2161a70SDouglas Gregor 
10688d323d15SHarlan Haskins     if (auto SubframeworkDir =
10690ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
107007c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
107107c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
107207c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
107307c22b78SDouglas Gregor       // out to a top-level framework.
10748d323d15SHarlan Haskins       StringRef SubframeworkDirName =
10758d323d15SHarlan Haskins           FileMgr.getCanonicalName(*SubframeworkDir);
107607c22b78SDouglas Gregor       bool FoundParent = false;
107707c22b78SDouglas Gregor       do {
107807c22b78SDouglas Gregor         // Get the parent directory name.
107907c22b78SDouglas Gregor         SubframeworkDirName
108007c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
108107c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
108207c22b78SDouglas Gregor           break;
108307c22b78SDouglas Gregor 
10848d323d15SHarlan Haskins         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
10858d323d15SHarlan Haskins           if (*SubDir == FrameworkDir) {
108607c22b78SDouglas Gregor             FoundParent = true;
108707c22b78SDouglas Gregor             break;
108807c22b78SDouglas Gregor           }
10898d323d15SHarlan Haskins         }
109007c22b78SDouglas Gregor       } while (true);
109107c22b78SDouglas Gregor 
109207c22b78SDouglas Gregor       if (!FoundParent)
109307c22b78SDouglas Gregor         continue;
109407c22b78SDouglas Gregor 
1095e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
10968d323d15SHarlan Haskins       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1097e89dbc1dSDouglas Gregor     }
1098e89dbc1dSDouglas Gregor   }
1099e89dbc1dSDouglas Gregor 
110011dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
110111dfe6feSDouglas Gregor   // framework.
110211dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
110311dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
110411dfe6feSDouglas Gregor   }
110511dfe6feSDouglas Gregor 
110656c64013SDouglas Gregor   return Result;
110756c64013SDouglas Gregor }
110856c64013SDouglas Gregor 
11098587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11108587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
11118587dfd9SBruno Cardoso Lopes 
11128587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
11138587dfd9SBruno Cardoso Lopes   Module *Result =
11148587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11158587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
11168587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
1117fc76b4adSRichard Smith   Result->markUnavailable(/*Unimportable*/true);
1118c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
11198587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
11208587dfd9SBruno Cardoso Lopes 
11218587dfd9SBruno Cardoso Lopes   return Result;
11228587dfd9SBruno Cardoso Lopes }
11238587dfd9SBruno Cardoso Lopes 
11242b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
11252b63d15fSRichard Smith                                   Twine NameAsWritten) {
112697da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
112773141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
1128bc883665SReid Kleckner   Mod->HasUmbrellaDir = false;
11292b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
11307033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1131b3a0fa48SBruno Cardoso Lopes 
1132b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1133b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1134b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1135a89c5ac4SDouglas Gregor }
1136a89c5ac4SDouglas Gregor 
11372b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
11382b63d15fSRichard Smith                                Twine NameAsWritten) {
1139524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
1140bc883665SReid Kleckner   Mod->HasUmbrellaDir = true;
11412b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1142524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1143524e33e1SDouglas Gregor }
1144524e33e1SDouglas Gregor 
1145040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11469f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11479f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1148040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1149040e1266SRichard Smith   // wrap the system header.
1150040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1151040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1152040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1153040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1154040e1266SRichard Smith     // case.
1155040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1156040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1157040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11583c1a41adSRichard Smith   }
1159040e1266SRichard Smith 
1160040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1161040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1162040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1163040e1266SRichard Smith   // headers.
1164040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1165040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1166040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1167040e1266SRichard Smith     // use the mtime as the key.
1168040e1266SRichard Smith     if (Header.ModTime)
1169040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1170040e1266SRichard Smith     else
1171040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1172040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1173040e1266SRichard Smith     return;
1174040e1266SRichard Smith   }
1175040e1266SRichard Smith 
1176040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1177040e1266SRichard Smith   // Perform the lookup now.
11789f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1179040e1266SRichard Smith }
1180040e1266SRichard Smith 
1181040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1182040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1183040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1184040e1266SRichard Smith     for (auto *M : BySize->second)
1185040e1266SRichard Smith       resolveHeaderDirectives(M);
1186040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1187040e1266SRichard Smith   }
1188040e1266SRichard Smith 
1189040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1190040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1191040e1266SRichard Smith     for (auto *M : ByModTime->second)
1192040e1266SRichard Smith       resolveHeaderDirectives(M);
1193040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1194040e1266SRichard Smith   }
1195040e1266SRichard Smith }
1196040e1266SRichard Smith 
1197040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11989f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1199040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1200040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1201040e1266SRichard Smith     // the header information for this file.
12029f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1203040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
12040e98d938SNAKAMURA Takumi }
1205202210b3SRichard Smith 
12063c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1207d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1208386bb073SRichard Smith   KnownHeader KH(Mod, Role);
12093c1a41adSRichard Smith 
1210386bb073SRichard Smith   // Only add each header to the headers list once.
1211386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1212386bb073SRichard Smith   // same module definition?
1213386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1214386bb073SRichard Smith   for (auto H : HeaderList)
1215386bb073SRichard Smith     if (H == KH)
1216386bb073SRichard Smith       return;
1217386bb073SRichard Smith 
1218386bb073SRichard Smith   HeaderList.push_back(KH);
12191ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1220386bb073SRichard Smith 
12217e82e019SRichard Smith   bool isCompilingModuleHeader =
1222bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1223d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1224d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1225d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1226d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1227d8879c85SRichard Smith                                     isCompilingModuleHeader);
1228d8879c85SRichard Smith   }
1229e62cfd7cSBruno Cardoso Lopes 
1230e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1231e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1232f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1233a89c5ac4SDouglas Gregor }
1234a89c5ac4SDouglas Gregor 
12353c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1236feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1237feb54b6dSRichard Smith   // umbrella directory module.
1238feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1239feb54b6dSRichard Smith   // specified module?
12403c1a41adSRichard Smith   (void) Headers[Header.Entry];
12413c1a41adSRichard Smith 
12423c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1243feb54b6dSRichard Smith }
1244feb54b6dSRichard Smith 
1245514b636aSDouglas Gregor const FileEntry *
12464b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12471f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1248d2d442caSCraig Topper     return nullptr;
1249514b636aSDouglas Gregor 
12501f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12511f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1252514b636aSDouglas Gregor }
1253514b636aSDouglas Gregor 
12544b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12559d6448b1SBen Langmuir   if (M->IsInferred) {
12569d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12579d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12589d6448b1SBen Langmuir   }
12599d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12609d6448b1SBen Langmuir }
12619d6448b1SBen Langmuir 
12629d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12639d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12649d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12659d6448b1SBen Langmuir }
12669d6448b1SBen Langmuir 
1267e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1268e08464fbSReid Kleckner                                            const FileEntry *ModuleMap) {
1269e08464fbSReid Kleckner   AdditionalModMaps[M].insert(ModuleMap);
1270e08464fbSReid Kleckner }
1271e08464fbSReid Kleckner 
1272cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1273718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1274718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1275718292f2SDouglas Gregor                                         MEnd = Modules.end();
1276718292f2SDouglas Gregor        M != MEnd; ++M)
1277d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1278718292f2SDouglas Gregor 
1279718292f2SDouglas Gregor   llvm::errs() << "Headers:";
128059527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1281718292f2SDouglas Gregor        H != HEnd; ++H) {
128297da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
128397da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
128497da9178SDaniel Jasper                                                       E = H->second.end();
128597da9178SDaniel Jasper          I != E; ++I) {
128697da9178SDaniel Jasper       if (I != H->second.begin())
128797da9178SDaniel Jasper         llvm::errs() << ",";
128897da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
128997da9178SDaniel Jasper     }
129097da9178SDaniel Jasper     llvm::errs() << "\n";
1291718292f2SDouglas Gregor   }
1292718292f2SDouglas Gregor }
1293718292f2SDouglas Gregor 
12942b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
129542413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
129642413141SRichard Smith   Mod->UnresolvedExports.clear();
129742413141SRichard Smith   for (auto &UE : Unresolved) {
129842413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1299f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
13002b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
13012b82c2a5SDouglas Gregor     else
130242413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
13032b82c2a5SDouglas Gregor   }
130442413141SRichard Smith   return !Mod->UnresolvedExports.empty();
13052b82c2a5SDouglas Gregor }
13062b82c2a5SDouglas Gregor 
1307ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
130842413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
130942413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
131042413141SRichard Smith   for (auto &UDU : Unresolved) {
131142413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1312ba7f2f71SDaniel Jasper     if (DirectUse)
1313ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1314ba7f2f71SDaniel Jasper     else
131542413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1316ba7f2f71SDaniel Jasper   }
131742413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1318ba7f2f71SDaniel Jasper }
1319ba7f2f71SDaniel Jasper 
1320fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
132142413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
132242413141SRichard Smith   Mod->UnresolvedConflicts.clear();
132342413141SRichard Smith   for (auto &UC : Unresolved) {
132442413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1325fb912657SDouglas Gregor       Module::Conflict Conflict;
1326fb912657SDouglas Gregor       Conflict.Other = OtherMod;
132742413141SRichard Smith       Conflict.Message = UC.Message;
1328fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
132942413141SRichard Smith     } else
133042413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1331fb912657SDouglas Gregor   }
133242413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1333fb912657SDouglas Gregor }
1334fb912657SDouglas Gregor 
1335718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1336718292f2SDouglas Gregor // Module map file parser
1337718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1338718292f2SDouglas Gregor 
1339718292f2SDouglas Gregor namespace clang {
1340afd1b1c9SEugene Zelenko 
13419fc8faf9SAdrian Prantl   /// A token in a module map file.
1342718292f2SDouglas Gregor   struct MMToken {
1343718292f2SDouglas Gregor     enum TokenKind {
13441fb5c3a6SDouglas Gregor       Comma,
134535b13eceSDouglas Gregor       ConfigMacros,
1346fb912657SDouglas Gregor       Conflict,
1347718292f2SDouglas Gregor       EndOfFile,
1348718292f2SDouglas Gregor       HeaderKeyword,
1349718292f2SDouglas Gregor       Identifier,
1350a3feee2aSRichard Smith       Exclaim,
135159527666SDouglas Gregor       ExcludeKeyword,
1352718292f2SDouglas Gregor       ExplicitKeyword,
13532b82c2a5SDouglas Gregor       ExportKeyword,
1354f0b11de2SDouglas Gregor       ExportAsKeyword,
135597292843SDaniel Jasper       ExternKeyword,
1356755b2055SDouglas Gregor       FrameworkKeyword,
13576ddfca91SDouglas Gregor       LinkKeyword,
1358718292f2SDouglas Gregor       ModuleKeyword,
13592b82c2a5SDouglas Gregor       Period,
1360b53e5483SLawrence Crowl       PrivateKeyword,
1361718292f2SDouglas Gregor       UmbrellaKeyword,
1362ba7f2f71SDaniel Jasper       UseKeyword,
13631fb5c3a6SDouglas Gregor       RequiresKeyword,
13642b82c2a5SDouglas Gregor       Star,
1365718292f2SDouglas Gregor       StringLiteral,
1366040e1266SRichard Smith       IntegerLiteral,
1367306d8920SRichard Smith       TextualKeyword,
1368718292f2SDouglas Gregor       LBrace,
1369a686e1b0SDouglas Gregor       RBrace,
1370a686e1b0SDouglas Gregor       LSquare,
1371a686e1b0SDouglas Gregor       RSquare
1372718292f2SDouglas Gregor     } Kind;
1373718292f2SDouglas Gregor 
1374718292f2SDouglas Gregor     unsigned Location;
1375718292f2SDouglas Gregor     unsigned StringLength;
1376040e1266SRichard Smith     union {
1377040e1266SRichard Smith       // If Kind != IntegerLiteral.
1378718292f2SDouglas Gregor       const char *StringData;
1379afd1b1c9SEugene Zelenko 
1380040e1266SRichard Smith       // If Kind == IntegerLiteral.
1381040e1266SRichard Smith       uint64_t IntegerValue;
1382040e1266SRichard Smith     };
1383718292f2SDouglas Gregor 
1384718292f2SDouglas Gregor     void clear() {
1385718292f2SDouglas Gregor       Kind = EndOfFile;
1386718292f2SDouglas Gregor       Location = 0;
1387718292f2SDouglas Gregor       StringLength = 0;
1388d2d442caSCraig Topper       StringData = nullptr;
1389718292f2SDouglas Gregor     }
1390718292f2SDouglas Gregor 
1391718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1392718292f2SDouglas Gregor 
1393718292f2SDouglas Gregor     SourceLocation getLocation() const {
1394718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1395718292f2SDouglas Gregor     }
1396718292f2SDouglas Gregor 
1397040e1266SRichard Smith     uint64_t getInteger() const {
1398040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1399040e1266SRichard Smith     }
1400040e1266SRichard Smith 
1401718292f2SDouglas Gregor     StringRef getString() const {
1402040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1403040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1404718292f2SDouglas Gregor     }
1405718292f2SDouglas Gregor   };
1406718292f2SDouglas Gregor 
1407718292f2SDouglas Gregor   class ModuleMapParser {
1408718292f2SDouglas Gregor     Lexer &L;
1409718292f2SDouglas Gregor     SourceManager &SourceMgr;
1410bc10b9fbSDouglas Gregor 
14119fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1412bc10b9fbSDouglas Gregor     /// parsing.
1413bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1414bc10b9fbSDouglas Gregor 
1415718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1416718292f2SDouglas Gregor     ModuleMap &Map;
1417718292f2SDouglas Gregor 
14189fc8faf9SAdrian Prantl     /// The current module map file.
1419beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1420beee15e7SBen Langmuir 
14219f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
14229f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
14239f6020bcSBruno Cardoso Lopes 
14249fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
14259acb99e3SRichard Smith     /// be resolved relative to.
14265257fc63SDouglas Gregor     const DirectoryEntry *Directory;
14275257fc63SDouglas Gregor 
14289fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1429963c5535SDouglas Gregor     bool IsSystem;
1430963c5535SDouglas Gregor 
14319fc8faf9SAdrian Prantl     /// Whether an error occurred.
1432afd1b1c9SEugene Zelenko     bool HadError = false;
1433718292f2SDouglas Gregor 
14349fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1435718292f2SDouglas Gregor     /// during parsing.
1436718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1437718292f2SDouglas Gregor 
14389fc8faf9SAdrian Prantl     /// The current token.
1439718292f2SDouglas Gregor     MMToken Tok;
1440718292f2SDouglas Gregor 
14419fc8faf9SAdrian Prantl     /// The active module.
1442afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1443718292f2SDouglas Gregor 
14449fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
14457ff29148SBen Langmuir     /// contents as 'textual'.
14467ff29148SBen Langmuir     ///
14477ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14487ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14497ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14507ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14517ff29148SBen Langmuir     /// 'textual' to match the original intent.
14527ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14537ff29148SBen Langmuir 
14549fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1455718292f2SDouglas Gregor     SourceLocation consumeToken();
1456718292f2SDouglas Gregor 
14579fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1458718292f2SDouglas Gregor     /// (or the end of the file).
1459718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1460718292f2SDouglas Gregor 
1461afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1462afd1b1c9SEugene Zelenko 
1463e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1464718292f2SDouglas Gregor     void parseModuleDecl();
146597292843SDaniel Jasper     void parseExternModuleDecl();
14661fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1467afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1468524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14692b82c2a5SDouglas Gregor     void parseExportDecl();
1470f0b11de2SDouglas Gregor     void parseExportAsDecl();
1471ba7f2f71SDaniel Jasper     void parseUseDecl();
14726ddfca91SDouglas Gregor     void parseLinkDecl();
147335b13eceSDouglas Gregor     void parseConfigMacros();
1474fb912657SDouglas Gregor     void parseConflict();
14759194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1476c1d88ea5SBen Langmuir 
14775f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14785f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14795f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14805f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14815f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14825f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14835f11e128SBruno Cardoso Lopes 
1484afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1485afd1b1c9SEugene Zelenko 
14864442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1487718292f2SDouglas Gregor 
1488718292f2SDouglas Gregor   public:
1489718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14908587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14918587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1492c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1493bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1494beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1495c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1496718292f2SDouglas Gregor       Tok.clear();
1497718292f2SDouglas Gregor       consumeToken();
1498718292f2SDouglas Gregor     }
1499718292f2SDouglas Gregor 
1500718292f2SDouglas Gregor     bool parseModuleMapFile();
15018128f332SRichard Smith 
15028128f332SRichard Smith     bool terminatedByDirective() { return false; }
15038128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1504718292f2SDouglas Gregor   };
1505afd1b1c9SEugene Zelenko 
1506afd1b1c9SEugene Zelenko } // namespace clang
1507718292f2SDouglas Gregor 
1508718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1509718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1510718292f2SDouglas Gregor 
15118128f332SRichard Smith retry:
15128128f332SRichard Smith   Tok.clear();
1513718292f2SDouglas Gregor   Token LToken;
1514718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1515718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1516718292f2SDouglas Gregor   switch (LToken.getKind()) {
15172d57cea2SAlp Toker   case tok::raw_identifier: {
15182d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
15192d57cea2SAlp Toker     Tok.StringData = RI.data();
15202d57cea2SAlp Toker     Tok.StringLength = RI.size();
15212d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
152235b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1523fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
152459527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1525718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
15262b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1527f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
152897292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1529755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
153035b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
15316ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1532718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1533b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
15341fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1535306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1536718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1537ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1538718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1539718292f2SDouglas Gregor     break;
15402d57cea2SAlp Toker   }
1541718292f2SDouglas Gregor 
15421fb5c3a6SDouglas Gregor   case tok::comma:
15431fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
15441fb5c3a6SDouglas Gregor     break;
15451fb5c3a6SDouglas Gregor 
1546718292f2SDouglas Gregor   case tok::eof:
1547718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1548718292f2SDouglas Gregor     break;
1549718292f2SDouglas Gregor 
1550718292f2SDouglas Gregor   case tok::l_brace:
1551718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1552718292f2SDouglas Gregor     break;
1553718292f2SDouglas Gregor 
1554a686e1b0SDouglas Gregor   case tok::l_square:
1555a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1556a686e1b0SDouglas Gregor     break;
1557a686e1b0SDouglas Gregor 
15582b82c2a5SDouglas Gregor   case tok::period:
15592b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15602b82c2a5SDouglas Gregor     break;
15612b82c2a5SDouglas Gregor 
1562718292f2SDouglas Gregor   case tok::r_brace:
1563718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1564718292f2SDouglas Gregor     break;
1565718292f2SDouglas Gregor 
1566a686e1b0SDouglas Gregor   case tok::r_square:
1567a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1568a686e1b0SDouglas Gregor     break;
1569a686e1b0SDouglas Gregor 
15702b82c2a5SDouglas Gregor   case tok::star:
15712b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15722b82c2a5SDouglas Gregor     break;
15732b82c2a5SDouglas Gregor 
1574a3feee2aSRichard Smith   case tok::exclaim:
1575a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1576a3feee2aSRichard Smith     break;
1577a3feee2aSRichard Smith 
1578718292f2SDouglas Gregor   case tok::string_literal: {
1579d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1580d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1581d67aea28SRichard Smith       HadError = true;
1582d67aea28SRichard Smith       goto retry;
1583d67aea28SRichard Smith     }
1584d67aea28SRichard Smith 
1585718292f2SDouglas Gregor     // Parse the string literal.
1586718292f2SDouglas Gregor     LangOptions LangOpts;
15879d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1588718292f2SDouglas Gregor     if (StringLiteral.hadError)
1589718292f2SDouglas Gregor       goto retry;
1590718292f2SDouglas Gregor 
1591718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1592718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1593718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1594718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1595718292f2SDouglas Gregor     Saved[Length] = 0;
1596718292f2SDouglas Gregor 
1597718292f2SDouglas Gregor     // Form the token.
1598718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1599718292f2SDouglas Gregor     Tok.StringData = Saved;
1600718292f2SDouglas Gregor     Tok.StringLength = Length;
1601718292f2SDouglas Gregor     break;
1602718292f2SDouglas Gregor   }
1603718292f2SDouglas Gregor 
1604040e1266SRichard Smith   case tok::numeric_constant: {
1605040e1266SRichard Smith     // We don't support any suffixes or other complications.
1606040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1607040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1608040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1609040e1266SRichard Smith     unsigned Length =
1610040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1611040e1266SRichard Smith     uint64_t Value;
1612040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1613040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1614040e1266SRichard Smith       HadError = true;
1615040e1266SRichard Smith       goto retry;
1616040e1266SRichard Smith     }
1617040e1266SRichard Smith 
1618040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1619040e1266SRichard Smith     Tok.IntegerValue = Value;
1620040e1266SRichard Smith     break;
1621040e1266SRichard Smith   }
1622040e1266SRichard Smith 
1623718292f2SDouglas Gregor   case tok::comment:
1624718292f2SDouglas Gregor     goto retry;
1625718292f2SDouglas Gregor 
16268128f332SRichard Smith   case tok::hash:
16278128f332SRichard Smith     // A module map can be terminated prematurely by
16288128f332SRichard Smith     //   #pragma clang module contents
16298128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
16308128f332SRichard Smith     // contents of the module.
16318128f332SRichard Smith     {
16328128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
16338128f332SRichard Smith         L.LexFromRawLexer(LToken);
16348128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16358128f332SRichard Smith                LToken.getRawIdentifier() == Str;
16368128f332SRichard Smith       };
16378128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16388128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
16398128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
16408128f332SRichard Smith         break;
16418128f332SRichard Smith       }
16428128f332SRichard Smith     }
16438128f332SRichard Smith     LLVM_FALLTHROUGH;
16448128f332SRichard Smith 
1645718292f2SDouglas Gregor   default:
16468128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1647718292f2SDouglas Gregor     HadError = true;
1648718292f2SDouglas Gregor     goto retry;
1649718292f2SDouglas Gregor   }
1650718292f2SDouglas Gregor 
1651718292f2SDouglas Gregor   return Result;
1652718292f2SDouglas Gregor }
1653718292f2SDouglas Gregor 
1654718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1655718292f2SDouglas Gregor   unsigned braceDepth = 0;
1656a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1657718292f2SDouglas Gregor   do {
1658718292f2SDouglas Gregor     switch (Tok.Kind) {
1659718292f2SDouglas Gregor     case MMToken::EndOfFile:
1660718292f2SDouglas Gregor       return;
1661718292f2SDouglas Gregor 
1662718292f2SDouglas Gregor     case MMToken::LBrace:
1663a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1664718292f2SDouglas Gregor         return;
1665718292f2SDouglas Gregor 
1666718292f2SDouglas Gregor       ++braceDepth;
1667718292f2SDouglas Gregor       break;
1668718292f2SDouglas Gregor 
1669a686e1b0SDouglas Gregor     case MMToken::LSquare:
1670a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1671a686e1b0SDouglas Gregor         return;
1672a686e1b0SDouglas Gregor 
1673a686e1b0SDouglas Gregor       ++squareDepth;
1674a686e1b0SDouglas Gregor       break;
1675a686e1b0SDouglas Gregor 
1676718292f2SDouglas Gregor     case MMToken::RBrace:
1677718292f2SDouglas Gregor       if (braceDepth > 0)
1678718292f2SDouglas Gregor         --braceDepth;
1679718292f2SDouglas Gregor       else if (Tok.is(K))
1680718292f2SDouglas Gregor         return;
1681718292f2SDouglas Gregor       break;
1682718292f2SDouglas Gregor 
1683a686e1b0SDouglas Gregor     case MMToken::RSquare:
1684a686e1b0SDouglas Gregor       if (squareDepth > 0)
1685a686e1b0SDouglas Gregor         --squareDepth;
1686a686e1b0SDouglas Gregor       else if (Tok.is(K))
1687a686e1b0SDouglas Gregor         return;
1688a686e1b0SDouglas Gregor       break;
1689a686e1b0SDouglas Gregor 
1690718292f2SDouglas Gregor     default:
1691a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1692718292f2SDouglas Gregor         return;
1693718292f2SDouglas Gregor       break;
1694718292f2SDouglas Gregor     }
1695718292f2SDouglas Gregor 
1696718292f2SDouglas Gregor    consumeToken();
1697718292f2SDouglas Gregor   } while (true);
1698718292f2SDouglas Gregor }
1699718292f2SDouglas Gregor 
17009fc8faf9SAdrian Prantl /// Parse a module-id.
1701e7ab3669SDouglas Gregor ///
1702e7ab3669SDouglas Gregor ///   module-id:
1703e7ab3669SDouglas Gregor ///     identifier
1704e7ab3669SDouglas Gregor ///     identifier '.' module-id
1705e7ab3669SDouglas Gregor ///
1706e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1707e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1708e7ab3669SDouglas Gregor   Id.clear();
1709e7ab3669SDouglas Gregor   do {
17103cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1711adcd0268SBenjamin Kramer       Id.push_back(
1712adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1713e7ab3669SDouglas Gregor       consumeToken();
1714e7ab3669SDouglas Gregor     } else {
1715e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1716e7ab3669SDouglas Gregor       return true;
1717e7ab3669SDouglas Gregor     }
1718e7ab3669SDouglas Gregor 
1719e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1720e7ab3669SDouglas Gregor       break;
1721e7ab3669SDouglas Gregor 
1722e7ab3669SDouglas Gregor     consumeToken();
1723e7ab3669SDouglas Gregor   } while (true);
1724e7ab3669SDouglas Gregor 
1725e7ab3669SDouglas Gregor   return false;
1726e7ab3669SDouglas Gregor }
1727e7ab3669SDouglas Gregor 
1728a686e1b0SDouglas Gregor namespace {
1729afd1b1c9SEugene Zelenko 
17309fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1731a686e1b0SDouglas Gregor   enum AttributeKind {
17329fc8faf9SAdrian Prantl     /// An unknown attribute.
1733a686e1b0SDouglas Gregor     AT_unknown,
1734afd1b1c9SEugene Zelenko 
17359fc8faf9SAdrian Prantl     /// The 'system' attribute.
173635b13eceSDouglas Gregor     AT_system,
1737afd1b1c9SEugene Zelenko 
17389fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
173977944868SRichard Smith     AT_extern_c,
1740afd1b1c9SEugene Zelenko 
17419fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1742ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1743afd1b1c9SEugene Zelenko 
17449fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1745ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1746a686e1b0SDouglas Gregor   };
1747afd1b1c9SEugene Zelenko 
1748afd1b1c9SEugene Zelenko } // namespace
1749a686e1b0SDouglas Gregor 
175029729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
175129729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
175229729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
175329729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17545f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17555f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
175629729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17577d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
175829729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
175929729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
176029729919SBruno Cardoso Lopes     D << BadName << M->Name;
17617d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
176229729919SBruno Cardoso Lopes   };
176329729919SBruno Cardoso Lopes 
176429729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
176529729919SBruno Cardoso Lopes     auto const *M = E->getValue();
176629729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
176729729919SBruno Cardoso Lopes       continue;
176829729919SBruno Cardoso Lopes 
176929729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
177029729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
177129729919SBruno Cardoso Lopes       continue;
17725f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
177329729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
177429729919SBruno Cardoso Lopes     Canonical.append("_Private");
177529729919SBruno Cardoso Lopes 
177629729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
177729729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
177829729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
177929729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
178029729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
178129729919SBruno Cardoso Lopes           << FullName;
17825f11e128SBruno Cardoso Lopes 
17835f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17845f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17855f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17865f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17875f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17885f11e128SBruno Cardoso Lopes 
17895f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17905f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17915f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17925f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
17935f11e128SBruno Cardoso Lopes 
17945f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17955f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
179629729919SBruno Cardoso Lopes       continue;
179729729919SBruno Cardoso Lopes     }
179829729919SBruno Cardoso Lopes 
179929729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
180029729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
180129729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
180229729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
180329729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
180429729919SBruno Cardoso Lopes           << ActiveModule->Name;
18057d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18067d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
180729729919SBruno Cardoso Lopes     }
180829729919SBruno Cardoso Lopes   }
180929729919SBruno Cardoso Lopes }
181029729919SBruno Cardoso Lopes 
18119fc8faf9SAdrian Prantl /// Parse a module declaration.
1812718292f2SDouglas Gregor ///
1813718292f2SDouglas Gregor ///   module-declaration:
181497292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1815a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1816a686e1b0SDouglas Gregor ///       { module-member* }
1817a686e1b0SDouglas Gregor ///
1818718292f2SDouglas Gregor ///   module-member:
18191fb5c3a6SDouglas Gregor ///     requires-declaration
1820718292f2SDouglas Gregor ///     header-declaration
1821e7ab3669SDouglas Gregor ///     submodule-declaration
18222b82c2a5SDouglas Gregor ///     export-declaration
1823f0b11de2SDouglas Gregor ///     export-as-declaration
18246ddfca91SDouglas Gregor ///     link-declaration
182573441091SDouglas Gregor ///
182673441091SDouglas Gregor ///   submodule-declaration:
182773441091SDouglas Gregor ///     module-declaration
182873441091SDouglas Gregor ///     inferred-submodule-declaration
1829718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1830755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
183197292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
183297292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
183397292843SDaniel Jasper     parseExternModuleDecl();
183497292843SDaniel Jasper     return;
183597292843SDaniel Jasper   }
183697292843SDaniel Jasper 
1837f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1838e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
18395f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1840718292f2SDouglas Gregor   bool Explicit = false;
1841f2161a70SDouglas Gregor   bool Framework = false;
1842755b2055SDouglas Gregor 
1843f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1844f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1845e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1846f2161a70SDouglas Gregor     Explicit = true;
1847f2161a70SDouglas Gregor   }
1848f2161a70SDouglas Gregor 
1849f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1850755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18515f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1852755b2055SDouglas Gregor     Framework = true;
1853755b2055SDouglas Gregor   }
1854718292f2SDouglas Gregor 
1855718292f2SDouglas Gregor   // Parse 'module' keyword.
1856718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1857d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1858718292f2SDouglas Gregor     consumeToken();
1859718292f2SDouglas Gregor     HadError = true;
1860718292f2SDouglas Gregor     return;
1861718292f2SDouglas Gregor   }
18629f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1863718292f2SDouglas Gregor 
186473441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
186573441091SDouglas Gregor   // Parse it.
186673441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18679194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
186873441091SDouglas Gregor 
1869718292f2SDouglas Gregor   // Parse the module name.
1870e7ab3669SDouglas Gregor   ModuleId Id;
1871e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1872718292f2SDouglas Gregor     HadError = true;
1873718292f2SDouglas Gregor     return;
1874718292f2SDouglas Gregor   }
1875e7ab3669SDouglas Gregor 
1876e7ab3669SDouglas Gregor   if (ActiveModule) {
1877e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1878e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1879e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1880e7ab3669SDouglas Gregor 
1881e7ab3669SDouglas Gregor       HadError = true;
1882e7ab3669SDouglas Gregor       return;
1883e7ab3669SDouglas Gregor     }
1884e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1885e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1886e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1887e7ab3669SDouglas Gregor     Explicit = false;
1888e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1889e7ab3669SDouglas Gregor     HadError = true;
1890e7ab3669SDouglas Gregor   }
1891e7ab3669SDouglas Gregor 
1892e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1893e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1894e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1895e7ab3669SDouglas Gregor     // is a submodule.
1896d2d442caSCraig Topper     ActiveModule = nullptr;
18974b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1898e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1899e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19004b8a9e95SBen Langmuir         if (I == 0)
19014b8a9e95SBen Langmuir           TopLevelModule = Next;
1902e7ab3669SDouglas Gregor         ActiveModule = Next;
1903e7ab3669SDouglas Gregor         continue;
1904e7ab3669SDouglas Gregor       }
1905e7ab3669SDouglas Gregor 
1906e7ab3669SDouglas Gregor       if (ActiveModule) {
1907e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
19085b5d21eaSRichard Smith           << Id[I].first
19095b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1910e7ab3669SDouglas Gregor       } else {
1911e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1912e7ab3669SDouglas Gregor       }
1913e7ab3669SDouglas Gregor       HadError = true;
1914e7ab3669SDouglas Gregor       return;
1915e7ab3669SDouglas Gregor     }
19164b8a9e95SBen Langmuir 
19174b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19184b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19194b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
19204b8a9e95SBen Langmuir              "top-level module");
19214b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19224b8a9e95SBen Langmuir     }
1923e7ab3669SDouglas Gregor   }
1924e7ab3669SDouglas Gregor 
1925e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1926e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1927718292f2SDouglas Gregor 
1928a686e1b0SDouglas Gregor   // Parse the optional attribute list.
19294442605fSBill Wendling   Attributes Attrs;
19305d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
19315d29dee0SDavide Italiano     return;
19325d29dee0SDavide Italiano 
1933718292f2SDouglas Gregor   // Parse the opening brace.
1934718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1935718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1936718292f2SDouglas Gregor       << ModuleName;
1937718292f2SDouglas Gregor     HadError = true;
1938718292f2SDouglas Gregor     return;
1939718292f2SDouglas Gregor   }
1940718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1941718292f2SDouglas Gregor 
1942718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
19438587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1944eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19454a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
19464a3751ffSRichard Smith     // definition for in two cases:
19474a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19484a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19494a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19504a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19514a3751ffSRichard Smith     //    module map file from which it was created.
19524a3751ffSRichard Smith     bool ParsedAsMainInput =
19534a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19544a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19554a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19564a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19574a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1958fcc54a3bSDouglas Gregor       // Skip the module definition.
1959fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1960fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1961fcc54a3bSDouglas Gregor         consumeToken();
1962fcc54a3bSDouglas Gregor       else {
1963fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1964fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1965fcc54a3bSDouglas Gregor         HadError = true;
1966fcc54a3bSDouglas Gregor       }
1967fcc54a3bSDouglas Gregor       return;
1968fcc54a3bSDouglas Gregor     }
1969fcc54a3bSDouglas Gregor 
1970c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19718587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19728587dfd9SBruno Cardoso Lopes     } else {
19738587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1974718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1975718292f2SDouglas Gregor           << ModuleName;
1976eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1977718292f2SDouglas Gregor 
1978718292f2SDouglas Gregor       // Skip the module definition.
1979718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1980718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1981718292f2SDouglas Gregor         consumeToken();
1982718292f2SDouglas Gregor 
1983718292f2SDouglas Gregor       HadError = true;
1984718292f2SDouglas Gregor       return;
1985718292f2SDouglas Gregor     }
19868587dfd9SBruno Cardoso Lopes   }
1987718292f2SDouglas Gregor 
1988718292f2SDouglas Gregor   // Start defining this module.
19898587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19908587dfd9SBruno Cardoso Lopes     ActiveModule =
19918587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19928587dfd9SBruno Cardoso Lopes   } else {
1993c192d194SBruno Cardoso Lopes     ActiveModule =
1994c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19958587dfd9SBruno Cardoso Lopes             .first;
19968587dfd9SBruno Cardoso Lopes   }
19978587dfd9SBruno Cardoso Lopes 
1998eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1999963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
2000a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
200177944868SRichard Smith   if (Attrs.IsExternC)
200277944868SRichard Smith     ActiveModule->IsExternC = true;
2003ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
2004ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
2005ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
20063c1a41adSRichard Smith   ActiveModule->Directory = Directory;
2007718292f2SDouglas Gregor 
200890b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
200990b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
201090b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
201190b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
201290b0a1fcSJordan Rose   }
201329729919SBruno Cardoso Lopes 
201429729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
201529729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
201629729919SBruno Cardoso Lopes   // Foo_Private instead.
201729729919SBruno Cardoso Lopes   SourceLocation StartLoc =
201829729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
201929729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
202029729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
202129729919SBruno Cardoso Lopes                        StartLoc) &&
202229729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
202329729919SBruno Cardoso Lopes                        StartLoc) &&
202490b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
20255f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20264d867640SGraydon Hoare 
2027718292f2SDouglas Gregor   bool Done = false;
2028718292f2SDouglas Gregor   do {
2029718292f2SDouglas Gregor     switch (Tok.Kind) {
2030718292f2SDouglas Gregor     case MMToken::EndOfFile:
2031718292f2SDouglas Gregor     case MMToken::RBrace:
2032718292f2SDouglas Gregor       Done = true;
2033718292f2SDouglas Gregor       break;
2034718292f2SDouglas Gregor 
203535b13eceSDouglas Gregor     case MMToken::ConfigMacros:
203635b13eceSDouglas Gregor       parseConfigMacros();
203735b13eceSDouglas Gregor       break;
203835b13eceSDouglas Gregor 
2039fb912657SDouglas Gregor     case MMToken::Conflict:
2040fb912657SDouglas Gregor       parseConflict();
2041fb912657SDouglas Gregor       break;
2042fb912657SDouglas Gregor 
2043718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
204497292843SDaniel Jasper     case MMToken::ExternKeyword:
2045f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
2046718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2047718292f2SDouglas Gregor       parseModuleDecl();
2048718292f2SDouglas Gregor       break;
2049718292f2SDouglas Gregor 
20502b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20512b82c2a5SDouglas Gregor       parseExportDecl();
20522b82c2a5SDouglas Gregor       break;
20532b82c2a5SDouglas Gregor 
2054f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2055f0b11de2SDouglas Gregor       parseExportAsDecl();
2056f0b11de2SDouglas Gregor       break;
2057f0b11de2SDouglas Gregor 
2058ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2059ba7f2f71SDaniel Jasper       parseUseDecl();
2060ba7f2f71SDaniel Jasper       break;
2061ba7f2f71SDaniel Jasper 
20621fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20631fb5c3a6SDouglas Gregor       parseRequiresDecl();
20641fb5c3a6SDouglas Gregor       break;
20651fb5c3a6SDouglas Gregor 
2066202210b3SRichard Smith     case MMToken::TextualKeyword:
2067202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2068306d8920SRichard Smith       break;
2069306d8920SRichard Smith 
2070524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2071524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2072524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2073b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2074524e33e1SDouglas Gregor       else
2075524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2076718292f2SDouglas Gregor       break;
2077524e33e1SDouglas Gregor     }
2078718292f2SDouglas Gregor 
2079202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2080202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
208159527666SDouglas Gregor       break;
208259527666SDouglas Gregor 
2083202210b3SRichard Smith     case MMToken::PrivateKeyword:
2084202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2085b53e5483SLawrence Crowl       break;
2086b53e5483SLawrence Crowl 
2087322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2088202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2089718292f2SDouglas Gregor       break;
2090718292f2SDouglas Gregor 
20916ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20926ddfca91SDouglas Gregor       parseLinkDecl();
20936ddfca91SDouglas Gregor       break;
20946ddfca91SDouglas Gregor 
2095718292f2SDouglas Gregor     default:
2096718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2097718292f2SDouglas Gregor       consumeToken();
2098718292f2SDouglas Gregor       break;
2099718292f2SDouglas Gregor     }
2100718292f2SDouglas Gregor   } while (!Done);
2101718292f2SDouglas Gregor 
2102718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2103718292f2SDouglas Gregor     consumeToken();
2104718292f2SDouglas Gregor   else {
2105718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2106718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2107718292f2SDouglas Gregor     HadError = true;
2108718292f2SDouglas Gregor   }
2109718292f2SDouglas Gregor 
211011dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
211111dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
211211dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
211311dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
211411dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
211511dfe6feSDouglas Gregor   }
211611dfe6feSDouglas Gregor 
2117ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2118ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2119fc76b4adSRichard Smith   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2120ec8c9752SBen Langmuir       ActiveModule->Parent) {
2121fc76b4adSRichard Smith     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2122ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2123ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2124ec8c9752SBen Langmuir   }
2125ec8c9752SBen Langmuir 
2126e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2127e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2128718292f2SDouglas Gregor }
2129718292f2SDouglas Gregor 
21309fc8faf9SAdrian Prantl /// Parse an extern module declaration.
213197292843SDaniel Jasper ///
213297292843SDaniel Jasper ///   extern module-declaration:
213397292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
213497292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
213597292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2136ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
213797292843SDaniel Jasper 
213897292843SDaniel Jasper   // Parse 'module' keyword.
213997292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
214097292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
214197292843SDaniel Jasper     consumeToken();
214297292843SDaniel Jasper     HadError = true;
214397292843SDaniel Jasper     return;
214497292843SDaniel Jasper   }
214597292843SDaniel Jasper   consumeToken(); // 'module' keyword
214697292843SDaniel Jasper 
214797292843SDaniel Jasper   // Parse the module name.
214897292843SDaniel Jasper   ModuleId Id;
214997292843SDaniel Jasper   if (parseModuleId(Id)) {
215097292843SDaniel Jasper     HadError = true;
215197292843SDaniel Jasper     return;
215297292843SDaniel Jasper   }
215397292843SDaniel Jasper 
215497292843SDaniel Jasper   // Parse the referenced module map file name.
215597292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
215697292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
215797292843SDaniel Jasper     HadError = true;
215897292843SDaniel Jasper     return;
215997292843SDaniel Jasper   }
2160adcd0268SBenjamin Kramer   std::string FileName = std::string(Tok.getString());
216197292843SDaniel Jasper   consumeToken(); // filename
216297292843SDaniel Jasper 
216397292843SDaniel Jasper   StringRef FileNameRef = FileName;
216497292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
216597292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
216697292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
216797292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
216892e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
216997292843SDaniel Jasper   }
21708d323d15SHarlan Haskins   if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21719acb99e3SRichard Smith     Map.parseModuleMapFile(
21728d323d15SHarlan Haskins         *File, /*IsSystem=*/false,
21739acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21749acb99e3SRichard Smith             ? Directory
21758d323d15SHarlan Haskins             : (*File)->getDir(),
2176c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
217797292843SDaniel Jasper }
217897292843SDaniel Jasper 
21797ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21807ff29148SBen Langmuir ///
21817ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21827ff29148SBen Langmuir /// module map files:
21837ff29148SBen Langmuir ///
21847ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21857ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21867ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21877ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21887ff29148SBen Langmuir ///    module to 'textual'.
21897ff29148SBen Langmuir ///
21907ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21917ff29148SBen Langmuir ///
21927ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21937ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21947ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21957ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21968013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21978013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21988013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21997ff29148SBen Langmuir     IsRequiresExcludedHack = true;
22007ff29148SBen Langmuir     return false;
22018013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
22027ff29148SBen Langmuir     return false;
22037ff29148SBen Langmuir   }
22047ff29148SBen Langmuir 
22057ff29148SBen Langmuir   return true;
22067ff29148SBen Langmuir }
22077ff29148SBen Langmuir 
22089fc8faf9SAdrian Prantl /// Parse a requires declaration.
22091fb5c3a6SDouglas Gregor ///
22101fb5c3a6SDouglas Gregor ///   requires-declaration:
22111fb5c3a6SDouglas Gregor ///     'requires' feature-list
22121fb5c3a6SDouglas Gregor ///
22131fb5c3a6SDouglas Gregor ///   feature-list:
2214a3feee2aSRichard Smith ///     feature ',' feature-list
2215a3feee2aSRichard Smith ///     feature
2216a3feee2aSRichard Smith ///
2217a3feee2aSRichard Smith ///   feature:
2218a3feee2aSRichard Smith ///     '!'[opt] identifier
22191fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
22201fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
22211fb5c3a6SDouglas Gregor 
22221fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
22231fb5c3a6SDouglas Gregor   consumeToken();
22241fb5c3a6SDouglas Gregor 
22251fb5c3a6SDouglas Gregor   // Parse the feature-list.
22261fb5c3a6SDouglas Gregor   do {
2227a3feee2aSRichard Smith     bool RequiredState = true;
2228a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2229a3feee2aSRichard Smith       RequiredState = false;
2230a3feee2aSRichard Smith       consumeToken();
2231a3feee2aSRichard Smith     }
2232a3feee2aSRichard Smith 
22331fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
22341fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22351fb5c3a6SDouglas Gregor       HadError = true;
22361fb5c3a6SDouglas Gregor       return;
22371fb5c3a6SDouglas Gregor     }
22381fb5c3a6SDouglas Gregor 
22391fb5c3a6SDouglas Gregor     // Consume the feature name.
2240adcd0268SBenjamin Kramer     std::string Feature = std::string(Tok.getString());
22411fb5c3a6SDouglas Gregor     consumeToken();
22421fb5c3a6SDouglas Gregor 
22437ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
22447ff29148SBen Langmuir     bool ShouldAddRequirement =
22457ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22467ff29148SBen Langmuir 
22477ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22487ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22497ff29148SBen Langmuir 
22507ff29148SBen Langmuir     if (ShouldAddRequirement) {
22511fb5c3a6SDouglas Gregor       // Add this feature.
22527ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22537ff29148SBen Langmuir                                    *Map.Target);
22547ff29148SBen Langmuir     }
22551fb5c3a6SDouglas Gregor 
22561fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22571fb5c3a6SDouglas Gregor       break;
22581fb5c3a6SDouglas Gregor 
22591fb5c3a6SDouglas Gregor     // Consume the comma.
22601fb5c3a6SDouglas Gregor     consumeToken();
22611fb5c3a6SDouglas Gregor   } while (true);
22621fb5c3a6SDouglas Gregor }
22631fb5c3a6SDouglas Gregor 
22649fc8faf9SAdrian Prantl /// Parse a header declaration.
2265718292f2SDouglas Gregor ///
2266718292f2SDouglas Gregor ///   header-declaration:
2267306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2268202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2269202210b3SRichard Smith ///     'exclude' 'header' string-literal
2270202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2271306d8920SRichard Smith ///
2272306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2273b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2274b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2275202210b3SRichard Smith   // We've already consumed the first token.
2276202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2277202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2278202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2279202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2280202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2281202210b3SRichard Smith       LeadingToken = Tok.Kind;
22821871ed3dSBenjamin Kramer       consumeToken();
2283202210b3SRichard Smith     }
2284202210b3SRichard Smith   }
22857ff29148SBen Langmuir 
2286202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2287202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2288202210b3SRichard Smith 
22897ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22907ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22917ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22927ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22937ff29148SBen Langmuir   }
22947ff29148SBen Langmuir 
2295202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2296202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2297202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2298202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2299202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2300202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2301202210b3SRichard Smith       return;
2302202210b3SRichard Smith     }
2303202210b3SRichard Smith     consumeToken();
2304202210b3SRichard Smith   }
2305718292f2SDouglas Gregor 
2306718292f2SDouglas Gregor   // Parse the header name.
2307718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2308718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2309718292f2SDouglas Gregor       << "header";
2310718292f2SDouglas Gregor     HadError = true;
2311718292f2SDouglas Gregor     return;
2312718292f2SDouglas Gregor   }
23133c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
2314adcd0268SBenjamin Kramer   Header.FileName = std::string(Tok.getString());
23150761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
23161d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2317040e1266SRichard Smith   Header.Kind =
2318040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2319040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2320718292f2SDouglas Gregor 
2321524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
23221d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
23230761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2324524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2325322f633cSDouglas Gregor     HadError = true;
2326322f633cSDouglas Gregor     return;
2327322f633cSDouglas Gregor   }
2328322f633cSDouglas Gregor 
2329040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2330040e1266SRichard Smith   // the file.
2331040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2332040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
23333ec6663bSDouglas Gregor 
2334040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2335040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2336040e1266SRichard Smith       StringRef Str = Tok.getString();
2337040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2338040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2339040e1266SRichard Smith                   .Case("size", Size)
2340040e1266SRichard Smith                   .Case("mtime", ModTime)
2341040e1266SRichard Smith                   .Default(Unknown)) {
2342040e1266SRichard Smith       case Size:
2343040e1266SRichard Smith         if (Header.Size)
2344040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2345040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2346040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2347040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2348040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2349040e1266SRichard Smith           break;
2350040e1266SRichard Smith         }
2351040e1266SRichard Smith         Header.Size = Tok.getInteger();
2352040e1266SRichard Smith         consumeToken();
2353040e1266SRichard Smith         break;
2354040e1266SRichard Smith 
2355040e1266SRichard Smith       case ModTime:
2356040e1266SRichard Smith         if (Header.ModTime)
2357040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2358040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2359040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2360040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2361040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2362040e1266SRichard Smith           break;
2363040e1266SRichard Smith         }
2364040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2365040e1266SRichard Smith         consumeToken();
2366040e1266SRichard Smith         break;
2367040e1266SRichard Smith 
2368040e1266SRichard Smith       case Unknown:
2369040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2370040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2371040e1266SRichard Smith         break;
2372040e1266SRichard Smith       }
23733ec6663bSDouglas Gregor     }
23745257fc63SDouglas Gregor 
2375040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2376040e1266SRichard Smith       consumeToken();
2377040e1266SRichard Smith     else {
2378040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2379040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2380322f633cSDouglas Gregor       HadError = true;
2381322f633cSDouglas Gregor     }
23820101b540SHans Wennborg   }
238325d50758SRichard Smith 
23849f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23859f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23869f6020bcSBruno Cardoso Lopes 
23879f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23889f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23899f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23909f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2391718292f2SDouglas Gregor }
2392718292f2SDouglas Gregor 
239341f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
239441f81994SBen Langmuir                                 const Module::Header *B) {
239541f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
239641f81994SBen Langmuir }
239741f81994SBen Langmuir 
23989fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2399524e33e1SDouglas Gregor ///
2400524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2401524e33e1SDouglas Gregor ///     umbrella string-literal
2402524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2403524e33e1SDouglas Gregor   // Parse the directory name.
2404524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2405524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2406524e33e1SDouglas Gregor       << "umbrella";
2407524e33e1SDouglas Gregor     HadError = true;
2408524e33e1SDouglas Gregor     return;
2409524e33e1SDouglas Gregor   }
2410524e33e1SDouglas Gregor 
2411adcd0268SBenjamin Kramer   std::string DirName = std::string(Tok.getString());
2412524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2413524e33e1SDouglas Gregor 
2414524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2415524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2416524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2417524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2418524e33e1SDouglas Gregor     HadError = true;
2419524e33e1SDouglas Gregor     return;
2420524e33e1SDouglas Gregor   }
2421524e33e1SDouglas Gregor 
2422524e33e1SDouglas Gregor   // Look for this file.
2423d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
24248d323d15SHarlan Haskins   if (llvm::sys::path::is_absolute(DirName)) {
24258d323d15SHarlan Haskins     if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24268d323d15SHarlan Haskins       Dir = *D;
24278d323d15SHarlan Haskins   } else {
24282c1dd271SDylan Noblesmith     SmallString<128> PathName;
2429524e33e1SDouglas Gregor     PathName = Directory->getName();
2430524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
24318d323d15SHarlan Haskins     if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24328d323d15SHarlan Haskins       Dir = *D;
2433524e33e1SDouglas Gregor   }
2434524e33e1SDouglas Gregor 
2435524e33e1SDouglas Gregor   if (!Dir) {
2436a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2437524e33e1SDouglas Gregor       << DirName;
2438524e33e1SDouglas Gregor     return;
2439524e33e1SDouglas Gregor   }
2440524e33e1SDouglas Gregor 
24417ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24427ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
24437ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24447ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
24457ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
24467ff29148SBen Langmuir     std::error_code EC;
24477ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2448fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2449db8a7422SDuncan P. N. Exon Smith         SourceMgr.getFileManager().getVirtualFileSystem();
2450fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24517ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
24528d323d15SHarlan Haskins       if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2453adcd0268SBenjamin Kramer         Module::Header Header = {std::string(I->path()), *FE};
24547ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24557ff29148SBen Langmuir       }
24567ff29148SBen Langmuir     }
24577ff29148SBen Langmuir 
24587ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
245941f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
246041f81994SBen Langmuir 
24617ff29148SBen Langmuir     for (auto &Header : Headers)
24627ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24637ff29148SBen Langmuir     return;
24647ff29148SBen Langmuir   }
24657ff29148SBen Langmuir 
2466524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2467524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2468524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2469524e33e1SDouglas Gregor     HadError = true;
2470524e33e1SDouglas Gregor     return;
2471524e33e1SDouglas Gregor   }
2472524e33e1SDouglas Gregor 
2473524e33e1SDouglas Gregor   // Record this umbrella directory.
24742b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2475524e33e1SDouglas Gregor }
2476524e33e1SDouglas Gregor 
24779fc8faf9SAdrian Prantl /// Parse a module export declaration.
24782b82c2a5SDouglas Gregor ///
24792b82c2a5SDouglas Gregor ///   export-declaration:
24802b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24812b82c2a5SDouglas Gregor ///
24822b82c2a5SDouglas Gregor ///   wildcard-module-id:
24832b82c2a5SDouglas Gregor ///     identifier
24842b82c2a5SDouglas Gregor ///     '*'
24852b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24862b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24872b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24882b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24892b82c2a5SDouglas Gregor 
24902b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24912b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24922b82c2a5SDouglas Gregor   bool Wildcard = false;
24932b82c2a5SDouglas Gregor   do {
2494306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24952b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
2496adcd0268SBenjamin Kramer       ParsedModuleId.push_back(
2497adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
24982b82c2a5SDouglas Gregor       consumeToken();
24992b82c2a5SDouglas Gregor 
25002b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
25012b82c2a5SDouglas Gregor         consumeToken();
25022b82c2a5SDouglas Gregor         continue;
25032b82c2a5SDouglas Gregor       }
25042b82c2a5SDouglas Gregor 
25052b82c2a5SDouglas Gregor       break;
25062b82c2a5SDouglas Gregor     }
25072b82c2a5SDouglas Gregor 
25082b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
25092b82c2a5SDouglas Gregor       Wildcard = true;
2510f5eedd05SDouglas Gregor       consumeToken();
25112b82c2a5SDouglas Gregor       break;
25122b82c2a5SDouglas Gregor     }
25132b82c2a5SDouglas Gregor 
2514ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25152b82c2a5SDouglas Gregor     HadError = true;
25162b82c2a5SDouglas Gregor     return;
25172b82c2a5SDouglas Gregor   } while (true);
25182b82c2a5SDouglas Gregor 
25192b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
25202b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
25212b82c2a5SDouglas Gregor   };
25222b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
25232b82c2a5SDouglas Gregor }
25242b82c2a5SDouglas Gregor 
25259fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2526f0b11de2SDouglas Gregor ///
2527f0b11de2SDouglas Gregor ///   export-as-declaration:
2528f0b11de2SDouglas Gregor ///     'export_as' identifier
2529f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2530f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2531f0b11de2SDouglas Gregor   consumeToken();
2532f0b11de2SDouglas Gregor 
2533f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2534f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2535f0b11de2SDouglas Gregor     HadError = true;
2536f0b11de2SDouglas Gregor     return;
2537f0b11de2SDouglas Gregor   }
2538f0b11de2SDouglas Gregor 
2539f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2540f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2541f0b11de2SDouglas Gregor     consumeToken();
2542f0b11de2SDouglas Gregor     return;
2543f0b11de2SDouglas Gregor   }
2544f0b11de2SDouglas Gregor 
2545f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2546f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2547f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2548f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2549f0b11de2SDouglas Gregor     } else {
2550f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2551f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2552f0b11de2SDouglas Gregor         << Tok.getString();
2553f0b11de2SDouglas Gregor     }
2554f0b11de2SDouglas Gregor   }
2555f0b11de2SDouglas Gregor 
2556adcd0268SBenjamin Kramer   ActiveModule->ExportAsModule = std::string(Tok.getString());
2557a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2558a3b5f71eSBruno Cardoso Lopes 
2559f0b11de2SDouglas Gregor   consumeToken();
2560f0b11de2SDouglas Gregor }
2561f0b11de2SDouglas Gregor 
25629fc8faf9SAdrian Prantl /// Parse a module use declaration.
2563ba7f2f71SDaniel Jasper ///
25648f4d3ff1SRichard Smith ///   use-declaration:
25658f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2566ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2567ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25688f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2569ba7f2f71SDaniel Jasper   // Parse the module-id.
2570ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25713cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2572ba7f2f71SDaniel Jasper 
25738f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25748f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25758f4d3ff1SRichard Smith   else
2576ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2577ba7f2f71SDaniel Jasper }
2578ba7f2f71SDaniel Jasper 
25799fc8faf9SAdrian Prantl /// Parse a link declaration.
25806ddfca91SDouglas Gregor ///
25816ddfca91SDouglas Gregor ///   module-declaration:
25826ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25836ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25846ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25856ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25866ddfca91SDouglas Gregor 
25876ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25886ddfca91SDouglas Gregor   bool IsFramework = false;
25896ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25906ddfca91SDouglas Gregor     consumeToken();
25916ddfca91SDouglas Gregor     IsFramework = true;
25926ddfca91SDouglas Gregor   }
25936ddfca91SDouglas Gregor 
25946ddfca91SDouglas Gregor   // Parse the library name
25956ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25966ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25976ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25986ddfca91SDouglas Gregor     HadError = true;
25996ddfca91SDouglas Gregor     return;
26006ddfca91SDouglas Gregor   }
26016ddfca91SDouglas Gregor 
2602adcd0268SBenjamin Kramer   std::string LibraryName = std::string(Tok.getString());
26036ddfca91SDouglas Gregor   consumeToken();
26046ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26056ddfca91SDouglas Gregor                                                             IsFramework));
26066ddfca91SDouglas Gregor }
26076ddfca91SDouglas Gregor 
26089fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
260935b13eceSDouglas Gregor ///
261035b13eceSDouglas Gregor ///   module-declaration:
261135b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
261235b13eceSDouglas Gregor ///
261335b13eceSDouglas Gregor ///   config-macro-list:
261435b13eceSDouglas Gregor ///     identifier (',' identifier)?
261535b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
261635b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
261735b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
261835b13eceSDouglas Gregor 
261935b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
262035b13eceSDouglas Gregor   if (ActiveModule->Parent) {
262135b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
262235b13eceSDouglas Gregor   }
262335b13eceSDouglas Gregor 
262435b13eceSDouglas Gregor   // Parse the optional attributes.
262535b13eceSDouglas Gregor   Attributes Attrs;
26265d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26275d29dee0SDavide Italiano     return;
26285d29dee0SDavide Italiano 
262935b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
263035b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
263135b13eceSDouglas Gregor   }
263235b13eceSDouglas Gregor 
263335b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2634306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
263535b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
263635b13eceSDouglas Gregor     return;
263735b13eceSDouglas Gregor 
263835b13eceSDouglas Gregor   // Consume the first identifier.
263935b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
264035b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
264135b13eceSDouglas Gregor   }
264235b13eceSDouglas Gregor   consumeToken();
264335b13eceSDouglas Gregor 
264435b13eceSDouglas Gregor   do {
264535b13eceSDouglas Gregor     // If there's a comma, consume it.
264635b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
264735b13eceSDouglas Gregor       break;
264835b13eceSDouglas Gregor     consumeToken();
264935b13eceSDouglas Gregor 
265035b13eceSDouglas Gregor     // We expect to see a macro name here.
2651306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
265235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
265335b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
265435b13eceSDouglas Gregor       break;
265535b13eceSDouglas Gregor     }
265635b13eceSDouglas Gregor 
265735b13eceSDouglas Gregor     // Consume the macro name.
265835b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
265935b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
266035b13eceSDouglas Gregor     }
266135b13eceSDouglas Gregor     consumeToken();
266235b13eceSDouglas Gregor   } while (true);
266335b13eceSDouglas Gregor }
266435b13eceSDouglas Gregor 
26659fc8faf9SAdrian Prantl /// Format a module-id into a string.
2666fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2667fb912657SDouglas Gregor   std::string result;
2668fb912657SDouglas Gregor   {
2669fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2670fb912657SDouglas Gregor 
2671fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2672fb912657SDouglas Gregor       if (I)
2673fb912657SDouglas Gregor         OS << ".";
2674fb912657SDouglas Gregor       OS << Id[I].first;
2675fb912657SDouglas Gregor     }
2676fb912657SDouglas Gregor   }
2677fb912657SDouglas Gregor 
2678fb912657SDouglas Gregor   return result;
2679fb912657SDouglas Gregor }
2680fb912657SDouglas Gregor 
26819fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2682fb912657SDouglas Gregor ///
2683fb912657SDouglas Gregor ///   module-declaration:
2684fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2685fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2686fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2687fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2688fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2689fb912657SDouglas Gregor 
2690fb912657SDouglas Gregor   // Parse the module-id.
2691fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2692fb912657SDouglas Gregor     return;
2693fb912657SDouglas Gregor 
2694fb912657SDouglas Gregor   // Parse the ','.
2695fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2696fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2697fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2698fb912657SDouglas Gregor     return;
2699fb912657SDouglas Gregor   }
2700fb912657SDouglas Gregor   consumeToken();
2701fb912657SDouglas Gregor 
2702fb912657SDouglas Gregor   // Parse the message.
2703fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2704fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2705fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2706fb912657SDouglas Gregor     return;
2707fb912657SDouglas Gregor   }
2708fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2709fb912657SDouglas Gregor   consumeToken();
2710fb912657SDouglas Gregor 
2711fb912657SDouglas Gregor   // Add this unresolved conflict.
2712fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2713fb912657SDouglas Gregor }
2714fb912657SDouglas Gregor 
27159fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
27169194a91dSDouglas Gregor ///
27179194a91dSDouglas Gregor ///   module-declaration:
27189194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27199194a91dSDouglas Gregor ///       { inferred-module-member* }
27209194a91dSDouglas Gregor ///
27219194a91dSDouglas Gregor ///   inferred-module-member:
27229194a91dSDouglas Gregor ///     'export' '*'
27239194a91dSDouglas Gregor ///     'exclude' identifier
27249194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
272573441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
272673441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
272773441091SDouglas Gregor   bool Failed = false;
272873441091SDouglas Gregor 
272973441091SDouglas Gregor   // Inferred modules must be submodules.
27309194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
273173441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
273273441091SDouglas Gregor     Failed = true;
273373441091SDouglas Gregor   }
273473441091SDouglas Gregor 
27359194a91dSDouglas Gregor   if (ActiveModule) {
2736524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
27374898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
27384898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
273973441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
274073441091SDouglas Gregor       Failed = true;
274173441091SDouglas Gregor     }
274273441091SDouglas Gregor 
274373441091SDouglas Gregor     // Check for redefinition of an inferred module.
2744dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
274573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2746dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2747dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
274873441091SDouglas Gregor                      diag::note_mmap_prev_definition);
274973441091SDouglas Gregor       Failed = true;
275073441091SDouglas Gregor     }
275173441091SDouglas Gregor 
27529194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27539194a91dSDouglas Gregor     if (Framework) {
27549194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27559194a91dSDouglas Gregor       Framework = false;
27569194a91dSDouglas Gregor     }
27579194a91dSDouglas Gregor   } else if (Explicit) {
27589194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27599194a91dSDouglas Gregor     Explicit = false;
27609194a91dSDouglas Gregor   }
27619194a91dSDouglas Gregor 
276273441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
276373441091SDouglas Gregor   if (Failed) {
276473441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
276573441091SDouglas Gregor       consumeToken();
276673441091SDouglas Gregor       skipUntil(MMToken::RBrace);
276773441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
276873441091SDouglas Gregor         consumeToken();
276973441091SDouglas Gregor     }
277073441091SDouglas Gregor     HadError = true;
277173441091SDouglas Gregor     return;
277273441091SDouglas Gregor   }
277373441091SDouglas Gregor 
27749194a91dSDouglas Gregor   // Parse optional attributes.
27754442605fSBill Wendling   Attributes Attrs;
27765d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27775d29dee0SDavide Italiano     return;
27789194a91dSDouglas Gregor 
27799194a91dSDouglas Gregor   if (ActiveModule) {
278073441091SDouglas Gregor     // Note that we have an inferred submodule.
2781dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2782dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2783dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27849194a91dSDouglas Gregor   } else {
27859194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27869194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2787c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2788beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2789131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27909194a91dSDouglas Gregor   }
279173441091SDouglas Gregor 
279273441091SDouglas Gregor   // Parse the opening brace.
279373441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
279473441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
279573441091SDouglas Gregor     HadError = true;
279673441091SDouglas Gregor     return;
279773441091SDouglas Gregor   }
279873441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
279973441091SDouglas Gregor 
280073441091SDouglas Gregor   // Parse the body of the inferred submodule.
280173441091SDouglas Gregor   bool Done = false;
280273441091SDouglas Gregor   do {
280373441091SDouglas Gregor     switch (Tok.Kind) {
280473441091SDouglas Gregor     case MMToken::EndOfFile:
280573441091SDouglas Gregor     case MMToken::RBrace:
280673441091SDouglas Gregor       Done = true;
280773441091SDouglas Gregor       break;
280873441091SDouglas Gregor 
2809afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
28109194a91dSDouglas Gregor       if (ActiveModule) {
28119194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2812d2d442caSCraig Topper           << (ActiveModule != nullptr);
28139194a91dSDouglas Gregor         consumeToken();
28149194a91dSDouglas Gregor         break;
28159194a91dSDouglas Gregor       }
28169194a91dSDouglas Gregor 
28179194a91dSDouglas Gregor       consumeToken();
2818306d8920SRichard Smith       // FIXME: Support string-literal module names here.
28199194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
28209194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28219194a91dSDouglas Gregor         break;
28229194a91dSDouglas Gregor       }
28239194a91dSDouglas Gregor 
2824adcd0268SBenjamin Kramer       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2825adcd0268SBenjamin Kramer           std::string(Tok.getString()));
28269194a91dSDouglas Gregor       consumeToken();
28279194a91dSDouglas Gregor       break;
28289194a91dSDouglas Gregor 
28299194a91dSDouglas Gregor     case MMToken::ExportKeyword:
28309194a91dSDouglas Gregor       if (!ActiveModule) {
28319194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2832d2d442caSCraig Topper           << (ActiveModule != nullptr);
28339194a91dSDouglas Gregor         consumeToken();
28349194a91dSDouglas Gregor         break;
28359194a91dSDouglas Gregor       }
28369194a91dSDouglas Gregor 
283773441091SDouglas Gregor       consumeToken();
283873441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2839dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
284073441091SDouglas Gregor       else
284173441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
284273441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
284373441091SDouglas Gregor       consumeToken();
284473441091SDouglas Gregor       break;
284573441091SDouglas Gregor 
284673441091SDouglas Gregor     case MMToken::ExplicitKeyword:
284773441091SDouglas Gregor     case MMToken::ModuleKeyword:
284873441091SDouglas Gregor     case MMToken::HeaderKeyword:
2849b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
285073441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
285173441091SDouglas Gregor     default:
28529194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2853d2d442caSCraig Topper           << (ActiveModule != nullptr);
285473441091SDouglas Gregor       consumeToken();
285573441091SDouglas Gregor       break;
285673441091SDouglas Gregor     }
285773441091SDouglas Gregor   } while (!Done);
285873441091SDouglas Gregor 
285973441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
286073441091SDouglas Gregor     consumeToken();
286173441091SDouglas Gregor   else {
286273441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
286373441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
286473441091SDouglas Gregor     HadError = true;
286573441091SDouglas Gregor   }
286673441091SDouglas Gregor }
286773441091SDouglas Gregor 
28689fc8faf9SAdrian Prantl /// Parse optional attributes.
28699194a91dSDouglas Gregor ///
28709194a91dSDouglas Gregor ///   attributes:
28719194a91dSDouglas Gregor ///     attribute attributes
28729194a91dSDouglas Gregor ///     attribute
28739194a91dSDouglas Gregor ///
28749194a91dSDouglas Gregor ///   attribute:
28759194a91dSDouglas Gregor ///     [ identifier ]
28769194a91dSDouglas Gregor ///
28779194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28789194a91dSDouglas Gregor ///
28799194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28804442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28819194a91dSDouglas Gregor   bool HadError = false;
28829194a91dSDouglas Gregor 
28839194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28849194a91dSDouglas Gregor     // Consume the '['.
28859194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28869194a91dSDouglas Gregor 
28879194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28889194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28899194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28909194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28919194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28929194a91dSDouglas Gregor         consumeToken();
28939194a91dSDouglas Gregor       HadError = true;
28949194a91dSDouglas Gregor     }
28959194a91dSDouglas Gregor 
28969194a91dSDouglas Gregor     // Decode the attribute name.
28979194a91dSDouglas Gregor     AttributeKind Attribute
28989194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
289935b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
290077944868SRichard Smith           .Case("extern_c", AT_extern_c)
2901ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
29029194a91dSDouglas Gregor           .Case("system", AT_system)
29039194a91dSDouglas Gregor           .Default(AT_unknown);
29049194a91dSDouglas Gregor     switch (Attribute) {
29059194a91dSDouglas Gregor     case AT_unknown:
29069194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29079194a91dSDouglas Gregor         << Tok.getString();
29089194a91dSDouglas Gregor       break;
29099194a91dSDouglas Gregor 
29109194a91dSDouglas Gregor     case AT_system:
29119194a91dSDouglas Gregor       Attrs.IsSystem = true;
29129194a91dSDouglas Gregor       break;
291335b13eceSDouglas Gregor 
291477944868SRichard Smith     case AT_extern_c:
291577944868SRichard Smith       Attrs.IsExternC = true;
291677944868SRichard Smith       break;
291777944868SRichard Smith 
291835b13eceSDouglas Gregor     case AT_exhaustive:
291935b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
292035b13eceSDouglas Gregor       break;
2921ed84df00SBruno Cardoso Lopes 
2922ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2923ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2924ed84df00SBruno Cardoso Lopes       break;
29259194a91dSDouglas Gregor     }
29269194a91dSDouglas Gregor     consumeToken();
29279194a91dSDouglas Gregor 
29289194a91dSDouglas Gregor     // Consume the ']'.
29299194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
29309194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29319194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29329194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
29339194a91dSDouglas Gregor       HadError = true;
29349194a91dSDouglas Gregor     }
29359194a91dSDouglas Gregor 
29369194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
29379194a91dSDouglas Gregor       consumeToken();
29389194a91dSDouglas Gregor   }
29399194a91dSDouglas Gregor 
29409194a91dSDouglas Gregor   return HadError;
29419194a91dSDouglas Gregor }
29429194a91dSDouglas Gregor 
29439fc8faf9SAdrian Prantl /// Parse a module map file.
2944718292f2SDouglas Gregor ///
2945718292f2SDouglas Gregor ///   module-map-file:
2946718292f2SDouglas Gregor ///     module-declaration*
2947718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2948718292f2SDouglas Gregor   do {
2949718292f2SDouglas Gregor     switch (Tok.Kind) {
2950718292f2SDouglas Gregor     case MMToken::EndOfFile:
2951718292f2SDouglas Gregor       return HadError;
2952718292f2SDouglas Gregor 
2953e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
295497292843SDaniel Jasper     case MMToken::ExternKeyword:
2955718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2956755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2957718292f2SDouglas Gregor       parseModuleDecl();
2958718292f2SDouglas Gregor       break;
2959718292f2SDouglas Gregor 
29601fb5c3a6SDouglas Gregor     case MMToken::Comma:
296135b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2962fb912657SDouglas Gregor     case MMToken::Conflict:
2963a3feee2aSRichard Smith     case MMToken::Exclaim:
296459527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29652b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2966f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2967718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2968718292f2SDouglas Gregor     case MMToken::Identifier:
2969718292f2SDouglas Gregor     case MMToken::LBrace:
29706ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2971a686e1b0SDouglas Gregor     case MMToken::LSquare:
29722b82c2a5SDouglas Gregor     case MMToken::Period:
2973b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2974718292f2SDouglas Gregor     case MMToken::RBrace:
2975a686e1b0SDouglas Gregor     case MMToken::RSquare:
29761fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29772b82c2a5SDouglas Gregor     case MMToken::Star:
2978718292f2SDouglas Gregor     case MMToken::StringLiteral:
2979040e1266SRichard Smith     case MMToken::IntegerLiteral:
2980b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2981718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2982ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2983718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2984718292f2SDouglas Gregor       HadError = true;
2985718292f2SDouglas Gregor       consumeToken();
2986718292f2SDouglas Gregor       break;
2987718292f2SDouglas Gregor     }
2988718292f2SDouglas Gregor   } while (true);
2989718292f2SDouglas Gregor }
2990718292f2SDouglas Gregor 
29919acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2992c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29938128f332SRichard Smith                                    unsigned *Offset,
2994ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29958128f332SRichard Smith   assert(Target && "Missing target information");
29964ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29974ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29984ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29994ddf2221SDouglas Gregor     return Known->second;
30004ddf2221SDouglas Gregor 
30018128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
30028128f332SRichard Smith   if (ID.isInvalid()) {
3003f3f84616SRichard Smith     auto FileCharacter =
3004f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30058128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30068128f332SRichard Smith   }
30078128f332SRichard Smith 
30088128f332SRichard Smith   assert(Target && "Missing target information");
30091f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
3010718292f2SDouglas Gregor   if (!Buffer)
30114ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
30128128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30138128f332SRichard Smith          "invalid buffer offset");
3014718292f2SDouglas Gregor 
3015718292f2SDouglas Gregor   // Parse this module map file.
30168128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30178128f332SRichard Smith           Buffer->getBufferStart(),
30188128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
30198128f332SRichard Smith           Buffer->getBufferEnd());
30202a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
3021beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3022c192d194SBruno Cardoso Lopes                          IsSystem);
3023718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
30244ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
30252a6edb30SRichard Smith 
30268128f332SRichard Smith   if (Offset) {
30278128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30288128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
30298128f332SRichard Smith     *Offset = Loc.second;
30308128f332SRichard Smith   }
30318128f332SRichard Smith 
30322a6edb30SRichard Smith   // Notify callbacks that we parsed it.
30332a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
30342a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
30358587dfd9SBruno Cardoso Lopes 
3036718292f2SDouglas Gregor   return Result;
3037718292f2SDouglas Gregor }
3038